From e6d10539af1fdca33b10bc3c1dfac16f1cdfe1c8 Mon Sep 17 00:00:00 2001 From: Tom Englund Date: Thu, 13 Jun 2024 12:08:02 +0200 Subject: [PATCH 0001/2181] core: fix a few small memory leaks on exit (#6470) * renderer: add destructor and destroy event source add destructor and destroy the event source. one less leak on exit of compositor reported by asan. * compositor: cleanup eventloop on exit destruct hyprctl to release the event sources, and properly cleanup the event loop on exit of compositor. less leaks on exit reported by asan * threadmgr: destroy event source on destruction destroy the event source on destruction. * eventloopmgr: reset eventloopmgr on exit aswell reset the eventloopmanager on exit of compositor and free the leaking last idle frame on monitor destroy. --- src/Compositor.cpp | 3 +++ src/events/Monitors.cpp | 3 +++ src/managers/ThreadManager.cpp | 3 ++- src/render/Renderer.cpp | 5 +++++ src/render/Renderer.hpp | 1 + 5 files changed, 14 insertions(+), 1 deletion(-) diff --git a/src/Compositor.cpp b/src/Compositor.cpp index 8f36b4ae..2f972335 100644 --- a/src/Compositor.cpp +++ b/src/Compositor.cpp @@ -351,6 +351,8 @@ void CCompositor::cleanup() { g_pXWaylandManager.reset(); g_pPointerManager.reset(); g_pSeatManager.reset(); + g_pHyprCtl.reset(); + g_pEventLoopManager.reset(); if (m_sWLRRenderer) wlr_renderer_destroy(m_sWLRRenderer); @@ -364,6 +366,7 @@ void CCompositor::cleanup() { if (m_critSigSource) wl_event_source_remove(m_critSigSource); + wl_event_loop_destroy(m_sWLEventLoop); wl_display_terminate(m_sWLDisplay); m_sWLDisplay = nullptr; diff --git a/src/events/Monitors.cpp b/src/events/Monitors.cpp index e3f8f03a..17b8ef65 100644 --- a/src/events/Monitors.cpp +++ b/src/events/Monitors.cpp @@ -188,6 +188,9 @@ void Events::listener_monitorDestroy(void* owner, void* data) { Debug::log(LOG, "Destroy called for monitor {}", pMonitor->output->name); + if (pMonitor->output->idle_frame) + wl_event_source_remove(pMonitor->output->idle_frame); + pMonitor->onDisconnect(true); pMonitor->output = nullptr; diff --git a/src/managers/ThreadManager.cpp b/src/managers/ThreadManager.cpp index cd892503..6f8e0c9a 100644 --- a/src/managers/ThreadManager.cpp +++ b/src/managers/ThreadManager.cpp @@ -25,5 +25,6 @@ CThreadManager::CThreadManager() { } CThreadManager::~CThreadManager() { - // + if (m_esConfigTimer) + wl_event_source_remove(m_esConfigTimer); } \ No newline at end of file diff --git a/src/render/Renderer.cpp b/src/render/Renderer.cpp index 48fa92a0..4fe35c7e 100644 --- a/src/render/Renderer.cpp +++ b/src/render/Renderer.cpp @@ -90,6 +90,11 @@ CHyprRenderer::CHyprRenderer() { wl_event_source_timer_update(m_pCursorTicker, 500); } +CHyprRenderer::~CHyprRenderer() { + if (m_pCursorTicker) + wl_event_source_remove(m_pCursorTicker); +} + static void renderSurface(SP surface, int x, int y, void* data) { if (!surface->current.buffer || !surface->current.buffer->texture) return; diff --git a/src/render/Renderer.hpp b/src/render/Renderer.hpp index f88bfebf..60101e87 100644 --- a/src/render/Renderer.hpp +++ b/src/render/Renderer.hpp @@ -42,6 +42,7 @@ struct SSessionLockSurface; class CHyprRenderer { public: CHyprRenderer(); + ~CHyprRenderer(); void renderMonitor(CMonitor* pMonitor); void arrangeLayersForMonitor(const int&); From 4842eb83b444418ad3fe1901d645dd02224989e5 Mon Sep 17 00:00:00 2001 From: Jan Beich Date: Thu, 13 Jun 2024 12:20:14 +0000 Subject: [PATCH 0002/2181] helpers: make shm_open() portable after 8bcccf9f0f0f (#6471) https://pubs.opengroup.org/onlinepubs/9699919799/functions/shm_open.html https://man.freebsd.org/shm_open/2 https://www.man7.org/linux/man-pages/man3/shm_open.3.html --- src/helpers/MiscFunctions.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/helpers/MiscFunctions.cpp b/src/helpers/MiscFunctions.cpp index b1d734c8..346a3ffa 100644 --- a/src/helpers/MiscFunctions.cpp +++ b/src/helpers/MiscFunctions.cpp @@ -814,7 +814,8 @@ bool envEnabled(const std::string& env) { } std::pair openExclusiveShm() { - std::string name = g_pTokenManager->getRandomUUID(); + // Only absolute paths can be shared across different shm_open() calls + std::string name = "/" + g_pTokenManager->getRandomUUID(); for (size_t i = 0; i < 69; ++i) { int fd = shm_open(name.c_str(), O_RDWR | O_CREAT | O_EXCL, 0600); From 5de273a14427cb4a4cad9ac57a22b418bcd4248d Mon Sep 17 00:00:00 2001 From: Vaxry Date: Thu, 13 Jun 2024 17:32:32 +0200 Subject: [PATCH 0003/2181] xwayland: drop some spammy logs to trace fixes #6478 --- src/xwayland/XWM.cpp | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/src/xwayland/XWM.cpp b/src/xwayland/XWM.cpp index 7af1d506..247af4b7 100644 --- a/src/xwayland/XWM.cpp +++ b/src/xwayland/XWM.cpp @@ -248,11 +248,11 @@ void CXWM::readProp(SP XSURF, uint32_t atom, xcb_get_property_ } } } else { - Debug::log(LOG, "[xwm] Unhandled prop {} -> {}", atom, propName); + Debug::log(TRACE, "[xwm] Unhandled prop {} -> {}", atom, propName); return; } - Debug::log(LOG, "[xwm] Handled prop {} -> {}", atom, propName); + Debug::log(TRACE, "[xwm] Handled prop {} -> {}", atom, propName); } void CXWM::handlePropertyNotify(xcb_property_notify_event_t* e) { @@ -354,11 +354,11 @@ void CXWM::handleClientMessage(xcb_client_message_event_t* e) { } else if (e->type == HYPRATOMS["_NET_ACTIVE_WINDOW"]) { XSURF->events.activate.emit(); } else { - Debug::log(LOG, "[xwm] Unhandled message prop {} -> {}", e->type, propName); + Debug::log(TRACE, "[xwm] Unhandled message prop {} -> {}", e->type, propName); return; } - Debug::log(LOG, "[xwm] Handled message prop {} -> {}", e->type, propName); + Debug::log(TRACE, "[xwm] Handled message prop {} -> {}", e->type, propName); } void CXWM::handleFocusIn(xcb_focus_in_event_t* e) { @@ -490,18 +490,18 @@ std::string CXWM::mimeFromAtom(xcb_atom_t atom) { } void CXWM::handleSelectionNotify(xcb_selection_notify_event_t* e) { - Debug::log(LOG, "[xwm] Selection notify for {} prop {} target {}", e->selection, e->property, e->target); + Debug::log(TRACE, "[xwm] Selection notify for {} prop {} target {}", e->selection, e->property, e->target); SXSelection& sel = clipboard; if (e->property == XCB_ATOM_NONE) { if (sel.transfer) { - Debug::log(ERR, "[xwm] converting selection failed"); + Debug::log(TRACE, "[xwm] converting selection failed"); sel.transfer.reset(); } } else if (e->target == HYPRATOMS["TARGETS"]) { if (!focusedSurface) { - Debug::log(LOG, "[xwm] denying access to write to clipboard because no X client is in focus"); + Debug::log(TRACE, "[xwm] denying access to write to clipboard because no X client is in focus"); return; } @@ -519,7 +519,7 @@ bool CXWM::handleSelectionPropertyNotify(xcb_property_notify_event_t* e) { } void CXWM::handleSelectionRequest(xcb_selection_request_event_t* e) { - Debug::log(LOG, "[xwm] Selection request for {} prop {} target {} time {} requestor {} selection {}", e->selection, e->property, e->target, e->time, e->requestor, + Debug::log(TRACE, "[xwm] Selection request for {} prop {} target {} time {} requestor {} selection {}", e->selection, e->property, e->target, e->time, e->requestor, e->selection); SXSelection& sel = clipboard; @@ -542,7 +542,7 @@ void CXWM::handleSelectionRequest(xcb_selection_request_event_t* e) { } if (!g_pSeatManager->state.keyboardFocusResource || g_pSeatManager->state.keyboardFocusResource->client() != g_pXWayland->pServer->xwaylandClient) { - Debug::log(LOG, "[xwm] Ignoring clipboard access: xwayland not in focus"); + Debug::log(TRACE, "[xwm] Ignoring clipboard access: xwayland not in focus"); selectionSendNotify(e, false); return; } @@ -585,7 +585,7 @@ void CXWM::handleSelectionRequest(xcb_selection_request_event_t* e) { } bool CXWM::handleSelectionXFixesNotify(xcb_xfixes_selection_notify_event_t* e) { - Debug::log(LOG, "[xwm] Selection xfixes notify for {}", e->selection); + Debug::log(TRACE, "[xwm] Selection xfixes notify for {}", e->selection); // IMPORTANT: mind the g_pSeatManager below SXSelection& sel = clipboard; From 8055b1c00a102f5419e40f5eddfb6ee8be693f33 Mon Sep 17 00:00:00 2001 From: phonetic112 <73647246+phonetic112@users.noreply.github.com> Date: Thu, 13 Jun 2024 17:23:23 -0400 Subject: [PATCH 0004/2181] misc: Fix build warnings (#6486) --- hyprpm/src/core/PluginManager.cpp | 7 ++++--- src/helpers/MiscFunctions.cpp | 7 ++++--- 2 files changed, 8 insertions(+), 6 deletions(-) diff --git a/hyprpm/src/core/PluginManager.cpp b/hyprpm/src/core/PluginManager.cpp index f9e9664a..e8c6e251 100644 --- a/hyprpm/src/core/PluginManager.cpp +++ b/hyprpm/src/core/PluginManager.cpp @@ -24,9 +24,10 @@ using namespace Hyprutils::String; static std::string execAndGet(std::string cmd) { cmd += " 2>&1"; - std::array buffer; - std::string result; - const std::unique_ptr pipe(popen(cmd.c_str(), "r"), pclose); + std::array buffer; + std::string result; + using PcloseType = int (*)(FILE*); + const std::unique_ptr pipe(popen(cmd.c_str(), "r"), static_cast(pclose)); if (!pipe) return ""; diff --git a/src/helpers/MiscFunctions.cpp b/src/helpers/MiscFunctions.cpp index 346a3ffa..821f3231 100644 --- a/src/helpers/MiscFunctions.cpp +++ b/src/helpers/MiscFunctions.cpp @@ -580,9 +580,10 @@ float vecToRectDistanceSquared(const Vector2D& vec, const Vector2D& p1, const Ve // Execute a shell command and get the output std::string execAndGet(const char* cmd) { - std::array buffer; - std::string result; - const std::unique_ptr pipe(popen(cmd, "r"), pclose); + std::array buffer; + std::string result; + using PcloseType = int (*)(FILE*); + const std::unique_ptr pipe(popen(cmd, "r"), static_cast(pclose)); if (!pipe) { Debug::log(ERR, "execAndGet: failed in pipe"); return ""; From 9cd5b3587cb1e3d42b647fa230024cd0153ea9cb Mon Sep 17 00:00:00 2001 From: outfoxxed Date: Fri, 14 Jun 2024 02:52:37 -0700 Subject: [PATCH 0005/2181] layerSurface: fix layer being refocused every commit with on_demand (#6487) * layerSurface: fix layer being refocused every commit with on_demand Fixes #6477 The surface will now only receive focus when its keyboard interactivity is more than the previous keyboard interactivity in the order none -> on_demand -> exclusive. * layerSurface: only kb focus if becoming exclusive --- src/desktop/LayerSurface.cpp | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/src/desktop/LayerSurface.cpp b/src/desktop/LayerSurface.cpp index 2eb66440..64eeead1 100644 --- a/src/desktop/LayerSurface.cpp +++ b/src/desktop/LayerSurface.cpp @@ -317,9 +317,8 @@ void CLayerSurface::onCommit() { // so unfocus the surface here. g_pCompositor->focusSurface(nullptr); g_pInputManager->refocusLastWindow(g_pCompositor->getMonitorFromID(monitorID)); - } else if (!WASEXCLUSIVE && !WASLASTFOCUS && - (ISEXCLUSIVE || (layerSurface->current.interactivity && (g_pSeatManager->mouse.expired() || !g_pInputManager->isConstrained())))) { - // if not focused last and exclusive or accepting input + unconstrained + } else if (!WASEXCLUSIVE && ISEXCLUSIVE) { + // if now exclusive and not previously g_pSeatManager->setGrab(nullptr); g_pInputManager->releaseAllMouseButtons(); g_pCompositor->focusSurface(surface->resource()); From b2590b58c51094424a9651d8df37dfab838b5bbb Mon Sep 17 00:00:00 2001 From: Alexander <51529891+Truenya@users.noreply.github.com> Date: Fri, 14 Jun 2024 13:11:40 +0300 Subject: [PATCH 0006/2181] hyprctl: added --follow option to rolliglog (#6325) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Крылов Александр --- Makefile | 2 +- hyprctl/Strings.hpp | 5 ++- hyprctl/main.cpp | 71 ++++++++++++++++++++++++++++++---- src/debug/HyprCtl.cpp | 51 +++++++++++++++++++++++- src/debug/Log.cpp | 4 ++ src/debug/RollingLogFollow.hpp | 65 +++++++++++++++++++++++++++++++ 6 files changed, 185 insertions(+), 13 deletions(-) create mode 100644 src/debug/RollingLogFollow.hpp diff --git a/Makefile b/Makefile index a33f4cb7..493a6784 100644 --- a/Makefile +++ b/Makefile @@ -42,7 +42,7 @@ uninstall: pluginenv: @echo -en "$(MAKE) pluginenv has been deprecated.\nPlease run $(MAKE) all && sudo $(MAKE) installheaders\n" @exit 1 - + installheaders: @if [ ! -f ./src/version.h ]; then echo -en "You need to run $(MAKE) all first.\n" && exit 1; fi diff --git a/hyprctl/Strings.hpp b/hyprctl/Strings.hpp index 76e87ecb..17725e77 100644 --- a/hyprctl/Strings.hpp +++ b/hyprctl/Strings.hpp @@ -38,7 +38,8 @@ commands: plugin ... → Issue a plugin request reload [config-only] → Issue a reload to force reload the config. Pass 'config-only' to disable monitor reload - rollinglog → Prints tail of the log + rollinglog → Prints tail of the log. Also supports -f/--follow + option setcursor → Sets the cursor theme and reloads the cursor manager seterror → Sets the hyprctl error string. Color has @@ -112,7 +113,7 @@ create : remove : Removes virtual output. Pass the output's name, as found in 'hyprctl monitors' - + flags: See 'hyprctl --help')#"; diff --git a/hyprctl/main.cpp b/hyprctl/main.cpp index 8fb9194c..f5de041b 100644 --- a/hyprctl/main.cpp +++ b/hyprctl/main.cpp @@ -1,9 +1,9 @@ -#include +#include #include #include -#include -#include -#include +#include +#include +#include #include #include #include @@ -12,7 +12,7 @@ #include #include #include -#include +#include #include #include @@ -22,8 +22,9 @@ #include #include #include -#include +#include #include +#include #include using namespace Hyprutils::String; @@ -100,13 +101,53 @@ std::vector instances() { return result; } -int request(std::string arg, int minArgs = 0) { +static volatile bool sigintReceived = false; +void intHandler(int sig) { + sigintReceived = true; + std::cout << "[hyprctl] SIGINT received, closing connection" << std::endl; +} + +int rollingRead(const int socket) { + sigintReceived = false; + signal(SIGINT, intHandler); + + constexpr size_t BUFFER_SIZE = 8192; + std::array buffer = {0}; + int sizeWritten = 0; + std::cout << "[hyprctl] reading from socket following up log:" << std::endl; + while (!sigintReceived) { + sizeWritten = read(socket, buffer.data(), BUFFER_SIZE); + if (sizeWritten < 0 && errno != EAGAIN) { + if (errno != EINTR) + std::cout << "Couldn't read (5) " << strerror(errno) << ":" << errno << std::endl; + close(socket); + return 5; + } + + if (sizeWritten == 0) + break; + + if (sizeWritten > 0) { + std::cout << std::string(buffer.data(), sizeWritten); + buffer.fill('\0'); + } + + usleep(100000); + } + close(socket); + return 0; +} + +int request(std::string arg, int minArgs = 0, bool needRoll = false) { const auto SERVERSOCKET = socket(AF_UNIX, SOCK_STREAM, 0); + auto t = timeval{.tv_sec = 0, .tv_usec = 100000}; + setsockopt(SERVERSOCKET, SOL_SOCKET, SO_RCVTIMEO, &t, sizeof(struct timeval)); + const auto ARGS = std::count(arg.begin(), arg.end(), ' '); if (ARGS < minArgs) { - log("Not enough arguments, expected at least " + minArgs); + log(std::format("Not enough arguments in '{}', expected at least {}", arg, minArgs)); return -1; } @@ -141,6 +182,9 @@ int request(std::string arg, int minArgs = 0) { return 4; } + if (needRoll) + return rollingRead(SERVERSOCKET); + std::string reply = ""; char buffer[8192] = {0}; @@ -284,6 +328,7 @@ int main(int argc, char** argv) { std::string fullArgs = ""; const auto ARGS = splitArgs(argc, argv); bool json = false; + bool needRoll = false; std::string overrideInstance = ""; for (std::size_t i = 0; i < ARGS.size(); ++i) { @@ -303,6 +348,9 @@ int main(int argc, char** argv) { fullArgs += "a"; } else if ((ARGS[i] == "-c" || ARGS[i] == "--config") && !fullArgs.contains("c")) { fullArgs += "c"; + } else if ((ARGS[i] == "-f" || ARGS[i] == "--follow") && !fullArgs.contains("f")) { + fullArgs += "f"; + needRoll = true; } else if (ARGS[i] == "--batch") { fullRequest = "--batch "; } else if (ARGS[i] == "--instance" || ARGS[i] == "-i") { @@ -362,6 +410,11 @@ int main(int argc, char** argv) { return 0; } + if (needRoll && !fullRequest.contains("/rollinglog")) { + log("only 'rollinglog' command supports '--follow' option"); + return 1; + } + if (overrideInstance.contains("_")) instanceSignature = overrideInstance; else if (!overrideInstance.empty()) { @@ -421,6 +474,8 @@ int main(int argc, char** argv) { exitStatus = request(fullRequest, 1); else if (fullRequest.contains("/--help")) std::cout << USAGE << std::endl; + else if (fullRequest.contains("/rollinglog") && needRoll) + exitStatus = request(fullRequest, 0, true); else { exitStatus = request(fullRequest); } diff --git a/src/debug/HyprCtl.cpp b/src/debug/HyprCtl.cpp index a7e714bd..70b886f2 100644 --- a/src/debug/HyprCtl.cpp +++ b/src/debug/HyprCtl.cpp @@ -28,6 +28,7 @@ using namespace Hyprutils::String; #include "../devices/IKeyboard.hpp" #include "../devices/ITouch.hpp" #include "../devices/Tablet.hpp" +#include "debug/RollingLogFollow.hpp" #include "config/ConfigManager.hpp" #include "helpers/MiscFunctions.hpp" @@ -1732,6 +1733,46 @@ std::string CHyprCtl::makeDynamicCall(const std::string& input) { return getReply(input); } +bool successWrite(int fd, const std::string& data, bool needLog = true) { + if (write(fd, data.c_str(), data.length()) > 0) + return true; + + if (errno == EAGAIN) + return true; + + if (needLog) + Debug::log(ERR, "Couldn't write to socket. Error: " + std::string(strerror(errno))); + + return false; +} + +void runWritingDebugLogThread(const int conn) { + using namespace std::chrono_literals; + Debug::log(LOG, "In followlog thread, got connection, start writing: {}", conn); + //will be finished, when reading side close connection + std::thread([conn]() { + while (Debug::RollingLogFollow::Get().IsRunning()) { + if (Debug::RollingLogFollow::Get().isEmpty(conn)) { + std::this_thread::sleep_for(1000ms); + continue; + } + + auto line = Debug::RollingLogFollow::Get().GetLog(conn); + if (!successWrite(conn, line)) + // We cannot write, when connection is closed. So thread will successfully exit by itself + break; + + std::this_thread::sleep_for(100ms); + } + close(conn); + Debug::RollingLogFollow::Get().StopFor(conn); + }).detach(); +} + +bool isFollowUpRollingLogRequest(const std::string& request) { + return request.contains("rollinglog") && request.contains("f"); +} + int hyprCtlFDTick(int fd, uint32_t mask, void* data) { if (mask & WL_EVENT_ERROR || mask & WL_EVENT_HANGUP) return 0; @@ -1775,9 +1816,15 @@ int hyprCtlFDTick(int fd, uint32_t mask, void* data) { reply = "Err: " + std::string(e.what()); } - write(ACCEPTEDCONNECTION, reply.c_str(), reply.length()); + successWrite(ACCEPTEDCONNECTION, reply); - close(ACCEPTEDCONNECTION); + if (isFollowUpRollingLogRequest(request)) { + Debug::log(LOG, "Followup rollinglog request received. Starting thread to write to socket."); + Debug::RollingLogFollow::Get().StartFor(ACCEPTEDCONNECTION); + runWritingDebugLogThread(ACCEPTEDCONNECTION); + Debug::log(LOG, Debug::RollingLogFollow::Get().DebugInfo()); + } else + close(ACCEPTEDCONNECTION); if (g_pConfigManager->m_bWantsMonitorReload) g_pConfigManager->ensureMonitorStatus(); diff --git a/src/debug/Log.cpp b/src/debug/Log.cpp index 8b82c852..7547204a 100644 --- a/src/debug/Log.cpp +++ b/src/debug/Log.cpp @@ -1,6 +1,7 @@ #include "Log.hpp" #include "../defines.hpp" #include "../Compositor.hpp" +#include "RollingLogFollow.hpp" #include #include @@ -73,6 +74,9 @@ void Debug::log(LogLevel level, std::string str) { if (rollingLog.size() > ROLLING_LOG_SIZE) rollingLog = rollingLog.substr(rollingLog.size() - ROLLING_LOG_SIZE); + if (RollingLogFollow::Get().IsRunning()) + RollingLogFollow::Get().AddLog(str); + if (!disableLogs || !**disableLogs) { // log to a file std::ofstream ofs; diff --git a/src/debug/RollingLogFollow.hpp b/src/debug/RollingLogFollow.hpp new file mode 100644 index 00000000..5ff018af --- /dev/null +++ b/src/debug/RollingLogFollow.hpp @@ -0,0 +1,65 @@ +#pragma once + +#include + +namespace Debug { + struct RollingLogFollow { + std::unordered_map socketToRollingLogFollowQueue; + std::shared_mutex m; + bool running = false; + static constexpr size_t ROLLING_LOG_FOLLOW_TOO_BIG = 8192; + + // Returns true if the queue is empty for the given socket + bool isEmpty(int socket) { + std::shared_lock r(m); + return socketToRollingLogFollowQueue[socket].empty(); + } + + std::string DebugInfo() { + std::shared_lock r(m); + return std::format("RollingLogFollow, got {} connections", socketToRollingLogFollowQueue.size()); + } + + std::string GetLog(int socket) { + std::unique_lock w(m); + + const std::string ret = socketToRollingLogFollowQueue[socket]; + socketToRollingLogFollowQueue[socket] = ""; + + return ret; + }; + + void AddLog(std::string log) { + std::unique_lock w(m); + running = true; + std::vector to_erase; + for (const auto& p : socketToRollingLogFollowQueue) + socketToRollingLogFollowQueue[p.first] += log + "\n"; + } + + bool IsRunning() { + std::shared_lock r(m); + return running; + } + + void StopFor(int socket) { + std::unique_lock w(m); + socketToRollingLogFollowQueue.erase(socket); + if (socketToRollingLogFollowQueue.empty()) + running = false; + } + + void StartFor(int socket) { + std::unique_lock w(m); + socketToRollingLogFollowQueue[socket] = std::format("[LOG] Following log to socket: {} started\n", socket); + running = true; + } + + static RollingLogFollow& Get() { + static RollingLogFollow instance; + static std::mutex gm; + std::lock_guard lock(gm); + return instance; + }; + }; +} From a9d53a2252f7ec084e2487d18777e2df01c8c351 Mon Sep 17 00:00:00 2001 From: UjinT34 <41110182+UjinT34@users.noreply.github.com> Date: Fri, 14 Jun 2024 14:45:32 +0300 Subject: [PATCH 0007/2181] vrr: add option to fix mouse breaking vrr (#6483) * option to fix mouse breaking vrr * skip damage on mouse move * remove this-> & cleanup * add cursor:min_refresh_rate to avoid cursor freezing * run clang-format --------- Co-authored-by: UjinT34 --- src/config/ConfigManager.cpp | 2 ++ src/helpers/Monitor.cpp | 18 ++++++++++++++++++ src/helpers/Monitor.hpp | 1 + src/managers/PointerManager.cpp | 2 +- src/managers/input/InputManager.cpp | 6 ++++-- src/render/Renderer.cpp | 5 +++-- src/render/Renderer.hpp | 2 +- 7 files changed, 30 insertions(+), 6 deletions(-) diff --git a/src/config/ConfigManager.cpp b/src/config/ConfigManager.cpp index e0de33cf..f63ff552 100644 --- a/src/config/ConfigManager.cpp +++ b/src/config/ConfigManager.cpp @@ -522,6 +522,8 @@ CConfigManager::CConfigManager() { m_pConfig->addConfigValue("opengl:force_introspection", Hyprlang::INT{2}); m_pConfig->addConfigValue("cursor:no_hardware_cursors", Hyprlang::INT{0}); + m_pConfig->addConfigValue("cursor:no_break_fs_vrr", Hyprlang::INT{0}); + m_pConfig->addConfigValue("cursor:min_refresh_rate", Hyprlang::INT{24}); m_pConfig->addConfigValue("cursor:hotspot_padding", Hyprlang::INT{1}); m_pConfig->addConfigValue("cursor:inactive_timeout", Hyprlang::INT{0}); m_pConfig->addConfigValue("cursor:no_warps", Hyprlang::INT{0}); diff --git a/src/helpers/Monitor.cpp b/src/helpers/Monitor.cpp index 027b47bd..58687e09 100644 --- a/src/helpers/Monitor.cpp +++ b/src/helpers/Monitor.cpp @@ -362,6 +362,24 @@ void CMonitor::addDamage(const CBox* box) { g_pCompositor->scheduleFrameForMonitor(this); } +bool CMonitor::shouldSkipScheduleFrameOnMouseEvent() { + static auto PNOBREAK = CConfigValue("cursor:no_break_fs_vrr"); + static auto PMINRR = CConfigValue("cursor:min_refresh_rate"); + + // skip scheduling extra frames for fullsreen apps with vrr + bool shouldSkip = *PNOBREAK && output->adaptive_sync_status == WLR_OUTPUT_ADAPTIVE_SYNC_ENABLED && activeWorkspace && activeWorkspace->m_bHasFullscreenWindow && + activeWorkspace->m_efFullscreenMode == FULLSCREEN_FULL; + + // keep requested minimum refresh rate + if (shouldSkip && *PMINRR && lastPresentationTimer.getMillis() > 1000 / *PMINRR) { + // damage whole screen because some previous cursor box damages were skipped + wlr_damage_ring_add_whole(&damage); + return false; + } + + return shouldSkip; +} + bool CMonitor::isMirror() { return pMirrorOf != nullptr; } diff --git a/src/helpers/Monitor.hpp b/src/helpers/Monitor.hpp index 4bfbf53c..c59e00ac 100644 --- a/src/helpers/Monitor.hpp +++ b/src/helpers/Monitor.hpp @@ -158,6 +158,7 @@ class CMonitor { void addDamage(const pixman_region32_t* rg); void addDamage(const CRegion* rg); void addDamage(const CBox* box); + bool shouldSkipScheduleFrameOnMouseEvent(); void setMirror(const std::string&); bool isMirror(); bool matchesStaticSelector(const std::string& selector) const; diff --git a/src/managers/PointerManager.cpp b/src/managers/PointerManager.cpp index bf7b5d0a..3a28ea8d 100644 --- a/src/managers/PointerManager.cpp +++ b/src/managers/PointerManager.cpp @@ -675,7 +675,7 @@ void CPointerManager::damageIfSoftware() { continue; if ((mw->softwareLocks > 0 || mw->hardwareFailed || *PNOHW) && b.overlaps({mw->monitor->vecPosition, mw->monitor->vecSize})) { - g_pHyprRenderer->damageBox(&b); + g_pHyprRenderer->damageBox(&b, mw->monitor->shouldSkipScheduleFrameOnMouseEvent()); break; } } diff --git a/src/managers/input/InputManager.cpp b/src/managers/input/InputManager.cpp index 3aa8d2ae..81a46f97 100644 --- a/src/managers/input/InputManager.cpp +++ b/src/managers/input/InputManager.cpp @@ -187,7 +187,9 @@ void CInputManager::mouseMoveUnified(uint32_t time, bool refocus) { if (*PZOOMFACTOR != 1.f) g_pHyprRenderer->damageMonitor(PMONITOR); - if (!PMONITOR->solitaryClient.lock() && g_pHyprRenderer->shouldRenderCursor() && PMONITOR->output->software_cursor_locks > 0) + bool skipFrameSchedule = PMONITOR->shouldSkipScheduleFrameOnMouseEvent(); + + if (!PMONITOR->solitaryClient.lock() && g_pHyprRenderer->shouldRenderCursor() && PMONITOR->output->software_cursor_locks > 0 && !skipFrameSchedule) g_pCompositor->scheduleFrameForMonitor(PMONITOR); PHLWINDOW forcedFocus = m_pForcedFocus.lock(); @@ -370,7 +372,7 @@ void CInputManager::mouseMoveUnified(uint32_t time, bool refocus) { foundSurface = g_pCompositor->vectorToLayerSurface(mouseCoords, &PMONITOR->m_aLayerSurfaceLayers[ZWLR_LAYER_SHELL_V1_LAYER_BACKGROUND], &surfaceCoords, &pFoundLayerSurface); - if (g_pCompositor->m_pLastMonitor->output->software_cursor_locks > 0) + if (g_pCompositor->m_pLastMonitor->output->software_cursor_locks > 0 && !skipFrameSchedule) g_pCompositor->scheduleFrameForMonitor(g_pCompositor->m_pLastMonitor.get()); // grabs diff --git a/src/render/Renderer.cpp b/src/render/Renderer.cpp index 4fe35c7e..19b646a4 100644 --- a/src/render/Renderer.cpp +++ b/src/render/Renderer.cpp @@ -1763,7 +1763,7 @@ void CHyprRenderer::damageMonitor(CMonitor* pMonitor) { Debug::log(LOG, "Damage: Monitor {}", pMonitor->szName); } -void CHyprRenderer::damageBox(CBox* pBox) { +void CHyprRenderer::damageBox(CBox* pBox, bool skipFrameSchedule) { if (g_pCompositor->m_bUnsafeState) return; @@ -1773,7 +1773,8 @@ void CHyprRenderer::damageBox(CBox* pBox) { CBox damageBox = {pBox->x - m->vecPosition.x, pBox->y - m->vecPosition.y, pBox->width, pBox->height}; damageBox.scale(m->scale); - m->addDamage(&damageBox); + if (!skipFrameSchedule) + m->addDamage(&damageBox); } static auto PLOGDAMAGE = CConfigValue("debug:log_damage"); diff --git a/src/render/Renderer.hpp b/src/render/Renderer.hpp index 60101e87..6adca72a 100644 --- a/src/render/Renderer.hpp +++ b/src/render/Renderer.hpp @@ -48,7 +48,7 @@ class CHyprRenderer { void arrangeLayersForMonitor(const int&); void damageSurface(SP, double, double, double scale = 1.0); void damageWindow(PHLWINDOW, bool forceFull = false); - void damageBox(CBox*); + void damageBox(CBox*, bool skipFrameSchedule = false); void damageBox(const int& x, const int& y, const int& w, const int& h); void damageRegion(const CRegion&); void damageMonitor(CMonitor*); From a357fa3e0a60b4f96a1924e0d9753d23001ab00e Mon Sep 17 00:00:00 2001 From: Vaxry Date: Fri, 14 Jun 2024 16:45:41 +0200 Subject: [PATCH 0008/2181] window: use effective damage for tearing re-schedules fixes #6377 --- src/events/Windows.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/events/Windows.cpp b/src/events/Windows.cpp index 899318ce..becff152 100644 --- a/src/events/Windows.cpp +++ b/src/events/Windows.cpp @@ -803,7 +803,7 @@ void Events::listener_commitWindow(void* owner, void* data) { // tearing: if solitary, redraw it. This still might be a single surface window const auto PMONITOR = g_pCompositor->getMonitorFromID(PWINDOW->m_iMonitorID); if (PMONITOR && PMONITOR->solitaryClient.lock() == PWINDOW && PWINDOW->canBeTorn() && PMONITOR->tearingState.canTear && PWINDOW->m_pWLSurface->resource()->current.buffer) { - CRegion damageBox{PWINDOW->m_pWLSurface->resource()->current.bufferDamage}; + CRegion damageBox{PWINDOW->m_pWLSurface->resource()->accumulateCurrentBufferDamage()}; if (!damageBox.empty()) { if (PMONITOR->tearingState.busy) { From 12ce06f39b2194685ddeadf656ebf2d334836992 Mon Sep 17 00:00:00 2001 From: Vaxry Date: Fri, 14 Jun 2024 19:10:12 +0200 Subject: [PATCH 0009/2181] format: fix flipped r/b channels on legacy_renderer We don't wanna use an extension, but for gles2 there is no other option. fixes #6465 --- src/helpers/Format.cpp | 16 ++++++++++++---- 1 file changed, 12 insertions(+), 4 deletions(-) diff --git a/src/helpers/Format.cpp b/src/helpers/Format.cpp index 9c94f68b..65828519 100644 --- a/src/helpers/Format.cpp +++ b/src/helpers/Format.cpp @@ -11,9 +11,13 @@ */ inline const std::vector GLES3_FORMATS = { { - .drmFormat = DRM_FORMAT_ARGB8888, - .flipRB = true, - .glFormat = GL_RGBA, + .drmFormat = DRM_FORMAT_ARGB8888, + .flipRB = true, +#ifndef GLES2 + .glFormat = GL_RGBA, +#else + .glFormat = GL_BGRA_EXT, +#endif .glType = GL_UNSIGNED_BYTE, .withAlpha = true, .alphaStripped = DRM_FORMAT_XRGB8888, @@ -22,7 +26,11 @@ inline const std::vector GLES3_FORMATS = { { .drmFormat = DRM_FORMAT_XRGB8888, .flipRB = true, - .glFormat = GL_RGBA, +#ifndef GLES2 + .glFormat = GL_RGBA, +#else + .glFormat = GL_BGRA_EXT, +#endif .glType = GL_UNSIGNED_BYTE, .withAlpha = false, .alphaStripped = DRM_FORMAT_XRGB8888, From 2f278dc883f3e4e84fb1d18154132f8f4efe42cf Mon Sep 17 00:00:00 2001 From: Vaxry Date: Fri, 14 Jun 2024 21:59:21 +0200 Subject: [PATCH 0010/2181] egl: fixup format modifier lookups with implicit modifiers ref #6485 --- src/helpers/Format.cpp | 4 ++-- src/render/OpenGL.cpp | 32 ++++++++++++++++++++++---------- src/render/OpenGL.hpp | 4 +++- 3 files changed, 27 insertions(+), 13 deletions(-) diff --git a/src/helpers/Format.cpp b/src/helpers/Format.cpp index 65828519..08c3ca63 100644 --- a/src/helpers/Format.cpp +++ b/src/helpers/Format.cpp @@ -24,8 +24,8 @@ inline const std::vector GLES3_FORMATS = { .bytesPerBlock = 4, }, { - .drmFormat = DRM_FORMAT_XRGB8888, - .flipRB = true, + .drmFormat = DRM_FORMAT_XRGB8888, + .flipRB = true, #ifndef GLES2 .glFormat = GL_RGBA, #else diff --git a/src/render/OpenGL.cpp b/src/render/OpenGL.cpp index 406ffdd0..5d8d6b83 100644 --- a/src/render/OpenGL.cpp +++ b/src/render/OpenGL.cpp @@ -79,20 +79,20 @@ CHyprOpenGLImpl::CHyprOpenGLImpl() { m_tGlobalTimer.reset(); } -std::vector CHyprOpenGLImpl::getModsForFormat(EGLint format) { +std::optional> CHyprOpenGLImpl::getModsForFormat(EGLint format) { // TODO: return std::expected when clang supports it if (!m_sExts.EXT_image_dma_buf_import_modifiers) - return {}; + return std::nullopt; EGLint len = 0; if (!m_sProc.eglQueryDmaBufModifiersEXT(wlr_egl_get_display(g_pCompositor->m_sWLREGL), format, 0, nullptr, nullptr, &len)) { Debug::log(ERR, "EGL: Failed to query mods"); - return {}; + return std::nullopt; } if (len <= 0) - return {DRM_FORMAT_MOD_LINEAR, DRM_FORMAT_MOD_INVALID}; // assume the driver can do linear and implicit. + return std::vector{}; std::vector mods; std::vector external; @@ -103,13 +103,21 @@ std::vector CHyprOpenGLImpl::getModsForFormat(EGLint format) { m_sProc.eglQueryDmaBufModifiersEXT(wlr_egl_get_display(g_pCompositor->m_sWLREGL), format, len, mods.data(), external.data(), &len); std::vector result; + bool linearIsExternal = false; for (size_t i = 0; i < mods.size(); ++i) { - if (external.at(i)) + if (external.at(i)) { + if (mods.at(i) == DRM_FORMAT_MOD_LINEAR) + linearIsExternal = true; continue; + } result.push_back(mods.at(i)); } + // if the driver doesn't mark linear as external, add it. It's allowed unless the driver says otherwise. (e.g. nvidia) + if (!linearIsExternal && std::find(mods.begin(), mods.end(), DRM_FORMAT_MOD_LINEAR) == mods.end() && mods.size() == 0) + mods.push_back(DRM_FORMAT_MOD_LINEAR); + return result; } @@ -147,15 +155,19 @@ void CHyprOpenGLImpl::initDRMFormats() { for (auto& fmt : formats) { std::vector mods; - if (!DISABLE_MODS) - mods = getModsForFormat(fmt); - else + if (!DISABLE_MODS) { + auto ret = getModsForFormat(fmt); + if (!ret.has_value()) + continue; + + mods = *ret; + } else mods = {DRM_FORMAT_MOD_LINEAR}; m_bHasModifiers = m_bHasModifiers || mods.size() > 0; - if (mods.size() == 0) - continue; + // EGL can always do implicit modifiers. + mods.push_back(DRM_FORMAT_MOD_INVALID); dmaFormats.push_back(SDRMFormat{ .format = fmt, diff --git a/src/render/OpenGL.hpp b/src/render/OpenGL.hpp index db0f8ea1..c6e173e5 100644 --- a/src/render/OpenGL.hpp +++ b/src/render/OpenGL.hpp @@ -238,7 +238,9 @@ class CHyprOpenGLImpl { void createBGTextureForMonitor(CMonitor*); void initShaders(); void initDRMFormats(); - std::vector getModsForFormat(EGLint format); + + // + std::optional> getModsForFormat(EGLint format); // returns the out FB, can be either Mirror or MirrorSwap CFramebuffer* blurMainFramebufferWithDamage(float a, CRegion* damage); From cb63398f079b4b4324c04e2e41ba17983d66487c Mon Sep 17 00:00:00 2001 From: vaxerski Date: Fri, 14 Jun 2024 20:00:53 +0000 Subject: [PATCH 0011/2181] [gha] Nix: update inputs --- flake.lock | 30 +++++++++++++++--------------- 1 file changed, 15 insertions(+), 15 deletions(-) diff --git a/flake.lock b/flake.lock index 477db69b..94fc9d90 100644 --- a/flake.lock +++ b/flake.lock @@ -13,11 +13,11 @@ ] }, "locked": { - "lastModified": 1717181720, - "narHash": "sha256-yv+QZWsusu/NWjydkxixHC2g+tIJ9v+xkE2EiVpJj6g=", + "lastModified": 1718368322, + "narHash": "sha256-VfMg3RsnRLQzbq0hFIh1dCM09b5C/F/qPFUOgU/CRi0=", "owner": "hyprwm", "repo": "hyprcursor", - "rev": "9e27a2c2ceb1e0b85bd55b0afefad196056fe87c", + "rev": "dd3a853c8239d1c3f3f37de7d2b8ae4b4f3840df", "type": "github" }, "original": { @@ -87,11 +87,11 @@ ] }, "locked": { - "lastModified": 1717881334, - "narHash": "sha256-a0inRgJhPL6v9v7RPM/rx1kbXdfe3xJA1c9z0ZkYnh4=", + "lastModified": 1718271409, + "narHash": "sha256-8KvVqtApNt4FWTdn1TqVvw00rpqyG9UuUPA2ilPVD1U=", "owner": "hyprwm", "repo": "hyprutils", - "rev": "0693f9398ab693d89c9a0aa3b3d062dd61b7a60e", + "rev": "8e10e0626fb26a14b859b3811b6ed7932400c86e", "type": "github" }, "original": { @@ -110,11 +110,11 @@ ] }, "locked": { - "lastModified": 1717784906, - "narHash": "sha256-YxmfxHfWed1fosaa7fC1u7XoKp1anEZU+7Lh/ojRKoM=", + "lastModified": 1718119275, + "narHash": "sha256-nqDYXATNkyGXVmNMkT19fT4sjtSPBDS1LLOxa3Fueo4=", "owner": "hyprwm", "repo": "hyprwayland-scanner", - "rev": "0f30f9eca6e404130988554accbb64d1c9ec877d", + "rev": "1419520d5f7f38d35e05504da5c1b38212a38525", "type": "github" }, "original": { @@ -125,11 +125,11 @@ }, "nixpkgs": { "locked": { - "lastModified": 1717974879, - "narHash": "sha256-GTO3C88+5DX171F/gVS3Qga/hOs/eRMxPFpiHq2t+D8=", + "lastModified": 1718318537, + "narHash": "sha256-4Zu0RYRcAY/VWuu6awwq4opuiD//ahpc2aFHg2CWqFY=", "owner": "NixOS", "repo": "nixpkgs", - "rev": "c7b821ba2e1e635ba5a76d299af62821cbcb09f3", + "rev": "e9ee548d90ff586a6471b4ae80ae9cfcbceb3420", "type": "github" }, "original": { @@ -179,11 +179,11 @@ ] }, "locked": { - "lastModified": 1717918856, - "narHash": "sha256-I38bmPLqamvOfVSArd1hhZtkVRAYBK38fOHZCU1P9Qg=", + "lastModified": 1718272114, + "narHash": "sha256-KsX7sAwkEFpXiwyjt0HGTnnrUU58wW1jlzj5IA/LRz8=", "owner": "hyprwm", "repo": "xdg-desktop-portal-hyprland", - "rev": "72907822c19afc0983c69d59d299204381623725", + "rev": "24be4a26f0706e456fca1b61b8c79f7486a9e86d", "type": "github" }, "original": { From df0c014ba0c9c665df51fe7750ab9d7288b57478 Mon Sep 17 00:00:00 2001 From: Vaxry Date: Sat, 15 Jun 2024 16:06:02 +0200 Subject: [PATCH 0012/2181] xwayland: use safeRemove for removing files fixes #6514 --- src/xwayland/Server.cpp | 18 +++++++++++++----- 1 file changed, 13 insertions(+), 5 deletions(-) diff --git a/src/xwayland/Server.cpp b/src/xwayland/Server.cpp index 26010cfb..e2dab412 100644 --- a/src/xwayland/Server.cpp +++ b/src/xwayland/Server.cpp @@ -155,6 +155,14 @@ static int xwaylandReady(int fd, uint32_t mask, void* data) { return g_pXWayland->pServer->ready(fd, mask); } +static bool safeRemove(const std::string& path) { + try { + return std::filesystem::remove(path); + } catch (std::exception& e) { Debug::log(ERR, "[XWayland] failed to remove {}", path); } + + return false; +} + bool CXWaylandServer::tryOpenSockets() { for (size_t i = 0; i <= 32; ++i) { auto LOCK = std::format("/tmp/.X{}-lock", i); @@ -162,7 +170,7 @@ bool CXWaylandServer::tryOpenSockets() { if (int fd = open(LOCK.c_str(), O_WRONLY | O_CREAT | O_EXCL | O_CLOEXEC, 0444); fd >= 0) { // we managed to open the lock if (!openSockets(xFDs, i)) { - std::filesystem::remove(LOCK); + safeRemove(LOCK); close(fd); continue; } @@ -170,7 +178,7 @@ bool CXWaylandServer::tryOpenSockets() { const auto PIDSTR = std::format("{}", getpid()); if (write(fd, PIDSTR.c_str(), PIDSTR.length()) != (long)PIDSTR.length()) { - std::filesystem::remove(LOCK); + safeRemove(LOCK); close(fd); continue; } @@ -197,7 +205,7 @@ bool CXWaylandServer::tryOpenSockets() { } catch (...) { continue; } if (kill(pid, 0) != 0 && errno == ESRCH) { - if (!std::filesystem::remove(LOCK)) + if (!safeRemove(LOCK)) continue; i--; @@ -228,7 +236,7 @@ CXWaylandServer::~CXWaylandServer() { close(xFDs[1]); auto LOCK = std::format("/tmp/.X{}-lock", display); - std::filesystem::remove(LOCK); + safeRemove(LOCK); std::string path; #ifdef __linux__ @@ -236,7 +244,7 @@ CXWaylandServer::~CXWaylandServer() { #else path = std::format("/tmp/.X11-unix/X{}_", display); #endif - std::filesystem::remove(path); + safeRemove(path); } void CXWaylandServer::die() { From 32aca887522063cf728357af247ca6f20d93eb97 Mon Sep 17 00:00:00 2001 From: Vaxry Date: Sat, 15 Jun 2024 16:20:00 +0200 Subject: [PATCH 0013/2181] keybinds: add custom event dispatcher fixes #3439 --- src/managers/KeybindManager.cpp | 5 +++++ src/managers/KeybindManager.hpp | 1 + 2 files changed, 6 insertions(+) diff --git a/src/managers/KeybindManager.cpp b/src/managers/KeybindManager.cpp index 49ea39a3..eb07850c 100644 --- a/src/managers/KeybindManager.cpp +++ b/src/managers/KeybindManager.cpp @@ -114,6 +114,7 @@ CKeybindManager::CKeybindManager() { m_mDispatchers["movewindoworgroup"] = moveWindowOrGroup; m_mDispatchers["setignoregrouplock"] = setIgnoreGroupLock; m_mDispatchers["denywindowfromgroup"] = denyWindowFromGroup; + m_mDispatchers["event"] = event; m_mDispatchers["global"] = global; m_tScrollTimer.reset(); @@ -2680,3 +2681,7 @@ void CKeybindManager::moveGroupWindow(std::string args) { PLASTWINDOW->updateWindowDecos(); } + +void CKeybindManager::event(std::string args) { + g_pEventManager->postEvent(SHyprIPCEvent{"custom", args}); +} diff --git a/src/managers/KeybindManager.hpp b/src/managers/KeybindManager.hpp index ecab6ee1..2a256760 100644 --- a/src/managers/KeybindManager.hpp +++ b/src/managers/KeybindManager.hpp @@ -205,6 +205,7 @@ class CKeybindManager { static void setIgnoreGroupLock(std::string); static void denyWindowFromGroup(std::string); static void global(std::string); + static void event(std::string); friend class CCompositor; friend class CInputManager; From fb82f6bcd7d829a3ab2d2cb7d9a27f3837abfb80 Mon Sep 17 00:00:00 2001 From: Vaxry Date: Sat, 15 Jun 2024 16:31:35 +0200 Subject: [PATCH 0014/2181] animations: fix overriding direction for slide fixes #6512 --- src/managers/AnimationManager.cpp | 21 ++++++++++----------- 1 file changed, 10 insertions(+), 11 deletions(-) diff --git a/src/managers/AnimationManager.cpp b/src/managers/AnimationManager.cpp index f8cb0184..74fe4117 100644 --- a/src/managers/AnimationManager.cpp +++ b/src/managers/AnimationManager.cpp @@ -6,6 +6,7 @@ #include "../desktop/Window.hpp" #include "../desktop/LayerSurface.hpp" #include "eventLoop/EventLoopManager.hpp" +#include "../helpers/varlist/VarList.hpp" int wlTick(SP self, void* data) { if (g_pAnimationManager) @@ -396,6 +397,8 @@ void CAnimationManager::onWindowPostCreateClose(PHLWINDOW pWindow, bool close) { auto ANIMSTYLE = pWindow->m_vRealPosition.m_pConfig->pValues->internalStyle; transform(ANIMSTYLE.begin(), ANIMSTYLE.end(), ANIMSTYLE.begin(), ::tolower); + CVarList animList(ANIMSTYLE, 0, 's'); + // if the window is not being animated, that means the layout set a fixed size for it, don't animate. if (!pWindow->m_vRealPosition.isBeingAnimated() && !pWindow->m_vRealSize.isBeingAnimated()) return; @@ -407,12 +410,8 @@ void CAnimationManager::onWindowPostCreateClose(PHLWINDOW pWindow, bool close) { if (pWindow->m_sAdditionalConfigData.animationStyle != "") { // the window has config'd special anim if (pWindow->m_sAdditionalConfigData.animationStyle.starts_with("slide")) { - if (pWindow->m_sAdditionalConfigData.animationStyle.contains(' ')) { - // has a direction - animationSlide(pWindow, pWindow->m_sAdditionalConfigData.animationStyle.substr(pWindow->m_sAdditionalConfigData.animationStyle.find(' ') + 1), close); - } else { - animationSlide(pWindow, "", close); - } + CVarList animList2(pWindow->m_sAdditionalConfigData.animationStyle, 0, 's'); + animationSlide(pWindow, animList2[1], close); } else { // anim popin, fallback @@ -429,9 +428,9 @@ void CAnimationManager::onWindowPostCreateClose(PHLWINDOW pWindow, bool close) { animationPopin(pWindow, close, minPerc / 100.f); } } else { - if (ANIMSTYLE == "slide") { - animationSlide(pWindow, "", close); - } else { + if (animList[0] == "slide") + animationSlide(pWindow, animList[1], close); + else { // anim popin, fallback float minPerc = 0.f; @@ -451,9 +450,9 @@ void CAnimationManager::onWindowPostCreateClose(PHLWINDOW pWindow, bool close) { std::string CAnimationManager::styleValidInConfigVar(const std::string& config, const std::string& style) { if (config.starts_with("window")) { - if (style == "slide") { + if (style.starts_with("slide")) return ""; - } else if (style.starts_with("popin")) { + else if (style.starts_with("popin")) { // try parsing float minPerc = 0.f; if (style.find("%") != std::string::npos) { From 46ef6653be90f1a3e2a8cecc1fd9112dc3c6f464 Mon Sep 17 00:00:00 2001 From: Vaxry Date: Sat, 15 Jun 2024 17:33:21 +0200 Subject: [PATCH 0015/2181] data-device: abort drag on unaccepted offers fixes #6509 --- src/protocols/core/DataDevice.cpp | 28 ++++++++++++++++++++++++++-- src/protocols/core/DataDevice.hpp | 1 + 2 files changed, 27 insertions(+), 2 deletions(-) diff --git a/src/protocols/core/DataDevice.cpp b/src/protocols/core/DataDevice.cpp index c1de8f83..86b372bf 100644 --- a/src/protocols/core/DataDevice.cpp +++ b/src/protocols/core/DataDevice.cpp @@ -13,13 +13,17 @@ CWLDataOfferResource::CWLDataOfferResource(SP resource_, SPsetDestroy([this](CWlDataOffer* r) { - if (!dead) + if (!dead && (recvd || accepted)) PROTO::data->completeDrag(); + else + PROTO::data->abortDrag(); PROTO::data->destroyResource(this); }); resource->setOnDestroy([this](CWlDataOffer* r) { - if (!dead) + if (!dead && (recvd || accepted)) PROTO::data->completeDrag(); + else + PROTO::data->abortDrag(); PROTO::data->destroyResource(this); }); @@ -592,6 +596,11 @@ void CWLDataDeviceProtocol::dropDrag() { return; } + if (!wasDragSuccessful()) { + abortDrag(); + return; + } + dnd.currentSource->sendDndDropPerformed(); dnd.focusedDevice->sendDrop(); dnd.focusedDevice->sendLeave(); @@ -603,6 +612,21 @@ void CWLDataDeviceProtocol::dropDrag() { dnd.overriddenCursor = false; } +bool CWLDataDeviceProtocol::wasDragSuccessful() { + if (!dnd.focusedDevice || !dnd.currentSource) + return false; + + for (auto& o : m_vOffers) { + if (o->dead || !o->source || !o->source->hasDnd()) + continue; + + if (o->recvd || o->accepted) + return true; + } + + return false; +} + void CWLDataDeviceProtocol::completeDrag() { resetDndState(); diff --git a/src/protocols/core/DataDevice.hpp b/src/protocols/core/DataDevice.hpp index f31725ee..5b31559f 100644 --- a/src/protocols/core/DataDevice.hpp +++ b/src/protocols/core/DataDevice.hpp @@ -175,6 +175,7 @@ class CWLDataDeviceProtocol : public IWaylandProtocol { void dropDrag(); void completeDrag(); void resetDndState(); + bool wasDragSuccessful(); // SP dataDeviceForClient(wl_client*); From 6c24dc0bb147d60cc5c7e44cc3e257a737ead828 Mon Sep 17 00:00:00 2001 From: Vaxry Date: Sat, 15 Jun 2024 17:43:39 +0200 Subject: [PATCH 0016/2181] xdg-shell: fixup xdg-positioner's pointForAnchor with non-corner points fixes #6157 --- src/protocols/XDGShell.cpp | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/protocols/XDGShell.cpp b/src/protocols/XDGShell.cpp index dcbc6162..49b7b417 100644 --- a/src/protocols/XDGShell.cpp +++ b/src/protocols/XDGShell.cpp @@ -507,12 +507,12 @@ CXDGPositionerRules::CXDGPositionerRules(SP positioner) state = positioner->state; } -static Vector2D pointForAnchor(const CBox& box, xdgPositionerAnchor anchor) { +static Vector2D pointForAnchor(const CBox& box, const Vector2D& predictionSize, xdgPositionerAnchor anchor) { switch (anchor) { - case XDG_POSITIONER_ANCHOR_TOP: return box.pos() + Vector2D{box.size().x / 2.F, 0}; - case XDG_POSITIONER_ANCHOR_BOTTOM: return box.pos() + Vector2D{box.size().x / 2.F, box.size().y}; - case XDG_POSITIONER_ANCHOR_LEFT: return box.pos() + Vector2D{0, box.size().y / 2.F}; - case XDG_POSITIONER_ANCHOR_RIGHT: return box.pos() + Vector2D{box.size().x, box.size().y / 2.F}; + case XDG_POSITIONER_ANCHOR_TOP: return box.pos() + Vector2D{box.size().x / 2.F - predictionSize.x / 2.F, 0}; + case XDG_POSITIONER_ANCHOR_BOTTOM: return box.pos() + Vector2D{box.size().x / 2.F - predictionSize.x / 2.F, box.size().y}; + case XDG_POSITIONER_ANCHOR_LEFT: return box.pos() + Vector2D{0, box.size().y / 2.F - predictionSize.y / 2.F}; + case XDG_POSITIONER_ANCHOR_RIGHT: return box.pos() + Vector2D{box.size().x, box.size().y / 2.F - predictionSize.y / 2.F}; case XDG_POSITIONER_ANCHOR_TOP_LEFT: return box.pos(); case XDG_POSITIONER_ANCHOR_BOTTOM_LEFT: return box.pos() + Vector2D{0, box.size().y}; case XDG_POSITIONER_ANCHOR_TOP_RIGHT: return box.pos() + Vector2D{box.size().x, 0}; @@ -527,7 +527,7 @@ CBox CXDGPositionerRules::getPosition(const CBox& constraint, const Vector2D& pa Debug::log(LOG, "GetPosition with constraint {} {} and parent {}", constraint.pos(), constraint.size(), parentCoord); - CBox predictedBox = {parentCoord + constraint.pos() + pointForAnchor(state.anchorRect, state.anchor) + state.offset, state.requestedSize}; + CBox predictedBox = {parentCoord + constraint.pos() + pointForAnchor(state.anchorRect, state.requestedSize, state.anchor) + state.offset, state.requestedSize}; bool success = predictedBox.inside(constraint); From 77f44bfcab6c3e553d26a776c011613efbfe6cfd Mon Sep 17 00:00:00 2001 From: Vaxry Date: Sat, 15 Jun 2024 17:56:44 +0200 Subject: [PATCH 0017/2181] output: avoid crashes when binding a defunct wl_output global ref #6508 --- src/protocols/core/Output.cpp | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/protocols/core/Output.cpp b/src/protocols/core/Output.cpp index 90358fa5..10daa15e 100644 --- a/src/protocols/core/Output.cpp +++ b/src/protocols/core/Output.cpp @@ -9,6 +9,9 @@ CWLOutputResource::CWLOutputResource(SP resource_, SP pMoni pClient = resource->client(); + if (!monitor) + return; + resource->setOnDestroy([this](CWlOutput* r) { if (monitor && PROTO::outputs.contains(monitor->szName)) PROTO::outputs.at(monitor->szName)->destroyResource(this); @@ -69,6 +72,9 @@ CWLOutputProtocol::CWLOutputProtocol(const wl_interface* iface, const int& ver, } void CWLOutputProtocol::bindManager(wl_client* client, void* data, uint32_t ver, uint32_t id) { + if (defunct) + Debug::log(WARN, "[wl_output] Binding a wl_output that's inert?? Possible client bug."); + const auto RESOURCE = m_vOutputs.emplace_back(makeShared(makeShared(client, ver, id), monitor.lock())); if (!RESOURCE->good()) { From 91fe58f8f278d126852877eadc87c50ca7b9b78d Mon Sep 17 00:00:00 2001 From: Vaxry Date: Sat, 15 Jun 2024 18:20:09 +0200 Subject: [PATCH 0018/2181] window: improve swallowing functionality cleanups, fixes, etc. ref #6095 --- src/desktop/Window.cpp | 55 +++++++++++++++++++++++++++++++++ src/desktop/Window.hpp | 1 + src/events/Windows.cpp | 69 +++++------------------------------------- 3 files changed, 63 insertions(+), 62 deletions(-) diff --git a/src/desktop/Window.cpp b/src/desktop/Window.cpp index b02a53e0..d153b344 100644 --- a/src/desktop/Window.cpp +++ b/src/desktop/Window.cpp @@ -1540,3 +1540,58 @@ void CWindow::warpCursor() { else g_pCompositor->warpCursorTo(middle()); } + +PHLWINDOW CWindow::getSwallower() { + static auto PSWALLOWREGEX = CConfigValue("misc:swallow_regex"); + static auto PSWALLOWEXREGEX = CConfigValue("misc:swallow_exception_regex"); + static auto PSWALLOW = CConfigValue("misc:enable_swallow"); + + if (!*PSWALLOW || (*PSWALLOWREGEX).empty()) + return nullptr; + + // check parent + std::vector candidates; + pid_t currentPid = getPID(); + // walk up the tree until we find someone, 25 iterations max. + for (size_t i = 0; i < 25; ++i) { + currentPid = getPPIDof(currentPid); + + if (!currentPid) + break; + + for (auto& w : g_pCompositor->m_vWindows) { + if (!w->m_bIsMapped || w->isHidden()) + continue; + + if (w->getPID() == currentPid) + candidates.push_back(w); + } + } + + if (!(*PSWALLOWREGEX).empty()) + std::erase_if(candidates, [&](const auto& other) { return !std::regex_match(other->m_szClass, std::regex(*PSWALLOWREGEX)); }); + + if (candidates.size() <= 0) + return nullptr; + + if (!(*PSWALLOWEXREGEX).empty()) + std::erase_if(candidates, [&](const auto& other) { return std::regex_match(other->m_szTitle, std::regex(*PSWALLOWEXREGEX)); }); + + if (candidates.size() <= 0) + return nullptr; + + if (candidates.size() == 1) + return candidates.at(0); + + // walk up the focus history and find the last focused + for (auto& w : g_pCompositor->m_vWindowFocusHistory) { + if (!w) + continue; + + if (std::find(candidates.begin(), candidates.end(), w.lock()) != candidates.end()) + return w.lock(); + } + + // if none are found (??) then just return the first one + return candidates.at(0); +} diff --git a/src/desktop/Window.hpp b/src/desktop/Window.hpp index 85c74622..16bf297c 100644 --- a/src/desktop/Window.hpp +++ b/src/desktop/Window.hpp @@ -450,6 +450,7 @@ class CWindow { std::string fetchTitle(); std::string fetchClass(); void warpCursor(); + PHLWINDOW getSwallower(); // listeners void onAck(uint32_t serial); diff --git a/src/events/Windows.cpp b/src/events/Windows.cpp index becff152..d37ba12b 100644 --- a/src/events/Windows.cpp +++ b/src/events/Windows.cpp @@ -44,7 +44,6 @@ void Events::listener_mapWindow(void* owner, void* data) { static auto PDIMSTRENGTH = CConfigValue("decoration:dim_strength"); static auto PSWALLOW = CConfigValue("misc:enable_swallow"); static auto PSWALLOWREGEX = CConfigValue("misc:swallow_regex"); - static auto PSWALLOWEXREGEX = CConfigValue("misc:swallow_exception_regex"); static auto PNEWTAKESOVERFS = CConfigValue("misc:new_window_takes_over_fullscreen"); static auto PINITIALWSTRACKING = CConfigValue("misc:initial_workspace_tracking"); @@ -527,71 +526,17 @@ void Events::listener_mapWindow(void* owner, void* data) { // verify swallowing if (*PSWALLOW && std::string{*PSWALLOWREGEX} != STRVAL_EMPTY) { - // don't swallow ourselves - std::regex rgx(*PSWALLOWREGEX); - if (!std::regex_match(PWINDOW->m_szClass, rgx)) { - // check parent - int ppid = getPPIDof(PWINDOW->getPID()); + const auto SWALLOWER = PWINDOW->getSwallower(); - int curppid = 0; + if (SWALLOWER) { + // swallow + PWINDOW->m_pSwallowed = SWALLOWER; - for (int i = 0; i < 5; ++i) { - curppid = getPPIDof(ppid); + g_pLayoutManager->getCurrentLayout()->onWindowRemoved(SWALLOWER); - if (curppid < 10) { - break; - } + SWALLOWER->setHidden(true); - ppid = curppid; - } - - if (ppid) { - // get window by pid - std::vector found; - PHLWINDOW finalFound; - for (auto& w : g_pCompositor->m_vWindows) { - if (!w->m_bIsMapped || w->isHidden()) - continue; - - if (w->getPID() == ppid) { - found.push_back(w); - } - } - - if (found.size() > 1) { - for (auto& w : found) { - // try get the focus, otherwise we'll ignore to avoid swallowing incorrect windows - if (w == PFOCUSEDWINDOWPREV) { - finalFound = w; - break; - } - } - } else if (found.size() == 1) { - finalFound = found[0]; - } - - if (finalFound) { - bool valid = std::regex_match(PWINDOW->m_szClass, rgx); - - if (std::string{*PSWALLOWEXREGEX} != STRVAL_EMPTY) { - std::regex exc(*PSWALLOWEXREGEX); - - valid = valid && !std::regex_match(PWINDOW->m_szTitle, exc); - } - - // check if it's the window we want & not exempt from getting swallowed - if (valid) { - // swallow - PWINDOW->m_pSwallowed = finalFound; - - g_pLayoutManager->getCurrentLayout()->onWindowRemoved(finalFound); - - finalFound->setHidden(true); - - g_pLayoutManager->getCurrentLayout()->recalculateMonitor(PWINDOW->m_iMonitorID); - } - } - } + g_pLayoutManager->getCurrentLayout()->recalculateMonitor(PWINDOW->m_iMonitorID); } } From 89f795da98cc53faf7e3a683d8c189aa24986267 Mon Sep 17 00:00:00 2001 From: memchr Date: Sat, 15 Jun 2024 19:17:38 +0000 Subject: [PATCH 0019/2181] master: refine master layout new window handling (#6479) * ## Open window relative to active window `new_on_active`: - `none` (default): - `before`: above of the focused window - `after`: below the focused window If the focused window is the solo master window, or the new window replaces master, this option has no effect and new_on_top are respected. ## Refine new window status control **BREAKING CHANGE**: new_is_master removed in favour of new variable `new_status`: - `slave` (default): new window open as slave - `master`: new window open as master - `inherit`: new window inherit status from active window, i.e. when the focused window is master, new window will become new master, otherwise new window are added to slaves * refactor: rename a few variables --- src/config/ConfigManager.cpp | 3 +- src/layout/MasterLayout.cpp | 54 +++++++++++++++++++++++++++--------- 2 files changed, 43 insertions(+), 14 deletions(-) diff --git a/src/config/ConfigManager.cpp b/src/config/ConfigManager.cpp index f63ff552..1b069f5d 100644 --- a/src/config/ConfigManager.cpp +++ b/src/config/ConfigManager.cpp @@ -431,8 +431,9 @@ CConfigManager::CConfigManager() { m_pConfig->addConfigValue("master:special_scale_factor", {1.f}); m_pConfig->addConfigValue("master:mfact", {0.55f}); - m_pConfig->addConfigValue("master:new_is_master", Hyprlang::INT{1}); + m_pConfig->addConfigValue("master:new_status", {"slave"}); m_pConfig->addConfigValue("master:always_center_master", Hyprlang::INT{0}); + m_pConfig->addConfigValue("master:new_on_active", {"none"}); m_pConfig->addConfigValue("master:new_on_top", Hyprlang::INT{0}); m_pConfig->addConfigValue("master:no_gaps_when_only", Hyprlang::INT{0}); m_pConfig->addConfigValue("master:orientation", {"left"}); diff --git a/src/layout/MasterLayout.cpp b/src/layout/MasterLayout.cpp index af0182e1..c5784c74 100644 --- a/src/layout/MasterLayout.cpp +++ b/src/layout/MasterLayout.cpp @@ -76,17 +76,31 @@ void CHyprMasterLayout::onWindowCreatedTiling(PHLWINDOW pWindow, eDirection dire if (pWindow->m_bIsFloating) return; - static auto PNEWTOP = CConfigValue("master:new_on_top"); + static auto PNEWONACTIVE = CConfigValue("master:new_on_active"); + static auto PNEWONTOP = CConfigValue("master:new_on_top"); + static auto PNEWSTATUS = CConfigValue("master:new_status"); const auto PMONITOR = g_pCompositor->getMonitorFromID(pWindow->m_iMonitorID); - const auto PNODE = *PNEWTOP ? &m_lMasterNodesData.emplace_front() : &m_lMasterNodesData.emplace_back(); + const bool BNEWBEFOREACTIVE = *PNEWONACTIVE == "before"; + const bool BNEWISMASTER = *PNEWSTATUS == "master"; + + const auto PNODE = [&]() { + if (*PNEWONACTIVE != "none" && !BNEWISMASTER) { + const auto pLastNode = getNodeFromWindow(g_pCompositor->m_pLastWindow.lock()); + if (pLastNode && !(pLastNode->isMaster && (getMastersOnWorkspace(pWindow->workspaceID()) == 1 || *PNEWSTATUS == "slave"))) { + auto it = std::find(m_lMasterNodesData.begin(), m_lMasterNodesData.end(), *pLastNode); + if (!BNEWBEFOREACTIVE) + ++it; + return &(*m_lMasterNodesData.emplace(it)); + } + } + return *PNEWONTOP ? &m_lMasterNodesData.emplace_front() : &m_lMasterNodesData.emplace_back(); + }(); PNODE->workspaceID = pWindow->workspaceID(); PNODE->pWindow = pWindow; - static auto PNEWISMASTER = CConfigValue("master:new_is_master"); - const auto WINDOWSONWORKSPACE = getNodesOnWorkspace(PNODE->workspaceID); static auto PMFACT = CConfigValue("master:mfact"); float lastSplitPercent = *PMFACT; @@ -186,13 +200,27 @@ void CHyprMasterLayout::onWindowCreatedTiling(PHLWINDOW pWindow, eDirection dire } } - if ((*PNEWISMASTER && g_pInputManager->dragMode != MBIND_MOVE) || WINDOWSONWORKSPACE == 1 || (WINDOWSONWORKSPACE > 2 && !pWindow->m_bFirstMap && OPENINGON->isMaster) || - forceDropAsMaster) { - for (auto& nd : m_lMasterNodesData) { - if (nd.isMaster && nd.workspaceID == PNODE->workspaceID) { - nd.isMaster = false; - lastSplitPercent = nd.percMaster; - break; + if ((BNEWISMASTER && g_pInputManager->dragMode != MBIND_MOVE) // + || WINDOWSONWORKSPACE == 1 // + || (WINDOWSONWORKSPACE > 2 && !pWindow->m_bFirstMap && OPENINGON->isMaster) // + || forceDropAsMaster // + || (*PNEWSTATUS == "inherit" && OPENINGON && OPENINGON->isMaster && g_pInputManager->dragMode != MBIND_MOVE)) { + + if (BNEWBEFOREACTIVE) { + for (auto& nd : m_lMasterNodesData | std::views::reverse) { + if (nd.isMaster && nd.workspaceID == PNODE->workspaceID) { + nd.isMaster = false; + lastSplitPercent = nd.percMaster; + break; + } + } + } else { + for (auto& nd : m_lMasterNodesData) { + if (nd.isMaster && nd.workspaceID == PNODE->workspaceID) { + nd.isMaster = false; + lastSplitPercent = nd.percMaster; + break; + } } } @@ -1440,7 +1468,7 @@ void CHyprMasterLayout::replaceWindowDataWith(PHLWINDOW from, PHLWINDOW to) { } Vector2D CHyprMasterLayout::predictSizeForNewWindowTiled() { - static auto PNEWISMASTER = CConfigValue("master:new_is_master"); + static auto PNEWSTATUS = CConfigValue("master:new_status"); if (!g_pCompositor->m_pLastMonitor) return {}; @@ -1454,7 +1482,7 @@ Vector2D CHyprMasterLayout::predictSizeForNewWindowTiled() { if (!MASTER) // wtf return {}; - if (*PNEWISMASTER) { + if (*PNEWSTATUS == "master") { return MASTER->size; } else { const auto SLAVES = NODES - getMastersOnWorkspace(g_pCompositor->m_pLastMonitor->activeWorkspace->m_iID); From 908bec1564e4fe448a2a8a7371bbb0621c62b11a Mon Sep 17 00:00:00 2001 From: Vaxry Date: Sat, 15 Jun 2024 21:24:26 +0200 Subject: [PATCH 0020/2181] wl_seat: send repeat data from current keyboard on bind ref #6515 --- src/protocols/core/Seat.cpp | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/src/protocols/core/Seat.cpp b/src/protocols/core/Seat.cpp index 331eb15e..8f9174f5 100644 --- a/src/protocols/core/Seat.cpp +++ b/src/protocols/core/Seat.cpp @@ -200,10 +200,13 @@ CWLKeyboardResource::CWLKeyboardResource(SP resource_, SPsetRelease([this](CWlKeyboard* r) { PROTO::seat->destroyResource(this); }); resource->setOnDestroy([this](CWlKeyboard* r) { PROTO::seat->destroyResource(this); }); - static auto REPEAT = CConfigValue("input:repeat_rate"); - static auto DELAY = CConfigValue("input:repeat_delay"); + if (!g_pSeatManager->keyboard) { + LOGM(ERR, "No keyboard on bound wl_keyboard??"); + return; + } + sendKeymap(g_pSeatManager->keyboard.lock()); - repeatInfo(*REPEAT, *DELAY); + repeatInfo(g_pSeatManager->keyboard->repeatRate, g_pSeatManager->keyboard->repeatDelay); } bool CWLKeyboardResource::good() { From 1f5fd7e64a1c0e8d1815bdd6d168193bf9c28d6d Mon Sep 17 00:00:00 2001 From: Vaxry Date: Sat, 15 Jun 2024 21:46:36 +0200 Subject: [PATCH 0021/2181] hyprpm: add --no-shallow --- hyprpm/src/core/PluginManager.cpp | 2 +- hyprpm/src/core/PluginManager.hpp | 3 ++- hyprpm/src/main.cpp | 10 +++++++--- 3 files changed, 10 insertions(+), 5 deletions(-) diff --git a/hyprpm/src/core/PluginManager.cpp b/hyprpm/src/core/PluginManager.cpp index e8c6e251..848b9cab 100644 --- a/hyprpm/src/core/PluginManager.cpp +++ b/hyprpm/src/core/PluginManager.cpp @@ -427,7 +427,7 @@ bool CPluginManager::updateHeaders(bool force) { progress.printMessageAbove(std::string{Colors::YELLOW} + "!" + Colors::RESET + " Cloning https://github.com/hyprwm/hyprland, this might take a moment."); - const bool bShallow = HLVER.branch == "main" || HLVER.branch == ""; + const bool bShallow = (HLVER.branch == "main" || HLVER.branch == "") && !m_bNoShallow; // let us give a bit of leg-room for shallowing // due to timezones, etc. diff --git a/hyprpm/src/core/PluginManager.hpp b/hyprpm/src/core/PluginManager.hpp index a87240e3..13ea5b12 100644 --- a/hyprpm/src/core/PluginManager.hpp +++ b/hyprpm/src/core/PluginManager.hpp @@ -58,7 +58,8 @@ class CPluginManager { bool hasDeps(); - bool m_bVerbose = false; + bool m_bVerbose = false; + bool m_bNoShallow = false; // will delete recursively if exists!! bool createSafeDirectory(const std::string& path); diff --git a/hyprpm/src/main.cpp b/hyprpm/src/main.cpp index 38b32c83..4f00f708 100644 --- a/hyprpm/src/main.cpp +++ b/hyprpm/src/main.cpp @@ -26,6 +26,7 @@ const std::string HELP = R"#(┏ hyprpm, a Hyprland Plugin Manager ┣ --help | -h → Show this menu ┣ --verbose | -v → Enable too much logging ┣ --force | -f → Force an operation ignoring checks (e.g. update -f) +┣ --no-shallow | -s → Disable shallow cloning of Hyprland sources ┗ )#"; @@ -41,7 +42,7 @@ int main(int argc, char** argv, char** envp) { } std::vector command; - bool notify = false, verbose = false, force = false; + bool notify = false, verbose = false, force = false, noShallow = false; for (int i = 1; i < argc; ++i) { if (ARGS[i].starts_with("-")) { @@ -52,6 +53,8 @@ int main(int argc, char** argv, char** envp) { notify = true; } else if (ARGS[i] == "--verbose" || ARGS[i] == "-v") { verbose = true; + } else if (ARGS[i] == "--no-shallow" || ARGS[i] == "-s") { + noShallow = true; } else if (ARGS[i] == "--force" || ARGS[i] == "-f") { force = true; std::cout << Colors::RED << "!" << Colors::RESET << " Using --force, I hope you know what you are doing.\n"; @@ -69,8 +72,9 @@ int main(int argc, char** argv, char** envp) { return 0; } - g_pPluginManager = std::make_unique(); - g_pPluginManager->m_bVerbose = verbose; + g_pPluginManager = std::make_unique(); + g_pPluginManager->m_bVerbose = verbose; + g_pPluginManager->m_bNoShallow = noShallow; if (command[0] == "add") { if (command.size() < 2) { From 2566d818848b58b114071f199ffe944609376270 Mon Sep 17 00:00:00 2001 From: Vaxry Date: Sun, 16 Jun 2024 12:38:09 +0200 Subject: [PATCH 0022/2181] xwayland: fixup unfocus atom conditions ref #6468 --- src/xwayland/XSurface.cpp | 2 +- src/xwayland/XWM.cpp | 25 +++++++++++++++++-------- src/xwayland/XWM.hpp | 2 +- 3 files changed, 19 insertions(+), 10 deletions(-) diff --git a/src/xwayland/XSurface.cpp b/src/xwayland/XSurface.cpp index 07cac832..5d25e0e8 100644 --- a/src/xwayland/XSurface.cpp +++ b/src/xwayland/XSurface.cpp @@ -179,7 +179,7 @@ void CXWaylandSurface::configure(const CBox& box) { void CXWaylandSurface::activate(bool activate) { if (overrideRedirect && !activate) return; - g_pXWayland->pWM->activateSurface(self.lock()); + g_pXWayland->pWM->activateSurface(self.lock(), activate); } void CXWaylandSurface::setFullscreen(bool fs) { diff --git a/src/xwayland/XWM.cpp b/src/xwayland/XWM.cpp index 247af4b7..719adcb9 100644 --- a/src/xwayland/XWM.cpp +++ b/src/xwayland/XWM.cpp @@ -394,11 +394,16 @@ void CXWM::focusWindow(SP surf) { if (surf == focusedSurface) return; - auto oldSurf = focusedSurface.lock(); focusedSurface = surf; - if (oldSurf) - sendState(oldSurf); + // send state to all surfaces, sometimes we might lose some + // that could still stick with the focused atom + for (auto& s : mappedSurfaces) { + if (!s) + continue; + + sendState(s.lock()); + } if (!surf) { xcb_set_input_focus_checked(connection, XCB_INPUT_FOCUS_POINTER_ROOT, XCB_NONE, XCB_CURRENT_TIME); @@ -868,13 +873,17 @@ void CXWM::createWMWindow() { xcb_set_selection_owner(connection, wmWindow, HYPRATOMS["_NET_WM_CM_S0"], XCB_CURRENT_TIME); } -void CXWM::activateSurface(SP surf) { - if (surf == focusedSurface || (surf && surf->overrideRedirect)) +void CXWM::activateSurface(SP surf, bool activate) { + if ((surf == focusedSurface && activate) || (surf && surf->overrideRedirect)) return; - setActiveWindow(surf ? surf->xID : (uint32_t)XCB_WINDOW_NONE); - - focusWindow(surf); + if (!activate || !surf) { + setActiveWindow((uint32_t)XCB_WINDOW_NONE); + focusWindow(nullptr); + } else { + setActiveWindow(surf ? surf->xID : (uint32_t)XCB_WINDOW_NONE); + focusWindow(surf); + } xcb_flush(connection); } diff --git a/src/xwayland/XWM.hpp b/src/xwayland/XWM.hpp index 7f68454c..6456c71b 100644 --- a/src/xwayland/XWM.hpp +++ b/src/xwayland/XWM.hpp @@ -79,7 +79,7 @@ class CXWM { void setActiveWindow(xcb_window_t window); void sendState(SP surf); void focusWindow(SP surf); - void activateSurface(SP surf); + void activateSurface(SP surf, bool activate); bool isWMWindow(xcb_window_t w); void sendWMMessage(SP surf, xcb_client_message_data_t* data, uint32_t mask); From 3eaf35f1e2d984bea89ab1d8a5abbef66243aa5d Mon Sep 17 00:00:00 2001 From: memchr Date: Sun, 16 Jun 2024 13:44:13 +0000 Subject: [PATCH 0023/2181] hyprland.conf: update master section (#6537) --- example/hyprland.conf | 2 +- src/config/defaultConfig.hpp | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/example/hyprland.conf b/example/hyprland.conf index f0ee8b25..f69309c2 100644 --- a/example/hyprland.conf +++ b/example/hyprland.conf @@ -125,7 +125,7 @@ dwindle { # See https://wiki.hyprland.org/Configuring/Master-Layout/ for more master { - new_is_master = true + new_status = master } # https://wiki.hyprland.org/Configuring/Variables/#misc diff --git a/src/config/defaultConfig.hpp b/src/config/defaultConfig.hpp index dd7df126..98b617d0 100644 --- a/src/config/defaultConfig.hpp +++ b/src/config/defaultConfig.hpp @@ -138,7 +138,7 @@ dwindle { # See https://wiki.hyprland.org/Configuring/Master-Layout/ for more master { - new_is_master = true + new_status = master } # https://wiki.hyprland.org/Configuring/Variables/#misc From 1b5444494d26624804de8f479da3cffb5d480dc6 Mon Sep 17 00:00:00 2001 From: Vaxry Date: Sun, 16 Jun 2024 16:23:35 +0200 Subject: [PATCH 0024/2181] seat/dnd: unfocus pointer from surfaces on dnd start GTK is speshyal and requires this for functioning properly. Ugh. It's technically not required by spec, f you gtk. Ref #6509 --- src/managers/SeatManager.cpp | 5 +++++ src/protocols/core/DataDevice.cpp | 9 +++++++-- 2 files changed, 12 insertions(+), 2 deletions(-) diff --git a/src/managers/SeatManager.cpp b/src/managers/SeatManager.cpp index a58bca72..fc14f0fc 100644 --- a/src/managers/SeatManager.cpp +++ b/src/managers/SeatManager.cpp @@ -191,6 +191,11 @@ void CSeatManager::setPointerFocus(SP surf, const Vector2D& if (state.pointerFocus == surf) return; + if (PROTO::data->dndActive() && surf) { + Debug::log(LOG, "[seatmgr] Refusing pointer focus during an active dnd"); + return; + } + if (!mouse || !mouse->wlr()) { Debug::log(ERR, "BUG THIS: setPointerFocus without a valid mouse set"); return; diff --git a/src/protocols/core/DataDevice.cpp b/src/protocols/core/DataDevice.cpp index 86b372bf..03c51852 100644 --- a/src/protocols/core/DataDevice.cpp +++ b/src/protocols/core/DataDevice.cpp @@ -542,6 +542,11 @@ void CWLDataDeviceProtocol::initiateDrag(WP currentSource } }); + // unfocus the pointer from the surface, this is part of """standard""" wayland procedure and gtk will freak out if this isn't happening. + // BTW, the spec does NOT require this explicitly... + // Fuck you gtk. + g_pSeatManager->setPointerFocus(nullptr, {}); + // make a new offer, etc updateDrag(); } @@ -638,7 +643,7 @@ void CWLDataDeviceProtocol::completeDrag() { dnd.focusedDevice.reset(); dnd.currentSource.reset(); - g_pSeatManager->resendEnterEvents(); + g_pInputManager->simulateMouseMovement(); } void CWLDataDeviceProtocol::abortDrag() { @@ -657,7 +662,7 @@ void CWLDataDeviceProtocol::abortDrag() { dnd.focusedDevice.reset(); dnd.currentSource.reset(); - g_pSeatManager->resendEnterEvents(); + g_pInputManager->simulateMouseMovement(); } void CWLDataDeviceProtocol::renderDND(CMonitor* pMonitor, timespec* when) { From 43c75f17eb9ce89f90ef443a3ae740a1bdd55d31 Mon Sep 17 00:00:00 2001 From: memchr Date: Sun, 16 Jun 2024 14:42:32 +0000 Subject: [PATCH 0025/2181] input: add cursor:warp_on_changeworkspace (#6480) * input: add cursor:warp_on_changeworkspace If enabled, warp the cursor to the last focused window on the workspace in the `changeworkspace' dispatcher, except if the cursor is currently on the WLR top layer. Respect persistent warps. * warp_on_change_workspace: check if focused layer is a window. --- src/config/ConfigManager.cpp | 1 + src/managers/KeybindManager.cpp | 13 +++++++++++++ 2 files changed, 14 insertions(+) diff --git a/src/config/ConfigManager.cpp b/src/config/ConfigManager.cpp index 1b069f5d..56fdae25 100644 --- a/src/config/ConfigManager.cpp +++ b/src/config/ConfigManager.cpp @@ -529,6 +529,7 @@ CConfigManager::CConfigManager() { m_pConfig->addConfigValue("cursor:inactive_timeout", Hyprlang::INT{0}); m_pConfig->addConfigValue("cursor:no_warps", Hyprlang::INT{0}); m_pConfig->addConfigValue("cursor:persistent_warps", Hyprlang::INT{0}); + m_pConfig->addConfigValue("cursor:warp_on_change_workspace", Hyprlang::INT{0}); m_pConfig->addConfigValue("cursor:default_monitor", {STRVAL_EMPTY}); m_pConfig->addConfigValue("cursor:zoom_factor", {1.f}); m_pConfig->addConfigValue("cursor:zoom_rigid", Hyprlang::INT{0}); diff --git a/src/managers/KeybindManager.cpp b/src/managers/KeybindManager.cpp index eb07850c..14fadf02 100644 --- a/src/managers/KeybindManager.cpp +++ b/src/managers/KeybindManager.cpp @@ -1,6 +1,7 @@ #include "../config/ConfigValue.hpp" #include "../devices/IKeyboard.hpp" #include "../managers/SeatManager.hpp" +#include "../protocols/LayerShell.hpp" #include "../protocols/ShortcutsInhibit.hpp" #include "../render/decorations/CHyprGroupBarDecoration.hpp" #include "KeybindManager.hpp" @@ -1087,6 +1088,8 @@ void CKeybindManager::changeworkspace(std::string args) { if (!PMONITORWORKSPACEOWNER) return; + updateRelativeCursorCoords(); + g_pCompositor->setActiveMonitor(PMONITORWORKSPACEOWNER); if (BISWORKSPACECURRENT) { @@ -1115,6 +1118,16 @@ void CKeybindManager::changeworkspace(std::string args) { else g_pInputManager->simulateMouseMovement(); } + + const static auto PWARPONWORKSPACECHANGE = CConfigValue("cursor:warp_on_change_workspace"); + + if (*PWARPONWORKSPACECHANGE) { + auto PLAST = pWorkspaceToChangeTo->getLastFocusedWindow(); + auto HLSurface = CWLSurface::fromResource(g_pSeatManager->state.pointerFocus.lock()); + + if (PLAST && (!HLSurface || HLSurface->getWindow())) + PLAST->warpCursor(); + } } void CKeybindManager::fullscreenActive(std::string args) { From 648ac8a00b0d68a9e3a86e928b30a490870dbed6 Mon Sep 17 00:00:00 2001 From: Vaxry Date: Sun, 16 Jun 2024 16:46:15 +0200 Subject: [PATCH 0026/2181] xdg-shell: properly check for resource version for TILED and SUSPENDED states fixes #6535 --- src/protocols/XDGShell.cpp | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/src/protocols/XDGShell.cpp b/src/protocols/XDGShell.cpp index 49b7b417..dddc3bca 100644 --- a/src/protocols/XDGShell.cpp +++ b/src/protocols/XDGShell.cpp @@ -136,10 +136,12 @@ CXDGToplevelResource::CXDGToplevelResource(SP resource_, SPversion() >= 2) { + pendingApply.states.push_back(XDG_TOPLEVEL_STATE_TILED_LEFT); + pendingApply.states.push_back(XDG_TOPLEVEL_STATE_TILED_RIGHT); + pendingApply.states.push_back(XDG_TOPLEVEL_STATE_TILED_TOP); + pendingApply.states.push_back(XDG_TOPLEVEL_STATE_TILED_BOTTOM); + } resource->setSetTitle([this](CXdgToplevel* r, const char* t) { state.title = t; @@ -261,6 +263,9 @@ uint32_t CXDGToplevelResource::setActive(bool active) { } uint32_t CXDGToplevelResource::setSuspeneded(bool sus) { + if (resource->version() < 6) + return owner->scheduleConfigure(); // SUSPENDED is since 6 + bool set = std::find(pendingApply.states.begin(), pendingApply.states.end(), XDG_TOPLEVEL_STATE_SUSPENDED) != pendingApply.states.end(); if (sus == set) From d0a6fa7aa6c3a9d94611130a9213de19a8754d67 Mon Sep 17 00:00:00 2001 From: Vaxry Date: Sun, 16 Jun 2024 17:04:10 +0200 Subject: [PATCH 0027/2181] wl_seat: accomodate for apps late-binding seat resources Sends enter events when an app binds wl_keyboard or wl_pointer later than it should. Fixes some buggy apps. Fixes #6131 --- src/protocols/core/Seat.cpp | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/protocols/core/Seat.cpp b/src/protocols/core/Seat.cpp index 8f9174f5..be05955c 100644 --- a/src/protocols/core/Seat.cpp +++ b/src/protocols/core/Seat.cpp @@ -98,6 +98,9 @@ CWLPointerResource::CWLPointerResource(SP resource_, SPonSetCursor(owner.lock(), serial, surf ? CWLSurfaceResource::fromResource(surf) : nullptr, {hotX, hotY}); }); + + if (g_pSeatManager->state.pointerFocus && g_pSeatManager->state.pointerFocus->client() == resource->client()) + sendEnter(g_pSeatManager->state.pointerFocus.lock(), {-1, -1} /* Coords don't really matter that much, they will be updated next move */); } bool CWLPointerResource::good() { @@ -207,6 +210,9 @@ CWLKeyboardResource::CWLKeyboardResource(SP resource_, SPkeyboard.lock()); repeatInfo(g_pSeatManager->keyboard->repeatRate, g_pSeatManager->keyboard->repeatDelay); + + if (g_pSeatManager->state.keyboardFocus && g_pSeatManager->state.keyboardFocus->client() == resource->client()) + sendEnter(g_pSeatManager->state.keyboardFocus.lock()); } bool CWLKeyboardResource::good() { From 2031af82fa029aa098357339d502b53c371919d4 Mon Sep 17 00:00:00 2001 From: Vaxry Date: Sun, 16 Jun 2024 17:41:16 +0200 Subject: [PATCH 0028/2181] wl_data_device: send drop_performed in completeDrag ref #6509 --- src/protocols/core/DataDevice.cpp | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/src/protocols/core/DataDevice.cpp b/src/protocols/core/DataDevice.cpp index 03c51852..e54d3633 100644 --- a/src/protocols/core/DataDevice.cpp +++ b/src/protocols/core/DataDevice.cpp @@ -606,15 +606,15 @@ void CWLDataDeviceProtocol::dropDrag() { return; } - dnd.currentSource->sendDndDropPerformed(); dnd.focusedDevice->sendDrop(); - dnd.focusedDevice->sendLeave(); resetDndState(); if (dnd.overriddenCursor) g_pInputManager->unsetCursorImage(); dnd.overriddenCursor = false; + + g_pInputManager->simulateMouseMovement(); } bool CWLDataDeviceProtocol::wasDragSuccessful() { @@ -638,6 +638,7 @@ void CWLDataDeviceProtocol::completeDrag() { if (!dnd.focusedDevice || !dnd.currentSource) return; + dnd.currentSource->sendDndDropPerformed(); dnd.currentSource->sendDndFinished(); dnd.focusedDevice.reset(); @@ -681,5 +682,5 @@ void CWLDataDeviceProtocol::renderDND(CMonitor* pMonitor, timespec* when) { } bool CWLDataDeviceProtocol::dndActive() { - return dnd.currentSource; + return dnd.currentSource && dnd.mouseButton /* test a member of the state to ensure it's also present */; } From 069a21a34ef062bb278cf70f153cfdd0bfec9df2 Mon Sep 17 00:00:00 2001 From: Vaxry Date: Sun, 16 Jun 2024 19:52:07 +0200 Subject: [PATCH 0029/2181] xwayland: force default plain mime atoms on known types ref #6247 --- src/xwayland/XDataSource.cpp | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/src/xwayland/XDataSource.cpp b/src/xwayland/XDataSource.cpp index 98e0701b..f4059ee1 100644 --- a/src/xwayland/XDataSource.cpp +++ b/src/xwayland/XDataSource.cpp @@ -49,10 +49,16 @@ std::vector CXDataSource::mimes() { void CXDataSource::send(const std::string& mime, uint32_t fd) { xcb_atom_t mimeAtom = 0; - for (size_t i = 0; i < mimeTypes.size(); ++i) { - if (mimeTypes.at(i) == mime) { - mimeAtom = mimeAtoms.at(i); - break; + if (mime == "text/plain") + mimeAtom = HYPRATOMS["TEXT"]; + else if (mime == "text/plain;charset=utf-8") + mimeAtom = HYPRATOMS["UTF8_STRING"]; + else { + for (size_t i = 0; i < mimeTypes.size(); ++i) { + if (mimeTypes.at(i) == mime) { + mimeAtom = mimeAtoms.at(i); + break; + } } } From 738530e62ee48f7326cd5a610b90b47344b701f1 Mon Sep 17 00:00:00 2001 From: Dashie Date: Sun, 16 Jun 2024 20:01:08 +0200 Subject: [PATCH 0030/2181] xdg-shell: Continue transform of popup until size fits (#6521) --- src/protocols/XDGShell.cpp | 47 ++++++++++++++++++++------------------ 1 file changed, 25 insertions(+), 22 deletions(-) diff --git a/src/protocols/XDGShell.cpp b/src/protocols/XDGShell.cpp index dddc3bca..c16ebb9d 100644 --- a/src/protocols/XDGShell.cpp +++ b/src/protocols/XDGShell.cpp @@ -539,30 +539,33 @@ CBox CXDGPositionerRules::getPosition(const CBox& constraint, const Vector2D& pa if (success) return predictedBox.translate(-parentCoord - constraint.pos()); + CBox test = predictedBox; + if (state.constraintAdjustment & (XDG_POSITIONER_CONSTRAINT_ADJUSTMENT_FLIP_X | XDG_POSITIONER_CONSTRAINT_ADJUSTMENT_FLIP_Y)) { // attempt to flip - const bool flipX = state.constraintAdjustment & XDG_POSITIONER_CONSTRAINT_ADJUSTMENT_FLIP_X; - const bool flipY = state.constraintAdjustment & XDG_POSITIONER_CONSTRAINT_ADJUSTMENT_FLIP_Y; + const bool flipX = state.constraintAdjustment & XDG_POSITIONER_CONSTRAINT_ADJUSTMENT_FLIP_X; + const bool flipY = state.constraintAdjustment & XDG_POSITIONER_CONSTRAINT_ADJUSTMENT_FLIP_Y; + auto countEdges = [constraint](const CBox& test) -> int { + int edgeCount = 0; + edgeCount += test.x < constraint.x ? 1 : 0; + edgeCount += test.x + test.w > constraint.x + constraint.w ? 1 : 0; + edgeCount += test.y < constraint.y ? 1 : 0; + edgeCount += test.y + test.h > constraint.y + constraint.h ? 1 : 0; + return edgeCount; + }; + int edgeCount = countEdges(test); - CBox test = predictedBox; - success = true; - if (flipX && test.copy().translate(Vector2D{-predictedBox.w - state.anchorRect.w, 0}).expand(-1).inside(constraint)) + if (flipX && edgeCount > countEdges(test.copy().translate(Vector2D{-predictedBox.w - state.anchorRect.w, 0}))) test.translate(Vector2D{-predictedBox.w - state.anchorRect.w, 0}); - else if (flipY && test.copy().translate(Vector2D{0, -predictedBox.h - state.anchorRect.h}).expand(-1).inside(constraint)) + if (flipY && edgeCount > countEdges(test.copy().translate(Vector2D{0, -predictedBox.h - state.anchorRect.h}))) test.translate(Vector2D{0, -predictedBox.h - state.anchorRect.h}); - else if (flipX && flipY && test.copy().translate(Vector2D{-predictedBox.w - state.anchorRect.w, -predictedBox.h - state.anchorRect.h}).expand(-1).inside(constraint)) - test.translate(Vector2D{-predictedBox.w - state.anchorRect.w, -predictedBox.h - state.anchorRect.h}); - else - success = false; + + success = test.copy().expand(-1).inside(constraint); if (success) return test.translate(-parentCoord - constraint.pos()); } - // if flips fail, we will slide and remember. - // if the positioner is allowed to resize, then resize the slid thing. - CBox test = predictedBox; - // for slide and resize, defines the padding around the edge for the positioned // surface. constexpr int EDGE_PADDING = 4; @@ -575,10 +578,10 @@ CBox CXDGPositionerRules::getPosition(const CBox& constraint, const Vector2D& pa //const bool gravityLeft = state.gravity == XDG_POSITIONER_GRAVITY_NONE || state.gravity == XDG_POSITIONER_GRAVITY_LEFT || state.gravity == XDG_POSITIONER_GRAVITY_TOP_LEFT || state.gravity == XDG_POSITIONER_GRAVITY_BOTTOM_LEFT; //const bool gravityTop = state.gravity == XDG_POSITIONER_GRAVITY_NONE || state.gravity == XDG_POSITIONER_GRAVITY_TOP || state.gravity == XDG_POSITIONER_GRAVITY_TOP_LEFT || state.gravity == XDG_POSITIONER_GRAVITY_TOP_RIGHT; - const bool leftEdgeOut = predictedBox.x < constraint.x; - const bool topEdgeOut = predictedBox.y < constraint.y; - const bool rightEdgeOut = predictedBox.x + predictedBox.w > constraint.x + constraint.w; - const bool bottomEdgeOut = predictedBox.y + predictedBox.h > constraint.y + constraint.h; + const bool leftEdgeOut = test.x < constraint.x; + const bool topEdgeOut = test.y < constraint.y; + const bool rightEdgeOut = test.x + test.w > constraint.x + constraint.w; + const bool bottomEdgeOut = test.y + test.h > constraint.y + constraint.h; // TODO: this isn't truly conformant. if (leftEdgeOut && slideX) @@ -600,10 +603,10 @@ CBox CXDGPositionerRules::getPosition(const CBox& constraint, const Vector2D& pa const bool resizeX = state.constraintAdjustment & XDG_POSITIONER_CONSTRAINT_ADJUSTMENT_RESIZE_X; const bool resizeY = state.constraintAdjustment & XDG_POSITIONER_CONSTRAINT_ADJUSTMENT_RESIZE_Y; - const bool leftEdgeOut = predictedBox.x < constraint.x; - const bool topEdgeOut = predictedBox.y < constraint.y; - const bool rightEdgeOut = predictedBox.x + predictedBox.w > constraint.x + constraint.w; - const bool bottomEdgeOut = predictedBox.y + predictedBox.h > constraint.y + constraint.h; + const bool leftEdgeOut = test.x < constraint.x; + const bool topEdgeOut = test.y < constraint.y; + const bool rightEdgeOut = test.x + test.w > constraint.x + constraint.w; + const bool bottomEdgeOut = test.y + test.h > constraint.y + constraint.h; // TODO: this isn't truly conformant. if (leftEdgeOut && resizeX) { From 172ee1cadaabd3ba4df330f9cdd02fb520b59e71 Mon Sep 17 00:00:00 2001 From: Vaxry Date: Sun, 16 Jun 2024 20:36:55 +0200 Subject: [PATCH 0031/2181] data-device: minor fixups ref #6543 firefox needs a re-enter after a dnd don't destroy dnd on an offer destroy, it's not valid --- src/protocols/core/DataDevice.cpp | 23 +++++++---------------- 1 file changed, 7 insertions(+), 16 deletions(-) diff --git a/src/protocols/core/DataDevice.cpp b/src/protocols/core/DataDevice.cpp index e54d3633..986d1176 100644 --- a/src/protocols/core/DataDevice.cpp +++ b/src/protocols/core/DataDevice.cpp @@ -12,20 +12,8 @@ CWLDataOfferResource::CWLDataOfferResource(SP resource_, SPsetDestroy([this](CWlDataOffer* r) { - if (!dead && (recvd || accepted)) - PROTO::data->completeDrag(); - else - PROTO::data->abortDrag(); - PROTO::data->destroyResource(this); - }); - resource->setOnDestroy([this](CWlDataOffer* r) { - if (!dead && (recvd || accepted)) - PROTO::data->completeDrag(); - else - PROTO::data->abortDrag(); - PROTO::data->destroyResource(this); - }); + resource->setDestroy([this](CWlDataOffer* r) { PROTO::data->destroyResource(this); }); + resource->setOnDestroy([this](CWlDataOffer* r) { PROTO::data->destroyResource(this); }); resource->setAccept([this](CWlDataOffer* r, uint32_t serial, const char* mime) { if (!source) { @@ -210,7 +198,7 @@ CWLDataDeviceResource::CWLDataDeviceResource(SP resource_) : reso pClient = resource->client(); - resource->setSetSelection([this](CWlDataDevice* r, wl_resource* sourceR, uint32_t serial) { + resource->setSetSelection([](CWlDataDevice* r, wl_resource* sourceR, uint32_t serial) { auto source = sourceR ? CWLDataSourceResource::fromResource(sourceR) : CSharedPointer{}; if (!source) { LOGM(LOG, "Reset selection received"); @@ -226,7 +214,7 @@ CWLDataDeviceResource::CWLDataDeviceResource(SP resource_) : reso g_pSeatManager->setCurrentSelection(source); }); - resource->setStartDrag([this](CWlDataDevice* r, wl_resource* sourceR, wl_resource* origin, wl_resource* icon, uint32_t serial) { + resource->setStartDrag([](CWlDataDevice* r, wl_resource* sourceR, wl_resource* origin, wl_resource* icon, uint32_t serial) { auto source = CWLDataSourceResource::fromResource(sourceR); if (!source) { LOGM(ERR, "No source in drag"); @@ -615,6 +603,7 @@ void CWLDataDeviceProtocol::dropDrag() { dnd.overriddenCursor = false; g_pInputManager->simulateMouseMovement(); + g_pSeatManager->resendEnterEvents(); } bool CWLDataDeviceProtocol::wasDragSuccessful() { @@ -645,6 +634,7 @@ void CWLDataDeviceProtocol::completeDrag() { dnd.currentSource.reset(); g_pInputManager->simulateMouseMovement(); + g_pSeatManager->resendEnterEvents(); } void CWLDataDeviceProtocol::abortDrag() { @@ -664,6 +654,7 @@ void CWLDataDeviceProtocol::abortDrag() { dnd.currentSource.reset(); g_pInputManager->simulateMouseMovement(); + g_pSeatManager->resendEnterEvents(); } void CWLDataDeviceProtocol::renderDND(CMonitor* pMonitor, timespec* when) { From d5ef10abf429355246abcda65fe4c15d886fad7c Mon Sep 17 00:00:00 2001 From: Vaxry Date: Sun, 16 Jun 2024 20:56:50 +0200 Subject: [PATCH 0032/2181] data-device: properly abort drag on missing device sometimes there is no focused device (e.g. when dnd'ing on nothing or xwayland) in which case abort would fail to send cancelled to the source. ref #6543 --- src/protocols/core/DataDevice.cpp | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/src/protocols/core/DataDevice.cpp b/src/protocols/core/DataDevice.cpp index 986d1176..2d50ff15 100644 --- a/src/protocols/core/DataDevice.cpp +++ b/src/protocols/core/DataDevice.cpp @@ -644,11 +644,13 @@ void CWLDataDeviceProtocol::abortDrag() { g_pInputManager->unsetCursorImage(); dnd.overriddenCursor = false; - if (!dnd.focusedDevice || !dnd.currentSource) + if (!dnd.focusedDevice && !dnd.currentSource) return; - dnd.focusedDevice->sendLeave(); - dnd.currentSource->cancelled(); + if (dnd.focusedDevice) + dnd.focusedDevice->sendLeave(); + if (dnd.currentSource) + dnd.currentSource->cancelled(); dnd.focusedDevice.reset(); dnd.currentSource.reset(); From b15be9c77de593581007de53b2bbca97d121900a Mon Sep 17 00:00:00 2001 From: Vaxry Date: Sun, 16 Jun 2024 21:34:17 +0200 Subject: [PATCH 0033/2181] xwayland: do not set a new data source if it has no MIMEs ref #6247 --- src/xwayland/XWM.cpp | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/src/xwayland/XWM.cpp b/src/xwayland/XWM.cpp index 719adcb9..7b57de0f 100644 --- a/src/xwayland/XWM.cpp +++ b/src/xwayland/XWM.cpp @@ -1034,16 +1034,16 @@ void CXWM::initSelection() { } void CXWM::setClipboardToWayland(SXSelection& sel) { - sel.dataSource = makeShared(sel); - if (sel.dataSource->mimes().empty()) { + auto source = makeShared(sel); + if (source->mimes().empty()) { Debug::log(ERR, "[xwm] can't set clipboard: no MIMEs"); - sel.dataSource.reset(); + return; } - if (sel.dataSource) { - Debug::log(LOG, "[xwm] X clipboard at {:x} takes clipboard", (uintptr_t)sel.dataSource.get()); - g_pSeatManager->setCurrentSelection(sel.dataSource); - } + sel.dataSource = source; + + Debug::log(LOG, "[xwm] X clipboard at {:x} takes clipboard", (uintptr_t)sel.dataSource.get()); + g_pSeatManager->setCurrentSelection(sel.dataSource); } void CXWM::getTransferData(SXSelection& sel) { From 9cb3bf1cac1a38fbac3942a60415d7050ffcd2cb Mon Sep 17 00:00:00 2001 From: Mihai Fufezan Date: Mon, 17 Jun 2024 13:03:59 +0300 Subject: [PATCH 0034/2181] Nix: tidy up derivation --- nix/default.nix | 55 ++++++++++++++++++++++++++++--------------------- 1 file changed, 32 insertions(+), 23 deletions(-) diff --git a/nix/default.nix b/nix/default.nix index 0493abc1..6b5068bc 100644 --- a/nix/default.nix +++ b/nix/default.nix @@ -11,6 +11,7 @@ expat, fribidi, git, + hwdata, hyprcursor, hyprlang, hyprutils, @@ -18,26 +19,28 @@ jq, libGL, libdatrie, + libdisplay-info, libdrm, libexecinfo, libinput, + libliftoff, libselinux, libsepol, libthai, libuuid, libxkbcommon, mesa, + meson, pango, pciutils, pcre2, python3, + seatd, systemd, tomlplusplus, - udis86, wayland, wayland-protocols, wayland-scanner, - wlroots, xorg, xwayland, debug ? false, @@ -76,23 +79,21 @@ assert lib.assertMsg (!hidpiXWayland) "The option `hidpiXWayland` has been remov sed -i "s#@PREFIX@/##g" hyprland.pc.in ''; + COMMITS = commit; DATE = date; + DIRTY = lib.optionalString (commit == "") "dirty"; HASH = commit; - DIRTY = if commit == "" then "dirty" else ""; - nativeBuildInputs = lib.concatLists [ - [ - hyprwayland-scanner - jq - makeWrapper - cmake - ninja - pkg-config - python3 - wayland-scanner - ] - # introduce this later so that cmake takes precedence - wlroots.nativeBuildInputs + nativeBuildInputs = [ + hyprwayland-scanner + jq + makeWrapper + cmake + meson # for wlroots + ninja + pkg-config + python3 # for udis86 + wayland-scanner ]; outputs = [ @@ -102,14 +103,13 @@ assert lib.assertMsg (!hidpiXWayland) "The option `hidpiXWayland` has been remov ]; buildInputs = lib.concatLists [ - wlroots.buildInputs - udis86.buildInputs [ cairo expat fribidi git - hyprcursor.dev + hwdata + hyprcursor hyprlang hyprutils libGL @@ -128,12 +128,18 @@ assert lib.assertMsg (!hidpiXWayland) "The option `hidpiXWayland` has been remov tomlplusplus wayland wayland-protocols + # for wlroots + seatd + libdisplay-info + libliftoff ] (lib.optionals stdenv.hostPlatform.isMusl [libexecinfo]) (lib.optionals enableXWayland [ xorg.libxcb xorg.libXdmcp xorg.xcbutil + xorg.xcbutilerrors + xorg.xcbutilrenderutil xorg.xcbutilwm xwayland ]) @@ -145,6 +151,9 @@ assert lib.assertMsg (!hidpiXWayland) "The option `hidpiXWayland` has been remov then "Debug" else "RelWithDebInfo"; + # we want as much debug info as possible + dontStrip = true; + cmakeFlags = [ (lib.cmakeBool "NO_XWAYLAND" (!enableXWayland)) (lib.cmakeBool "LEGACY_RENDERER" legacyRenderer) @@ -164,11 +173,11 @@ assert lib.assertMsg (!hidpiXWayland) "The option `hidpiXWayland` has been remov passthru.providedSessions = ["hyprland"]; - meta = with lib; { + meta = { homepage = "https://github.com/hyprwm/Hyprland"; - description = "A dynamic tiling Wayland compositor that doesn't sacrifice on its looks"; - license = licenses.bsd3; - platforms = wlroots.meta.platforms; + description = "Dynamic tiling Wayland compositor that doesn't sacrifice on its looks"; + license = lib.licenses.bsd3; + platforms = lib.platforms.linux; mainProgram = "Hyprland"; }; } From 14ab0ecc5eb3c437dd62f92629fc29e33679043b Mon Sep 17 00:00:00 2001 From: Mihai Fufezan Date: Mon, 17 Jun 2024 13:14:26 +0300 Subject: [PATCH 0035/2181] Nix: don't strip in debug builds Strip in Release builds, as the non-stripped binary is almost 500MB. --- nix/default.nix | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/nix/default.nix b/nix/default.nix index 6b5068bc..a2302688 100644 --- a/nix/default.nix +++ b/nix/default.nix @@ -152,7 +152,7 @@ assert lib.assertMsg (!hidpiXWayland) "The option `hidpiXWayland` has been remov else "RelWithDebInfo"; # we want as much debug info as possible - dontStrip = true; + dontStrip = debug; cmakeFlags = [ (lib.cmakeBool "NO_XWAYLAND" (!enableXWayland)) From 1360677478e867034713e5d43d7a8a8f6bf1343d Mon Sep 17 00:00:00 2001 From: Vaxry Date: Mon, 17 Jun 2024 12:42:32 +0200 Subject: [PATCH 0036/2181] subcompositor/renderer: fixup handling of subsurfaces below the main one some apps (notably vlc 4) place a subsurface below the main surface (which is kinda cursed) but we have to accomodate for that --- src/helpers/WLClasses.hpp | 3 ++ src/protocols/core/Compositor.cpp | 25 ++++++++++++--- src/protocols/core/Subcompositor.cpp | 48 ++++++++++++++++++++++------ src/protocols/core/Subcompositor.hpp | 2 ++ src/render/Renderer.cpp | 12 ++++++- 5 files changed, 75 insertions(+), 15 deletions(-) diff --git a/src/helpers/WLClasses.hpp b/src/helpers/WLClasses.hpp index 247aa8f0..bcd6bf10 100644 --- a/src/helpers/WLClasses.hpp +++ b/src/helpers/WLClasses.hpp @@ -51,6 +51,9 @@ struct SRenderData { PHLWINDOW pWindow; bool popup = false; + + // counts how many surfaces this pass has rendered + int surfaceCounter = 0; }; struct SSwipeGesture { diff --git a/src/protocols/core/Compositor.cpp b/src/protocols/core/Compositor.cpp index db6e3258..165da6ee 100644 --- a/src/protocols/core/Compositor.cpp +++ b/src/protocols/core/Compositor.cpp @@ -277,8 +277,26 @@ void CWLSurfaceResource::resetRole() { } void CWLSurfaceResource::bfHelper(std::vector> nodes, std::function, const Vector2D&, void*)> fn, void* data) { - for (auto& n : nodes) { + std::vector> nodes2; + + // first, gather all nodes below + for (auto& n : nodes) { + std::erase_if(n->subsurfaces, [](const auto& e) { return e.expired(); }); + // subsurfaces is sorted lowest -> highest + for (auto& c : n->subsurfaces) { + if (c->zIndex >= 0) + break; + nodes2.push_back(c->surface.lock()); + } + } + + if (!nodes2.empty()) + bfHelper(nodes2, fn, data); + + nodes2.clear(); + + for (auto& n : nodes) { Vector2D offset = {}; if (n->role->role() == SURFACE_ROLE_SUBSURFACE) { auto subsurface = (CWLSubsurfaceResource*)n->role.get(); @@ -288,11 +306,10 @@ void CWLSurfaceResource::bfHelper(std::vector> nodes, std fn(n, offset, data); } - std::vector> nodes2; - for (auto& n : nodes) { - std::erase_if(n->subsurfaces, [](const auto& e) { return e.expired(); }); for (auto& c : n->subsurfaces) { + if (c->zIndex < 0) + continue; nodes2.push_back(c->surface.lock()); } } diff --git a/src/protocols/core/Subcompositor.cpp b/src/protocols/core/Subcompositor.cpp index d407636c..cbc4063a 100644 --- a/src/protocols/core/Subcompositor.cpp +++ b/src/protocols/core/Subcompositor.cpp @@ -23,15 +23,29 @@ CWLSubsurfaceResource::CWLSubsurfaceResource(SP resource_, SPsubsurfaces, self.lock()); + auto pushAboveIndex = [this](int idx) -> void { + for (auto& c : parent->subsurfaces) { + if (c->zIndex >= idx) + c->zIndex++; + } + }; + + std::erase_if(parent->subsurfaces, [this](const auto& e) { return e == self || !e; }); auto it = std::find(parent->subsurfaces.begin(), parent->subsurfaces.end(), SURF); if (it == parent->subsurfaces.end()) { - LOGM(ERR, "Invalid surface reference in placeAbove"); - parent->subsurfaces.emplace_back(self.lock()); - } else - parent->subsurfaces.insert(it, self.lock()); + LOGM(ERR, "Invalid surface reference in placeAbove, likely parent"); + pushAboveIndex(1); + parent->subsurfaces.emplace_back(self); + zIndex = 1; + } else { + pushAboveIndex((*it)->zIndex); + zIndex = (*it)->zIndex; + parent->subsurfaces.emplace_back(self); + } + + std::sort(parent->subsurfaces.begin(), parent->subsurfaces.end(), [](const auto& a, const auto& b) { return a->zIndex < b->zIndex; }); }); resource->setPlaceBelow([this](CWlSubsurface* r, wl_resource* surf) { @@ -40,15 +54,29 @@ CWLSubsurfaceResource::CWLSubsurfaceResource(SP resource_, SPsubsurfaces, self.lock()); + auto pushBelowIndex = [this](int idx) -> void { + for (auto& c : parent->subsurfaces) { + if (c->zIndex <= idx) + c->zIndex--; + } + }; + + std::erase_if(parent->subsurfaces, [this](const auto& e) { return e == self || !e; }); auto it = std::find(parent->subsurfaces.begin(), parent->subsurfaces.end(), SURF); if (it == parent->subsurfaces.end()) { - LOGM(ERR, "Invalid surface reference in placeBelow"); - parent->subsurfaces.emplace_back(self.lock()); - } else - parent->subsurfaces.insert(it--, self.lock()); + LOGM(ERR, "Invalid surface reference in placeBelow, likely parent"); + pushBelowIndex(-1); + parent->subsurfaces.emplace_back(self); + zIndex = -1; + } else { + pushBelowIndex((*it)->zIndex); + zIndex = (*it)->zIndex; + parent->subsurfaces.emplace_back(self); + } + + std::sort(parent->subsurfaces.begin(), parent->subsurfaces.end(), [](const auto& a, const auto& b) { return a->zIndex < b->zIndex; }); }); listeners.commitSurface = surface->events.commit.registerListener([this](std::any d) { diff --git a/src/protocols/core/Subcompositor.hpp b/src/protocols/core/Subcompositor.hpp index abcfbf6d..824f0ffc 100644 --- a/src/protocols/core/Subcompositor.hpp +++ b/src/protocols/core/Subcompositor.hpp @@ -35,6 +35,8 @@ class CWLSubsurfaceResource : public ISurfaceRole { WP self; + int zIndex = 1; // by default, it's above + struct { CSignal destroy; } events; diff --git a/src/render/Renderer.cpp b/src/render/Renderer.cpp index 19b646a4..f56fb5d6 100644 --- a/src/render/Renderer.cpp +++ b/src/render/Renderer.cpp @@ -209,7 +209,10 @@ static void renderSurface(SP surface, int x, int y, void* da else g_pHyprOpenGL->blend(true); - if (RDATA->surface && surface == RDATA->surface) { + // FIXME: This is wrong and will bug the blur out as shit if the first surface + // is a subsurface that does NOT cover the entire frame. In such cases, we probably should fall back + // to what we do for misaligned surfaces (blur the entire thing and then render shit without blur) + if (RDATA->surfaceCounter == 0) { if (RDATA->blur) g_pHyprOpenGL->renderTextureWithBlur(TEXTURE, &windowBox, ALPHA, surface, rounding, RDATA->blockBlurOptimization, RDATA->fadeAlpha); else @@ -235,6 +238,9 @@ static void renderSurface(SP surface, int x, int y, void* da g_pHyprOpenGL->m_RenderData.primarySurfaceUVTopLeft = Vector2D(-1, -1); g_pHyprOpenGL->m_RenderData.primarySurfaceUVBottomRight = Vector2D(-1, -1); g_pHyprOpenGL->m_RenderData.useNearestNeighbor = NEARESTNEIGHBORSET; + + // up the counter so that we dont blur any surfaces above this one + RDATA->surfaceCounter++; } bool CHyprRenderer::shouldRenderWindow(PHLWINDOW pWindow, CMonitor* pMonitor) { @@ -602,6 +608,7 @@ void CHyprRenderer::renderWindow(PHLWINDOW pWindow, CMonitor* pMonitor, timespec renderdata.blur = false; } + renderdata.surfaceCounter = 0; pWindow->m_pWLSurface->resource()->breadthfirst([](SP s, const Vector2D& offset, void* data) { renderSurface(s, offset.x, offset.y, data); }, &renderdata); @@ -658,6 +665,8 @@ void CHyprRenderer::renderWindow(PHLWINDOW pWindow, CMonitor* pMonitor, timespec if (pWindow->m_sAdditionalConfigData.nearestNeighbor.toUnderlying()) g_pHyprOpenGL->m_RenderData.useNearestNeighbor = true; + renderdata.surfaceCounter = 0; + pWindow->m_pPopupHead->breadthfirst( [](CPopup* popup, void* data) { if (!popup->m_pWLSurface || !popup->m_pWLSurface->resource()) @@ -743,6 +752,7 @@ void CHyprRenderer::renderLayer(PHLLS pLayer, CMonitor* pMonitor, timespec* time renderdata.dontRound = true; renderdata.popup = true; renderdata.blur = pLayer->forceBlurPopups; + renderdata.surfaceCounter = 0; if (popups) { pLayer->popupHead->breadthfirst( [](CPopup* popup, void* data) { From 785d0628876a4782759b13c25fa644c12f340356 Mon Sep 17 00:00:00 2001 From: Vaxry Date: Mon, 17 Jun 2024 16:07:32 +0200 Subject: [PATCH 0037/2181] seat: track pressed pointer buttons releases them on leave, unless there is a dnd going on --- src/protocols/core/Seat.cpp | 26 ++++++++++++++++++++++++++ src/protocols/core/Seat.hpp | 2 ++ 2 files changed, 28 insertions(+) diff --git a/src/protocols/core/Seat.cpp b/src/protocols/core/Seat.cpp index be05955c..f578292a 100644 --- a/src/protocols/core/Seat.cpp +++ b/src/protocols/core/Seat.cpp @@ -1,5 +1,6 @@ #include "Seat.hpp" #include "Compositor.hpp" +#include "DataDevice.hpp" #include "../../devices/IKeyboard.hpp" #include "../../managers/SeatManager.hpp" #include "../../config/ConfigValue.hpp" @@ -128,6 +129,18 @@ void CWLPointerResource::sendLeave() { if (!owner || !currentSurface) return; + // release all buttons unless we have a dnd going on in which case + // the events shall be lost. + if (!PROTO::data->dndActive()) { + timespec now; + clock_gettime(CLOCK_MONOTONIC, &now); + for (auto& b : pressedButtons) { + sendButton(now.tv_sec * 1000 + now.tv_nsec / 1000000, b, WL_POINTER_BUTTON_STATE_RELEASED); + } + } + + pressedButtons.clear(); + resource->sendLeave(g_pSeatManager->nextSerial(owner.lock()), currentSurface->getResource().get()); currentSurface.reset(); listeners.destroySurface.reset(); @@ -144,6 +157,19 @@ void CWLPointerResource::sendButton(uint32_t timeMs, uint32_t button, wl_pointer if (!owner || !currentSurface) return; + if (state == WL_POINTER_BUTTON_STATE_RELEASED && std::find(pressedButtons.begin(), pressedButtons.end(), button) == pressedButtons.end()) { + LOGM(ERR, "sendButton release on a non-pressed button"); + return; + } else if (state == WL_POINTER_BUTTON_STATE_PRESSED && std::find(pressedButtons.begin(), pressedButtons.end(), button) != pressedButtons.end()) { + LOGM(ERR, "sendButton press on a non-pressed button"); + return; + } + + if (state == WL_POINTER_BUTTON_STATE_RELEASED) + std::erase(pressedButtons, button); + else if (state == WL_POINTER_BUTTON_STATE_PRESSED) + pressedButtons.emplace_back(button); + resource->sendButton(g_pSeatManager->nextSerial(owner.lock()), timeMs, button, state); } diff --git a/src/protocols/core/Seat.hpp b/src/protocols/core/Seat.hpp index 625d3a98..0b563b8f 100644 --- a/src/protocols/core/Seat.hpp +++ b/src/protocols/core/Seat.hpp @@ -76,6 +76,8 @@ class CWLPointerResource { SP resource; WP currentSurface; + std::vector pressedButtons; + struct { CHyprSignalListener destroySurface; } listeners; From a9c7a0830fd9a8b9fc4065f1cd654efd1326691a Mon Sep 17 00:00:00 2001 From: Vaxry Date: Mon, 17 Jun 2024 16:14:45 +0200 Subject: [PATCH 0038/2181] data-device: minor fixes send leave after drop, improve checks in completeDrag --- src/protocols/core/DataDevice.cpp | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/src/protocols/core/DataDevice.cpp b/src/protocols/core/DataDevice.cpp index 2d50ff15..9634d569 100644 --- a/src/protocols/core/DataDevice.cpp +++ b/src/protocols/core/DataDevice.cpp @@ -540,7 +540,7 @@ void CWLDataDeviceProtocol::initiateDrag(WP currentSource } void CWLDataDeviceProtocol::updateDrag() { - if (!dnd.currentSource) + if (!dndActive()) return; if (dnd.focusedDevice) @@ -595,15 +595,13 @@ void CWLDataDeviceProtocol::dropDrag() { } dnd.focusedDevice->sendDrop(); + dnd.focusedDevice->sendLeave(); resetDndState(); if (dnd.overriddenCursor) g_pInputManager->unsetCursorImage(); dnd.overriddenCursor = false; - - g_pInputManager->simulateMouseMovement(); - g_pSeatManager->resendEnterEvents(); } bool CWLDataDeviceProtocol::wasDragSuccessful() { @@ -624,11 +622,13 @@ bool CWLDataDeviceProtocol::wasDragSuccessful() { void CWLDataDeviceProtocol::completeDrag() { resetDndState(); - if (!dnd.focusedDevice || !dnd.currentSource) + if (!dnd.focusedDevice && !dnd.currentSource) return; - dnd.currentSource->sendDndDropPerformed(); - dnd.currentSource->sendDndFinished(); + if (dnd.currentSource) { + dnd.currentSource->sendDndDropPerformed(); + dnd.currentSource->sendDndFinished(); + } dnd.focusedDevice.reset(); dnd.currentSource.reset(); From 28ce0e0f804de50f75eab797bc404c1be0b54442 Mon Sep 17 00:00:00 2001 From: Tom Englund Date: Mon, 17 Jun 2024 17:37:36 +0200 Subject: [PATCH 0039/2181] misc: a few compiler level performance optimisations (#6559) * window: use const references instead of copies use const references instead of wasteful copies and make the = operator check for self assignment and return early. also use const in all the other operators. * listener: pass std::function as const reference instead of copies pass the std::functions as const references. * config: dont unnecessarily convert to c_str getHyprlangConfigValuePtr wants an std::string and we already have an std::string, dont convert it to a c_str only for it to be converted back to an std::string. * buffer: pass attributes as const reference pass attributes as const reference instead of copies. --- src/config/ConfigValue.hpp | 2 +- src/desktop/Window.hpp | 30 +++++++++++++++++------------- src/helpers/WLListener.cpp | 4 ++-- src/helpers/WLListener.hpp | 4 ++-- src/protocols/types/DMABuffer.cpp | 2 +- src/protocols/types/DMABuffer.hpp | 2 +- 6 files changed, 24 insertions(+), 20 deletions(-) diff --git a/src/config/ConfigValue.hpp b/src/config/ConfigValue.hpp index 72accd67..fc8abb4b 100644 --- a/src/config/ConfigValue.hpp +++ b/src/config/ConfigValue.hpp @@ -11,7 +11,7 @@ template class CConfigValue { public: CConfigValue(const std::string& val) { - const auto PVHYPRLANG = g_pConfigManager->getHyprlangConfigValuePtr(val.c_str()); + const auto PVHYPRLANG = g_pConfigManager->getHyprlangConfigValuePtr(val); p_ = PVHYPRLANG->getDataStaticPtr(); diff --git a/src/desktop/Window.hpp b/src/desktop/Window.hpp index 16bf297c..3f387d31 100644 --- a/src/desktop/Window.hpp +++ b/src/desktop/Window.hpp @@ -62,18 +62,22 @@ class IWindowTransformer; template class CWindowOverridableVar { public: - CWindowOverridableVar(T val) { + CWindowOverridableVar(T const& val) { value = val; } ~CWindowOverridableVar() = default; - CWindowOverridableVar& operator=(CWindowOverridableVar other) { - if (locked) + CWindowOverridableVar& operator=(CWindowOverridableVar const& other) { + // Self-assignment check + if (this == &other) return *this; - locked = other.locked; - value = other.value; + // Check if the current object is locked + if (!locked) { + locked = other.locked; + value = other.value; + } return *this; } @@ -85,36 +89,36 @@ class CWindowOverridableVar { return other; } - void forceSetIgnoreLocked(T val, bool lock = false) { + void forceSetIgnoreLocked(T const& val, bool lock = false) { value = val; locked = lock; } - T operator*(T& other) { + T operator*(T const& other) { return value * other; } - T operator+(T& other) { + T operator+(T const& other) { return value + other; } - bool operator==(T& other) { + bool operator==(T const& other) { return other == value; } - bool operator>=(T& other) { + bool operator>=(T const& other) { return value >= other; } - bool operator<=(T& other) { + bool operator<=(T const& other) { return value <= other; } - bool operator>(T& other) { + bool operator>(T const& other) { return value > other; } - bool operator<(T& other) { + bool operator<(T const& other) { return value < other; } diff --git a/src/helpers/WLListener.cpp b/src/helpers/WLListener.cpp index 978ff034..2ea5c0b6 100644 --- a/src/helpers/WLListener.cpp +++ b/src/helpers/WLListener.cpp @@ -18,7 +18,7 @@ void handleWrapped(wl_listener* listener, void* data) { g_pWatchdog->endWatching(); } -CHyprWLListener::CHyprWLListener(wl_signal* pSignal, std::function callback, void* pOwner) { +CHyprWLListener::CHyprWLListener(wl_signal* pSignal, std::function const& callback, void* pOwner) { initCallback(pSignal, callback, pOwner); } @@ -44,7 +44,7 @@ bool CHyprWLListener::isConnected() { return !wl_list_empty(&m_swWrapper.m_sListener.link); } -void CHyprWLListener::initCallback(wl_signal* pSignal, std::function callback, void* pOwner, std::string author) { +void CHyprWLListener::initCallback(wl_signal* pSignal, std::function const& callback, void* pOwner, std::string author) { if (isConnected()) { Debug::log(ERR, "Tried to connect a listener twice?!"); return; diff --git a/src/helpers/WLListener.hpp b/src/helpers/WLListener.hpp index d5d925b0..621458e6 100644 --- a/src/helpers/WLListener.hpp +++ b/src/helpers/WLListener.hpp @@ -6,7 +6,7 @@ class CHyprWLListener { public: - CHyprWLListener(wl_signal*, std::function, void* owner); + CHyprWLListener(wl_signal*, std::function const&, void* owner); CHyprWLListener(); ~CHyprWLListener(); @@ -15,7 +15,7 @@ class CHyprWLListener { CHyprWLListener& operator=(const CHyprWLListener&) = delete; CHyprWLListener& operator=(CHyprWLListener&&) = delete; - void initCallback(wl_signal*, std::function, void* owner, std::string author = ""); + void initCallback(wl_signal*, std::function const&, void* owner, std::string author = ""); void removeCallback(); diff --git a/src/protocols/types/DMABuffer.cpp b/src/protocols/types/DMABuffer.cpp index f26328e9..7c3a9886 100644 --- a/src/protocols/types/DMABuffer.cpp +++ b/src/protocols/types/DMABuffer.cpp @@ -3,7 +3,7 @@ #include "../../render/Renderer.hpp" #include "../../helpers/Format.hpp" -CDMABuffer::CDMABuffer(uint32_t id, wl_client* client, SDMABUFAttrs attrs_) : attrs(attrs_) { +CDMABuffer::CDMABuffer(uint32_t id, wl_client* client, SDMABUFAttrs const& attrs_) : attrs(attrs_) { g_pHyprRenderer->makeEGLCurrent(); listeners.resourceDestroy = events.destroy.registerListener([this](std::any d) { diff --git a/src/protocols/types/DMABuffer.hpp b/src/protocols/types/DMABuffer.hpp index dac89493..d07840b7 100644 --- a/src/protocols/types/DMABuffer.hpp +++ b/src/protocols/types/DMABuffer.hpp @@ -4,7 +4,7 @@ class CDMABuffer : public IWLBuffer { public: - CDMABuffer(uint32_t id, wl_client* client, SDMABUFAttrs attrs_); + CDMABuffer(uint32_t id, wl_client* client, SDMABUFAttrs const& attrs_); virtual ~CDMABuffer(); virtual eBufferCapability caps(); From d1340bd1d8eedd274283e0cb2568a3ed67b58c81 Mon Sep 17 00:00:00 2001 From: Vaxry Date: Mon, 17 Jun 2024 17:53:44 +0200 Subject: [PATCH 0040/2181] keybinds: ignore missing keysyms if no other methods match fixes #6548 --- src/managers/KeybindManager.cpp | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/managers/KeybindManager.cpp b/src/managers/KeybindManager.cpp index 14fadf02..875ba239 100644 --- a/src/managers/KeybindManager.cpp +++ b/src/managers/KeybindManager.cpp @@ -636,6 +636,12 @@ bool CKeybindManager::handleKeybinds(const uint32_t modmask, const SPressedKeyWi if (found || key.submapAtPress != m_szCurrentSelectedSubmap) continue; } else { + // in this case, we only have the keysym to go off. + // if the keysym failed resolving, we can't do anything. It's likely missing + // from the keymap. + if (key.keysym == 0) + return false; + // oMg such performance hit!!11! // this little maneouver is gonna cost us 4µs const auto KBKEY = xkb_keysym_from_name(k.key.c_str(), XKB_KEYSYM_NO_FLAGS); From 236150b3c5227bbfbe46d2610c739a386afdca1f Mon Sep 17 00:00:00 2001 From: Aqa-Ib Date: Tue, 18 Jun 2024 17:06:14 +0200 Subject: [PATCH 0041/2181] github: reword bug or regression (#6520) --- .github/ISSUE_TEMPLATE/bug.yml | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/.github/ISSUE_TEMPLATE/bug.yml b/.github/ISSUE_TEMPLATE/bug.yml index 285a15a1..e3e97bef 100644 --- a/.github/ISSUE_TEMPLATE/bug.yml +++ b/.github/ISSUE_TEMPLATE/bug.yml @@ -5,18 +5,21 @@ body: - type: markdown attributes: value: | - Before opening a new issue, take a moment to search through the current open ones. + ## Before opening a new issue, please take a moment to search through the current open and closed issues to check if it already exists. --- - type: dropdown id: type attributes: - label: Bug or Regression? - description: Is this a bug or a regression? + label: Regression? + description: | + Regression means that something used to work but no longer does. + **BEFORE CONTINUING**, please check if this bug is a regression or not, and if it is, we need you to bisect with the help of the wiki: https://wiki.hyprland.org/Crashes-and-Bugs/#bisecting-an-issue + multiple: true options: - - Bug - - Regression + - "Yes" + - "No" validations: required: true From b98e0876d3b54b7625bacf14e3546dd2d0e600d0 Mon Sep 17 00:00:00 2001 From: Vaxry Date: Tue, 18 Jun 2024 21:38:33 +0200 Subject: [PATCH 0042/2181] hyprctl: avoid using select() move to poll() ref #6584 --- src/debug/HyprCtl.cpp | 17 +++++++++++------ 1 file changed, 11 insertions(+), 6 deletions(-) diff --git a/src/debug/HyprCtl.cpp b/src/debug/HyprCtl.cpp index 70b886f2..e212ed1c 100644 --- a/src/debug/HyprCtl.cpp +++ b/src/debug/HyprCtl.cpp @@ -11,6 +11,7 @@ #include #include #include +#include #include #include @@ -1784,13 +1785,17 @@ int hyprCtlFDTick(int fd, uint32_t mask, void* data) { std::array readBuffer; - fd_set fdset; - FD_ZERO(&fdset); - FD_SET(ACCEPTEDCONNECTION, &fdset); - timeval timeout = {.tv_sec = 0, .tv_usec = 5000}; - auto success = select(ACCEPTEDCONNECTION + 1, &fdset, nullptr, nullptr, &timeout); + // + pollfd pollfds[1] = { + { + .fd = ACCEPTEDCONNECTION, + .events = POLLIN, + }, + }; - if (success <= 0) { + int ret = poll(pollfds, 1, 5000); + + if (ret <= 0) { close(ACCEPTEDCONNECTION); return 0; } From e0e3c4c6ae15af88ac5fd5ab959adfe45a2e1dca Mon Sep 17 00:00:00 2001 From: Vaxry Date: Tue, 18 Jun 2024 21:52:55 +0200 Subject: [PATCH 0043/2181] compositor: bump nofile rlimits on launch ref #6584 --- src/Compositor.cpp | 43 +++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 43 insertions(+) diff --git a/src/Compositor.cpp b/src/Compositor.cpp index 2f972335..af46b0ff 100644 --- a/src/Compositor.cpp +++ b/src/Compositor.cpp @@ -29,6 +29,7 @@ using namespace Hyprutils::String; #include #include +#include int handleCritSignal(int signo, void* data) { Debug::log(LOG, "Hyprland received signal {}", signo); @@ -70,6 +71,46 @@ void handleUserSignal(int sig) { } } +static void bumpNofile() { + unsigned long limit = 1024; + + try { + std::ifstream f("/proc/sys/fs/nr_open"); + if (!f.good()) + limit = 1073741816; + else { + std::string content((std::istreambuf_iterator(f)), (std::istreambuf_iterator())); + f.close(); + + limit = std::stoll(content); + } + + } catch (...) { limit = 1073741816; } + + struct rlimit rlimit_; + if (!getrlimit(RLIMIT_NOFILE, &rlimit_)) + Debug::log(LOG, "Old rlimit: soft -> {}, hard -> {}", rlimit_.rlim_cur, rlimit_.rlim_max); + + if (rlimit_.rlim_max <= 1024) + rlimit_.rlim_max = limit; + + unsigned long oldHardLimit = rlimit_.rlim_max; + + rlimit_.rlim_max = limit; + + if (setrlimit(RLIMIT_NOFILE, &rlimit_) < 0) { + Debug::log(LOG, "Failed bumping NOFILE limits higher, retrying with previous hard."); + rlimit_.rlim_max = oldHardLimit; + rlimit_.rlim_cur = std::clamp((unsigned long)limit, 1UL, (unsigned long)rlimit_.rlim_max); + + if (setrlimit(RLIMIT_NOFILE, &rlimit_) < 0) + Debug::log(LOG, "Failed bumping NOFILE limits higher for the second time."); + } + + if (!getrlimit(RLIMIT_NOFILE, &rlimit_)) + Debug::log(LOG, "New rlimit: soft -> {}, hard -> {}", rlimit_.rlim_cur, rlimit_.rlim_max); +} + CCompositor::CCompositor() { m_iHyprlandPID = getpid(); @@ -131,6 +172,8 @@ CCompositor::CCompositor() { setRandomSplash(); Debug::log(LOG, "\nCurrent splash: {}\n\n", m_szCurrentSplash); + + bumpNofile(); } CCompositor::~CCompositor() { From 6e5804b53de753f24953d9d647940df66bc68f6d Mon Sep 17 00:00:00 2001 From: random2907 <81547183+random2907@users.noreply.github.com> Date: Wed, 19 Jun 2024 11:50:49 +0530 Subject: [PATCH 0044/2181] hyprctl: fix zsh completion (#6467) Co-authored-by: random2907 --- hyprctl/hyprctl.zsh | 2 ++ 1 file changed, 2 insertions(+) diff --git a/hyprctl/hyprctl.zsh b/hyprctl/hyprctl.zsh index 6babd835..1a4cc187 100644 --- a/hyprctl/hyprctl.zsh +++ b/hyprctl/hyprctl.zsh @@ -1,3 +1,5 @@ +#compdef hyprctl + _hyprctl_cmd_2 () { hyprctl monitors | grep Monitor | awk '{ print $2 }' } From fb15b7aa2a9bba0f0693f84d0c65d386942583f8 Mon Sep 17 00:00:00 2001 From: Vaxry Date: Wed, 19 Jun 2024 16:20:06 +0200 Subject: [PATCH 0045/2181] core: Move to hyprutils for Math Moves CRegion, CBox and Vector2D over to hyprutils. Requires hyprutils>=0.1.4 --- CMakeLists.txt | 2 +- src/Compositor.cpp | 3 +- src/SharedDefs.hpp | 29 +-- src/config/ConfigManager.cpp | 3 +- src/debug/HyprNotificationOverlay.cpp | 2 +- src/desktop/LayerSurface.cpp | 4 +- src/desktop/WLSurface.cpp | 2 +- src/desktop/WLSurface.hpp | 2 +- src/desktop/Window.cpp | 10 +- src/desktop/Window.hpp | 136 +++++------ src/desktop/Workspace.cpp | 16 +- src/devices/IKeyboard.hpp | 2 +- src/devices/IPointer.hpp | 2 +- src/devices/ITouch.hpp | 2 +- src/devices/Tablet.hpp | 4 +- src/helpers/AnimatedVariable.hpp | 2 +- src/helpers/BezierCurve.hpp | 2 +- src/helpers/Box.cpp | 179 -------------- src/helpers/Box.hpp | 92 -------- src/helpers/Format.hpp | 2 +- src/helpers/MiscFunctions.cpp | 2 +- src/helpers/MiscFunctions.hpp | 2 +- src/helpers/Monitor.cpp | 4 +- src/helpers/Monitor.hpp | 2 +- src/helpers/Region.cpp | 183 --------------- src/helpers/Region.hpp | 69 ------ src/helpers/Vector2D.cpp | 58 ----- src/helpers/Vector2D.hpp | 133 ----------- src/helpers/WLClasses.hpp | 2 +- src/helpers/math/Math.cpp | 220 ++++++++++++++++++ src/helpers/math/Math.hpp | 11 + src/includes.hpp | 2 - src/layout/DwindleLayout.cpp | 12 +- src/layout/IHyprLayout.cpp | 4 +- src/layout/MasterLayout.cpp | 4 +- src/macros.hpp | 7 + src/managers/AnimationManager.cpp | 18 +- src/managers/CursorManager.cpp | 9 +- src/managers/CursorManager.hpp | 2 +- src/managers/PointerManager.cpp | 2 +- src/managers/PointerManager.hpp | 4 +- src/managers/SeatManager.hpp | 2 +- src/managers/input/InputMethodPopup.hpp | 2 +- src/managers/input/Swipe.cpp | 40 ++-- src/managers/input/TextInput.hpp | 2 +- src/protocols/LayerShell.cpp | 2 +- src/protocols/LayerShell.hpp | 2 +- src/protocols/PointerConstraints.hpp | 4 +- src/protocols/PointerGestures.hpp | 2 +- src/protocols/RelativePointer.hpp | 2 +- src/protocols/Screencopy.cpp | 9 +- src/protocols/Tablet.hpp | 2 +- src/protocols/TextInputV3.hpp | 2 +- src/protocols/ToplevelExport.cpp | 2 +- src/protocols/XDGShell.cpp | 20 +- src/protocols/XDGShell.hpp | 4 +- src/protocols/core/Compositor.cpp | 2 +- src/protocols/core/Compositor.hpp | 2 +- src/protocols/core/DataDevice.hpp | 2 +- src/protocols/core/Seat.hpp | 2 +- src/protocols/core/Shm.hpp | 2 +- src/render/OpenGL.cpp | 38 +-- src/render/OpenGL.hpp | 2 +- src/render/Renderer.cpp | 16 +- src/render/Renderer.hpp | 2 +- src/render/Texture.cpp | 2 +- src/render/Texture.hpp | 2 +- .../decorations/CHyprBorderDecoration.hpp | 16 +- .../decorations/CHyprDropShadowDecoration.cpp | 2 +- .../decorations/CHyprDropShadowDecoration.hpp | 14 +- .../decorations/CHyprGroupBarDecoration.hpp | 2 +- .../decorations/DecorationPositioner.cpp | 30 +-- .../decorations/DecorationPositioner.hpp | 28 +-- .../decorations/IHyprWindowDecoration.hpp | 2 +- src/xwayland/XSurface.hpp | 2 +- src/xwayland/XWM.cpp | 2 +- 76 files changed, 509 insertions(+), 1004 deletions(-) delete mode 100644 src/helpers/Box.cpp delete mode 100644 src/helpers/Box.hpp delete mode 100644 src/helpers/Region.cpp delete mode 100644 src/helpers/Region.hpp delete mode 100644 src/helpers/Vector2D.cpp delete mode 100644 src/helpers/Vector2D.hpp create mode 100644 src/helpers/math/Math.cpp create mode 100644 src/helpers/math/Math.hpp diff --git a/CMakeLists.txt b/CMakeLists.txt index 7aa2bf5c..632621ac 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -113,7 +113,7 @@ pkg_check_modules(deps REQUIRED IMPORTED_TARGET wayland-server wayland-client wayland-cursor wayland-protocols cairo pango pangocairo pixman-1 libdrm libinput hwdata libseat libdisplay-info libliftoff libudev gbm - hyprlang>=0.3.2 hyprcursor>=0.1.7 hyprutils>=0.1.1 + hyprlang>=0.3.2 hyprcursor>=0.1.7 hyprutils>=0.1.4 ) find_package(hyprwayland-scanner 0.3.10 REQUIRED) diff --git a/src/Compositor.cpp b/src/Compositor.cpp index af46b0ff..7777a55f 100644 --- a/src/Compositor.cpp +++ b/src/Compositor.cpp @@ -1434,8 +1434,7 @@ PHLWINDOW CCompositor::getWindowInDirection(PHLWINDOW pWindow, char dir) { if (!PMONITOR) return nullptr; // ?? - const auto WINDOWIDEALBB = pWindow->m_bIsFullscreen ? wlr_box{(int)PMONITOR->vecPosition.x, (int)PMONITOR->vecPosition.y, (int)PMONITOR->vecSize.x, (int)PMONITOR->vecSize.y} : - pWindow->getWindowIdealBoundingBoxIgnoreReserved(); + const auto WINDOWIDEALBB = pWindow->m_bIsFullscreen ? CBox{PMONITOR->vecPosition, PMONITOR->vecSize} : pWindow->getWindowIdealBoundingBoxIgnoreReserved(); const auto POSA = Vector2D(WINDOWIDEALBB.x, WINDOWIDEALBB.y); const auto SIZEA = Vector2D(WINDOWIDEALBB.width, WINDOWIDEALBB.height); diff --git a/src/SharedDefs.hpp b/src/SharedDefs.hpp index 1b4876bb..2a1546c6 100644 --- a/src/SharedDefs.hpp +++ b/src/SharedDefs.hpp @@ -1,7 +1,11 @@ #pragma once -#include "helpers/Vector2D.hpp" +#include "helpers/math/Math.hpp" #include +#include +#include + +using namespace Hyprutils::Math; enum eIcons { ICON_WARNING = 0, @@ -37,29 +41,6 @@ struct SCallbackInfo { bool cancelled = false; /* on cancellable events, will cancel the event. */ }; -struct SWindowDecorationExtents { - Vector2D topLeft; - Vector2D bottomRight; - - // - SWindowDecorationExtents operator*(const double& scale) const { - return SWindowDecorationExtents{topLeft * scale, bottomRight * scale}; - } - - SWindowDecorationExtents round() { - return {topLeft.round(), bottomRight.round()}; - } - - bool operator==(const SWindowDecorationExtents& other) const { - return topLeft == other.topLeft && bottomRight == other.bottomRight; - } - - void addExtents(const SWindowDecorationExtents& other) { - topLeft = topLeft.getComponentMax(other.topLeft); - bottomRight = bottomRight.getComponentMax(other.bottomRight); - } -}; - enum eHyprCtlOutputFormat { FORMAT_NORMAL = 0, FORMAT_JSON diff --git a/src/config/ConfigManager.cpp b/src/config/ConfigManager.cpp index 56fdae25..17bbe465 100644 --- a/src/config/ConfigManager.cpp +++ b/src/config/ConfigManager.cpp @@ -982,7 +982,8 @@ float CConfigManager::getDeviceFloat(const std::string& dev, const std::string& } Vector2D CConfigManager::getDeviceVec(const std::string& dev, const std::string& v, const std::string& fallback) { - return std::any_cast(getConfigValueSafeDevice(dev, v, fallback)->getValue()); + auto vec = std::any_cast(getConfigValueSafeDevice(dev, v, fallback)->getValue()); + return {vec.x, vec.y}; } std::string CConfigManager::getDeviceString(const std::string& dev, const std::string& v, const std::string& fallback) { diff --git a/src/debug/HyprNotificationOverlay.cpp b/src/debug/HyprNotificationOverlay.cpp index aec3853e..3f8bb579 100644 --- a/src/debug/HyprNotificationOverlay.cpp +++ b/src/debug/HyprNotificationOverlay.cpp @@ -131,7 +131,7 @@ CBox CHyprNotificationOverlay::drawNotifications(CMonitor* pMonitor) { textW /= PANGO_SCALE; textH /= PANGO_SCALE; - const auto NOTIFSIZE = Vector2D{textW + 20 + iconW + 2 * ICONPADFORNOTIF, textH + 10}; + const auto NOTIFSIZE = Vector2D{textW + 20.0 + iconW + 2 * ICONPADFORNOTIF, textH + 10.0}; // draw rects cairo_set_source_rgba(m_pCairo, notif->color.r, notif->color.g, notif->color.b, notif->color.a); diff --git a/src/desktop/LayerSurface.cpp b/src/desktop/LayerSurface.cpp index 64eeead1..9a891531 100644 --- a/src/desktop/LayerSurface.cpp +++ b/src/desktop/LayerSurface.cpp @@ -412,9 +412,9 @@ void CLayerSurface::startAnimation(bool in, bool instant) { } const std::array edgePoints = { - PMONITOR->vecPosition + Vector2D{PMONITOR->vecSize.x / 2, 0}, + PMONITOR->vecPosition + Vector2D{PMONITOR->vecSize.x / 2, 0.0}, PMONITOR->vecPosition + Vector2D{PMONITOR->vecSize.x / 2, PMONITOR->vecSize.y}, - PMONITOR->vecPosition + Vector2D{0, PMONITOR->vecSize.y}, + PMONITOR->vecPosition + Vector2D{0.0, PMONITOR->vecSize.y}, PMONITOR->vecPosition + Vector2D{PMONITOR->vecSize.x, PMONITOR->vecSize.y / 2}, }; diff --git a/src/desktop/WLSurface.cpp b/src/desktop/WLSurface.cpp index c7a09b40..97335d27 100644 --- a/src/desktop/WLSurface.cpp +++ b/src/desktop/WLSurface.cpp @@ -86,7 +86,7 @@ CRegion CWLSurface::logicalDamage() const { return {}; CRegion damage = m_pResource->accumulateCurrentBufferDamage(); - damage.transform(m_pResource->current.transform, m_pResource->current.buffer->size.x, m_pResource->current.buffer->size.y); + damage.transform(wlTransformToHyprutils(m_pResource->current.transform), m_pResource->current.buffer->size.x, m_pResource->current.buffer->size.y); damage.scale(1.0 / m_pResource->current.scale); const auto VPSIZE = getViewporterCorrectedSize(); diff --git a/src/desktop/WLSurface.hpp b/src/desktop/WLSurface.hpp index 4ba381a9..447f4582 100644 --- a/src/desktop/WLSurface.hpp +++ b/src/desktop/WLSurface.hpp @@ -1,7 +1,7 @@ #pragma once #include "../defines.hpp" -#include "../helpers/Region.hpp" +#include "../helpers/math/Math.hpp" #include "../helpers/signal/Signal.hpp" class CSubsurface; diff --git a/src/desktop/Window.cpp b/src/desktop/Window.cpp index d153b344..e67a3357 100644 --- a/src/desktop/Window.cpp +++ b/src/desktop/Window.cpp @@ -104,7 +104,7 @@ CWindow::~CWindow() { std::erase_if(g_pHyprOpenGL->m_mWindowFramebuffers, [&](const auto& other) { return !other.first.lock() || other.first.lock().get() == this; }); } -SWindowDecorationExtents CWindow::getFullWindowExtents() { +SBoxExtents CWindow::getFullWindowExtents() { if (m_bFadingOut) return m_eOriginalClosedExtents; @@ -116,9 +116,9 @@ SWindowDecorationExtents CWindow::getFullWindowExtents() { {PMONITOR->vecSize.x - (m_vRealPosition.value().x - PMONITOR->vecPosition.x), PMONITOR->vecSize.y - (m_vRealPosition.value().y - PMONITOR->vecPosition.y)}}; } - SWindowDecorationExtents maxExtents = {{BORDERSIZE + 2, BORDERSIZE + 2}, {BORDERSIZE + 2, BORDERSIZE + 2}}; + SBoxExtents maxExtents = {{BORDERSIZE + 2, BORDERSIZE + 2}, {BORDERSIZE + 2, BORDERSIZE + 2}}; - const auto EXTENTS = g_pDecorationPositioner->getWindowDecorationExtents(m_pSelf.lock()); + const auto EXTENTS = g_pDecorationPositioner->getWindowDecorationExtents(m_pSelf.lock()); if (EXTENTS.topLeft.x > maxExtents.topLeft.x) maxExtents.topLeft.x = EXTENTS.topLeft.x; @@ -224,7 +224,7 @@ CBox CWindow::getWindowBoxUnified(uint64_t properties) { return {PMONITOR->vecPosition.x, PMONITOR->vecPosition.y, PMONITOR->vecSize.x, PMONITOR->vecSize.y}; } - SWindowDecorationExtents EXTENTS = {{0, 0}, {0, 0}}; + SBoxExtents EXTENTS = {{0, 0}, {0, 0}}; if (properties & RESERVED_EXTENTS) EXTENTS.addExtents(g_pDecorationPositioner->getWindowDecorationReserved(m_pSelf.lock())); if (properties & INPUT_EXTENTS) @@ -242,7 +242,7 @@ CBox CWindow::getWindowMainSurfaceBox() { return {m_vRealPosition.value().x, m_vRealPosition.value().y, m_vRealSize.value().x, m_vRealSize.value().y}; } -SWindowDecorationExtents CWindow::getFullWindowReservedArea() { +SBoxExtents CWindow::getFullWindowReservedArea() { return g_pDecorationPositioner->getWindowDecorationReserved(m_pSelf.lock()); } diff --git a/src/desktop/Window.hpp b/src/desktop/Window.hpp index 3f387d31..6bfdbc50 100644 --- a/src/desktop/Window.hpp +++ b/src/desktop/Window.hpp @@ -6,7 +6,7 @@ #include "../config/ConfigDataValues.hpp" #include "../defines.hpp" #include "../helpers/AnimatedVariable.hpp" -#include "../helpers/Vector2D.hpp" +#include "../helpers/math/Math.hpp" #include "../helpers/signal/Signal.hpp" #include "../helpers/TagKeeper.hpp" #include "../macros.hpp" @@ -310,7 +310,7 @@ class CWindow { bool m_bReadyToDelete = false; Vector2D m_vOriginalClosedPos; // these will be used for calculations later on in Vector2D m_vOriginalClosedSize; // drawing the closing animations - SWindowDecorationExtents m_eOriginalClosedExtents; + SBoxExtents m_eOriginalClosedExtents; bool m_bAnimatingIn = false; // For pinned (sticky) windows @@ -386,75 +386,75 @@ class CWindow { } // methods - CBox getFullWindowBoundingBox(); - SWindowDecorationExtents getFullWindowExtents(); - CBox getWindowBoxUnified(uint64_t props); - CBox getWindowMainSurfaceBox(); - CBox getWindowIdealBoundingBoxIgnoreReserved(); - void addWindowDeco(std::unique_ptr deco); - void updateWindowDecos(); - void removeWindowDeco(IHyprWindowDecoration* deco); - void uncacheWindowDecos(); - bool checkInputOnDecos(const eInputType, const Vector2D&, std::any = {}); - pid_t getPID(); - IHyprWindowDecoration* getDecorationByType(eDecorationType); - void removeDecorationByType(eDecorationType); - void updateToplevel(); - void updateSurfaceScaleTransformDetails(bool force = false); - void moveToWorkspace(PHLWORKSPACE); - PHLWINDOW X11TransientFor(); - void onUnmap(); - void onMap(); - void setHidden(bool hidden); - bool isHidden(); - void applyDynamicRule(const SWindowRule& r); - void updateDynamicRules(); - SWindowDecorationExtents getFullWindowReservedArea(); - Vector2D middle(); - bool opaque(); - float rounding(); - bool canBeTorn(); - bool shouldSendFullscreenState(); - void setSuspended(bool suspend); - bool visibleOnMonitor(CMonitor* pMonitor); - int workspaceID(); - bool onSpecialWorkspace(); - void activate(bool force = false); - int surfacesCount(); + CBox getFullWindowBoundingBox(); + SBoxExtents getFullWindowExtents(); + CBox getWindowBoxUnified(uint64_t props); + CBox getWindowMainSurfaceBox(); + CBox getWindowIdealBoundingBoxIgnoreReserved(); + void addWindowDeco(std::unique_ptr deco); + void updateWindowDecos(); + void removeWindowDeco(IHyprWindowDecoration* deco); + void uncacheWindowDecos(); + bool checkInputOnDecos(const eInputType, const Vector2D&, std::any = {}); + pid_t getPID(); + IHyprWindowDecoration* getDecorationByType(eDecorationType); + void removeDecorationByType(eDecorationType); + void updateToplevel(); + void updateSurfaceScaleTransformDetails(bool force = false); + void moveToWorkspace(PHLWORKSPACE); + PHLWINDOW X11TransientFor(); + void onUnmap(); + void onMap(); + void setHidden(bool hidden); + bool isHidden(); + void applyDynamicRule(const SWindowRule& r); + void updateDynamicRules(); + SBoxExtents getFullWindowReservedArea(); + Vector2D middle(); + bool opaque(); + float rounding(); + bool canBeTorn(); + bool shouldSendFullscreenState(); + void setSuspended(bool suspend); + bool visibleOnMonitor(CMonitor* pMonitor); + int workspaceID(); + bool onSpecialWorkspace(); + void activate(bool force = false); + int surfacesCount(); - int getRealBorderSize(); - void updateSpecialRenderData(); - void updateSpecialRenderData(const struct SWorkspaceRule&); + int getRealBorderSize(); + void updateSpecialRenderData(); + void updateSpecialRenderData(const struct SWorkspaceRule&); - void onBorderAngleAnimEnd(void* ptr); - bool isInCurvedCorner(double x, double y); - bool hasPopupAt(const Vector2D& pos); - int popupsCount(); + void onBorderAngleAnimEnd(void* ptr); + bool isInCurvedCorner(double x, double y); + bool hasPopupAt(const Vector2D& pos); + int popupsCount(); - void applyGroupRules(); - void createGroup(); - void destroyGroup(); - PHLWINDOW getGroupHead(); - PHLWINDOW getGroupTail(); - PHLWINDOW getGroupCurrent(); - PHLWINDOW getGroupPrevious(); - PHLWINDOW getGroupWindowByIndex(int); - int getGroupSize(); - bool canBeGroupedInto(PHLWINDOW pWindow); - void setGroupCurrent(PHLWINDOW pWindow); - void insertWindowToGroup(PHLWINDOW pWindow); - void updateGroupOutputs(); - void switchWithWindowInGroup(PHLWINDOW pWindow); - void setAnimationsToMove(); - void onWorkspaceAnimUpdate(); - void onUpdateState(); - void onUpdateMeta(); - void onX11Configure(CBox box); - void onResourceChangeX11(); - std::string fetchTitle(); - std::string fetchClass(); - void warpCursor(); - PHLWINDOW getSwallower(); + void applyGroupRules(); + void createGroup(); + void destroyGroup(); + PHLWINDOW getGroupHead(); + PHLWINDOW getGroupTail(); + PHLWINDOW getGroupCurrent(); + PHLWINDOW getGroupPrevious(); + PHLWINDOW getGroupWindowByIndex(int); + int getGroupSize(); + bool canBeGroupedInto(PHLWINDOW pWindow); + void setGroupCurrent(PHLWINDOW pWindow); + void insertWindowToGroup(PHLWINDOW pWindow); + void updateGroupOutputs(); + void switchWithWindowInGroup(PHLWINDOW pWindow); + void setAnimationsToMove(); + void onWorkspaceAnimUpdate(); + void onUpdateState(); + void onUpdateMeta(); + void onX11Configure(CBox box); + void onResourceChangeX11(); + std::string fetchTitle(); + std::string fetchClass(); + void warpCursor(); + PHLWINDOW getSwallower(); // listeners void onAck(uint32_t serial); diff --git a/src/desktop/Workspace.cpp b/src/desktop/Workspace.cpp index ed09fbc0..04685bd5 100644 --- a/src/desktop/Workspace.cpp +++ b/src/desktop/Workspace.cpp @@ -104,24 +104,24 @@ void CWorkspace::startAnim(bool in, bool left, bool instant) { if (ANIMSTYLE.starts_with("slidefadevert")) { if (in) { m_fAlpha.setValueAndWarp(0.f); - m_vRenderOffset.setValueAndWarp(Vector2D(0, (left ? PMONITOR->vecSize.y : -PMONITOR->vecSize.y) * (movePerc / 100.f))); + m_vRenderOffset.setValueAndWarp(Vector2D(0.0, (left ? PMONITOR->vecSize.y : -PMONITOR->vecSize.y) * (movePerc / 100.f))); m_fAlpha = 1.f; m_vRenderOffset = Vector2D(0, 0); } else { m_fAlpha.setValueAndWarp(1.f); m_fAlpha = 0.f; - m_vRenderOffset = Vector2D(0, (left ? -PMONITOR->vecSize.y : PMONITOR->vecSize.y) * (movePerc / 100.f)); + m_vRenderOffset = Vector2D(0.0, (left ? -PMONITOR->vecSize.y : PMONITOR->vecSize.y) * (movePerc / 100.f)); } } else { if (in) { m_fAlpha.setValueAndWarp(0.f); - m_vRenderOffset.setValueAndWarp(Vector2D((left ? PMONITOR->vecSize.x : -PMONITOR->vecSize.x) * (movePerc / 100.f), 0)); + m_vRenderOffset.setValueAndWarp(Vector2D((left ? PMONITOR->vecSize.x : -PMONITOR->vecSize.x) * (movePerc / 100.f), 0.0)); m_fAlpha = 1.f; m_vRenderOffset = Vector2D(0, 0); } else { m_fAlpha.setValueAndWarp(1.f); m_fAlpha = 0.f; - m_vRenderOffset = Vector2D((left ? -PMONITOR->vecSize.x : PMONITOR->vecSize.x) * (movePerc / 100.f), 0); + m_vRenderOffset = Vector2D((left ? -PMONITOR->vecSize.x : PMONITOR->vecSize.x) * (movePerc / 100.f), 0.0); } } } else if (ANIMSTYLE == "fade") { @@ -142,10 +142,10 @@ void CWorkspace::startAnim(bool in, bool left, bool instant) { m_fAlpha.setValueAndWarp(1.f); // fix a bug, if switching from fade -> slide. if (in) { - m_vRenderOffset.setValueAndWarp(Vector2D(0, left ? YDISTANCE : -YDISTANCE)); + m_vRenderOffset.setValueAndWarp(Vector2D(0.0, left ? YDISTANCE : -YDISTANCE)); m_vRenderOffset = Vector2D(0, 0); } else { - m_vRenderOffset = Vector2D(0, left ? -YDISTANCE : YDISTANCE); + m_vRenderOffset = Vector2D(0.0, left ? -YDISTANCE : YDISTANCE); } } else { // fallback is slide @@ -155,10 +155,10 @@ void CWorkspace::startAnim(bool in, bool left, bool instant) { m_fAlpha.setValueAndWarp(1.f); // fix a bug, if switching from fade -> slide. if (in) { - m_vRenderOffset.setValueAndWarp(Vector2D(left ? XDISTANCE : -XDISTANCE, 0)); + m_vRenderOffset.setValueAndWarp(Vector2D(left ? XDISTANCE : -XDISTANCE, 0.0)); m_vRenderOffset = Vector2D(0, 0); } else { - m_vRenderOffset = Vector2D(left ? -XDISTANCE : XDISTANCE, 0); + m_vRenderOffset = Vector2D(left ? -XDISTANCE : XDISTANCE, 0.0); } } diff --git a/src/devices/IKeyboard.hpp b/src/devices/IKeyboard.hpp index ec58ff5b..b1757a18 100644 --- a/src/devices/IKeyboard.hpp +++ b/src/devices/IKeyboard.hpp @@ -3,7 +3,7 @@ #include "IHID.hpp" #include "../helpers/WLListener.hpp" #include "../macros.hpp" -#include "../helpers/Vector2D.hpp" +#include "../helpers/math/Math.hpp" #include diff --git a/src/devices/IPointer.hpp b/src/devices/IPointer.hpp index e2347c95..b2995b2f 100644 --- a/src/devices/IPointer.hpp +++ b/src/devices/IPointer.hpp @@ -3,7 +3,7 @@ #include "IHID.hpp" #include "../helpers/WLListener.hpp" #include "../macros.hpp" -#include "../helpers/Vector2D.hpp" +#include "../helpers/math/Math.hpp" struct wlr_pointer; diff --git a/src/devices/ITouch.hpp b/src/devices/ITouch.hpp index 5929be02..b9cbf2ae 100644 --- a/src/devices/ITouch.hpp +++ b/src/devices/ITouch.hpp @@ -3,7 +3,7 @@ #include "IHID.hpp" #include "../helpers/WLListener.hpp" #include "../macros.hpp" -#include "../helpers/Vector2D.hpp" +#include "../helpers/math/Math.hpp" struct wlr_touch; diff --git a/src/devices/Tablet.hpp b/src/devices/Tablet.hpp index 1805f3ba..ada2cf89 100644 --- a/src/devices/Tablet.hpp +++ b/src/devices/Tablet.hpp @@ -3,8 +3,8 @@ #include "IHID.hpp" #include "../helpers/WLListener.hpp" #include "../macros.hpp" -#include "../helpers/Vector2D.hpp" -#include "../helpers/Box.hpp" +#include "../helpers/math/Math.hpp" +#include "../helpers/math/Math.hpp" struct wlr_tablet; struct wlr_tablet_tool; diff --git a/src/helpers/AnimatedVariable.hpp b/src/helpers/AnimatedVariable.hpp index 5c63032e..073cf65b 100644 --- a/src/helpers/AnimatedVariable.hpp +++ b/src/helpers/AnimatedVariable.hpp @@ -4,7 +4,7 @@ #include #include #include -#include "Vector2D.hpp" +#include "math/Math.hpp" #include "Color.hpp" #include "../defines.hpp" #include "../debug/Log.hpp" diff --git a/src/helpers/BezierCurve.hpp b/src/helpers/BezierCurve.hpp index fb11d52b..54af46a6 100644 --- a/src/helpers/BezierCurve.hpp +++ b/src/helpers/BezierCurve.hpp @@ -3,7 +3,7 @@ #include #include #include -#include "Vector2D.hpp" +#include "math/Math.hpp" constexpr int BAKEDPOINTS = 255; constexpr float INVBAKEDPOINTS = 1.f / BAKEDPOINTS; diff --git a/src/helpers/Box.cpp b/src/helpers/Box.cpp deleted file mode 100644 index 4b7f5726..00000000 --- a/src/helpers/Box.cpp +++ /dev/null @@ -1,179 +0,0 @@ -#include "Box.hpp" - -#include -#include - -wlr_box CBox::wlr() { - CBox rounded = roundInternal(); - m_bWlrBox = wlr_box{(int)rounded.x, (int)rounded.y, (int)rounded.w, (int)rounded.h}; - return m_bWlrBox; -} - -wlr_box* CBox::pWlr() { - CBox rounded = roundInternal(); - m_bWlrBox = wlr_box{(int)rounded.x, (int)rounded.y, (int)rounded.w, (int)rounded.h}; - return &m_bWlrBox; -} - -CBox& CBox::scale(double scale) { - x *= scale; - y *= scale; - w *= scale; - h *= scale; - - return *this; -} - -CBox& CBox::scale(const Vector2D& scale) { - x *= scale.x; - y *= scale.y; - w *= scale.x; - h *= scale.y; - - return *this; -} - -CBox& CBox::translate(const Vector2D& vec) { - x += vec.x; - y += vec.y; - - return *this; -} - -Vector2D CBox::middle() const { - return Vector2D{x + w / 2.0, y + h / 2.0}; -} - -bool CBox::containsPoint(const Vector2D& vec) const { - return VECINRECT(vec, x, y, x + w, y + h); -} - -bool CBox::empty() const { - return w == 0 || h == 0; -} - -CBox& CBox::applyFromWlr() { - x = m_bWlrBox.x; - y = m_bWlrBox.y; - w = m_bWlrBox.width; - h = m_bWlrBox.height; - - return *this; -} - -CBox& CBox::round() { - float newW = x + w - std::round(x); - float newH = y + h - std::round(y); - x = std::round(x); - y = std::round(y); - w = std::round(newW); - h = std::round(newH); - - return *this; -} - -CBox& CBox::transform(const wl_output_transform t, double w, double h) { - wlr_box_transform(&m_bWlrBox, pWlr(), t, w, h); - applyFromWlr(); - - return *this; -} - -CBox& CBox::addExtents(const SWindowDecorationExtents& e) { - x -= e.topLeft.x; - y -= e.topLeft.y; - w += e.topLeft.x + e.bottomRight.x; - h += e.topLeft.y + e.bottomRight.y; - - return *this; -} - -CBox& CBox::scaleFromCenter(double scale) { - double oldW = w, oldH = h; - - w *= scale; - h *= scale; - - x -= (w - oldW) / 2.0; - y -= (h - oldH) / 2.0; - - return *this; -} - -CBox& CBox::expand(const double& value) { - x -= value; - y -= value; - w += value * 2.0; - h += value * 2.0; - - if (w <= 0 || h <= 0) { - w = 0; - h = 0; - } - - return *this; -} - -CBox& CBox::noNegativeSize() { - w = std::clamp(w, 0.0, std::numeric_limits::infinity()); - h = std::clamp(h, 0.0, std::numeric_limits::infinity()); - - return *this; -} - -CBox CBox::intersection(const CBox& other) const { - const float newX = std::max(x, other.x); - const float newY = std::max(y, other.y); - const float newBottom = std::min(y + h, other.y + other.h); - const float newRight = std::min(x + w, other.x + other.w); - float newW = newRight - newX; - float newH = newBottom - newY; - - if (newW <= 0 || newH <= 0) { - newW = 0; - newH = 0; - } - - return {newX, newY, newW, newH}; -} - -bool CBox::overlaps(const CBox& other) const { - return (other.x + other.w >= x) && (x + w >= other.x) && (other.y + other.h >= y) && (y + h >= other.y); -} - -bool CBox::inside(const CBox& bound) const { - return bound.x < x && bound.y < y && x + w < bound.x + bound.w && y + h < bound.y + bound.h; -} - -CBox CBox::roundInternal() { - float newW = x + w - std::floor(x); - float newH = y + h - std::floor(y); - - return CBox{std::floor(x), std::floor(y), std::floor(newW), std::floor(newH)}; -} - -CBox CBox::copy() const { - return CBox{*this}; -} - -Vector2D CBox::pos() const { - return {x, y}; -} - -Vector2D CBox::size() const { - return {w, h}; -} - -Vector2D CBox::closestPoint(const Vector2D& vec) const { - if (containsPoint(vec)) - return vec; - - Vector2D nv = vec; - nv.x = std::clamp(nv.x, x, x + w); - nv.y = std::clamp(nv.y, y, y + h); - return nv; -} - -SWindowDecorationExtents CBox::extentsFrom(const CBox& small) { - return {{small.x - x, small.y - y}, {w - small.w - (small.x - x), h - small.h - (small.y - y)}}; -} diff --git a/src/helpers/Box.hpp b/src/helpers/Box.hpp deleted file mode 100644 index 57df2154..00000000 --- a/src/helpers/Box.hpp +++ /dev/null @@ -1,92 +0,0 @@ -#pragma once - -#include "Vector2D.hpp" -#include "../SharedDefs.hpp" -#include "../includes.hpp" - -class CBox { - public: - CBox(double x_, double y_, double w_, double h_) { - x = x_; - y = y_; - w = w_; - h = h_; - } - - CBox() { - w = 0; - h = 0; - } - - CBox(const wlr_box& box) { - x = box.x; - y = box.y; - w = box.width; - h = box.height; - } - - CBox(const double d) { - x = d; - y = d; - w = d; - h = d; - } - - CBox(const Vector2D& pos, const Vector2D& size) { - x = pos.x; - y = pos.y; - w = size.x; - h = size.y; - } - - wlr_box wlr(); - wlr_box* pWlr(); - - CBox& applyFromWlr(); - CBox& scale(double scale); - CBox& scaleFromCenter(double scale); - CBox& scale(const Vector2D& scale); - CBox& translate(const Vector2D& vec); - CBox& round(); - CBox& transform(const wl_output_transform t, double w, double h); - CBox& addExtents(const SWindowDecorationExtents& e); - CBox& expand(const double& value); - CBox& noNegativeSize(); - - CBox copy() const; - CBox intersection(const CBox& other) const; - bool overlaps(const CBox& other) const; - bool inside(const CBox& bound) const; - - SWindowDecorationExtents extentsFrom(const CBox&); // this is the big box - - Vector2D middle() const; - Vector2D pos() const; - Vector2D size() const; - Vector2D closestPoint(const Vector2D& vec) const; - - bool containsPoint(const Vector2D& vec) const; - bool empty() const; - - double x = 0, y = 0; - union { - double w; - double width; - }; - union { - double h; - double height; - }; - - double rot = 0; /* rad, ccw */ - - // - bool operator==(const CBox& rhs) const { - return x == rhs.x && y == rhs.y && w == rhs.w && h == rhs.h; - } - - private: - CBox roundInternal(); - - wlr_box m_bWlrBox; -}; diff --git a/src/helpers/Format.hpp b/src/helpers/Format.hpp index b86f44dd..a1ef53f5 100644 --- a/src/helpers/Format.hpp +++ b/src/helpers/Format.hpp @@ -1,7 +1,7 @@ #pragma once #include -#include "Vector2D.hpp" +#include "math/Math.hpp" typedef uint32_t DRMFormat; typedef uint32_t SHMFormat; diff --git a/src/helpers/MiscFunctions.cpp b/src/helpers/MiscFunctions.cpp index 821f3231..654ccf35 100644 --- a/src/helpers/MiscFunctions.cpp +++ b/src/helpers/MiscFunctions.cpp @@ -762,7 +762,7 @@ Vector2D configStringToVector2D(const std::string& VALUE) { if (std::getline(iss, token)) throw std::invalid_argument("Invalid string format"); - return Vector2D(x, y); + return Vector2D((double)x, (double)y); } double normalizeAngleRad(double ang) { diff --git a/src/helpers/MiscFunctions.hpp b/src/helpers/MiscFunctions.hpp index feb0380b..111abba0 100644 --- a/src/helpers/MiscFunctions.hpp +++ b/src/helpers/MiscFunctions.hpp @@ -4,7 +4,7 @@ #include #include #include -#include "Vector2D.hpp" +#include "math/Math.hpp" #include #include diff --git a/src/helpers/Monitor.cpp b/src/helpers/Monitor.cpp index 58687e09..da6da873 100644 --- a/src/helpers/Monitor.cpp +++ b/src/helpers/Monitor.cpp @@ -358,7 +358,9 @@ void CMonitor::addDamage(const CBox* box) { g_pCompositor->scheduleFrameForMonitor(this); } - if (wlr_damage_ring_add_box(&damage, const_cast(box)->pWlr())) + wlr_box damageBox = {(int)box->x, (int)box->y, (int)box->w, (int)box->h}; + + if (wlr_damage_ring_add_box(&damage, &damageBox)) g_pCompositor->scheduleFrameForMonitor(this); } diff --git a/src/helpers/Monitor.hpp b/src/helpers/Monitor.hpp index c59e00ac..b8902197 100644 --- a/src/helpers/Monitor.hpp +++ b/src/helpers/Monitor.hpp @@ -8,7 +8,7 @@ #include #include #include "Timer.hpp" -#include "Region.hpp" +#include "math/Math.hpp" #include #include "signal/Signal.hpp" diff --git a/src/helpers/Region.cpp b/src/helpers/Region.cpp deleted file mode 100644 index 9e572b34..00000000 --- a/src/helpers/Region.cpp +++ /dev/null @@ -1,183 +0,0 @@ -#include "Region.hpp" -extern "C" { -#include -#include -} - -constexpr const int64_t MAX_REGION_SIDE = 10000000; - -CRegion::CRegion() { - pixman_region32_init(&m_rRegion); -} - -CRegion::CRegion(const pixman_region32_t* const ref) { - pixman_region32_init(&m_rRegion); - pixman_region32_copy(&m_rRegion, ref); -} - -CRegion::CRegion(double x, double y, double w, double h) { - pixman_region32_init_rect(&m_rRegion, x, y, w, h); -} - -CRegion::CRegion(wlr_box* box) { - pixman_region32_init_rect(&m_rRegion, box->x, box->y, box->width, box->height); -} - -CRegion::CRegion(const CBox& box) { - pixman_region32_init_rect(&m_rRegion, box.x, box.y, box.w, box.h); -} - -CRegion::CRegion(pixman_box32_t* box) { - pixman_region32_init_rect(&m_rRegion, box->x1, box->y1, box->x2 - box->x1, box->y2 - box->y1); -} - -CRegion::CRegion(const CRegion& other) { - pixman_region32_init(&m_rRegion); - pixman_region32_copy(&m_rRegion, const_cast(&other)->pixman()); -} - -CRegion::CRegion(CRegion&& other) { - pixman_region32_init(&m_rRegion); - pixman_region32_copy(&m_rRegion, other.pixman()); -} - -CRegion::~CRegion() { - pixman_region32_fini(&m_rRegion); -} - -CRegion& CRegion::clear() { - pixman_region32_clear(&m_rRegion); - return *this; -} - -CRegion& CRegion::set(const CRegion& other) { - pixman_region32_copy(&m_rRegion, const_cast(&other)->pixman()); - return *this; -} - -CRegion& CRegion::add(const CRegion& other) { - pixman_region32_union(&m_rRegion, &m_rRegion, const_cast(&other)->pixman()); - return *this; -} - -CRegion& CRegion::add(double x, double y, double w, double h) { - pixman_region32_union_rect(&m_rRegion, &m_rRegion, x, y, w, h); - return *this; -} - -CRegion& CRegion::add(const CBox& other) { - pixman_region32_union_rect(&m_rRegion, &m_rRegion, other.x, other.y, other.w, other.h); - return *this; -} - -CRegion& CRegion::subtract(const CRegion& other) { - pixman_region32_subtract(&m_rRegion, &m_rRegion, const_cast(&other)->pixman()); - return *this; -} - -CRegion& CRegion::intersect(const CRegion& other) { - pixman_region32_intersect(&m_rRegion, &m_rRegion, const_cast(&other)->pixman()); - return *this; -} - -CRegion& CRegion::intersect(double x, double y, double w, double h) { - pixman_region32_intersect_rect(&m_rRegion, &m_rRegion, x, y, w, h); - return *this; -} - -CRegion& CRegion::invert(pixman_box32_t* box) { - pixman_region32_inverse(&m_rRegion, &m_rRegion, box); - return *this; -} - -CRegion& CRegion::invert(const CBox& box) { - pixman_box32 pixmanBox = {box.x, box.y, box.w + box.x, box.h + box.y}; - return this->invert(&pixmanBox); -} - -CRegion& CRegion::translate(const Vector2D& vec) { - pixman_region32_translate(&m_rRegion, vec.x, vec.y); - return *this; -} - -CRegion& CRegion::transform(const wl_output_transform t, double w, double h) { - wlr_region_transform(&m_rRegion, &m_rRegion, t, w, h); - return *this; -} - -CRegion& CRegion::rationalize() { - intersect(CBox{-MAX_REGION_SIDE, -MAX_REGION_SIDE, MAX_REGION_SIDE * 2, MAX_REGION_SIDE * 2}); - return *this; -} - -CRegion CRegion::copy() const { - return CRegion(*this); -} - -CRegion& CRegion::scale(float scale) { - wlr_region_scale(&m_rRegion, &m_rRegion, scale); - return *this; -} - -CRegion& CRegion::scale(const Vector2D& scale) { - wlr_region_scale_xy(&m_rRegion, &m_rRegion, scale.x, scale.y); - return *this; -} - -std::vector CRegion::getRects() const { - std::vector result; - - int rectsNum = 0; - const auto RECTSARR = pixman_region32_rectangles(&m_rRegion, &rectsNum); - - result.assign(RECTSARR, RECTSARR + rectsNum); - - return result; -} - -CBox CRegion::getExtents() { - pixman_box32_t* box = pixman_region32_extents(&m_rRegion); - return {box->x1, box->y1, box->x2 - box->x1, box->y2 - box->y1}; -} - -bool CRegion::containsPoint(const Vector2D& vec) const { - return pixman_region32_contains_point(&m_rRegion, vec.x, vec.y, nullptr); -} - -bool CRegion::empty() const { - return !pixman_region32_not_empty(&m_rRegion); -} - -Vector2D CRegion::closestPoint(const Vector2D& vec) const { - if (containsPoint(vec)) - return vec; - - double bestDist = __FLT_MAX__; - Vector2D leader = vec; - - for (auto& box : getRects()) { - double x = 0, y = 0; - - if (vec.x >= box.x2) - x = box.x2 - 1; - else if (vec.x < box.x1) - x = box.x1; - else - x = vec.x; - - if (vec.y >= box.y2) - y = box.y2 - 1; - else if (vec.y < box.y1) - y = box.y1; - else - y = vec.y; - - double distance = pow(x, 2) + pow(y, 2); - if (distance < bestDist) { - bestDist = distance; - leader = {x, y}; - } - } - - return leader; -} \ No newline at end of file diff --git a/src/helpers/Region.hpp b/src/helpers/Region.hpp deleted file mode 100644 index 42693c21..00000000 --- a/src/helpers/Region.hpp +++ /dev/null @@ -1,69 +0,0 @@ -#pragma once -#include -#include -#include "Vector2D.hpp" -#include "Box.hpp" - -struct wlr_box; - -class CRegion { - public: - /* Create an empty region */ - CRegion(); - /* Create from a reference. Copies, does not own. */ - CRegion(const pixman_region32_t* const ref); - /* Create from a box */ - CRegion(double x, double y, double w, double h); - /* Create from a wlr_box */ - CRegion(wlr_box* box); - /* Create from a CBox */ - CRegion(const CBox& box); - /* Create from a pixman_box32_t */ - CRegion(pixman_box32_t* box); - - CRegion(const CRegion&); - CRegion(CRegion&&); - - ~CRegion(); - - CRegion& operator=(CRegion&& other) { - pixman_region32_copy(&m_rRegion, other.pixman()); - return *this; - } - - CRegion& operator=(CRegion& other) { - pixman_region32_copy(&m_rRegion, other.pixman()); - return *this; - } - - CRegion& clear(); - CRegion& set(const CRegion& other); - CRegion& add(const CRegion& other); - CRegion& add(double x, double y, double w, double h); - CRegion& add(const CBox& other); - CRegion& subtract(const CRegion& other); - CRegion& intersect(const CRegion& other); - CRegion& intersect(double x, double y, double w, double h); - CRegion& translate(const Vector2D& vec); - CRegion& transform(const wl_output_transform t, double w, double h); - CRegion& invert(pixman_box32_t* box); - CRegion& invert(const CBox& box); - CRegion& scale(float scale); - CRegion& scale(const Vector2D& scale); - CRegion& rationalize(); - CBox getExtents(); - bool containsPoint(const Vector2D& vec) const; - bool empty() const; - Vector2D closestPoint(const Vector2D& vec) const; - CRegion copy() const; - - std::vector getRects() const; - - // - pixman_region32_t* pixman() { - return &m_rRegion; - } - - private: - pixman_region32_t m_rRegion; -}; diff --git a/src/helpers/Vector2D.cpp b/src/helpers/Vector2D.cpp deleted file mode 100644 index 6f96d686..00000000 --- a/src/helpers/Vector2D.cpp +++ /dev/null @@ -1,58 +0,0 @@ -#include "Vector2D.hpp" -#include -#include - -Vector2D::Vector2D(double xx, double yy) { - x = xx; - y = yy; -} - -Vector2D::Vector2D() { - x = 0; - y = 0; -} - -Vector2D::Vector2D(const Hyprlang::VEC2& ref) { - x = ref.x; - y = ref.y; -} - -Vector2D::~Vector2D() {} - -double Vector2D::normalize() { - // get max abs - const auto max = std::abs(x) > std::abs(y) ? std::abs(x) : std::abs(y); - - x /= max; - y /= max; - - return max; -} - -Vector2D Vector2D::floor() const { - return Vector2D(std::floor(x), std::floor(y)); -} - -Vector2D Vector2D::round() const { - return Vector2D(std::round(x), std::round(y)); -} - -Vector2D Vector2D::clamp(const Vector2D& min, const Vector2D& max) const { - return Vector2D(std::clamp(this->x, min.x, max.x < min.x ? INFINITY : max.x), std::clamp(this->y, min.y, max.y < min.y ? INFINITY : max.y)); -} - -double Vector2D::distance(const Vector2D& other) const { - return std::sqrt(distanceSq(other)); -} - -double Vector2D::distanceSq(const Vector2D& other) const { - return (x - other.x) * (x - other.x) + (y - other.y) * (y - other.y); -} - -double Vector2D::size() const { - return std::sqrt(x * x + y * y); -} - -Vector2D Vector2D::getComponentMax(const Vector2D& other) const { - return Vector2D(std::max(this->x, other.x), std::max(this->y, other.y)); -} diff --git a/src/helpers/Vector2D.hpp b/src/helpers/Vector2D.hpp deleted file mode 100644 index 0f1440c3..00000000 --- a/src/helpers/Vector2D.hpp +++ /dev/null @@ -1,133 +0,0 @@ -#pragma once - -#include -#include -#include "../macros.hpp" -#include - -class Vector2D { - public: - Vector2D(double, double); - Vector2D(); - ~Vector2D(); - Vector2D(const Hyprlang::VEC2&); - - 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 { - return Vector2D(-this->x, -this->y); - } - Vector2D operator*(const double& a) const { - return Vector2D(this->x * a, this->y * a); - } - Vector2D operator/(const double& 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 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); - } - - bool operator>(const Vector2D& a) const { - return this->x > a.x && this->y > a.y; - } - - bool operator<(const Vector2D& a) const { - return this->x < a.x && this->y < a.y; - } - Vector2D& operator+=(const Vector2D& a) { - this->x += a.x; - this->y += a.y; - return *this; - } - Vector2D& operator-=(const Vector2D& a) { - this->x -= a.x; - this->y -= a.y; - return *this; - } - Vector2D& operator*=(const Vector2D& a) { - this->x *= a.x; - this->y *= a.y; - return *this; - } - Vector2D& operator/=(const Vector2D& a) { - this->x /= a.x; - this->y /= a.y; - return *this; - } - Vector2D& operator*=(const double& a) { - this->x *= a; - this->y *= a; - return *this; - } - Vector2D& operator/=(const double& a) { - this->x /= a; - this->y /= a; - return *this; - } - - double distance(const Vector2D& other) const; - double distanceSq(const Vector2D& other) const; - double size() const; - Vector2D clamp(const Vector2D& min, const Vector2D& max = Vector2D{-1, -1}) const; - - Vector2D floor() const; - Vector2D round() const; - - Vector2D getComponentMax(const Vector2D& other) const; -}; - -/** - format specification - - 'j', as json array - - 'X', same as std::format("{}x{}", vec.x, vec.y) - - number, floating point precision, use `0` to format as integer -*/ -template -struct std::formatter : std::formatter { - bool formatJson = false; - bool formatX = false; - std::string precision = ""; - FORMAT_PARSE(FORMAT_FLAG('j', formatJson) // - FORMAT_FLAG('X', formatX) // - FORMAT_NUMBER(precision), - Vector2D) - - template - auto format(const Vector2D& vec, FormatContext& ctx) const { - std::string formatString = precision.empty() ? "{}" : std::format("{{:.{}f}}", precision); - - if (formatJson) - formatString = std::format("[{0}, {0}]", formatString); - else if (formatX) - formatString = std::format("{0}x{0}", formatString); - else - formatString = std::format("[Vector2D: x: {0}, y: {0}]", formatString); - try { - string buf = std::vformat(formatString, std::make_format_args(vec.x, vec.y)); - return std::format_to(ctx.out(), "{}", buf); - } catch (std::format_error& e) { return std::format_to(ctx.out(), "[{}, {}]", vec.x, vec.y); } - } -}; diff --git a/src/helpers/WLClasses.hpp b/src/helpers/WLClasses.hpp index bcd6bf10..6b25e76d 100644 --- a/src/helpers/WLClasses.hpp +++ b/src/helpers/WLClasses.hpp @@ -8,7 +8,7 @@ #include "AnimatedVariable.hpp" #include "../desktop/WLSurface.hpp" #include "signal/Signal.hpp" -#include "Region.hpp" +#include "math/Math.hpp" class CMonitor; class IPointer; diff --git a/src/helpers/math/Math.cpp b/src/helpers/math/Math.cpp new file mode 100644 index 00000000..df4f1bb5 --- /dev/null +++ b/src/helpers/math/Math.cpp @@ -0,0 +1,220 @@ +#include "Math.hpp" +#include + +Hyprutils::Math::eTransform wlTransformToHyprutils(wl_output_transform t) { + switch (t) { + case WL_OUTPUT_TRANSFORM_NORMAL: return Hyprutils::Math::eTransform::HYPRUTILS_TRANSFORM_NORMAL; + case WL_OUTPUT_TRANSFORM_180: return Hyprutils::Math::eTransform::HYPRUTILS_TRANSFORM_180; + case WL_OUTPUT_TRANSFORM_90: return Hyprutils::Math::eTransform::HYPRUTILS_TRANSFORM_90; + case WL_OUTPUT_TRANSFORM_270: return Hyprutils::Math::eTransform::HYPRUTILS_TRANSFORM_270; + case WL_OUTPUT_TRANSFORM_FLIPPED: return Hyprutils::Math::eTransform::HYPRUTILS_TRANSFORM_FLIPPED; + case WL_OUTPUT_TRANSFORM_FLIPPED_180: return Hyprutils::Math::eTransform::HYPRUTILS_TRANSFORM_FLIPPED_180; + case WL_OUTPUT_TRANSFORM_FLIPPED_270: return Hyprutils::Math::eTransform::HYPRUTILS_TRANSFORM_FLIPPED_270; + case WL_OUTPUT_TRANSFORM_FLIPPED_90: return Hyprutils::Math::eTransform::HYPRUTILS_TRANSFORM_FLIPPED_90; + default: break; + } + return Hyprutils::Math::eTransform::HYPRUTILS_TRANSFORM_NORMAL; +} + +static void matrixIdentity(float mat[9]) { + static const float identity[9] = { + 1.0f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f, 1.0f, + }; + memcpy(mat, identity, sizeof(identity)); +} + +static void matrixMultiply(float mat[9], const float a[9], const float b[9]) { + float product[9]; + + product[0] = a[0] * b[0] + a[1] * b[3] + a[2] * b[6]; + product[1] = a[0] * b[1] + a[1] * b[4] + a[2] * b[7]; + product[2] = a[0] * b[2] + a[1] * b[5] + a[2] * b[8]; + + product[3] = a[3] * b[0] + a[4] * b[3] + a[5] * b[6]; + product[4] = a[3] * b[1] + a[4] * b[4] + a[5] * b[7]; + product[5] = a[3] * b[2] + a[4] * b[5] + a[5] * b[8]; + + product[6] = a[6] * b[0] + a[7] * b[3] + a[8] * b[6]; + product[7] = a[6] * b[1] + a[7] * b[4] + a[8] * b[7]; + product[8] = a[6] * b[2] + a[7] * b[5] + a[8] * b[8]; + + memcpy(mat, product, sizeof(product)); +} + +static void matrixTranspose(float mat[9], const float a[9]) { + float transposition[9] = { + a[0], a[3], a[6], a[1], a[4], a[7], a[2], a[5], a[8], + }; + memcpy(mat, transposition, sizeof(transposition)); +} + +static void matrixTranslate(float mat[9], float x, float y) { + float translate[9] = { + 1.0f, 0.0f, x, 0.0f, 1.0f, y, 0.0f, 0.0f, 1.0f, + }; + wlr_matrix_multiply(mat, mat, translate); +} + +static void matrixScale(float mat[9], float x, float y) { + float scale[9] = { + x, 0.0f, 0.0f, 0.0f, y, 0.0f, 0.0f, 0.0f, 1.0f, + }; + wlr_matrix_multiply(mat, mat, scale); +} + +static void matrixRotate(float mat[9], float rad) { + float rotate[9] = { + cos(rad), -sin(rad), 0.0f, sin(rad), cos(rad), 0.0f, 0.0f, 0.0f, 1.0f, + }; + wlr_matrix_multiply(mat, mat, rotate); +} + +static std::unordered_map> transforms = { + {HYPRUTILS_TRANSFORM_NORMAL, + { + 1.0f, + 0.0f, + 0.0f, + 0.0f, + 1.0f, + 0.0f, + 0.0f, + 0.0f, + 1.0f, + }}, + {HYPRUTILS_TRANSFORM_90, + { + 0.0f, + 1.0f, + 0.0f, + -1.0f, + 0.0f, + 0.0f, + 0.0f, + 0.0f, + 1.0f, + }}, + {HYPRUTILS_TRANSFORM_180, + { + -1.0f, + 0.0f, + 0.0f, + 0.0f, + -1.0f, + 0.0f, + 0.0f, + 0.0f, + 1.0f, + }}, + {HYPRUTILS_TRANSFORM_270, + { + 0.0f, + -1.0f, + 0.0f, + 1.0f, + 0.0f, + 0.0f, + 0.0f, + 0.0f, + 1.0f, + }}, + {HYPRUTILS_TRANSFORM_FLIPPED, + { + -1.0f, + 0.0f, + 0.0f, + 0.0f, + 1.0f, + 0.0f, + 0.0f, + 0.0f, + 1.0f, + }}, + {HYPRUTILS_TRANSFORM_FLIPPED_90, + { + 0.0f, + 1.0f, + 0.0f, + 1.0f, + 0.0f, + 0.0f, + 0.0f, + 0.0f, + 1.0f, + }}, + {HYPRUTILS_TRANSFORM_FLIPPED_180, + { + 1.0f, + 0.0f, + 0.0f, + 0.0f, + -1.0f, + 0.0f, + 0.0f, + 0.0f, + 1.0f, + }}, + {HYPRUTILS_TRANSFORM_FLIPPED_270, + { + 0.0f, + -1.0f, + 0.0f, + -1.0f, + 0.0f, + 0.0f, + 0.0f, + 0.0f, + 1.0f, + }}, +}; + +static void matrixTransform(float mat[9], eTransform transform) { + matrixMultiply(mat, mat, transforms.at(transform).data()); +} + +static void matrixProjection(float mat[9], int width, int height, eTransform transform) { + memset(mat, 0, sizeof(*mat) * 9); + + const float* t = transforms.at(transform).data(); + float x = 2.0f / width; + float y = 2.0f / height; + + // Rotation + reflection + mat[0] = x * t[0]; + mat[1] = x * t[1]; + mat[3] = y * -t[3]; + mat[4] = y * -t[4]; + + // Translation + mat[2] = -copysign(1.0f, mat[0] + mat[1]); + mat[5] = -copysign(1.0f, mat[3] + mat[4]); + + // Identity + mat[8] = 1.0f; +} + +void projectBox(float mat[9], CBox& box, eTransform transform, float rotation, const float projection[9]) { + double x = box.x; + double y = box.y; + double width = box.width; + double height = box.height; + + matrixIdentity(mat); + matrixTranslate(mat, x, y); + + if (rotation != 0) { + matrixTranslate(mat, width / 2, height / 2); + matrixRotate(mat, rotation); + matrixTranslate(mat, -width / 2, -height / 2); + } + + wlr_matrix_scale(mat, width, height); + + if (transform != HYPRUTILS_TRANSFORM_NORMAL) { + matrixTranslate(mat, 0.5, 0.5); + matrixTransform(mat, transform); + matrixTranslate(mat, -0.5, -0.5); + } + + matrixMultiply(mat, projection, mat); +} diff --git a/src/helpers/math/Math.hpp b/src/helpers/math/Math.hpp new file mode 100644 index 00000000..4aa65c93 --- /dev/null +++ b/src/helpers/math/Math.hpp @@ -0,0 +1,11 @@ +#pragma once + +#include + +// includes box and vector as well +#include + +using namespace Hyprutils::Math; + +eTransform wlTransformToHyprutils(wl_output_transform t); +void projectBox(float mat[9], CBox& box, eTransform transform, float rotation, const float projection[9]); diff --git a/src/includes.hpp b/src/includes.hpp index dbae7635..87bd21f8 100644 --- a/src/includes.hpp +++ b/src/includes.hpp @@ -110,6 +110,4 @@ extern "C" { #define XWAYLAND true #endif -#include "helpers/Vector2D.hpp" -#include "helpers/Box.hpp" #include "SharedDefs.hpp" diff --git a/src/layout/DwindleLayout.cpp b/src/layout/DwindleLayout.cpp index 172a157b..cbeaa420 100644 --- a/src/layout/DwindleLayout.cpp +++ b/src/layout/DwindleLayout.cpp @@ -180,9 +180,9 @@ void CHyprDwindleLayout::applyNodeDataToWindow(SDwindleNodeData* pNode, bool for auto calcPos = PWINDOW->m_vPosition; auto calcSize = PWINDOW->m_vSize; - const auto OFFSETTOPLEFT = Vector2D(DISPLAYLEFT ? gapsOut.left : gapsIn.left, DISPLAYTOP ? gapsOut.top : gapsIn.top); + const auto OFFSETTOPLEFT = Vector2D((double)(DISPLAYLEFT ? gapsOut.left : gapsIn.left), (double)(DISPLAYTOP ? gapsOut.top : gapsIn.top)); - const auto OFFSETBOTTOMRIGHT = Vector2D(DISPLAYRIGHT ? gapsOut.right : gapsIn.right, DISPLAYBOTTOM ? gapsOut.bottom : gapsIn.bottom); + const auto OFFSETBOTTOMRIGHT = Vector2D((double)(DISPLAYRIGHT ? gapsOut.right : gapsIn.right), (double)(DISPLAYBOTTOM ? gapsOut.bottom : gapsIn.bottom)); calcPos = calcPos + OFFSETTOPLEFT; calcSize = calcSize - OFFSETTOPLEFT - OFFSETBOTTOMRIGHT; @@ -912,11 +912,11 @@ void CHyprDwindleLayout::moveWindowTo(PHLWINDOW pWindow, const std::string& dir, switch (dir[0]) { case 't': - case 'u': focalPoint = pWindow->m_vPosition + Vector2D{pWindow->m_vSize.x / 2.f, -1}; break; + case 'u': focalPoint = pWindow->m_vPosition + Vector2D{pWindow->m_vSize.x / 2.0, -1.0}; break; case 'd': - case 'b': focalPoint = pWindow->m_vPosition + Vector2D{pWindow->m_vSize.x / 2.f, pWindow->m_vSize.y + 1}; break; - case 'l': focalPoint = pWindow->m_vPosition + Vector2D{-1, pWindow->m_vSize.y / 2.f}; break; - case 'r': focalPoint = pWindow->m_vPosition + Vector2D{pWindow->m_vSize.x + 1, pWindow->m_vSize.y / 2.f}; break; + case 'b': focalPoint = pWindow->m_vPosition + Vector2D{pWindow->m_vSize.x / 2.0, pWindow->m_vSize.y + 1.0}; break; + case 'l': focalPoint = pWindow->m_vPosition + Vector2D{-1.0, pWindow->m_vSize.y / 2.0}; break; + case 'r': focalPoint = pWindow->m_vPosition + Vector2D{pWindow->m_vSize.x + 1.0, pWindow->m_vSize.y / 2.0}; break; default: UNREACHABLE(); } diff --git a/src/layout/IHyprLayout.cpp b/src/layout/IHyprLayout.cpp index b4270bb8..c6a7a66c 100644 --- a/src/layout/IHyprLayout.cpp +++ b/src/layout/IHyprLayout.cpp @@ -428,9 +428,9 @@ void IHyprLayout::onMouseMove(const Vector2D& mousePos) { if (m_eGrabbedCorner == CORNER_TOPLEFT) newPos = newPos - newSize + m_vBeginDragSizeXY; else if (m_eGrabbedCorner == CORNER_TOPRIGHT) - newPos = newPos + Vector2D(0, (m_vBeginDragSizeXY - newSize).y); + newPos = newPos + Vector2D(0.0, (m_vBeginDragSizeXY - newSize).y); else if (m_eGrabbedCorner == CORNER_BOTTOMLEFT) - newPos = newPos + Vector2D((m_vBeginDragSizeXY - newSize).x, 0); + newPos = newPos + Vector2D((m_vBeginDragSizeXY - newSize).x, 0.0); CBox wb = {newPos, newSize}; wb.round(); diff --git a/src/layout/MasterLayout.cpp b/src/layout/MasterLayout.cpp index c5784c74..965c0ed7 100644 --- a/src/layout/MasterLayout.cpp +++ b/src/layout/MasterLayout.cpp @@ -689,9 +689,9 @@ void CHyprMasterLayout::applyNodeDataToWindow(SMasterNodeData* pNode) { auto calcPos = PWINDOW->m_vPosition; auto calcSize = PWINDOW->m_vSize; - const auto OFFSETTOPLEFT = Vector2D(DISPLAYLEFT ? gapsOut.left : gapsIn.left, DISPLAYTOP ? gapsOut.top : gapsIn.top); + const auto OFFSETTOPLEFT = Vector2D((double)(DISPLAYLEFT ? gapsOut.left : gapsIn.left), (double)(DISPLAYTOP ? gapsOut.top : gapsIn.top)); - const auto OFFSETBOTTOMRIGHT = Vector2D(DISPLAYRIGHT ? gapsOut.right : gapsIn.right, DISPLAYBOTTOM ? gapsOut.bottom : gapsIn.bottom); + const auto OFFSETBOTTOMRIGHT = Vector2D((double)(DISPLAYRIGHT ? gapsOut.right : gapsIn.right), (double)(DISPLAYBOTTOM ? gapsOut.bottom : gapsIn.bottom)); calcPos = calcPos + OFFSETTOPLEFT; calcSize = calcSize - OFFSETTOPLEFT - OFFSETBOTTOMRIGHT; diff --git a/src/macros.hpp b/src/macros.hpp index cca088d8..cacfdfea 100644 --- a/src/macros.hpp +++ b/src/macros.hpp @@ -98,3 +98,10 @@ ([]() constexpr -> std::string { return std::string(__FILE__).substr(std::string(__FILE__).find_last_of('/') + 1); })(), err); \ } \ } + +#define HYPRUTILS_FORWARD(ns, name) \ + namespace Hyprutils { \ + namespace ns { \ + class name; \ + } \ + } diff --git a/src/managers/AnimationManager.cpp b/src/managers/AnimationManager.cpp index 74fe4117..9d6668c9 100644 --- a/src/managers/AnimationManager.cpp +++ b/src/managers/AnimationManager.cpp @@ -25,7 +25,7 @@ int wlTick(SP self, void* data) { } CAnimationManager::CAnimationManager() { - std::vector points = {Vector2D(0, 0.75f), Vector2D(0.15f, 1.f)}; + std::vector points = {Vector2D(0.0, 0.75), Vector2D(0.15, 1.0)}; m_mBezierCurves["default"].setup(&points); m_pAnimationTimer = SP(new CEventLoopTimer(std::chrono::microseconds(500), wlTick, nullptr)); @@ -36,7 +36,7 @@ void CAnimationManager::removeAllBeziers() { m_mBezierCurves.clear(); // add the default one - std::vector points = {Vector2D(0, 0.75f), Vector2D(0.15f, 1.f)}; + std::vector points = {Vector2D(0.0, 0.75), Vector2D(0.15, 1.0)}; m_mBezierCurves["default"].setup(&points); } @@ -336,9 +336,9 @@ void CAnimationManager::animationSlide(PHLWINDOW pWindow, std::string force, boo if (force == "bottom") posOffset = Vector2D(GOALPOS.x, PMONITOR->vecPosition.y + PMONITOR->vecSize.y); else if (force == "left") - posOffset = GOALPOS - Vector2D(GOALSIZE.x, 0); + posOffset = GOALPOS - Vector2D(GOALSIZE.x, 0.0); else if (force == "right") - posOffset = GOALPOS + Vector2D(GOALSIZE.x, 0); + posOffset = GOALPOS + Vector2D(GOALSIZE.x, 0.0); else posOffset = Vector2D(GOALPOS.x, PMONITOR->vecPosition.y - GOALSIZE.y); @@ -360,16 +360,16 @@ void CAnimationManager::animationSlide(PHLWINDOW pWindow, std::string force, boo if (DISPLAYBOTTOM && DISPLAYTOP) { if (DISPLAYLEFT && DISPLAYRIGHT) { - posOffset = GOALPOS + Vector2D(0, GOALSIZE.y); + posOffset = GOALPOS + Vector2D(0.0, GOALSIZE.y); } else if (DISPLAYLEFT) { - posOffset = GOALPOS - Vector2D(GOALSIZE.x, 0); + posOffset = GOALPOS - Vector2D(GOALSIZE.x, 0.0); } else { - posOffset = GOALPOS + Vector2D(GOALSIZE.x, 0); + posOffset = GOALPOS + Vector2D(GOALSIZE.x, 0.0); } } else if (DISPLAYTOP) { - posOffset = GOALPOS - Vector2D(0, GOALSIZE.y); + posOffset = GOALPOS - Vector2D(0.0, GOALSIZE.y); } else if (DISPLAYBOTTOM) { - posOffset = GOALPOS + Vector2D(0, GOALSIZE.y); + posOffset = GOALPOS + Vector2D(0.0, GOALSIZE.y); } else { if (MIDPOINT.y > PMONITOR->vecPosition.y + PMONITOR->vecSize.y / 2.f) posOffset = Vector2D(GOALPOS.x, PMONITOR->vecPosition.y + PMONITOR->vecSize.y); diff --git a/src/managers/CursorManager.cpp b/src/managers/CursorManager.cpp index 4430d0f4..daa4f4be 100644 --- a/src/managers/CursorManager.cpp +++ b/src/managers/CursorManager.cpp @@ -149,9 +149,10 @@ void CCursorManager::setXCursor(const std::string& name) { auto image = xcursor->images[0]; - m_vCursorBuffers.emplace_back(std::make_unique(image->buffer, Vector2D{image->width, image->height}, Vector2D{image->hotspot_x, image->hotspot_y})); + m_vCursorBuffers.emplace_back( + std::make_unique(image->buffer, Vector2D{(int)image->width, (int)image->height}, Vector2D{(double)image->hotspot_x, (double)image->hotspot_y})); - g_pPointerManager->setCursorBuffer(getCursorBuffer(), Vector2D{image->hotspot_x, image->hotspot_y} / scale, scale); + g_pPointerManager->setCursorBuffer(getCursorBuffer(), Vector2D{(double)image->hotspot_x, (double)image->hotspot_y} / scale, scale); if (m_vCursorBuffers.size() > 1) wlr_buffer_drop(&m_vCursorBuffers.front()->wlrBuffer.base); @@ -256,8 +257,8 @@ void CCursorManager::setXWaylandCursor() { g_pXWayland->setCursor(cairo_image_surface_get_data(CURSOR.surface), cairo_image_surface_get_stride(CURSOR.surface), {CURSOR.size, CURSOR.size}, {CURSOR.hotspotX, CURSOR.hotspotY}); } else if (const auto XCURSOR = wlr_xcursor_manager_get_xcursor(m_pWLRXCursorMgr, "left_ptr", 1); XCURSOR) { - g_pXWayland->setCursor(XCURSOR->images[0]->buffer, XCURSOR->images[0]->width * 4, {XCURSOR->images[0]->width, XCURSOR->images[0]->height}, - {XCURSOR->images[0]->hotspot_x, XCURSOR->images[0]->hotspot_y}); + g_pXWayland->setCursor(XCURSOR->images[0]->buffer, XCURSOR->images[0]->width * 4, {(int)XCURSOR->images[0]->width, (int)XCURSOR->images[0]->height}, + {(double)XCURSOR->images[0]->hotspot_x, (double)XCURSOR->images[0]->hotspot_y}); } else Debug::log(ERR, "CursorManager: no valid cursor for xwayland"); } diff --git a/src/managers/CursorManager.hpp b/src/managers/CursorManager.hpp index 6fbff636..f983efbb 100644 --- a/src/managers/CursorManager.hpp +++ b/src/managers/CursorManager.hpp @@ -4,7 +4,7 @@ #include #include #include "../includes.hpp" -#include "../helpers/Vector2D.hpp" +#include "../helpers/math/Math.hpp" struct wlr_buffer; struct wlr_xcursor_manager; diff --git a/src/managers/PointerManager.cpp b/src/managers/PointerManager.cpp index 3a28ea8d..05059669 100644 --- a/src/managers/PointerManager.cpp +++ b/src/managers/PointerManager.cpp @@ -577,7 +577,7 @@ Vector2D CPointerManager::transformedHotspot(SP pMonitor) { return {}; // doesn't matter, we have no hw cursor, and this is only for hw cursors return CBox{currentCursorImage.hotspot * pMonitor->scale, {0, 0}} - .transform(wlr_output_transform_invert(pMonitor->transform), pMonitor->output->cursor_swapchain->width, pMonitor->output->cursor_swapchain->height) + .transform(wlTransformToHyprutils(wlr_output_transform_invert(pMonitor->transform)), pMonitor->output->cursor_swapchain->width, pMonitor->output->cursor_swapchain->height) .pos(); } diff --git a/src/managers/PointerManager.hpp b/src/managers/PointerManager.hpp index 1e386797..c3673e16 100644 --- a/src/managers/PointerManager.hpp +++ b/src/managers/PointerManager.hpp @@ -3,8 +3,8 @@ #include "../devices/IPointer.hpp" #include "../devices/ITouch.hpp" #include "../devices/Tablet.hpp" -#include "../helpers/Box.hpp" -#include "../helpers/Region.hpp" +#include "../helpers/math/Math.hpp" +#include "../helpers/math/Math.hpp" #include "../desktop/WLSurface.hpp" #include diff --git a/src/managers/SeatManager.hpp b/src/managers/SeatManager.hpp index 1a1df1d5..43ebe8b5 100644 --- a/src/managers/SeatManager.hpp +++ b/src/managers/SeatManager.hpp @@ -5,7 +5,7 @@ #include "../helpers/WLListener.hpp" #include "../macros.hpp" #include "../helpers/signal/Signal.hpp" -#include "../helpers/Vector2D.hpp" +#include "../helpers/math/Math.hpp" #include "../protocols/types/DataDevice.hpp" #include diff --git a/src/managers/input/InputMethodPopup.hpp b/src/managers/input/InputMethodPopup.hpp index 3151aedb..f6e5c8be 100644 --- a/src/managers/input/InputMethodPopup.hpp +++ b/src/managers/input/InputMethodPopup.hpp @@ -3,7 +3,7 @@ #include "../../helpers/WLListener.hpp" #include "../../desktop/WLSurface.hpp" #include "../../macros.hpp" -#include "../../helpers/Box.hpp" +#include "../../helpers/math/Math.hpp" #include "../../helpers/signal/Signal.hpp" class CInputMethodPopupV2; diff --git a/src/managers/input/Swipe.cpp b/src/managers/input/Swipe.cpp index a605fea7..ead7c5b8 100644 --- a/src/managers/input/Swipe.cpp +++ b/src/managers/input/Swipe.cpp @@ -109,16 +109,16 @@ void CInputManager::endWorkspaceSwipe() { if (PWORKSPACEL) { if (VERTANIMS) - PWORKSPACEL->m_vRenderOffset = Vector2D{0, -YDISTANCE}; + PWORKSPACEL->m_vRenderOffset = Vector2D{0.0, -YDISTANCE}; else - PWORKSPACEL->m_vRenderOffset = Vector2D{-XDISTANCE, 0}; + PWORKSPACEL->m_vRenderOffset = Vector2D{-XDISTANCE, 0.0}; } } else if (PWORKSPACER) { // to right if (VERTANIMS) - PWORKSPACER->m_vRenderOffset = Vector2D{0, YDISTANCE}; + PWORKSPACER->m_vRenderOffset = Vector2D{0.0, YDISTANCE}; else - PWORKSPACER->m_vRenderOffset = Vector2D{XDISTANCE, 0}; + PWORKSPACER->m_vRenderOffset = Vector2D{XDISTANCE, 0.0}; } m_sActiveSwipe.pWorkspaceBegin->m_vRenderOffset = Vector2D(); @@ -141,9 +141,9 @@ void CInputManager::endWorkspaceSwipe() { m_sActiveSwipe.pWorkspaceBegin->m_vRenderOffset.setValue(RENDEROFFSETMIDDLE); if (VERTANIMS) - m_sActiveSwipe.pWorkspaceBegin->m_vRenderOffset = Vector2D(0, YDISTANCE); + m_sActiveSwipe.pWorkspaceBegin->m_vRenderOffset = Vector2D(0.0, YDISTANCE); else - m_sActiveSwipe.pWorkspaceBegin->m_vRenderOffset = Vector2D(XDISTANCE, 0); + m_sActiveSwipe.pWorkspaceBegin->m_vRenderOffset = Vector2D(XDISTANCE, 0.0); m_sActiveSwipe.pWorkspaceBegin->m_fAlpha.setValueAndWarp(1.f); g_pInputManager->unconstrainMouse(); @@ -167,9 +167,9 @@ void CInputManager::endWorkspaceSwipe() { m_sActiveSwipe.pWorkspaceBegin->m_vRenderOffset.setValue(RENDEROFFSETMIDDLE); if (VERTANIMS) - m_sActiveSwipe.pWorkspaceBegin->m_vRenderOffset = Vector2D(0, -YDISTANCE); + m_sActiveSwipe.pWorkspaceBegin->m_vRenderOffset = Vector2D(0.0, -YDISTANCE); else - m_sActiveSwipe.pWorkspaceBegin->m_vRenderOffset = Vector2D(-XDISTANCE, 0); + m_sActiveSwipe.pWorkspaceBegin->m_vRenderOffset = Vector2D(-XDISTANCE, 0.0); m_sActiveSwipe.pWorkspaceBegin->m_fAlpha.setValueAndWarp(1.f); g_pInputManager->unconstrainMouse(); @@ -269,9 +269,9 @@ void CInputManager::updateWorkspaceSwipe(double delta) { g_pHyprRenderer->damageMonitor(m_sActiveSwipe.pMonitor); if (VERTANIMS) - m_sActiveSwipe.pWorkspaceBegin->m_vRenderOffset.setValueAndWarp(Vector2D(0, ((-m_sActiveSwipe.delta) / SWIPEDISTANCE) * YDISTANCE)); + m_sActiveSwipe.pWorkspaceBegin->m_vRenderOffset.setValueAndWarp(Vector2D(0.0, ((-m_sActiveSwipe.delta) / SWIPEDISTANCE) * YDISTANCE)); else - m_sActiveSwipe.pWorkspaceBegin->m_vRenderOffset.setValueAndWarp(Vector2D(((-m_sActiveSwipe.delta) / SWIPEDISTANCE) * XDISTANCE, 0)); + m_sActiveSwipe.pWorkspaceBegin->m_vRenderOffset.setValueAndWarp(Vector2D(((-m_sActiveSwipe.delta) / SWIPEDISTANCE) * XDISTANCE, 0.0)); g_pCompositor->updateWorkspaceWindowDecos(m_sActiveSwipe.pWorkspaceBegin->m_iID); return; @@ -293,11 +293,11 @@ void CInputManager::updateWorkspaceSwipe(double delta) { } if (VERTANIMS) { - PWORKSPACE->m_vRenderOffset.setValueAndWarp(Vector2D(0, ((-m_sActiveSwipe.delta) / SWIPEDISTANCE) * YDISTANCE - YDISTANCE)); - m_sActiveSwipe.pWorkspaceBegin->m_vRenderOffset.setValueAndWarp(Vector2D(0, ((-m_sActiveSwipe.delta) / SWIPEDISTANCE) * YDISTANCE)); + PWORKSPACE->m_vRenderOffset.setValueAndWarp(Vector2D(0.0, ((-m_sActiveSwipe.delta) / SWIPEDISTANCE) * YDISTANCE - YDISTANCE)); + m_sActiveSwipe.pWorkspaceBegin->m_vRenderOffset.setValueAndWarp(Vector2D(0.0, ((-m_sActiveSwipe.delta) / SWIPEDISTANCE) * YDISTANCE)); } else { - PWORKSPACE->m_vRenderOffset.setValueAndWarp(Vector2D(((-m_sActiveSwipe.delta) / SWIPEDISTANCE) * XDISTANCE - XDISTANCE, 0)); - m_sActiveSwipe.pWorkspaceBegin->m_vRenderOffset.setValueAndWarp(Vector2D(((-m_sActiveSwipe.delta) / SWIPEDISTANCE) * XDISTANCE, 0)); + PWORKSPACE->m_vRenderOffset.setValueAndWarp(Vector2D(((-m_sActiveSwipe.delta) / SWIPEDISTANCE) * XDISTANCE - XDISTANCE, 0.0)); + m_sActiveSwipe.pWorkspaceBegin->m_vRenderOffset.setValueAndWarp(Vector2D(((-m_sActiveSwipe.delta) / SWIPEDISTANCE) * XDISTANCE, 0.0)); } g_pCompositor->updateWorkspaceWindowDecos(workspaceIDLeft); @@ -309,9 +309,9 @@ void CInputManager::updateWorkspaceSwipe(double delta) { g_pHyprRenderer->damageMonitor(m_sActiveSwipe.pMonitor); if (VERTANIMS) - m_sActiveSwipe.pWorkspaceBegin->m_vRenderOffset.setValueAndWarp(Vector2D(0, ((-m_sActiveSwipe.delta) / SWIPEDISTANCE) * YDISTANCE)); + m_sActiveSwipe.pWorkspaceBegin->m_vRenderOffset.setValueAndWarp(Vector2D(0.0, ((-m_sActiveSwipe.delta) / SWIPEDISTANCE) * YDISTANCE)); else - m_sActiveSwipe.pWorkspaceBegin->m_vRenderOffset.setValueAndWarp(Vector2D(((-m_sActiveSwipe.delta) / SWIPEDISTANCE) * XDISTANCE, 0)); + m_sActiveSwipe.pWorkspaceBegin->m_vRenderOffset.setValueAndWarp(Vector2D(((-m_sActiveSwipe.delta) / SWIPEDISTANCE) * XDISTANCE, 0.0)); g_pCompositor->updateWorkspaceWindowDecos(m_sActiveSwipe.pWorkspaceBegin->m_iID); return; @@ -333,11 +333,11 @@ void CInputManager::updateWorkspaceSwipe(double delta) { } if (VERTANIMS) { - PWORKSPACE->m_vRenderOffset.setValueAndWarp(Vector2D(0, ((-m_sActiveSwipe.delta) / SWIPEDISTANCE) * YDISTANCE + YDISTANCE)); - m_sActiveSwipe.pWorkspaceBegin->m_vRenderOffset.setValueAndWarp(Vector2D(0, ((-m_sActiveSwipe.delta) / SWIPEDISTANCE) * YDISTANCE)); + PWORKSPACE->m_vRenderOffset.setValueAndWarp(Vector2D(0.0, ((-m_sActiveSwipe.delta) / SWIPEDISTANCE) * YDISTANCE + YDISTANCE)); + m_sActiveSwipe.pWorkspaceBegin->m_vRenderOffset.setValueAndWarp(Vector2D(0.0, ((-m_sActiveSwipe.delta) / SWIPEDISTANCE) * YDISTANCE)); } else { - PWORKSPACE->m_vRenderOffset.setValueAndWarp(Vector2D(((-m_sActiveSwipe.delta) / SWIPEDISTANCE) * XDISTANCE + XDISTANCE, 0)); - m_sActiveSwipe.pWorkspaceBegin->m_vRenderOffset.setValueAndWarp(Vector2D(((-m_sActiveSwipe.delta) / SWIPEDISTANCE) * XDISTANCE, 0)); + PWORKSPACE->m_vRenderOffset.setValueAndWarp(Vector2D(((-m_sActiveSwipe.delta) / SWIPEDISTANCE) * XDISTANCE + XDISTANCE, 0.0)); + m_sActiveSwipe.pWorkspaceBegin->m_vRenderOffset.setValueAndWarp(Vector2D(((-m_sActiveSwipe.delta) / SWIPEDISTANCE) * XDISTANCE, 0.0)); } g_pCompositor->updateWorkspaceWindowDecos(workspaceIDRight); diff --git a/src/managers/input/TextInput.hpp b/src/managers/input/TextInput.hpp index 61a664b9..79e08af9 100644 --- a/src/managers/input/TextInput.hpp +++ b/src/managers/input/TextInput.hpp @@ -2,7 +2,7 @@ #include "../../helpers/WLListener.hpp" #include "../../macros.hpp" -#include "../../helpers/Box.hpp" +#include "../../helpers/math/Math.hpp" #include "../../helpers/signal/Signal.hpp" #include diff --git a/src/protocols/LayerShell.cpp b/src/protocols/LayerShell.cpp index d4b105cb..fd66ba5e 100644 --- a/src/protocols/LayerShell.cpp +++ b/src/protocols/LayerShell.cpp @@ -82,7 +82,7 @@ CLayerShellResource::CLayerShellResource(SP resource_, SPsetSetSize([this](CZwlrLayerSurfaceV1* r, uint32_t x, uint32_t y) { pending.committed |= STATE_SIZE; - pending.desiredSize = {x, y}; + pending.desiredSize = {(int)x, (int)y}; }); resource->setSetAnchor([this](CZwlrLayerSurfaceV1* r, zwlrLayerSurfaceV1Anchor anchor) { diff --git a/src/protocols/LayerShell.hpp b/src/protocols/LayerShell.hpp index 7fa14447..6d29248a 100644 --- a/src/protocols/LayerShell.hpp +++ b/src/protocols/LayerShell.hpp @@ -6,7 +6,7 @@ #include #include "WaylandProtocol.hpp" #include "wlr-layer-shell-unstable-v1.hpp" -#include "../helpers/Vector2D.hpp" +#include "../helpers/math/Math.hpp" #include "../helpers/signal/Signal.hpp" #include "types/SurfaceRole.hpp" diff --git a/src/protocols/PointerConstraints.hpp b/src/protocols/PointerConstraints.hpp index 8a78de99..faf28b32 100644 --- a/src/protocols/PointerConstraints.hpp +++ b/src/protocols/PointerConstraints.hpp @@ -7,8 +7,8 @@ #include #include "WaylandProtocol.hpp" #include "pointer-constraints-unstable-v1.hpp" -#include "../helpers/Vector2D.hpp" -#include "../helpers/Region.hpp" +#include "../helpers/math/Math.hpp" +#include "../helpers/math/Math.hpp" #include "../helpers/signal/Signal.hpp" class CWLSurface; diff --git a/src/protocols/PointerGestures.hpp b/src/protocols/PointerGestures.hpp index 33c2bace..f907a49f 100644 --- a/src/protocols/PointerGestures.hpp +++ b/src/protocols/PointerGestures.hpp @@ -4,7 +4,7 @@ #include #include "WaylandProtocol.hpp" #include "pointer-gestures-unstable-v1.hpp" -#include "../helpers/Vector2D.hpp" +#include "../helpers/math/Math.hpp" class CPointerGestureSwipe { public: diff --git a/src/protocols/RelativePointer.hpp b/src/protocols/RelativePointer.hpp index 93446e85..453ce157 100644 --- a/src/protocols/RelativePointer.hpp +++ b/src/protocols/RelativePointer.hpp @@ -5,7 +5,7 @@ #include #include "WaylandProtocol.hpp" #include "relative-pointer-unstable-v1.hpp" -#include "../helpers/Vector2D.hpp" +#include "../helpers/math/Math.hpp" class CRelativePointer { public: diff --git a/src/protocols/Screencopy.cpp b/src/protocols/Screencopy.cpp index 0c4eac86..8a6285a1 100644 --- a/src/protocols/Screencopy.cpp +++ b/src/protocols/Screencopy.cpp @@ -279,7 +279,7 @@ void CScreencopyProtocolManager::captureOutput(wl_client* client, wl_resource* r } int ow, oh; wlr_output_effective_resolution(PFRAME->pMonitor->output, &ow, &oh); - PFRAME->box.transform(PFRAME->pMonitor->transform, ow, oh).scale(PFRAME->pMonitor->scale).round(); + PFRAME->box.transform(wlTransformToHyprutils(PFRAME->pMonitor->transform), ow, oh).scale(PFRAME->pMonitor->scale).round(); PFRAME->shmStride = FormatUtils::minStride(PSHMINFO, PFRAME->box.w); @@ -556,9 +556,10 @@ bool CScreencopyProtocolManager::copyFrameDmabuf(SScreencopyFrame* frame) { if (!g_pHyprRenderer->beginRender(frame->pMonitor, fakeDamage, RENDER_MODE_TO_BUFFER, frame->buffer.lock(), nullptr, true)) return false; - CBox monbox = CBox{0, 0, frame->pMonitor->vecPixelSize.x, frame->pMonitor->vecPixelSize.y} - .translate({-frame->box.x, -frame->box.y}) // vvvv kinda ass-backwards but that's how I designed the renderer... sigh. - .transform(wlr_output_transform_invert(frame->pMonitor->output->transform), frame->pMonitor->vecPixelSize.x, frame->pMonitor->vecPixelSize.y); + CBox monbox = + CBox{0, 0, frame->pMonitor->vecPixelSize.x, frame->pMonitor->vecPixelSize.y} + .translate({-frame->box.x, -frame->box.y}) // vvvv kinda ass-backwards but that's how I designed the renderer... sigh. + .transform(wlTransformToHyprutils(wlr_output_transform_invert(frame->pMonitor->output->transform)), frame->pMonitor->vecPixelSize.x, frame->pMonitor->vecPixelSize.y); g_pHyprOpenGL->setMonitorTransformEnabled(true); g_pHyprOpenGL->setRenderModifEnabled(false); g_pHyprOpenGL->renderTexture(TEXTURE, &monbox, 1); diff --git a/src/protocols/Tablet.hpp b/src/protocols/Tablet.hpp index c61395c9..58f13c1a 100644 --- a/src/protocols/Tablet.hpp +++ b/src/protocols/Tablet.hpp @@ -5,7 +5,7 @@ #include #include "WaylandProtocol.hpp" #include "tablet-v2.hpp" -#include "../helpers/Vector2D.hpp" +#include "../helpers/math/Math.hpp" class CTablet; class CTabletTool; diff --git a/src/protocols/TextInputV3.hpp b/src/protocols/TextInputV3.hpp index 3959e72b..9f6284dc 100644 --- a/src/protocols/TextInputV3.hpp +++ b/src/protocols/TextInputV3.hpp @@ -7,7 +7,7 @@ #include "WaylandProtocol.hpp" #include "text-input-unstable-v3.hpp" #include "../helpers/signal/Signal.hpp" -#include "../helpers/Box.hpp" +#include "../helpers/math/Math.hpp" class CWLSurfaceResource; diff --git a/src/protocols/ToplevelExport.cpp b/src/protocols/ToplevelExport.cpp index 80f9defa..287538b5 100644 --- a/src/protocols/ToplevelExport.cpp +++ b/src/protocols/ToplevelExport.cpp @@ -202,7 +202,7 @@ void CToplevelExportProtocolManager::captureToplevel(wl_client* client, wl_resou PFRAME->box = {0, 0, (int)(pWindow->m_vRealSize.value().x * PMONITOR->scale), (int)(pWindow->m_vRealSize.value().y * PMONITOR->scale)}; int ow, oh; wlr_output_effective_resolution(PMONITOR->output, &ow, &oh); - PFRAME->box.transform(PMONITOR->transform, ow, oh).round(); + PFRAME->box.transform(wlTransformToHyprutils(PMONITOR->transform), ow, oh).round(); PFRAME->shmStride = FormatUtils::minStride(PSHMINFO, PFRAME->box.w); diff --git a/src/protocols/XDGShell.cpp b/src/protocols/XDGShell.cpp index c16ebb9d..9c56df93 100644 --- a/src/protocols/XDGShell.cpp +++ b/src/protocols/XDGShell.cpp @@ -514,13 +514,13 @@ CXDGPositionerRules::CXDGPositionerRules(SP positioner) static Vector2D pointForAnchor(const CBox& box, const Vector2D& predictionSize, xdgPositionerAnchor anchor) { switch (anchor) { - case XDG_POSITIONER_ANCHOR_TOP: return box.pos() + Vector2D{box.size().x / 2.F - predictionSize.x / 2.F, 0}; - case XDG_POSITIONER_ANCHOR_BOTTOM: return box.pos() + Vector2D{box.size().x / 2.F - predictionSize.x / 2.F, box.size().y}; - case XDG_POSITIONER_ANCHOR_LEFT: return box.pos() + Vector2D{0, box.size().y / 2.F - predictionSize.y / 2.F}; - case XDG_POSITIONER_ANCHOR_RIGHT: return box.pos() + Vector2D{box.size().x, box.size().y / 2.F - predictionSize.y / 2.F}; + case XDG_POSITIONER_ANCHOR_TOP: return box.pos() + Vector2D{box.size().x / 2.0 - predictionSize.x / 2.0, 0.0}; + case XDG_POSITIONER_ANCHOR_BOTTOM: return box.pos() + Vector2D{box.size().x / 2.0 - predictionSize.x / 2.0, box.size().y}; + case XDG_POSITIONER_ANCHOR_LEFT: return box.pos() + Vector2D{0.0, box.size().y / 2.0 - predictionSize.y / 2.0}; + case XDG_POSITIONER_ANCHOR_RIGHT: return box.pos() + Vector2D{box.size().x, box.size().y / 2.F - predictionSize.y / 2.0}; case XDG_POSITIONER_ANCHOR_TOP_LEFT: return box.pos(); - case XDG_POSITIONER_ANCHOR_BOTTOM_LEFT: return box.pos() + Vector2D{0, box.size().y}; - case XDG_POSITIONER_ANCHOR_TOP_RIGHT: return box.pos() + Vector2D{box.size().x, 0}; + case XDG_POSITIONER_ANCHOR_BOTTOM_LEFT: return box.pos() + Vector2D{0.0, box.size().y}; + case XDG_POSITIONER_ANCHOR_TOP_RIGHT: return box.pos() + Vector2D{box.size().x, 0.0}; case XDG_POSITIONER_ANCHOR_BOTTOM_RIGHT: return box.pos() + Vector2D{box.size().x, box.size().y}; default: return box.pos(); } @@ -555,10 +555,10 @@ CBox CXDGPositionerRules::getPosition(const CBox& constraint, const Vector2D& pa }; int edgeCount = countEdges(test); - if (flipX && edgeCount > countEdges(test.copy().translate(Vector2D{-predictedBox.w - state.anchorRect.w, 0}))) - test.translate(Vector2D{-predictedBox.w - state.anchorRect.w, 0}); - if (flipY && edgeCount > countEdges(test.copy().translate(Vector2D{0, -predictedBox.h - state.anchorRect.h}))) - test.translate(Vector2D{0, -predictedBox.h - state.anchorRect.h}); + if (flipX && edgeCount > countEdges(test.copy().translate(Vector2D{-predictedBox.w - state.anchorRect.w, 0.0}))) + test.translate(Vector2D{-predictedBox.w - state.anchorRect.w, 0.0}); + if (flipY && edgeCount > countEdges(test.copy().translate(Vector2D{0.0, -predictedBox.h - state.anchorRect.h}))) + test.translate(Vector2D{0.0, -predictedBox.h - state.anchorRect.h}); success = test.copy().expand(-1).inside(constraint); diff --git a/src/protocols/XDGShell.hpp b/src/protocols/XDGShell.hpp index d60db86a..da551718 100644 --- a/src/protocols/XDGShell.hpp +++ b/src/protocols/XDGShell.hpp @@ -6,8 +6,8 @@ #include #include "WaylandProtocol.hpp" #include "xdg-shell.hpp" -#include "../helpers/Vector2D.hpp" -#include "../helpers/Box.hpp" +#include "../helpers/math/Math.hpp" +#include "../helpers/math/Math.hpp" #include "../helpers/signal/Signal.hpp" #include "types/SurfaceRole.hpp" diff --git a/src/protocols/core/Compositor.cpp b/src/protocols/core/Compositor.cpp index 165da6ee..4bce3f58 100644 --- a/src/protocols/core/Compositor.cpp +++ b/src/protocols/core/Compositor.cpp @@ -421,7 +421,7 @@ CRegion CWLSurfaceResource::accumulateCurrentBufferDamage() { Vector2D trc = current.transform % 2 == 1 ? Vector2D{current.buffer->size.y, current.buffer->size.x} : current.buffer->size; - return surfaceDamage.scale(current.scale).transform(wlr_output_transform_invert(current.transform), trc.x, trc.y).add(current.bufferDamage); + return surfaceDamage.scale(current.scale).transform(wlTransformToHyprutils(wlr_output_transform_invert(current.transform)), trc.x, trc.y).add(current.bufferDamage); } CWLCompositorResource::CWLCompositorResource(SP resource_) : resource(resource_) { diff --git a/src/protocols/core/Compositor.hpp b/src/protocols/core/Compositor.hpp index f50144bf..2f276719 100644 --- a/src/protocols/core/Compositor.hpp +++ b/src/protocols/core/Compositor.hpp @@ -14,7 +14,7 @@ #include "../WaylandProtocol.hpp" #include "wayland.hpp" #include "../../helpers/signal/Signal.hpp" -#include "../../helpers/Region.hpp" +#include "../../helpers/math/Math.hpp" #include "../types/Buffer.hpp" #include "../types/SurfaceRole.hpp" diff --git a/src/protocols/core/DataDevice.hpp b/src/protocols/core/DataDevice.hpp index 5b31559f..22bb9376 100644 --- a/src/protocols/core/DataDevice.hpp +++ b/src/protocols/core/DataDevice.hpp @@ -15,7 +15,7 @@ #include #include "wayland.hpp" #include "../../helpers/signal/Signal.hpp" -#include "../../helpers/Vector2D.hpp" +#include "../../helpers/math/Math.hpp" #include "../types/DataDevice.hpp" class CWLDataDeviceResource; diff --git a/src/protocols/core/Seat.hpp b/src/protocols/core/Seat.hpp index 0b563b8f..09b36056 100644 --- a/src/protocols/core/Seat.hpp +++ b/src/protocols/core/Seat.hpp @@ -15,7 +15,7 @@ #include #include "wayland.hpp" #include "../../helpers/signal/Signal.hpp" -#include "../../helpers/Vector2D.hpp" +#include "../../helpers/math/Math.hpp" constexpr const char* HL_SEAT_NAME = "Hyprland"; diff --git a/src/protocols/core/Shm.hpp b/src/protocols/core/Shm.hpp index 687e2031..70a8b208 100644 --- a/src/protocols/core/Shm.hpp +++ b/src/protocols/core/Shm.hpp @@ -13,7 +13,7 @@ #include "../WaylandProtocol.hpp" #include "wayland.hpp" #include "../types/Buffer.hpp" -#include "../../helpers/Vector2D.hpp" +#include "../../helpers/math/Math.hpp" class CWLSHMPoolResource; diff --git a/src/render/OpenGL.cpp b/src/render/OpenGL.cpp index 5d8d6b83..3178ab8c 100644 --- a/src/render/OpenGL.cpp +++ b/src/render/OpenGL.cpp @@ -916,7 +916,7 @@ void CHyprOpenGLImpl::scissor(const CBox* pBox, bool transform) { int w, h; wlr_output_transformed_resolution(m_RenderData.pMonitor->output, &w, &h); - const auto TR = wlr_output_transform_invert(m_RenderData.pMonitor->transform); + const auto TR = wlTransformToHyprutils(wlr_output_transform_invert(m_RenderData.pMonitor->transform)); newBox.transform(TR, w, h); } @@ -1006,8 +1006,8 @@ void CHyprOpenGLImpl::renderRectWithDamage(CBox* box, const CColor& col, CRegion box = &newBox; float matrix[9]; - wlr_matrix_project_box(matrix, box->pWlr(), wlr_output_transform_invert(!m_bEndFrame ? WL_OUTPUT_TRANSFORM_NORMAL : m_RenderData.pMonitor->transform), newBox.rot, - m_RenderData.monitorProjection.data()); // TODO: write own, don't use WLR here + projectBox(matrix, newBox, wlTransformToHyprutils(wlr_output_transform_invert(!m_bEndFrame ? WL_OUTPUT_TRANSFORM_NORMAL : m_RenderData.pMonitor->transform)), newBox.rot, + m_RenderData.monitorProjection.data()); // TODO: write own, don't use WLR here float glMatrix[9]; wlr_matrix_multiply(glMatrix, m_RenderData.projection, matrix); @@ -1025,7 +1025,7 @@ void CHyprOpenGLImpl::renderRectWithDamage(CBox* box, const CColor& col, CRegion glUniform4f(m_RenderData.pCurrentMonData->m_shQUAD.color, col.r * col.a, col.g * col.a, col.b * col.a, col.a); CBox transformedBox = *box; - transformedBox.transform(wlr_output_transform_invert(m_RenderData.pMonitor->transform), m_RenderData.pMonitor->vecTransformedSize.x, + transformedBox.transform(wlTransformToHyprutils(wlr_output_transform_invert(m_RenderData.pMonitor->transform)), m_RenderData.pMonitor->vecTransformedSize.x, m_RenderData.pMonitor->vecTransformedSize.y); const auto TOPLEFT = Vector2D(transformedBox.x, transformedBox.y); @@ -1097,9 +1097,9 @@ void CHyprOpenGLImpl::renderTextureInternalWithDamage(SP tex, CBox* pB static auto PDT = CConfigValue("debug:damage_tracking"); // get transform - const auto TRANSFORM = wlr_output_transform_invert(!m_bEndFrame ? WL_OUTPUT_TRANSFORM_NORMAL : m_RenderData.pMonitor->transform); + const auto TRANSFORM = wlTransformToHyprutils(wlr_output_transform_invert(!m_bEndFrame ? WL_OUTPUT_TRANSFORM_NORMAL : m_RenderData.pMonitor->transform)); float matrix[9]; - wlr_matrix_project_box(matrix, newBox.pWlr(), TRANSFORM, newBox.rot, m_RenderData.monitorProjection.data()); + projectBox(matrix, newBox, TRANSFORM, newBox.rot, m_RenderData.monitorProjection.data()); float glMatrix[9]; wlr_matrix_multiply(glMatrix, m_RenderData.projection, matrix); @@ -1185,7 +1185,7 @@ void CHyprOpenGLImpl::renderTextureInternalWithDamage(SP tex, CBox* pB } CBox transformedBox = newBox; - transformedBox.transform(wlr_output_transform_invert(m_RenderData.pMonitor->transform), m_RenderData.pMonitor->vecTransformedSize.x, + transformedBox.transform(wlTransformToHyprutils(wlr_output_transform_invert(m_RenderData.pMonitor->transform)), m_RenderData.pMonitor->vecTransformedSize.x, m_RenderData.pMonitor->vecTransformedSize.y); const auto TOPLEFT = Vector2D(transformedBox.x, transformedBox.y); @@ -1260,9 +1260,9 @@ void CHyprOpenGLImpl::renderTexturePrimitive(SP tex, CBox* pBox) { m_RenderData.renderModif.applyToBox(newBox); // get transform - const auto TRANSFORM = wlr_output_transform_invert(!m_bEndFrame ? WL_OUTPUT_TRANSFORM_NORMAL : m_RenderData.pMonitor->transform); + const auto TRANSFORM = wlTransformToHyprutils(wlr_output_transform_invert(!m_bEndFrame ? WL_OUTPUT_TRANSFORM_NORMAL : m_RenderData.pMonitor->transform)); float matrix[9]; - wlr_matrix_project_box(matrix, newBox.pWlr(), TRANSFORM, newBox.rot, m_RenderData.monitorProjection.data()); + projectBox(matrix, newBox, TRANSFORM, newBox.rot, m_RenderData.monitorProjection.data()); float glMatrix[9]; wlr_matrix_multiply(glMatrix, m_RenderData.projection, matrix); @@ -1314,9 +1314,9 @@ void CHyprOpenGLImpl::renderTextureMatte(SP tex, CBox* pBox, CFramebuf m_RenderData.renderModif.applyToBox(newBox); // get transform - const auto TRANSFORM = wlr_output_transform_invert(!m_bEndFrame ? WL_OUTPUT_TRANSFORM_NORMAL : m_RenderData.pMonitor->transform); + const auto TRANSFORM = wlTransformToHyprutils(wlr_output_transform_invert(!m_bEndFrame ? WL_OUTPUT_TRANSFORM_NORMAL : m_RenderData.pMonitor->transform)); float matrix[9]; - wlr_matrix_project_box(matrix, newBox.pWlr(), TRANSFORM, newBox.rot, m_RenderData.monitorProjection.data()); + projectBox(matrix, newBox, TRANSFORM, newBox.rot, m_RenderData.monitorProjection.data()); float glMatrix[9]; wlr_matrix_multiply(glMatrix, m_RenderData.projection, matrix); @@ -1372,10 +1372,10 @@ CFramebuffer* CHyprOpenGLImpl::blurMainFramebufferWithDamage(float a, CRegion* o glDisable(GL_STENCIL_TEST); // get transforms for the full monitor - const auto TRANSFORM = wlr_output_transform_invert(m_RenderData.pMonitor->transform); + const auto TRANSFORM = wlTransformToHyprutils(wlr_output_transform_invert(m_RenderData.pMonitor->transform)); float matrix[9]; CBox MONITORBOX = {0, 0, m_RenderData.pMonitor->vecTransformedSize.x, m_RenderData.pMonitor->vecTransformedSize.y}; - wlr_matrix_project_box(matrix, MONITORBOX.pWlr(), TRANSFORM, 0, m_RenderData.monitorProjection.data()); + projectBox(matrix, MONITORBOX, TRANSFORM, 0, m_RenderData.monitorProjection.data()); float glMatrix[9]; wlr_matrix_multiply(glMatrix, m_RenderData.projection, matrix); @@ -1870,8 +1870,8 @@ void CHyprOpenGLImpl::renderBorder(CBox* box, const CGradientValueData& grad, in round += round == 0 ? 0 : scaledBorderSize; float matrix[9]; - wlr_matrix_project_box(matrix, box->pWlr(), wlr_output_transform_invert(!m_bEndFrame ? WL_OUTPUT_TRANSFORM_NORMAL : m_RenderData.pMonitor->transform), newBox.rot, - m_RenderData.monitorProjection.data()); // TODO: write own, don't use WLR here + projectBox(matrix, newBox, wlTransformToHyprutils(wlr_output_transform_invert(!m_bEndFrame ? WL_OUTPUT_TRANSFORM_NORMAL : m_RenderData.pMonitor->transform)), newBox.rot, + m_RenderData.monitorProjection.data()); // TODO: write own, don't use WLR here float glMatrix[9]; wlr_matrix_multiply(glMatrix, m_RenderData.projection, matrix); @@ -1896,7 +1896,7 @@ void CHyprOpenGLImpl::renderBorder(CBox* box, const CGradientValueData& grad, in glUniform1f(m_RenderData.pCurrentMonData->m_shBORDER1.alpha, a); CBox transformedBox = *box; - transformedBox.transform(wlr_output_transform_invert(m_RenderData.pMonitor->transform), m_RenderData.pMonitor->vecTransformedSize.x, + transformedBox.transform(wlTransformToHyprutils(wlr_output_transform_invert(m_RenderData.pMonitor->transform)), m_RenderData.pMonitor->vecTransformedSize.x, m_RenderData.pMonitor->vecTransformedSize.y); const auto TOPLEFT = Vector2D(transformedBox.x, transformedBox.y); @@ -2176,8 +2176,8 @@ void CHyprOpenGLImpl::renderRoundedShadow(CBox* box, int round, int range, const const auto col = color; float matrix[9]; - wlr_matrix_project_box(matrix, box->pWlr(), wlr_output_transform_invert(!m_bEndFrame ? WL_OUTPUT_TRANSFORM_NORMAL : m_RenderData.pMonitor->transform), newBox.rot, - m_RenderData.monitorProjection.data()); // TODO: write own, don't use WLR here + projectBox(matrix, newBox, wlTransformToHyprutils(wlr_output_transform_invert(!m_bEndFrame ? WL_OUTPUT_TRANSFORM_NORMAL : m_RenderData.pMonitor->transform)), newBox.rot, + m_RenderData.monitorProjection.data()); // TODO: write own, don't use WLR here float glMatrix[9]; wlr_matrix_multiply(glMatrix, m_RenderData.projection, matrix); @@ -2258,7 +2258,7 @@ void CHyprOpenGLImpl::renderMirrored() { CBox monbox = {0, 0, mirrored->vecTransformedSize.x * scale, mirrored->vecTransformedSize.y * scale}; // transform box as it will be drawn on a transformed projection - monbox.transform(mirrored->transform, mirrored->vecTransformedSize.x * scale, mirrored->vecTransformedSize.y * scale); + monbox.transform(wlTransformToHyprutils(mirrored->transform), mirrored->vecTransformedSize.x * scale, mirrored->vecTransformedSize.y * scale); monbox.x = (monitor->vecTransformedSize.x - monbox.w) / 2; monbox.y = (monitor->vecTransformedSize.y - monbox.h) / 2; diff --git a/src/render/OpenGL.hpp b/src/render/OpenGL.hpp index c6e173e5..814b80fe 100644 --- a/src/render/OpenGL.hpp +++ b/src/render/OpenGL.hpp @@ -4,7 +4,7 @@ #include "../helpers/Monitor.hpp" #include "../helpers/Color.hpp" #include "../helpers/Timer.hpp" -#include "../helpers/Region.hpp" +#include "../helpers/math/Math.hpp" #include "../helpers/Format.hpp" #include #include diff --git a/src/render/Renderer.cpp b/src/render/Renderer.cpp index f56fb5d6..d44f4cd5 100644 --- a/src/render/Renderer.cpp +++ b/src/render/Renderer.cpp @@ -1,6 +1,6 @@ #include "Renderer.hpp" #include "../Compositor.hpp" -#include "../helpers/Region.hpp" +#include "../helpers/math/Math.hpp" #include #include "../config/ConfigValue.hpp" #include "../managers/CursorManager.hpp" @@ -1508,15 +1508,15 @@ void CHyprRenderer::setWindowScanoutMode(PHLWINDOW pWindow) { // taken from Sway. // this is just too much of a spaghetti for me to understand -static void applyExclusive(wlr_box& usableArea, uint32_t anchor, int32_t exclusive, int32_t marginTop, int32_t marginRight, int32_t marginBottom, int32_t marginLeft) { +static void applyExclusive(CBox& usableArea, uint32_t anchor, int32_t exclusive, int32_t marginTop, int32_t marginRight, int32_t marginBottom, int32_t marginLeft) { if (exclusive <= 0) { return; } struct { uint32_t singular_anchor; uint32_t anchor_triplet; - int* positive_axis; - int* negative_axis; + double* positive_axis; + double* negative_axis; int margin; } edges[] = { // Top @@ -1640,9 +1640,7 @@ void CHyprRenderer::arrangeLayerArray(CMonitor* pMonitor, const std::vectorgeometry = box; - applyExclusive(*usableArea->pWlr(), PSTATE->anchor, PSTATE->exclusive, PSTATE->margin.top, PSTATE->margin.right, PSTATE->margin.bottom, PSTATE->margin.left); - - usableArea->applyFromWlr(); + applyExclusive(*usableArea, PSTATE->anchor, PSTATE->exclusive, PSTATE->margin.top, PSTATE->margin.right, PSTATE->margin.bottom, PSTATE->margin.left); if (Vector2D{box.width, box.height} != OLDSIZE) ls->layerSurface->configure(box.size()); @@ -1820,7 +1818,7 @@ void CHyprRenderer::damageMirrorsWith(CMonitor* pMonitor, const CRegion& pRegion monbox.y = (monitor->vecTransformedSize.y - monbox.h) / 2; wlr_region_scale(transformed.pixman(), transformed.pixman(), scale); - transformed.transform(mirrored->transform, mirrored->vecPixelSize.x * scale, mirrored->vecPixelSize.y * scale); + transformed.transform(wlTransformToHyprutils(mirrored->transform), mirrored->vecPixelSize.x * scale, mirrored->vecPixelSize.y * scale); transformed.translate(Vector2D(monbox.x, monbox.y)); mirror->addDamage(&transformed); @@ -2234,7 +2232,7 @@ bool CHyprRenderer::applyMonitorRule(CMonitor* pMonitor, SMonitorRule* pMonitorR if (pMonitor->createdByUser) { CBox transformedBox = {0, 0, pMonitor->vecTransformedSize.x, pMonitor->vecTransformedSize.y}; - transformedBox.transform(wlr_output_transform_invert(pMonitor->output->transform), pMonitor->vecTransformedSize.x, pMonitor->vecTransformedSize.y); + transformedBox.transform(wlTransformToHyprutils(wlr_output_transform_invert(pMonitor->output->transform)), pMonitor->vecTransformedSize.x, pMonitor->vecTransformedSize.y); pMonitor->vecPixelSize = Vector2D(transformedBox.width, transformedBox.height); } diff --git a/src/render/Renderer.hpp b/src/render/Renderer.hpp index 6adca72a..8f404c88 100644 --- a/src/render/Renderer.hpp +++ b/src/render/Renderer.hpp @@ -6,7 +6,7 @@ #include "OpenGL.hpp" #include "Renderbuffer.hpp" #include "../helpers/Timer.hpp" -#include "../helpers/Region.hpp" +#include "../helpers/math/Math.hpp" struct SMonitorRule; class CWorkspace; diff --git a/src/render/Texture.cpp b/src/render/Texture.cpp index aef8e4ac..5560db97 100644 --- a/src/render/Texture.cpp +++ b/src/render/Texture.cpp @@ -55,7 +55,7 @@ CTexture::CTexture(wlr_texture* tex) { else m_iType = TEXTURE_EXTERNAL; - m_vSize = Vector2D(tex->width, tex->height); + m_vSize = Vector2D((int)tex->width, (int)tex->height); } CTexture::CTexture(const SDMABUFAttrs& attrs, void* image) { diff --git a/src/render/Texture.hpp b/src/render/Texture.hpp index fa1ca4fe..c80e943d 100644 --- a/src/render/Texture.hpp +++ b/src/render/Texture.hpp @@ -4,7 +4,7 @@ class IWLBuffer; struct SDMABUFAttrs; -class CRegion; +HYPRUTILS_FORWARD(Math, CRegion); enum TEXTURETYPE { TEXTURE_INVALID, // Invalid diff --git a/src/render/decorations/CHyprBorderDecoration.hpp b/src/render/decorations/CHyprBorderDecoration.hpp index 3fa0946e..8ad3263e 100644 --- a/src/render/decorations/CHyprBorderDecoration.hpp +++ b/src/render/decorations/CHyprBorderDecoration.hpp @@ -26,16 +26,16 @@ class CHyprBorderDecoration : public IHyprWindowDecoration { virtual std::string getDisplayName(); private: - SWindowDecorationExtents m_seExtents; - SWindowDecorationExtents m_seReportedExtents; + SBoxExtents m_seExtents; + SBoxExtents m_seReportedExtents; - PHLWINDOWREF m_pWindow; + PHLWINDOWREF m_pWindow; - Vector2D m_vLastWindowPos; - Vector2D m_vLastWindowSize; + Vector2D m_vLastWindowPos; + Vector2D m_vLastWindowSize; - CBox m_bAssignedGeometry = {0}; + CBox m_bAssignedGeometry = {0}; - CBox assignedBoxGlobal(); - bool doesntWantBorders(); + CBox assignedBoxGlobal(); + bool doesntWantBorders(); }; diff --git a/src/render/decorations/CHyprDropShadowDecoration.cpp b/src/render/decorations/CHyprDropShadowDecoration.cpp index fba279cc..6893d78c 100644 --- a/src/render/decorations/CHyprDropShadowDecoration.cpp +++ b/src/render/decorations/CHyprDropShadowDecoration.cpp @@ -130,7 +130,7 @@ void CHyprDropShadowDecoration::draw(CMonitor* pMonitor, float a) { const float SHADOWSCALE = std::clamp(*PSHADOWSCALE, 0.f, 1.f); // scale the box in relation to the center of the box - fullBox.scaleFromCenter(SHADOWSCALE).translate(*PSHADOWOFFSET); + fullBox.scaleFromCenter(SHADOWSCALE).translate({(*PSHADOWOFFSET).x, (*PSHADOWOFFSET).y}); updateWindow(PWINDOW); m_vLastWindowPos += WORKSPACEOFFSET; diff --git a/src/render/decorations/CHyprDropShadowDecoration.hpp b/src/render/decorations/CHyprDropShadowDecoration.hpp index 06319cb7..ecd5a47b 100644 --- a/src/render/decorations/CHyprDropShadowDecoration.hpp +++ b/src/render/decorations/CHyprDropShadowDecoration.hpp @@ -26,14 +26,14 @@ class CHyprDropShadowDecoration : public IHyprWindowDecoration { virtual std::string getDisplayName(); private: - SWindowDecorationExtents m_seExtents; - SWindowDecorationExtents m_seReportedExtents; + SBoxExtents m_seExtents; + SBoxExtents m_seReportedExtents; - PHLWINDOWREF m_pWindow; + PHLWINDOWREF m_pWindow; - Vector2D m_vLastWindowPos; - Vector2D m_vLastWindowSize; + Vector2D m_vLastWindowPos; + Vector2D m_vLastWindowSize; - CBox m_bLastWindowBox = {0}; - CBox m_bLastWindowBoxWithDecos = {0}; + CBox m_bLastWindowBox = {0}; + CBox m_bLastWindowBoxWithDecos = {0}; }; diff --git a/src/render/decorations/CHyprGroupBarDecoration.hpp b/src/render/decorations/CHyprGroupBarDecoration.hpp index 1af24717..bfb15d5c 100644 --- a/src/render/decorations/CHyprGroupBarDecoration.hpp +++ b/src/render/decorations/CHyprGroupBarDecoration.hpp @@ -48,7 +48,7 @@ class CHyprGroupBarDecoration : public IHyprWindowDecoration { virtual std::string getDisplayName(); private: - SWindowDecorationExtents m_seExtents; + SBoxExtents m_seExtents; CBox m_bAssignedBox = {0}; diff --git a/src/render/decorations/DecorationPositioner.cpp b/src/render/decorations/DecorationPositioner.cpp index 17f6d913..d66a5760 100644 --- a/src/render/decorations/DecorationPositioner.cpp +++ b/src/render/decorations/DecorationPositioner.cpp @@ -33,11 +33,11 @@ Vector2D CDecorationPositioner::getEdgeDefinedPoint(uint32_t edges, PHLWINDOW pW if (EDGESNO == 1) { if (TOP) - return wb.pos() + Vector2D{wb.size().x / 2.0, 0}; + return wb.pos() + Vector2D{wb.size().x / 2.0, 0.0}; else if (BOTTOM) return wb.pos() + Vector2D{wb.size().x / 2.0, wb.size().y}; else if (LEFT) - return wb.pos() + Vector2D{0, wb.size().y / 2.0}; + return wb.pos() + Vector2D{0.0, wb.size().y / 2.0}; else if (RIGHT) return wb.pos() + Vector2D{wb.size().x, wb.size().y / 2.0}; UNREACHABLE(); @@ -45,11 +45,11 @@ Vector2D CDecorationPositioner::getEdgeDefinedPoint(uint32_t edges, PHLWINDOW pW if (TOP && LEFT) return wb.pos(); if (TOP && RIGHT) - return wb.pos() + Vector2D{wb.size().x, 0}; + return wb.pos() + Vector2D{wb.size().x, 0.0}; if (BOTTOM && RIGHT) return wb.pos() + wb.size(); if (BOTTOM && LEFT) - return wb.pos() + Vector2D{0, wb.size().y}; + return wb.pos() + Vector2D{0.0, wb.size().y}; UNREACHABLE(); } UNREACHABLE(); @@ -234,26 +234,26 @@ void CDecorationPositioner::onWindowUpdate(PHLWINDOW pWindow) { } else if (LEFT) { pos = wb.pos() - EDGEPOINT - Vector2D{stickyOffsetXL, -stickyOffsetYT}; pos.x -= desiredSize; - size = {desiredSize, wb.size().y + stickyOffsetYB + stickyOffsetYT}; + size = {(double)desiredSize, wb.size().y + stickyOffsetYB + stickyOffsetYT}; if (SOLID) stickyOffsetXL += desiredSize; } else if (RIGHT) { - pos = wb.pos() + Vector2D{wb.size().x, 0} - EDGEPOINT + Vector2D{stickyOffsetXR, -stickyOffsetYT}; - size = {desiredSize, wb.size().y + stickyOffsetYB + stickyOffsetYT}; + pos = wb.pos() + Vector2D{wb.size().x, 0.0} - EDGEPOINT + Vector2D{stickyOffsetXR, -stickyOffsetYT}; + size = {(double)desiredSize, wb.size().y + stickyOffsetYB + stickyOffsetYT}; if (SOLID) stickyOffsetXR += desiredSize; } else if (TOP) { pos = wb.pos() - EDGEPOINT - Vector2D{stickyOffsetXL, stickyOffsetYT}; pos.y -= desiredSize; - size = {wb.size().x + stickyOffsetXL + stickyOffsetXR, desiredSize}; + size = {wb.size().x + stickyOffsetXL + stickyOffsetXR, (double)desiredSize}; if (SOLID) stickyOffsetYT += desiredSize; } else { - pos = wb.pos() + Vector2D{0, wb.size().y} - EDGEPOINT - Vector2D{stickyOffsetXL, stickyOffsetYB}; - size = {wb.size().x + stickyOffsetXL + stickyOffsetXR, desiredSize}; + pos = wb.pos() + Vector2D{0.0, wb.size().y} - EDGEPOINT - Vector2D{stickyOffsetXL, stickyOffsetYB}; + size = {wb.size().x + stickyOffsetXL + stickyOffsetXR, (double)desiredSize}; if (SOLID) stickyOffsetYB += desiredSize; @@ -271,7 +271,7 @@ void CDecorationPositioner::onWindowUpdate(PHLWINDOW pWindow) { } } - if (WINDOWDATA->extents != SWindowDecorationExtents{{stickyOffsetXL + reservedXL, stickyOffsetYT + reservedYT}, {stickyOffsetXR + reservedXR, stickyOffsetYB + reservedYB}}) { + if (WINDOWDATA->extents != SBoxExtents{{stickyOffsetXL + reservedXL, stickyOffsetYT + reservedYT}, {stickyOffsetXR + reservedXR, stickyOffsetYB + reservedYB}}) { WINDOWDATA->extents = {{stickyOffsetXL + reservedXL, stickyOffsetYT + reservedYT}, {stickyOffsetXR + reservedXR, stickyOffsetYB + reservedYB}}; g_pLayoutManager->getCurrentLayout()->recalculateWindow(pWindow); } @@ -286,14 +286,14 @@ void CDecorationPositioner::onWindowMap(PHLWINDOW pWindow) { m_mWindowDatas[pWindow] = {}; } -SWindowDecorationExtents CDecorationPositioner::getWindowDecorationReserved(PHLWINDOW pWindow) { +SBoxExtents CDecorationPositioner::getWindowDecorationReserved(PHLWINDOW pWindow) { try { const auto E = m_mWindowDatas.at(pWindow); return E.reserved; } catch (std::out_of_range& e) { return {}; } } -SWindowDecorationExtents CDecorationPositioner::getWindowDecorationExtents(PHLWINDOW pWindow, bool inputOnly) { +SBoxExtents CDecorationPositioner::getWindowDecorationExtents(PHLWINDOW pWindow, bool inputOnly) { CBox accum = pWindow->getWindowMainSurfaceBox(); for (auto& data : m_vWindowPositioningDatas) { @@ -317,7 +317,7 @@ SWindowDecorationExtents CDecorationPositioner::getWindowDecorationExtents(PHLWI decoBox.translate(EDGEPOINT); } - SWindowDecorationExtents extentsToAdd; + SBoxExtents extentsToAdd; if (decoBox.x < accum.x) extentsToAdd.topLeft.x = accum.x - decoBox.x; @@ -355,7 +355,7 @@ CBox CDecorationPositioner::getBoxWithIncludedDecos(PHLWINDOW pWindow) { decoBox.translate(EDGEPOINT); } - SWindowDecorationExtents extentsToAdd; + SBoxExtents extentsToAdd; if (decoBox.x < accum.x) extentsToAdd.topLeft.x = accum.x - decoBox.x; diff --git a/src/render/decorations/DecorationPositioner.hpp b/src/render/decorations/DecorationPositioner.hpp index 880dc3f8..27e56f0b 100644 --- a/src/render/decorations/DecorationPositioner.hpp +++ b/src/render/decorations/DecorationPositioner.hpp @@ -3,7 +3,7 @@ #include #include #include -#include "../../helpers/Box.hpp" +#include "../../helpers/math/Math.hpp" #include "../../desktop/DesktopTypes.hpp" class CWindow; @@ -37,7 +37,7 @@ struct SDecorationPositioningInfo { eDecorationPositioningPolicy policy = DECORATION_POSITION_ABSOLUTE; uint32_t edges = 0; // enum eDecorationEdges uint32_t priority = 10; // priority, decos will be evaluated high -> low - SWindowDecorationExtents desiredExtents; + SBoxExtents desiredExtents; bool reserved = false; // if true, geometry will use reserved area }; @@ -62,14 +62,14 @@ class CDecorationPositioner { Vector2D getEdgeDefinedPoint(uint32_t edges, PHLWINDOW pWindow); // called on resize, or insert/removal of a new deco - void onWindowUpdate(PHLWINDOW pWindow); - void uncacheDecoration(IHyprWindowDecoration* deco); - SWindowDecorationExtents getWindowDecorationReserved(PHLWINDOW pWindow); - SWindowDecorationExtents getWindowDecorationExtents(PHLWINDOW pWindow, bool inputOnly = false); - CBox getBoxWithIncludedDecos(PHLWINDOW pWindow); - void repositionDeco(IHyprWindowDecoration* deco); - CBox getWindowDecorationBox(IHyprWindowDecoration* deco); - void forceRecalcFor(PHLWINDOW pWindow); + void onWindowUpdate(PHLWINDOW pWindow); + void uncacheDecoration(IHyprWindowDecoration* deco); + SBoxExtents getWindowDecorationReserved(PHLWINDOW pWindow); + SBoxExtents getWindowDecorationExtents(PHLWINDOW pWindow, bool inputOnly = false); + CBox getBoxWithIncludedDecos(PHLWINDOW pWindow); + void repositionDeco(IHyprWindowDecoration* deco); + CBox getWindowDecorationBox(IHyprWindowDecoration* deco); + void forceRecalcFor(PHLWINDOW pWindow); private: struct SWindowPositioningData { @@ -81,10 +81,10 @@ class CDecorationPositioner { }; struct SWindowData { - Vector2D lastWindowSize = {}; - SWindowDecorationExtents reserved = {}; - SWindowDecorationExtents extents = {}; - bool needsRecalc = false; + Vector2D lastWindowSize = {}; + SBoxExtents reserved = {}; + SBoxExtents extents = {}; + bool needsRecalc = false; }; std::map m_mWindowDatas; diff --git a/src/render/decorations/IHyprWindowDecoration.hpp b/src/render/decorations/IHyprWindowDecoration.hpp index 2346106f..a58560f3 100644 --- a/src/render/decorations/IHyprWindowDecoration.hpp +++ b/src/render/decorations/IHyprWindowDecoration.hpp @@ -2,7 +2,7 @@ #include #include "../../defines.hpp" -#include "../../helpers/Region.hpp" +#include "../../helpers/math/Math.hpp" #include "DecorationPositioner.hpp" enum eDecorationType { diff --git a/src/xwayland/XSurface.hpp b/src/xwayland/XSurface.hpp index 0cdac1d5..4e31e88d 100644 --- a/src/xwayland/XSurface.hpp +++ b/src/xwayland/XSurface.hpp @@ -2,7 +2,7 @@ #include "../helpers/WLListener.hpp" #include "../helpers/signal/Signal.hpp" -#include "../helpers/Box.hpp" +#include "../helpers/math/Math.hpp" #include class CWLSurfaceResource; diff --git a/src/xwayland/XWM.cpp b/src/xwayland/XWM.cpp index 7b57de0f..aa38910f 100644 --- a/src/xwayland/XWM.cpp +++ b/src/xwayland/XWM.cpp @@ -1,4 +1,4 @@ -#include "helpers/Vector2D.hpp" +#include "helpers/math/Math.hpp" #ifndef NO_XWAYLAND #include "XWayland.hpp" From 20a465f69d342c5caead27df696d228492ea02e8 Mon Sep 17 00:00:00 2001 From: Lucas Reis Date: Wed, 19 Jun 2024 10:24:28 -0400 Subject: [PATCH 0046/2181] pointer: use software rendering when monitor is mirrored (#6587) * pointer_manager: add lock/unlock software wrappers that receive the raw pointer * monitor: lock/unlock software pointer rendering when adding/removing mirrored screens * use relative path in includes --- src/helpers/Monitor.cpp | 10 ++++++++++ src/managers/PointerManager.cpp | 18 ++++++++++++++++++ src/managers/PointerManager.hpp | 2 ++ 3 files changed, 30 insertions(+) diff --git a/src/helpers/Monitor.cpp b/src/helpers/Monitor.cpp index da6da873..e99e16ef 100644 --- a/src/helpers/Monitor.cpp +++ b/src/helpers/Monitor.cpp @@ -6,6 +6,7 @@ #include "../devices/ITouch.hpp" #include "../protocols/LayerShell.hpp" #include "../protocols/PresentationTime.hpp" +#include "../managers/PointerManager.hpp" #include using namespace Hyprutils::String; @@ -248,6 +249,9 @@ void CMonitor::onDisconnect(bool destroy) { // remove mirror if (pMirrorOf) { pMirrorOf->mirrors.erase(std::find_if(pMirrorOf->mirrors.begin(), pMirrorOf->mirrors.end(), [&](const auto& other) { return other == this; })); + + // unlock software for mirrored monitor + g_pPointerManager->unlockSoftwareForMonitor(pMirrorOf); pMirrorOf = nullptr; } @@ -471,6 +475,9 @@ void CMonitor::setMirror(const std::string& mirrorOf) { if (pMirrorOf) { pMirrorOf->mirrors.erase(std::find_if(pMirrorOf->mirrors.begin(), pMirrorOf->mirrors.end(), [&](const auto& other) { return other == this; })); + + // unlock software for mirrored monitor + g_pPointerManager->unlockSoftwareForMonitor(pMirrorOf); } pMirrorOf = nullptr; @@ -540,6 +547,9 @@ void CMonitor::setMirror(const std::string& mirrorOf) { g_pCompositor->setActiveMonitor(g_pCompositor->m_vMonitors.front().get()); g_pCompositor->sanityCheckWorkspaces(); + + // Software lock mirrored monitor + g_pPointerManager->lockSoftwareForMonitor(PMIRRORMON); } events.modeChanged.emit(); diff --git a/src/managers/PointerManager.cpp b/src/managers/PointerManager.cpp index 05059669..d3da5eff 100644 --- a/src/managers/PointerManager.cpp +++ b/src/managers/PointerManager.cpp @@ -164,6 +164,15 @@ void CPointerManager::unlockSoftwareAll() { updateCursorBackend(); } +void CPointerManager::lockSoftwareForMonitor(CMonitor* Monitor) { + for (auto& m : g_pCompositor->m_vMonitors) { + if (m->ID == Monitor->ID) { + lockSoftwareForMonitor(m); + return; + } + } +} + void CPointerManager::lockSoftwareForMonitor(SP mon) { auto state = stateFor(mon); state->softwareLocks++; @@ -172,6 +181,15 @@ void CPointerManager::lockSoftwareForMonitor(SP mon) { updateCursorBackend(); } +void CPointerManager::unlockSoftwareForMonitor(CMonitor* Monitor) { + for (auto& m : g_pCompositor->m_vMonitors) { + if (m->ID == Monitor->ID) { + unlockSoftwareForMonitor(m); + return; + } + } +} + void CPointerManager::unlockSoftwareForMonitor(SP mon) { auto state = stateFor(mon); state->softwareLocks--; diff --git a/src/managers/PointerManager.hpp b/src/managers/PointerManager.hpp index c3673e16..545b76fb 100644 --- a/src/managers/PointerManager.hpp +++ b/src/managers/PointerManager.hpp @@ -43,6 +43,8 @@ class CPointerManager { void lockSoftwareForMonitor(SP pMonitor); void unlockSoftwareForMonitor(SP pMonitor); + void lockSoftwareForMonitor(CMonitor* pMonitor); + void unlockSoftwareForMonitor(CMonitor* pMonitor); void lockSoftwareAll(); void unlockSoftwareAll(); From 6d21014a50d8e7863b1b25cb5ed19bb1fcba1583 Mon Sep 17 00:00:00 2001 From: Vaxry Date: Wed, 19 Jun 2024 16:28:54 +0200 Subject: [PATCH 0047/2181] core: fix no-pch build --- src/plugins/PluginAPI.hpp | 1 + 1 file changed, 1 insertion(+) diff --git a/src/plugins/PluginAPI.hpp b/src/plugins/PluginAPI.hpp index 83db5f85..4dcf4ba5 100644 --- a/src/plugins/PluginAPI.hpp +++ b/src/plugins/PluginAPI.hpp @@ -29,6 +29,7 @@ Feel like the API is missing something you'd like to use in your plugin? Open an #include #include #include +#include typedef struct { std::string name; From 65f04f265c268d9752d6c2534c2b078d0e54a150 Mon Sep 17 00:00:00 2001 From: Mihai Fufezan Date: Wed, 19 Jun 2024 18:36:50 +0300 Subject: [PATCH 0048/2181] flake.lock: update --- flake.lock | 30 +++++++++++++++--------------- 1 file changed, 15 insertions(+), 15 deletions(-) diff --git a/flake.lock b/flake.lock index 94fc9d90..cb1f7875 100644 --- a/flake.lock +++ b/flake.lock @@ -13,11 +13,11 @@ ] }, "locked": { - "lastModified": 1718368322, - "narHash": "sha256-VfMg3RsnRLQzbq0hFIh1dCM09b5C/F/qPFUOgU/CRi0=", + "lastModified": 1718450675, + "narHash": "sha256-jpsns6buS4bK+1sF8sL8AaixAiCRjA+nldTKvcwmvUs=", "owner": "hyprwm", "repo": "hyprcursor", - "rev": "dd3a853c8239d1c3f3f37de7d2b8ae4b4f3840df", + "rev": "66d5b46ff94efbfa6fa3d1d1b66735f1779c34a6", "type": "github" }, "original": { @@ -38,11 +38,11 @@ ] }, "locked": { - "lastModified": 1691753796, - "narHash": "sha256-zOEwiWoXk3j3+EoF3ySUJmberFewWlagvewDRuWYAso=", + "lastModified": 1714869498, + "narHash": "sha256-vbLVOWvQqo4n1yvkg/Q70VTlPbMmTiCQfNTgcWDCfJM=", "owner": "hyprwm", "repo": "hyprland-protocols", - "rev": "0c2ce70625cb30aef199cb388f99e19a61a6ce03", + "rev": "e06482e0e611130cd1929f75e8c1cf679e57d161", "type": "github" }, "original": { @@ -87,11 +87,11 @@ ] }, "locked": { - "lastModified": 1718271409, - "narHash": "sha256-8KvVqtApNt4FWTdn1TqVvw00rpqyG9UuUPA2ilPVD1U=", + "lastModified": 1718804078, + "narHash": "sha256-CqRZne63BpYlPd/i8lXV0UInUt59oKogiwdVtBRHt60=", "owner": "hyprwm", "repo": "hyprutils", - "rev": "8e10e0626fb26a14b859b3811b6ed7932400c86e", + "rev": "4f1351295c55a8f51219b25aa4a6497a067989d0", "type": "github" }, "original": { @@ -125,11 +125,11 @@ }, "nixpkgs": { "locked": { - "lastModified": 1718318537, - "narHash": "sha256-4Zu0RYRcAY/VWuu6awwq4opuiD//ahpc2aFHg2CWqFY=", + "lastModified": 1718530797, + "narHash": "sha256-pup6cYwtgvzDpvpSCFh1TEUjw2zkNpk8iolbKnyFmmU=", "owner": "NixOS", "repo": "nixpkgs", - "rev": "e9ee548d90ff586a6471b4ae80ae9cfcbceb3420", + "rev": "b60ebf54c15553b393d144357375ea956f89e9a9", "type": "github" }, "original": { @@ -179,11 +179,11 @@ ] }, "locked": { - "lastModified": 1718272114, - "narHash": "sha256-KsX7sAwkEFpXiwyjt0HGTnnrUU58wW1jlzj5IA/LRz8=", + "lastModified": 1718619174, + "narHash": "sha256-FWW68AVYmB91ZDQnhLMBNCUUTCjb1ZpO2k2KIytHtkA=", "owner": "hyprwm", "repo": "xdg-desktop-portal-hyprland", - "rev": "24be4a26f0706e456fca1b61b8c79f7486a9e86d", + "rev": "c7894aa54f9a7dbd16df5cd24d420c8af22d5623", "type": "github" }, "original": { From def5fcb2128304392e9e76bcc081d088b316a197 Mon Sep 17 00:00:00 2001 From: Vaxry Date: Wed, 19 Jun 2024 18:25:20 +0200 Subject: [PATCH 0049/2181] damageRing: move to hyprland impl A small wlroots utility we were still using. --- src/helpers/DamageRing.cpp | 52 ++++++++++++++++++++++++++++++++++++++ src/helpers/DamageRing.hpp | 22 ++++++++++++++++ src/helpers/Monitor.cpp | 18 +++++-------- src/helpers/Monitor.hpp | 40 ++++++++++++++--------------- src/includes.hpp | 1 - src/render/Renderer.cpp | 16 +++++++----- 6 files changed, 111 insertions(+), 38 deletions(-) create mode 100644 src/helpers/DamageRing.cpp create mode 100644 src/helpers/DamageRing.hpp diff --git a/src/helpers/DamageRing.cpp b/src/helpers/DamageRing.cpp new file mode 100644 index 00000000..093e7ca6 --- /dev/null +++ b/src/helpers/DamageRing.cpp @@ -0,0 +1,52 @@ +#include "DamageRing.hpp" + +void CDamageRing::setSize(const Vector2D& size_) { + if (size_ == size) + return; + + size = size_; + + damageEntire(); +} + +bool CDamageRing::damage(const CRegion& rg) { + CRegion clipped = rg.copy().intersect(CBox{{}, size}); + if (clipped.empty()) + return false; + + current.add(clipped); + return true; +} + +void CDamageRing::damageEntire() { + damage(CBox{{}, size}); +} + +void CDamageRing::rotate() { + previousIdx = (previousIdx + DAMAGE_RING_PREVIOUS_LEN - 1) % DAMAGE_RING_PREVIOUS_LEN; + + previous[previousIdx] = current; + current.clear(); +} + +CRegion CDamageRing::getBufferDamage(int age) { + if (age <= 0 || age > DAMAGE_RING_PREVIOUS_LEN + 1) + return CBox{{}, size}; + + CRegion damage = current; + + for (int i = 0; i < age - 1; ++i) { + int j = (previousIdx + i) % DAMAGE_RING_PREVIOUS_LEN; + damage.add(previous.at(j)); + } + + // don't return a ludicrous amount of rects + if (damage.getRects().size() > 8) + return damage.getExtents(); + + return damage; +} + +bool CDamageRing::hasChanged() { + return !current.empty(); +} diff --git a/src/helpers/DamageRing.hpp b/src/helpers/DamageRing.hpp new file mode 100644 index 00000000..ae85c453 --- /dev/null +++ b/src/helpers/DamageRing.hpp @@ -0,0 +1,22 @@ +#pragma once + +#include "./math/Math.hpp" +#include + +constexpr static int DAMAGE_RING_PREVIOUS_LEN = 2; + +class CDamageRing { + public: + void setSize(const Vector2D& size_); + bool damage(const CRegion& rg); + void damageEntire(); + void rotate(); + CRegion getBufferDamage(int age); + bool hasChanged(); + + private: + Vector2D size; + CRegion current; + std::array previous; + size_t previousIdx = 0; +}; diff --git a/src/helpers/Monitor.cpp b/src/helpers/Monitor.cpp index e99e16ef..7ebd2539 100644 --- a/src/helpers/Monitor.cpp +++ b/src/helpers/Monitor.cpp @@ -17,12 +17,10 @@ int ratHandler(void* data) { } CMonitor::CMonitor() : state(this) { - wlr_damage_ring_init(&damage); + ; } CMonitor::~CMonitor() { - wlr_damage_ring_finish(&damage); - hyprListener_monitorDestroy.removeCallback(); hyprListener_monitorFrame.removeCallback(); hyprListener_monitorStateRequest.removeCallback(); @@ -162,7 +160,7 @@ void CMonitor::onConnect(bool noRule) { if (!state.commit()) Debug::log(WARN, "wlr_output_commit_state failed in CMonitor::onCommit"); - wlr_damage_ring_set_bounds(&damage, vecTransformedSize.x, vecTransformedSize.y); + damage.setSize(vecTransformedSize); Debug::log(LOG, "Added new monitor with name {} at {:j0} with size {:j0}, pointer {:x}", output->name, vecPosition, vecPixelSize, (uintptr_t)output); @@ -345,9 +343,9 @@ void CMonitor::onDisconnect(bool destroy) { void CMonitor::addDamage(const pixman_region32_t* rg) { static auto PZOOMFACTOR = CConfigValue("cursor:zoom_factor"); if (*PZOOMFACTOR != 1.f && g_pCompositor->getMonitorFromCursor() == this) { - wlr_damage_ring_add_whole(&damage); + damage.damageEntire(); g_pCompositor->scheduleFrameForMonitor(this); - } else if (wlr_damage_ring_add(&damage, rg)) + } else if (damage.damage(rg)) g_pCompositor->scheduleFrameForMonitor(this); } @@ -358,13 +356,11 @@ void CMonitor::addDamage(const CRegion* rg) { void CMonitor::addDamage(const CBox* box) { static auto PZOOMFACTOR = CConfigValue("cursor:zoom_factor"); if (*PZOOMFACTOR != 1.f && g_pCompositor->getMonitorFromCursor() == this) { - wlr_damage_ring_add_whole(&damage); + damage.damageEntire(); g_pCompositor->scheduleFrameForMonitor(this); } - wlr_box damageBox = {(int)box->x, (int)box->y, (int)box->w, (int)box->h}; - - if (wlr_damage_ring_add_box(&damage, &damageBox)) + if (damage.damage(*box)) g_pCompositor->scheduleFrameForMonitor(this); } @@ -379,7 +375,7 @@ bool CMonitor::shouldSkipScheduleFrameOnMouseEvent() { // keep requested minimum refresh rate if (shouldSkip && *PMINRR && lastPresentationTimer.getMillis() > 1000 / *PMINRR) { // damage whole screen because some previous cursor box damages were skipped - wlr_damage_ring_add_whole(&damage); + damage.damageEntire(); return false; } diff --git a/src/helpers/Monitor.hpp b/src/helpers/Monitor.hpp index b8902197..8a2acdaf 100644 --- a/src/helpers/Monitor.hpp +++ b/src/helpers/Monitor.hpp @@ -11,6 +11,7 @@ #include "math/Math.hpp" #include #include "signal/Signal.hpp" +#include "DamageRing.hpp" // Enum for the different types of auto directions, e.g. auto-left, auto-up. enum eAutoDirs { @@ -60,33 +61,32 @@ class CMonitor { CMonitor(); ~CMonitor(); - Vector2D vecPosition = Vector2D(-1, -1); // means unset - Vector2D vecXWaylandPosition = Vector2D(-1, -1); // means unset - Vector2D vecSize = Vector2D(0, 0); - Vector2D vecPixelSize = Vector2D(0, 0); - Vector2D vecTransformedSize = Vector2D(0, 0); + Vector2D vecPosition = Vector2D(-1, -1); // means unset + Vector2D vecXWaylandPosition = Vector2D(-1, -1); // means unset + Vector2D vecSize = Vector2D(0, 0); + Vector2D vecPixelSize = Vector2D(0, 0); + Vector2D vecTransformedSize = Vector2D(0, 0); - bool primary = false; + bool primary = false; - uint64_t ID = -1; - PHLWORKSPACE activeWorkspace = nullptr; - PHLWORKSPACE activeSpecialWorkspace = nullptr; - float setScale = 1; // scale set by cfg - float scale = 1; // real scale + uint64_t ID = -1; + PHLWORKSPACE activeWorkspace = nullptr; + PHLWORKSPACE activeSpecialWorkspace = nullptr; + float setScale = 1; // scale set by cfg + float scale = 1; // real scale - std::string szName = ""; - std::string szDescription = ""; - std::string szShortDescription = ""; + std::string szName = ""; + std::string szDescription = ""; + std::string szShortDescription = ""; - Vector2D vecReservedTopLeft = Vector2D(0, 0); - Vector2D vecReservedBottomRight = Vector2D(0, 0); + Vector2D vecReservedTopLeft = Vector2D(0, 0); + Vector2D vecReservedBottomRight = Vector2D(0, 0); - drmModeModeInfo customDrmMode = {}; + drmModeModeInfo customDrmMode = {}; - CMonitorState state; + CMonitorState state; + CDamageRing damage; - // WLR stuff - wlr_damage_ring damage; wlr_output* output = nullptr; float refreshRate = 60; int framesToSkip = 0; diff --git a/src/includes.hpp b/src/includes.hpp index 87bd21f8..afec078a 100644 --- a/src/includes.hpp +++ b/src/includes.hpp @@ -53,7 +53,6 @@ extern "C" { #include #include #include -#include #include #include #include diff --git a/src/render/Renderer.cpp b/src/render/Renderer.cpp index d44f4cd5..b783ab81 100644 --- a/src/render/Renderer.cpp +++ b/src/render/Renderer.cpp @@ -1246,7 +1246,7 @@ void CHyprRenderer::renderMonitor(CMonitor* pMonitor) { clock_gettime(CLOCK_MONOTONIC, &now); // check the damage - bool hasChanged = pMonitor->output->needs_frame || pixman_region32_not_empty(&pMonitor->damage.current); + bool hasChanged = pMonitor->output->needs_frame || pMonitor->damage.hasChanged(); if (!hasChanged && *PDAMAGETRACKINGMODE != DAMAGE_TRACKING_NONE && pMonitor->forceFullFrames == 0 && damageBlinkCleanup == 0) return; @@ -1414,7 +1414,7 @@ void CHyprRenderer::renderMonitor(CMonitor* pMonitor) { pMonitor->state.wlr()->tearing_page_flip = shouldTear; if (!pMonitor->state.commit()) { - wlr_damage_ring_add_whole(&pMonitor->damage); + pMonitor->damage.damageEntire(); return; } @@ -2245,7 +2245,7 @@ bool CHyprRenderer::applyMonitorRule(CMonitor* pMonitor, SMonitorRule* pMonitorR // updato wlroots g_pCompositor->arrangeMonitors(); - wlr_damage_ring_set_bounds(&pMonitor->damage, pMonitor->vecTransformedSize.x, pMonitor->vecTransformedSize.y); + pMonitor->damage.setSize(pMonitor->vecTransformedSize); // Set scale for all surfaces on this monitor, needed for some clients // but not on unsafe state to avoid crashes @@ -2609,13 +2609,15 @@ bool CHyprRenderer::beginRender(CMonitor* pMonitor, CRegion& damage, eRenderMode return true; } + int bufferAge = 0; + if (!buffer) { if (!wlr_output_configure_primary_swapchain(pMonitor->output, pMonitor->state.wlr(), &pMonitor->output->swapchain)) { Debug::log(ERR, "Failed to configure primary swapchain for {}", pMonitor->szName); return false; } - m_pCurrentWlrBuffer = wlr_swapchain_acquire(pMonitor->output->swapchain, nullptr); + m_pCurrentWlrBuffer = wlr_swapchain_acquire(pMonitor->output->swapchain, &bufferAge); if (!m_pCurrentWlrBuffer) { Debug::log(ERR, "Failed to acquire swapchain buffer for {}", pMonitor->szName); return false; @@ -2634,8 +2636,10 @@ bool CHyprRenderer::beginRender(CMonitor* pMonitor, CRegion& damage, eRenderMode return false; } - if (mode == RENDER_MODE_NORMAL) - wlr_damage_ring_rotate_buffer(&pMonitor->damage, m_pCurrentWlrBuffer, damage.pixman()); + if (mode == RENDER_MODE_NORMAL) { + damage = pMonitor->damage.getBufferDamage(bufferAge); + pMonitor->damage.rotate(); + } m_pCurrentRenderbuffer->bind(); if (simple) From c1e21719a2fff2fa9549f00053ac40173da54af9 Mon Sep 17 00:00:00 2001 From: Vaxry Date: Wed, 19 Jun 2024 18:36:40 +0200 Subject: [PATCH 0050/2181] core: avoid bumping hard rlimits, restore on fork ref #6584 --- src/Compositor.cpp | 63 ++++++++++++++------------------- src/Compositor.hpp | 8 +++-- src/managers/KeybindManager.cpp | 1 + 3 files changed, 34 insertions(+), 38 deletions(-) diff --git a/src/Compositor.cpp b/src/Compositor.cpp index 7777a55f..7a1d035d 100644 --- a/src/Compositor.cpp +++ b/src/Compositor.cpp @@ -71,44 +71,35 @@ void handleUserSignal(int sig) { } } -static void bumpNofile() { - unsigned long limit = 1024; - - try { - std::ifstream f("/proc/sys/fs/nr_open"); - if (!f.good()) - limit = 1073741816; - else { - std::string content((std::istreambuf_iterator(f)), (std::istreambuf_iterator())); - f.close(); - - limit = std::stoll(content); - } - - } catch (...) { limit = 1073741816; } - - struct rlimit rlimit_; - if (!getrlimit(RLIMIT_NOFILE, &rlimit_)) - Debug::log(LOG, "Old rlimit: soft -> {}, hard -> {}", rlimit_.rlim_cur, rlimit_.rlim_max); - - if (rlimit_.rlim_max <= 1024) - rlimit_.rlim_max = limit; - - unsigned long oldHardLimit = rlimit_.rlim_max; - - rlimit_.rlim_max = limit; - - if (setrlimit(RLIMIT_NOFILE, &rlimit_) < 0) { - Debug::log(LOG, "Failed bumping NOFILE limits higher, retrying with previous hard."); - rlimit_.rlim_max = oldHardLimit; - rlimit_.rlim_cur = std::clamp((unsigned long)limit, 1UL, (unsigned long)rlimit_.rlim_max); - - if (setrlimit(RLIMIT_NOFILE, &rlimit_) < 0) - Debug::log(LOG, "Failed bumping NOFILE limits higher for the second time."); +void CCompositor::bumpNofile() { + if (!getrlimit(RLIMIT_NOFILE, &m_sOriginalNofile)) + Debug::log(LOG, "Old rlimit: soft -> {}, hard -> {}", m_sOriginalNofile.rlim_cur, m_sOriginalNofile.rlim_max); + else { + Debug::log(ERR, "Failed to get NOFILE rlimits"); + m_sOriginalNofile.rlim_max = 0; + return; } - if (!getrlimit(RLIMIT_NOFILE, &rlimit_)) - Debug::log(LOG, "New rlimit: soft -> {}, hard -> {}", rlimit_.rlim_cur, rlimit_.rlim_max); + rlimit newLimit = m_sOriginalNofile; + + newLimit.rlim_cur = newLimit.rlim_max; + + if (setrlimit(RLIMIT_NOFILE, &newLimit) < 0) { + Debug::log(ERR, "Failed bumping NOFILE limits higher"); + m_sOriginalNofile.rlim_max = 0; + return; + } + + if (!getrlimit(RLIMIT_NOFILE, &newLimit)) + Debug::log(LOG, "New rlimit: soft -> {}, hard -> {}", newLimit.rlim_cur, newLimit.rlim_max); +} + +void CCompositor::restoreNofile() { + if (m_sOriginalNofile.rlim_max <= 0) + return; + + if (setrlimit(RLIMIT_NOFILE, &m_sOriginalNofile) < 0) + Debug::log(ERR, "Failed restoring NOFILE limits"); } CCompositor::CCompositor() { diff --git a/src/Compositor.hpp b/src/Compositor.hpp index 242c3b13..5a1d8a64 100644 --- a/src/Compositor.hpp +++ b/src/Compositor.hpp @@ -3,6 +3,7 @@ #include #include #include +#include #include "defines.hpp" #include "debug/Log.hpp" @@ -81,6 +82,8 @@ class CCompositor { void cleanup(); void createLockFile(); void removeLockFile(); + void bumpNofile(); + void restoreNofile(); WP m_pLastFocus; PHLWINDOWREF m_pLastWindow; @@ -190,8 +193,9 @@ class CCompositor { void initManagers(eManagersInitStage stage); void prepareFallbackOutput(); - uint64_t m_iHyprlandPID = 0; - wl_event_source* m_critSigSource = nullptr; + uint64_t m_iHyprlandPID = 0; + wl_event_source* m_critSigSource = nullptr; + rlimit m_sOriginalNofile = {0}; }; inline std::unique_ptr g_pCompositor; diff --git a/src/managers/KeybindManager.cpp b/src/managers/KeybindManager.cpp index 875ba239..80af767c 100644 --- a/src/managers/KeybindManager.cpp +++ b/src/managers/KeybindManager.cpp @@ -890,6 +890,7 @@ uint64_t CKeybindManager::spawnRaw(std::string args) { } if (child == 0) { // run in child + g_pCompositor->restoreNofile(); sigset_t set; sigemptyset(&set); From d6de248b0d434a382a7036ff04b3f9b367668cb0 Mon Sep 17 00:00:00 2001 From: Przegryw321 <65826466+Przegryw321@users.noreply.github.com> Date: Wed, 19 Jun 2024 23:19:18 +0200 Subject: [PATCH 0051/2181] window: expose pseudotiled state and add param to dispatcher (#6583) * Show pseudotiled state of window in hyprctl clients * Add a window as an optional argument for the pseudo dispatcher * change formatting --- src/debug/HyprCtl.cpp | 31 ++++++++++++++++--------------- src/managers/KeybindManager.cpp | 16 +++++++++++----- 2 files changed, 27 insertions(+), 20 deletions(-) diff --git a/src/debug/HyprCtl.cpp b/src/debug/HyprCtl.cpp index e212ed1c..b0a0c477 100644 --- a/src/debug/HyprCtl.cpp +++ b/src/debug/HyprCtl.cpp @@ -210,6 +210,7 @@ static std::string getWindowData(PHLWINDOW w, eHyprCtlOutputFormat format) { "name": "{}" }}, "floating": {}, + "pseudo": {}, "monitor": {}, "class": "{}", "title": "{}", @@ -228,22 +229,22 @@ static std::string getWindowData(PHLWINDOW w, eHyprCtlOutputFormat format) { }},)#", (uintptr_t)w.get(), (w->m_bIsMapped ? "true" : "false"), (w->isHidden() ? "true" : "false"), (int)w->m_vRealPosition.goal().x, (int)w->m_vRealPosition.goal().y, (int)w->m_vRealSize.goal().x, (int)w->m_vRealSize.goal().y, w->m_pWorkspace ? w->workspaceID() : WORKSPACE_INVALID, - escapeJSONStrings(!w->m_pWorkspace ? "" : w->m_pWorkspace->m_szName), ((int)w->m_bIsFloating == 1 ? "true" : "false"), (int64_t)w->m_iMonitorID, - escapeJSONStrings(w->m_szClass), escapeJSONStrings(w->m_szTitle), escapeJSONStrings(w->m_szInitialClass), escapeJSONStrings(w->m_szInitialTitle), w->getPID(), - ((int)w->m_bIsX11 == 1 ? "true" : "false"), (w->m_bPinned ? "true" : "false"), (w->m_bIsFullscreen ? "true" : "false"), - (w->m_bIsFullscreen ? (w->m_pWorkspace ? (int)w->m_pWorkspace->m_efFullscreenMode : 0) : 0), w->m_bFakeFullscreenState ? "true" : "false", getGroupedData(w, format), - getTagsData(w, format), (uintptr_t)w->m_pSwallowed.lock().get(), getFocusHistoryID(w)); + escapeJSONStrings(!w->m_pWorkspace ? "" : w->m_pWorkspace->m_szName), ((int)w->m_bIsFloating == 1 ? "true" : "false"), (w->m_bIsPseudotiled ? "true" : "false"), + (int64_t)w->m_iMonitorID, escapeJSONStrings(w->m_szClass), escapeJSONStrings(w->m_szTitle), escapeJSONStrings(w->m_szInitialClass), + escapeJSONStrings(w->m_szInitialTitle), w->getPID(), ((int)w->m_bIsX11 == 1 ? "true" : "false"), (w->m_bPinned ? "true" : "false"), + (w->m_bIsFullscreen ? "true" : "false"), (w->m_bIsFullscreen ? (w->m_pWorkspace ? (int)w->m_pWorkspace->m_efFullscreenMode : 0) : 0), + w->m_bFakeFullscreenState ? "true" : "false", getGroupedData(w, format), getTagsData(w, format), (uintptr_t)w->m_pSwallowed.lock().get(), getFocusHistoryID(w)); } else { - return std::format("Window {:x} -> {}:\n\tmapped: {}\n\thidden: {}\n\tat: {},{}\n\tsize: {},{}\n\tworkspace: {} ({})\n\tfloating: {}\n\tmonitor: {}\n\tclass: {}\n\ttitle: " - "{}\n\tinitialClass: {}\n\tinitialTitle: {}\n\tpid: " - "{}\n\txwayland: {}\n\tpinned: " - "{}\n\tfullscreen: {}\n\tfullscreenmode: {}\n\tfakefullscreen: {}\n\tgrouped: {}\n\ttags: {}\n\tswallowing: {:x}\n\tfocusHistoryID: {}\n\n", - (uintptr_t)w.get(), w->m_szTitle, (int)w->m_bIsMapped, (int)w->isHidden(), (int)w->m_vRealPosition.goal().x, (int)w->m_vRealPosition.goal().y, - (int)w->m_vRealSize.goal().x, (int)w->m_vRealSize.goal().y, w->m_pWorkspace ? w->workspaceID() : WORKSPACE_INVALID, - (!w->m_pWorkspace ? "" : w->m_pWorkspace->m_szName), (int)w->m_bIsFloating, (int64_t)w->m_iMonitorID, w->m_szClass, w->m_szTitle, w->m_szInitialClass, - w->m_szInitialTitle, w->getPID(), (int)w->m_bIsX11, (int)w->m_bPinned, (int)w->m_bIsFullscreen, - (w->m_bIsFullscreen ? (w->m_pWorkspace ? w->m_pWorkspace->m_efFullscreenMode : 0) : 0), (int)w->m_bFakeFullscreenState, getGroupedData(w, format), - getTagsData(w, format), (uintptr_t)w->m_pSwallowed.lock().get(), getFocusHistoryID(w)); + return std::format( + "Window {:x} -> {}:\n\tmapped: {}\n\thidden: {}\n\tat: {},{}\n\tsize: {},{}\n\tworkspace: {} ({})\n\tfloating: {}\n\tpseudo: {}\n\tmonitor: {}\n\tclass: {}\n\ttitle: " + "{}\n\tinitialClass: {}\n\tinitialTitle: {}\n\tpid: " + "{}\n\txwayland: {}\n\tpinned: " + "{}\n\tfullscreen: {}\n\tfullscreenmode: {}\n\tfakefullscreen: {}\n\tgrouped: {}\n\ttags: {}\n\tswallowing: {:x}\n\tfocusHistoryID: {}\n\n", + (uintptr_t)w.get(), w->m_szTitle, (int)w->m_bIsMapped, (int)w->isHidden(), (int)w->m_vRealPosition.goal().x, (int)w->m_vRealPosition.goal().y, + (int)w->m_vRealSize.goal().x, (int)w->m_vRealSize.goal().y, w->m_pWorkspace ? w->workspaceID() : WORKSPACE_INVALID, (!w->m_pWorkspace ? "" : w->m_pWorkspace->m_szName), + (int)w->m_bIsFloating, (int)w->m_bIsPseudotiled, (int64_t)w->m_iMonitorID, w->m_szClass, w->m_szTitle, w->m_szInitialClass, w->m_szInitialTitle, w->getPID(), + (int)w->m_bIsX11, (int)w->m_bPinned, (int)w->m_bIsFullscreen, (w->m_bIsFullscreen ? (w->m_pWorkspace ? w->m_pWorkspace->m_efFullscreenMode : 0) : 0), + (int)w->m_bFakeFullscreenState, getGroupedData(w, format), getTagsData(w, format), (uintptr_t)w->m_pSwallowed.lock().get(), getFocusHistoryID(w)); } } diff --git a/src/managers/KeybindManager.cpp b/src/managers/KeybindManager.cpp index 80af767c..e5db8918 100644 --- a/src/managers/KeybindManager.cpp +++ b/src/managers/KeybindManager.cpp @@ -5,6 +5,7 @@ #include "../protocols/ShortcutsInhibit.hpp" #include "../render/decorations/CHyprGroupBarDecoration.hpp" #include "KeybindManager.hpp" +#include "Compositor.hpp" #include "TokenManager.hpp" #include "debug/Log.hpp" #include "helpers/varlist/VarList.hpp" @@ -1017,15 +1018,20 @@ void CKeybindManager::centerWindow(std::string args) { } void CKeybindManager::toggleActivePseudo(std::string args) { - const auto ACTIVEWINDOW = g_pCompositor->m_pLastWindow.lock(); + PHLWINDOW PWINDOW = nullptr; - if (!ACTIVEWINDOW) + if (args != "active" && args.length() > 1) + PWINDOW = g_pCompositor->getWindowByRegex(args); + else + PWINDOW = g_pCompositor->m_pLastWindow.lock(); + + if (!PWINDOW) return; - ACTIVEWINDOW->m_bIsPseudotiled = !ACTIVEWINDOW->m_bIsPseudotiled; + PWINDOW->m_bIsPseudotiled = !PWINDOW->m_bIsPseudotiled; - if (!ACTIVEWINDOW->m_bIsFullscreen) - g_pLayoutManager->getCurrentLayout()->recalculateWindow(ACTIVEWINDOW); + if (!PWINDOW->m_bIsFullscreen) + g_pLayoutManager->getCurrentLayout()->recalculateWindow(PWINDOW); } void CKeybindManager::changeworkspace(std::string args) { From fabc30df52ab5d2c369fc8acd4ff909a6ba3b8ac Mon Sep 17 00:00:00 2001 From: Vaxry Date: Thu, 20 Jun 2024 00:15:18 +0200 Subject: [PATCH 0052/2181] format: include macros for unreachable --- src/helpers/Format.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/src/helpers/Format.cpp b/src/helpers/Format.cpp index 08c3ca63..5251002c 100644 --- a/src/helpers/Format.cpp +++ b/src/helpers/Format.cpp @@ -2,6 +2,7 @@ #include #include "../includes.hpp" #include "debug/Log.hpp" +#include "../macros.hpp" /* DRM formats are LE, while OGL is BE. The two primary formats From 8cf2ca196620bc4431cbab83bfa25314e1e80ad7 Mon Sep 17 00:00:00 2001 From: Vaxry Date: Fri, 21 Jun 2024 15:56:25 +0200 Subject: [PATCH 0053/2181] math: include cstring for memset fixup name too --- src/helpers/math/Math.cpp | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/src/helpers/math/Math.cpp b/src/helpers/math/Math.cpp index df4f1bb5..560f29c9 100644 --- a/src/helpers/math/Math.cpp +++ b/src/helpers/math/Math.cpp @@ -1,5 +1,6 @@ #include "Math.hpp" #include +#include Hyprutils::Math::eTransform wlTransformToHyprutils(wl_output_transform t) { switch (t) { @@ -52,21 +53,21 @@ static void matrixTranslate(float mat[9], float x, float y) { float translate[9] = { 1.0f, 0.0f, x, 0.0f, 1.0f, y, 0.0f, 0.0f, 1.0f, }; - wlr_matrix_multiply(mat, mat, translate); + matrixMultiply(mat, mat, translate); } static void matrixScale(float mat[9], float x, float y) { float scale[9] = { x, 0.0f, 0.0f, 0.0f, y, 0.0f, 0.0f, 0.0f, 1.0f, }; - wlr_matrix_multiply(mat, mat, scale); + matrixMultiply(mat, mat, scale); } static void matrixRotate(float mat[9], float rad) { float rotate[9] = { cos(rad), -sin(rad), 0.0f, sin(rad), cos(rad), 0.0f, 0.0f, 0.0f, 1.0f, }; - wlr_matrix_multiply(mat, mat, rotate); + matrixMultiply(mat, mat, rotate); } static std::unordered_map> transforms = { @@ -208,7 +209,7 @@ void projectBox(float mat[9], CBox& box, eTransform transform, float rotation, c matrixTranslate(mat, -width / 2, -height / 2); } - wlr_matrix_scale(mat, width, height); + matrixScale(mat, width, height); if (transform != HYPRUTILS_TRANSFORM_NORMAL) { matrixTranslate(mat, 0.5, 0.5); From 4a8b13ea4f8e5111390471c9212d10d4d032e837 Mon Sep 17 00:00:00 2001 From: Vaxry Date: Fri, 21 Jun 2024 19:25:34 +0200 Subject: [PATCH 0054/2181] renderer: shrink occlusion rect if blur is used if we are blurring, we cannot be sure whether the occluded region won't be included in the expanded damage. If it is, we'd get dark shimmers. fixes #6547 --- src/render/Renderer.cpp | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/src/render/Renderer.cpp b/src/render/Renderer.cpp index b783ab81..4fc751ff 100644 --- a/src/render/Renderer.cpp +++ b/src/render/Renderer.cpp @@ -2451,9 +2451,14 @@ void CHyprRenderer::setOccludedForMainWorkspace(CRegion& region, PHLWORKSPACE pW } void CHyprRenderer::setOccludedForBackLayers(CRegion& region, PHLWORKSPACE pWorkspace) { - CRegion rg; + CRegion rg; - const auto PMONITOR = g_pCompositor->getMonitorFromID(pWorkspace->m_iMonitorID); + const auto PMONITOR = g_pCompositor->getMonitorFromID(pWorkspace->m_iMonitorID); + + static auto PBLUR = CConfigValue("decoration:blur:enabled"); + static auto PBLURSIZE = CConfigValue("decoration:blur:size"); + static auto PBLURPASSES = CConfigValue("decoration:blur:passes"); + const auto BLURRADIUS = *PBLUR ? (*PBLURPASSES > 10 ? pow(2, 15) : std::clamp(*PBLURSIZE, (int64_t)1, (int64_t)40) * pow(2, *PBLURPASSES)) : 0; for (auto& w : g_pCompositor->m_vWindows) { if (!w->m_bIsMapped || w->isHidden() || w->m_pWorkspace != pWorkspace) @@ -2468,7 +2473,8 @@ void CHyprRenderer::setOccludedForBackLayers(CRegion& region, PHLWORKSPACE pWork CBox box = {POS.x, POS.y, SIZE.x, SIZE.y}; - box.scale(PMONITOR->scale); + box.scale(PMONITOR->scale).expand(-BLURRADIUS); + g_pHyprOpenGL->m_RenderData.renderModif.applyToBox(box); rg.add(box); From fa022901cf2c9acdae9e9a24a68b9148d44f8627 Mon Sep 17 00:00:00 2001 From: Tom Englund Date: Sat, 22 Jun 2024 00:40:45 +0200 Subject: [PATCH 0055/2181] surface: add virtual destructor to surfacerole to avoid undefined behaviour (#6620) * surfacerole: add virtual destructor all classes that will be derived from should have a virtual destructor otherwise deleting an instance via pointer to a base class is undefined behaviour, layershell/xdgshell hits this with std::default_delete in the new sharedptr implentation. * includes: fix missing includes fix missing includes for no precompiled headers builds, and remove a redefiniton of a macro already defined in macros.hpp --- src/managers/CursorManager.hpp | 1 + src/protocols/types/SurfaceRole.hpp | 1 + src/xwayland/XSurface.hpp | 1 + src/xwayland/XWM.hpp | 1 + src/xwayland/XWayland.hpp | 5 ++--- 5 files changed, 6 insertions(+), 3 deletions(-) diff --git a/src/managers/CursorManager.hpp b/src/managers/CursorManager.hpp index f983efbb..3ee98ca6 100644 --- a/src/managers/CursorManager.hpp +++ b/src/managers/CursorManager.hpp @@ -5,6 +5,7 @@ #include #include "../includes.hpp" #include "../helpers/math/Math.hpp" +#include "../helpers/memory/Memory.hpp" struct wlr_buffer; struct wlr_xcursor_manager; diff --git a/src/protocols/types/SurfaceRole.hpp b/src/protocols/types/SurfaceRole.hpp index 05c0ea66..faaf70ee 100644 --- a/src/protocols/types/SurfaceRole.hpp +++ b/src/protocols/types/SurfaceRole.hpp @@ -11,4 +11,5 @@ enum eSurfaceRole { class ISurfaceRole { public: virtual eSurfaceRole role() = 0; + virtual ~ISurfaceRole() = default; }; diff --git a/src/xwayland/XSurface.hpp b/src/xwayland/XSurface.hpp index 4e31e88d..61eee984 100644 --- a/src/xwayland/XSurface.hpp +++ b/src/xwayland/XSurface.hpp @@ -2,6 +2,7 @@ #include "../helpers/WLListener.hpp" #include "../helpers/signal/Signal.hpp" +#include "../helpers/memory/Memory.hpp" #include "../helpers/math/Math.hpp" #include diff --git a/src/xwayland/XWM.hpp b/src/xwayland/XWM.hpp index 6456c71b..88606416 100644 --- a/src/xwayland/XWM.hpp +++ b/src/xwayland/XWM.hpp @@ -1,6 +1,7 @@ #pragma once #include "../helpers/signal/Signal.hpp" +#include "../helpers/memory/Memory.hpp" #include "../helpers/WLListener.hpp" #include "../macros.hpp" diff --git a/src/xwayland/XWayland.hpp b/src/xwayland/XWayland.hpp index c7981251..d1cc4421 100644 --- a/src/xwayland/XWayland.hpp +++ b/src/xwayland/XWayland.hpp @@ -2,6 +2,7 @@ #include #include "../helpers/signal/Signal.hpp" +#include "../helpers/memory/Memory.hpp" #include "XSurface.hpp" @@ -29,10 +30,8 @@ class CXWayland { } events; }; -inline std::unique_ptr g_pXWayland; +inline std::unique_ptr g_pXWayland; -#define HYPRATOM(name) \ - { name, 0 } inline std::unordered_map HYPRATOMS = { HYPRATOM("_NET_SUPPORTED"), HYPRATOM("_NET_SUPPORTING_WM_CHECK"), From 4778afe2e6b4a6f8c7d218ccd8fe7e0bd4d2ee9c Mon Sep 17 00:00:00 2001 From: Ikalco <73481042+ikalco@users.noreply.github.com> Date: Fri, 21 Jun 2024 17:41:23 -0500 Subject: [PATCH 0056/2181] hyprctl: make recv timeout bigger and give error message if it does timeout (#6621) --- hyprctl/main.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/hyprctl/main.cpp b/hyprctl/main.cpp index f5de041b..2bd325e3 100644 --- a/hyprctl/main.cpp +++ b/hyprctl/main.cpp @@ -141,7 +141,7 @@ int rollingRead(const int socket) { int request(std::string arg, int minArgs = 0, bool needRoll = false) { const auto SERVERSOCKET = socket(AF_UNIX, SOCK_STREAM, 0); - auto t = timeval{.tv_sec = 0, .tv_usec = 100000}; + auto t = timeval{.tv_sec = 1, .tv_usec = 0}; setsockopt(SERVERSOCKET, SOL_SOCKET, SO_RCVTIMEO, &t, sizeof(struct timeval)); const auto ARGS = std::count(arg.begin(), arg.end(), ' '); @@ -191,6 +191,8 @@ int request(std::string arg, int minArgs = 0, bool needRoll = false) { sizeWritten = read(SERVERSOCKET, buffer, 8192); if (sizeWritten < 0) { + if (errno == EWOULDBLOCK) + log("Hyprland IPC didn't respond in time\n"); log("Couldn't read (5)"); return 5; } From 0b924f541c744f96d32c9a0d98dcfd90205bab4c Mon Sep 17 00:00:00 2001 From: MariuszTrybus Date: Sat, 22 Jun 2024 17:05:05 +0200 Subject: [PATCH 0057/2181] constraints: Lock surface region when region is empty (#6627) * Pointer constraints: Lock surface region when region is empty * Format code --- src/protocols/PointerConstraints.cpp | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/src/protocols/PointerConstraints.cpp b/src/protocols/PointerConstraints.cpp index c7b78a5b..a17fa6cd 100644 --- a/src/protocols/PointerConstraints.cpp +++ b/src/protocols/PointerConstraints.cpp @@ -165,8 +165,15 @@ SP CPointerConstraint::owner() { } CRegion CPointerConstraint::logicConstraintRegion() { - CRegion rg = region; - const auto SURFBOX = pHLSurface->getSurfaceBoxGlobal(); + CRegion rg = region; + const auto SURFBOX = pHLSurface->getSurfaceBoxGlobal(); + + // if region wasn't set in pointer-constraints request take surface region + if (rg.empty() && SURFBOX.has_value()) { + rg.set(SURFBOX.value()); + return rg; + } + const auto CONSTRAINTPOS = SURFBOX.has_value() ? SURFBOX->pos() : Vector2D{}; rg.translate(CONSTRAINTPOS); return rg; From 7f09646ab8b5b6d9f835681d0af5d7a0dc29d8f1 Mon Sep 17 00:00:00 2001 From: Alexander <51529891+Truenya@users.noreply.github.com> Date: Sun, 23 Jun 2024 00:52:42 +0300 Subject: [PATCH 0058/2181] core: add ability to select previous workspace per monitor (#6598) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Крылов Александр --- src/Compositor.cpp | 3 +- src/config/ConfigManager.cpp | 13 +++-- src/desktop/Workspace.cpp | 20 ++++++-- src/desktop/Workspace.hpp | 34 ++++++------- src/events/Windows.cpp | 3 +- src/helpers/MiscFunctions.cpp | 90 ++++++++++++++++----------------- src/helpers/MiscFunctions.hpp | 9 +++- src/helpers/Monitor.cpp | 25 +++++---- src/macros.hpp | 3 +- src/managers/KeybindManager.cpp | 88 +++++++++++++++----------------- src/managers/input/Swipe.cpp | 12 ++--- 11 files changed, 154 insertions(+), 146 deletions(-) diff --git a/src/Compositor.cpp b/src/Compositor.cpp index 7a1d035d..c607dfb6 100644 --- a/src/Compositor.cpp +++ b/src/Compositor.cpp @@ -1648,8 +1648,7 @@ PHLWORKSPACE CCompositor::getWorkspaceByString(const std::string& str) { } try { - std::string name = ""; - return getWorkspaceByID(getWorkspaceIDFromString(str, name)); + return getWorkspaceByID(getWorkspaceIDNameFromString(str).id); } catch (std::exception& e) { Debug::log(ERR, "Error in getWorkspaceByString, invalid id"); } return nullptr; diff --git a/src/config/ConfigManager.cpp b/src/config/ConfigManager.cpp index 17bbe465..6a1c896c 100644 --- a/src/config/ConfigManager.cpp +++ b/src/config/ConfigManager.cpp @@ -1815,14 +1815,13 @@ std::optional CConfigManager::handleMonitor(const std::string& comm newrule.vrr = std::stoi(ARGS[argno + 1]); argno++; } else if (ARGS[argno] == "workspace") { - std::string name = ""; - int wsId = getWorkspaceIDFromString(ARGS[argno + 1], name); + const auto& [id, name] = getWorkspaceIDNameFromString(ARGS[argno + 1]); SWorkspaceRule wsRule; wsRule.monitor = newrule.name; wsRule.workspaceString = ARGS[argno + 1]; + wsRule.workspaceId = id; wsRule.workspaceName = name; - wsRule.workspaceId = wsId; m_dWorkspaceRules.emplace_back(wsRule); argno++; @@ -2370,11 +2369,11 @@ std::optional CConfigManager::handleBlurLS(const std::string& comma std::optional CConfigManager::handleWorkspaceRules(const std::string& command, const std::string& value) { // This can either be the monitor or the workspace identifier - const auto FIRST_DELIM = value.find_first_of(','); + const auto FIRST_DELIM = value.find_first_of(','); - std::string name = ""; - auto first_ident = trim(value.substr(0, FIRST_DELIM)); - int id = getWorkspaceIDFromString(first_ident, name); + auto first_ident = trim(value.substr(0, FIRST_DELIM)); + + const auto& [id, name] = getWorkspaceIDNameFromString(first_ident); auto rules = value.substr(FIRST_DELIM + 1); SWorkspaceRule wsRule; diff --git a/src/desktop/Workspace.cpp b/src/desktop/Workspace.cpp index 04685bd5..34db914e 100644 --- a/src/desktop/Workspace.cpp +++ b/src/desktop/Workspace.cpp @@ -57,6 +57,13 @@ void CWorkspace::init(PHLWORKSPACE self) { EMIT_HOOK_EVENT("createWorkspace", this); } +SWorkspaceIDName CWorkspace::getPrevWorkspaceIDName(bool perMonitor) const { + if (perMonitor) + return m_sPrevWorkspacePerMonitor; + + return m_sPrevWorkspace; +} + CWorkspace::~CWorkspace() { m_vRenderOffset.unregister(); @@ -196,7 +203,7 @@ PHLWINDOW CWorkspace::getLastFocusedWindow() { void CWorkspace::rememberPrevWorkspace(const PHLWORKSPACE& prev) { if (!prev) { - m_sPrevWorkspace.iID = -1; + m_sPrevWorkspace.id = -1; m_sPrevWorkspace.name = ""; return; } @@ -206,8 +213,13 @@ void CWorkspace::rememberPrevWorkspace(const PHLWORKSPACE& prev) { return; } - m_sPrevWorkspace.iID = prev->m_iID; + m_sPrevWorkspace.id = prev->m_iID; m_sPrevWorkspace.name = prev->m_szName; + + if (prev->m_iMonitorID == m_iMonitorID) { + m_sPrevWorkspacePerMonitor.id = prev->m_iID; + m_sPrevWorkspacePerMonitor.name = prev->m_szName; + } } std::string CWorkspace::getConfigName() { @@ -228,9 +240,7 @@ bool CWorkspace::matchesStaticSelector(const std::string& selector_) { return true; if (isNumber(selector)) { - - std::string wsname = ""; - int wsid = getWorkspaceIDFromString(selector, wsname); + const auto& [wsid, wsname] = getWorkspaceIDNameFromString(selector); if (wsid == WORKSPACE_INVALID) return false; diff --git a/src/desktop/Workspace.hpp b/src/desktop/Workspace.hpp index 17431215..ab3907aa 100644 --- a/src/desktop/Workspace.hpp +++ b/src/desktop/Workspace.hpp @@ -4,6 +4,7 @@ #include #include "../defines.hpp" #include "DesktopTypes.hpp" +#include "helpers/MiscFunctions.hpp" enum eFullscreenMode : int8_t { FULLSCREEN_INVALID = -1, @@ -25,17 +26,14 @@ class CWorkspace { int m_iID = -1; std::string m_szName = ""; uint64_t m_iMonitorID = -1; - // Previous workspace ID is stored during a workspace change, allowing travel + // Previous workspace ID and name is stored during a workspace change, allowing travel // to the previous workspace. - struct SPrevWorkspaceData { - int iID = -1; - std::string name = ""; - } m_sPrevWorkspace; + SWorkspaceIDName m_sPrevWorkspace, m_sPrevWorkspacePerMonitor; - bool m_bHasFullscreenWindow = false; - eFullscreenMode m_efFullscreenMode = FULLSCREEN_FULL; + bool m_bHasFullscreenWindow = false; + eFullscreenMode m_efFullscreenMode = FULLSCREEN_FULL; - wl_array m_wlrCoordinateArr; + wl_array m_wlrCoordinateArr; // for animations CAnimatedVariable m_vRenderOffset; @@ -63,21 +61,23 @@ class CWorkspace { bool m_bPersistent = false; // Inert: destroyed and invalid. If this is true, release the ptr you have. - bool inert(); + bool inert(); - void startAnim(bool in, bool left, bool instant = false); - void setActive(bool on); + void startAnim(bool in, bool left, bool instant = false); + void setActive(bool on); - void moveToMonitor(const int&); + void moveToMonitor(const int&); - PHLWINDOW getLastFocusedWindow(); - void rememberPrevWorkspace(const PHLWORKSPACE& prevWorkspace); + PHLWINDOW getLastFocusedWindow(); + void rememberPrevWorkspace(const PHLWORKSPACE& prevWorkspace); - std::string getConfigName(); + std::string getConfigName(); - bool matchesStaticSelector(const std::string& selector); + bool matchesStaticSelector(const std::string& selector); - void markInert(); + void markInert(); + + SWorkspaceIDName getPrevWorkspaceIDName(bool perMonitor) const; private: void init(PHLWORKSPACE self); diff --git a/src/events/Windows.cpp b/src/events/Windows.cpp index d37ba12b..bb1197e5 100644 --- a/src/events/Windows.cpp +++ b/src/events/Windows.cpp @@ -293,8 +293,7 @@ void Events::listener_mapWindow(void* owner, void* data) { if (WORKSPACEARGS[WORKSPACEARGS.size() - 1].starts_with("silent")) workspaceSilent = true; - std::string requestedWorkspaceName; - const int REQUESTEDWORKSPACEID = getWorkspaceIDFromString(WORKSPACEARGS.join(" ", 0, workspaceSilent ? WORKSPACEARGS.size() - 1 : 0), requestedWorkspaceName); + const auto& [REQUESTEDWORKSPACEID, requestedWorkspaceName] = getWorkspaceIDNameFromString(WORKSPACEARGS.join(" ", 0, workspaceSilent ? WORKSPACEARGS.size() - 1 : 0)); if (REQUESTEDWORKSPACEID != WORKSPACE_INVALID) { auto pWorkspace = g_pCompositor->getWorkspaceByID(REQUESTEDWORKSPACEID); diff --git a/src/helpers/MiscFunctions.cpp b/src/helpers/MiscFunctions.cpp index 654ccf35..aa034254 100644 --- a/src/helpers/MiscFunctions.cpp +++ b/src/helpers/MiscFunctions.cpp @@ -214,37 +214,36 @@ bool isDirection(const char& arg) { return arg == 'l' || arg == 'r' || arg == 'u' || arg == 'd' || arg == 't' || arg == 'b'; } -int getWorkspaceIDFromString(const std::string& in, std::string& outName) { - int result = WORKSPACE_INVALID; +SWorkspaceIDName getWorkspaceIDNameFromString(const std::string& in) { + SWorkspaceIDName result = {WORKSPACE_INVALID, ""}; + if (in.starts_with("special")) { - outName = "special:special"; + result.name = "special:special"; if (in.length() > 8) { const auto NAME = in.substr(8); + const auto WS = g_pCompositor->getWorkspaceByName("special:" + NAME); - const auto WS = g_pCompositor->getWorkspaceByName("special:" + NAME); - - outName = "special:" + NAME; - - return WS ? WS->m_iID : g_pCompositor->getNewSpecialID(); + return {WS ? WS->m_iID : g_pCompositor->getNewSpecialID(), "special:" + NAME}; } - return SPECIAL_WORKSPACE_START; + result.id = SPECIAL_WORKSPACE_START; + return result; } else if (in.starts_with("name:")) { const auto WORKSPACENAME = in.substr(in.find_first_of(':') + 1); const auto WORKSPACE = g_pCompositor->getWorkspaceByName(WORKSPACENAME); if (!WORKSPACE) { - result = g_pCompositor->getNextAvailableNamedWorkspace(); + result.id = g_pCompositor->getNextAvailableNamedWorkspace(); } else { - result = WORKSPACE->m_iID; + result.id = WORKSPACE->m_iID; } - outName = WORKSPACENAME; + result.name = WORKSPACENAME; } else if (in.starts_with("empty")) { const bool same_mon = in.substr(5).contains("m"); const bool next = in.substr(5).contains("n"); if ((same_mon || next) && !g_pCompositor->m_pLastMonitor) { Debug::log(ERR, "Empty monitor workspace on monitor null!"); - return WORKSPACE_INVALID; + return {WORKSPACE_INVALID}; } std::set invalidWSes; @@ -259,41 +258,42 @@ int getWorkspaceIDFromString(const std::string& in, std::string& outName) { int id = next ? g_pCompositor->m_pLastMonitor->activeWorkspaceID() : 0; while (++id < INT_MAX) { const auto PWORKSPACE = g_pCompositor->getWorkspaceByID(id); - if (!invalidWSes.contains(id) && (!PWORKSPACE || g_pCompositor->getWindowsOnWorkspace(id) == 0)) - return id; + if (!invalidWSes.contains(id) && (!PWORKSPACE || g_pCompositor->getWindowsOnWorkspace(id) == 0)) { + result.id = id; + return result; + } } } else if (in.starts_with("prev")) { if (!g_pCompositor->m_pLastMonitor) - return WORKSPACE_INVALID; + return {WORKSPACE_INVALID}; const auto PWORKSPACE = g_pCompositor->m_pLastMonitor->activeWorkspace; if (!valid(PWORKSPACE)) - return WORKSPACE_INVALID; + return {WORKSPACE_INVALID}; - const auto PLASTWORKSPACE = g_pCompositor->getWorkspaceByID(PWORKSPACE->m_sPrevWorkspace.iID); + const auto PLASTWORKSPACE = g_pCompositor->getWorkspaceByID(PWORKSPACE->m_sPrevWorkspace.id); if (!PLASTWORKSPACE) - return WORKSPACE_INVALID; + return {WORKSPACE_INVALID}; - outName = PLASTWORKSPACE->m_szName; - return PLASTWORKSPACE->m_iID; + return {PLASTWORKSPACE->m_iID, PLASTWORKSPACE->m_szName}; } else { if (in[0] == 'r' && (in[1] == '-' || in[1] == '+' || in[1] == '~') && isNumber(in.substr(2))) { bool absolute = in[1] == '~'; if (!g_pCompositor->m_pLastMonitor) { Debug::log(ERR, "Relative monitor workspace on monitor null!"); - return WORKSPACE_INVALID; + return {WORKSPACE_INVALID}; } const auto PLUSMINUSRESULT = getPlusMinusKeywordResult(in.substr(absolute ? 2 : 1), 0); if (!PLUSMINUSRESULT.has_value()) - return WORKSPACE_INVALID; + return {WORKSPACE_INVALID}; - result = (int)PLUSMINUSRESULT.value(); + result.id = (int)PLUSMINUSRESULT.value(); - int remains = (int)result; + int remains = (int)result.id; std::set invalidWSes; @@ -330,13 +330,13 @@ int getWorkspaceIDFromString(const std::string& in, std::string& outName) { // traverse valid workspaces until we reach the remains if ((size_t)remains < namedWSes.size()) { - result = namedWSes[remains]; + result.id = namedWSes[remains]; } else { remains -= namedWSes.size(); - result = 0; + result.id = 0; while (remains >= 0) { - result++; - if (!invalidWSes.contains(result)) { + result.id++; + if (!invalidWSes.contains(result.id)) { remains--; } } @@ -430,14 +430,14 @@ int getWorkspaceIDFromString(const std::string& in, std::string& outName) { finalWSID = curID; } } - result = finalWSID; + result.id = finalWSID; } - const auto PWORKSPACE = g_pCompositor->getWorkspaceByID(result); + const auto PWORKSPACE = g_pCompositor->getWorkspaceByID(result.id); if (PWORKSPACE) - outName = g_pCompositor->getWorkspaceByID(result)->m_szName; + result.name = g_pCompositor->getWorkspaceByID(result.id)->m_szName; else - outName = std::to_string(result); + result.name = std::to_string(result.id); } else if ((in[0] == 'm' || in[0] == 'e') && (in[1] == '-' || in[1] == '+' || in[1] == '~') && isNumber(in.substr(2))) { bool onAllMonitors = in[0] == 'e'; @@ -445,19 +445,19 @@ int getWorkspaceIDFromString(const std::string& in, std::string& outName) { if (!g_pCompositor->m_pLastMonitor) { Debug::log(ERR, "Relative monitor workspace on monitor null!"); - return WORKSPACE_INVALID; + return {WORKSPACE_INVALID}; } // monitor relative const auto PLUSMINUSRESULT = getPlusMinusKeywordResult(in.substr(absolute ? 2 : 1), 0); if (!PLUSMINUSRESULT.has_value()) - return WORKSPACE_INVALID; + return {WORKSPACE_INVALID}; - result = (int)PLUSMINUSRESULT.value(); + result.id = (int)PLUSMINUSRESULT.value(); // result now has +/- what we should move on mon - int remains = (int)result; + int remains = (int)result.id; std::vector validWSes; for (auto& ws : g_pCompositor->m_vWorkspaces) { @@ -505,30 +505,30 @@ int getWorkspaceIDFromString(const std::string& in, std::string& outName) { } } - result = validWSes[currentItem]; - outName = g_pCompositor->getWorkspaceByID(validWSes[currentItem])->m_szName; + result.id = validWSes[currentItem]; + result.name = g_pCompositor->getWorkspaceByID(validWSes[currentItem])->m_szName; } else { if (in[0] == '+' || in[0] == '-') { if (g_pCompositor->m_pLastMonitor) { const auto PLUSMINUSRESULT = getPlusMinusKeywordResult(in, g_pCompositor->m_pLastMonitor->activeWorkspaceID()); if (!PLUSMINUSRESULT.has_value()) - return WORKSPACE_INVALID; + return {WORKSPACE_INVALID}; - result = std::max((int)PLUSMINUSRESULT.value(), 1); + result.id = std::max((int)PLUSMINUSRESULT.value(), 1); } else { Debug::log(ERR, "Relative workspace on no mon!"); - return WORKSPACE_INVALID; + return {WORKSPACE_INVALID}; } } else if (isNumber(in)) - result = std::max(std::stoi(in), 1); + result.id = std::max(std::stoi(in), 1); else { // maybe name const auto PWORKSPACE = g_pCompositor->getWorkspaceByName(in); if (PWORKSPACE) - result = PWORKSPACE->m_iID; + result.id = PWORKSPACE->m_iID; } - outName = std::to_string(result); + result.name = std::to_string(result.id); } } diff --git a/src/helpers/MiscFunctions.hpp b/src/helpers/MiscFunctions.hpp index 111abba0..33be7965 100644 --- a/src/helpers/MiscFunctions.hpp +++ b/src/helpers/MiscFunctions.hpp @@ -13,13 +13,18 @@ struct SCallstackFrameInfo { std::string desc; }; +struct SWorkspaceIDName { + int id = -1; + std::string name; +}; + std::string absolutePath(const std::string&, const std::string&); void addWLSignal(wl_signal*, wl_listener*, void* pOwner, const std::string& ownerString); void removeWLSignal(wl_listener*); std::string escapeJSONStrings(const std::string& str); bool isDirection(const std::string&); bool isDirection(const char&); -int getWorkspaceIDFromString(const std::string&, std::string&); +SWorkspaceIDName getWorkspaceIDNameFromString(const std::string&); std::optional cleanCmdForWorkspace(const std::string&, std::string); float vecToRectDistanceSquared(const Vector2D& vec, const Vector2D& p1, const Vector2D& p2); void logSystemInfo(); @@ -42,4 +47,4 @@ template // because any suck format specifier will cause a compilation error // this is actually what std::format in stdlib does return std::vformat(fmt.get(), std::make_format_args(args...)); -} \ No newline at end of file +} diff --git a/src/helpers/Monitor.cpp b/src/helpers/Monitor.cpp index 7ebd2539..199b1c5d 100644 --- a/src/helpers/Monitor.cpp +++ b/src/helpers/Monitor.cpp @@ -415,20 +415,25 @@ int CMonitor::findAvailableDefaultWS() { void CMonitor::setupDefaultWS(const SMonitorRule& monitorRule) { // Workspace std::string newDefaultWorkspaceName = ""; - int64_t WORKSPACEID = g_pConfigManager->getDefaultWorkspaceFor(szName).empty() ? - findAvailableDefaultWS() : - getWorkspaceIDFromString(g_pConfigManager->getDefaultWorkspaceFor(szName), newDefaultWorkspaceName); + int64_t wsID = WORKSPACE_INVALID; + if (g_pConfigManager->getDefaultWorkspaceFor(szName).empty()) + wsID = findAvailableDefaultWS(); + else { + const auto ws = getWorkspaceIDNameFromString(g_pConfigManager->getDefaultWorkspaceFor(szName)); + wsID = ws.id; + newDefaultWorkspaceName = ws.name; + } - if (WORKSPACEID == WORKSPACE_INVALID || (WORKSPACEID >= SPECIAL_WORKSPACE_START && WORKSPACEID <= -2)) { - WORKSPACEID = g_pCompositor->m_vWorkspaces.size() + 1; - newDefaultWorkspaceName = std::to_string(WORKSPACEID); + if (wsID == WORKSPACE_INVALID || (wsID >= SPECIAL_WORKSPACE_START && wsID <= -2)) { + wsID = g_pCompositor->m_vWorkspaces.size() + 1; + newDefaultWorkspaceName = std::to_string(wsID); Debug::log(LOG, "Invalid workspace= directive name in monitor parsing, workspace name \"{}\" is invalid.", g_pConfigManager->getDefaultWorkspaceFor(szName)); } - auto PNEWWORKSPACE = g_pCompositor->getWorkspaceByID(WORKSPACEID); + auto PNEWWORKSPACE = g_pCompositor->getWorkspaceByID(wsID); - Debug::log(LOG, "New monitor: WORKSPACEID {}, exists: {}", WORKSPACEID, (int)(PNEWWORKSPACE != nullptr)); + Debug::log(LOG, "New monitor: WORKSPACEID {}, exists: {}", wsID, (int)(PNEWWORKSPACE != nullptr)); if (PNEWWORKSPACE) { // workspace exists, move it to the newly connected monitor @@ -438,9 +443,9 @@ void CMonitor::setupDefaultWS(const SMonitorRule& monitorRule) { PNEWWORKSPACE->startAnim(true, true, true); } else { if (newDefaultWorkspaceName == "") - newDefaultWorkspaceName = std::to_string(WORKSPACEID); + newDefaultWorkspaceName = std::to_string(wsID); - PNEWWORKSPACE = g_pCompositor->m_vWorkspaces.emplace_back(CWorkspace::create(WORKSPACEID, ID, newDefaultWorkspaceName)); + PNEWWORKSPACE = g_pCompositor->m_vWorkspaces.emplace_back(CWorkspace::create(wsID, ID, newDefaultWorkspaceName)); } activeWorkspace = PNEWWORKSPACE; diff --git a/src/macros.hpp b/src/macros.hpp index cacfdfea..67f6301b 100644 --- a/src/macros.hpp +++ b/src/macros.hpp @@ -24,7 +24,8 @@ #define STRVAL_EMPTY "[[EMPTY]]" -#define WORKSPACE_INVALID -1L +#define WORKSPACE_INVALID -1L +#define WORKSPACE_NOT_CHANGED -101 #define LISTENER(name) \ void listener_##name(wl_listener*, void*); \ diff --git a/src/managers/KeybindManager.cpp b/src/managers/KeybindManager.cpp index e5db8918..bfcea3da 100644 --- a/src/managers/KeybindManager.cpp +++ b/src/managers/KeybindManager.cpp @@ -1034,10 +1034,26 @@ void CKeybindManager::toggleActivePseudo(std::string args) { g_pLayoutManager->getCurrentLayout()->recalculateWindow(PWINDOW); } -void CKeybindManager::changeworkspace(std::string args) { - int workspaceToChangeTo = 0; - std::string workspaceName = ""; +SWorkspaceIDName getWorkspaceToChangeFromArgs(std::string args, PHLWORKSPACE PCURRENTWORKSPACE) { + if (!args.starts_with("previous")) { + return getWorkspaceIDNameFromString(args); + } + const SWorkspaceIDName PPREVWS = PCURRENTWORKSPACE->getPrevWorkspaceIDName(args.contains("_per_monitor")); + // Do nothing if there's no previous workspace, otherwise switch to it. + if (PPREVWS.id == -1) { + Debug::log(LOG, "No previous workspace to change to"); + return {WORKSPACE_NOT_CHANGED, ""}; + } + + const auto ID = PCURRENTWORKSPACE->m_iID; + if (const auto PWORKSPACETOCHANGETO = g_pCompositor->getWorkspaceByID(PPREVWS.id); PWORKSPACETOCHANGETO) + return {ID, PWORKSPACETOCHANGETO->m_szName}; + + return {ID, PPREVWS.name.empty() ? std::to_string(PPREVWS.id) : PPREVWS.name}; +} + +void CKeybindManager::changeworkspace(std::string args) { // Workspace_back_and_forth being enabled means that an attempt to switch to // the current workspace will instead switch to the previous. static auto PBACKANDFORTH = CConfigValue("binds:workspace_back_and_forth"); @@ -1050,43 +1066,31 @@ void CKeybindManager::changeworkspace(std::string args) { return; const auto PCURRENTWORKSPACE = PMONITOR->activeWorkspace; - const bool EXPLICITPREVIOUS = args.starts_with("previous"); - - if (args.starts_with("previous")) { - // Do nothing if there's no previous workspace, otherwise switch to it. - if (PCURRENTWORKSPACE->m_sPrevWorkspace.iID == -1) { - Debug::log(LOG, "No previous workspace to change to"); - return; - } else { - workspaceToChangeTo = PCURRENTWORKSPACE->m_iID; - - if (const auto PWORKSPACETOCHANGETO = g_pCompositor->getWorkspaceByID(PCURRENTWORKSPACE->m_sPrevWorkspace.iID); PWORKSPACETOCHANGETO) - workspaceName = PWORKSPACETOCHANGETO->m_szName; - else - workspaceName = - PCURRENTWORKSPACE->m_sPrevWorkspace.name.empty() ? std::to_string(PCURRENTWORKSPACE->m_sPrevWorkspace.iID) : PCURRENTWORKSPACE->m_sPrevWorkspace.name; - } - } else { - workspaceToChangeTo = getWorkspaceIDFromString(args, workspaceName); - } + const bool EXPLICITPREVIOUS = args.contains("previous"); + const auto& [workspaceToChangeTo, workspaceName] = getWorkspaceToChangeFromArgs(args, PCURRENTWORKSPACE); if (workspaceToChangeTo == WORKSPACE_INVALID) { Debug::log(ERR, "Error in changeworkspace, invalid value"); return; } - const bool BISWORKSPACECURRENT = workspaceToChangeTo == PCURRENTWORKSPACE->m_iID; + if (workspaceToChangeTo == WORKSPACE_NOT_CHANGED) { + return; + } - if (BISWORKSPACECURRENT && (!(*PBACKANDFORTH || EXPLICITPREVIOUS) || PCURRENTWORKSPACE->m_sPrevWorkspace.iID == -1)) + const auto PREVWS = PCURRENTWORKSPACE->getPrevWorkspaceIDName(args.contains("_per_monitor")); + + const bool BISWORKSPACECURRENT = workspaceToChangeTo == PCURRENTWORKSPACE->m_iID; + if (BISWORKSPACECURRENT && (!(*PBACKANDFORTH || EXPLICITPREVIOUS) || PREVWS.id == -1)) return; g_pInputManager->unconstrainMouse(); g_pInputManager->m_bEmptyFocusCursorSet = false; - auto pWorkspaceToChangeTo = g_pCompositor->getWorkspaceByID(BISWORKSPACECURRENT ? PCURRENTWORKSPACE->m_sPrevWorkspace.iID : workspaceToChangeTo); + auto pWorkspaceToChangeTo = g_pCompositor->getWorkspaceByID(BISWORKSPACECURRENT ? PREVWS.id : workspaceToChangeTo); if (!pWorkspaceToChangeTo) - pWorkspaceToChangeTo = g_pCompositor->createNewWorkspace(BISWORKSPACECURRENT ? PCURRENTWORKSPACE->m_sPrevWorkspace.iID : workspaceToChangeTo, PMONITOR->ID, - BISWORKSPACECURRENT ? PCURRENTWORKSPACE->m_sPrevWorkspace.name : workspaceName); + pWorkspaceToChangeTo = + g_pCompositor->createNewWorkspace(BISWORKSPACECURRENT ? PREVWS.id : workspaceToChangeTo, PMONITOR->ID, BISWORKSPACECURRENT ? PREVWS.name : workspaceName); if (!BISWORKSPACECURRENT && pWorkspaceToChangeTo->m_bIsSpecialWorkspace) { PMONITOR->setSpecialWorkspace(pWorkspaceToChangeTo); @@ -1169,10 +1173,7 @@ void CKeybindManager::moveActiveToWorkspace(std::string args) { if (!PWINDOW) return; - // hack - std::string workspaceName; - const auto WORKSPACEID = getWorkspaceIDFromString(args, workspaceName); - + const auto& [WORKSPACEID, workspaceName] = getWorkspaceIDNameFromString(args); if (WORKSPACEID == WORKSPACE_INVALID) { Debug::log(LOG, "Invalid workspace in moveActiveToWorkspace"); return; @@ -1233,10 +1234,7 @@ void CKeybindManager::moveActiveToWorkspaceSilent(std::string args) { if (!PWINDOW) return; - std::string workspaceName = ""; - - const int WORKSPACEID = getWorkspaceIDFromString(args, workspaceName); - + const auto& [WORKSPACEID, workspaceName] = getWorkspaceIDNameFromString(args); if (WORKSPACEID == WORKSPACE_INVALID) { Debug::log(ERR, "Error in moveActiveToWorkspaceSilent, invalid value"); return; @@ -1702,8 +1700,7 @@ void CKeybindManager::moveWorkspaceToMonitor(std::string args) { return; } - std::string workspaceName; - const int WORKSPACEID = getWorkspaceIDFromString(workspace, workspaceName); + const int WORKSPACEID = getWorkspaceIDNameFromString(workspace).id; if (WORKSPACEID == WORKSPACE_INVALID) { Debug::log(ERR, "moveWorkspaceToMonitor invalid workspace!"); @@ -1721,9 +1718,7 @@ void CKeybindManager::moveWorkspaceToMonitor(std::string args) { } void CKeybindManager::focusWorkspaceOnCurrentMonitor(std::string args) { - std::string workspaceName; - int workspaceID = getWorkspaceIDFromString(args, workspaceName); - + int workspaceID = getWorkspaceIDNameFromString(args).id; if (workspaceID == WORKSPACE_INVALID) { Debug::log(ERR, "focusWorkspaceOnCurrentMonitor invalid workspace!"); return; @@ -1746,14 +1741,13 @@ void CKeybindManager::focusWorkspaceOnCurrentMonitor(std::string args) { } static auto PBACKANDFORTH = CConfigValue("binds:workspace_back_and_forth"); + const auto PREVWS = pWorkspace->getPrevWorkspaceIDName(false); - if (*PBACKANDFORTH && PCURRMONITOR->activeWorkspaceID() == workspaceID && pWorkspace->m_sPrevWorkspace.iID != -1) { - const int PREVWORKSPACEID = pWorkspace->m_sPrevWorkspace.iID; - const auto PREVWORKSPACENAME = pWorkspace->m_sPrevWorkspace.name; + if (*PBACKANDFORTH && PCURRMONITOR->activeWorkspaceID() == workspaceID && PREVWS.id != -1) { // Workspace to focus is previous workspace - pWorkspace = g_pCompositor->getWorkspaceByID(PREVWORKSPACEID); + pWorkspace = g_pCompositor->getWorkspaceByID(PREVWS.id); if (!pWorkspace) - pWorkspace = g_pCompositor->createNewWorkspace(PREVWORKSPACEID, PCURRMONITOR->ID, PREVWORKSPACENAME); + pWorkspace = g_pCompositor->createNewWorkspace(PREVWS.id, PCURRMONITOR->ID, PREVWS.name); workspaceID = pWorkspace->m_iID; } @@ -1776,9 +1770,7 @@ void CKeybindManager::focusWorkspaceOnCurrentMonitor(std::string args) { } void CKeybindManager::toggleSpecialWorkspace(std::string args) { - std::string workspaceName = ""; - int workspaceID = getWorkspaceIDFromString("special:" + args, workspaceName); - + const auto& [workspaceID, workspaceName] = getWorkspaceIDNameFromString("special:" + args); if (workspaceID == WORKSPACE_INVALID || !g_pCompositor->isWorkspaceSpecial(workspaceID)) { Debug::log(ERR, "Invalid workspace passed to special"); return; diff --git a/src/managers/input/Swipe.cpp b/src/managers/input/Swipe.cpp index ead7c5b8..775881cd 100644 --- a/src/managers/input/Swipe.cpp +++ b/src/managers/input/Swipe.cpp @@ -63,10 +63,9 @@ void CInputManager::endWorkspaceSwipe() { m_sActiveSwipe.pWorkspaceBegin->m_vRenderOffset.getConfig()->pValues->internalStyle.starts_with("slidefadevert"); // commit - std::string wsname = ""; - auto workspaceIDLeft = getWorkspaceIDFromString((*PSWIPEUSER ? "r-1" : "m-1"), wsname); - auto workspaceIDRight = getWorkspaceIDFromString((*PSWIPEUSER ? "r+1" : "m+1"), wsname); - const auto SWIPEDISTANCE = std::clamp(*PSWIPEDIST, (int64_t)1LL, (int64_t)UINT32_MAX); + auto workspaceIDLeft = getWorkspaceIDNameFromString((*PSWIPEUSER ? "r-1" : "m-1")).id; + auto workspaceIDRight = getWorkspaceIDNameFromString((*PSWIPEUSER ? "r+1" : "m+1")).id; + const auto SWIPEDISTANCE = std::clamp(*PSWIPEDIST, (int64_t)1LL, (int64_t)UINT32_MAX); // If we've been swiping off the right end with PSWIPENEW enabled, there is // no workspace there yet, and we need to choose an ID for a new one now. @@ -232,9 +231,8 @@ void CInputManager::updateWorkspaceSwipe(double delta) { m_sActiveSwipe.avgSpeed = (m_sActiveSwipe.avgSpeed * m_sActiveSwipe.speedPoints + abs(d)) / (m_sActiveSwipe.speedPoints + 1); m_sActiveSwipe.speedPoints++; - std::string wsname = ""; - auto workspaceIDLeft = getWorkspaceIDFromString((*PSWIPEUSER ? "r-1" : "m-1"), wsname); - auto workspaceIDRight = getWorkspaceIDFromString((*PSWIPEUSER ? "r+1" : "m+1"), wsname); + auto workspaceIDLeft = getWorkspaceIDNameFromString((*PSWIPEUSER ? "r-1" : "m-1")).id; + auto workspaceIDRight = getWorkspaceIDNameFromString((*PSWIPEUSER ? "r+1" : "m+1")).id; if ((workspaceIDLeft == WORKSPACE_INVALID || workspaceIDRight == WORKSPACE_INVALID || workspaceIDLeft == m_sActiveSwipe.pWorkspaceBegin->m_iID) && !*PSWIPENEW) { m_sActiveSwipe.pWorkspaceBegin = nullptr; // invalidate the swipe From 315f16d501f38d6bc743fca359d13b655c4a970d Mon Sep 17 00:00:00 2001 From: John Titor <50095635+JohnRTitor@users.noreply.github.com> Date: Sun, 23 Jun 2024 12:43:17 +0530 Subject: [PATCH 0059/2181] dbus: import PATH XDG_DATA_DIRS variables into systemd and dbus session --- src/Compositor.cpp | 8 ++++---- src/config/ConfigManager.cpp | 4 ++-- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/src/Compositor.cpp b/src/Compositor.cpp index c607dfb6..2ed1a951 100644 --- a/src/Compositor.cpp +++ b/src/Compositor.cpp @@ -311,10 +311,10 @@ void CCompositor::cleanEnvironment() { if (m_sWLRSession) { const auto CMD = #ifdef USES_SYSTEMD - "systemctl --user unset-environment DISPLAY WAYLAND_DISPLAY HYPRLAND_INSTANCE_SIGNATURE XDG_CURRENT_DESKTOP QT_QPA_PLATFORMTHEME && hash " + "systemctl --user unset-environment DISPLAY WAYLAND_DISPLAY HYPRLAND_INSTANCE_SIGNATURE XDG_CURRENT_DESKTOP QT_QPA_PLATFORMTHEME PATH XDG_DATA_DIRS && hash " "dbus-update-activation-environment 2>/dev/null && " #endif - "dbus-update-activation-environment --systemd WAYLAND_DISPLAY XDG_CURRENT_DESKTOP HYPRLAND_INSTANCE_SIGNATURE QT_QPA_PLATFORMTHEME"; + "dbus-update-activation-environment --systemd WAYLAND_DISPLAY XDG_CURRENT_DESKTOP HYPRLAND_INSTANCE_SIGNATURE QT_QPA_PLATFORMTHEME PATH XDG_DATA_DIRS"; g_pKeybindManager->spawn(CMD); } } @@ -569,10 +569,10 @@ void CCompositor::startCompositor() { if (m_sWLRSession /* Session-less Hyprland usually means a nest, don't update the env in that case */) { const auto CMD = #ifdef USES_SYSTEMD - "systemctl --user import-environment DISPLAY WAYLAND_DISPLAY HYPRLAND_INSTANCE_SIGNATURE XDG_CURRENT_DESKTOP QT_QPA_PLATFORMTHEME && hash " + "systemctl --user import-environment DISPLAY WAYLAND_DISPLAY HYPRLAND_INSTANCE_SIGNATURE XDG_CURRENT_DESKTOP QT_QPA_PLATFORMTHEME PATH XDG_DATA_DIRS && hash " "dbus-update-activation-environment 2>/dev/null && " #endif - "dbus-update-activation-environment --systemd WAYLAND_DISPLAY XDG_CURRENT_DESKTOP HYPRLAND_INSTANCE_SIGNATURE QT_QPA_PLATFORMTHEME"; + "dbus-update-activation-environment --systemd WAYLAND_DISPLAY XDG_CURRENT_DESKTOP HYPRLAND_INSTANCE_SIGNATURE QT_QPA_PLATFORMTHEME PATH XDG_DATA_DIRS"; g_pKeybindManager->spawn(CMD); } diff --git a/src/config/ConfigManager.cpp b/src/config/ConfigManager.cpp index 6a1c896c..a4a80944 100644 --- a/src/config/ConfigManager.cpp +++ b/src/config/ConfigManager.cpp @@ -1282,10 +1282,10 @@ void CConfigManager::dispatchExecOnce() { if (g_pCompositor->m_sWLRSession) handleRawExec("", #ifdef USES_SYSTEMD - "systemctl --user import-environment DISPLAY WAYLAND_DISPLAY HYPRLAND_INSTANCE_SIGNATURE XDG_CURRENT_DESKTOP QT_QPA_PLATFORMTHEME && hash " + "systemctl --user import-environment DISPLAY WAYLAND_DISPLAY HYPRLAND_INSTANCE_SIGNATURE XDG_CURRENT_DESKTOP QT_QPA_PLATFORMTHEME PATH XDG_DATA_DIRS && hash " "dbus-update-activation-environment 2>/dev/null && " #endif - "dbus-update-activation-environment --systemd WAYLAND_DISPLAY XDG_CURRENT_DESKTOP HYPRLAND_INSTANCE_SIGNATURE QT_QPA_PLATFORMTHEME"); + "dbus-update-activation-environment --systemd WAYLAND_DISPLAY XDG_CURRENT_DESKTOP HYPRLAND_INSTANCE_SIGNATURE QT_QPA_PLATFORMTHEME PATH XDG_DATA_DIRS"); firstExecDispatched = true; From e09addf8dede9a8e7f2dd0e5bb414d3a0d5dc471 Mon Sep 17 00:00:00 2001 From: Mihai Fufezan Date: Sun, 23 Jun 2024 16:43:53 +0300 Subject: [PATCH 0060/2181] Workspace.hpp: fix include --- src/desktop/Workspace.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/desktop/Workspace.hpp b/src/desktop/Workspace.hpp index ab3907aa..bb5cd441 100644 --- a/src/desktop/Workspace.hpp +++ b/src/desktop/Workspace.hpp @@ -4,7 +4,7 @@ #include #include "../defines.hpp" #include "DesktopTypes.hpp" -#include "helpers/MiscFunctions.hpp" +#include "../helpers/MiscFunctions.hpp" enum eFullscreenMode : int8_t { FULLSCREEN_INVALID = -1, From 8a68199a0ceb2894a5d9cc300961c38123ac0312 Mon Sep 17 00:00:00 2001 From: Vaxry Date: Sun, 23 Jun 2024 19:49:48 +0200 Subject: [PATCH 0061/2181] foreign-toplevel-wlr: fix out-of-range for missing monitor resources fixes #6635 --- src/protocols/ForeignToplevelWlr.cpp | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/src/protocols/ForeignToplevelWlr.cpp b/src/protocols/ForeignToplevelWlr.cpp index 14800393..2b378386 100644 --- a/src/protocols/ForeignToplevelWlr.cpp +++ b/src/protocols/ForeignToplevelWlr.cpp @@ -124,17 +124,19 @@ void CForeignToplevelHandleWlr::sendMonitor(CMonitor* pMonitor) { const auto CLIENT = resource->client(); - if (const auto PLASTMONITOR = g_pCompositor->getMonitorFromID(lastMonitorID); PLASTMONITOR) { + if (const auto PLASTMONITOR = g_pCompositor->getMonitorFromID(lastMonitorID); PLASTMONITOR && PROTO::outputs.contains(PLASTMONITOR->szName)) { const auto OLDRESOURCE = PROTO::outputs.at(PLASTMONITOR->szName)->outputResourceFrom(CLIENT); if (OLDRESOURCE) resource->sendOutputLeave(OLDRESOURCE->getResource()->resource()); } - const auto NEWRESOURCE = PROTO::outputs.at(pMonitor->szName)->outputResourceFrom(CLIENT); + if (PROTO::outputs.contains(pMonitor->szName)) { + const auto NEWRESOURCE = PROTO::outputs.at(pMonitor->szName)->outputResourceFrom(CLIENT); - if (NEWRESOURCE) - resource->sendOutputEnter(NEWRESOURCE->getResource()->resource()); + if (NEWRESOURCE) + resource->sendOutputEnter(NEWRESOURCE->getResource()->resource()); + } lastMonitorID = pMonitor->ID; } From cff0123ce62a1f721d3aa2ac0fb58019787a7778 Mon Sep 17 00:00:00 2001 From: Vaxry Date: Mon, 24 Jun 2024 23:29:26 +0200 Subject: [PATCH 0062/2181] wl-compositor: don't send enter to defunct output globals --- src/protocols/core/Compositor.cpp | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/protocols/core/Compositor.cpp b/src/protocols/core/Compositor.cpp index 4bce3f58..691267b0 100644 --- a/src/protocols/core/Compositor.cpp +++ b/src/protocols/core/Compositor.cpp @@ -221,6 +221,11 @@ void CWLSurfaceResource::enter(SP monitor) { return; } + if (PROTO::outputs.at(monitor->szName)->isDefunct()) { + LOGM(ERR, "enter() called on a defunct output global"); + return; + } + auto output = PROTO::outputs.at(monitor->szName)->outputResourceFrom(pClient); if (!output || !output->getResource() || !output->getResource()->resource()) { From 4dd2b5902e770eeaf84820eccfebb5451aedb6a5 Mon Sep 17 00:00:00 2001 From: Vaxry Date: Mon, 24 Jun 2024 23:58:10 +0200 Subject: [PATCH 0063/2181] hyprctl: add a newline after log() --- hyprctl/main.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/hyprctl/main.cpp b/hyprctl/main.cpp index 2bd325e3..45fe9142 100644 --- a/hyprctl/main.cpp +++ b/hyprctl/main.cpp @@ -47,7 +47,7 @@ void log(std::string str) { if (quiet) return; - std::cout << str; + std::cout << str << "\n"; } std::string getRuntimeDir() { From eef207ce0a46c13dafa8fab3a462e62c8a3c04f1 Mon Sep 17 00:00:00 2001 From: outfoxxed Date: Tue, 25 Jun 2024 03:55:54 -0700 Subject: [PATCH 0064/2181] output: fix cursors disappearing after dpms (#6659) --- src/managers/KeybindManager.cpp | 3 +++ src/managers/PointerManager.hpp | 3 ++- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/src/managers/KeybindManager.cpp b/src/managers/KeybindManager.cpp index bfcea3da..37159ca8 100644 --- a/src/managers/KeybindManager.cpp +++ b/src/managers/KeybindManager.cpp @@ -5,6 +5,7 @@ #include "../protocols/ShortcutsInhibit.hpp" #include "../render/decorations/CHyprGroupBarDecoration.hpp" #include "KeybindManager.hpp" +#include "PointerManager.hpp" #include "Compositor.hpp" #include "TokenManager.hpp" #include "debug/Log.hpp" @@ -2280,6 +2281,8 @@ void CKeybindManager::dpms(std::string arg) { } g_pCompositor->m_bDPMSStateON = enable; + + g_pPointerManager->recheckEnteredOutputs(); } void CKeybindManager::swapnext(std::string arg) { diff --git a/src/managers/PointerManager.hpp b/src/managers/PointerManager.hpp index 545b76fb..da639340 100644 --- a/src/managers/PointerManager.hpp +++ b/src/managers/PointerManager.hpp @@ -59,6 +59,8 @@ class CPointerManager { Vector2D position(); Vector2D cursorSizeLogical(); + void recheckEnteredOutputs(); + private: void recheckPointerPosition(); void onMonitorLayoutChange(); @@ -67,7 +69,6 @@ class CPointerManager { void onCursorMoved(); bool hasCursor(); void damageIfSoftware(); - void recheckEnteredOutputs(); // closest valid point to a given one Vector2D closestValid(const Vector2D& pos); From 784c0b5ccb9b99bde66bd45bb94af5f195980f2e Mon Sep 17 00:00:00 2001 From: Gregory <56975502+Trimutex@users.noreply.github.com> Date: Tue, 25 Jun 2024 06:46:49 -0500 Subject: [PATCH 0065/2181] keybinds: fix mouse pass (#6652) * keybinds: fix mouse pass * keybinds: keep mouse and keyboard focus separate after pass bind --- src/managers/KeybindManager.cpp | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/src/managers/KeybindManager.cpp b/src/managers/KeybindManager.cpp index 37159ca8..c5a35012 100644 --- a/src/managers/KeybindManager.cpp +++ b/src/managers/KeybindManager.cpp @@ -2025,8 +2025,9 @@ void CKeybindManager::pass(std::string regexp) { return; } - const auto XWTOXW = PWINDOW->m_bIsX11 && g_pCompositor->m_pLastWindow.lock() && g_pCompositor->m_pLastWindow->m_bIsX11; - const auto LASTSRF = g_pCompositor->m_pLastFocus.lock(); + const auto XWTOXW = PWINDOW->m_bIsX11 && g_pCompositor->m_pLastWindow.lock() && g_pCompositor->m_pLastWindow->m_bIsX11; + const auto LASTMOUSESURF = g_pSeatManager->state.pointerFocus.lock(); + const auto LASTKBSURF = g_pSeatManager->state.keyboardFocus.lock(); // pass all mf shit if (!XWTOXW) { @@ -2078,9 +2079,9 @@ void CKeybindManager::pass(std::string regexp) { const auto SL = PWINDOW->m_vRealPosition.goal() - g_pInputManager->getMouseCoordsInternal(); if (g_pKeybindManager->m_uLastCode != 0) - g_pSeatManager->setKeyboardFocus(LASTSRF); + g_pSeatManager->setKeyboardFocus(LASTKBSURF); else - g_pSeatManager->setPointerFocus(PWINDOW->m_pWLSurface->resource(), SL); + g_pSeatManager->setPointerFocus(LASTMOUSESURF, SL); } void CKeybindManager::sendshortcut(std::string args) { From 8121e66f34eb9247cd202590370bf91f8c3ec447 Mon Sep 17 00:00:00 2001 From: Vaxry Date: Tue, 25 Jun 2024 13:50:54 +0200 Subject: [PATCH 0066/2181] cmake: bump hyprutils dep to 0.1.5 --- CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 632621ac..e8f203b4 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -113,7 +113,7 @@ pkg_check_modules(deps REQUIRED IMPORTED_TARGET wayland-server wayland-client wayland-cursor wayland-protocols cairo pango pangocairo pixman-1 libdrm libinput hwdata libseat libdisplay-info libliftoff libudev gbm - hyprlang>=0.3.2 hyprcursor>=0.1.7 hyprutils>=0.1.4 + hyprlang>=0.3.2 hyprcursor>=0.1.7 hyprutils>=0.1.5 ) find_package(hyprwayland-scanner 0.3.10 REQUIRED) From 4f7113972e9803a41329125e5e8f77fe5281fb22 Mon Sep 17 00:00:00 2001 From: Vaxry Date: Tue, 25 Jun 2024 13:53:41 +0200 Subject: [PATCH 0067/2181] props: bump version to 0.41.2 --- props.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/props.json b/props.json index 4af3eb2a..2ff7562e 100644 --- a/props.json +++ b/props.json @@ -1,3 +1,3 @@ { - "version": "0.41.1" + "version": "0.41.2" } \ No newline at end of file From 918d8340afd652b011b937d29d5eea0be08467f5 Mon Sep 17 00:00:00 2001 From: Mihai Fufezan Date: Tue, 25 Jun 2024 15:06:02 +0300 Subject: [PATCH 0068/2181] flake.lock: update --- flake.lock | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/flake.lock b/flake.lock index cb1f7875..c1f37d2e 100644 --- a/flake.lock +++ b/flake.lock @@ -87,11 +87,11 @@ ] }, "locked": { - "lastModified": 1718804078, - "narHash": "sha256-CqRZne63BpYlPd/i8lXV0UInUt59oKogiwdVtBRHt60=", + "lastModified": 1719316102, + "narHash": "sha256-dmRz128j/lJmMuTYeCYPfSBRHHQO3VeH4PbmoyAhHzw=", "owner": "hyprwm", "repo": "hyprutils", - "rev": "4f1351295c55a8f51219b25aa4a6497a067989d0", + "rev": "1f6bbec5954f623ff8d68e567bddcce97cd2f085", "type": "github" }, "original": { @@ -110,11 +110,11 @@ ] }, "locked": { - "lastModified": 1718119275, - "narHash": "sha256-nqDYXATNkyGXVmNMkT19fT4sjtSPBDS1LLOxa3Fueo4=", + "lastModified": 1719067853, + "narHash": "sha256-mAnZG/eQy72Fp1ImGtqCgUrDumnR1rMZv2E/zgP4U74=", "owner": "hyprwm", "repo": "hyprwayland-scanner", - "rev": "1419520d5f7f38d35e05504da5c1b38212a38525", + "rev": "914f083741e694092ee60a39d31f693d0a6dc734", "type": "github" }, "original": { @@ -125,11 +125,11 @@ }, "nixpkgs": { "locked": { - "lastModified": 1718530797, - "narHash": "sha256-pup6cYwtgvzDpvpSCFh1TEUjw2zkNpk8iolbKnyFmmU=", + "lastModified": 1719075281, + "narHash": "sha256-CyyxvOwFf12I91PBWz43iGT1kjsf5oi6ax7CrvaMyAo=", "owner": "NixOS", "repo": "nixpkgs", - "rev": "b60ebf54c15553b393d144357375ea956f89e9a9", + "rev": "a71e967ef3694799d0c418c98332f7ff4cc5f6af", "type": "github" }, "original": { From 1d70962892a6e3e1cacd3663b390bbdf81426984 Mon Sep 17 00:00:00 2001 From: Vaxry Date: Tue, 25 Jun 2024 16:05:39 +0200 Subject: [PATCH 0069/2181] core: move to steady_clock where applicable avoid issues when system clock gets desynchronized or changed --- src/events/Monitors.cpp | 4 ++-- src/helpers/AnimatedVariable.cpp | 4 ++-- src/helpers/AnimatedVariable.hpp | 6 +++--- src/helpers/Timer.cpp | 8 ++++---- src/helpers/Timer.hpp | 6 +++--- src/managers/AnimationManager.cpp | 2 +- src/managers/TokenManager.cpp | 8 ++++---- src/managers/TokenManager.hpp | 6 +++--- src/managers/eventLoop/EventLoopTimer.cpp | 12 ++++++------ src/managers/eventLoop/EventLoopTimer.hpp | 6 +++--- 10 files changed, 31 insertions(+), 31 deletions(-) diff --git a/src/events/Monitors.cpp b/src/events/Monitors.cpp index 17b8ef65..2536e1f7 100644 --- a/src/events/Monitors.cpp +++ b/src/events/Monitors.cpp @@ -19,7 +19,7 @@ static void checkDefaultCursorWarp(SP PNEWMONITOR, std::string monitorName) { static auto PCURSORMONITOR = CConfigValue("cursor:default_monitor"); - static auto firstMonitorAdded = std::chrono::system_clock::now(); + static auto firstMonitorAdded = std::chrono::steady_clock::now(); static bool cursorDefaultDone = false; static bool firstLaunch = true; @@ -37,7 +37,7 @@ static void checkDefaultCursorWarp(SP PNEWMONITOR, std::string monitor return; // after 10s, don't set cursor to default monitor - auto timePassedSec = std::chrono::duration_cast(std::chrono::system_clock::now() - firstMonitorAdded); + auto timePassedSec = std::chrono::duration_cast(std::chrono::steady_clock::now() - firstMonitorAdded); if (timePassedSec.count() > 10) { cursorDefaultDone = true; return; diff --git a/src/helpers/AnimatedVariable.cpp b/src/helpers/AnimatedVariable.cpp index bdfb4b77..117cd25b 100644 --- a/src/helpers/AnimatedVariable.cpp +++ b/src/helpers/AnimatedVariable.cpp @@ -57,11 +57,11 @@ void CBaseAnimatedVariable::registerVar() { int CBaseAnimatedVariable::getDurationLeftMs() { return std::max( - (int)(m_pConfig->pValues->internalSpeed * 100) - (int)std::chrono::duration_cast(std::chrono::system_clock::now() - animationBegin).count(), 0); + (int)(m_pConfig->pValues->internalSpeed * 100) - (int)std::chrono::duration_cast(std::chrono::steady_clock::now() - animationBegin).count(), 0); } float CBaseAnimatedVariable::getPercent() { - const auto DURATIONPASSED = std::chrono::duration_cast(std::chrono::system_clock::now() - animationBegin).count(); + const auto DURATIONPASSED = std::chrono::duration_cast(std::chrono::steady_clock::now() - animationBegin).count(); return std::clamp((DURATIONPASSED / 100.f) / m_pConfig->pValues->internalSpeed, 0.f, 1.f); } diff --git a/src/helpers/AnimatedVariable.hpp b/src/helpers/AnimatedVariable.hpp index 073cf65b..6310afb7 100644 --- a/src/helpers/AnimatedVariable.hpp +++ b/src/helpers/AnimatedVariable.hpp @@ -155,7 +155,7 @@ class CBaseAnimatedVariable { bool m_bIsRegistered = false; bool m_bIsBeingAnimated = false; - std::chrono::system_clock::time_point animationBegin; + std::chrono::steady_clock::time_point animationBegin; AVARDAMAGEPOLICY m_eDamagePolicy = AVARDAMAGE_NONE; ANIMATEDVARTYPE m_Type; @@ -253,7 +253,7 @@ class CAnimatedVariable : public CBaseAnimatedVariable { return *this; m_Goal = v; - animationBegin = std::chrono::system_clock::now(); + animationBegin = std::chrono::steady_clock::now(); m_Begun = m_Value; onAnimationBegin(); @@ -267,7 +267,7 @@ class CAnimatedVariable : public CBaseAnimatedVariable { return; m_Value = v; - animationBegin = std::chrono::system_clock::now(); + animationBegin = std::chrono::steady_clock::now(); m_Begun = m_Value; onAnimationBegin(); diff --git a/src/helpers/Timer.cpp b/src/helpers/Timer.cpp index 6847567a..ec530df4 100644 --- a/src/helpers/Timer.cpp +++ b/src/helpers/Timer.cpp @@ -1,11 +1,11 @@ #include "Timer.hpp" void CTimer::reset() { - m_tpLastReset = std::chrono::system_clock::now(); + m_tpLastReset = std::chrono::steady_clock::now(); } -std::chrono::system_clock::duration CTimer::getDuration() { - return std::chrono::system_clock::now() - m_tpLastReset; +std::chrono::steady_clock::duration CTimer::getDuration() { + return std::chrono::steady_clock::now() - m_tpLastReset; } int CTimer::getMillis() { @@ -16,6 +16,6 @@ float CTimer::getSeconds() { return std::chrono::duration_cast(getDuration()).count() / 1000.f; } -const std::chrono::system_clock::time_point& CTimer::chrono() const { +const std::chrono::steady_clock::time_point& CTimer::chrono() const { return m_tpLastReset; } \ No newline at end of file diff --git a/src/helpers/Timer.hpp b/src/helpers/Timer.hpp index e55f4ebf..a6d1aeed 100644 --- a/src/helpers/Timer.hpp +++ b/src/helpers/Timer.hpp @@ -7,10 +7,10 @@ class CTimer { void reset(); float getSeconds(); int getMillis(); - const std::chrono::system_clock::time_point& chrono() const; + const std::chrono::steady_clock::time_point& chrono() const; private: - std::chrono::system_clock::time_point m_tpLastReset; + std::chrono::steady_clock::time_point m_tpLastReset; - std::chrono::system_clock::duration getDuration(); + std::chrono::steady_clock::duration getDuration(); }; \ No newline at end of file diff --git a/src/managers/AnimationManager.cpp b/src/managers/AnimationManager.cpp index 9d6668c9..1fec375e 100644 --- a/src/managers/AnimationManager.cpp +++ b/src/managers/AnimationManager.cpp @@ -552,7 +552,7 @@ void CAnimationManager::scheduleTick() { float refreshDelayMs = std::floor(1000.f / PMOSTHZ->refreshRate); - const float SINCEPRES = std::chrono::duration_cast(std::chrono::system_clock::now() - PMOSTHZ->lastPresentationTimer.chrono()).count() / 1000.f; + const float SINCEPRES = std::chrono::duration_cast(std::chrono::steady_clock::now() - PMOSTHZ->lastPresentationTimer.chrono()).count() / 1000.f; const auto TOPRES = std::clamp(refreshDelayMs - SINCEPRES, 1.1f, 1000.f); // we can't send 0, that will disarm it diff --git a/src/managers/TokenManager.cpp b/src/managers/TokenManager.cpp index 451baac1..cee97c1c 100644 --- a/src/managers/TokenManager.cpp +++ b/src/managers/TokenManager.cpp @@ -2,8 +2,8 @@ #include #include -CUUIDToken::CUUIDToken(const std::string& uuid_, std::any data_, std::chrono::system_clock::duration expires) : data(data_), uuid(uuid_) { - expiresAt = std::chrono::system_clock::now() + expires; +CUUIDToken::CUUIDToken(const std::string& uuid_, std::any data_, std::chrono::steady_clock::duration expires) : data(data_), uuid(uuid_) { + expiresAt = std::chrono::steady_clock::now() + expires; } std::string CUUIDToken::getUUID() { @@ -23,7 +23,7 @@ std::string CTokenManager::getRandomUUID() { return uuid; } -std::string CTokenManager::registerNewToken(std::any data, std::chrono::system_clock::duration expires) { +std::string CTokenManager::registerNewToken(std::any data, std::chrono::steady_clock::duration expires) { std::string uuid = getRandomUUID(); m_mTokens[uuid] = makeShared(uuid, data, expires); @@ -33,7 +33,7 @@ std::string CTokenManager::registerNewToken(std::any data, std::chrono::system_c SP CTokenManager::getToken(const std::string& uuid) { // cleanup expired tokens - const auto NOW = std::chrono::system_clock::now(); + const auto NOW = std::chrono::steady_clock::now(); std::erase_if(m_mTokens, [this, &NOW](const auto& el) { return el.second->expiresAt < NOW; }); if (!m_mTokens.contains(uuid)) diff --git a/src/managers/TokenManager.hpp b/src/managers/TokenManager.hpp index 4587f556..92638e9b 100644 --- a/src/managers/TokenManager.hpp +++ b/src/managers/TokenManager.hpp @@ -9,7 +9,7 @@ class CUUIDToken { public: - CUUIDToken(const std::string& uuid_, std::any data_, std::chrono::system_clock::duration expires); + CUUIDToken(const std::string& uuid_, std::any data_, std::chrono::steady_clock::duration expires); std::string getUUID(); @@ -18,14 +18,14 @@ class CUUIDToken { private: std::string uuid; - std::chrono::system_clock::time_point expiresAt; + std::chrono::steady_clock::time_point expiresAt; friend class CTokenManager; }; class CTokenManager { public: - std::string registerNewToken(std::any data, std::chrono::system_clock::duration expires); + std::string registerNewToken(std::any data, std::chrono::steady_clock::duration expires); std::string getRandomUUID(); SP getToken(const std::string& uuid); diff --git a/src/managers/eventLoop/EventLoopTimer.cpp b/src/managers/eventLoop/EventLoopTimer.cpp index dbb405e5..d3cfdf8d 100644 --- a/src/managers/eventLoop/EventLoopTimer.cpp +++ b/src/managers/eventLoop/EventLoopTimer.cpp @@ -2,23 +2,23 @@ #include #include "EventLoopManager.hpp" -CEventLoopTimer::CEventLoopTimer(std::optional timeout, std::function self, void* data)> cb_, void* data_) : +CEventLoopTimer::CEventLoopTimer(std::optional timeout, std::function self, void* data)> cb_, void* data_) : cb(cb_), data(data_) { if (!timeout.has_value()) expires.reset(); else - expires = std::chrono::system_clock::now() + *timeout; + expires = std::chrono::steady_clock::now() + *timeout; } -void CEventLoopTimer::updateTimeout(std::optional timeout) { +void CEventLoopTimer::updateTimeout(std::optional timeout) { if (!timeout.has_value()) { expires.reset(); g_pEventLoopManager->nudgeTimers(); return; } - expires = std::chrono::system_clock::now() + *timeout; + expires = std::chrono::steady_clock::now() + *timeout; g_pEventLoopManager->nudgeTimers(); } @@ -26,7 +26,7 @@ void CEventLoopTimer::updateTimeout(std::optional *expires; + return std::chrono::steady_clock::now() > *expires; } void CEventLoopTimer::cancel() { @@ -47,5 +47,5 @@ float CEventLoopTimer::leftUs() { if (!expires.has_value()) return std::numeric_limits::max(); - return std::chrono::duration_cast(*expires - std::chrono::system_clock::now()).count(); + return std::chrono::duration_cast(*expires - std::chrono::steady_clock::now()).count(); } diff --git a/src/managers/eventLoop/EventLoopTimer.hpp b/src/managers/eventLoop/EventLoopTimer.hpp index 73f5dc73..ad7d3986 100644 --- a/src/managers/eventLoop/EventLoopTimer.hpp +++ b/src/managers/eventLoop/EventLoopTimer.hpp @@ -8,11 +8,11 @@ class CEventLoopTimer { public: - CEventLoopTimer(std::optional timeout, std::function self, void* data)> cb_, void* data_); + CEventLoopTimer(std::optional timeout, std::function self, void* data)> cb_, void* data_); // if not specified, disarms. // if specified, arms. - void updateTimeout(std::optional timeout); + void updateTimeout(std::optional timeout); void cancel(); bool passed(); @@ -26,6 +26,6 @@ class CEventLoopTimer { private: std::function self, void* data)> cb; void* data = nullptr; - std::optional expires; + std::optional expires; bool wasCancelled = false; }; From 3ba3d20ad35f904cdafdd664b0acd1671924597a Mon Sep 17 00:00:00 2001 From: Vaxry Date: Tue, 25 Jun 2024 18:44:54 +0200 Subject: [PATCH 0070/2181] pointer: round position when rendering software cursors otherwise the image gets resampled and gets blurry --- src/managers/PointerManager.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/managers/PointerManager.cpp b/src/managers/PointerManager.cpp index d3da5eff..2b34f380 100644 --- a/src/managers/PointerManager.cpp +++ b/src/managers/PointerManager.cpp @@ -576,6 +576,8 @@ void CPointerManager::renderSoftwareCursorsFor(SP pMonitor, timespec* return; box.scale(pMonitor->scale); + box.x = std::round(box.x); + box.y = std::round(box.y); g_pHyprOpenGL->renderTextureWithDamage(texture, &box, &damage, 1.F); From 95782de966ec9e182d49b2f032b74a1101f423e8 Mon Sep 17 00:00:00 2001 From: Vaxry Date: Tue, 25 Jun 2024 20:04:02 +0200 Subject: [PATCH 0071/2181] renderer: don't use the surface counter in popup iterations fixes #6663 --- src/render/Renderer.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/render/Renderer.cpp b/src/render/Renderer.cpp index 4fc751ff..3ea5197e 100644 --- a/src/render/Renderer.cpp +++ b/src/render/Renderer.cpp @@ -212,7 +212,7 @@ static void renderSurface(SP surface, int x, int y, void* da // FIXME: This is wrong and will bug the blur out as shit if the first surface // is a subsurface that does NOT cover the entire frame. In such cases, we probably should fall back // to what we do for misaligned surfaces (blur the entire thing and then render shit without blur) - if (RDATA->surfaceCounter == 0) { + if (RDATA->surfaceCounter == 0 && !RDATA->popup) { if (RDATA->blur) g_pHyprOpenGL->renderTextureWithBlur(TEXTURE, &windowBox, ALPHA, surface, rounding, RDATA->blockBlurOptimization, RDATA->fadeAlpha); else From c338acbb7dc64a735dadd0ae54f3b17d85a2a467 Mon Sep 17 00:00:00 2001 From: Vaxry Date: Tue, 25 Jun 2024 22:46:36 +0200 Subject: [PATCH 0072/2181] ime-relay: fix crash on nullptr surface focus --- src/managers/input/InputMethodRelay.cpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/managers/input/InputMethodRelay.cpp b/src/managers/input/InputMethodRelay.cpp index 92ab14d8..f1fe6421 100644 --- a/src/managers/input/InputMethodRelay.cpp +++ b/src/managers/input/InputMethodRelay.cpp @@ -143,6 +143,9 @@ void CInputMethodRelay::onKeyboardFocus(SP pSurface) { ti->leave(); } + if (!pSurface) + return; + for (auto& ti : m_vTextInputs) { if (!ti->isV3()) continue; From e4d09aa3a9de9a9e71c10bf4b6800585b3db9a4c Mon Sep 17 00:00:00 2001 From: outfoxxed Date: Tue, 25 Jun 2024 14:22:38 -0700 Subject: [PATCH 0073/2181] sessionLock: focus lock on creation based on mouse position (#6658) * sessionLock: focus lock on creation based on mouse position * sessionLock: immediately unfocus any focused surfaces on lock --- src/managers/SessionLockManager.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/managers/SessionLockManager.cpp b/src/managers/SessionLockManager.cpp index 3bec1c4b..b4695e0e 100644 --- a/src/managers/SessionLockManager.cpp +++ b/src/managers/SessionLockManager.cpp @@ -10,7 +10,7 @@ SSessionLockSurface::SSessionLockSurface(SP surface_) : sur listeners.map = surface_->events.map.registerListener([this](std::any data) { mapped = true; - g_pCompositor->focusSurface(surface->surface()); + g_pInputManager->simulateMouseMovement(); const auto PMONITOR = g_pCompositor->getMonitorFromID(iMonitorID); @@ -78,6 +78,7 @@ void CSessionLockManager::onNewSessionLock(SP pLock) { }); pLock->sendLocked(); + g_pCompositor->focusSurface(nullptr); } bool CSessionLockManager::isSessionLocked() { From f2dc48d92f340efe6d4264b92d38378c18a3e1ea Mon Sep 17 00:00:00 2001 From: Alexander <51529891+Truenya@users.noreply.github.com> Date: Thu, 27 Jun 2024 16:07:56 +0300 Subject: [PATCH 0074/2181] keybinds: never switch to another monitor with per_monitor (#6665) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Крылов Александр --- src/managers/KeybindManager.cpp | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/src/managers/KeybindManager.cpp b/src/managers/KeybindManager.cpp index c5a35012..005ce392 100644 --- a/src/managers/KeybindManager.cpp +++ b/src/managers/KeybindManager.cpp @@ -1040,7 +1040,8 @@ SWorkspaceIDName getWorkspaceToChangeFromArgs(std::string args, PHLWORKSPACE PCU return getWorkspaceIDNameFromString(args); } - const SWorkspaceIDName PPREVWS = PCURRENTWORKSPACE->getPrevWorkspaceIDName(args.contains("_per_monitor")); + const bool PER_MON = args.contains("_per_monitor"); + const SWorkspaceIDName PPREVWS = PCURRENTWORKSPACE->getPrevWorkspaceIDName(PER_MON); // Do nothing if there's no previous workspace, otherwise switch to it. if (PPREVWS.id == -1) { Debug::log(LOG, "No previous workspace to change to"); @@ -1048,8 +1049,11 @@ SWorkspaceIDName getWorkspaceToChangeFromArgs(std::string args, PHLWORKSPACE PCU } const auto ID = PCURRENTWORKSPACE->m_iID; - if (const auto PWORKSPACETOCHANGETO = g_pCompositor->getWorkspaceByID(PPREVWS.id); PWORKSPACETOCHANGETO) + if (const auto PWORKSPACETOCHANGETO = g_pCompositor->getWorkspaceByID(PPREVWS.id); PWORKSPACETOCHANGETO) { + if (PER_MON && PCURRENTWORKSPACE->m_iMonitorID != PWORKSPACETOCHANGETO->m_iMonitorID) + return {WORKSPACE_NOT_CHANGED, ""}; return {ID, PWORKSPACETOCHANGETO->m_szName}; + } return {ID, PPREVWS.name.empty() ? std::to_string(PPREVWS.id) : PPREVWS.name}; } @@ -1678,7 +1682,6 @@ void CKeybindManager::moveCurrentWorkspaceToMonitor(std::string args) { // get the current workspace const auto PCURRENTWORKSPACE = g_pCompositor->m_pLastMonitor->activeWorkspace; - if (!PCURRENTWORKSPACE) { Debug::log(ERR, "moveCurrentWorkspaceToMonitor invalid workspace!"); return; From ac11771348146087eb577d20162ec10a81358a7e Mon Sep 17 00:00:00 2001 From: Tom Englund Date: Fri, 28 Jun 2024 22:24:32 +0200 Subject: [PATCH 0075/2181] core: fix a few ubsan issues reported at exit of hyprland (#6699) * watchdog: dont detach and cause race condition instead of detaching and causing a race condition on destruction where the thread is alive and watchdog has been destroyed, check if its joinable and join it on destruction. causes heap use after free on exit of compositor. * render: add checks for compositor shutting down avoid member call on null pointer, if the g_pHyprRenderer is destroyed we can call the member makeEGLCurrent on it, causes undefined behaviour on destruction of the compositor/hyprrenderer. found with ubsan. --- src/helpers/Watchdog.cpp | 6 +++--- src/render/Renderbuffer.cpp | 2 +- src/render/Texture.cpp | 2 +- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/src/helpers/Watchdog.cpp b/src/helpers/Watchdog.cpp index afb8a946..b9f654da 100644 --- a/src/helpers/Watchdog.cpp +++ b/src/helpers/Watchdog.cpp @@ -7,7 +7,9 @@ CWatchdog::~CWatchdog() { m_bExitThread = true; m_bNotified = true; m_cvWatchdogCondition.notify_all(); - m_pWatchdog.reset(); + + if (m_pWatchdog && m_pWatchdog->joinable()) + m_pWatchdog->join(); } CWatchdog::CWatchdog() { @@ -33,8 +35,6 @@ CWatchdog::CWatchdog() { m_bNotified = false; } }); - - m_pWatchdog->detach(); } void CWatchdog::startWatching() { diff --git a/src/render/Renderbuffer.cpp b/src/render/Renderbuffer.cpp index 694485c2..b55a921b 100644 --- a/src/render/Renderbuffer.cpp +++ b/src/render/Renderbuffer.cpp @@ -6,7 +6,7 @@ #include CRenderbuffer::~CRenderbuffer() { - if (!g_pCompositor) + if (!g_pCompositor || g_pCompositor->m_bIsShuttingDown || !g_pHyprRenderer) return; g_pHyprRenderer->makeEGLCurrent(); diff --git a/src/render/Texture.cpp b/src/render/Texture.cpp index 5560db97..46c501a0 100644 --- a/src/render/Texture.cpp +++ b/src/render/Texture.cpp @@ -9,7 +9,7 @@ CTexture::CTexture() { } CTexture::~CTexture() { - if (m_bNonOwning) + if (m_bNonOwning || !g_pCompositor || g_pCompositor->m_bIsShuttingDown || !g_pHyprRenderer) return; g_pHyprRenderer->makeEGLCurrent(); From d16c6aa1db52a0ee60ca1f53a9aa9ed1a2537ff2 Mon Sep 17 00:00:00 2001 From: Vaxry Date: Sat, 29 Jun 2024 00:18:18 +0200 Subject: [PATCH 0076/2181] pointer-constraint: set lifetime correctly ref #6679 --- src/protocols/PointerConstraints.cpp | 8 ++++---- src/protocols/PointerConstraints.hpp | 4 ++-- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/src/protocols/PointerConstraints.cpp b/src/protocols/PointerConstraints.cpp index a17fa6cd..fd15242d 100644 --- a/src/protocols/PointerConstraints.cpp +++ b/src/protocols/PointerConstraints.cpp @@ -7,8 +7,8 @@ #define LOGM PROTO::constraints->protoLog -CPointerConstraint::CPointerConstraint(SP resource_, SP surf, wl_resource* region_, zwpPointerConstraintsV1Lifetime lifetime) : - resourceL(resource_), locked(true) { +CPointerConstraint::CPointerConstraint(SP resource_, SP surf, wl_resource* region_, zwpPointerConstraintsV1Lifetime lifetime_) : + resourceL(resource_), locked(true), lifetime(lifetime_) { if (!resource_->resource()) return; @@ -46,8 +46,8 @@ CPointerConstraint::CPointerConstraint(SP resource_, SP resource_, SP surf, wl_resource* region_, zwpPointerConstraintsV1Lifetime lifetime) : - resourceC(resource_), locked(false) { +CPointerConstraint::CPointerConstraint(SP resource_, SP surf, wl_resource* region_, zwpPointerConstraintsV1Lifetime lifetime_) : + resourceC(resource_), locked(false), lifetime(lifetime_) { if (!resource_->resource()) return; diff --git a/src/protocols/PointerConstraints.hpp b/src/protocols/PointerConstraints.hpp index faf28b32..35d60632 100644 --- a/src/protocols/PointerConstraints.hpp +++ b/src/protocols/PointerConstraints.hpp @@ -16,8 +16,8 @@ class CWLSurfaceResource; class CPointerConstraint { public: - CPointerConstraint(SP resource_, SP surf, wl_resource* region, zwpPointerConstraintsV1Lifetime lifetime); - CPointerConstraint(SP resource_, SP surf, wl_resource* region, zwpPointerConstraintsV1Lifetime lifetime); + CPointerConstraint(SP resource_, SP surf, wl_resource* region, zwpPointerConstraintsV1Lifetime lifetime_); + CPointerConstraint(SP resource_, SP surf, wl_resource* region, zwpPointerConstraintsV1Lifetime lifetime_); ~CPointerConstraint(); bool good(); From 9c5dd59d4b1927b7d88e8e3c2e260eb01d95794b Mon Sep 17 00:00:00 2001 From: Vaxry Date: Sat, 29 Jun 2024 00:23:02 +0200 Subject: [PATCH 0077/2181] input: fix capabilities enum types passed hyprland down to the seat protocol impl expects IHID capabilities, not WL_ ones ref #6702 #6196 --- src/managers/input/InputManager.cpp | 9 +-------- 1 file changed, 1 insertion(+), 8 deletions(-) diff --git a/src/managers/input/InputManager.cpp b/src/managers/input/InputManager.cpp index 81a46f97..b3621520 100644 --- a/src/managers/input/InputManager.cpp +++ b/src/managers/input/InputManager.cpp @@ -1473,14 +1473,7 @@ void CInputManager::updateCapabilities() { if (h.expired()) continue; - auto cap = h->getCapabilities(); - - if (cap & HID_INPUT_CAPABILITY_KEYBOARD) - caps |= WL_SEAT_CAPABILITY_KEYBOARD; - if (cap & HID_INPUT_CAPABILITY_POINTER) - caps |= WL_SEAT_CAPABILITY_POINTER; - if (cap & HID_INPUT_CAPABILITY_TOUCH) - caps |= WL_SEAT_CAPABILITY_TOUCH; + caps |= h->getCapabilities(); } g_pSeatManager->updateCapabilities(caps); From 1f43a5c859bfdf3dc6e880610e21cd9434a4e47b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E3=81=AF=E3=82=8C=E3=81=AA=E3=82=88?= <123649644+harenayo@users.noreply.github.com> Date: Sun, 30 Jun 2024 03:04:48 +0900 Subject: [PATCH 0078/2181] session: fix activate events being always treated as on (#6696) * Fix listener_sessionActive to handle an event correctly when the session get inactivated * Remove log --- src/events/Misc.cpp | 25 ++++++++++++++++++------- src/managers/KeybindManager.cpp | 13 +------------ 2 files changed, 19 insertions(+), 19 deletions(-) diff --git a/src/events/Misc.cpp b/src/events/Misc.cpp index 6580d93e..32f894ec 100644 --- a/src/events/Misc.cpp +++ b/src/events/Misc.cpp @@ -30,14 +30,25 @@ void Events::listener_RendererDestroy(wl_listener* listener, void* data) { } void Events::listener_sessionActive(wl_listener* listener, void* data) { - Debug::log(LOG, "Session got activated!"); + if (g_pCompositor->m_sWLRSession->active) { + Debug::log(LOG, "Session got activated!"); - g_pCompositor->m_bSessionActive = true; + g_pCompositor->m_bSessionActive = true; - for (auto& m : g_pCompositor->m_vMonitors) { - g_pCompositor->scheduleFrameForMonitor(m.get()); - g_pHyprRenderer->applyMonitorRule(m.get(), &m->activeMonitorRule, true); + for (auto& m : g_pCompositor->m_vMonitors) { + g_pCompositor->scheduleFrameForMonitor(m.get()); + g_pHyprRenderer->applyMonitorRule(m.get(), &m->activeMonitorRule, true); + } + + g_pConfigManager->m_bWantsMonitorReload = true; + } else { + Debug::log(LOG, "Session got inactivated!"); + + g_pCompositor->m_bSessionActive = false; + + for (auto& m : g_pCompositor->m_vMonitors) { + m->noFrameSchedule = true; + m->framesToSkip = 1; + } } - - g_pConfigManager->m_bWantsMonitorReload = true; } diff --git a/src/managers/KeybindManager.cpp b/src/managers/KeybindManager.cpp index 005ce392..f66b4457 100644 --- a/src/managers/KeybindManager.cpp +++ b/src/managers/KeybindManager.cpp @@ -810,18 +810,7 @@ bool CKeybindManager::handleVT(xkb_keysym_t keysym) { Debug::log(LOG, "Switching from VT {} to VT {}", ttynum, TTY); - if (!wlr_session_change_vt(g_pCompositor->m_sWLRSession, TTY)) - return true; // probably same session - - g_pCompositor->m_bSessionActive = false; - - for (auto& m : g_pCompositor->m_vMonitors) { - m->noFrameSchedule = true; - m->framesToSkip = 1; - } - - Debug::log(LOG, "Switched to VT {}, destroyed all render data, frames to skip for each: 2", TTY); - + wlr_session_change_vt(g_pCompositor->m_sWLRSession, TTY); return true; } From 718afe271ecebfe6711453b9cfee90fa49a7e761 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E3=81=AF=E3=82=8C=E3=81=AA=E3=82=88?= <123649644+harenayo@users.noreply.github.com> Date: Sun, 30 Jun 2024 03:05:07 +0900 Subject: [PATCH 0079/2181] seat: don't send keyboard data without a keyboard cap (#6697) * Fix #6279: prevent sending keymap or repeat info events by keyboards without keyboard capability * Remove brackets --- src/protocols/core/Seat.cpp | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/src/protocols/core/Seat.cpp b/src/protocols/core/Seat.cpp index f578292a..464a901c 100644 --- a/src/protocols/core/Seat.cpp +++ b/src/protocols/core/Seat.cpp @@ -2,6 +2,7 @@ #include "Compositor.hpp" #include "DataDevice.hpp" #include "../../devices/IKeyboard.hpp" +#include "../../devices/IHID.hpp" #include "../../managers/SeatManager.hpp" #include "../../config/ConfigValue.hpp" #include @@ -451,12 +452,18 @@ void CWLSeatProtocol::updateCapabilities(uint32_t caps) { } void CWLSeatProtocol::updateKeymap() { + if (!(currentCaps & eHIDCapabilityType::HID_INPUT_CAPABILITY_KEYBOARD)) + return; + for (auto& k : m_vKeyboards) { k->sendKeymap(g_pSeatManager->keyboard.lock()); } } void CWLSeatProtocol::updateRepeatInfo(uint32_t rate, uint32_t delayMs) { + if (!(currentCaps & eHIDCapabilityType::HID_INPUT_CAPABILITY_KEYBOARD)) + return; + for (auto& k : m_vKeyboards) { k->repeatInfo(rate, delayMs); } From 8ff9410d2cd39fc1c677799a29f7a063743c0dc9 Mon Sep 17 00:00:00 2001 From: Tom Englund Date: Sun, 30 Jun 2024 13:15:59 +0200 Subject: [PATCH 0080/2181] inputmgr: ensure we dont divide by zero (#6713) some weird combination of scrolling/nesting hyprland and closing a window i managed to divide by zero here, reported by ubsan. add a check to ensure we dont hit UB. --- src/managers/input/InputManager.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/managers/input/InputManager.cpp b/src/managers/input/InputManager.cpp index b3621520..9180e9cd 100644 --- a/src/managers/input/InputManager.cpp +++ b/src/managers/input/InputManager.cpp @@ -798,7 +798,7 @@ void CInputManager::onMouseWheel(IPointer::SAxisEvent e) { } } } - double deltaDiscrete = factor * e.deltaDiscrete / std::abs(e.deltaDiscrete); + double deltaDiscrete = (e.deltaDiscrete != 0) ? (factor * e.deltaDiscrete / std::abs(e.deltaDiscrete)) : 0; g_pSeatManager->sendPointerAxis(e.timeMs, e.axis, factor * e.delta, deltaDiscrete > 0 ? std::ceil(deltaDiscrete) : std::floor(deltaDiscrete), std::round(factor * e.deltaDiscrete), e.source, WL_POINTER_AXIS_RELATIVE_DIRECTION_IDENTICAL); } From 4d6f96f74f9fa6e7b69790fa569ffe60267f8017 Mon Sep 17 00:00:00 2001 From: UjinT34 <41110182+UjinT34@users.noreply.github.com> Date: Sun, 30 Jun 2024 14:16:41 +0300 Subject: [PATCH 0081/2181] debug: add Nvidia driver info (#6715) * add nvidia driver info to systeminfo * check file exists --- src/debug/HyprCtl.cpp | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/debug/HyprCtl.cpp b/src/debug/HyprCtl.cpp index b0a0c477..571aa6d1 100644 --- a/src/debug/HyprCtl.cpp +++ b/src/debug/HyprCtl.cpp @@ -912,7 +912,10 @@ std::string systemInfoRequest(eHyprCtlOutputFormat format, std::string request) #else const std::string GPUINFO = execAndGet("lspci -vnn | grep VGA"); #endif - result += "GPU information: \n" + GPUINFO + "\n\n"; + result += "GPU information: \n" + GPUINFO; + if (GPUINFO.contains("NVIDIA") && std::filesystem::exists("/proc/driver/nvidia/version")) + result += execAndGet("cat /proc/driver/nvidia/version | grep NVRM"); + result += "\n\n"; result += "os-release: " + execAndGet("cat /etc/os-release") + "\n\n"; From d7ea1b7785f31e9fd6477490309721a19a835592 Mon Sep 17 00:00:00 2001 From: Tom Englund Date: Mon, 1 Jul 2024 00:26:08 +0200 Subject: [PATCH 0082/2181] xwayland: break cyclic loop of parents (#6722) in X11 some surfaces is a parent of itself and creates a cyclic loop when trying to find its parent. check for old parent and break if its beginning to roll over. --- src/desktop/Window.cpp | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/desktop/Window.cpp b/src/desktop/Window.cpp index e67a3357..560e5103 100644 --- a/src/desktop/Window.cpp +++ b/src/desktop/Window.cpp @@ -444,9 +444,11 @@ PHLWINDOW CWindow::X11TransientFor() { if (!m_pXWaylandSurface || !m_pXWaylandSurface->parent) return nullptr; - auto s = m_pXWaylandSurface->parent; + auto s = m_pXWaylandSurface->parent; + auto oldParent = s; while (s) { - if (!s->parent) + // break cyclic loop of m_pXWaylandSurface being parent of itself, #TODO reject this from even being created? + if (!s->parent || s->parent == oldParent) break; s = s->parent; } From e58fd3bfb09f329e3a1bd10c42f31f95e8299a98 Mon Sep 17 00:00:00 2001 From: Ikalco <73481042+ikalco@users.noreply.github.com> Date: Tue, 2 Jul 2024 05:14:27 -0500 Subject: [PATCH 0083/2181] meson: fix wlroots-hyprland dep checks (for libliftoff patch to work) (#6736) --- CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index e8f203b4..d41dd6e5 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -57,7 +57,7 @@ ExternalProject_Add( wlroots-hyprland PREFIX ${CMAKE_SOURCE_DIR}/subprojects/wlroots-hyprland SOURCE_DIR ${CMAKE_SOURCE_DIR}/subprojects/wlroots-hyprland - CONFIGURE_COMMAND meson setup --reconfigure build --buildtype=${BUILDTYPE_LOWER} -Dwerror=false -Dxwayland=$,disabled,enabled> -Dexamples=false -Drenderers=gles2 -Dbackends=drm,libinput $,-Db_sanitize=address,-Db_sanitize=none> + CONFIGURE_COMMAND meson setup --reconfigure --clearcache build --buildtype=${BUILDTYPE_LOWER} -Dwerror=false -Dxwayland=$,disabled,enabled> -Dexamples=false -Drenderers=gles2 -Dbackends=drm,libinput $,-Db_sanitize=address,-Db_sanitize=none> BUILD_COMMAND ninja -C build BUILD_ALWAYS true BUILD_IN_SOURCE true From 2fa57f2dc4909be697d003a22ce6870039e4db9b Mon Sep 17 00:00:00 2001 From: drendog <53359960+drendog@users.noreply.github.com> Date: Tue, 2 Jul 2024 12:17:48 +0200 Subject: [PATCH 0084/2181] pointer: change min cursor padding to 0 (#6027) * fix: change min cursor padding to 0 * chore: set default hotspot padding to 0 * fix: adjusting clamp after getting closest point to fix getting off limit point * fix: deal with floating point to clamp to prev value * refactor: max coords to vector * fix: remove box closestPoint adjustment due its fix on hyprutils --- src/config/ConfigManager.cpp | 2 +- src/managers/PointerManager.cpp | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/config/ConfigManager.cpp b/src/config/ConfigManager.cpp index a4a80944..ff9d3a6d 100644 --- a/src/config/ConfigManager.cpp +++ b/src/config/ConfigManager.cpp @@ -525,7 +525,7 @@ CConfigManager::CConfigManager() { m_pConfig->addConfigValue("cursor:no_hardware_cursors", Hyprlang::INT{0}); m_pConfig->addConfigValue("cursor:no_break_fs_vrr", Hyprlang::INT{0}); m_pConfig->addConfigValue("cursor:min_refresh_rate", Hyprlang::INT{24}); - m_pConfig->addConfigValue("cursor:hotspot_padding", Hyprlang::INT{1}); + m_pConfig->addConfigValue("cursor:hotspot_padding", Hyprlang::INT{0}); m_pConfig->addConfigValue("cursor:inactive_timeout", Hyprlang::INT{0}); m_pConfig->addConfigValue("cursor:no_warps", Hyprlang::INT{0}); m_pConfig->addConfigValue("cursor:persistent_warps", Hyprlang::INT{0}); diff --git a/src/managers/PointerManager.cpp b/src/managers/PointerManager.cpp index 2b34f380..8b4ba0ee 100644 --- a/src/managers/PointerManager.cpp +++ b/src/managers/PointerManager.cpp @@ -612,7 +612,7 @@ CBox CPointerManager::getCursorBoxGlobal() { Vector2D CPointerManager::closestValid(const Vector2D& pos) { static auto PADDING = CConfigValue("cursor:hotspot_padding"); - auto CURSOR_PADDING = std::clamp((int)*PADDING, 1, 100); // 1px + auto CURSOR_PADDING = std::clamp((int)*PADDING, 0, 100); CBox hotBox = {{pos.x - CURSOR_PADDING, pos.y - CURSOR_PADDING}, {2 * CURSOR_PADDING, 2 * CURSOR_PADDING}}; // From 6247a6b537fd1c05ecf35420529fab1adf83143e Mon Sep 17 00:00:00 2001 From: Vaxry Date: Tue, 2 Jul 2024 18:40:21 +0200 Subject: [PATCH 0085/2181] renderer: don't skip back background on preBlurQueued fixes #6332 --- src/render/Renderer.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/render/Renderer.cpp b/src/render/Renderer.cpp index 3ea5197e..8d98a182 100644 --- a/src/render/Renderer.cpp +++ b/src/render/Renderer.cpp @@ -864,7 +864,7 @@ void CHyprRenderer::renderAllClientsForWorkspace(CMonitor* pMonitor, PHLWORKSPAC // TODO: check better with solitary after MR for tearing. const auto PFULLWINDOW = pWorkspace ? g_pCompositor->getFullscreenWindowOnWorkspace(pWorkspace->m_iID) : nullptr; if (!pWorkspace->m_bHasFullscreenWindow || pWorkspace->m_efFullscreenMode != FULLSCREEN_FULL || !PFULLWINDOW || PFULLWINDOW->m_vRealSize.isBeingAnimated() || - !PFULLWINDOW->opaque() || pWorkspace->m_vRenderOffset.value() != Vector2D{}) { + !PFULLWINDOW->opaque() || pWorkspace->m_vRenderOffset.value() != Vector2D{} || g_pHyprOpenGL->preBlurQueued()) { if (!g_pHyprOpenGL->m_RenderData.pCurrentMonData->blurFBShouldRender) setOccludedForBackLayers(g_pHyprOpenGL->m_RenderData.damage, pWorkspace); From 8bb75a223db3ea9471d05d74fbed3328334a9f78 Mon Sep 17 00:00:00 2001 From: Lincoln Yuji Date: Tue, 2 Jul 2024 16:04:14 -0300 Subject: [PATCH 0086/2181] hyprctl completions: Use only awk rather than grep + awk Using "awk '//{ print $n }'" is more minimal and slightly faster than using "grep '' | awk '{ print $n }'". Signed-off-by: Lincoln Yuji --- hyprctl/hyprctl.bash | 6 +++--- hyprctl/hyprctl.fish | 6 +++--- hyprctl/hyprctl.zsh | 6 +++--- 3 files changed, 9 insertions(+), 9 deletions(-) diff --git a/hyprctl/hyprctl.bash b/hyprctl/hyprctl.bash index 8386cfbc..c69cca21 100644 --- a/hyprctl/hyprctl.bash +++ b/hyprctl/hyprctl.bash @@ -1,13 +1,13 @@ _hyprctl_cmd_2 () { - hyprctl monitors | grep Monitor | awk '{ print $2 }' + hyprctl monitors | awk '/Monitor/{ print $2 }' } _hyprctl_cmd_3 () { - hyprpm list | grep "Plugin" | awk '{print $4}' + hyprpm list | awk '/Plugin/{ print $4 }' } _hyprctl_cmd_0 () { - hyprctl clients | grep class | awk '{print $2}' + hyprctl clients | awk '/class/{ print $2 }' } _hyprctl_cmd_1 () { diff --git a/hyprctl/hyprctl.fish b/hyprctl/hyprctl.fish index 2a75eb12..c5c03e49 100644 --- a/hyprctl/hyprctl.fish +++ b/hyprctl/hyprctl.fish @@ -1,16 +1,16 @@ function _hyprctl_3 set 1 $argv[1] - hyprctl monitors | grep Monitor | awk '{ print $2 }' + hyprctl monitors | awk '/Monitor/{ print $2 }' end function _hyprctl_4 set 1 $argv[1] - hyprpm list | grep "Plugin" | awk '{print $4}' + hyprpm list | awk '/Plugin/{ print $4 }' end function _hyprctl_1 set 1 $argv[1] - hyprctl clients | grep class | awk '{print $2}' + hyprctl clients | awk '/class/{ print $2 }' end function _hyprctl_2 diff --git a/hyprctl/hyprctl.zsh b/hyprctl/hyprctl.zsh index 1a4cc187..aeac9663 100644 --- a/hyprctl/hyprctl.zsh +++ b/hyprctl/hyprctl.zsh @@ -1,15 +1,15 @@ #compdef hyprctl _hyprctl_cmd_2 () { - hyprctl monitors | grep Monitor | awk '{ print $2 }' + hyprctl monitors | awk '/Monitor/{ print $2 }' } _hyprctl_cmd_3 () { - hyprpm list | grep "Plugin" | awk '{print $4}' + hyprpm list | awk '/Plugin/{ print $4 }' } _hyprctl_cmd_0 () { - hyprctl clients | grep class | awk '{print $2}' + hyprctl clients | awk '/class/{ print $2 }' } _hyprctl_cmd_1 () { From e894d5e964994e988ef75de4d95e98c9503235e1 Mon Sep 17 00:00:00 2001 From: Agent00Ming <107314235+Agent00Ming@users.noreply.github.com> Date: Wed, 3 Jul 2024 15:40:18 -0400 Subject: [PATCH 0087/2181] tablet: Send .frame() on .proximity_out() (#6761) Co-authored-by: Agent_00Ming --- src/protocols/Tablet.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/protocols/Tablet.cpp b/src/protocols/Tablet.cpp index 393dfd38..518ea5bd 100644 --- a/src/protocols/Tablet.cpp +++ b/src/protocols/Tablet.cpp @@ -599,10 +599,10 @@ void CTabletV2Protocol::proximityOut(SP tool) { if (t->tool != tool || !t->current) continue; - t->current = false; t->lastSurf.reset(); t->resource->sendProximityOut(); t->sendFrame(); + t->current = false; } } From 0a6e83005f1910b5c1ec78476fcffc05af47833a Mon Sep 17 00:00:00 2001 From: Lincoln Yuji de Oliveira <63720047+Lincoln-Yuji@users.noreply.github.com> Date: Thu, 4 Jul 2024 08:21:07 -0300 Subject: [PATCH 0088/2181] Completions: use only awk (#6763) --- hyprctl/hyprctl.usage | 6 +++--- hyprpm/hyprpm.bash | 2 +- hyprpm/hyprpm.fish | 2 +- hyprpm/hyprpm.usage | 2 +- hyprpm/hyprpm.zsh | 2 +- 5 files changed, 7 insertions(+), 7 deletions(-) diff --git a/hyprctl/hyprctl.usage b/hyprctl/hyprctl.usage index 64cbbb80..298d253e 100644 --- a/hyprctl/hyprctl.usage +++ b/hyprctl/hyprctl.usage @@ -11,11 +11,11 @@ hyprctl []... | (-q | --quiet) "Disable output" ; - ::= {{{ hyprctl clients | grep class | awk '{print $2}' }}}; + ::= {{{ hyprctl clients | awk '/class/{print $2}' }}}; - ::= {{{ hyprpm list | grep "Plugin" | awk '{print $4}' }}}; + ::= {{{ hyprpm list | awk '/Plugin/{print $4}' }}}; - ::= {{{ hyprctl monitors | grep Monitor | awk '{ print $2 }' }}}; + ::= {{{ hyprctl monitors | awk '/Monitor/{ print $2 }' }}}; ::= {{{ hyprctl devices | sed -n '/Keyboard at/{n; s/^\s\+//; p}' }}}; diff --git a/hyprpm/hyprpm.bash b/hyprpm/hyprpm.bash index 6989f7c1..ffc33e19 100644 --- a/hyprpm/hyprpm.bash +++ b/hyprpm/hyprpm.bash @@ -1,5 +1,5 @@ _hyprpm_cmd_0 () { - hyprpm list | grep Plugin | awk '{print $4}' + hyprpm list | awk '/Plugin/{print $4}' } _hyprpm () { diff --git a/hyprpm/hyprpm.fish b/hyprpm/hyprpm.fish index 81a1c59e..7be4f224 100644 --- a/hyprpm/hyprpm.fish +++ b/hyprpm/hyprpm.fish @@ -1,6 +1,6 @@ function _hyprpm_1 set 1 $argv[1] - hyprpm list | grep Plugin | awk '{print $4}' + hyprpm list | awk '/Plugin/{print $4}' end function _hyprpm diff --git a/hyprpm/hyprpm.usage b/hyprpm/hyprpm.usage index f321faf6..369c9d2b 100644 --- a/hyprpm/hyprpm.usage +++ b/hyprpm/hyprpm.usage @@ -16,4 +16,4 @@ hyprpm []... | (reload) "Reload all plugins" ; - ::= {{{ hyprpm list | grep Plugin | awk '{print $4}' }}}; + ::= {{{ hyprpm list | awk '/Plugin/{print $4}' }}}; diff --git a/hyprpm/hyprpm.zsh b/hyprpm/hyprpm.zsh index e355a1fa..854e8426 100644 --- a/hyprpm/hyprpm.zsh +++ b/hyprpm/hyprpm.zsh @@ -1,7 +1,7 @@ #compdef hyprpm _hyprpm_cmd_0 () { - hyprpm list | grep Plugin | awk '{print $4}' + hyprpm list | awk '/Plugin/{print $4}' } _hyprpm () { From 0502c3f62b1a562e7649ac72bd208b4a89d4f3f4 Mon Sep 17 00:00:00 2001 From: MightyPlaza <123664421+MightyPlaza@users.noreply.github.com> Date: Fri, 5 Jul 2024 20:46:38 +0000 Subject: [PATCH 0089/2181] keybinds: fix movewindow float to 0 (#6777) modified: src/managers/KeybindManager.cpp --- src/managers/KeybindManager.cpp | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) diff --git a/src/managers/KeybindManager.cpp b/src/managers/KeybindManager.cpp index f66b4457..cfc77c10 100644 --- a/src/managers/KeybindManager.cpp +++ b/src/managers/KeybindManager.cpp @@ -1374,20 +1374,21 @@ void CKeybindManager::moveActiveTo(std::string args) { return; if (PLASTWINDOW->m_bIsFloating) { - Vector2D vPos; - const auto PMONITOR = g_pCompositor->getMonitorFromID(PLASTWINDOW->m_iMonitorID); - const auto BORDERSIZE = PLASTWINDOW->getRealBorderSize(); + std::optional vPosx, vPosy; + const auto PMONITOR = g_pCompositor->getMonitorFromID(PLASTWINDOW->m_iMonitorID); + const auto BORDERSIZE = PLASTWINDOW->getRealBorderSize(); switch (arg) { - case 'l': vPos.x = PMONITOR->vecReservedTopLeft.x + BORDERSIZE + PMONITOR->vecPosition.x; break; - case 'r': vPos.x = PMONITOR->vecSize.x - PMONITOR->vecReservedBottomRight.x - PLASTWINDOW->m_vRealSize.goal().x - BORDERSIZE + PMONITOR->vecPosition.x; break; + case 'l': vPosx = PMONITOR->vecReservedTopLeft.x + BORDERSIZE + PMONITOR->vecPosition.x; break; + case 'r': vPosx = PMONITOR->vecSize.x - PMONITOR->vecReservedBottomRight.x - PLASTWINDOW->m_vRealSize.goal().x - BORDERSIZE + PMONITOR->vecPosition.x; break; case 't': - case 'u': vPos.y = PMONITOR->vecReservedTopLeft.y + BORDERSIZE + PMONITOR->vecPosition.y; break; + case 'u': vPosy = PMONITOR->vecReservedTopLeft.y + BORDERSIZE + PMONITOR->vecPosition.y; break; case 'b': - case 'd': vPos.y = PMONITOR->vecSize.y - PMONITOR->vecReservedBottomRight.y - PLASTWINDOW->m_vRealSize.goal().y - BORDERSIZE + PMONITOR->vecPosition.y; break; + case 'd': vPosy = PMONITOR->vecSize.y - PMONITOR->vecReservedBottomRight.y - PLASTWINDOW->m_vRealSize.goal().y - BORDERSIZE + PMONITOR->vecPosition.y; break; } - PLASTWINDOW->m_vRealPosition = Vector2D(vPos.x != 0 ? vPos.x : PLASTWINDOW->m_vRealPosition.goal().x, vPos.y != 0 ? vPos.y : PLASTWINDOW->m_vRealPosition.goal().y); + PLASTWINDOW->m_vRealPosition = Vector2D(vPosx.value_or(PLASTWINDOW->m_vRealPosition.goal().x), vPosy.value_or(PLASTWINDOW->m_vRealPosition.goal().y)); + return; } From cc98594c3aed0b542e03818371a4636f549f80e1 Mon Sep 17 00:00:00 2001 From: Vaxry Date: Fri, 5 Jul 2024 23:05:03 +0200 Subject: [PATCH 0090/2181] pointer: update geometry after unplug events fixes #6700 fixes #6740 --- src/Compositor.cpp | 4 +-- src/managers/PointerManager.cpp | 5 +-- src/managers/eventLoop/EventLoopManager.cpp | 38 ++++++++++++++++----- src/managers/eventLoop/EventLoopManager.hpp | 14 ++++++-- 4 files changed, 46 insertions(+), 15 deletions(-) diff --git a/src/Compositor.cpp b/src/Compositor.cpp index 2ed1a951..f0a2887a 100644 --- a/src/Compositor.cpp +++ b/src/Compositor.cpp @@ -413,7 +413,7 @@ void CCompositor::initManagers(eManagersInitStage stage) { switch (stage) { case STAGE_PRIORITY: { Debug::log(LOG, "Creating the EventLoopManager!"); - g_pEventLoopManager = std::make_unique(); + g_pEventLoopManager = std::make_unique(m_sWLDisplay, m_sWLEventLoop); Debug::log(LOG, "Creating the HookSystem!"); g_pHookSystem = std::make_unique(); @@ -604,7 +604,7 @@ void CCompositor::startCompositor() { // This blocks until we are done. Debug::log(LOG, "Hyprland is ready, running the event loop!"); - g_pEventLoopManager->enterLoop(m_sWLDisplay, m_sWLEventLoop); + g_pEventLoopManager->enterLoop(); } CMonitor* CCompositor::getMonitorFromID(const int& id) { diff --git a/src/managers/PointerManager.cpp b/src/managers/PointerManager.cpp index 8b4ba0ee..e34aa54b 100644 --- a/src/managers/PointerManager.cpp +++ b/src/managers/PointerManager.cpp @@ -4,6 +4,7 @@ #include "../protocols/PointerGestures.hpp" #include "../protocols/FractionalScale.hpp" #include "../protocols/core/Compositor.hpp" +#include "eventLoop/EventLoopManager.hpp" #include "SeatManager.hpp" #include #include @@ -139,8 +140,8 @@ CPointerManager::CPointerManager() { onMonitorLayoutChange(); - PMONITOR->events.modeChanged.registerStaticListener([this](void* owner, std::any data) { onMonitorLayoutChange(); }, nullptr); - PMONITOR->events.disconnect.registerStaticListener([this](void* owner, std::any data) { onMonitorLayoutChange(); }, nullptr); + PMONITOR->events.modeChanged.registerStaticListener([this](void* owner, std::any data) { g_pEventLoopManager->doLater([this]() { onMonitorLayoutChange(); }); }, nullptr); + PMONITOR->events.disconnect.registerStaticListener([this](void* owner, std::any data) { g_pEventLoopManager->doLater([this]() { onMonitorLayoutChange(); }); }, nullptr); PMONITOR->events.destroy.registerStaticListener( [this](void* owner, std::any data) { if (g_pCompositor && !g_pCompositor->m_bIsShuttingDown) diff --git a/src/managers/eventLoop/EventLoopManager.cpp b/src/managers/eventLoop/EventLoopManager.cpp index 1193ffb8..0d1b0223 100644 --- a/src/managers/eventLoop/EventLoopManager.cpp +++ b/src/managers/eventLoop/EventLoopManager.cpp @@ -9,8 +9,10 @@ #define TIMESPEC_NSEC_PER_SEC 1000000000L -CEventLoopManager::CEventLoopManager() { - m_sTimers.timerfd = timerfd_create(CLOCK_MONOTONIC, TFD_CLOEXEC); +CEventLoopManager::CEventLoopManager(wl_display* display, wl_event_loop* wlEventLoop) { + m_sTimers.timerfd = timerfd_create(CLOCK_MONOTONIC, TFD_CLOEXEC); + m_sWayland.loop = wlEventLoop; + m_sWayland.display = display; } CEventLoopManager::~CEventLoopManager() { @@ -23,13 +25,10 @@ static int timerWrite(int fd, uint32_t mask, void* data) { return 1; } -void CEventLoopManager::enterLoop(wl_display* display, wl_event_loop* wlEventLoop) { - m_sWayland.loop = wlEventLoop; - m_sWayland.display = display; +void CEventLoopManager::enterLoop() { + m_sWayland.eventSource = wl_event_loop_add_fd(m_sWayland.loop, m_sTimers.timerfd, WL_EVENT_READABLE, timerWrite, nullptr); - m_sWayland.eventSource = wl_event_loop_add_fd(wlEventLoop, m_sTimers.timerfd, WL_EVENT_READABLE, timerWrite, nullptr); - - wl_display_run(display); + wl_display_run(m_sWayland.display); Debug::log(LOG, "Kicked off the event loop! :("); } @@ -86,4 +85,25 @@ void CEventLoopManager::nudgeTimers() { itimerspec ts = {.it_value = now}; timerfd_settime(m_sTimers.timerfd, TFD_TIMER_ABSTIME, &ts, nullptr); -} \ No newline at end of file +} + +void CEventLoopManager::doLater(const std::function& fn) { + m_sIdle.fns.emplace_back(fn); + + if (m_sIdle.eventSource) + return; + + m_sIdle.eventSource = wl_event_loop_add_idle( + m_sWayland.loop, + [](void* data) { + auto IDLE = (CEventLoopManager::SIdleData*)data; + auto cpy = IDLE->fns; + IDLE->fns.clear(); + IDLE->eventSource = nullptr; + for (auto& c : cpy) { + if (c) + c(); + } + }, + &m_sIdle); +} diff --git a/src/managers/eventLoop/EventLoopManager.hpp b/src/managers/eventLoop/EventLoopManager.hpp index 7a4fa19e..0b2f9578 100644 --- a/src/managers/eventLoop/EventLoopManager.hpp +++ b/src/managers/eventLoop/EventLoopManager.hpp @@ -9,10 +9,10 @@ class CEventLoopManager { public: - CEventLoopManager(); + CEventLoopManager(wl_display* display, wl_event_loop* wlEventLoop); ~CEventLoopManager(); - void enterLoop(wl_display* display, wl_event_loop* wlEventLoop); + void enterLoop(); // Note: will remove the timer if the ptr is lost. void addTimer(SP timer); @@ -23,6 +23,14 @@ class CEventLoopManager { // recalculates timers void nudgeTimers(); + // schedules a function to run later, aka in a wayland idle event. + void doLater(const std::function& fn); + + struct SIdleData { + wl_event_source* eventSource = nullptr; + std::vector> fns; + }; + private: struct { wl_event_loop* loop = nullptr; @@ -34,6 +42,8 @@ class CEventLoopManager { std::vector> timers; int timerfd = -1; } m_sTimers; + + SIdleData m_sIdle; }; inline std::unique_ptr g_pEventLoopManager; \ No newline at end of file From ede1e63f69e0356eaef10e3da30b86862df38e8c Mon Sep 17 00:00:00 2001 From: Maximilian Seidler Date: Fri, 5 Jul 2024 22:58:47 +0200 Subject: [PATCH 0091/2181] config: don't crash when getenv HOME returns null --- src/config/ConfigManager.cpp | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/src/config/ConfigManager.cpp b/src/config/ConfigManager.cpp index ff9d3a6d..12f3ac22 100644 --- a/src/config/ConfigManager.cpp +++ b/src/config/ConfigManager.cpp @@ -633,7 +633,12 @@ std::string CConfigManager::getConfigDir() { if (xdgConfigHome && std::filesystem::path(xdgConfigHome).is_absolute()) return xdgConfigHome; - return getenv("HOME") + std::string("/.config"); + static const char* home = getenv("HOME"); + + if (!home) + throw std::runtime_error("Neither HOME nor XDG_CONFIG_HOME is set in the environment. Cannot determine config directory."); + + return home + std::string("/.config"); } std::string CConfigManager::getMainConfigPath() { From 19fb13e6cf7c9125b471780156fc423118914fb7 Mon Sep 17 00:00:00 2001 From: Yusuf <37774475+Yusuf-Duran@users.noreply.github.com> Date: Sun, 7 Jul 2024 17:52:56 +0200 Subject: [PATCH 0092/2181] internal: Add functions to hyprctl header (#6745) * add functions to hyprctl header * refactor monitor json into own function and add it to header * format hyprctl.hpp * move functions to namespace * move helper functions to class --- src/debug/HyprCtl.cpp | 76 +++++++++++++++++++++++-------------------- src/debug/HyprCtl.hpp | 4 +++ 2 files changed, 45 insertions(+), 35 deletions(-) diff --git a/src/debug/HyprCtl.cpp b/src/debug/HyprCtl.cpp index 571aa6d1..f96c071a 100644 --- a/src/debug/HyprCtl.cpp +++ b/src/debug/HyprCtl.cpp @@ -70,26 +70,13 @@ static std::string availableModesForOutput(CMonitor* pMonitor, eHyprCtlOutputFor return result; } -std::string monitorsRequest(eHyprCtlOutputFormat format, std::string request) { - CVarList vars(request, 0, ' '); - auto allMonitors = false; +std::string CHyprCtl::getMonitorData(Hyprutils::Memory::CSharedPointer m, eHyprCtlOutputFormat format) { + std::string result; + if (!m->output || m->ID == -1ull) + return ""; - if (vars.size() > 2) - return "too many args"; - - if (vars.size() == 2 && vars[1] == "all") - allMonitors = true; - - std::string result = ""; - if (format == eHyprCtlOutputFormat::FORMAT_JSON) { - result += "["; - - for (auto& m : allMonitors ? g_pCompositor->m_vRealMonitors : g_pCompositor->m_vMonitors) { - if (!m->output || m->ID == -1ull) - continue; - - result += std::format( - R"#({{ + result += std::format( + R"#({{ "id": {}, "name": "{}", "description": "{}", @@ -120,14 +107,33 @@ std::string monitorsRequest(eHyprCtlOutputFormat format, std::string request) { "currentFormat": "{}", "availableModes": [{}] }},)#", - m->ID, escapeJSONStrings(m->szName), escapeJSONStrings(m->szShortDescription), escapeJSONStrings(m->output->make ? m->output->make : ""), - escapeJSONStrings(m->output->model ? m->output->model : ""), escapeJSONStrings(m->output->serial ? m->output->serial : ""), (int)m->vecPixelSize.x, - (int)m->vecPixelSize.y, m->refreshRate, (int)m->vecPosition.x, (int)m->vecPosition.y, m->activeWorkspaceID(), - (!m->activeWorkspace ? "" : escapeJSONStrings(m->activeWorkspace->m_szName)), m->activeSpecialWorkspaceID(), - escapeJSONStrings(m->activeSpecialWorkspace ? m->activeSpecialWorkspace->m_szName : ""), (int)m->vecReservedTopLeft.x, (int)m->vecReservedTopLeft.y, - (int)m->vecReservedBottomRight.x, (int)m->vecReservedBottomRight.y, m->scale, (int)m->transform, (m == g_pCompositor->m_pLastMonitor ? "true" : "false"), - (m->dpmsStatus ? "true" : "false"), (m->output->adaptive_sync_status == WLR_OUTPUT_ADAPTIVE_SYNC_ENABLED ? "true" : "false"), - (m->tearingState.activelyTearing ? "true" : "false"), (m->m_bEnabled ? "false" : "true"), formatToString(m->drmFormat), availableModesForOutput(m.get(), format)); + m->ID, escapeJSONStrings(m->szName), escapeJSONStrings(m->szShortDescription), escapeJSONStrings(m->output->make ? m->output->make : ""), + escapeJSONStrings(m->output->model ? m->output->model : ""), escapeJSONStrings(m->output->serial ? m->output->serial : ""), (int)m->vecPixelSize.x, (int)m->vecPixelSize.y, + m->refreshRate, (int)m->vecPosition.x, (int)m->vecPosition.y, m->activeWorkspaceID(), (!m->activeWorkspace ? "" : escapeJSONStrings(m->activeWorkspace->m_szName)), + m->activeSpecialWorkspaceID(), escapeJSONStrings(m->activeSpecialWorkspace ? m->activeSpecialWorkspace->m_szName : ""), (int)m->vecReservedTopLeft.x, + (int)m->vecReservedTopLeft.y, (int)m->vecReservedBottomRight.x, (int)m->vecReservedBottomRight.y, m->scale, (int)m->transform, + (m == g_pCompositor->m_pLastMonitor ? "true" : "false"), (m->dpmsStatus ? "true" : "false"), + (m->output->adaptive_sync_status == WLR_OUTPUT_ADAPTIVE_SYNC_ENABLED ? "true" : "false"), (m->tearingState.activelyTearing ? "true" : "false"), + (m->m_bEnabled ? "false" : "true"), formatToString(m->drmFormat), availableModesForOutput(m.get(), format)); + return result; +} + +std::string monitorsRequest(eHyprCtlOutputFormat format, std::string request) { + CVarList vars(request, 0, ' '); + auto allMonitors = false; + + if (vars.size() > 2) + return "too many args"; + + if (vars.size() == 2 && vars[1] == "all") + allMonitors = true; + + std::string result = ""; + if (format == eHyprCtlOutputFormat::FORMAT_JSON) { + result += "["; + + for (auto& m : allMonitors ? g_pCompositor->m_vRealMonitors : g_pCompositor->m_vMonitors) { + result += CHyprCtl::getMonitorData(m, format); } trimTrailingComma(result); @@ -188,7 +194,7 @@ static std::string getGroupedData(PHLWINDOW w, eHyprCtlOutputFormat format) { return result.str(); } -static std::string getWindowData(PHLWINDOW w, eHyprCtlOutputFormat format) { +std::string CHyprCtl::getWindowData(PHLWINDOW w, eHyprCtlOutputFormat format) { auto getFocusHistoryID = [](PHLWINDOW wnd) -> int { for (size_t i = 0; i < g_pCompositor->m_vWindowFocusHistory.size(); ++i) { if (g_pCompositor->m_vWindowFocusHistory[i].lock() == wnd) @@ -257,7 +263,7 @@ std::string clientsRequest(eHyprCtlOutputFormat format, std::string request) { if (!w->m_bIsMapped && !g_pHyprCtl->m_sCurrentRequestParams.all) continue; - result += getWindowData(w, format); + result += CHyprCtl::getWindowData(w, format); } trimTrailingComma(result); @@ -268,13 +274,13 @@ std::string clientsRequest(eHyprCtlOutputFormat format, std::string request) { if (!w->m_bIsMapped && !g_pHyprCtl->m_sCurrentRequestParams.all) continue; - result += getWindowData(w, format); + result += CHyprCtl::getWindowData(w, format); } } return result; } -static std::string getWorkspaceData(PHLWORKSPACE w, eHyprCtlOutputFormat format) { +std::string CHyprCtl::getWorkspaceData(PHLWORKSPACE w, eHyprCtlOutputFormat format) { const auto PLASTW = w->getLastFocusedWindow(); const auto PMONITOR = g_pCompositor->getMonitorFromID(w->m_iMonitorID); if (format == eHyprCtlOutputFormat::FORMAT_JSON) { @@ -354,7 +360,7 @@ std::string activeWorkspaceRequest(eHyprCtlOutputFormat format, std::string requ if (!valid(w)) return "internal error"; - return getWorkspaceData(w, format); + return CHyprCtl::getWorkspaceData(w, format); } std::string workspacesRequest(eHyprCtlOutputFormat format, std::string request) { @@ -363,7 +369,7 @@ std::string workspacesRequest(eHyprCtlOutputFormat format, std::string request) if (format == eHyprCtlOutputFormat::FORMAT_JSON) { result += "["; for (auto& w : g_pCompositor->m_vWorkspaces) { - result += getWorkspaceData(w, format); + result += CHyprCtl::getWorkspaceData(w, format); result += ","; } @@ -371,7 +377,7 @@ std::string workspacesRequest(eHyprCtlOutputFormat format, std::string request) result += "]"; } else { for (auto& w : g_pCompositor->m_vWorkspaces) { - result += getWorkspaceData(w, format); + result += CHyprCtl::getWorkspaceData(w, format); } } @@ -404,7 +410,7 @@ std::string activeWindowRequest(eHyprCtlOutputFormat format, std::string request if (!validMapped(PWINDOW)) return format == eHyprCtlOutputFormat::FORMAT_JSON ? "{}" : "Invalid"; - auto result = getWindowData(PWINDOW, format); + auto result = CHyprCtl::getWindowData(PWINDOW, format); if (format == eHyprCtlOutputFormat::FORMAT_JSON) result.pop_back(); diff --git a/src/debug/HyprCtl.hpp b/src/debug/HyprCtl.hpp index 21a2c5f8..ccbd40cd 100644 --- a/src/debug/HyprCtl.hpp +++ b/src/debug/HyprCtl.hpp @@ -22,6 +22,10 @@ class CHyprCtl { bool sysInfoConfig = false; } m_sCurrentRequestParams; + static std::string getWindowData(PHLWINDOW w, eHyprCtlOutputFormat format); + static std::string getWorkspaceData(PHLWORKSPACE w, eHyprCtlOutputFormat format); + static std::string getMonitorData(Hyprutils::Memory::CSharedPointer m, eHyprCtlOutputFormat format); + private: void startHyprCtlSocket(); From 22138ac259b2f4253be29311f6b60fbd675074b4 Mon Sep 17 00:00:00 2001 From: Virt <41426325+VirtCode@users.noreply.github.com> Date: Sun, 7 Jul 2024 21:27:18 +0200 Subject: [PATCH 0093/2181] workspaces: don't try to reopen special workspaces (#6802) --- src/helpers/Monitor.cpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/helpers/Monitor.cpp b/src/helpers/Monitor.cpp index 199b1c5d..20c2e81e 100644 --- a/src/helpers/Monitor.cpp +++ b/src/helpers/Monitor.cpp @@ -652,6 +652,9 @@ void CMonitor::changeWorkspace(const int& id, bool internal, bool noMouseMove, b } void CMonitor::setSpecialWorkspace(const PHLWORKSPACE& pWorkspace) { + if (activeSpecialWorkspace == pWorkspace) + return; + g_pHyprRenderer->damageMonitor(this); if (!pWorkspace) { From 648f824b9e9ba58cc49962b0c58fc90892da2bda Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andr=C3=A9=20Silva?= Date: Mon, 8 Jul 2024 15:30:10 +0100 Subject: [PATCH 0094/2181] flake.lock: update --- flake.lock | 42 +++++++++++++++++++++--------------------- 1 file changed, 21 insertions(+), 21 deletions(-) diff --git a/flake.lock b/flake.lock index c1f37d2e..d3f40397 100644 --- a/flake.lock +++ b/flake.lock @@ -13,11 +13,11 @@ ] }, "locked": { - "lastModified": 1718450675, - "narHash": "sha256-jpsns6buS4bK+1sF8sL8AaixAiCRjA+nldTKvcwmvUs=", + "lastModified": 1720108799, + "narHash": "sha256-AxRkTJlbB8r7aG6gvc7IaLhc2T9TO4/8uqanKRxukBQ=", "owner": "hyprwm", "repo": "hyprcursor", - "rev": "66d5b46ff94efbfa6fa3d1d1b66735f1779c34a6", + "rev": "a5c0d57325c5f0814c39110a70ca19c070ae9486", "type": "github" }, "original": { @@ -38,11 +38,11 @@ ] }, "locked": { - "lastModified": 1714869498, - "narHash": "sha256-vbLVOWvQqo4n1yvkg/Q70VTlPbMmTiCQfNTgcWDCfJM=", + "lastModified": 1718746314, + "narHash": "sha256-HUklK5u86w2Yh9dOkk4FdsL8eehcOZ95jPhLixGDRQY=", "owner": "hyprwm", "repo": "hyprland-protocols", - "rev": "e06482e0e611130cd1929f75e8c1cf679e57d161", + "rev": "1b61f0093afff20ab44d88ad707aed8bf2215290", "type": "github" }, "original": { @@ -64,11 +64,11 @@ ] }, "locked": { - "lastModified": 1717881852, - "narHash": "sha256-XeeVoKHQgfKuXoP6q90sUqKyl7EYy3ol2dVZGM+Jj94=", + "lastModified": 1720381373, + "narHash": "sha256-lyC/EZdHULsaAKVryK11lgHY9u6pXr7qR4irnxNWC7k=", "owner": "hyprwm", "repo": "hyprlang", - "rev": "ec6938c66253429192274d612912649a0cfe4d28", + "rev": "5df0174fd09de4ac5475233d65ffc703e89b82eb", "type": "github" }, "original": { @@ -87,11 +87,11 @@ ] }, "locked": { - "lastModified": 1719316102, - "narHash": "sha256-dmRz128j/lJmMuTYeCYPfSBRHHQO3VeH4PbmoyAhHzw=", + "lastModified": 1720203444, + "narHash": "sha256-lq2dPPPcwMHTLsFrQ2pRp4c2LwDZWoqzSyjuPdeJCP4=", "owner": "hyprwm", "repo": "hyprutils", - "rev": "1f6bbec5954f623ff8d68e567bddcce97cd2f085", + "rev": "a8c3a135701a7b64db0a88ec353a392f402d2a87", "type": "github" }, "original": { @@ -110,11 +110,11 @@ ] }, "locked": { - "lastModified": 1719067853, - "narHash": "sha256-mAnZG/eQy72Fp1ImGtqCgUrDumnR1rMZv2E/zgP4U74=", + "lastModified": 1720215857, + "narHash": "sha256-JPdL+Qul+jEueAn8CARfcWP83eJgwkhMejQYfDvrgvU=", "owner": "hyprwm", "repo": "hyprwayland-scanner", - "rev": "914f083741e694092ee60a39d31f693d0a6dc734", + "rev": "d5fa094ca27e0039be5e94c0a80ae433145af8bb", "type": "github" }, "original": { @@ -125,11 +125,11 @@ }, "nixpkgs": { "locked": { - "lastModified": 1719075281, - "narHash": "sha256-CyyxvOwFf12I91PBWz43iGT1kjsf5oi6ax7CrvaMyAo=", + "lastModified": 1720031269, + "narHash": "sha256-rwz8NJZV+387rnWpTYcXaRNvzUSnnF9aHONoJIYmiUQ=", "owner": "NixOS", "repo": "nixpkgs", - "rev": "a71e967ef3694799d0c418c98332f7ff4cc5f6af", + "rev": "9f4128e00b0ae8ec65918efeba59db998750ead6", "type": "github" }, "original": { @@ -179,11 +179,11 @@ ] }, "locked": { - "lastModified": 1718619174, - "narHash": "sha256-FWW68AVYmB91ZDQnhLMBNCUUTCjb1ZpO2k2KIytHtkA=", + "lastModified": 1720194466, + "narHash": "sha256-Rizg9efi6ue95zOp0MeIV2ZedNo+5U9G2l6yirgBUnA=", "owner": "hyprwm", "repo": "xdg-desktop-portal-hyprland", - "rev": "c7894aa54f9a7dbd16df5cd24d420c8af22d5623", + "rev": "b9b97e5ba23fe7bd5fa4df54696102e8aa863cf6", "type": "github" }, "original": { From b03f41efec14273cf25c42d4cef326acc36cb319 Mon Sep 17 00:00:00 2001 From: Ikalco <73481042+ikalco@users.noreply.github.com> Date: Mon, 8 Jul 2024 10:46:42 -0500 Subject: [PATCH 0095/2181] xwayland: fix setting title prop (#6809) * fix setting xwayland title prop * add window title types --- src/xwayland/XWM.cpp | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/src/xwayland/XWM.cpp b/src/xwayland/XWM.cpp index aa38910f..b34d0cfe 100644 --- a/src/xwayland/XWM.cpp +++ b/src/xwayland/XWM.cpp @@ -153,7 +153,7 @@ static bool lookupParentExists(SP XSURF, SP } void CXWM::readProp(SP XSURF, uint32_t atom, xcb_get_property_reply_t* reply) { - std::string propName = "?"; + std::string propName = std::format("{}?", atom); for (auto& ha : HYPRATOMS) { if (ha.second != atom) continue; @@ -172,8 +172,10 @@ void CXWM::readProp(SP XSURF, uint32_t atom, xcb_get_property_ XSURF->state.appid.pop_back(); XSURF->events.metadataChanged.emit(); } else if (atom == XCB_ATOM_WM_NAME || atom == HYPRATOMS["_NET_WM_NAME"]) { - size_t len = xcb_get_property_value_length(reply); - char* string = (char*)xcb_get_property_value(reply); + size_t len = xcb_get_property_value_length(reply); + char* string = (char*)xcb_get_property_value(reply); + if (reply->type != HYPRATOMS["UTF8_STRING"] && reply->type != HYPRATOMS["TEXT"] && reply->type != XCB_ATOM_STRING) + return; XSURF->state.title = std::string{string, len}; XSURF->events.metadataChanged.emit(); } else if (atom == HYPRATOMS["_NET_WM_WINDOW_TYPE"]) { @@ -520,7 +522,7 @@ bool CXWM::handleSelectionPropertyNotify(xcb_property_notify_event_t* e) { // Debug::log(ERR, "[xwm] FIXME: CXWM::handleSelectionPropertyNotify stub"); - return true; + return false; } void CXWM::handleSelectionRequest(xcb_selection_request_event_t* e) { From a443902abca6549839910720b80bd01faf10f387 Mon Sep 17 00:00:00 2001 From: MightyPlaza <123664421+MightyPlaza@users.noreply.github.com> Date: Thu, 11 Jul 2024 14:10:42 +0000 Subject: [PATCH 0096/2181] core: Improve handling of window properties (#6776) * add mWindowProperties modified: src/debug/HyprCtl.cpp modified: src/desktop/Window.cpp modified: src/desktop/Window.hpp modified: src/events/Windows.cpp * support int values modified: src/debug/HyprCtl.cpp modified: src/desktop/Window.cpp modified: src/desktop/Window.hpp * create m_sWindowData modified: src/Compositor.cpp modified: src/debug/HyprCtl.cpp modified: src/desktop/Window.cpp modified: src/desktop/Window.hpp modified: src/events/Windows.cpp modified: src/layout/DwindleLayout.cpp modified: src/layout/IHyprLayout.cpp modified: src/layout/MasterLayout.cpp modified: src/managers/AnimationManager.cpp modified: src/managers/KeybindManager.cpp modified: src/managers/XWaylandManager.cpp modified: src/render/OpenGL.cpp modified: src/render/Renderer.cpp modified: src/render/decorations/CHyprBorderDecoration.cpp modified: src/render/decorations/CHyprDropShadowDecoration.cpp modified: src/render/decorations/CHyprGroupBarDecoration.cpp * simplify some properties modified: src/Compositor.cpp modified: src/debug/HyprCtl.cpp modified: src/desktop/Window.cpp modified: src/desktop/Window.hpp modified: src/managers/KeybindManager.cpp * store multiple values in CWindowOverridableVar modified: src/Compositor.cpp modified: src/debug/HyprCtl.cpp modified: src/desktop/Window.cpp modified: src/desktop/Window.hpp modified: src/events/Windows.cpp modified: src/layout/IHyprLayout.cpp modified: src/managers/AnimationManager.cpp modified: src/managers/KeybindManager.cpp modified: src/managers/XWaylandManager.cpp modified: src/render/OpenGL.cpp modified: src/render/Renderer.cpp modified: src/render/decorations/CHyprBorderDecoration.cpp modified: src/render/decorations/CHyprDropShadowDecoration.cpp modified: src/render/decorations/CHyprGroupBarDecoration.cpp * clean up modified: src/Compositor.cpp modified: src/Compositor.hpp modified: src/config/ConfigManager.cpp modified: src/config/ConfigManager.hpp modified: src/debug/HyprCtl.cpp modified: src/desktop/Window.cpp modified: src/desktop/Window.hpp modified: src/events/Windows.cpp modified: src/layout/DwindleLayout.cpp modified: src/layout/IHyprLayout.cpp modified: src/layout/IHyprLayout.hpp modified: src/layout/MasterLayout.cpp modified: src/managers/KeybindManager.cpp * use SET_PROP priority for exec rules modified: src/config/ConfigManager.hpp modified: src/desktop/Window.cpp * add default value modified: src/Compositor.cpp modified: src/debug/HyprCtl.cpp modified: src/desktop/Window.cpp modified: src/desktop/Window.hpp modified: src/events/Windows.cpp modified: src/layout/IHyprLayout.cpp modified: src/managers/KeybindManager.cpp modified: src/managers/XWaylandManager.cpp modified: src/render/OpenGL.cpp modified: src/render/Renderer.cpp modified: src/render/decorations/CHyprBorderDecoration.cpp modified: src/render/decorations/CHyprDropShadowDecoration.cpp modified: src/render/decorations/CHyprGroupBarDecoration.cpp * add setprop toggle modified: src/config/ConfigManager.hpp modified: src/debug/HyprCtl.cpp modified: src/desktop/Window.cpp * add setprop toggle modified: src/debug/HyprCtl.cpp * make window rules functional modified: src/config/ConfigManager.cpp modified: src/desktop/Window.cpp * minor fixes modified: src/Compositor.cpp modified: src/debug/HyprCtl.cpp modified: src/desktop/Window.hpp * properly clean layout data modified: src/desktop/Window.cpp modified: src/desktop/Window.hpp modified: src/events/Windows.cpp modified: src/layout/DwindleLayout.cpp modified: src/layout/IHyprLayout.cpp modified: src/layout/IHyprLayout.hpp modified: src/layout/MasterLayout.cpp * remove newline modified: src/events/Windows.cpp * fixes modified: src/config/ConfigManager.hpp modified: src/debug/HyprCtl.cpp modified: src/desktop/Window.cpp modified: src/desktop/Window.hpp * use CamelCase modified: src/Compositor.cpp modified: src/debug/HyprCtl.cpp modified: src/desktop/Window.cpp modified: src/desktop/Window.hpp modified: src/events/Windows.cpp modified: src/layout/IHyprLayout.cpp modified: src/managers/AnimationManager.cpp modified: src/managers/KeybindManager.cpp modified: src/managers/XWaylandManager.cpp modified: src/render/OpenGL.cpp modified: src/render/Renderer.cpp modified: src/render/decorations/CHyprBorderDecoration.cpp modified: src/render/decorations/CHyprDropShadowDecoration.cpp modified: src/render/decorations/CHyprGroupBarDecoration.cpp --- src/Compositor.cpp | 43 ++-- src/Compositor.hpp | 2 +- src/config/ConfigManager.cpp | 29 +-- src/config/ConfigManager.hpp | 68 ++++-- src/debug/HyprCtl.cpp | 126 ++++------- src/desktop/Window.cpp | 210 +++++++----------- src/desktop/Window.hpp | 176 +++++++-------- src/events/Windows.cpp | 22 +- src/layout/DwindleLayout.cpp | 14 +- src/layout/IHyprLayout.cpp | 16 +- src/layout/MasterLayout.cpp | 14 +- src/managers/AnimationManager.cpp | 13 +- src/managers/KeybindManager.cpp | 7 +- src/managers/XWaylandManager.cpp | 3 +- src/render/OpenGL.cpp | 16 +- src/render/Renderer.cpp | 12 +- .../decorations/CHyprBorderDecoration.cpp | 2 +- .../decorations/CHyprDropShadowDecoration.cpp | 7 +- .../decorations/CHyprGroupBarDecoration.cpp | 4 +- 19 files changed, 364 insertions(+), 420 deletions(-) diff --git a/src/Compositor.cpp b/src/Compositor.cpp index f0a2887a..2abc1144 100644 --- a/src/Compositor.cpp +++ b/src/Compositor.cpp @@ -702,7 +702,7 @@ PHLWINDOW CCompositor::vectorToWindowUnified(const Vector2D& pos, uint8_t proper for (auto& w : m_vWindows | std::views::reverse) { const auto BB = w->getWindowBoxUnified(properties); CBox box = BB.copy().expand(w->m_iX11Type == 2 ? BORDER_GRAB_AREA : 0); - if (w->m_bIsFloating && w->m_bIsMapped && !w->isHidden() && !w->m_bX11ShouldntFocus && w->m_bPinned && !w->m_sAdditionalConfigData.noFocus && w != pIgnoreWindow) { + if (w->m_bIsFloating && w->m_bIsMapped && !w->isHidden() && !w->m_bX11ShouldntFocus && w->m_bPinned && !w->m_sWindowData.noFocus.valueOrDefault() && w != pIgnoreWindow) { if (box.containsPoint(g_pPointerManager->position())) return w; @@ -731,7 +731,7 @@ PHLWINDOW CCompositor::vectorToWindowUnified(const Vector2D& pos, uint8_t proper continue; CBox box = BB.copy().expand(w->m_iX11Type == 2 ? BORDER_GRAB_AREA : 0); - if (w->m_bIsFloating && w->m_bIsMapped && isWorkspaceVisible(w->m_pWorkspace) && !w->isHidden() && !w->m_bPinned && !w->m_sAdditionalConfigData.noFocus && + if (w->m_bIsFloating && w->m_bIsMapped && isWorkspaceVisible(w->m_pWorkspace) && !w->isHidden() && !w->m_bPinned && !w->m_sWindowData.noFocus.valueOrDefault() && w != pIgnoreWindow && (!aboveFullscreen || w->m_bCreatedOverFullscreen)) { // OR windows should add focus to parent if (w->m_bX11ShouldntFocus && w->m_iX11Type != 2) @@ -784,7 +784,7 @@ PHLWINDOW CCompositor::vectorToWindowUnified(const Vector2D& pos, uint8_t proper continue; if (!w->m_bIsX11 && !w->m_bIsFloating && w->m_bIsMapped && w->workspaceID() == WORKSPACEID && !w->isHidden() && !w->m_bX11ShouldntFocus && - !w->m_sAdditionalConfigData.noFocus && w != pIgnoreWindow) { + !w->m_sWindowData.noFocus.valueOrDefault() && w != pIgnoreWindow) { if (w->hasPopupAt(pos)) return w; } @@ -796,7 +796,7 @@ PHLWINDOW CCompositor::vectorToWindowUnified(const Vector2D& pos, uint8_t proper CBox box = (properties & USE_PROP_TILED) ? w->getWindowBoxUnified(properties) : CBox{w->m_vPosition, w->m_vSize}; if (!w->m_bIsFloating && w->m_bIsMapped && box.containsPoint(pos) && w->workspaceID() == WORKSPACEID && !w->isHidden() && !w->m_bX11ShouldntFocus && - !w->m_sAdditionalConfigData.noFocus && w != pIgnoreWindow) + !w->m_sWindowData.noFocus.valueOrDefault() && w != pIgnoreWindow) return w; } @@ -940,7 +940,7 @@ void CCompositor::focusWindow(PHLWINDOW pWindow, SP pSurface return; } - if (pWindow->m_sAdditionalConfigData.noFocus) { + if (pWindow->m_sWindowData.noFocus.valueOrDefault()) { Debug::log(LOG, "Ignoring focus to nofocus window!"); return; } @@ -1579,7 +1579,7 @@ PHLWINDOW CCompositor::getNextWindowOnWorkspace(PHLWINDOW pWindow, bool focusabl if (floating.has_value() && w->m_bIsFloating != floating.value()) continue; - if (w->m_pWorkspace == pWindow->m_pWorkspace && w->m_bIsMapped && !w->isHidden() && (!focusableOnly || !w->m_sAdditionalConfigData.noFocus)) + if (w->m_pWorkspace == pWindow->m_pWorkspace && w->m_bIsMapped && !w->isHidden() && (!focusableOnly || !w->m_sWindowData.noFocus.valueOrDefault())) return w; } @@ -1587,7 +1587,7 @@ PHLWINDOW CCompositor::getNextWindowOnWorkspace(PHLWINDOW pWindow, bool focusabl if (floating.has_value() && w->m_bIsFloating != floating.value()) continue; - if (w != pWindow && w->m_pWorkspace == pWindow->m_pWorkspace && w->m_bIsMapped && !w->isHidden() && (!focusableOnly || !w->m_sAdditionalConfigData.noFocus)) + if (w != pWindow && w->m_pWorkspace == pWindow->m_pWorkspace && w->m_bIsMapped && !w->isHidden() && (!focusableOnly || !w->m_sWindowData.noFocus.valueOrDefault())) return w; } @@ -1608,7 +1608,7 @@ PHLWINDOW CCompositor::getPrevWindowOnWorkspace(PHLWINDOW pWindow, bool focusabl if (floating.has_value() && w->m_bIsFloating != floating.value()) continue; - if (w->m_pWorkspace == pWindow->m_pWorkspace && w->m_bIsMapped && !w->isHidden() && (!focusableOnly || !w->m_sAdditionalConfigData.noFocus)) + if (w->m_pWorkspace == pWindow->m_pWorkspace && w->m_bIsMapped && !w->isHidden() && (!focusableOnly || !w->m_sWindowData.noFocus.valueOrDefault())) return w; } @@ -1616,7 +1616,7 @@ PHLWINDOW CCompositor::getPrevWindowOnWorkspace(PHLWINDOW pWindow, bool focusabl if (floating.has_value() && w->m_bIsFloating != floating.value()) continue; - if (w != pWindow && w->m_pWorkspace == pWindow->m_pWorkspace && w->m_bIsMapped && !w->isHidden() && (!focusableOnly || !w->m_sAdditionalConfigData.noFocus)) + if (w != pWindow && w->m_pWorkspace == pWindow->m_pWorkspace && w->m_bIsMapped && !w->isHidden() && (!focusableOnly || !w->m_sWindowData.noFocus.valueOrDefault())) return w; } @@ -1804,13 +1804,11 @@ void CCompositor::updateWindowAnimatedDecorationValues(PHLWINDOW pWindow) { if (pWindow == m_pLastWindow) { const auto* const ACTIVECOLOR = !pWindow->m_sGroupData.pNextWindow.lock() ? (!pWindow->m_sGroupData.deny ? ACTIVECOL : NOGROUPACTIVECOL) : (GROUPLOCKED ? GROUPACTIVELOCKEDCOL : GROUPACTIVECOL); - setBorderColor(pWindow->m_sSpecialRenderData.activeBorderColor.toUnderlying().m_vColors.empty() ? *ACTIVECOLOR : - pWindow->m_sSpecialRenderData.activeBorderColor.toUnderlying()); + setBorderColor(pWindow->m_sWindowData.activeBorderColor.valueOr(*ACTIVECOLOR)); } else { const auto* const INACTIVECOLOR = !pWindow->m_sGroupData.pNextWindow.lock() ? (!pWindow->m_sGroupData.deny ? INACTIVECOL : NOGROUPINACTIVECOL) : (GROUPLOCKED ? GROUPINACTIVELOCKEDCOL : GROUPINACTIVECOL); - setBorderColor(pWindow->m_sSpecialRenderData.inactiveBorderColor.toUnderlying().m_vColors.empty() ? *INACTIVECOLOR : - pWindow->m_sSpecialRenderData.inactiveBorderColor.toUnderlying()); + setBorderColor(pWindow->m_sWindowData.inactiveBorderColor.valueOr(*INACTIVECOLOR)); } } @@ -1821,23 +1819,16 @@ void CCompositor::updateWindowAnimatedDecorationValues(PHLWINDOW pWindow) { // opacity const auto PWORKSPACE = pWindow->m_pWorkspace; if (pWindow->m_bIsFullscreen && PWORKSPACE->m_efFullscreenMode == FULLSCREEN_FULL) { - pWindow->m_fActiveInactiveAlpha = pWindow->m_sSpecialRenderData.alphaFullscreen.toUnderlying() != -1 ? - (pWindow->m_sSpecialRenderData.alphaFullscreenOverride.toUnderlying() ? pWindow->m_sSpecialRenderData.alphaFullscreen.toUnderlying() : - pWindow->m_sSpecialRenderData.alphaFullscreen.toUnderlying() * *PFULLSCREENALPHA) : - *PFULLSCREENALPHA; + pWindow->m_fActiveInactiveAlpha = pWindow->m_sWindowData.alphaFullscreen.valueOrDefault().applyAlpha(*PFULLSCREENALPHA); } else { if (pWindow == m_pLastWindow) - pWindow->m_fActiveInactiveAlpha = pWindow->m_sSpecialRenderData.alphaOverride.toUnderlying() ? pWindow->m_sSpecialRenderData.alpha.toUnderlying() : - pWindow->m_sSpecialRenderData.alpha.toUnderlying() * *PACTIVEALPHA; + pWindow->m_fActiveInactiveAlpha = pWindow->m_sWindowData.alpha.valueOrDefault().applyAlpha(*PACTIVEALPHA); else - pWindow->m_fActiveInactiveAlpha = pWindow->m_sSpecialRenderData.alphaInactive.toUnderlying() != -1 ? - (pWindow->m_sSpecialRenderData.alphaInactiveOverride.toUnderlying() ? pWindow->m_sSpecialRenderData.alphaInactive.toUnderlying() : - pWindow->m_sSpecialRenderData.alphaInactive.toUnderlying() * *PINACTIVEALPHA) : - *PINACTIVEALPHA; + pWindow->m_fActiveInactiveAlpha = pWindow->m_sWindowData.alphaInactive.valueOrDefault().applyAlpha(*PINACTIVEALPHA); } // dim - if (pWindow == m_pLastWindow.lock() || pWindow->m_sAdditionalConfigData.forceNoDim || !*PDIMENABLED) { + if (pWindow == m_pLastWindow.lock() || pWindow->m_sWindowData.noDim.valueOrDefault() || !*PDIMENABLED) { pWindow->m_fDimPercent = 0; } else { pWindow->m_fDimPercent = *PDIMSTRENGTH; @@ -2268,7 +2259,7 @@ void CCompositor::updateWorkspaceWindowDecos(const int& id) { } } -void CCompositor::updateWorkspaceSpecialRenderData(const int& id) { +void CCompositor::updateWorkspaceWindowData(const int& id) { const auto PWORKSPACE = getWorkspaceByID(id); const auto WORKSPACERULE = PWORKSPACE ? g_pConfigManager->getWorkspaceRuleFor(PWORKSPACE) : SWorkspaceRule{}; @@ -2276,7 +2267,7 @@ void CCompositor::updateWorkspaceSpecialRenderData(const int& id) { if (w->workspaceID() != id) continue; - w->updateSpecialRenderData(WORKSPACERULE); + w->updateWindowData(WORKSPACERULE); } } diff --git a/src/Compositor.hpp b/src/Compositor.hpp index 5a1d8a64..17db2c8b 100644 --- a/src/Compositor.hpp +++ b/src/Compositor.hpp @@ -127,7 +127,7 @@ class CCompositor { PHLWORKSPACE getWorkspaceByString(const std::string&); void sanityCheckWorkspaces(); void updateWorkspaceWindowDecos(const int&); - void updateWorkspaceSpecialRenderData(const int&); + void updateWorkspaceWindowData(const int&); int getWindowsOnWorkspace(const int& id, std::optional onlyTiled = {}, std::optional onlyVisible = {}); int getGroupsOnWorkspace(const int& id, std::optional onlyTiled = {}, std::optional onlyVisible = {}); PHLWINDOW getUrgentWindow(); diff --git a/src/config/ConfigManager.cpp b/src/config/ConfigManager.cpp index 12f3ac22..01fac7cf 100644 --- a/src/config/ConfigManager.cpp +++ b/src/config/ConfigManager.cpp @@ -844,7 +844,7 @@ void CConfigManager::postConfigReload(const Hyprlang::CParseResult& result) { if (w->inert()) continue; g_pCompositor->updateWorkspaceWindows(w->m_iID); - g_pCompositor->updateWorkspaceSpecialRenderData(w->m_iID); + g_pCompositor->updateWorkspaceWindowData(w->m_iID); } // Update window border colors @@ -1058,14 +1058,14 @@ SWorkspaceRule CConfigManager::mergeWorkspaceRules(const SWorkspaceRule& rule1, mergedRule.gapsOut = rule2.gapsOut; if (rule2.borderSize.has_value()) mergedRule.borderSize = rule2.borderSize; - if (rule2.border.has_value()) - mergedRule.border = rule2.border; - if (rule2.rounding.has_value()) - mergedRule.rounding = rule2.rounding; + if (rule2.noBorder.has_value()) + mergedRule.noBorder = rule2.noBorder; + if (rule2.noRounding.has_value()) + mergedRule.noRounding = rule2.noRounding; if (rule2.decorate.has_value()) mergedRule.decorate = rule2.decorate; - if (rule2.shadow.has_value()) - mergedRule.shadow = rule2.shadow; + if (rule2.noShadow.has_value()) + mergedRule.noShadow = rule2.noShadow; if (rule2.onCreatedEmptyRunCmd.has_value()) mergedRule.onCreatedEmptyRunCmd = rule2.onCreatedEmptyRunCmd; if (rule2.defaultName.has_value()) @@ -2086,16 +2086,17 @@ std::optional CConfigManager::handleUnbind(const std::string& comma bool windowRuleValid(const std::string& RULE) { static const auto rules = std::unordered_set{ - "dimaround", "fakefullscreen", "float", "focusonactivate", "forceinput", "forcergbx", "fullscreen", "immediate", - "keepaspectratio", "maximize", "nearestneighbor", "noanim", "noblur", "noborder", "nodim", "nofocus", - "noinitialfocus", "nomaxsize", "noshadow", "opaque", "pin", "stayfocused", "tile", "windowdance", + "fakefullscreen", "float", "fullscreen", "maximize", "noinitialfocus", "pin", "stayfocused", "tile", }; static const auto rulesPrefix = std::vector{ "animation", "bordercolor", "bordersize", "center", "group", "idleinhibit", "maxsize", "minsize", "monitor", "move", "opacity", "plugin:", "pseudo", "rounding", "size", "suppressevent", "tag", "workspace", "xray", }; - return rules.contains(RULE) || std::any_of(rulesPrefix.begin(), rulesPrefix.end(), [&RULE](auto prefix) { return RULE.starts_with(prefix); }); + const auto VALS = CVarList(RULE, 2, ' '); + return rules.contains(RULE) || std::any_of(rulesPrefix.begin(), rulesPrefix.end(), [&RULE](auto prefix) { return RULE.starts_with(prefix); }) || + (g_pConfigManager->mbWindowProperties.find(VALS[0]) != g_pConfigManager->mbWindowProperties.end()) || + (g_pConfigManager->miWindowProperties.find(VALS[0]) != g_pConfigManager->miWindowProperties.end()); } bool layerRuleValid(const std::string& RULE) { @@ -2421,11 +2422,11 @@ std::optional CConfigManager::handleWorkspaceRules(const std::strin wsRule.borderSize = std::stoi(rule.substr(delim + 11)); } catch (...) { return "Error parsing workspace rule bordersize: {}", rule.substr(delim + 11); } else if ((delim = rule.find("border:")) != std::string::npos) - wsRule.border = configStringToInt(rule.substr(delim + 7)); + wsRule.noBorder = !configStringToInt(rule.substr(delim + 7)); else if ((delim = rule.find("shadow:")) != std::string::npos) - wsRule.shadow = configStringToInt(rule.substr(delim + 7)); + wsRule.noShadow = !configStringToInt(rule.substr(delim + 7)); else if ((delim = rule.find("rounding:")) != std::string::npos) - wsRule.rounding = configStringToInt(rule.substr(delim + 9)); + wsRule.noRounding = !configStringToInt(rule.substr(delim + 9)); else if ((delim = rule.find("decorate:")) != std::string::npos) wsRule.decorate = configStringToInt(rule.substr(delim + 9)); else if ((delim = rule.find("monitor:")) != std::string::npos) diff --git a/src/config/ConfigManager.hpp b/src/config/ConfigManager.hpp index c43cb020..10021187 100644 --- a/src/config/ConfigManager.hpp +++ b/src/config/ConfigManager.hpp @@ -39,10 +39,10 @@ struct SWorkspaceRule { std::optional gapsIn; std::optional gapsOut; std::optional borderSize; - std::optional border; - std::optional rounding; - std::optional decorate; - std::optional shadow; + std::optional decorate; + std::optional noRounding; + std::optional noBorder; + std::optional noShadow; std::optional onCreatedEmptyRunCmd; std::optional defaultName; std::map layoutopts; @@ -148,25 +148,49 @@ class CConfigManager { std::string getErrors(); // keywords - std::optional handleRawExec(const std::string&, const std::string&); - std::optional handleExecOnce(const std::string&, const std::string&); - std::optional handleMonitor(const std::string&, const std::string&); - std::optional handleBind(const std::string&, const std::string&); - std::optional handleUnbind(const std::string&, const std::string&); - std::optional handleWindowRule(const std::string&, const std::string&); - std::optional handleLayerRule(const std::string&, const std::string&); - std::optional handleWindowRuleV2(const std::string&, const std::string&); - std::optional handleWorkspaceRules(const std::string&, const std::string&); - std::optional handleBezier(const std::string&, const std::string&); - std::optional handleAnimation(const std::string&, const std::string&); - std::optional handleSource(const std::string&, const std::string&); - std::optional handleSubmap(const std::string&, const std::string&); - std::optional handleBlurLS(const std::string&, const std::string&); - std::optional handleBindWS(const std::string&, const std::string&); - std::optional handleEnv(const std::string&, const std::string&); - std::optional handlePlugin(const std::string&, const std::string&); + std::optional handleRawExec(const std::string&, const std::string&); + std::optional handleExecOnce(const std::string&, const std::string&); + std::optional handleMonitor(const std::string&, const std::string&); + std::optional handleBind(const std::string&, const std::string&); + std::optional handleUnbind(const std::string&, const std::string&); + std::optional handleWindowRule(const std::string&, const std::string&); + std::optional handleLayerRule(const std::string&, const std::string&); + std::optional handleWindowRuleV2(const std::string&, const std::string&); + std::optional handleWorkspaceRules(const std::string&, const std::string&); + std::optional handleBezier(const std::string&, const std::string&); + std::optional handleAnimation(const std::string&, const std::string&); + std::optional handleSource(const std::string&, const std::string&); + std::optional handleSubmap(const std::string&, const std::string&); + std::optional handleBlurLS(const std::string&, const std::string&); + std::optional handleBindWS(const std::string&, const std::string&); + std::optional handleEnv(const std::string&, const std::string&); + std::optional handlePlugin(const std::string&, const std::string&); - std::string configCurrentPath; + std::string configCurrentPath; + + std::unordered_map*(PHLWINDOW)>> mbWindowProperties = { + {"allowsinput", [](PHLWINDOW pWindow) { return &pWindow->m_sWindowData.allowsInput; }}, + {"dimaround", [](PHLWINDOW pWindow) { return &pWindow->m_sWindowData.dimAround; }}, + {"decorate", [](PHLWINDOW pWindow) { return &pWindow->m_sWindowData.decorate; }}, + {"focusonactivate", [](PHLWINDOW pWindow) { return &pWindow->m_sWindowData.focusOnActivate; }}, + {"keepaspectratio", [](PHLWINDOW pWindow) { return &pWindow->m_sWindowData.keepAspectRatio; }}, + {"nearestneighbor", [](PHLWINDOW pWindow) { return &pWindow->m_sWindowData.nearestNeighbor; }}, + {"noanim", [](PHLWINDOW pWindow) { return &pWindow->m_sWindowData.noAnim; }}, + {"noblur", [](PHLWINDOW pWindow) { return &pWindow->m_sWindowData.noBlur; }}, + {"noborder", [](PHLWINDOW pWindow) { return &pWindow->m_sWindowData.noBorder; }}, + {"nodim", [](PHLWINDOW pWindow) { return &pWindow->m_sWindowData.noDim; }}, + {"nofocus", [](PHLWINDOW pWindow) { return &pWindow->m_sWindowData.noFocus; }}, + {"nomaxsize", [](PHLWINDOW pWindow) { return &pWindow->m_sWindowData.noMaxSize; }}, + {"norounding", [](PHLWINDOW pWindow) { return &pWindow->m_sWindowData.noRounding; }}, + {"noshadow", [](PHLWINDOW pWindow) { return &pWindow->m_sWindowData.noShadow; }}, + {"opaque", [](PHLWINDOW pWindow) { return &pWindow->m_sWindowData.opaque; }}, + {"forcergbx", [](PHLWINDOW pWindow) { return &pWindow->m_sWindowData.RGBX; }}, + {"immediate", [](PHLWINDOW pWindow) { return &pWindow->m_sWindowData.tearing; }}, + {"xray", [](PHLWINDOW pWindow) { return &pWindow->m_sWindowData.xray; }}, + }; + + std::unordered_map*(PHLWINDOW)>> miWindowProperties = { + {"rounding", [](PHLWINDOW pWindow) { return &pWindow->m_sWindowData.rounding; }}, {"bordersize", [](PHLWINDOW pWindow) { return &pWindow->m_sWindowData.borderSize; }}}; private: std::unique_ptr m_pConfig; diff --git a/src/debug/HyprCtl.cpp b/src/debug/HyprCtl.cpp index f96c071a..08d2bb57 100644 --- a/src/debug/HyprCtl.cpp +++ b/src/debug/HyprCtl.cpp @@ -317,10 +317,10 @@ static std::string getWorkspaceRuleData(const SWorkspaceRule& r, eHyprCtlOutputF std::format(",\n \"gapsOut\": [{}, {}, {}, {}]", r.gapsOut.value().top, r.gapsOut.value().right, r.gapsOut.value().bottom, r.gapsOut.value().left) : ""; const std::string borderSize = (bool)(r.borderSize) ? std::format(",\n \"borderSize\": {}", r.borderSize.value()) : ""; - const std::string border = (bool)(r.border) ? std::format(",\n \"border\": {}", boolToString(r.border.value())) : ""; - const std::string rounding = (bool)(r.rounding) ? std::format(",\n \"rounding\": {}", boolToString(r.rounding.value())) : ""; + const std::string border = (bool)(r.noBorder) ? std::format(",\n \"border\": {}", boolToString(!r.noBorder.value())) : ""; + const std::string rounding = (bool)(r.noRounding) ? std::format(",\n \"rounding\": {}", boolToString(!r.noRounding.value())) : ""; const std::string decorate = (bool)(r.decorate) ? std::format(",\n \"decorate\": {}", boolToString(r.decorate.value())) : ""; - const std::string shadow = (bool)(r.shadow) ? std::format(",\n \"shadow\": {}", boolToString(r.shadow.value())) : ""; + const std::string shadow = (bool)(r.noShadow) ? std::format(",\n \"shadow\": {}", boolToString(!r.noShadow.value())) : ""; std::string result = std::format(R"#({{ "workspaceString": "{}"{}{}{}{}{}{}{}{} @@ -339,10 +339,10 @@ static std::string getWorkspaceRuleData(const SWorkspaceRule& r, eHyprCtlOutputF std::to_string(r.gapsOut.value().bottom), std::to_string(r.gapsOut.value().left)) : std::format("\tgapsOut: \n"); const std::string borderSize = std::format("\tborderSize: {}\n", (bool)(r.borderSize) ? std::to_string(r.borderSize.value()) : ""); - const std::string border = std::format("\tborder: {}\n", (bool)(r.border) ? boolToString(r.border.value()) : ""); - const std::string rounding = std::format("\trounding: {}\n", (bool)(r.rounding) ? boolToString(r.rounding.value()) : ""); + const std::string border = std::format("\tborder: {}\n", (bool)(r.noBorder) ? boolToString(!r.noBorder.value()) : ""); + const std::string rounding = std::format("\trounding: {}\n", (bool)(r.noRounding) ? boolToString(!r.noRounding.value()) : ""); const std::string decorate = std::format("\tdecorate: {}\n", (bool)(r.decorate) ? boolToString(r.decorate.value()) : ""); - const std::string shadow = std::format("\tshadow: {}\n", (bool)(r.shadow) ? boolToString(r.shadow.value()) : ""); + const std::string shadow = std::format("\tshadow: {}\n", (bool)(r.noShadow) ? boolToString(!r.noShadow.value()) : ""); std::string result = std::format("Workspace rule {}:\n{}{}{}{}{}{}{}{}{}{}\n", escapeJSONStrings(r.workspaceString), monitor, default_, persistent, gapsIn, gapsOut, borderSize, border, rounding, decorate, shadow); @@ -1202,74 +1202,44 @@ std::string dispatchSetProp(eHyprCtlOutputFormat format, std::string request) { const auto PROP = vars[2]; const auto VAL = vars[3]; - auto noFocus = PWINDOW->m_sAdditionalConfigData.noFocus; - - bool lock = false; - - if (request.ends_with("lock")) - lock = true; + bool noFocus = PWINDOW->m_sWindowData.noFocus.valueOrDefault(); try { if (PROP == "animationstyle") { - PWINDOW->m_sAdditionalConfigData.animationStyle = VAL; - } else if (PROP == "rounding") { - PWINDOW->m_sAdditionalConfigData.rounding.forceSetIgnoreLocked(configStringToInt(VAL), lock); - } else if (PROP == "forcenoblur") { - PWINDOW->m_sAdditionalConfigData.forceNoBlur.forceSetIgnoreLocked(configStringToInt(VAL), lock); - } else if (PROP == "forceopaque") { - PWINDOW->m_sAdditionalConfigData.forceOpaque.forceSetIgnoreLocked(configStringToInt(VAL), lock); - } else if (PROP == "forceopaqueoverriden") { - PWINDOW->m_sAdditionalConfigData.forceOpaqueOverridden.forceSetIgnoreLocked(configStringToInt(VAL), lock); - } else if (PROP == "forceallowsinput") { - PWINDOW->m_sAdditionalConfigData.forceAllowsInput.forceSetIgnoreLocked(configStringToInt(VAL), lock); - } else if (PROP == "forcenoanims") { - PWINDOW->m_sAdditionalConfigData.forceNoAnims.forceSetIgnoreLocked(configStringToInt(VAL), lock); - } else if (PROP == "forcenoborder") { - PWINDOW->m_sAdditionalConfigData.forceNoBorder.forceSetIgnoreLocked(configStringToInt(VAL), lock); - } else if (PROP == "forcenoshadow") { - PWINDOW->m_sAdditionalConfigData.forceNoShadow.forceSetIgnoreLocked(configStringToInt(VAL), lock); - } else if (PROP == "forcenodim") { - PWINDOW->m_sAdditionalConfigData.forceNoDim.forceSetIgnoreLocked(configStringToInt(VAL), lock); - } else if (PROP == "nofocus") { - PWINDOW->m_sAdditionalConfigData.noFocus.forceSetIgnoreLocked(configStringToInt(VAL), lock); - } else if (PROP == "windowdancecompat") { - PWINDOW->m_sAdditionalConfigData.windowDanceCompat.forceSetIgnoreLocked(configStringToInt(VAL), lock); - } else if (PROP == "nomaxsize") { - PWINDOW->m_sAdditionalConfigData.noMaxSize.forceSetIgnoreLocked(configStringToInt(VAL), lock); + PWINDOW->m_sWindowData.animationStyle = CWindowOverridableVar(VAL, PRIORITY_SET_PROP); } else if (PROP == "maxsize") { - PWINDOW->m_sAdditionalConfigData.maxSize.forceSetIgnoreLocked(configStringToVector2D(VAL + " " + vars[4]), lock); - if (lock) { - PWINDOW->m_vRealSize = Vector2D(std::min((double)PWINDOW->m_sAdditionalConfigData.maxSize.toUnderlying().x, PWINDOW->m_vRealSize.goal().x), - std::min((double)PWINDOW->m_sAdditionalConfigData.maxSize.toUnderlying().y, PWINDOW->m_vRealSize.goal().y)); - g_pXWaylandManager->setWindowSize(PWINDOW, PWINDOW->m_vRealSize.goal()); - PWINDOW->setHidden(false); - } + PWINDOW->m_sWindowData.maxSize = CWindowOverridableVar(configStringToVector2D(VAL + " " + vars[4]), PRIORITY_SET_PROP); + PWINDOW->m_vRealSize = Vector2D(std::min((double)PWINDOW->m_sWindowData.maxSize.value().x, PWINDOW->m_vRealSize.goal().x), + std::min((double)PWINDOW->m_sWindowData.maxSize.value().y, PWINDOW->m_vRealSize.goal().y)); + g_pXWaylandManager->setWindowSize(PWINDOW, PWINDOW->m_vRealSize.goal()); + PWINDOW->setHidden(false); } else if (PROP == "minsize") { - PWINDOW->m_sAdditionalConfigData.minSize.forceSetIgnoreLocked(configStringToVector2D(VAL + " " + vars[4]), lock); - if (lock) { - PWINDOW->m_vRealSize = Vector2D(std::max((double)PWINDOW->m_sAdditionalConfigData.minSize.toUnderlying().x, PWINDOW->m_vRealSize.goal().x), - std::max((double)PWINDOW->m_sAdditionalConfigData.minSize.toUnderlying().y, PWINDOW->m_vRealSize.goal().y)); - g_pXWaylandManager->setWindowSize(PWINDOW, PWINDOW->m_vRealSize.goal()); - PWINDOW->setHidden(false); - } - } else if (PROP == "dimaround") { - PWINDOW->m_sAdditionalConfigData.dimAround.forceSetIgnoreLocked(configStringToInt(VAL), lock); - } else if (PROP == "alphaoverride") { - PWINDOW->m_sSpecialRenderData.alphaOverride.forceSetIgnoreLocked(configStringToInt(VAL), lock); + PWINDOW->m_sWindowData.minSize = CWindowOverridableVar(configStringToVector2D(VAL + " " + vars[4]), PRIORITY_SET_PROP); + PWINDOW->m_vRealSize = Vector2D(std::max((double)PWINDOW->m_sWindowData.minSize.value().x, PWINDOW->m_vRealSize.goal().x), + std::max((double)PWINDOW->m_sWindowData.minSize.value().y, PWINDOW->m_vRealSize.goal().y)); + g_pXWaylandManager->setWindowSize(PWINDOW, PWINDOW->m_vRealSize.goal()); + PWINDOW->setHidden(false); } else if (PROP == "alpha") { - PWINDOW->m_sSpecialRenderData.alpha.forceSetIgnoreLocked(std::stof(VAL), lock); - } else if (PROP == "alphainactiveoverride") { - PWINDOW->m_sSpecialRenderData.alphaInactiveOverride.forceSetIgnoreLocked(configStringToInt(VAL), lock); + PWINDOW->m_sWindowData.alpha = CWindowOverridableVar(SAlphaValue{std::stof(VAL), PWINDOW->m_sWindowData.alpha.valueOrDefault().m_bOverride}, PRIORITY_SET_PROP); } else if (PROP == "alphainactive") { - PWINDOW->m_sSpecialRenderData.alphaInactive.forceSetIgnoreLocked(std::stof(VAL), lock); - } else if (PROP == "alphafullscreenoverride") { - PWINDOW->m_sSpecialRenderData.alphaFullscreenOverride.forceSetIgnoreLocked(configStringToInt(VAL), lock); + PWINDOW->m_sWindowData.alphaInactive = + CWindowOverridableVar(SAlphaValue{std::stof(VAL), PWINDOW->m_sWindowData.alphaInactive.valueOrDefault().m_bOverride}, PRIORITY_SET_PROP); } else if (PROP == "alphafullscreen") { - PWINDOW->m_sSpecialRenderData.alphaFullscreen.forceSetIgnoreLocked(std::stof(VAL), lock); + PWINDOW->m_sWindowData.alphaFullscreen = + CWindowOverridableVar(SAlphaValue{std::stof(VAL), PWINDOW->m_sWindowData.alphaFullscreen.valueOrDefault().m_bOverride}, PRIORITY_SET_PROP); + } else if (PROP == "alphaoverride") { + PWINDOW->m_sWindowData.alpha = + CWindowOverridableVar(SAlphaValue{PWINDOW->m_sWindowData.alpha.valueOrDefault().m_fAlpha, (bool)configStringToInt(VAL)}, PRIORITY_SET_PROP); + } else if (PROP == "alphainactiveoverride") { + PWINDOW->m_sWindowData.alphaInactive = + CWindowOverridableVar(SAlphaValue{PWINDOW->m_sWindowData.alphaInactive.valueOrDefault().m_fAlpha, (bool)configStringToInt(VAL)}, PRIORITY_SET_PROP); + } else if (PROP == "alphafullscreenoverride") { + PWINDOW->m_sWindowData.alphaFullscreen = + CWindowOverridableVar(SAlphaValue{PWINDOW->m_sWindowData.alphaFullscreen.valueOrDefault().m_fAlpha, (bool)configStringToInt(VAL)}, PRIORITY_SET_PROP); } else if (PROP == "activebordercolor" || PROP == "inactivebordercolor") { CGradientValueData colorData = {}; if (vars.size() > 4) { - for (int i = 3; i < static_cast(lock ? vars.size() - 1 : vars.size()); ++i) { + for (int i = 3; i < static_cast(vars.size()); ++i) { const auto TOKEN = vars[i]; if (TOKEN.ends_with("deg")) colorData.m_fAngle = std::stoi(TOKEN.substr(0, TOKEN.size() - 3)) * (PI / 180.0); @@ -1280,19 +1250,22 @@ std::string dispatchSetProp(eHyprCtlOutputFormat format, std::string request) { colorData.m_vColors.push_back(configStringToInt(VAL)); if (PROP == "activebordercolor") - PWINDOW->m_sSpecialRenderData.activeBorderColor.forceSetIgnoreLocked(colorData, lock); + PWINDOW->m_sWindowData.activeBorderColor = CWindowOverridableVar(colorData, PRIORITY_SET_PROP); else - PWINDOW->m_sSpecialRenderData.inactiveBorderColor.forceSetIgnoreLocked(colorData, lock); - } else if (PROP == "forcergbx") { - PWINDOW->m_sAdditionalConfigData.forceRGBX.forceSetIgnoreLocked(configStringToInt(VAL), lock); - } else if (PROP == "bordersize") { - PWINDOW->m_sSpecialRenderData.borderSize.forceSetIgnoreLocked(configStringToInt(VAL), lock); - } else if (PROP == "keepaspectratio") { - PWINDOW->m_sAdditionalConfigData.keepAspectRatio.forceSetIgnoreLocked(configStringToInt(VAL), lock); - } else if (PROP == "immediate") { - PWINDOW->m_sAdditionalConfigData.forceTearing.forceSetIgnoreLocked(configStringToInt(VAL), lock); - } else if (PROP == "nearestneighbor") { - PWINDOW->m_sAdditionalConfigData.nearestNeighbor.forceSetIgnoreLocked(configStringToInt(VAL), lock); + PWINDOW->m_sWindowData.inactiveBorderColor = CWindowOverridableVar(colorData, PRIORITY_SET_PROP); + } else if (auto search = g_pConfigManager->mbWindowProperties.find(PROP); search != g_pConfigManager->mbWindowProperties.end()) { + auto pWindowDataElement = search->second(PWINDOW); + if (VAL == "toggle") + *pWindowDataElement = CWindowOverridableVar(!pWindowDataElement->valueOrDefault(), PRIORITY_SET_PROP); + else if (VAL == "unset") + pWindowDataElement->unset(PRIORITY_SET_PROP); + else + *pWindowDataElement = CWindowOverridableVar((bool)configStringToInt(VAL), PRIORITY_SET_PROP); + } else if (auto search = g_pConfigManager->miWindowProperties.find(PROP); search != g_pConfigManager->miWindowProperties.end()) { + if (VAL == "unset") + search->second(PWINDOW)->unset(PRIORITY_SET_PROP); + else + *(search->second(PWINDOW)) = CWindowOverridableVar((int)configStringToInt(VAL), PRIORITY_SET_PROP); } else { return "prop not found"; } @@ -1300,7 +1273,7 @@ std::string dispatchSetProp(eHyprCtlOutputFormat format, std::string request) { g_pCompositor->updateAllWindowsAnimatedDecorationValues(); - if (!(PWINDOW->m_sAdditionalConfigData.noFocus.toUnderlying() == noFocus.toUnderlying())) { + if (!(PWINDOW->m_sWindowData.noFocus.valueOrDefault() == noFocus)) { g_pCompositor->focusWindow(nullptr); g_pCompositor->focusWindow(PWINDOW); g_pCompositor->focusWindow(PLASTWINDOW); @@ -1848,7 +1821,6 @@ int hyprCtlFDTick(int fd, uint32_t mask, void* data) { } void CHyprCtl::startHyprCtlSocket() { - m_iSocketFD = socket(AF_UNIX, SOCK_STREAM | SOCK_CLOEXEC, 0); if (m_iSocketFD < 0) { diff --git a/src/desktop/Window.cpp b/src/desktop/Window.cpp index 560e5103..2dc5846b 100644 --- a/src/desktop/Window.cpp +++ b/src/desktop/Window.cpp @@ -110,7 +110,7 @@ SBoxExtents CWindow::getFullWindowExtents() { const int BORDERSIZE = getRealBorderSize(); - if (m_sAdditionalConfigData.dimAround) { + if (m_sWindowData.dimAround.valueOrDefault()) { if (const auto PMONITOR = g_pCompositor->getMonitorFromID(m_iMonitorID); PMONITOR) return {{m_vRealPosition.value().x - PMONITOR->vecPosition.x, m_vRealPosition.value().y - PMONITOR->vecPosition.y}, {PMONITOR->vecSize.x - (m_vRealPosition.value().x - PMONITOR->vecPosition.x), PMONITOR->vecSize.y - (m_vRealPosition.value().y - PMONITOR->vecPosition.y)}}; @@ -170,7 +170,7 @@ SBoxExtents CWindow::getFullWindowExtents() { } CBox CWindow::getFullWindowBoundingBox() { - if (m_sAdditionalConfigData.dimAround) { + if (m_sWindowData.dimAround.valueOrDefault()) { if (const auto PMONITOR = g_pCompositor->getMonitorFromID(m_iMonitorID); PMONITOR) return {PMONITOR->vecPosition.x, PMONITOR->vecPosition.y, PMONITOR->vecSize.x, PMONITOR->vecSize.y}; } @@ -218,7 +218,7 @@ CBox CWindow::getWindowIdealBoundingBoxIgnoreReserved() { } CBox CWindow::getWindowBoxUnified(uint64_t properties) { - if (m_sAdditionalConfigData.dimAround) { + if (m_sWindowData.dimAround.valueOrDefault()) { const auto PMONITOR = g_pCompositor->getMonitorFromID(m_iMonitorID); if (PMONITOR) return {PMONITOR->vecPosition.x, PMONITOR->vecPosition.y, PMONITOR->vecSize.x, PMONITOR->vecSize.y}; @@ -411,11 +411,11 @@ void CWindow::moveToWorkspace(PHLWORKSPACE pWorkspace) { setAnimationsToMove(); g_pCompositor->updateWorkspaceWindows(OLDWORKSPACE->m_iID); - g_pCompositor->updateWorkspaceSpecialRenderData(OLDWORKSPACE->m_iID); + g_pCompositor->updateWorkspaceWindowData(OLDWORKSPACE->m_iID); g_pLayoutManager->getCurrentLayout()->recalculateMonitor(OLDWORKSPACE->m_iMonitorID); g_pCompositor->updateWorkspaceWindows(workspaceID()); - g_pCompositor->updateWorkspaceSpecialRenderData(workspaceID()); + g_pCompositor->updateWorkspaceWindowData(workspaceID()); g_pLayoutManager->getCurrentLayout()->recalculateMonitor(m_iMonitorID); g_pCompositor->updateAllWindowsAnimatedDecorationValues(); @@ -524,7 +524,7 @@ void CWindow::onUnmap() { PMONITOR->solitaryClient.reset(); g_pCompositor->updateWorkspaceWindows(workspaceID()); - g_pCompositor->updateWorkspaceSpecialRenderData(workspaceID()); + g_pCompositor->updateWorkspaceWindowData(workspaceID()); g_pLayoutManager->getCurrentLayout()->recalculateMonitor(m_iMonitorID); g_pCompositor->updateAllWindowsAnimatedDecorationValues(); @@ -607,38 +607,15 @@ bool CWindow::isHidden() { } void CWindow::applyDynamicRule(const SWindowRule& r) { - if (r.szRule == "noblur") { - m_sAdditionalConfigData.forceNoBlur = true; - } else if (r.szRule == "noborder") { - m_sAdditionalConfigData.forceNoBorder = true; - } else if (r.szRule == "noshadow") { - m_sAdditionalConfigData.forceNoShadow = true; - } else if (r.szRule == "nodim") { - m_sAdditionalConfigData.forceNoDim = true; - } else if (r.szRule == "forcergbx") { - m_sAdditionalConfigData.forceRGBX = true; - } else if (r.szRule == "opaque") { - if (!m_sAdditionalConfigData.forceOpaqueOverridden) - m_sAdditionalConfigData.forceOpaque = true; - } else if (r.szRule == "immediate") { - m_sAdditionalConfigData.forceTearing = true; - } else if (r.szRule == "nearestneighbor") { - m_sAdditionalConfigData.nearestNeighbor = true; - } else if (r.szRule.starts_with("tag")) { + const eOverridePriority priority = r.szValue == "execRule" ? PRIORITY_SET_PROP : PRIORITY_WINDOW_RULE; + const CVarList VARS(r.szRule, 0, ' '); + if (r.szRule.starts_with("tag")) { CVarList vars{r.szRule, 0, 's', true}; if (vars.size() == 2 && vars[0] == "tag") m_tags.applyTag(vars[1], true); else Debug::log(ERR, "Tag rule invalid: {}", r.szRule); - } else if (r.szRule.starts_with("rounding")) { - try { - m_sAdditionalConfigData.rounding = std::stoi(r.szRule.substr(r.szRule.find_first_of(' ') + 1)); - } catch (std::exception& e) { Debug::log(ERR, "Rounding rule \"{}\" failed with: {}", r.szRule, e.what()); } - } else if (r.szRule.starts_with("bordersize")) { - try { - m_sAdditionalConfigData.borderSize = std::stoi(r.szRule.substr(r.szRule.find_first_of(' ') + 1)); - } catch (std::exception& e) { Debug::log(ERR, "Bordersize rule \"{}\" failed with: {}", r.szRule, e.what()); } } else if (r.szRule.starts_with("opacity")) { try { CVarList vars(r.szRule, 0, ' '); @@ -651,21 +628,18 @@ void CWindow::applyDynamicRule(const SWindowRule& r) { if (r == "override") { if (opacityIDX == 1) - m_sSpecialRenderData.alphaOverride = true; + m_sWindowData.alpha = CWindowOverridableVar(SAlphaValue{m_sWindowData.alpha.value().m_fAlpha, true}, priority); else if (opacityIDX == 2) - m_sSpecialRenderData.alphaInactiveOverride = true; + m_sWindowData.alphaInactive = CWindowOverridableVar(SAlphaValue{m_sWindowData.alphaInactive.value().m_fAlpha, true}, priority); else if (opacityIDX == 3) - m_sSpecialRenderData.alphaFullscreenOverride = true; + m_sWindowData.alphaFullscreen = CWindowOverridableVar(SAlphaValue{m_sWindowData.alphaFullscreen.value().m_fAlpha, true}, priority); } else { if (opacityIDX == 0) { - m_sSpecialRenderData.alpha = std::stof(r); - m_sSpecialRenderData.alphaOverride = false; + m_sWindowData.alpha = CWindowOverridableVar(SAlphaValue{std::stof(r), false}, priority); } else if (opacityIDX == 1) { - m_sSpecialRenderData.alphaInactive = std::stof(r); - m_sSpecialRenderData.alphaInactiveOverride = false; + m_sWindowData.alphaInactive = CWindowOverridableVar(SAlphaValue{std::stof(r), false}, priority); } else if (opacityIDX == 2) { - m_sSpecialRenderData.alphaFullscreen = std::stof(r); - m_sSpecialRenderData.alphaFullscreenOverride = false; + m_sWindowData.alphaFullscreen = CWindowOverridableVar(SAlphaValue{std::stof(r), false}, priority); } else { throw std::runtime_error("more than 3 alpha values"); } @@ -675,17 +649,13 @@ void CWindow::applyDynamicRule(const SWindowRule& r) { } if (opacityIDX == 1) { - m_sSpecialRenderData.alphaInactiveOverride = m_sSpecialRenderData.alphaOverride; - m_sSpecialRenderData.alphaInactive = m_sSpecialRenderData.alpha; - m_sSpecialRenderData.alphaFullscreenOverride = m_sSpecialRenderData.alphaOverride; - m_sSpecialRenderData.alphaFullscreen = m_sSpecialRenderData.alpha; + m_sWindowData.alphaInactive = m_sWindowData.alpha; + m_sWindowData.alphaFullscreen = m_sWindowData.alpha; } } catch (std::exception& e) { Debug::log(ERR, "Opacity rule \"{}\" failed with: {}", r.szRule, e.what()); } - } else if (r.szRule == "noanim") { - m_sAdditionalConfigData.forceNoAnims = true; } else if (r.szRule.starts_with("animation")) { - auto STYLE = r.szRule.substr(r.szRule.find_first_of(' ') + 1); - m_sAdditionalConfigData.animationStyle = STYLE; + auto STYLE = r.szRule.substr(r.szRule.find_first_of(' ') + 1); + m_sWindowData.animationStyle = CWindowOverridableVar(STYLE, priority); } else if (r.szRule.starts_with("bordercolor")) { try { // Each vector will only get used if it has at least one color @@ -696,8 +666,8 @@ void CWindow::applyDynamicRule(const SWindowRule& r) { // Basic form has only two colors, everything else can be parsed as a gradient if (colorsAndAngles.size() == 2 && !colorsAndAngles[1].contains("deg")) { - m_sSpecialRenderData.activeBorderColor = CGradientValueData(CColor(configStringToInt(colorsAndAngles[0]))); - m_sSpecialRenderData.inactiveBorderColor = CGradientValueData(CColor(configStringToInt(colorsAndAngles[1]))); + m_sWindowData.activeBorderColor = CWindowOverridableVar(CGradientValueData(CColor(configStringToInt(colorsAndAngles[0]))), priority); + m_sWindowData.inactiveBorderColor = CWindowOverridableVar(CGradientValueData(CColor(configStringToInt(colorsAndAngles[1]))), priority); return; } @@ -720,24 +690,24 @@ void CWindow::applyDynamicRule(const SWindowRule& r) { else if (activeBorderGradient.m_vColors.empty()) Debug::log(WARN, "Bordercolor rule \"{}\" has no colors, ignoring", r.szRule); else if (inactiveBorderGradient.m_vColors.empty()) - m_sSpecialRenderData.activeBorderColor = activeBorderGradient; + m_sWindowData.activeBorderColor = CWindowOverridableVar(activeBorderGradient, priority); else { - m_sSpecialRenderData.activeBorderColor = activeBorderGradient; - m_sSpecialRenderData.inactiveBorderColor = inactiveBorderGradient; + m_sWindowData.activeBorderColor = CWindowOverridableVar(activeBorderGradient, priority); + m_sWindowData.inactiveBorderColor = CWindowOverridableVar(inactiveBorderGradient, priority); } } catch (std::exception& e) { Debug::log(ERR, "BorderColor rule \"{}\" failed with: {}", r.szRule, e.what()); } - } else if (r.szRule == "dimaround") { - m_sAdditionalConfigData.dimAround = true; - } else if (r.szRule == "keepaspectratio") { - m_sAdditionalConfigData.keepAspectRatio = true; - } else if (r.szRule.starts_with("focusonactivate")) { - m_sAdditionalConfigData.focusOnActivate = true; - } else if (r.szRule.starts_with("xray")) { - CVarList vars(r.szRule, 0, ' '); - + } else if (auto search = g_pConfigManager->mbWindowProperties.find(VARS[0]); search != g_pConfigManager->mbWindowProperties.end()) { + if (VARS[1].empty()) { + *(search->second(m_pSelf.lock())) = CWindowOverridableVar(true, priority); + } else { + try { + *(search->second(m_pSelf.lock())) = CWindowOverridableVar((bool)configStringToInt(VARS[1]), priority); + } catch (...) {} + } + } else if (auto search = g_pConfigManager->miWindowProperties.find(VARS[0]); search != g_pConfigManager->miWindowProperties.end()) { try { - m_sAdditionalConfigData.xray = configStringToInt(vars[1]); - } catch (...) {} + *(search->second(m_pSelf.lock())) = CWindowOverridableVar(std::stoi(VARS[1]), priority); + } catch (std::exception& e) { Debug::log(ERR, "Rule \"{}\" failed with: {}", r.szRule, e.what()); } } else if (r.szRule.starts_with("idleinhibit")) { auto IDLERULE = r.szRule.substr(r.szRule.find_first_of(' ') + 1); @@ -761,9 +731,9 @@ void CWindow::applyDynamicRule(const SWindowRule& r) { return; } - m_sAdditionalConfigData.maxSize = VEC; - m_vRealSize = Vector2D(std::min((double)m_sAdditionalConfigData.maxSize.toUnderlying().x, m_vRealSize.goal().x), - std::min((double)m_sAdditionalConfigData.maxSize.toUnderlying().y, m_vRealSize.goal().y)); + m_sWindowData.maxSize = CWindowOverridableVar(VEC, priority); + m_vRealSize = + Vector2D(std::min((double)m_sWindowData.maxSize.value().x, m_vRealSize.goal().x), std::min((double)m_sWindowData.maxSize.value().y, m_vRealSize.goal().y)); g_pXWaylandManager->setWindowSize(m_pSelf.lock(), m_vRealSize.goal()); } catch (std::exception& e) { Debug::log(ERR, "maxsize rule \"{}\" failed with: {}", r.szRule, e.what()); } } else if (r.szRule.starts_with("minsize")) { @@ -776,9 +746,9 @@ void CWindow::applyDynamicRule(const SWindowRule& r) { return; } - m_sAdditionalConfigData.minSize = VEC; - m_vRealSize = Vector2D(std::max((double)m_sAdditionalConfigData.minSize.toUnderlying().x, m_vRealSize.goal().x), - std::max((double)m_sAdditionalConfigData.minSize.toUnderlying().y, m_vRealSize.goal().y)); + m_sWindowData.minSize = CWindowOverridableVar(VEC, priority); + m_vRealSize = + Vector2D(std::max((double)m_sWindowData.minSize.value().x, m_vRealSize.goal().x), std::max((double)m_sWindowData.minSize.value().y, m_vRealSize.goal().y)); g_pXWaylandManager->setWindowSize(m_pSelf.lock(), m_vRealSize.goal()); if (m_sGroupData.pNextWindow.expired()) setHidden(false); @@ -787,30 +757,20 @@ void CWindow::applyDynamicRule(const SWindowRule& r) { } void CWindow::updateDynamicRules() { - m_sSpecialRenderData.activeBorderColor = CGradientValueData(); - m_sSpecialRenderData.inactiveBorderColor = CGradientValueData(); - m_sSpecialRenderData.alpha = 1.f; - m_sSpecialRenderData.alphaInactive = -1.f; - m_sAdditionalConfigData.forceNoBlur = false; - m_sAdditionalConfigData.forceNoBorder = false; - m_sAdditionalConfigData.forceNoShadow = false; - m_sAdditionalConfigData.forceNoDim = false; - if (!m_sAdditionalConfigData.forceOpaqueOverridden) - m_sAdditionalConfigData.forceOpaque = false; - m_sAdditionalConfigData.maxSize = Vector2D(std::numeric_limits::max(), std::numeric_limits::max()); - m_sAdditionalConfigData.minSize = Vector2D(20, 20); - m_sAdditionalConfigData.forceNoAnims = false; - m_sAdditionalConfigData.animationStyle = std::string(""); - m_sAdditionalConfigData.rounding = -1; - m_sAdditionalConfigData.dimAround = false; - m_sAdditionalConfigData.forceRGBX = false; - m_sAdditionalConfigData.borderSize = -1; - m_sAdditionalConfigData.keepAspectRatio = false; - m_sAdditionalConfigData.focusOnActivate = false; - m_sAdditionalConfigData.xray = -1; - m_sAdditionalConfigData.forceTearing = false; - m_sAdditionalConfigData.nearestNeighbor = false; - m_eIdleInhibitMode = IDLEINHIBIT_NONE; + m_sWindowData.alpha.unset(PRIORITY_WINDOW_RULE); + m_sWindowData.alphaInactive.unset(PRIORITY_WINDOW_RULE); + m_sWindowData.alphaFullscreen.unset(PRIORITY_WINDOW_RULE); + + unsetWindowData(PRIORITY_WINDOW_RULE); + + m_sWindowData.animationStyle.unset(PRIORITY_WINDOW_RULE); + m_sWindowData.maxSize.unset(PRIORITY_WINDOW_RULE); + m_sWindowData.minSize.unset(PRIORITY_WINDOW_RULE); + + m_sWindowData.activeBorderColor.unset(PRIORITY_WINDOW_RULE); + m_sWindowData.inactiveBorderColor.unset(PRIORITY_WINDOW_RULE); + + m_eIdleInhibitMode = IDLEINHIBIT_NONE; m_tags.removeDynamicTags(); @@ -887,7 +847,7 @@ void CWindow::createGroup() { addWindowDeco(std::make_unique(m_pSelf.lock())); g_pCompositor->updateWorkspaceWindows(workspaceID()); - g_pCompositor->updateWorkspaceSpecialRenderData(workspaceID()); + g_pCompositor->updateWorkspaceWindowData(workspaceID()); g_pLayoutManager->getCurrentLayout()->recalculateMonitor(m_iMonitorID); g_pCompositor->updateAllWindowsAnimatedDecorationValues(); @@ -905,7 +865,7 @@ void CWindow::destroyGroup() { m_sGroupData.head = false; updateWindowDecos(); g_pCompositor->updateWorkspaceWindows(workspaceID()); - g_pCompositor->updateWorkspaceSpecialRenderData(workspaceID()); + g_pCompositor->updateWorkspaceWindowData(workspaceID()); g_pLayoutManager->getCurrentLayout()->recalculateMonitor(m_iMonitorID); g_pCompositor->updateAllWindowsAnimatedDecorationValues(); @@ -941,7 +901,7 @@ void CWindow::destroyGroup() { g_pKeybindManager->m_bGroupsLocked = GROUPSLOCKEDPREV; g_pCompositor->updateWorkspaceWindows(workspaceID()); - g_pCompositor->updateWorkspaceSpecialRenderData(workspaceID()); + g_pCompositor->updateWorkspaceWindowData(workspaceID()); g_pLayoutManager->getCurrentLayout()->recalculateMonitor(m_iMonitorID); g_pCompositor->updateAllWindowsAnimatedDecorationValues(); @@ -1159,48 +1119,43 @@ bool CWindow::opaque() { float CWindow::rounding() { static auto PROUNDING = CConfigValue("decoration:rounding"); - float rounding = m_sAdditionalConfigData.rounding.toUnderlying() == -1 ? *PROUNDING : m_sAdditionalConfigData.rounding.toUnderlying(); + float rounding = m_sWindowData.rounding.valueOr(*PROUNDING); - return m_sSpecialRenderData.rounding ? rounding : 0; + return m_sWindowData.noRounding.valueOrDefault() ? 0 : rounding; } -void CWindow::updateSpecialRenderData() { +void CWindow::updateWindowData() { const auto PWORKSPACE = m_pWorkspace; const auto WORKSPACERULE = PWORKSPACE ? g_pConfigManager->getWorkspaceRuleFor(PWORKSPACE) : SWorkspaceRule{}; - updateSpecialRenderData(WORKSPACERULE); + updateWindowData(WORKSPACERULE); } -void CWindow::updateSpecialRenderData(const SWorkspaceRule& workspaceRule) { +void CWindow::updateWindowData(const SWorkspaceRule& workspaceRule) { static auto PNOBORDERONFLOATING = CConfigValue("general:no_border_on_floating"); - bool border = true; - if (m_bIsFloating && *PNOBORDERONFLOATING == 1) - border = false; + if (*PNOBORDERONFLOATING) + m_sWindowData.noBorder = CWindowOverridableVar(m_bIsFloating, PRIORITY_LAYOUT); + else + m_sWindowData.noBorder.unset(PRIORITY_LAYOUT); - m_sSpecialRenderData.border = workspaceRule.border.value_or(border); - m_sSpecialRenderData.borderSize = workspaceRule.borderSize.value_or(-1); - m_sSpecialRenderData.decorate = workspaceRule.decorate.value_or(true); - m_sSpecialRenderData.rounding = workspaceRule.rounding.value_or(true); - m_sSpecialRenderData.shadow = workspaceRule.shadow.value_or(true); + m_sWindowData.borderSize.matchOptional(workspaceRule.borderSize, PRIORITY_WORKSPACE_RULE); + m_sWindowData.decorate.matchOptional(workspaceRule.decorate, PRIORITY_WORKSPACE_RULE); + m_sWindowData.noBorder.matchOptional(workspaceRule.noBorder, PRIORITY_WORKSPACE_RULE); + m_sWindowData.noRounding.matchOptional(workspaceRule.noRounding, PRIORITY_WORKSPACE_RULE); + m_sWindowData.noShadow.matchOptional(workspaceRule.noShadow, PRIORITY_WORKSPACE_RULE); } int CWindow::getRealBorderSize() { - if (!m_sSpecialRenderData.border || m_sAdditionalConfigData.forceNoBorder || (m_pWorkspace && m_bIsFullscreen && (m_pWorkspace->m_efFullscreenMode == FULLSCREEN_FULL))) + if (m_sWindowData.noBorder.valueOrDefault() || (m_pWorkspace && m_bIsFullscreen && (m_pWorkspace->m_efFullscreenMode == FULLSCREEN_FULL))) return 0; - if (m_sAdditionalConfigData.borderSize.toUnderlying() != -1) - return m_sAdditionalConfigData.borderSize.toUnderlying(); - - if (m_sSpecialRenderData.borderSize.toUnderlying() != -1) - return m_sSpecialRenderData.borderSize.toUnderlying(); - static auto PBORDERSIZE = CConfigValue("general:border_size"); - return *PBORDERSIZE; + return m_sWindowData.borderSize.valueOr(*PBORDERSIZE); } bool CWindow::canBeTorn() { - return (m_sAdditionalConfigData.forceTearing.toUnderlying() || m_bTearingHint); + return m_sWindowData.tearing.valueOr(m_bTearingHint); } bool CWindow::shouldSendFullscreenState() { @@ -1349,8 +1304,7 @@ void CWindow::activate(bool force) { m_bIsUrgent = true; - if (!force && - (!(*PFOCUSONACTIVATE || m_sAdditionalConfigData.focusOnActivate) || (m_eSuppressedEvents & SUPPRESS_ACTIVATE_FOCUSONLY) || (m_eSuppressedEvents & SUPPRESS_ACTIVATE))) + if (!force && (!m_sWindowData.focusOnActivate.valueOr(*PFOCUSONACTIVATE) || (m_eSuppressedEvents & SUPPRESS_ACTIVATE_FOCUSONLY) || (m_eSuppressedEvents & SUPPRESS_ACTIVATE))) return; if (m_bIsFloating) @@ -1526,9 +1480,6 @@ void CWindow::onX11Configure(CBox box) { m_bCreatedOverFullscreen = true; - if (!m_sAdditionalConfigData.windowDanceCompat) - g_pInputManager->refocus(); - g_pHyprRenderer->damageWindow(m_pSelf.lock()); } @@ -1597,3 +1548,12 @@ PHLWINDOW CWindow::getSwallower() { // if none are found (??) then just return the first one return candidates.at(0); } + +void CWindow::unsetWindowData(eOverridePriority priority) { + for (auto const& element : g_pConfigManager->mbWindowProperties) { + element.second(m_pSelf.lock())->unset(priority); + } + for (auto const& element : g_pConfigManager->miWindowProperties) { + element.second(m_pSelf.lock())->unset(priority); + } +} diff --git a/src/desktop/Window.hpp b/src/desktop/Window.hpp index 6bfdbc50..60189fac 100644 --- a/src/desktop/Window.hpp +++ b/src/desktop/Window.hpp @@ -59,13 +59,36 @@ enum eSuppressEvents { class IWindowTransformer; +struct SAlphaValue { + float m_fAlpha; + bool m_bOverride; + + float applyAlpha(float alpha) { + if (m_bOverride) + return m_fAlpha; + else + return m_fAlpha * alpha; + }; +}; + +enum eOverridePriority { + PRIORITY_LAYOUT, + PRIORITY_WORKSPACE_RULE, + PRIORITY_WINDOW_RULE, + PRIORITY_SET_PROP, +}; + template class CWindowOverridableVar { public: - CWindowOverridableVar(T const& val) { - value = val; + CWindowOverridableVar(T const& value, eOverridePriority priority) { + values[priority] = value; + } + CWindowOverridableVar(T const& value) { + defaultValue = value; } + CWindowOverridableVar() = default; ~CWindowOverridableVar() = default; CWindowOverridableVar& operator=(CWindowOverridableVar const& other) { @@ -73,112 +96,91 @@ class CWindowOverridableVar { if (this == &other) return *this; - // Check if the current object is locked - if (!locked) { - locked = other.locked; - value = other.value; + for (auto const& value : other.values) { + values[value.first] = value.second; } return *this; } - T operator=(T& other) { - if (locked) - return value; - value = other; - return other; + void unset(eOverridePriority priority) { + values.erase(priority); } - void forceSetIgnoreLocked(T const& val, bool lock = false) { - value = val; - locked = lock; + bool hasValue() { + return !values.empty(); } - T operator*(T const& other) { - return value * other; + T value() { + if (!values.empty()) + return std::prev(values.end())->second; + else + throw std::bad_optional_access(); } - T operator+(T const& other) { - return value + other; + T valueOr(T const& other) { + if (hasValue()) + return value(); + else + return other; } - bool operator==(T const& other) { - return other == value; + T valueOrDefault() { + return valueOr(defaultValue); } - bool operator>=(T const& other) { - return value >= other; + eOverridePriority getPriority() { + if (!values.empty()) + return std::prev(values.end())->first; + else + throw std::bad_optional_access(); } - bool operator<=(T const& other) { - return value <= other; + void matchOptional(std::optional const& optValue, eOverridePriority priority) { + if (optValue.has_value()) + values[priority] = optValue.value(); + else + unset(priority); } - bool operator>(T const& other) { - return value > other; - } - - bool operator<(T const& other) { - return value < other; - } - - explicit operator bool() { - return static_cast(value); - } - - T toUnderlying() { - return value; - } - - bool locked = false; - private: - T value; + std::map values; + T defaultValue; // used for toggling, so required for bool }; -struct SWindowSpecialRenderData { - CWindowOverridableVar alphaOverride = false; - CWindowOverridableVar alpha = 1.f; - CWindowOverridableVar alphaInactiveOverride = false; - CWindowOverridableVar alphaInactive = -1.f; // -1 means unset - CWindowOverridableVar alphaFullscreenOverride = false; - CWindowOverridableVar alphaFullscreen = -1.f; // -1 means unset +struct SWindowData { + CWindowOverridableVar alpha = SAlphaValue{1.f, false}; + CWindowOverridableVar alphaInactive = SAlphaValue{1.f, false}; + CWindowOverridableVar alphaFullscreen = SAlphaValue{1.f, false}; - CWindowOverridableVar activeBorderColor = CGradientValueData(); // empty color vector means unset - CWindowOverridableVar inactiveBorderColor = CGradientValueData(); // empty color vector means unset + CWindowOverridableVar allowsInput = false; + CWindowOverridableVar dimAround = false; + CWindowOverridableVar decorate = true; + CWindowOverridableVar focusOnActivate = false; + CWindowOverridableVar keepAspectRatio = false; + CWindowOverridableVar nearestNeighbor = false; + CWindowOverridableVar noAnim = false; + CWindowOverridableVar noBorder = false; + CWindowOverridableVar noBlur = false; + CWindowOverridableVar noDim = false; + CWindowOverridableVar noFocus = false; + CWindowOverridableVar noMaxSize = false; + CWindowOverridableVar noRounding = false; + CWindowOverridableVar noShadow = false; + CWindowOverridableVar opaque = false; + CWindowOverridableVar RGBX = false; + CWindowOverridableVar tearing = false; + CWindowOverridableVar xray = false; - // set by the layout - CWindowOverridableVar borderSize = -1; // -1 means unset - bool rounding = true; - bool border = true; - bool decorate = true; - bool shadow = true; -}; + CWindowOverridableVar rounding; + CWindowOverridableVar borderSize; -struct SWindowAdditionalConfigData { - std::string animationStyle = std::string(""); - CWindowOverridableVar rounding = -1; // -1 means no - CWindowOverridableVar forceNoBlur = false; - CWindowOverridableVar forceOpaque = false; - CWindowOverridableVar forceOpaqueOverridden = false; // if true, a rule will not change the forceOpaque state. This is for the force opaque dispatcher. - CWindowOverridableVar forceAllowsInput = false; - CWindowOverridableVar forceNoAnims = false; - CWindowOverridableVar forceNoBorder = false; - CWindowOverridableVar forceNoShadow = false; - CWindowOverridableVar forceNoDim = false; - CWindowOverridableVar noFocus = false; - CWindowOverridableVar windowDanceCompat = false; - CWindowOverridableVar noMaxSize = false; - CWindowOverridableVar maxSize = Vector2D(std::numeric_limits::max(), std::numeric_limits::max()); - CWindowOverridableVar minSize = Vector2D(20, 20); - CWindowOverridableVar dimAround = false; - CWindowOverridableVar forceRGBX = false; - CWindowOverridableVar keepAspectRatio = false; - CWindowOverridableVar focusOnActivate = false; - CWindowOverridableVar xray = -1; // -1 means unset, takes precedence over the renderdata one - CWindowOverridableVar borderSize = -1; // -1 means unset, takes precedence over the renderdata one - CWindowOverridableVar forceTearing = false; - CWindowOverridableVar nearestNeighbor = false; + CWindowOverridableVar animationStyle; + CWindowOverridableVar maxSize; + CWindowOverridableVar minSize; + + CWindowOverridableVar activeBorderColor; + CWindowOverridableVar inactiveBorderColor; }; struct SWindowRule { @@ -331,8 +333,7 @@ class CWindow { std::vector m_vDecosToRemove; // Special render data, rules, etc - SWindowSpecialRenderData m_sSpecialRenderData; - SWindowAdditionalConfigData m_sAdditionalConfigData; + SWindowData m_sWindowData; // Transformers std::vector> m_vTransformers; @@ -423,8 +424,8 @@ class CWindow { int surfacesCount(); int getRealBorderSize(); - void updateSpecialRenderData(); - void updateSpecialRenderData(const struct SWorkspaceRule&); + void updateWindowData(); + void updateWindowData(const struct SWorkspaceRule&); void onBorderAngleAnimEnd(void* ptr); bool isInCurvedCorner(double x, double y); @@ -455,6 +456,7 @@ class CWindow { std::string fetchClass(); void warpCursor(); PHLWINDOW getSwallower(); + void unsetWindowData(eOverridePriority priority); // listeners void onAck(uint32_t serial); diff --git a/src/events/Windows.cpp b/src/events/Windows.cpp index bb1197e5..1612deeb 100644 --- a/src/events/Windows.cpp +++ b/src/events/Windows.cpp @@ -196,8 +196,6 @@ void Events::listener_mapWindow(void* owner, void* data) { PWINDOW->m_bIsFloating = false; } else if (r.szRule.starts_with("pseudo")) { PWINDOW->m_bIsPseudotiled = true; - } else if (r.szRule.starts_with("nofocus")) { - PWINDOW->m_sAdditionalConfigData.noFocus = true; } else if (r.szRule.starts_with("noinitialfocus")) { PWINDOW->m_bNoInitialFocus = true; } else if (r.szRule.starts_with("suppressevent")) { @@ -219,12 +217,6 @@ void Events::listener_mapWindow(void* owner, void* data) { overridingNoFullscreen = true; } else if (r.szRule == "fakefullscreen") { requestsFakeFullscreen = true; - } else if (r.szRule == "windowdance") { - PWINDOW->m_sAdditionalConfigData.windowDanceCompat = true; - } else if (r.szRule == "nomaxsize") { - PWINDOW->m_sAdditionalConfigData.noMaxSize = true; - } else if (r.szRule == "forceinput") { - PWINDOW->m_sAdditionalConfigData.forceAllowsInput = true; } else if (r.szRule == "pin") { PWINDOW->m_bPinned = true; } else if (r.szRule == "maximize") { @@ -321,7 +313,7 @@ void Events::listener_mapWindow(void* owner, void* data) { workspaceSilent = false; } - PWINDOW->updateSpecialRenderData(); + PWINDOW->updateWindowData(); if (PWINDOW->m_bIsFloating) { g_pLayoutManager->getCurrentLayout()->onWindowCreatedFloating(PWINDOW); @@ -457,10 +449,10 @@ void Events::listener_mapWindow(void* owner, void* data) { const auto PFOCUSEDWINDOWPREV = g_pCompositor->m_pLastWindow.lock(); - if (PWINDOW->m_sAdditionalConfigData.forceAllowsInput) { - PWINDOW->m_sAdditionalConfigData.noFocus = false; - PWINDOW->m_bNoInitialFocus = false; - PWINDOW->m_bX11ShouldntFocus = false; + if (PWINDOW->m_sWindowData.allowsInput.valueOrDefault()) { // if default value wasn't set to false getPriority() would throw an exception + PWINDOW->m_sWindowData.noFocus = CWindowOverridableVar(false, PWINDOW->m_sWindowData.allowsInput.getPriority()); + PWINDOW->m_bNoInitialFocus = false; + PWINDOW->m_bX11ShouldntFocus = false; } // check LS focus grab @@ -479,12 +471,12 @@ void Events::listener_mapWindow(void* owner, void* data) { requestsFullscreen = true; } - if (!PWINDOW->m_sAdditionalConfigData.noFocus && !PWINDOW->m_bNoInitialFocus && + if (!PWINDOW->m_sWindowData.noFocus.valueOrDefault() && !PWINDOW->m_bNoInitialFocus && (PWINDOW->m_iX11Type != 2 || (PWINDOW->m_bIsX11 && PWINDOW->m_pXWaylandSurface->wantsFocus())) && !workspaceSilent && (!PFORCEFOCUS || PFORCEFOCUS == PWINDOW) && !g_pInputManager->isConstrained()) { g_pCompositor->focusWindow(PWINDOW); PWINDOW->m_fActiveInactiveAlpha.setValueAndWarp(*PACTIVEALPHA); - PWINDOW->m_fDimPercent.setValueAndWarp(PWINDOW->m_sAdditionalConfigData.forceNoDim ? 0.f : *PDIMSTRENGTH); + PWINDOW->m_fDimPercent.setValueAndWarp(PWINDOW->m_sWindowData.noDim.valueOrDefault() ? 0.f : *PDIMSTRENGTH); } else { PWINDOW->m_fActiveInactiveAlpha.setValueAndWarp(*PINACTIVEALPHA); PWINDOW->m_fDimPercent.setValueAndWarp(0); diff --git a/src/layout/DwindleLayout.cpp b/src/layout/DwindleLayout.cpp index cbeaa420..d1b4b7ca 100644 --- a/src/layout/DwindleLayout.cpp +++ b/src/layout/DwindleLayout.cpp @@ -139,7 +139,7 @@ void CHyprDwindleLayout::applyNodeDataToWindow(SDwindleNodeData* pNode, bool for if (PWINDOW->m_bIsFullscreen && !pNode->ignoreFullscreenChecks) return; - PWINDOW->updateSpecialRenderData(); + PWINDOW->unsetWindowData(PRIORITY_LAYOUT); static auto PNOGAPSWHENONLY = CConfigValue("dwindle:no_gaps_when_only"); static auto PGAPSINDATA = CConfigValue("general:gaps_in"); @@ -160,10 +160,10 @@ void CHyprDwindleLayout::applyNodeDataToWindow(SDwindleNodeData* pNode, bool for if (*PNOGAPSWHENONLY && !PWINDOW->onSpecialWorkspace() && (NODESONWORKSPACE == 1 || (PWINDOW->m_bIsFullscreen && PWINDOW->m_pWorkspace->m_efFullscreenMode == FULLSCREEN_MAXIMIZED))) { - PWINDOW->m_sSpecialRenderData.border = WORKSPACERULE.border.value_or(*PNOGAPSWHENONLY == 2); - PWINDOW->m_sSpecialRenderData.decorate = WORKSPACERULE.decorate.value_or(true); - PWINDOW->m_sSpecialRenderData.rounding = false; - PWINDOW->m_sSpecialRenderData.shadow = false; + PWINDOW->m_sWindowData.decorate = CWindowOverridableVar(true, PRIORITY_LAYOUT); + PWINDOW->m_sWindowData.noBorder = CWindowOverridableVar(*PNOGAPSWHENONLY != 2, PRIORITY_LAYOUT); + PWINDOW->m_sWindowData.noRounding = CWindowOverridableVar(true, PRIORITY_LAYOUT); + PWINDOW->m_sWindowData.noShadow = CWindowOverridableVar(true, PRIORITY_LAYOUT); PWINDOW->updateWindowDecos(); @@ -496,7 +496,7 @@ void CHyprDwindleLayout::onWindowRemovedTiling(PHLWINDOW pWindow) { return; } - pWindow->updateSpecialRenderData(); + pWindow->unsetWindowData(PRIORITY_LAYOUT); if (pWindow->m_bIsFullscreen) g_pCompositor->setWindowFullscreen(pWindow, false, FULLSCREEN_FULL); @@ -830,7 +830,7 @@ void CHyprDwindleLayout::fullscreenRequestForWindow(PHLWINDOW pWindow, eFullscre pWindow->m_vRealPosition = pWindow->m_vLastFloatingPosition; pWindow->m_vRealSize = pWindow->m_vLastFloatingSize; - pWindow->updateSpecialRenderData(); + pWindow->unsetWindowData(PRIORITY_LAYOUT); } } else { // if it now got fullscreen, make it fullscreen diff --git a/src/layout/IHyprLayout.cpp b/src/layout/IHyprLayout.cpp index c6a7a66c..56d22d4b 100644 --- a/src/layout/IHyprLayout.cpp +++ b/src/layout/IHyprLayout.cpp @@ -386,8 +386,12 @@ void IHyprLayout::onMouseMove(const Vector2D& mousePos) { } else if (g_pInputManager->dragMode == MBIND_RESIZE || g_pInputManager->dragMode == MBIND_RESIZE_FORCE_RATIO || g_pInputManager->dragMode == MBIND_RESIZE_BLOCK_RATIO) { if (DRAGGINGWINDOW->m_bIsFloating) { - Vector2D MINSIZE = g_pXWaylandManager->getMinSizeForWindow(DRAGGINGWINDOW).clamp(DRAGGINGWINDOW->m_sAdditionalConfigData.minSize.toUnderlying()); - Vector2D MAXSIZE = g_pXWaylandManager->getMaxSizeForWindow(DRAGGINGWINDOW).clamp({}, DRAGGINGWINDOW->m_sAdditionalConfigData.maxSize.toUnderlying()); + Vector2D MINSIZE = g_pXWaylandManager->getMinSizeForWindow(DRAGGINGWINDOW).clamp(DRAGGINGWINDOW->m_sWindowData.minSize.valueOr(Vector2D(20, 20))); + Vector2D MAXSIZE; + if (DRAGGINGWINDOW->m_sWindowData.maxSize.hasValue()) + MAXSIZE = g_pXWaylandManager->getMaxSizeForWindow(DRAGGINGWINDOW).clamp({}, DRAGGINGWINDOW->m_sWindowData.maxSize.value()); + else + MAXSIZE = g_pXWaylandManager->getMaxSizeForWindow(DRAGGINGWINDOW).clamp({}, Vector2D(std::numeric_limits::max(), std::numeric_limits::max())); Vector2D newSize = m_vBeginDragSizeXY; Vector2D newPos = m_vBeginDragPositionXY; @@ -403,7 +407,7 @@ void IHyprLayout::onMouseMove(const Vector2D& mousePos) { if ((m_vBeginDragSizeXY.x >= 1 && m_vBeginDragSizeXY.y >= 1) && (g_pInputManager->dragMode == MBIND_RESIZE_FORCE_RATIO || - (!(g_pInputManager->dragMode == MBIND_RESIZE_BLOCK_RATIO) && DRAGGINGWINDOW->m_sAdditionalConfigData.keepAspectRatio))) { + (!(g_pInputManager->dragMode == MBIND_RESIZE_BLOCK_RATIO) && DRAGGINGWINDOW->m_sWindowData.keepAspectRatio.valueOrDefault()))) { const float RATIO = m_vBeginDragSizeXY.y / m_vBeginDragSizeXY.x; @@ -538,7 +542,7 @@ void IHyprLayout::changeWindowFloatingMode(PHLWINDOW pWindow) { g_pHyprRenderer->damageMonitor(g_pCompositor->getMonitorFromID(pWindow->m_iMonitorID)); - pWindow->updateSpecialRenderData(); + pWindow->unsetWindowData(PRIORITY_LAYOUT); if (pWindow == m_pLastTiledWindow) m_pLastTiledWindow.reset(); @@ -587,7 +591,7 @@ PHLWINDOW IHyprLayout::getNextWindowCandidate(PHLWINDOW pWindow) { // find whether there is a floating window below this one for (auto& w : g_pCompositor->m_vWindows) { if (w->m_bIsMapped && !w->isHidden() && w->m_bIsFloating && w->m_iX11Type != 2 && w->m_pWorkspace == pWindow->m_pWorkspace && !w->m_bX11ShouldntFocus && - !w->m_sAdditionalConfigData.noFocus && w != pWindow) { + !w->m_sWindowData.noFocus.valueOrDefault() && w != pWindow) { if (VECINRECT((pWindow->m_vSize / 2.f + pWindow->m_vPosition), w->m_vPosition.x, w->m_vPosition.y, w->m_vPosition.x + w->m_vSize.x, w->m_vPosition.y + w->m_vSize.y)) { return w; @@ -607,7 +611,7 @@ PHLWINDOW IHyprLayout::getNextWindowCandidate(PHLWINDOW pWindow) { // if not, floating window for (auto& w : g_pCompositor->m_vWindows) { if (w->m_bIsMapped && !w->isHidden() && w->m_bIsFloating && w->m_iX11Type != 2 && w->m_pWorkspace == pWindow->m_pWorkspace && !w->m_bX11ShouldntFocus && - !w->m_sAdditionalConfigData.noFocus && w != pWindow) + !w->m_sWindowData.noFocus.valueOrDefault() && w != pWindow) return w; } diff --git a/src/layout/MasterLayout.cpp b/src/layout/MasterLayout.cpp index 965c0ed7..b5f2fa9f 100644 --- a/src/layout/MasterLayout.cpp +++ b/src/layout/MasterLayout.cpp @@ -264,7 +264,7 @@ void CHyprMasterLayout::onWindowRemovedTiling(PHLWINDOW pWindow) { const auto MASTERSLEFT = getMastersOnWorkspace(WORKSPACEID); static auto SMALLSPLIT = CConfigValue("master:allow_small_split"); - pWindow->updateSpecialRenderData(); + pWindow->unsetWindowData(PRIORITY_LAYOUT); g_pCompositor->setWindowFullscreen(pWindow, false, FULLSCREEN_FULL); @@ -646,7 +646,7 @@ void CHyprMasterLayout::applyNodeDataToWindow(SMasterNodeData* pNode) { if (PWINDOW->m_bIsFullscreen && !pNode->ignoreFullscreenChecks) return; - PWINDOW->updateSpecialRenderData(); + PWINDOW->unsetWindowData(PRIORITY_LAYOUT); static auto PNOGAPSWHENONLY = CConfigValue("master:no_gaps_when_only"); static auto PANIMATE = CConfigValue("misc:animate_manual_resizes"); @@ -669,10 +669,10 @@ void CHyprMasterLayout::applyNodeDataToWindow(SMasterNodeData* pNode) { if (*PNOGAPSWHENONLY && !PWINDOW->onSpecialWorkspace() && (getNodesOnWorkspace(PWINDOW->workspaceID()) == 1 || (PWINDOW->m_bIsFullscreen && PWINDOW->m_pWorkspace->m_efFullscreenMode == FULLSCREEN_MAXIMIZED))) { - PWINDOW->m_sSpecialRenderData.border = WORKSPACERULE.border.value_or(*PNOGAPSWHENONLY == 2); - PWINDOW->m_sSpecialRenderData.decorate = WORKSPACERULE.decorate.value_or(true); - PWINDOW->m_sSpecialRenderData.rounding = false; - PWINDOW->m_sSpecialRenderData.shadow = false; + PWINDOW->m_sWindowData.decorate = CWindowOverridableVar(true, PRIORITY_LAYOUT); + PWINDOW->m_sWindowData.noBorder = CWindowOverridableVar(*PNOGAPSWHENONLY != 2, PRIORITY_LAYOUT); + PWINDOW->m_sWindowData.noRounding = CWindowOverridableVar(true, PRIORITY_LAYOUT); + PWINDOW->m_sWindowData.noShadow = CWindowOverridableVar(true, PRIORITY_LAYOUT); PWINDOW->updateWindowDecos(); @@ -922,7 +922,7 @@ void CHyprMasterLayout::fullscreenRequestForWindow(PHLWINDOW pWindow, eFullscree pWindow->m_vRealPosition = pWindow->m_vLastFloatingPosition; pWindow->m_vRealSize = pWindow->m_vLastFloatingSize; - pWindow->updateSpecialRenderData(); + pWindow->unsetWindowData(PRIORITY_LAYOUT); } } else { // if it now got fullscreen, make it fullscreen diff --git a/src/managers/AnimationManager.cpp b/src/managers/AnimationManager.cpp index 1fec375e..677b2109 100644 --- a/src/managers/AnimationManager.cpp +++ b/src/managers/AnimationManager.cpp @@ -102,7 +102,7 @@ void CAnimationManager::tick() { PMONITOR = g_pCompositor->getMonitorFromID(PWINDOW->m_iMonitorID); if (!PMONITOR) continue; - animationsDisabled = animationsDisabled || PWINDOW->m_sAdditionalConfigData.forceNoAnims; + animationsDisabled = PWINDOW->m_sWindowData.noAnim.valueOr(animationsDisabled); } else if (PWORKSPACE) { PMONITOR = g_pCompositor->getMonitorFromID(PWORKSPACE->m_iMonitorID); if (!PMONITOR) @@ -407,18 +407,19 @@ void CAnimationManager::onWindowPostCreateClose(PHLWINDOW pWindow, bool close) { if (!pWindow->m_vRealPosition.m_pConfig->pValues->internalEnabled) return; - if (pWindow->m_sAdditionalConfigData.animationStyle != "") { + if (pWindow->m_sWindowData.animationStyle.hasValue()) { + const auto STYLE = pWindow->m_sWindowData.animationStyle.value(); // the window has config'd special anim - if (pWindow->m_sAdditionalConfigData.animationStyle.starts_with("slide")) { - CVarList animList2(pWindow->m_sAdditionalConfigData.animationStyle, 0, 's'); + if (STYLE.starts_with("slide")) { + CVarList animList2(STYLE, 0, 's'); animationSlide(pWindow, animList2[1], close); } else { // anim popin, fallback float minPerc = 0.f; - if (pWindow->m_sAdditionalConfigData.animationStyle.find("%") != std::string::npos) { + if (STYLE.find("%") != std::string::npos) { try { - auto percstr = pWindow->m_sAdditionalConfigData.animationStyle.substr(pWindow->m_sAdditionalConfigData.animationStyle.find_last_of(' ')); + auto percstr = STYLE.substr(STYLE.find_last_of(' ')); minPerc = std::stoi(percstr.substr(0, percstr.length() - 1)); } catch (std::exception& e) { ; // oops diff --git a/src/managers/KeybindManager.cpp b/src/managers/KeybindManager.cpp index cfc77c10..eb8a3232 100644 --- a/src/managers/KeybindManager.cpp +++ b/src/managers/KeybindManager.cpp @@ -252,7 +252,7 @@ bool CKeybindManager::ensureMouseBindState() { g_pInputManager->dragMode = MBIND_INVALID; g_pCompositor->updateWorkspaceWindows(lastDraggedWindow->workspaceID()); - g_pCompositor->updateWorkspaceSpecialRenderData(lastDraggedWindow->workspaceID()); + g_pCompositor->updateWorkspaceWindowData(lastDraggedWindow->workspaceID()); g_pLayoutManager->getCurrentLayout()->recalculateMonitor(lastDraggedWindow->m_iMonitorID); g_pCompositor->updateAllWindowsAnimatedDecorationValues(); @@ -974,7 +974,7 @@ static void toggleActiveFloatingCore(std::string args, std::optional float g_pLayoutManager->getCurrentLayout()->changeWindowFloatingMode(PWINDOW); } g_pCompositor->updateWorkspaceWindows(PWINDOW->workspaceID()); - g_pCompositor->updateWorkspaceSpecialRenderData(PWINDOW->workspaceID()); + g_pCompositor->updateWorkspaceWindowData(PWINDOW->workspaceID()); g_pLayoutManager->getCurrentLayout()->recalculateMonitor(PWINDOW->m_iMonitorID); g_pCompositor->updateAllWindowsAnimatedDecorationValues(); } @@ -2239,8 +2239,7 @@ void CKeybindManager::toggleOpaque(std::string unused) { if (!PWINDOW) return; - PWINDOW->m_sAdditionalConfigData.forceOpaque = !PWINDOW->m_sAdditionalConfigData.forceOpaque; - PWINDOW->m_sAdditionalConfigData.forceOpaqueOverridden = true; + PWINDOW->m_sWindowData.opaque = CWindowOverridableVar(!PWINDOW->m_sWindowData.opaque.valueOrDefault(), PRIORITY_SET_PROP); g_pHyprRenderer->damageWindow(PWINDOW); } diff --git a/src/managers/XWaylandManager.cpp b/src/managers/XWaylandManager.cpp index 12387900..e702a172 100644 --- a/src/managers/XWaylandManager.cpp +++ b/src/managers/XWaylandManager.cpp @@ -206,7 +206,8 @@ Vector2D CHyprXWaylandManager::getMaxSizeForWindow(PHLWINDOW pWindow) { if (!validMapped(pWindow)) return Vector2D(99999, 99999); - if ((pWindow->m_bIsX11 && !pWindow->m_pXWaylandSurface->sizeHints) || (!pWindow->m_bIsX11 && !pWindow->m_pXDGSurface->toplevel) || pWindow->m_sAdditionalConfigData.noMaxSize) + if ((pWindow->m_bIsX11 && !pWindow->m_pXWaylandSurface->sizeHints) || (!pWindow->m_bIsX11 && !pWindow->m_pXDGSurface->toplevel) || + pWindow->m_sWindowData.noMaxSize.valueOrDefault()) return Vector2D(99999, 99999); auto MAXSIZE = pWindow->m_bIsX11 ? Vector2D(pWindow->m_pXWaylandSurface->sizeHints->max_width, pWindow->m_pXWaylandSurface->sizeHints->max_height) : diff --git a/src/render/OpenGL.cpp b/src/render/OpenGL.cpp index 3178ab8c..2b603868 100644 --- a/src/render/OpenGL.cpp +++ b/src/render/OpenGL.cpp @@ -434,7 +434,7 @@ bool CHyprOpenGLImpl::passRequiresIntrospection(CMonitor* pMonitor) { if (!w->m_bIsFloating && *POPTIM && !w->onSpecialWorkspace()) continue; - if (w->m_sAdditionalConfigData.forceNoBlur.toUnderlying() == true || w->m_sAdditionalConfigData.xray.toUnderlying() == true) + if (w->m_sWindowData.noBlur.valueOrDefault() || w->m_sWindowData.xray.valueOrDefault() == true) continue; if (w->opaque()) @@ -1130,7 +1130,7 @@ void CHyprOpenGLImpl::renderTextureInternalWithDamage(SP tex, CBox* pB } } - if (m_pCurrentWindow.lock() && m_pCurrentWindow->m_sAdditionalConfigData.forceRGBX) + if (m_pCurrentWindow.lock() && m_pCurrentWindow->m_sWindowData.RGBX.valueOrDefault()) shader = &m_RenderData.pCurrentMonData->m_shRGBX; glActiveTexture(GL_TEXTURE0); @@ -1601,7 +1601,7 @@ void CHyprOpenGLImpl::preRender(CMonitor* pMonitor) { if (!pWindow) return false; - if (pWindow->m_sAdditionalConfigData.forceNoBlur) + if (pWindow->m_sWindowData.noBlur.valueOrDefault()) return false; if (pWindow->m_pWLSurface->small() && !pWindow->m_pWLSurface->m_bFillIgnoreSmall) @@ -1717,7 +1717,7 @@ bool CHyprOpenGLImpl::shouldUseNewBlurOptimizations(PHLLS pLayer, PHLWINDOW pWin if (!m_RenderData.pCurrentMonData->blurFB.m_cTex->m_iTexID) return false; - if (pWindow && pWindow->m_sAdditionalConfigData.xray.toUnderlying() == 0) + if (pWindow && !pWindow->m_sWindowData.xray.valueOrDefault()) return false; if (pLayer && pLayer->xray == 0) @@ -1726,7 +1726,7 @@ bool CHyprOpenGLImpl::shouldUseNewBlurOptimizations(PHLLS pLayer, PHLWINDOW pWin if ((*PBLURNEWOPTIMIZE && pWindow && !pWindow->m_bIsFloating && !pWindow->onSpecialWorkspace()) || *PBLURXRAY) return true; - if ((pLayer && pLayer->xray == 1) || (pWindow && pWindow->m_sAdditionalConfigData.xray.toUnderlying() == 1)) + if ((pLayer && pLayer->xray == 1) || (pWindow && pWindow->m_sWindowData.xray.valueOrDefault())) return true; return false; @@ -1750,7 +1750,7 @@ void CHyprOpenGLImpl::renderTextureWithBlur(SP tex, CBox* pBox, float m_RenderData.renderModif.applyToRegion(texDamage); if (*PBLURENABLED == 0 || (*PNOBLUROVERSIZED && m_RenderData.primarySurfaceUVTopLeft != Vector2D(-1, -1)) || - (m_pCurrentWindow.lock() && (m_pCurrentWindow->m_sAdditionalConfigData.forceNoBlur || m_pCurrentWindow->m_sAdditionalConfigData.forceRGBX))) { + (m_pCurrentWindow.lock() && (m_pCurrentWindow->m_sWindowData.noBlur.valueOrDefault() || m_pCurrentWindow->m_sWindowData.RGBX.valueOrDefault()))) { renderTexture(tex, pBox, a, round, false, true); return; } @@ -1847,7 +1847,7 @@ void CHyprOpenGLImpl::renderBorder(CBox* box, const CGradientValueData& grad, in TRACY_GPU_ZONE("RenderBorder"); - if (m_RenderData.damage.empty() || (m_pCurrentWindow.lock() && m_pCurrentWindow->m_sAdditionalConfigData.forceNoBorder)) + if (m_RenderData.damage.empty() || (m_pCurrentWindow.lock() && m_pCurrentWindow->m_sWindowData.noBorder.valueOrDefault())) return; CBox newBox = *box; @@ -2108,7 +2108,7 @@ void CHyprOpenGLImpl::renderSnapshot(PHLWINDOW pWindow) { CRegion fakeDamage{0, 0, PMONITOR->vecTransformedSize.x, PMONITOR->vecTransformedSize.y}; - if (*PDIMAROUND && pWindow->m_sAdditionalConfigData.dimAround) { + if (*PDIMAROUND && pWindow->m_sWindowData.dimAround.valueOrDefault()) { CBox monbox = {0, 0, g_pHyprOpenGL->m_RenderData.pMonitor->vecPixelSize.x, g_pHyprOpenGL->m_RenderData.pMonitor->vecPixelSize.y}; g_pHyprOpenGL->renderRect(&monbox, CColor(0, 0, 0, *PDIMAROUND * pWindow->m_fAlpha.value())); g_pHyprRenderer->damageMonitor(PMONITOR); diff --git a/src/render/Renderer.cpp b/src/render/Renderer.cpp index 8d98a182..955a16b9 100644 --- a/src/render/Renderer.cpp +++ b/src/render/Renderer.cpp @@ -531,7 +531,7 @@ void CHyprRenderer::renderWindow(PHLWINDOW pWindow, CMonitor* pMonitor, timespec decorate = false; renderdata.surface = pWindow->m_pWLSurface->resource(); - renderdata.dontRound = (pWindow->m_bIsFullscreen && PWORKSPACE->m_efFullscreenMode == FULLSCREEN_FULL) || (!pWindow->m_sSpecialRenderData.rounding); + renderdata.dontRound = (pWindow->m_bIsFullscreen && PWORKSPACE->m_efFullscreenMode == FULLSCREEN_FULL) || pWindow->m_sWindowData.noRounding.valueOrDefault(); renderdata.fadeAlpha = pWindow->m_fAlpha.value() * (pWindow->m_bPinned ? 1.f : PWORKSPACE->m_fAlpha.value()); renderdata.alpha = pWindow->m_fActiveInactiveAlpha.value(); renderdata.decorate = decorate && !pWindow->m_bX11DoesntWantBorders && (!pWindow->m_bIsFullscreen || PWORKSPACE->m_efFullscreenMode != FULLSCREEN_FULL); @@ -545,14 +545,14 @@ void CHyprRenderer::renderWindow(PHLWINDOW pWindow, CMonitor* pMonitor, timespec } // apply opaque - if (pWindow->m_sAdditionalConfigData.forceOpaque) + if (pWindow->m_sWindowData.opaque.valueOrDefault()) renderdata.alpha = 1.f; g_pHyprOpenGL->m_pCurrentWindow = pWindow; EMIT_HOOK_EVENT("render", RENDER_PRE_WINDOW); - if (*PDIMAROUND && pWindow->m_sAdditionalConfigData.dimAround && !m_bRenderingSnapshot && mode != RENDER_PASS_POPUP) { + if (*PDIMAROUND && pWindow->m_sWindowData.dimAround.valueOrDefault() && !m_bRenderingSnapshot && mode != RENDER_PASS_POPUP) { CBox monbox = {0, 0, g_pHyprOpenGL->m_RenderData.pMonitor->vecTransformedSize.x, g_pHyprOpenGL->m_RenderData.pMonitor->vecTransformedSize.y}; g_pHyprOpenGL->renderRect(&monbox, CColor(0, 0, 0, *PDIMAROUND * renderdata.alpha * renderdata.fadeAlpha)); } @@ -597,10 +597,10 @@ void CHyprRenderer::renderWindow(PHLWINDOW pWindow, CMonitor* pMonitor, timespec } static auto PXWLUSENN = CConfigValue("xwayland:use_nearest_neighbor"); - if ((pWindow->m_bIsX11 && *PXWLUSENN) || pWindow->m_sAdditionalConfigData.nearestNeighbor.toUnderlying()) + if ((pWindow->m_bIsX11 && *PXWLUSENN) || pWindow->m_sWindowData.nearestNeighbor.valueOrDefault()) g_pHyprOpenGL->m_RenderData.useNearestNeighbor = true; - if (!pWindow->m_sAdditionalConfigData.forceNoBlur && pWindow->m_pWLSurface->small() && !pWindow->m_pWLSurface->m_bFillIgnoreSmall && renderdata.blur && *PBLUR) { + if (!pWindow->m_sWindowData.noBlur.valueOrDefault() && pWindow->m_pWLSurface->small() && !pWindow->m_pWLSurface->m_bFillIgnoreSmall && renderdata.blur && *PBLUR) { CBox wb = {renderdata.x - pMonitor->vecPosition.x, renderdata.y - pMonitor->vecPosition.y, renderdata.w, renderdata.h}; wb.scale(pMonitor->scale).round(); g_pHyprOpenGL->renderRectWithBlur(&wb, CColor(0, 0, 0, 0), renderdata.dontRound ? 0 : renderdata.rounding - 1, renderdata.fadeAlpha, @@ -662,7 +662,7 @@ void CHyprRenderer::renderWindow(PHLWINDOW pWindow, CMonitor* pMonitor, timespec g_pHyprOpenGL->m_RenderData.discardOpacity = *PBLURIGNOREA; } - if (pWindow->m_sAdditionalConfigData.nearestNeighbor.toUnderlying()) + if (pWindow->m_sWindowData.nearestNeighbor.valueOrDefault()) g_pHyprOpenGL->m_RenderData.useNearestNeighbor = true; renderdata.surfaceCounter = 0; diff --git a/src/render/decorations/CHyprBorderDecoration.cpp b/src/render/decorations/CHyprBorderDecoration.cpp index 7d9a0401..708215b6 100644 --- a/src/render/decorations/CHyprBorderDecoration.cpp +++ b/src/render/decorations/CHyprBorderDecoration.cpp @@ -133,5 +133,5 @@ std::string CHyprBorderDecoration::getDisplayName() { } bool CHyprBorderDecoration::doesntWantBorders() { - return !m_pWindow->m_sSpecialRenderData.border || m_pWindow->m_bX11DoesntWantBorders || m_pWindow->getRealBorderSize() == 0; + return m_pWindow->m_sWindowData.noBorder.valueOrDefault() || m_pWindow->m_bX11DoesntWantBorders || m_pWindow->getRealBorderSize() == 0; } diff --git a/src/render/decorations/CHyprDropShadowDecoration.cpp b/src/render/decorations/CHyprDropShadowDecoration.cpp index 6893d78c..423256d7 100644 --- a/src/render/decorations/CHyprDropShadowDecoration.cpp +++ b/src/render/decorations/CHyprDropShadowDecoration.cpp @@ -96,13 +96,10 @@ void CHyprDropShadowDecoration::draw(CMonitor* pMonitor, float a) { if (PWINDOW->m_cRealShadowColor.value() == CColor(0, 0, 0, 0)) return; // don't draw invisible shadows - if (!PWINDOW->m_sSpecialRenderData.decorate) + if (!PWINDOW->m_sWindowData.decorate.valueOrDefault()) return; - if (!PWINDOW->m_sSpecialRenderData.shadow) - return; - - if (PWINDOW->m_sAdditionalConfigData.forceNoShadow) + if (PWINDOW->m_sWindowData.noShadow.valueOrDefault()) return; static auto PSHADOWS = CConfigValue("decoration:drop_shadow"); diff --git a/src/render/decorations/CHyprGroupBarDecoration.cpp b/src/render/decorations/CHyprGroupBarDecoration.cpp index e461ba08..a13750d0 100644 --- a/src/render/decorations/CHyprGroupBarDecoration.cpp +++ b/src/render/decorations/CHyprGroupBarDecoration.cpp @@ -42,7 +42,7 @@ SDecorationPositioningInfo CHyprGroupBarDecoration::getPositioningInfo() { info.priority = *PPRIORITY; info.reserved = true; - if (*PENABLED && m_pWindow->m_sSpecialRenderData.decorate) { + if (*PENABLED && m_pWindow->m_sWindowData.decorate.valueOrDefault()) { if (*PSTACKED) { const auto ONEBARHEIGHT = BAR_PADDING_OUTER_VERT + BAR_INDICATOR_HEIGHT + (*PGRADIENTS || *PRENDERTITLES ? *PHEIGHT : 0); info.desiredExtents = {{0, (ONEBARHEIGHT * m_dwGroupMembers.size()) + 2 + BAR_PADDING_OUTER_VERT}, {0, 0}}; @@ -105,7 +105,7 @@ void CHyprGroupBarDecoration::draw(CMonitor* pMonitor, float a) { static auto PGRADIENTS = CConfigValue("group:groupbar:gradients"); static auto PSTACKED = CConfigValue("group:groupbar:stacked"); - if (!*PENABLED || !m_pWindow->m_sSpecialRenderData.decorate) + if (!*PENABLED || !m_pWindow->m_sWindowData.decorate.valueOrDefault()) return; const auto ASSIGNEDBOX = assignedBoxGlobal(); From 3247d18a7c257ac8c59bf9bfdebaaf51bfc5c1df Mon Sep 17 00:00:00 2001 From: vaxerski Date: Thu, 11 Jul 2024 14:12:19 +0000 Subject: [PATCH 0097/2181] [gha] Nix: update inputs --- flake.lock | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/flake.lock b/flake.lock index d3f40397..1066e37b 100644 --- a/flake.lock +++ b/flake.lock @@ -87,11 +87,11 @@ ] }, "locked": { - "lastModified": 1720203444, - "narHash": "sha256-lq2dPPPcwMHTLsFrQ2pRp4c2LwDZWoqzSyjuPdeJCP4=", + "lastModified": 1720545076, + "narHash": "sha256-Pxacc2uoxI00koXp5+CyNqHOTQlqNlK0rlRHDBHX4+g=", "owner": "hyprwm", "repo": "hyprutils", - "rev": "a8c3a135701a7b64db0a88ec353a392f402d2a87", + "rev": "6174a2a25f4e216c0f1d0c4278adc23c476b1d09", "type": "github" }, "original": { @@ -125,11 +125,11 @@ }, "nixpkgs": { "locked": { - "lastModified": 1720031269, - "narHash": "sha256-rwz8NJZV+387rnWpTYcXaRNvzUSnnF9aHONoJIYmiUQ=", + "lastModified": 1720542800, + "narHash": "sha256-ZgnNHuKV6h2+fQ5LuqnUaqZey1Lqqt5dTUAiAnqH0QQ=", "owner": "NixOS", "repo": "nixpkgs", - "rev": "9f4128e00b0ae8ec65918efeba59db998750ead6", + "rev": "feb2849fdeb70028c70d73b848214b00d324a497", "type": "github" }, "original": { From 9ff83f4aa97269bf26381a84501d0b19f1926961 Mon Sep 17 00:00:00 2001 From: Maximilian Seidler <78690852+PaideiaDilemma@users.noreply.github.com> Date: Thu, 11 Jul 2024 16:40:43 +0200 Subject: [PATCH 0098/2181] sessionLock: fix the check for locking a locked session (#6843) --- src/protocols/SessionLock.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/protocols/SessionLock.cpp b/src/protocols/SessionLock.cpp index e7abc7cb..42df5fd6 100644 --- a/src/protocols/SessionLock.cpp +++ b/src/protocols/SessionLock.cpp @@ -177,7 +177,7 @@ void CSessionLockProtocol::onLock(CExtSessionLockManagerV1* pMgr, uint32_t id) { return; } - if (m_vLocks.size() > 1) { + if (locked) { LOGM(ERR, "Tried to lock a locked session"); RESOURCE->inert = true; RESOURCE->resource->sendFinished(); From e728e56cbc6af0a9be1276b2cf8e019a894016e7 Mon Sep 17 00:00:00 2001 From: Virt <41426325+VirtCode@users.noreply.github.com> Date: Mon, 8 Jul 2024 22:50:39 +0200 Subject: [PATCH 0099/2181] meson: install wayland.hpp header --- protocols/meson.build | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/protocols/meson.build b/protocols/meson.build index f4978c23..7c508659 100644 --- a/protocols/meson.build +++ b/protocols/meson.build @@ -113,7 +113,8 @@ foreach p : wl_server_protos wl_server_protos_gen += custom_target( p.underscorify(), input: p, - install: false, + install: true, + install_dir: [false, join_paths(get_option('includedir'), 'hyprland/protocols')], output: ['@BASENAME@.cpp', '@BASENAME@.hpp'], command: [hyprwayland_scanner, '--wayland-enums', '@INPUT@', '@OUTDIR@'], ) From f85c6416c6f5e56c75178ecb24c11e346069197d Mon Sep 17 00:00:00 2001 From: MightyPlaza <123664421+MightyPlaza@users.noreply.github.com> Date: Fri, 12 Jul 2024 21:05:19 +0000 Subject: [PATCH 0100/2181] renderer: fix a few xray regressions (#6855) * fix xray unset modified: src/render/OpenGL.cpp * fix xwray unset modified: src/render/OpenGL.cpp --- src/render/OpenGL.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/render/OpenGL.cpp b/src/render/OpenGL.cpp index 2b603868..2556fafc 100644 --- a/src/render/OpenGL.cpp +++ b/src/render/OpenGL.cpp @@ -434,7 +434,7 @@ bool CHyprOpenGLImpl::passRequiresIntrospection(CMonitor* pMonitor) { if (!w->m_bIsFloating && *POPTIM && !w->onSpecialWorkspace()) continue; - if (w->m_sWindowData.noBlur.valueOrDefault() || w->m_sWindowData.xray.valueOrDefault() == true) + if (w->m_sWindowData.noBlur.valueOrDefault() || !w->m_sWindowData.xray.hasValue() || w->m_sWindowData.xray.valueOrDefault()) continue; if (w->opaque()) @@ -1717,7 +1717,7 @@ bool CHyprOpenGLImpl::shouldUseNewBlurOptimizations(PHLLS pLayer, PHLWINDOW pWin if (!m_RenderData.pCurrentMonData->blurFB.m_cTex->m_iTexID) return false; - if (pWindow && !pWindow->m_sWindowData.xray.valueOrDefault()) + if (pWindow && pWindow->m_sWindowData.xray.hasValue() && !pWindow->m_sWindowData.xray.valueOrDefault()) return false; if (pLayer && pLayer->xray == 0) From 7486576fa7a3d394254cb07734679df4b2469071 Mon Sep 17 00:00:00 2001 From: Junxuan Liao <70618504+MikeWalrus@users.noreply.github.com> Date: Sat, 13 Jul 2024 18:32:08 +0800 Subject: [PATCH 0101/2181] session-lock: send `locked` after the lock screen is properly rendered (#6850) The protocol says: > The locked event "must not be sent until a new "locked" frame (either from a > session lock surface or the compositor blanking the output) has been presented > on all outputs and no security sensitive normal/unlocked content is possibly > visible". This helps users ensure the screen is properly locked before suspending the machine. (e.g. with swaylock --ready-fd) --- src/managers/SessionLockManager.cpp | 15 +++++++++++++-- src/managers/SessionLockManager.hpp | 8 +++++++- src/render/Renderer.cpp | 3 +++ 3 files changed, 23 insertions(+), 3 deletions(-) diff --git a/src/managers/SessionLockManager.cpp b/src/managers/SessionLockManager.cpp index b4695e0e..83ff3ee7 100644 --- a/src/managers/SessionLockManager.cpp +++ b/src/managers/SessionLockManager.cpp @@ -3,6 +3,7 @@ #include "../config/ConfigValue.hpp" #include "../protocols/FractionalScale.hpp" #include "../protocols/SessionLock.hpp" +#include SSessionLockSurface::SSessionLockSurface(SP surface_) : surface(surface_) { pWlrSurface = surface->surface(); @@ -77,7 +78,6 @@ void CSessionLockManager::onNewSessionLock(SP pLock) { g_pHyprRenderer->damageMonitor(m.get()); }); - pLock->sendLocked(); g_pCompositor->focusSurface(nullptr); } @@ -102,7 +102,6 @@ SSessionLockSurface* CSessionLockManager::getSessionLockSurfaceForMonitor(uint64 } // We don't want the red screen to flash. -// This violates the protocol a bit, but tries to handle the missing sync between a lock surface beeing created and the red screen beeing drawn. float CSessionLockManager::getRedScreenAlphaForMonitor(uint64_t id) { if (!m_pSessionLock) return 0.F; @@ -118,6 +117,18 @@ float CSessionLockManager::getRedScreenAlphaForMonitor(uint64_t id) { return std::clamp(NOMAPPEDSURFACETIMER->second.getSeconds() - /* delay for screencopy */ 0.5f, 0.f, 1.f); } +void CSessionLockManager::onLockscreenRenderedOnMonitor(uint64_t id) { + if (!m_pSessionLock || m_pSessionLock->m_hasSentLocked) + return; + m_pSessionLock->m_lockedMonitors.emplace(id); + const auto MONITORS = g_pCompositor->m_vMonitors; + const bool LOCKED = std::all_of(MONITORS.begin(), MONITORS.end(), [this](auto m) { return m_pSessionLock->m_lockedMonitors.contains(m->ID); }); + if (LOCKED) { + m_pSessionLock->lock->sendLocked(); + m_pSessionLock->m_hasSentLocked = true; + } +} + bool CSessionLockManager::isSurfaceSessionLock(SP pSurface) { // TODO: this has some edge cases when it's wrong (e.g. destroyed lock but not yet surfaces) // but can be easily fixed when I rewrite wlr_surface diff --git a/src/managers/SessionLockManager.hpp b/src/managers/SessionLockManager.hpp index fe4a4434..b01ee288 100644 --- a/src/managers/SessionLockManager.hpp +++ b/src/managers/SessionLockManager.hpp @@ -5,6 +5,7 @@ #include "../helpers/signal/Signal.hpp" #include #include +#include class CSessionLockSurface; class CSessionLock; @@ -37,6 +38,9 @@ struct SSessionLock { CHyprSignalListener unlock; CHyprSignalListener destroy; } listeners; + + bool m_hasSentLocked = false; + std::unordered_set m_lockedMonitors; }; class CSessionLockManager { @@ -54,6 +58,8 @@ class CSessionLockManager { void removeSessionLockSurface(SSessionLockSurface*); + void onLockscreenRenderedOnMonitor(uint64_t id); + private: UP m_pSessionLock; @@ -64,4 +70,4 @@ class CSessionLockManager { void onNewSessionLock(SP pWlrLock); }; -inline std::unique_ptr g_pSessionLockManager; \ No newline at end of file +inline std::unique_ptr g_pSessionLockManager; diff --git a/src/render/Renderer.cpp b/src/render/Renderer.cpp index 955a16b9..a7f3c941 100644 --- a/src/render/Renderer.cpp +++ b/src/render/Renderer.cpp @@ -990,8 +990,11 @@ void CHyprRenderer::renderLockscreen(CMonitor* pMonitor, timespec* now, const CB if (ALPHA < 1.f) /* animate */ damageMonitor(pMonitor); + else + g_pSessionLockManager->onLockscreenRenderedOnMonitor(pMonitor->ID); } else { renderSessionLockSurface(PSLS, pMonitor, now); + g_pSessionLockManager->onLockscreenRenderedOnMonitor(pMonitor->ID); } } } From 13bc7e1e1415a0b17db609774f59b594c7633941 Mon Sep 17 00:00:00 2001 From: Vaxry Date: Sat, 13 Jul 2024 12:36:29 +0200 Subject: [PATCH 0102/2181] style: fix clang-format --- src/Compositor.cpp | 3 ++- src/config/ConfigDataValues.hpp | 14 +++++++------- src/helpers/MiscFunctions.cpp | 8 ++------ src/macros.hpp | 3 +-- src/managers/PointerManager.cpp | 3 +-- src/managers/input/InputManager.cpp | 3 +-- src/managers/input/TextInput.cpp | 9 +++------ src/protocols/Tablet.cpp | 3 +-- src/render/Renderbuffer.cpp | 3 +-- 9 files changed, 19 insertions(+), 30 deletions(-) diff --git a/src/Compositor.cpp b/src/Compositor.cpp index 2abc1144..d1c51075 100644 --- a/src/Compositor.cpp +++ b/src/Compositor.cpp @@ -702,7 +702,8 @@ PHLWINDOW CCompositor::vectorToWindowUnified(const Vector2D& pos, uint8_t proper for (auto& w : m_vWindows | std::views::reverse) { const auto BB = w->getWindowBoxUnified(properties); CBox box = BB.copy().expand(w->m_iX11Type == 2 ? BORDER_GRAB_AREA : 0); - if (w->m_bIsFloating && w->m_bIsMapped && !w->isHidden() && !w->m_bX11ShouldntFocus && w->m_bPinned && !w->m_sWindowData.noFocus.valueOrDefault() && w != pIgnoreWindow) { + if (w->m_bIsFloating && w->m_bIsMapped && !w->isHidden() && !w->m_bX11ShouldntFocus && w->m_bPinned && !w->m_sWindowData.noFocus.valueOrDefault() && + w != pIgnoreWindow) { if (box.containsPoint(g_pPointerManager->position())) return w; diff --git a/src/config/ConfigDataValues.hpp b/src/config/ConfigDataValues.hpp index 322bd14a..37c9fc92 100644 --- a/src/config/ConfigDataValues.hpp +++ b/src/config/ConfigDataValues.hpp @@ -20,11 +20,11 @@ class ICustomConfigValueData { class CGradientValueData : public ICustomConfigValueData { public: - CGradientValueData(){}; + CGradientValueData() {}; CGradientValueData(CColor col) { m_vColors.push_back(col); }; - virtual ~CGradientValueData(){}; + virtual ~CGradientValueData() {}; virtual eConfigValueDataTypes getDataType() { return CVD_TYPE_GRADIENT; @@ -67,11 +67,11 @@ class CGradientValueData : public ICustomConfigValueData { class CCssGapData : public ICustomConfigValueData { public: - CCssGapData() : top(0), right(0), bottom(0), left(0){}; - CCssGapData(int64_t global) : top(global), right(global), bottom(global), left(global){}; - CCssGapData(int64_t vertical, int64_t horizontal) : top(vertical), right(horizontal), bottom(vertical), left(horizontal){}; - CCssGapData(int64_t top, int64_t horizontal, int64_t bottom) : top(top), right(horizontal), bottom(bottom), left(horizontal){}; - CCssGapData(int64_t top, int64_t right, int64_t bottom, int64_t left) : top(top), right(right), bottom(bottom), left(left){}; + CCssGapData() : top(0), right(0), bottom(0), left(0) {}; + CCssGapData(int64_t global) : top(global), right(global), bottom(global), left(global) {}; + CCssGapData(int64_t vertical, int64_t horizontal) : top(vertical), right(horizontal), bottom(vertical), left(horizontal) {}; + CCssGapData(int64_t top, int64_t horizontal, int64_t bottom) : top(top), right(horizontal), bottom(bottom), left(horizontal) {}; + CCssGapData(int64_t top, int64_t right, int64_t bottom, int64_t left) : top(top), right(right), bottom(bottom), left(left) {}; /* Css like directions */ int64_t top; diff --git a/src/helpers/MiscFunctions.cpp b/src/helpers/MiscFunctions.cpp index aa034254..712e4e50 100644 --- a/src/helpers/MiscFunctions.cpp +++ b/src/helpers/MiscFunctions.cpp @@ -649,13 +649,9 @@ void matrixProjection(float mat[9], int w, int h, wl_output_transform tr) { int64_t getPPIDof(int64_t pid) { #if defined(KERN_PROC_PID) int mib[] = { - CTL_KERN, - KERN_PROC, - KERN_PROC_PID, - (int)pid, + CTL_KERN, KERN_PROC, KERN_PROC_PID, (int)pid, #if defined(__NetBSD__) || defined(__OpenBSD__) - sizeof(KINFO_PROC), - 1, + sizeof(KINFO_PROC), 1, #endif }; u_int miblen = sizeof(mib) / sizeof(mib[0]); diff --git a/src/macros.hpp b/src/macros.hpp index 67f6301b..f1393cbd 100644 --- a/src/macros.hpp +++ b/src/macros.hpp @@ -40,8 +40,7 @@ #define STICKS(a, b) abs((a) - (b)) < 2 -#define HYPRATOM(name) \ - { name, 0 } +#define HYPRATOM(name) {name, 0} #define RASSERT(expr, reason, ...) \ if (!(expr)) { \ diff --git a/src/managers/PointerManager.cpp b/src/managers/PointerManager.cpp index e34aa54b..7090645f 100644 --- a/src/managers/PointerManager.cpp +++ b/src/managers/PointerManager.cpp @@ -235,8 +235,7 @@ void CPointerManager::setCursorBuffer(wlr_buffer* buf, const Vector2D& hotspot, currentCursorImage.size = {buf->width, buf->height}; currentCursorImage.pBuffer = wlr_buffer_lock(buf); - currentCursorImage.hyprListener_destroyBuffer.initCallback( - &buf->events.destroy, [this](void* owner, void* data) { resetCursorImage(); }, this, "CPointerManager"); + currentCursorImage.hyprListener_destroyBuffer.initCallback(&buf->events.destroy, [this](void* owner, void* data) { resetCursorImage(); }, this, "CPointerManager"); } currentCursorImage.hotspot = hotspot; diff --git a/src/managers/input/InputManager.cpp b/src/managers/input/InputManager.cpp index 9180e9cd..b2bbd577 100644 --- a/src/managers/input/InputManager.cpp +++ b/src/managers/input/InputManager.cpp @@ -1624,8 +1624,7 @@ void CInputManager::newSwitch(wlr_input_device* pDevice) { Debug::log(LOG, "New switch with name \"{}\" added", pDevice->name); - PNEWDEV->hyprListener_destroy.initCallback( - &pDevice->events.destroy, [&](void* owner, void* data) { destroySwitch((SSwitchDevice*)owner); }, PNEWDEV, "SwitchDevice"); + PNEWDEV->hyprListener_destroy.initCallback(&pDevice->events.destroy, [&](void* owner, void* data) { destroySwitch((SSwitchDevice*)owner); }, PNEWDEV, "SwitchDevice"); const auto PSWITCH = wlr_switch_from_input_device(pDevice); diff --git a/src/managers/input/TextInput.cpp b/src/managers/input/TextInput.cpp index 4c7ffe6e..635a8b01 100644 --- a/src/managers/input/TextInput.cpp +++ b/src/managers/input/TextInput.cpp @@ -41,14 +41,11 @@ void CTextInput::initCallbacks() { g_pInputManager->m_sIMERelay.removeTextInput(this); }); } else { - hyprListener_textInputEnable.initCallback( - &pV1Input->sEnable, [this](void* owner, void* data) { onEnabled(); }, this, "textInput"); + hyprListener_textInputEnable.initCallback(&pV1Input->sEnable, [this](void* owner, void* data) { onEnabled(); }, this, "textInput"); - hyprListener_textInputCommit.initCallback( - &pV1Input->sCommit, [this](void* owner, void* data) { onCommit(); }, this, "textInput"); + hyprListener_textInputCommit.initCallback(&pV1Input->sCommit, [this](void* owner, void* data) { onCommit(); }, this, "textInput"); - hyprListener_textInputDisable.initCallback( - &pV1Input->sDisable, [this](void* owner, void* data) { onDisabled(); }, this, "textInput"); + hyprListener_textInputDisable.initCallback(&pV1Input->sDisable, [this](void* owner, void* data) { onDisabled(); }, this, "textInput"); hyprListener_textInputDestroy.initCallback( &pV1Input->sDestroy, diff --git a/src/protocols/Tablet.cpp b/src/protocols/Tablet.cpp index 518ea5bd..7b62f245 100644 --- a/src/protocols/Tablet.cpp +++ b/src/protocols/Tablet.cpp @@ -215,8 +215,7 @@ void CTabletToolV2Resource::queueFrame() { if (frameSource) return; - frameSource = wl_event_loop_add_idle( - g_pCompositor->m_sWLEventLoop, [](void* data) { ((CTabletToolV2Resource*)data)->sendFrame(false); }, this); + frameSource = wl_event_loop_add_idle(g_pCompositor->m_sWLEventLoop, [](void* data) { ((CTabletToolV2Resource*)data)->sendFrame(false); }, this); } void CTabletToolV2Resource::sendFrame(bool removeSource) { diff --git a/src/render/Renderbuffer.cpp b/src/render/Renderbuffer.cpp index b55a921b..3f591d13 100644 --- a/src/render/Renderbuffer.cpp +++ b/src/render/Renderbuffer.cpp @@ -58,8 +58,7 @@ CRenderbuffer::CRenderbuffer(wlr_buffer* buffer, uint32_t format) : m_pWlrBuffer glBindFramebuffer(GL_FRAMEBUFFER, 0); - hyprListener_destroyBuffer.initCallback( - &buffer->events.destroy, [this](void* owner, void* data) { g_pHyprRenderer->onRenderbufferDestroy(this); }, this, "CRenderbuffer"); + hyprListener_destroyBuffer.initCallback(&buffer->events.destroy, [this](void* owner, void* data) { g_pHyprRenderer->onRenderbufferDestroy(this); }, this, "CRenderbuffer"); } CRenderbuffer::CRenderbuffer(SP buffer, uint32_t format) : m_pHLBuffer(buffer), m_uDrmFormat(format) { From 1f6466895326defef370a378f9d7b61a7e246df7 Mon Sep 17 00:00:00 2001 From: Tim Waterhouse Date: Sat, 13 Jul 2024 03:53:23 -0700 Subject: [PATCH 0103/2181] ext-foreign-toplevel: Send done after title and class (#6857) According to the spec (https://wayland.app/protocols/ext-foreign-toplevel-list-v1#ext_foreign_toplevel_handle_v1:event:title), clients should wait for the done signal before applying updates --- src/protocols/ForeignToplevel.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/protocols/ForeignToplevel.cpp b/src/protocols/ForeignToplevel.cpp index 40420da7..f7b3886f 100644 --- a/src/protocols/ForeignToplevel.cpp +++ b/src/protocols/ForeignToplevel.cpp @@ -81,6 +81,7 @@ void CForeignToplevelList::onTitle(PHLWINDOW pWindow) { return; H->resource->sendTitle(pWindow->m_szTitle.c_str()); + H->resource->sendDone(); } void CForeignToplevelList::onClass(PHLWINDOW pWindow) { @@ -92,6 +93,7 @@ void CForeignToplevelList::onClass(PHLWINDOW pWindow) { return; H->resource->sendAppId(pWindow->m_szClass.c_str()); + H->resource->sendDone(); } void CForeignToplevelList::onUnmap(PHLWINDOW pWindow) { From a770a88e0962f37c0b6f36f1876cbf27db4cf3c9 Mon Sep 17 00:00:00 2001 From: David De Sousa Date: Sat, 13 Jul 2024 12:53:53 +0200 Subject: [PATCH 0104/2181] toplevelexport: fix flipped r/b channels when sharing windows (#6861) fixes #6823 --- src/protocols/ToplevelExport.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/protocols/ToplevelExport.cpp b/src/protocols/ToplevelExport.cpp index 287538b5..d4c66c3b 100644 --- a/src/protocols/ToplevelExport.cpp +++ b/src/protocols/ToplevelExport.cpp @@ -409,7 +409,8 @@ bool CToplevelExportProtocolManager::copyFrameShm(SScreencopyFrame* frame, times glPixelStorei(GL_PACK_ALIGNMENT, 1); - glReadPixels(0, 0, frame->box.width, frame->box.height, PFORMAT->glFormat, PFORMAT->glType, pixelData); + auto glFormat = PFORMAT->flipRB ? GL_BGRA_EXT : GL_RGBA; + glReadPixels(0, 0, frame->box.width, frame->box.height, glFormat, PFORMAT->glType, pixelData); if (frame->overlayCursor) { g_pPointerManager->unlockSoftwareForMonitor(PMONITOR->self.lock()); From 45c48984236d7a682a1941b147f8ae489ac9a1e6 Mon Sep 17 00:00:00 2001 From: Tim Waterhouse Date: Sat, 13 Jul 2024 07:21:32 -0700 Subject: [PATCH 0105/2181] socket2: Add windowtitlev2 event which includes the window address (#6856) Fixes #5393 --- src/desktop/Window.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/src/desktop/Window.cpp b/src/desktop/Window.cpp index 2dc5846b..4ea34156 100644 --- a/src/desktop/Window.cpp +++ b/src/desktop/Window.cpp @@ -1343,6 +1343,7 @@ void CWindow::onUpdateMeta() { if (m_szTitle != NEWTITLE) { m_szTitle = NEWTITLE; g_pEventManager->postEvent(SHyprIPCEvent{"windowtitle", std::format("{:x}", (uintptr_t)this)}); + g_pEventManager->postEvent(SHyprIPCEvent{"windowtitlev2", std::format("{:x},{}", (uintptr_t)this, m_szTitle)}); EMIT_HOOK_EVENT("windowTitle", m_pSelf.lock()); if (m_pSelf == g_pCompositor->m_pLastWindow) { // if it's the active, let's post an event to update others From ed6c701144b827869e0c0fca7a7849ec251bf9ef Mon Sep 17 00:00:00 2001 From: MightyPlaza <123664421+MightyPlaza@users.noreply.github.com> Date: Sat, 13 Jul 2024 18:29:07 +0000 Subject: [PATCH 0106/2181] renderer: partially revert previous xray fix (#6868) modified: src/render/OpenGL.cpp --- src/render/OpenGL.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/render/OpenGL.cpp b/src/render/OpenGL.cpp index 2556fafc..cb3d2e71 100644 --- a/src/render/OpenGL.cpp +++ b/src/render/OpenGL.cpp @@ -434,7 +434,7 @@ bool CHyprOpenGLImpl::passRequiresIntrospection(CMonitor* pMonitor) { if (!w->m_bIsFloating && *POPTIM && !w->onSpecialWorkspace()) continue; - if (w->m_sWindowData.noBlur.valueOrDefault() || !w->m_sWindowData.xray.hasValue() || w->m_sWindowData.xray.valueOrDefault()) + if (w->m_sWindowData.noBlur.valueOrDefault() || w->m_sWindowData.xray.valueOrDefault()) continue; if (w->opaque()) From bc6b0880dda2607a80f000c134f573c970452a0f Mon Sep 17 00:00:00 2001 From: Khiet Tam Nguyen <86177399+nktnet1@users.noreply.github.com> Date: Sun, 14 Jul 2024 04:44:32 +1000 Subject: [PATCH 0107/2181] window: override noMaximize if new window takes over fullscreen (#6812) (#6870) --- src/events/Windows.cpp | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/events/Windows.cpp b/src/events/Windows.cpp index 1612deeb..44e8fa02 100644 --- a/src/events/Windows.cpp +++ b/src/events/Windows.cpp @@ -465,9 +465,11 @@ void Events::listener_mapWindow(void* owner, void* data) { PWINDOW->m_bNoInitialFocus = true; else if (*PNEWTAKESOVERFS == 2) g_pCompositor->setWindowFullscreen(g_pCompositor->getFullscreenWindowOnWorkspace(PWINDOW->m_pWorkspace->m_iID), false, FULLSCREEN_INVALID); - else if (PWINDOW->m_pWorkspace->m_efFullscreenMode == FULLSCREEN_MAXIMIZED) + else if (PWINDOW->m_pWorkspace->m_efFullscreenMode == FULLSCREEN_MAXIMIZED) { requestsMaximize = true; - else + if (*PNEWTAKESOVERFS == 1) + overridingNoMaximize = true; + } else requestsFullscreen = true; } From f442f435d34e983768fcc83b54374ac94a7f7658 Mon Sep 17 00:00:00 2001 From: MightyPlaza <123664421+MightyPlaza@users.noreply.github.com> Date: Mon, 15 Jul 2024 09:57:52 +0000 Subject: [PATCH 0108/2181] layout: update workspace rules on layout change (#6878) modified: src/layout/DwindleLayout.cpp modified: src/layout/IHyprLayout.cpp modified: src/layout/MasterLayout.cpp --- src/layout/DwindleLayout.cpp | 3 +++ src/layout/IHyprLayout.cpp | 1 + src/layout/MasterLayout.cpp | 3 +++ 3 files changed, 7 insertions(+) diff --git a/src/layout/DwindleLayout.cpp b/src/layout/DwindleLayout.cpp index d1b4b7ca..7fa6fdbc 100644 --- a/src/layout/DwindleLayout.cpp +++ b/src/layout/DwindleLayout.cpp @@ -140,6 +140,7 @@ void CHyprDwindleLayout::applyNodeDataToWindow(SDwindleNodeData* pNode, bool for return; PWINDOW->unsetWindowData(PRIORITY_LAYOUT); + PWINDOW->updateWindowData(); static auto PNOGAPSWHENONLY = CConfigValue("dwindle:no_gaps_when_only"); static auto PGAPSINDATA = CConfigValue("general:gaps_in"); @@ -497,6 +498,7 @@ void CHyprDwindleLayout::onWindowRemovedTiling(PHLWINDOW pWindow) { } pWindow->unsetWindowData(PRIORITY_LAYOUT); + pWindow->updateWindowData(); if (pWindow->m_bIsFullscreen) g_pCompositor->setWindowFullscreen(pWindow, false, FULLSCREEN_FULL); @@ -831,6 +833,7 @@ void CHyprDwindleLayout::fullscreenRequestForWindow(PHLWINDOW pWindow, eFullscre pWindow->m_vRealSize = pWindow->m_vLastFloatingSize; pWindow->unsetWindowData(PRIORITY_LAYOUT); + pWindow->updateWindowData(); } } else { // if it now got fullscreen, make it fullscreen diff --git a/src/layout/IHyprLayout.cpp b/src/layout/IHyprLayout.cpp index 56d22d4b..528cea72 100644 --- a/src/layout/IHyprLayout.cpp +++ b/src/layout/IHyprLayout.cpp @@ -543,6 +543,7 @@ void IHyprLayout::changeWindowFloatingMode(PHLWINDOW pWindow) { g_pHyprRenderer->damageMonitor(g_pCompositor->getMonitorFromID(pWindow->m_iMonitorID)); pWindow->unsetWindowData(PRIORITY_LAYOUT); + pWindow->updateWindowData(); if (pWindow == m_pLastTiledWindow) m_pLastTiledWindow.reset(); diff --git a/src/layout/MasterLayout.cpp b/src/layout/MasterLayout.cpp index b5f2fa9f..d7f264e7 100644 --- a/src/layout/MasterLayout.cpp +++ b/src/layout/MasterLayout.cpp @@ -265,6 +265,7 @@ void CHyprMasterLayout::onWindowRemovedTiling(PHLWINDOW pWindow) { static auto SMALLSPLIT = CConfigValue("master:allow_small_split"); pWindow->unsetWindowData(PRIORITY_LAYOUT); + pWindow->updateWindowData(); g_pCompositor->setWindowFullscreen(pWindow, false, FULLSCREEN_FULL); @@ -647,6 +648,7 @@ void CHyprMasterLayout::applyNodeDataToWindow(SMasterNodeData* pNode) { return; PWINDOW->unsetWindowData(PRIORITY_LAYOUT); + PWINDOW->updateWindowData(); static auto PNOGAPSWHENONLY = CConfigValue("master:no_gaps_when_only"); static auto PANIMATE = CConfigValue("misc:animate_manual_resizes"); @@ -923,6 +925,7 @@ void CHyprMasterLayout::fullscreenRequestForWindow(PHLWINDOW pWindow, eFullscree pWindow->m_vRealSize = pWindow->m_vLastFloatingSize; pWindow->unsetWindowData(PRIORITY_LAYOUT); + pWindow->updateWindowData(); } } else { // if it now got fullscreen, make it fullscreen From bd526822deb9ed47c0b51b534817aa8541fff07b Mon Sep 17 00:00:00 2001 From: Khiet Tam Nguyen <86177399+nktnet1@users.noreply.github.com> Date: Mon, 15 Jul 2024 21:48:04 +1000 Subject: [PATCH 0109/2181] config: add option to exit window while retaining fullscreen (#516) (#6880) * feat: saving fullscreen mode and state for restoring later * style: no p-prefix, capitalised constants --- src/config/ConfigManager.cpp | 1 + src/events/Windows.cpp | 10 +++++++++- 2 files changed, 10 insertions(+), 1 deletion(-) diff --git a/src/config/ConfigManager.cpp b/src/config/ConfigManager.cpp index 01fac7cf..04d29f3a 100644 --- a/src/config/ConfigManager.cpp +++ b/src/config/ConfigManager.cpp @@ -352,6 +352,7 @@ CConfigManager::CConfigManager() { m_pConfig->addConfigValue("misc:close_special_on_empty", Hyprlang::INT{1}); m_pConfig->addConfigValue("misc:background_color", Hyprlang::INT{0xff111111}); m_pConfig->addConfigValue("misc:new_window_takes_over_fullscreen", Hyprlang::INT{0}); + m_pConfig->addConfigValue("misc:exit_window_retains_fullscreen", Hyprlang::INT{0}); m_pConfig->addConfigValue("misc:initial_workspace_tracking", Hyprlang::INT{1}); m_pConfig->addConfigValue("misc:middle_click_paste", Hyprlang::INT{1}); diff --git a/src/events/Windows.cpp b/src/events/Windows.cpp index 44e8fa02..516ac2ae 100644 --- a/src/events/Windows.cpp +++ b/src/events/Windows.cpp @@ -580,6 +580,11 @@ void Events::listener_unmapWindow(void* owner, void* data) { Debug::log(LOG, "{:c} unmapped", PWINDOW); + static auto PEXITRETAINSFS = CConfigValue("misc:exit_window_retains_fullscreen"); + + const auto CURRENTWINDOWFSSTATE = PWINDOW->m_bIsFullscreen; + const auto CURRENTWINDOWFSMODE = PWINDOW->m_pWorkspace->m_efFullscreenMode; + if (!PWINDOW->m_pWLSurface->exists() || !PWINDOW->m_bIsMapped) { Debug::log(WARN, "{} unmapped without being mapped??", PWINDOW); PWINDOW->m_bFadingOut = false; @@ -638,8 +643,11 @@ void Events::listener_unmapWindow(void* owner, void* data) { Debug::log(LOG, "On closed window, new focused candidate is {}", PWINDOWCANDIDATE); - if (PWINDOWCANDIDATE != g_pCompositor->m_pLastWindow.lock() && PWINDOWCANDIDATE) + if (PWINDOWCANDIDATE != g_pCompositor->m_pLastWindow.lock() && PWINDOWCANDIDATE) { g_pCompositor->focusWindow(PWINDOWCANDIDATE); + if (*PEXITRETAINSFS && CURRENTWINDOWFSSTATE) + g_pCompositor->setWindowFullscreen(PWINDOWCANDIDATE, true, CURRENTWINDOWFSMODE); + } if (!PWINDOWCANDIDATE && g_pCompositor->getWindowsOnWorkspace(PWINDOW->workspaceID()) == 0) g_pInputManager->refocus(); From da956c8a979471282db6790f5fa5dcec320ec226 Mon Sep 17 00:00:00 2001 From: Mihai Fufezan Date: Tue, 16 Jul 2024 22:23:37 +0300 Subject: [PATCH 0110/2181] config: use hyprutils helper (#6891) * flake.lock: update nix/overlays: remove xwayland overlay (merged upstream) * config: use hyprutils helper * flake.lock: update * CMake & Meson: update required versions --- CMakeLists.txt | 2 +- flake.lock | 12 +++---- nix/overlays.nix | 11 ------ src/config/ConfigManager.cpp | 69 ++++++++++++++++++------------------ src/config/ConfigManager.hpp | 18 +++++----- src/meson.build | 4 +-- src/render/OpenGL.cpp | 2 +- 7 files changed, 53 insertions(+), 65 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index d41dd6e5..07fa8cf6 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -113,7 +113,7 @@ pkg_check_modules(deps REQUIRED IMPORTED_TARGET wayland-server wayland-client wayland-cursor wayland-protocols cairo pango pangocairo pixman-1 libdrm libinput hwdata libseat libdisplay-info libliftoff libudev gbm - hyprlang>=0.3.2 hyprcursor>=0.1.7 hyprutils>=0.1.5 + hyprlang>=0.3.2 hyprcursor>=0.1.7 hyprutils>=0.2.0 ) find_package(hyprwayland-scanner 0.3.10 REQUIRED) diff --git a/flake.lock b/flake.lock index 1066e37b..b5f5738a 100644 --- a/flake.lock +++ b/flake.lock @@ -87,11 +87,11 @@ ] }, "locked": { - "lastModified": 1720545076, - "narHash": "sha256-Pxacc2uoxI00koXp5+CyNqHOTQlqNlK0rlRHDBHX4+g=", + "lastModified": 1721071737, + "narHash": "sha256-qmC9jGfbE4+EIBbbSAkrfR/p49wShjpv4/KztgE/P54=", "owner": "hyprwm", "repo": "hyprutils", - "rev": "6174a2a25f4e216c0f1d0c4278adc23c476b1d09", + "rev": "eb1ceff2b87f6820789249f63faa8e9dcb54d05f", "type": "github" }, "original": { @@ -125,11 +125,11 @@ }, "nixpkgs": { "locked": { - "lastModified": 1720542800, - "narHash": "sha256-ZgnNHuKV6h2+fQ5LuqnUaqZey1Lqqt5dTUAiAnqH0QQ=", + "lastModified": 1720957393, + "narHash": "sha256-oedh2RwpjEa+TNxhg5Je9Ch6d3W1NKi7DbRO1ziHemA=", "owner": "NixOS", "repo": "nixpkgs", - "rev": "feb2849fdeb70028c70d73b848214b00d324a497", + "rev": "693bc46d169f5af9c992095736e82c3488bf7dbb", "type": "github" }, "original": { diff --git a/nix/overlays.nix b/nix/overlays.nix index cc66e1b5..a4e1df37 100644 --- a/nix/overlays.nix +++ b/nix/overlays.nix @@ -25,7 +25,6 @@ in { inputs.hyprlang.overlays.default inputs.hyprutils.overlays.default inputs.hyprwayland-scanner.overlays.default - self.overlays.xwayland # Hyprland packages themselves (final: prev: let @@ -63,14 +62,4 @@ in { hyprland-extras = lib.composeManyExtensions [ inputs.xdph.overlays.xdg-desktop-portal-hyprland ]; - - # Patches XWayland's pkgconfig file to not include Cflags or includedir - # The above two variables trip up CMake and the build fails - xwayland = final: prev: { - xwayland = prev.xwayland.overrideAttrs (old: { - postInstall = '' - sed -i '/includedir/d' $out/lib/pkgconfig/xwayland.pc - ''; - }); - }; } diff --git a/src/config/ConfigManager.cpp b/src/config/ConfigManager.cpp index 04d29f3a..944aa0b2 100644 --- a/src/config/ConfigManager.cpp +++ b/src/config/ConfigManager.cpp @@ -8,6 +8,7 @@ #include #include +#include #include #include #include @@ -628,25 +629,49 @@ CConfigManager::CConfigManager() { g_pHyprError->queueCreate(ERR.value(), CColor{1.0, 0.1, 0.1, 1.0}); } -std::string CConfigManager::getConfigDir() { - static const char* xdgConfigHome = getenv("XDG_CONFIG_HOME"); +std::optional CConfigManager::generateConfig(std::string configPath) { + std::string parentPath = std::filesystem::path(configPath).parent_path(); - if (xdgConfigHome && std::filesystem::path(xdgConfigHome).is_absolute()) - return xdgConfigHome; + if (!std::filesystem::is_directory(parentPath)) { + Debug::log(WARN, "Creating config home directory"); + try { + std::filesystem::create_directories(parentPath); + } catch (std::exception e) { throw e; } + } - static const char* home = getenv("HOME"); + Debug::log(WARN, "No config file found; attempting to generate."); + std::ofstream ofs; + ofs.open(configPath, std::ios::trunc); + ofs << AUTOCONFIG; + ofs.close(); - if (!home) - throw std::runtime_error("Neither HOME nor XDG_CONFIG_HOME is set in the environment. Cannot determine config directory."); + if (!std::filesystem::exists(configPath)) + return "Config could not be generated."; - return home + std::string("/.config"); + return configPath; } std::string CConfigManager::getMainConfigPath() { if (!g_pCompositor->explicitConfigPath.empty()) return g_pCompositor->explicitConfigPath; - return getConfigDir() + "/hypr/" + (ISDEBUG ? "hyprlandd.conf" : "hyprland.conf"); + static const auto paths = Hyprutils::Path::findConfig(ISDEBUG ? "hyprlandd" : "hyprland"); + if (paths.first.has_value()) { + return paths.first.value(); + } else if (paths.second.has_value()) { + auto configPath = Hyprutils::Path::fullConfigPath(paths.second.value(), ISDEBUG ? "hyprlandd" : "hyprland"); + return generateConfig(configPath).value(); + } else + throw std::runtime_error("Neither HOME nor XDG_CONFIG_HOME are set in the environment. Could not find config in XDG_CONFIG_DIRS or /etc/xdg."); +} + +std::optional CConfigManager::verifyConfigExists() { + std::string mainConfigPath = getMainConfigPath(); + + if (!std::filesystem::exists(mainConfigPath)) + return "broken config dir?"; + + return {}; } const std::string CConfigManager::getConfigString() { @@ -742,32 +767,6 @@ void CConfigManager::setDefaultAnimationVars() { CREATEANIMCFG("specialWorkspace", "workspaces"); } -std::optional CConfigManager::verifyConfigExists() { - std::string mainConfigPath = getMainConfigPath(); - - if (g_pCompositor->explicitConfigPath.empty() && !std::filesystem::exists(mainConfigPath)) { - std::string configPath = std::filesystem::path(mainConfigPath).parent_path(); - - if (!std::filesystem::is_directory(configPath)) { - Debug::log(WARN, "Creating config home directory"); - try { - std::filesystem::create_directories(configPath); - } catch (...) { return "Broken config file! (Could not create config directory)"; } - } - - Debug::log(WARN, "No config file found; attempting to generate."); - std::ofstream ofs; - ofs.open(mainConfigPath, std::ios::trunc); - ofs << AUTOCONFIG; - ofs.close(); - } - - if (!std::filesystem::exists(mainConfigPath)) - return "broken config dir?"; - - return {}; -} - std::optional CConfigManager::resetHLConfig() { m_dMonitorRules.clear(); m_dWindowRules.clear(); diff --git a/src/config/ConfigManager.hpp b/src/config/ConfigManager.hpp index 10021187..df7c202b 100644 --- a/src/config/ConfigManager.hpp +++ b/src/config/ConfigManager.hpp @@ -101,7 +101,6 @@ class CConfigManager { void* const* getConfigValuePtr(const std::string&); Hyprlang::CConfigValue* getHyprlangConfigValuePtr(const std::string& name, const std::string& specialCat = ""); void onPluginLoadUnload(const std::string& name, bool load); - static std::string getConfigDir(); static std::string getMainConfigPath(); const std::string getConfigString(); @@ -224,14 +223,15 @@ class CConfigManager { std::string m_szConfigErrors = ""; // internal methods - void setAnimForChildren(SAnimationPropertyConfig* const); - void updateBlurredLS(const std::string&, const bool); - void setDefaultAnimationVars(); - std::optional resetHLConfig(); - std::optional verifyConfigExists(); - void postConfigReload(const Hyprlang::CParseResult& result); - void reload(); - SWorkspaceRule mergeWorkspaceRules(const SWorkspaceRule&, const SWorkspaceRule&); + void setAnimForChildren(SAnimationPropertyConfig* const); + void updateBlurredLS(const std::string&, const bool); + void setDefaultAnimationVars(); + std::optional resetHLConfig(); + static std::optional generateConfig(std::string configPath); + static std::optional verifyConfigExists(); + void postConfigReload(const Hyprlang::CParseResult& result); + void reload(); + SWorkspaceRule mergeWorkspaceRules(const SWorkspaceRule&, const SWorkspaceRule&); }; inline std::unique_ptr g_pConfigManager; diff --git a/src/meson.build b/src/meson.build index ccb1922a..f6ae043d 100644 --- a/src/meson.build +++ b/src/meson.build @@ -11,9 +11,9 @@ executable('Hyprland', src, dependency('wayland-client'), wlroots.get_variable('wlroots'), dependency('cairo'), - dependency('hyprcursor'), + dependency('hyprcursor', version: '>=0.1.7'), dependency('hyprlang', version: '>= 0.3.2'), - dependency('hyprutils', version: '>= 0.1.1'), + dependency('hyprutils', version: '>= 0.2.0'), dependency('libdrm'), dependency('egl'), dependency('xkbcommon'), diff --git a/src/render/OpenGL.cpp b/src/render/OpenGL.cpp index cb3d2e71..8229e210 100644 --- a/src/render/OpenGL.cpp +++ b/src/render/OpenGL.cpp @@ -842,7 +842,7 @@ void CHyprOpenGLImpl::applyScreenShader(const std::string& path) { if (path == "" || path == STRVAL_EMPTY) return; - std::ifstream infile(absolutePath(path, g_pConfigManager->getConfigDir())); + std::ifstream infile(absolutePath(path, g_pConfigManager->getMainConfigPath())); if (!infile.good()) { g_pConfigManager->addParseError("Screen shader parser: Screen shader path not found"); From 293e687389a19b369f312c5c335c9afe7c886be1 Mon Sep 17 00:00:00 2001 From: Party Wumpus <48649272+PartyWumpus@users.noreply.github.com> Date: Tue, 16 Jul 2024 21:03:10 +0100 Subject: [PATCH 0111/2181] renderer: Make shader time always count from zero (#6903) * testing out an initialtime variable * Make time universally start at zero instead of exposing an initial time * Appease the CI --- src/render/OpenGL.cpp | 10 ++++++---- src/render/Shader.hpp | 9 +++++---- 2 files changed, 11 insertions(+), 8 deletions(-) diff --git a/src/render/OpenGL.cpp b/src/render/OpenGL.cpp index 8229e210..e127ec2d 100644 --- a/src/render/OpenGL.cpp +++ b/src/render/OpenGL.cpp @@ -858,9 +858,11 @@ void CHyprOpenGLImpl::applyScreenShader(const std::string& path) { return; } - m_sFinalScreenShader.proj = glGetUniformLocation(m_sFinalScreenShader.program, "proj"); - m_sFinalScreenShader.tex = glGetUniformLocation(m_sFinalScreenShader.program, "tex"); - m_sFinalScreenShader.time = glGetUniformLocation(m_sFinalScreenShader.program, "time"); + m_sFinalScreenShader.proj = glGetUniformLocation(m_sFinalScreenShader.program, "proj"); + m_sFinalScreenShader.tex = glGetUniformLocation(m_sFinalScreenShader.program, "tex"); + m_sFinalScreenShader.time = glGetUniformLocation(m_sFinalScreenShader.program, "time"); + if (m_sFinalScreenShader.time != -1) + m_sFinalScreenShader.initialTime = m_tGlobalTimer.getSeconds(); m_sFinalScreenShader.wl_output = glGetUniformLocation(m_sFinalScreenShader.program, "wl_output"); m_sFinalScreenShader.fullSize = glGetUniformLocation(m_sFinalScreenShader.program, "screen_size"); if (m_sFinalScreenShader.fullSize == -1) @@ -1155,7 +1157,7 @@ void CHyprOpenGLImpl::renderTextureInternalWithDamage(SP tex, CBox* pB glUniform1i(shader->tex, 0); if ((usingFinalShader && *PDT == 0) || CRASHING) { - glUniform1f(shader->time, m_tGlobalTimer.getSeconds()); + glUniform1f(shader->time, m_tGlobalTimer.getSeconds() - shader->initialTime); } else if (usingFinalShader && shader->time != -1) { // Don't let time be unitialised glUniform1f(shader->time, 0.f); diff --git a/src/render/Shader.hpp b/src/render/Shader.hpp index 185c3dff..d5a312c3 100644 --- a/src/render/Shader.hpp +++ b/src/render/Shader.hpp @@ -42,9 +42,10 @@ class CShader { GLint gradientLength = -1; GLint angle = -1; - GLint time = -1; - GLint distort = -1; - GLint wl_output = -1; + float initialTime = 0; + GLint time = -1; + GLint distort = -1; + GLint wl_output = -1; // Blur prepare GLint contrast = -1; @@ -64,4 +65,4 @@ class CShader { private: std::unordered_map m_muUniforms; -}; \ No newline at end of file +}; From 300228b503b36e5977b0d58713c5b4cf1f07b8a9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?VESSE=20L=C3=A9o?= Date: Wed, 17 Jul 2024 22:30:02 +0200 Subject: [PATCH 0112/2181] flake: add clang-tools to devShell (#6916) --- flake.nix | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/flake.nix b/flake.nix index c1be8720..88cb593b 100644 --- a/flake.nix +++ b/flake.nix @@ -90,9 +90,13 @@ stdenv = pkgsFor.${system}.gcc13Stdenv; } { name = "hyprland-shell"; - nativeBuildInputs = with pkgsFor.${system}; [expat libxml2]; + nativeBuildInputs = with pkgsFor.${system}; [ + expat + libxml2 + ]; hardeningDisable = ["fortify"]; inputsFrom = [pkgsFor.${system}.hyprland]; + packages = [pkgsFor.${system}.clang-tools]; }; }); From 8e15f91c2417c8f05d69a93f1294185ccc5f8f3e Mon Sep 17 00:00:00 2001 From: Agent00Ming <107314235+Agent00Ming@users.noreply.github.com> Date: Thu, 18 Jul 2024 15:57:08 -0400 Subject: [PATCH 0113/2181] input: Emulate discrete scrolling from v120 events (#6881) * seat: avoid sending axis_stop() when source is wheel * fix rounding for absolute discrete values greater than 1 Co-authored-by: Agent_00Ming --- src/config/ConfigManager.cpp | 1 + src/managers/SeatManager.cpp | 4 +-- src/managers/input/InputManager.cpp | 42 ++++++++++++++++++++++++++--- src/managers/input/InputManager.hpp | 8 ++++++ 4 files changed, 49 insertions(+), 6 deletions(-) diff --git a/src/config/ConfigManager.cpp b/src/config/ConfigManager.cpp index 944aa0b2..71349068 100644 --- a/src/config/ConfigManager.cpp +++ b/src/config/ConfigManager.cpp @@ -472,6 +472,7 @@ CConfigManager::CConfigManager() { m_pConfig->addConfigValue("input:scroll_button_lock", Hyprlang::INT{0}); m_pConfig->addConfigValue("input:scroll_factor", {1.f}); m_pConfig->addConfigValue("input:scroll_points", {STRVAL_EMPTY}); + m_pConfig->addConfigValue("input:emulate_discrete_scroll", Hyprlang::INT{1}); m_pConfig->addConfigValue("input:touchpad:natural_scroll", Hyprlang::INT{0}); m_pConfig->addConfigValue("input:touchpad:disable_while_typing", Hyprlang::INT{1}); m_pConfig->addConfigValue("input:touchpad:clickfinger_behavior", Hyprlang::INT{0}); diff --git a/src/managers/SeatManager.cpp b/src/managers/SeatManager.cpp index fc14f0fc..6589c4bf 100644 --- a/src/managers/SeatManager.cpp +++ b/src/managers/SeatManager.cpp @@ -333,9 +333,7 @@ void CSeatManager::sendPointerAxis(uint32_t timeMs, wl_pointer_axis axis, double if (source == 0) { p->sendAxisValue120(axis, value120); p->sendAxisDiscrete(axis, discrete); - } - - if (value == 0) + } else if (value == 0) p->sendAxisStop(timeMs, axis); } } diff --git a/src/managers/input/InputManager.cpp b/src/managers/input/InputManager.cpp index b2bbd577..23e183d0 100644 --- a/src/managers/input/InputManager.cpp +++ b/src/managers/input/InputManager.cpp @@ -760,6 +760,7 @@ void CInputManager::onMouseWheel(IPointer::SAxisEvent e) { static auto POFFWINDOWAXIS = CConfigValue("input:off_window_axis_events"); static auto PINPUTSCROLLFACTOR = CConfigValue("input:scroll_factor"); static auto PTOUCHPADSCROLLFACTOR = CConfigValue("input:touchpad:scroll_factor"); + static auto PEMULATEDISCRETE = CConfigValue("input:emulate_discrete_scroll"); auto factor = (*PTOUCHPADSCROLLFACTOR <= 0.f || e.source == WL_POINTER_AXIS_SOURCE_FINGER ? *PTOUCHPADSCROLLFACTOR : *PINPUTSCROLLFACTOR); @@ -798,9 +799,44 @@ void CInputManager::onMouseWheel(IPointer::SAxisEvent e) { } } } - double deltaDiscrete = (e.deltaDiscrete != 0) ? (factor * e.deltaDiscrete / std::abs(e.deltaDiscrete)) : 0; - g_pSeatManager->sendPointerAxis(e.timeMs, e.axis, factor * e.delta, deltaDiscrete > 0 ? std::ceil(deltaDiscrete) : std::floor(deltaDiscrete), - std::round(factor * e.deltaDiscrete), e.source, WL_POINTER_AXIS_RELATIVE_DIRECTION_IDENTICAL); + + double discrete = (e.deltaDiscrete != 0) ? (factor * e.deltaDiscrete / std::abs(e.deltaDiscrete)) : 0; + double delta = e.delta * factor; + + if (e.source == 0) { + // if an application supports v120, it should ignore discrete anyways + if ((*PEMULATEDISCRETE >= 1 && std::abs(e.deltaDiscrete) != 120) || *PEMULATEDISCRETE >= 2) { + + const int interval = factor != 0 ? std::round(120 * (1 / factor)) : 120; + + // reset the accumulator when timeout is reached or direction/axis has changed + if (std::signbit(e.deltaDiscrete) != m_ScrollWheelState.lastEventSign || e.axis != m_ScrollWheelState.lastEventAxis || + e.timeMs - m_ScrollWheelState.lastEventTime > 500 /* 500ms taken from libinput default timeout */) { + + m_ScrollWheelState.accumulatedScroll = 0; + // send 1 discrete on first event for responsiveness + discrete = std::copysign(1, e.deltaDiscrete); + } else + discrete = 0; + + for (int ac = m_ScrollWheelState.accumulatedScroll; ac >= interval; ac -= interval) { + discrete += std::copysign(1, e.deltaDiscrete); + m_ScrollWheelState.accumulatedScroll -= interval; + } + + m_ScrollWheelState.lastEventSign = std::signbit(e.deltaDiscrete); + m_ScrollWheelState.lastEventAxis = e.axis; + m_ScrollWheelState.lastEventTime = e.timeMs; + m_ScrollWheelState.accumulatedScroll += std::abs(e.deltaDiscrete); + + delta = 15.0 * discrete * factor; + } + } + + int32_t value120 = std::round(factor * e.deltaDiscrete); + int32_t deltaDiscrete = std::abs(discrete) != 0 && std::abs(discrete) < 1 ? std::copysign(1, discrete) : std::round(discrete); + + g_pSeatManager->sendPointerAxis(e.timeMs, e.axis, delta, deltaDiscrete, value120, e.source, WL_POINTER_AXIS_RELATIVE_DIRECTION_IDENTICAL); } Vector2D CInputManager::getMouseCoordsInternal() { diff --git a/src/managers/input/InputManager.hpp b/src/managers/input/InputManager.hpp index 8050defe..85ae6197 100644 --- a/src/managers/input/InputManager.hpp +++ b/src/managers/input/InputManager.hpp @@ -278,6 +278,14 @@ class CInputManager { void restoreCursorIconToApp(); // no-op if restored + // discrete scrolling emulation using v120 data + struct { + bool lastEventSign = 0; + bool lastEventAxis = 0; + uint32_t lastEventTime = 0; + uint32_t accumulatedScroll = 0; + } m_ScrollWheelState; + friend class CKeybindManager; friend class CWLSurface; }; From efccf25fcc72b416c63ff540703d9f061f39a7f2 Mon Sep 17 00:00:00 2001 From: Ferdinand Bachmann Date: Sat, 20 Jul 2024 00:37:20 +0200 Subject: [PATCH 0114/2181] compositor: implement wayland socket handover (#6930) * compositor: implement wayland socket handover This commit implements the compositor side of the Wayland socket handover protocol as described in the [KDE Wiki]. The CLI options are chosen so that they are compatible with Kwin. [KDE Wiki]: https://invent.kde.org/plasma/kwin/-/wikis/Restarting * main: verify that --wayland-fd is a valid file descriptor * main: fail if only one of --socket and --wayland-fd is passed --- docs/Hyprland.1 | 4 ++++ docs/Hyprland.1.rst | 6 ++++++ src/Compositor.cpp | 30 ++++++++++++++++++++---------- src/Compositor.hpp | 2 +- src/main.cpp | 44 +++++++++++++++++++++++++++++++++++++++++++- 5 files changed, 74 insertions(+), 12 deletions(-) diff --git a/docs/Hyprland.1 b/docs/Hyprland.1 index f43d2c5d..5ef24fd5 100644 --- a/docs/Hyprland.1 +++ b/docs/Hyprland.1 @@ -32,6 +32,10 @@ Show command usage. .TP \f[B]-c\f[R], \f[B]--config\f[R] Specify config file to use. +\f[B]--socket\f[R] +Sets the Wayland socket name (for Wayland socket handover) +\f[B]--wayland-fd\f[R] +Sets the Wayland socket file descriptor (for Wayland socket handover) .SH BUGS .TP Submit bug reports and request features online at: diff --git a/docs/Hyprland.1.rst b/docs/Hyprland.1.rst index 54126501..c73b4343 100644 --- a/docs/Hyprland.1.rst +++ b/docs/Hyprland.1.rst @@ -41,6 +41,12 @@ OPTIONS **-c**, **--config** Specify config file to use. +**--socket** + Sets the Wayland socket name (for Wayland socket handover) + +**--wayland-fd** + Sets the Wayland socket file descriptor (for Wayland socket handover) + BUGS ==== diff --git a/src/Compositor.cpp b/src/Compositor.cpp index d1c51075..7ffccf36 100644 --- a/src/Compositor.cpp +++ b/src/Compositor.cpp @@ -27,6 +27,7 @@ #include using namespace Hyprutils::String; +#include #include #include #include @@ -533,19 +534,28 @@ void CCompositor::prepareFallbackOutput() { wlr_headless_add_output(headless, 1920, 1080); } -void CCompositor::startCompositor() { +void CCompositor::startCompositor(std::string socketName, int socketFd) { initAllSignals(); - // get socket, avoid using 0 - for (int candidate = 1; candidate <= 32; candidate++) { - const auto CANDIDATESTR = ("wayland-" + std::to_string(candidate)); - const auto RETVAL = wl_display_add_socket(m_sWLDisplay, CANDIDATESTR.c_str()); + if (!socketName.empty() && socketFd != -1) { + fcntl(socketFd, F_SETFD, FD_CLOEXEC); + const auto RETVAL = wl_display_add_socket_fd(m_sWLDisplay, socketFd); if (RETVAL >= 0) { - m_szWLDisplaySocket = CANDIDATESTR; - Debug::log(LOG, "wl_display_add_socket for {} succeeded with {}", CANDIDATESTR, RETVAL); - break; - } else { - Debug::log(WARN, "wl_display_add_socket for {} returned {}: skipping candidate {}", CANDIDATESTR, RETVAL, candidate); + m_szWLDisplaySocket = socketName; + Debug::log(LOG, "wl_display_add_socket_fd for {} succeeded with {}", socketName, RETVAL); + } else + Debug::log(WARN, "wl_display_add_socket_fd for {} returned {}: skipping", socketName, RETVAL); + } else { + // get socket, avoid using 0 + for (int candidate = 1; candidate <= 32; candidate++) { + const auto CANDIDATESTR = ("wayland-" + std::to_string(candidate)); + const auto RETVAL = wl_display_add_socket(m_sWLDisplay, CANDIDATESTR.c_str()); + if (RETVAL >= 0) { + m_szWLDisplaySocket = CANDIDATESTR; + Debug::log(LOG, "wl_display_add_socket for {} succeeded with {}", CANDIDATESTR, RETVAL); + break; + } else + Debug::log(WARN, "wl_display_add_socket for {} returned {}: skipping candidate {}", CANDIDATESTR, RETVAL, candidate); } } diff --git a/src/Compositor.hpp b/src/Compositor.hpp index 17db2c8b..4aec323f 100644 --- a/src/Compositor.hpp +++ b/src/Compositor.hpp @@ -78,7 +78,7 @@ class CCompositor { std::unordered_map m_mMonitorIDMap; void initServer(); - void startCompositor(); + void startCompositor(std::string socketName, int socketFd); void cleanup(); void createLockFile(); void removeLockFile(); diff --git a/src/main.cpp b/src/main.cpp index 7e6fee02..1ac3ab8b 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -4,6 +4,7 @@ #include "config/ConfigManager.hpp" #include "init/initHelpers.hpp" +#include #include #include #include @@ -16,6 +17,8 @@ void help() { std::cout << "\nArguments:\n"; std::cout << " --help -h - Show this message again\n"; std::cout << " --config FILE -c FILE - Specify config file to use\n"; + std::cout << " --socket NAME - Sets the Wayland socket name (for Wayland socket handover)\n"; + std::cout << " --wayland-fd FD - Sets the Wayland socket fd (for Wayland socket handover)\n"; std::cout << " --i-am-really-stupid - Omits root user privileges check (why would you do that?)\n"; } @@ -37,6 +40,8 @@ int main(int argc, char** argv) { // parse some args std::string configPath; + std::string socketName; + int socketFd = -1; bool ignoreSudo = false; std::vector args{argv + 1, argv + argc}; @@ -46,6 +51,36 @@ int main(int argc, char** argv) { std::cout << "[ WARNING ] Running Hyprland with superuser privileges might damage your system\n"; ignoreSudo = true; + } else if (it->compare("--socket") == 0) { + if (std::next(it) == args.end()) { + help(); + + return 1; + } + + socketName = *std::next(it); + it++; + } else if (it->compare("--wayland-fd") == 0) { + if (std::next(it) == args.end()) { + help(); + + return 1; + } + + try { + socketFd = std::stoi(std::next(it)->c_str()); + + // check if socketFd is a valid file descriptor + if (fcntl(socketFd, F_GETFD) == -1) + throw std::exception(); + } catch (...) { + std::cerr << "[ ERROR ] Invalid Wayland FD!\n"; + help(); + + return 1; + } + + it++; } else if (it->compare("-c") == 0 || it->compare("--config") == 0) { if (std::next(it) == args.end()) { help(); @@ -93,6 +128,13 @@ int main(int argc, char** argv) { std::cout << "Superuser privileges check is omitted. I hope you know what you're doing.\n"; } + if (socketName.empty() ^ (socketFd == -1)) { + std::cerr << "[ ERROR ] Hyprland was launched with only one of --socket and --wayland-fd.\n"; + std::cerr << " Hint: Pass both --socket and --wayland-fd to perform Wayland socket handover.\n"; + + return 1; + } + std::cout << "Welcome to Hyprland!\n"; // let's init the compositor. @@ -113,7 +155,7 @@ int main(int argc, char** argv) { Debug::log(LOG, "Hyprland init finished."); // If all's good to go, start. - g_pCompositor->startCompositor(); + g_pCompositor->startCompositor(socketName, socketFd); g_pCompositor->m_bIsShuttingDown = true; From 9b0993cc49b7285a2724a87fdb72bfc90cc75cc5 Mon Sep 17 00:00:00 2001 From: vaxerski Date: Fri, 19 Jul 2024 22:37:42 +0000 Subject: [PATCH 0115/2181] [gha] build man pages --- docs/Hyprland.1 | 2 ++ 1 file changed, 2 insertions(+) diff --git a/docs/Hyprland.1 b/docs/Hyprland.1 index 5ef24fd5..92061da2 100644 --- a/docs/Hyprland.1 +++ b/docs/Hyprland.1 @@ -32,8 +32,10 @@ Show command usage. .TP \f[B]-c\f[R], \f[B]--config\f[R] Specify config file to use. +.TP \f[B]--socket\f[R] Sets the Wayland socket name (for Wayland socket handover) +.TP \f[B]--wayland-fd\f[R] Sets the Wayland socket file descriptor (for Wayland socket handover) .SH BUGS From f642fb97df5c69267a03452533de383ff8023570 Mon Sep 17 00:00:00 2001 From: phonetic112 <73647246+phonetic112@users.noreply.github.com> Date: Sat, 20 Jul 2024 04:11:32 -0400 Subject: [PATCH 0116/2181] core: Fix crash on opening chromium (#6932) --- src/protocols/PresentationTime.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/protocols/PresentationTime.cpp b/src/protocols/PresentationTime.cpp index 0275b53f..3907bf1e 100644 --- a/src/protocols/PresentationTime.cpp +++ b/src/protocols/PresentationTime.cpp @@ -60,7 +60,7 @@ void CPresentationFeedback::sendQueued(SP data, timespe if (reportedFlags & WLR_OUTPUT_PRESENT_HW_COMPLETION) flags |= WP_PRESENTATION_FEEDBACK_KIND_HW_COMPLETION; - if (data->wasPresented) + if (data->wasPresented && when) resource->sendPresented((uint32_t)(when->tv_sec >> 32), (uint32_t)(when->tv_sec & 0xFFFFFFFF), (uint32_t)(when->tv_nsec), untilRefreshNs, (uint32_t)(seq >> 32), (uint32_t)(seq & 0xFFFFFFFF), (wpPresentationFeedbackKind)flags); else From 016da234d0e852de3ef20eb2e89ac58d2a85f6e7 Mon Sep 17 00:00:00 2001 From: Vaxry <43317083+vaxerski@users.noreply.github.com> Date: Sun, 21 Jul 2024 13:09:54 +0200 Subject: [PATCH 0117/2181] Core: Move to aquamarine (#6608) Moves Hyprland from wlroots to aquamarine for the backend. --------- Signed-off-by: Vaxry Co-authored-by: Mihai Fufezan Co-authored-by: Jan Beich Co-authored-by: vaxerski Co-authored-by: UjinT34 <41110182+UjinT34@users.noreply.github.com> Co-authored-by: Tom Englund Co-authored-by: Ikalco <73481042+ikalco@users.noreply.github.com> Co-authored-by: diniamo --- .github/actions/setup_base/action.yml | 6 + .gitmodules | 4 - CMakeLists.txt | 42 +- Makefile | 6 +- README.md | 9 +- flake.lock | 30 + flake.nix | 8 + hyprland.pc.in | 2 +- hyprpm/src/core/PluginManager.cpp | 7 +- meson.build | 11 +- nix/default.nix | 3 + nix/overlays.nix | 1 + nix/update-wlroots.sh | 17 - protocols/meson.build | 2 + src/Compositor.cpp | 399 +++++++++---- src/Compositor.hpp | 36 +- src/config/ConfigManager.cpp | 23 +- src/debug/CrashReporter.cpp | 1 + src/debug/HyprCtl.cpp | 183 +++--- src/debug/Log.cpp | 24 - src/debug/Log.hpp | 2 - src/desktop/Popup.cpp | 5 +- src/desktop/Popup.hpp | 4 +- src/desktop/Window.cpp | 3 +- src/devices/IKeyboard.cpp | 256 ++++++++- src/devices/IKeyboard.hpp | 73 ++- src/devices/IPointer.hpp | 10 +- src/devices/ITouch.hpp | 10 +- src/devices/Keyboard.cpp | 66 +-- src/devices/Keyboard.hpp | 22 +- src/devices/Mouse.cpp | 182 +++--- src/devices/Mouse.hpp | 41 +- src/devices/Tablet.cpp | 256 ++++----- src/devices/Tablet.hpp | 154 +++-- src/devices/TouchDevice.cpp | 78 ++- src/devices/TouchDevice.hpp | 26 +- src/devices/VirtualKeyboard.cpp | 63 +- src/devices/VirtualKeyboard.hpp | 21 +- src/devices/VirtualPointer.cpp | 172 +----- src/devices/VirtualPointer.hpp | 37 +- src/events/Devices.cpp | 50 -- src/events/Events.hpp | 31 - src/events/Misc.cpp | 54 -- src/events/Monitors.cpp | 135 +---- src/helpers/CursorShapes.hpp | 43 ++ src/helpers/Format.cpp | 16 + src/helpers/Format.hpp | 9 +- src/helpers/MiscFunctions.cpp | 3 + src/helpers/MiscFunctions.hpp | 1 - src/helpers/Monitor.cpp | 293 ++++++---- src/helpers/Monitor.hpp | 136 +++-- src/helpers/WLClasses.hpp | 14 +- src/helpers/X11Stubs.hpp | 7 - src/helpers/math/Math.cpp | 140 +---- src/helpers/math/Math.hpp | 13 +- src/helpers/sync/SyncTimeline.cpp | 190 +++++++ src/helpers/sync/SyncTimeline.hpp | 47 ++ src/includes.hpp | 76 --- src/macros.hpp | 5 + src/managers/AnimationManager.cpp | 2 +- src/managers/CursorManager.cpp | 327 +++++++---- src/managers/CursorManager.hpp | 70 ++- src/managers/KeybindManager.cpp | 61 +- src/managers/KeybindManager.hpp | 1 + src/managers/PointerManager.cpp | 283 +++------ src/managers/PointerManager.hpp | 50 +- src/managers/ProtocolManager.cpp | 20 + src/managers/SeatManager.cpp | 10 +- src/managers/eventLoop/EventLoopManager.cpp | 15 + src/managers/eventLoop/EventLoopManager.hpp | 16 +- src/managers/input/InputManager.cpp | 232 +++----- src/managers/input/InputManager.hpp | 23 +- src/managers/input/Tablets.cpp | 51 +- src/meson.build | 5 +- src/plugins/PluginAPI.cpp | 1 + src/protocols/CursorShape.cpp | 45 +- src/protocols/DRMLease.cpp | 302 ++++++++++ src/protocols/DRMLease.hpp | 137 +++++ src/protocols/DRMSyncobj.cpp | 183 ++++++ src/protocols/DRMSyncobj.hpp | 82 +++ src/protocols/GammaControl.cpp | 32 +- src/protocols/GammaControl.hpp | 2 +- src/protocols/InputMethodV2.cpp | 22 +- src/protocols/InputMethodV2.hpp | 7 +- src/protocols/LinuxDMABUF.cpp | 323 ++++++++--- src/protocols/LinuxDMABUF.hpp | 52 +- src/protocols/MesaDRM.cpp | 42 +- src/protocols/MesaDRM.hpp | 2 +- src/protocols/OutputManagement.cpp | 56 +- src/protocols/OutputManagement.hpp | 15 +- src/protocols/OutputPower.cpp | 2 +- src/protocols/PresentationTime.cpp | 18 +- src/protocols/Screencopy.cpp | 52 +- src/protocols/Screencopy.hpp | 9 +- src/protocols/Tablet.cpp | 61 +- src/protocols/Tablet.hpp | 5 +- src/protocols/ToplevelExport.cpp | 19 +- src/protocols/ToplevelExport.hpp | 2 +- src/protocols/Viewporter.cpp | 29 +- src/protocols/Viewporter.hpp | 5 +- src/protocols/VirtualKeyboard.cpp | 58 +- src/protocols/VirtualKeyboard.hpp | 13 +- src/protocols/VirtualPointer.cpp | 80 +-- src/protocols/VirtualPointer.hpp | 31 +- src/protocols/XDGOutput.cpp | 6 +- src/protocols/XDGShell.cpp | 1 + src/protocols/core/Compositor.cpp | 149 +++-- src/protocols/core/Compositor.hpp | 14 +- src/protocols/core/Output.cpp | 10 +- src/protocols/core/Output.hpp | 3 + src/protocols/core/Seat.cpp | 4 +- src/protocols/core/Shm.cpp | 27 +- src/protocols/core/Shm.hpp | 8 +- src/protocols/types/Buffer.cpp | 41 +- src/protocols/types/Buffer.hpp | 80 +-- src/protocols/types/DMABuffer.cpp | 12 +- src/protocols/types/DMABuffer.hpp | 12 +- src/protocols/types/WLBuffer.cpp | 15 + src/protocols/types/WLBuffer.hpp | 8 +- src/render/OpenGL.cpp | 487 ++++++++++++---- src/render/OpenGL.hpp | 52 +- src/render/Renderbuffer.cpp | 69 +-- src/render/Renderbuffer.hpp | 31 +- src/render/Renderer.cpp | 599 ++++++++++---------- src/render/Renderer.hpp | 76 +-- src/render/Texture.cpp | 62 +- src/render/Texture.hpp | 15 +- src/signal-safe.hpp | 1 + src/xwayland/Server.cpp | 11 +- src/xwayland/XWM.cpp | 10 +- subprojects/wlroots-hyprland | 1 - 131 files changed, 4755 insertions(+), 3460 deletions(-) delete mode 100755 nix/update-wlroots.sh delete mode 100644 src/events/Devices.cpp delete mode 100644 src/events/Misc.cpp create mode 100644 src/helpers/CursorShapes.hpp delete mode 100644 src/helpers/X11Stubs.hpp create mode 100644 src/helpers/sync/SyncTimeline.cpp create mode 100644 src/helpers/sync/SyncTimeline.hpp create mode 100644 src/protocols/DRMLease.cpp create mode 100644 src/protocols/DRMLease.hpp create mode 100644 src/protocols/DRMSyncobj.cpp create mode 100644 src/protocols/DRMSyncobj.hpp delete mode 160000 subprojects/wlroots-hyprland diff --git a/.github/actions/setup_base/action.yml b/.github/actions/setup_base/action.yml index a7b9994c..26660ce6 100644 --- a/.github/actions/setup_base/action.yml +++ b/.github/actions/setup_base/action.yml @@ -34,6 +34,7 @@ runs: libglvnd \ libinput \ libliftoff \ + libxcursor \ libxcvt \ libxfont2 \ libxkbcommon \ @@ -73,6 +74,11 @@ runs: run: | git clone https://github.com/hyprwm/hyprutils && cd hyprutils && cmake -DCMAKE_BUILD_TYPE:STRING=Release -DCMAKE_INSTALL_PREFIX:PATH=/usr -B build && cmake --build build --target hyprutils && cmake --install build + - name: Get aquamarine-git + shell: bash + run: | + git clone https://github.com/hyprwm/aquamarine && cd aquamarine && cmake -DCMAKE_BUILD_TYPE:STRING=Release -DCMAKE_INSTALL_PREFIX:PATH=/usr -B build && cmake --build build --target aquamarine && cmake --install build + - name: Get Xorg pacman pkgs shell: bash if: inputs.INSTALL_XORG_PKGS == 'true' diff --git a/.gitmodules b/.gitmodules index 37b48a5a..638f8ba9 100644 --- a/.gitmodules +++ b/.gitmodules @@ -7,7 +7,3 @@ [submodule "subprojects/tracy"] path = subprojects/tracy url = https://github.com/wolfpld/tracy -[submodule "subprojects/wlroots-hyprland"] - path = subprojects/wlroots-hyprland - url = https://github.com/hyprwm/wlroots-hyprland - ignore = dirty diff --git a/CMakeLists.txt b/CMakeLists.txt index 07fa8cf6..e951b874 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,7 +1,6 @@ cmake_minimum_required(VERSION 3.27) include(CheckIncludeFile) -include(ExternalProject) include(GNUInstallDirs) # Get version @@ -31,9 +30,6 @@ execute_process( # udis add_subdirectory("subprojects/udis86") -# wlroots -message(STATUS "Setting up wlroots") - if(CMAKE_BUILD_TYPE) string(TOLOWER ${CMAKE_BUILD_TYPE} BUILDTYPE_LOWER) if(BUILDTYPE_LOWER STREQUAL "release") @@ -53,18 +49,6 @@ else() set(BUILDTYPE_LOWER "release") endif() -ExternalProject_Add( - wlroots-hyprland - PREFIX ${CMAKE_SOURCE_DIR}/subprojects/wlroots-hyprland - SOURCE_DIR ${CMAKE_SOURCE_DIR}/subprojects/wlroots-hyprland - CONFIGURE_COMMAND meson setup --reconfigure --clearcache build --buildtype=${BUILDTYPE_LOWER} -Dwerror=false -Dxwayland=$,disabled,enabled> -Dexamples=false -Drenderers=gles2 -Dbackends=drm,libinput $,-Db_sanitize=address,-Db_sanitize=none> - BUILD_COMMAND ninja -C build - BUILD_ALWAYS true - BUILD_IN_SOURCE true - BUILD_BYPRODUCTS ${CMAKE_SOURCE_DIR}/subprojects/wlroots-hyprland/build/libwlroots.a - INSTALL_COMMAND echo "wlroots-hyprland: install not needed" -) - find_package(PkgConfig REQUIRED) pkg_get_variable(WaylandScanner wayland-scanner wayland_scanner) @@ -84,12 +68,9 @@ endif() include_directories( . "src/" - "subprojects/wlroots-hyprland/include/" - "subprojects/wlroots-hyprland/build/include/" "subprojects/udis86/" "protocols/") set(CMAKE_CXX_STANDARD 23) -add_compile_definitions(WLR_USE_UNSTABLE) add_compile_options(-Wall -Wextra -Wno-unused-parameter -Wno-unused-value -Wno-missing-field-initializers -Wno-narrowing -Wno-pointer-arith -fmacro-prefix-map=${CMAKE_SOURCE_DIR}/=) @@ -109,9 +90,10 @@ endif() find_package(OpenGL REQUIRED COMPONENTS ${GLES_VERSION}) pkg_check_modules(deps REQUIRED IMPORTED_TARGET + aquamarine xkbcommon uuid wayland-server wayland-client wayland-cursor wayland-protocols - cairo pango pangocairo pixman-1 + cairo pango pangocairo pixman-1 xcursor libdrm libinput hwdata libseat libdisplay-info libliftoff libudev gbm hyprlang>=0.3.2 hyprcursor>=0.1.7 hyprutils>=0.2.0 ) @@ -127,7 +109,6 @@ if(USE_TRACY) endif() add_executable(Hyprland ${SRCFILES} ${TRACY_CPP_FILES}) -add_dependencies(Hyprland wlroots-hyprland) set(USE_GPROF ON) @@ -266,7 +247,6 @@ function(protocolWayland) endfunction() target_link_libraries(Hyprland - ${CMAKE_SOURCE_DIR}/subprojects/wlroots-hyprland/build/libwlroots.a OpenGL::EGL OpenGL::GL Threads::Threads @@ -314,6 +294,8 @@ protocolNew("unstable/primary-selection" "primary-selection-unstable-v1" false) protocolNew("staging/xwayland-shell" "xwayland-shell-v1" false) protocolNew("stable/viewporter" "viewporter" false) protocolNew("stable/linux-dmabuf" "linux-dmabuf-v1" false) +protocolNew("staging/drm-lease" "drm-lease-v1" false) +protocolNew("staging/linux-drm-syncobj" "linux-drm-syncobj-v1" false) protocolWayland() @@ -326,8 +308,8 @@ install(TARGETS Hyprland) install(CODE "execute_process( \ COMMAND ${CMAKE_COMMAND} -E create_symlink \ - ${CMAKE_INSTALL_BINDIR}/Hyprland \ - ${CMAKE_INSTALL_BINDIR}/hyprland + ${CMAKE_INSTALL_FULL_BINDIR}/Hyprland \ + ${CMAKE_INSTALL_FULL_BINDIR}/hyprland )" ) @@ -358,18 +340,6 @@ install(FILES ${MANPAGES} install(FILES ${CMAKE_BINARY_DIR}/hyprland.pc DESTINATION ${CMAKE_INSTALL_DATAROOTDIR}/pkgconfig) -# wlroots headers -set(HEADERS_WLR "${CMAKE_CURRENT_SOURCE_DIR}/subprojects/wlroots-hyprland/include/wlr") -install(DIRECTORY ${HEADERS_WLR} - DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/hyprland - FILES_MATCHING PATTERN "*.h") - -# config.h and version.h -set(HEADERS_WLR_ROOT "${CMAKE_CURRENT_SOURCE_DIR}/subprojects/wlroots-hyprland/build/include/wlr") -install(DIRECTORY ${HEADERS_WLR_ROOT}/ - DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/hyprland/wlr - FILES_MATCHING PATTERN "*.h") - # protocol headers set(HEADERS_PROTO "${CMAKE_CURRENT_SOURCE_DIR}/protocols") install(DIRECTORY ${HEADERS_PROTO} diff --git a/Makefile b/Makefile index 493a6784..adf6fbe8 100644 --- a/Makefile +++ b/Makefile @@ -27,7 +27,6 @@ nopch: clear: rm -rf build rm -f ./protocols/*.h ./protocols/*.c ./protocols/*.cpp ./protocols/*.hpp - rm -rf ./subprojects/wlroots-hyprland/build all: $(MAKE) clear @@ -50,14 +49,11 @@ installheaders: rm -fr ${PREFIX}/include/hyprland mkdir -p ${PREFIX}/include/hyprland mkdir -p ${PREFIX}/include/hyprland/protocols - mkdir -p ${PREFIX}/include/hyprland/wlr mkdir -p ${PREFIX}/share/pkgconfig cmake --build ./build --config Release --target generate-protocol-headers find src -name '*.h*' -print0 | cpio --quiet -0dump ${PREFIX}/include/hyprland - cd subprojects/wlroots-hyprland/include/wlr && find . -name '*.h*' -print0 | cpio --quiet -0dump ${PREFIX}/include/hyprland/wlr && cd ../../../.. - cd subprojects/wlroots-hyprland/build/include && find . -name '*.h*' -print0 | cpio --quiet -0dump ${PREFIX}/include/hyprland/wlr && cd ../../../.. cp ./protocols/*.h* ${PREFIX}/include/hyprland/protocols cp ./build/hyprland.pc ${PREFIX}/share/pkgconfig if [ -d /usr/share/pkgconfig ]; then cp ./build/hyprland.pc /usr/share/pkgconfig 2>/dev/null || true; fi @@ -88,7 +84,7 @@ asan: @pidof Hyprland > /dev/null && exit 1 || echo "" rm -rf ./wayland - git reset --hard + #git reset --hard @echo -en "If you want to apply a patch, input its path (leave empty for none):\n" @read patchvar diff --git a/README.md b/README.md index ca44621d..fc2bd206 100644 --- a/README.md +++ b/README.md @@ -13,10 +13,10 @@
-Hyprland is a dynamic tiling Wayland compositor based on wlroots that doesn't sacrifice on its looks. +Hyprland is a 100% independent, dynamic tiling Wayland compositor that doesn't sacrifice on its looks. It provides the latest Wayland features, is highly customizable, has all the eyecandy, the most powerful plugins, -easy IPC, much more QoL stuff than other wlr-based compositors and more... +easy IPC, much more QoL stuff than other compositors and more...

@@ -37,7 +37,7 @@ easy IPC, much more QoL stuff than other wlr-based compositors and more... - All of the eyecandy: gradient borders, blur, animations, shadows and much more - A lot of customization -- Much more QoL stuff than other wlr-based compositors +- 100% independent, no wlroots, no libweston, no kwin, no mutter. - Custom bezier curves for the best animations - Powerful plugin support - Built-in plugin manager @@ -48,7 +48,6 @@ easy IPC, much more QoL stuff than other wlr-based compositors and more... - Config reloaded instantly upon saving - Fully dynamic workspaces - Two built-in layouts and more available as plugins -- Uses forked wlroots with QoL patches - Global keybinds passed to your apps of choice - Tiling/pseudotiling/floating/fullscreen windows - Special workspaces (scratchpads) @@ -86,7 +85,7 @@ easy IPC, much more QoL stuff than other wlr-based compositors and more...
-**[wlroots]** - *For their amazing library* +**[wlroots]** - *For powering Hyprland in the past* **[tinywl]** - *For showing how 2 do stuff* diff --git a/flake.lock b/flake.lock index b5f5738a..b2cc9703 100644 --- a/flake.lock +++ b/flake.lock @@ -1,5 +1,34 @@ { "nodes": { + "aquamarine": { + "inputs": { + "hyprutils": [ + "hyprutils" + ], + "hyprwayland-scanner": [ + "hyprwayland-scanner" + ], + "nixpkgs": [ + "nixpkgs" + ], + "systems": [ + "systems" + ] + }, + "locked": { + "lastModified": 1721487522, + "narHash": "sha256-aF3uwUwUK2CgbItoMe3IJF0yidIEWcDx47AiH5y8VKk=", + "owner": "hyprwm", + "repo": "aquamarine", + "rev": "acfea3bd1d9e756c7152e639240d52c6628844b0", + "type": "github" + }, + "original": { + "owner": "hyprwm", + "repo": "aquamarine", + "type": "github" + } + }, "hyprcursor": { "inputs": { "hyprlang": [ @@ -141,6 +170,7 @@ }, "root": { "inputs": { + "aquamarine": "aquamarine", "hyprcursor": "hyprcursor", "hyprlang": "hyprlang", "hyprutils": "hyprutils", diff --git a/flake.nix b/flake.nix index 88cb593b..9c20b3f5 100644 --- a/flake.nix +++ b/flake.nix @@ -7,6 +7,14 @@ # systems.url = "github:nix-systems/default-linux"; + aquamarine = { + url = "github:hyprwm/aquamarine"; + inputs.nixpkgs.follows = "nixpkgs"; + inputs.systems.follows = "systems"; + inputs.hyprutils.follows = "hyprutils"; + inputs.hyprwayland-scanner.follows = "hyprwayland-scanner"; + }; + hyprcursor = { url = "github:hyprwm/hyprcursor"; inputs.nixpkgs.follows = "nixpkgs"; diff --git a/hyprland.pc.in b/hyprland.pc.in index 382fb1e6..81a0ef11 100644 --- a/hyprland.pc.in +++ b/hyprland.pc.in @@ -4,4 +4,4 @@ Name: Hyprland URL: https://github.com/hyprwm/Hyprland Description: Hyprland header files Version: @HYPRLAND_VERSION@ -Cflags: -I${prefix} -I${prefix}/hyprland/protocols -I${prefix}/hyprland -I${prefix}/hyprland/wlr +Cflags: -I${prefix} -I${prefix}/hyprland/protocols -I${prefix}/hyprland diff --git a/hyprpm/src/core/PluginManager.cpp b/hyprpm/src/core/PluginManager.cpp index 848b9cab..7d7cc079 100644 --- a/hyprpm/src/core/PluginManager.cpp +++ b/hyprpm/src/core/PluginManager.cpp @@ -356,7 +356,7 @@ eHeadersErrors CPluginManager::headersValid() { else headers = ""; - if (PATH.ends_with("protocols") || PATH.ends_with("wlroots-hyprland")) + if (PATH.ends_with("protocols")) continue; verHeader = trim(PATH.substr(2)) + "/hyprland/src/version.h"; @@ -493,11 +493,6 @@ bool CPluginManager::updateHeaders(bool force) { return false; } - // le hack. Wlroots has to generate its build/include - ret = execAndGet("cd " + WORKINGDIR + "/subprojects/wlroots-hyprland && meson setup -Drenderers=gles2 -Dexamples=false build"); - if (m_bVerbose) - progress.printMessageAbove(std::string{Colors::BLUE} + "[v] " + Colors::RESET + "meson returned: " + ret); - progress.printMessageAbove(std::string{Colors::GREEN} + "✔" + Colors::RESET + " configured Hyprland"); progress.m_iSteps = 4; progress.m_szCurrentMessage = "Installing sources"; diff --git a/meson.build b/meson.build index 49c48c6c..b8101f6c 100644 --- a/meson.build +++ b/meson.build @@ -24,8 +24,6 @@ if cpp_compiler.check_header('execinfo.h') add_project_arguments('-DHAS_EXECINFO', language: 'cpp') endif -wlroots = subproject('wlroots-hyprland', default_options: ['examples=false', 'renderers=gles2']) -have_xwlr = wlroots.get_variable('features').get('xwayland') xcb_dep = dependency('xcb', required: get_option('xwayland')) xcb_composite_dep = dependency('xcb-composite', required: get_option('xwayland')) xcb_errors_dep = dependency('xcb-errors', required: get_option('xwayland')) @@ -38,12 +36,7 @@ cmake = import('cmake') udis = cmake.subproject('udis86') udis86 = udis.dependency('libudis86') -if get_option('xwayland').enabled() and not have_xwlr - error('Cannot enable Xwayland in Hyprland: wlroots has been built without Xwayland support') -endif -have_xwayland = xcb_dep.found() and have_xwlr - -if not have_xwayland +if not xcb_dep.found() add_project_arguments('-DNO_XWAYLAND', language: 'cpp') endif @@ -86,5 +79,5 @@ import('pkgconfig').generate( url: 'https://github.com/hyprwm/Hyprland', description: 'Hyprland header files', install_dir: pkg_install_dir, - subdirs: ['', 'hyprland/protocols', 'hyprland', 'hyprland/wlr'], + subdirs: ['', 'hyprland/protocols', 'hyprland'], ) diff --git a/nix/default.nix b/nix/default.nix index a2302688..7775b729 100644 --- a/nix/default.nix +++ b/nix/default.nix @@ -6,6 +6,7 @@ makeWrapper, cmake, ninja, + aquamarine, binutils, cairo, expat, @@ -104,6 +105,7 @@ assert lib.assertMsg (!hidpiXWayland) "The option `hidpiXWayland` has been remov buildInputs = lib.concatLists [ [ + aquamarine cairo expat fribidi @@ -136,6 +138,7 @@ assert lib.assertMsg (!hidpiXWayland) "The option `hidpiXWayland` has been remov (lib.optionals stdenv.hostPlatform.isMusl [libexecinfo]) (lib.optionals enableXWayland [ xorg.libxcb + xorg.libXcursor xorg.libXdmcp xorg.xcbutil xorg.xcbutilerrors diff --git a/nix/overlays.nix b/nix/overlays.nix index a4e1df37..9d100d51 100644 --- a/nix/overlays.nix +++ b/nix/overlays.nix @@ -21,6 +21,7 @@ in { # Packages for variations of Hyprland, dependencies included. hyprland-packages = lib.composeManyExtensions [ # Dependencies + inputs.aquamarine.overlays.default inputs.hyprcursor.overlays.default inputs.hyprlang.overlays.default inputs.hyprutils.overlays.default diff --git a/nix/update-wlroots.sh b/nix/update-wlroots.sh deleted file mode 100755 index 01f5cd83..00000000 --- a/nix/update-wlroots.sh +++ /dev/null @@ -1,17 +0,0 @@ -#!/usr/bin/env -S nix shell nixpkgs#gawk nixpkgs#git nixpkgs#gnused nixpkgs#ripgrep -c bash - -# get wlroots revision from submodule -SUB_REV=$(git submodule status | rg wlroots | awk '{ print substr($1,2) }') -# and from lockfile -CRT_REV=$(rg rev flake.nix | awk '{ print substr($3, 2, 40) }') - -if [ "$SUB_REV" != "$CRT_REV" ]; then - echo "Updating wlroots..." - # update wlroots to submodule revision - sed -Ei "s/\w{40}/$SUB_REV/g" flake.nix - nix flake lock - - echo "wlroots: $CRT_REV -> $SUB_REV" -else - echo "wlroots is up to date!" -fi diff --git a/protocols/meson.build b/protocols/meson.build index 7c508659..5cdeb160 100644 --- a/protocols/meson.build +++ b/protocols/meson.build @@ -66,6 +66,8 @@ new_protocols = [ [wl_protocol_dir, 'staging/xwayland-shell/xwayland-shell-v1.xml'], [wl_protocol_dir, 'stable/viewporter/viewporter.xml'], [wl_protocol_dir, 'stable/linux-dmabuf/linux-dmabuf-v1.xml'], + [wl_protocol_dir, 'staging/drm-lease/drm-lease-v1.xml'], + [wl_protocol_dir, 'staging/linux-drm-syncobj/linux-drm-syncobj-v1.xml'], ] wl_protos_src = [] diff --git a/src/Compositor.cpp b/src/Compositor.cpp index 7ffccf36..c7a0cfb1 100644 --- a/src/Compositor.cpp +++ b/src/Compositor.cpp @@ -6,7 +6,10 @@ #include "managers/PointerManager.hpp" #include "managers/SeatManager.hpp" #include "managers/eventLoop/EventLoopManager.hpp" +#include #include +#include +#include #include #include "debug/HyprCtl.hpp" #include "debug/CrashReporter.hpp" @@ -22,16 +25,20 @@ #include "protocols/core/Compositor.hpp" #include "protocols/core/Subcompositor.hpp" #include "desktop/LayerSurface.hpp" +#include "render/Renderer.hpp" #include "xwayland/XWayland.hpp" #include -using namespace Hyprutils::String; +#include #include #include #include #include +using namespace Hyprutils::String; +using namespace Aquamarine; + int handleCritSignal(int signo, void* data) { Debug::log(LOG, "Hyprland received signal {}", signo); @@ -72,6 +79,23 @@ void handleUserSignal(int sig) { } } +static LogLevel aqLevelToHl(Aquamarine::eBackendLogLevel level) { + switch (level) { + case Aquamarine::eBackendLogLevel::AQ_LOG_TRACE: return TRACE; + case Aquamarine::eBackendLogLevel::AQ_LOG_DEBUG: return LOG; + case Aquamarine::eBackendLogLevel::AQ_LOG_ERROR: return ERR; + case Aquamarine::eBackendLogLevel::AQ_LOG_WARNING: return WARN; + case Aquamarine::eBackendLogLevel::AQ_LOG_CRITICAL: return CRIT; + default: break; + } + + return NONE; +} + +void aqLog(Aquamarine::eBackendLogLevel level, std::string msg) { + Debug::log(aqLevelToHl(level), "[AQ] {}", msg); +} + void CCompositor::bumpNofile() { if (!getrlimit(RLIMIT_NOFILE, &m_sOriginalNofile)) Debug::log(LOG, "Old rlimit: soft -> {}, hard -> {}", m_sOriginalNofile.rlim_cur, m_sOriginalNofile.rlim_max); @@ -180,6 +204,9 @@ void CCompositor::setRandomSplash() { m_szCurrentSplash = SPLASHES[distribution(engine)]; } +static std::vector> pendingOutputs; + +// void CCompositor::initServer() { m_sWLDisplay = wl_display_create(); @@ -200,102 +227,179 @@ void CCompositor::initServer() { if (envEnabled("HYPRLAND_TRACE")) Debug::trace = true; - wlr_log_init(WLR_INFO, NULL); + Aquamarine::SBackendOptions options; + options.logFunction = aqLog; - if (envEnabled("HYPRLAND_LOG_WLR")) - wlr_log_init(WLR_DEBUG, Debug::wlrLog); - else - wlr_log_init(WLR_ERROR, Debug::wlrLog); + std::vector implementations; + Aquamarine::SBackendImplementationOptions option; + option.backendType = Aquamarine::eBackendType::AQ_BACKEND_HEADLESS; + option.backendRequestMode = Aquamarine::eBackendRequestMode::AQ_BACKEND_REQUEST_MANDATORY; + implementations.emplace_back(option); + option.backendType = Aquamarine::eBackendType::AQ_BACKEND_DRM; + option.backendRequestMode = Aquamarine::eBackendRequestMode::AQ_BACKEND_REQUEST_IF_AVAILABLE; + implementations.emplace_back(option); + option.backendType = Aquamarine::eBackendType::AQ_BACKEND_WAYLAND; + option.backendRequestMode = Aquamarine::eBackendRequestMode::AQ_BACKEND_REQUEST_FALLBACK; + implementations.emplace_back(option); - m_sWLRBackend = wlr_backend_autocreate(m_sWLEventLoop, &m_sWLRSession); + m_pAqBackend = CBackend::create(implementations, options); - if (!m_sWLRBackend) { - Debug::log(CRIT, "m_sWLRBackend was NULL! This usually means wlroots could not find a GPU or enountered some issues."); - throwError("wlr_backend_autocreate() failed!"); + if (!m_pAqBackend) { + Debug::log(CRIT, + "m_pAqBackend was null! This usually means aquamarine could not find a GPU or enountered some issues. Make sure you're running either on a tty or on a Wayland " + "session, NOT an X11 one."); + throwError("CBackend::create() failed!"); } - bool isHeadlessOnly = true; - wlr_multi_for_each_backend( - m_sWLRBackend, - [](wlr_backend* backend, void* isHeadlessOnly) { - if (!wlr_backend_is_headless(backend) && !wlr_backend_is_libinput(backend)) - *(bool*)isHeadlessOnly = false; - }, - &isHeadlessOnly); + // TODO: headless only - if (isHeadlessOnly) { - m_sWLRRenderer = wlr_renderer_autocreate(m_sWLRBackend); // TODO: remove this, it's barely needed now. - } else { - m_iDRMFD = wlr_backend_get_drm_fd(m_sWLRBackend); - if (m_iDRMFD < 0) { - Debug::log(CRIT, "Couldn't query the DRM FD!"); - throwError("wlr_backend_get_drm_fd() failed!"); + initAllSignals(); + + if (!m_pAqBackend->start()) { + Debug::log(CRIT, + "m_pAqBackend couldn't start! This usually means aquamarine could not find a GPU or enountered some issues. Make sure you're running either on a tty or on a " + "Wayland session, NOT an X11 one."); + throwError("CBackend::create() failed!"); + } + + m_bInitialized = true; + + m_iDRMFD = m_pAqBackend->drmFD(); + Debug::log(LOG, "Running on DRMFD: {}", m_iDRMFD); + + // get socket, avoid using 0 + for (int candidate = 1; candidate <= 32; candidate++) { + const auto CANDIDATESTR = ("wayland-" + std::to_string(candidate)); + const auto RETVAL = wl_display_add_socket(m_sWLDisplay, CANDIDATESTR.c_str()); + if (RETVAL >= 0) { + m_szWLDisplaySocket = CANDIDATESTR; + Debug::log(LOG, "wl_display_add_socket for {} succeeded with {}", CANDIDATESTR, RETVAL); + break; + } else { + Debug::log(WARN, "wl_display_add_socket for {} returned {}: skipping candidate {}", CANDIDATESTR, RETVAL, candidate); } - - m_sWLRRenderer = wlr_gles2_renderer_create_with_drm_fd(m_iDRMFD); } - if (!m_sWLRRenderer) { - Debug::log(CRIT, "m_sWLRRenderer was NULL! This usually means wlroots could not find a GPU or enountered some issues."); - throwError("wlr_gles2_renderer_create_with_drm_fd() failed!"); + if (m_szWLDisplaySocket.empty()) { + Debug::log(WARN, "All candidates failed, trying wl_display_add_socket_auto"); + const auto SOCKETSTR = wl_display_add_socket_auto(m_sWLDisplay); + if (SOCKETSTR) + m_szWLDisplaySocket = SOCKETSTR; } - m_sWLRAllocator = wlr_allocator_autocreate(m_sWLRBackend, m_sWLRRenderer); - - if (!m_sWLRAllocator) { - Debug::log(CRIT, "m_sWLRAllocator was NULL!"); - throwError("wlr_allocator_autocreate() failed!"); + if (m_szWLDisplaySocket.empty()) { + Debug::log(CRIT, "m_szWLDisplaySocket NULL!"); + throwError("m_szWLDisplaySocket was null! (wl_display_add_socket and wl_display_add_socket_auto failed)"); } - m_sWLREGL = wlr_gles2_renderer_get_egl(m_sWLRRenderer); - - if (!m_sWLREGL) { - Debug::log(CRIT, "m_sWLREGL was NULL!"); - throwError("wlr_gles2_renderer_get_egl() failed!"); - } + Debug::log(LOG, "Setting WAYLAND_DISPLAY to {}", m_szWLDisplaySocket); + setenv("WAYLAND_DISPLAY", m_szWLDisplaySocket.c_str(), 1); + setenv("XDG_SESSION_TYPE", "wayland", 1); initManagers(STAGE_BASICINIT); - m_sWRLDRMLeaseMgr = wlr_drm_lease_v1_manager_create(m_sWLDisplay, m_sWLRBackend); - if (!m_sWRLDRMLeaseMgr) { - Debug::log(INFO, "Failed to create wlr_drm_lease_v1_manager"); - Debug::log(INFO, "VR will not be available"); - } - - m_sWLRHeadlessBackend = wlr_headless_backend_create(m_sWLEventLoop); - - if (!m_sWLRHeadlessBackend) { - Debug::log(CRIT, "Couldn't create the headless backend"); - throwError("wlr_headless_backend_create() failed!"); - } - - wlr_multi_backend_add(m_sWLRBackend, m_sWLRHeadlessBackend); - initManagers(STAGE_LATE); + + for (auto& o : pendingOutputs) { + onNewMonitor(o); + } + pendingOutputs.clear(); } void CCompositor::initAllSignals() { - addWLSignal(&m_sWLRBackend->events.new_output, &Events::listen_newOutput, m_sWLRBackend, "Backend"); - addWLSignal(&m_sWLRBackend->events.new_input, &Events::listen_newInput, m_sWLRBackend, "Backend"); - addWLSignal(&m_sWLRRenderer->events.destroy, &Events::listen_RendererDestroy, m_sWLRRenderer, "WLRRenderer"); + m_pAqBackend->events.newOutput.registerStaticListener( + [this](void* p, std::any data) { + auto output = std::any_cast>(data); + Debug::log(LOG, "New aquamarine output with name {}", output->name); + if (m_bInitialized) + onNewMonitor(output); + else + pendingOutputs.emplace_back(output); + }, + nullptr); - if (m_sWRLDRMLeaseMgr) - addWLSignal(&m_sWRLDRMLeaseMgr->events.request, &Events::listen_leaseRequest, &m_sWRLDRMLeaseMgr, "DRM"); + m_pAqBackend->events.newPointer.registerStaticListener( + [](void* data, std::any d) { + auto dev = std::any_cast>(d); + Debug::log(LOG, "New aquamarine pointer with name {}", dev->getName()); + g_pInputManager->newMouse(dev); + g_pInputManager->updateCapabilities(); + }, + nullptr); - if (m_sWLRSession) - addWLSignal(&m_sWLRSession->events.active, &Events::listen_sessionActive, m_sWLRSession, "Session"); + m_pAqBackend->events.newKeyboard.registerStaticListener( + [](void* data, std::any d) { + auto dev = std::any_cast>(d); + Debug::log(LOG, "New aquamarine keyboard with name {}", dev->getName()); + g_pInputManager->newKeyboard(dev); + g_pInputManager->updateCapabilities(); + }, + nullptr); + + m_pAqBackend->events.newTouch.registerStaticListener( + [](void* data, std::any d) { + auto dev = std::any_cast>(d); + Debug::log(LOG, "New aquamarine touch with name {}", dev->getName()); + g_pInputManager->newTouchDevice(dev); + g_pInputManager->updateCapabilities(); + }, + nullptr); + + m_pAqBackend->events.newSwitch.registerStaticListener( + [](void* data, std::any d) { + auto dev = std::any_cast>(d); + Debug::log(LOG, "New aquamarine switch with name {}", dev->getName()); + g_pInputManager->newSwitch(dev); + }, + nullptr); + + m_pAqBackend->events.newTablet.registerStaticListener( + [](void* data, std::any d) { + auto dev = std::any_cast>(d); + Debug::log(LOG, "New aquamarine tablet with name {}", dev->getName()); + g_pInputManager->newTablet(dev); + }, + nullptr); + + m_pAqBackend->events.newTabletPad.registerStaticListener( + [](void* data, std::any d) { + auto dev = std::any_cast>(d); + Debug::log(LOG, "New aquamarine tablet pad with name {}", dev->getName()); + g_pInputManager->newTabletPad(dev); + }, + nullptr); + + if (m_pAqBackend->hasSession()) { + m_pAqBackend->session->events.changeActive.registerStaticListener( + [this](void*, std::any) { + if (m_pAqBackend->session->active) { + Debug::log(LOG, "Session got activated!"); + + m_bSessionActive = true; + + for (auto& m : m_vMonitors) { + scheduleFrameForMonitor(m.get()); + g_pHyprRenderer->applyMonitorRule(m.get(), &m->activeMonitorRule, true); + } + + g_pConfigManager->m_bWantsMonitorReload = true; + } else { + Debug::log(LOG, "Session got deactivated!"); + + m_bSessionActive = false; + + for (auto& m : m_vMonitors) { + m->noFrameSchedule = true; + m->framesToSkip = 1; + } + } + }, + nullptr); + } } void CCompositor::removeAllSignals() { - removeWLSignal(&Events::listen_newOutput); - removeWLSignal(&Events::listen_newInput); - removeWLSignal(&Events::listen_RendererDestroy); - - if (m_sWRLDRMLeaseMgr) - removeWLSignal(&Events::listen_leaseRequest); - - if (m_sWLRSession) - removeWLSignal(&Events::listen_sessionActive); + ; } void CCompositor::cleanEnvironment() { @@ -309,7 +413,7 @@ void CCompositor::cleanEnvironment() { unsetenv("XDG_BACKEND"); unsetenv("XDG_CURRENT_DESKTOP"); - if (m_sWLRSession) { + if (m_pAqBackend->hasSession()) { const auto CMD = #ifdef USES_SYSTEMD "systemctl --user unset-environment DISPLAY WAYLAND_DISPLAY HYPRLAND_INSTANCE_SIGNATURE XDG_CURRENT_DESKTOP QT_QPA_PLATFORMTHEME PATH XDG_DATA_DIRS && hash " @@ -352,7 +456,7 @@ void CCompositor::cleanup() { for (auto& m : m_vMonitors) { g_pHyprOpenGL->destroyMonitorResources(m.get()); - wlr_output_state_set_enabled(m->state.wlr(), false); + m->output->state->setEnabled(false); m->state.commit(); } @@ -389,14 +493,8 @@ void CCompositor::cleanup() { g_pHyprCtl.reset(); g_pEventLoopManager.reset(); - if (m_sWLRRenderer) - wlr_renderer_destroy(m_sWLRRenderer); - - if (m_sWLRAllocator) - wlr_allocator_destroy(m_sWLRAllocator); - - if (m_sWLRBackend) - wlr_backend_destroy(m_sWLRBackend); + if (m_pAqBackend) + m_pAqBackend.reset(); if (m_critSigSource) wl_event_source_remove(m_critSigSource); @@ -442,6 +540,9 @@ void CCompositor::initManagers(eManagersInitStage stage) { Debug::log(LOG, "Creating the PointerManager!"); g_pPointerManager = std::make_unique(); + + Debug::log(LOG, "Creating the EventManager!"); + g_pEventManager = std::make_unique(); } break; case STAGE_BASICINIT: { Debug::log(LOG, "Creating the CHyprOpenGLImpl!"); @@ -472,9 +573,6 @@ void CCompositor::initManagers(eManagersInitStage stage) { Debug::log(LOG, "Creating the SessionLockManager!"); g_pSessionLockManager = std::make_unique(); - Debug::log(LOG, "Creating the EventManager!"); - g_pEventManager = std::make_unique(); - Debug::log(LOG, "Creating the HyprDebugOverlay!"); g_pDebugOverlay = std::make_unique(); @@ -517,26 +615,23 @@ void CCompositor::removeLockFile() { void CCompositor::prepareFallbackOutput() { // create a backup monitor - wlr_backend* headless = nullptr; - wlr_multi_for_each_backend( - m_sWLRBackend, - [](wlr_backend* b, void* data) { - if (wlr_backend_is_headless(b)) - *((wlr_backend**)data) = b; - }, - &headless); + SP headless; + for (auto& impl : m_pAqBackend->getImplementations()) { + if (impl->type() == Aquamarine::AQ_BACKEND_HEADLESS) { + headless = impl; + break; + } + } if (!headless) { - Debug::log(WARN, "Unsafe state will be ineffective, no fallback output"); + Debug::log(WARN, "No headless in prepareFallbackOutput?!"); return; } - wlr_headless_add_output(headless, 1920, 1080); + headless->createOutput(); } void CCompositor::startCompositor(std::string socketName, int socketFd) { - initAllSignals(); - if (!socketName.empty() && socketFd != -1) { fcntl(socketFd, F_SETFD, FD_CLOEXEC); const auto RETVAL = wl_display_add_socket_fd(m_sWLDisplay, socketFd); @@ -568,15 +663,15 @@ void CCompositor::startCompositor(std::string socketName, int socketFd) { if (m_szWLDisplaySocket.empty()) { Debug::log(CRIT, "m_szWLDisplaySocket NULL!"); - wlr_backend_destroy(m_sWLRBackend); throwError("m_szWLDisplaySocket was null! (wl_display_add_socket and wl_display_add_socket_auto failed)"); } setenv("WAYLAND_DISPLAY", m_szWLDisplaySocket.c_str(), 1); + setenv("XDG_SESSION_TYPE", "wayland", 1); signal(SIGPIPE, SIG_IGN); - if (m_sWLRSession /* Session-less Hyprland usually means a nest, don't update the env in that case */) { + if (m_pAqBackend->hasSession() /* Session-less Hyprland usually means a nest, don't update the env in that case */) { const auto CMD = #ifdef USES_SYSTEMD "systemctl --user import-environment DISPLAY WAYLAND_DISPLAY HYPRLAND_INSTANCE_SIGNATURE XDG_CURRENT_DESKTOP QT_QPA_PLATFORMTHEME PATH XDG_DATA_DIRS && hash " @@ -588,13 +683,6 @@ void CCompositor::startCompositor(std::string socketName, int socketFd) { Debug::log(LOG, "Running on WAYLAND_DISPLAY: {}", m_szWLDisplaySocket); - if (!wlr_backend_start(m_sWLRBackend)) { - Debug::log(CRIT, "Backend did not start!"); - wlr_backend_destroy(m_sWLRBackend); - wl_display_destroy(m_sWLDisplay); - throwError("The backend could not start!"); - } - prepareFallbackOutput(); g_pHyprRenderer->setCursorFromName("left_ptr"); @@ -882,7 +970,7 @@ Vector2D CCompositor::vectorToSurfaceLocal(const Vector2D& vec, PHLWINDOW pWindo return vec - pWindow->m_vRealPosition.goal() - std::get<1>(iterData) + Vector2D{geom.x, geom.y}; } -CMonitor* CCompositor::getMonitorFromOutput(wlr_output* out) { +CMonitor* CCompositor::getMonitorFromOutput(SP out) { for (auto& m : m_vMonitors) { if (m->output == out) { return m.get(); @@ -892,7 +980,7 @@ CMonitor* CCompositor::getMonitorFromOutput(wlr_output* out) { return nullptr; } -CMonitor* CCompositor::getRealMonitorFromOutput(wlr_output* out) { +CMonitor* CCompositor::getRealMonitorFromOutput(SP out) { for (auto& m : m_vRealMonitors) { if (m->output == out) { return m.get(); @@ -2240,8 +2328,12 @@ void CCompositor::setWindowFullscreen(PHLWINDOW pWindow, bool on, eFullscreenMod g_pInputManager->recheckIdleInhibitorStatus(); - // DMAbuf stuff for direct scanout - g_pHyprRenderer->setWindowScanoutMode(pWindow); + // further updates require a monitor + if (!PMONITOR) + return; + + // send a scanout tranche if we are entering fullscreen, and send a regular one if we aren't. + g_pHyprRenderer->setSurfaceScanoutMode(pWindow->m_pWLSurface->resource(), on ? PMONITOR->self.lock() : nullptr); g_pConfigManager->ensureVRR(PMONITOR); } @@ -2282,8 +2374,8 @@ void CCompositor::updateWorkspaceWindowData(const int& id) { } } -void CCompositor::scheduleFrameForMonitor(CMonitor* pMonitor) { - if ((m_sWLRSession && !m_sWLRSession->active) || !m_bSessionActive) +void CCompositor::scheduleFrameForMonitor(CMonitor* pMonitor, IOutput::scheduleFrameReason reason) { + if ((m_pAqBackend->hasSession() && !m_pAqBackend->session->active) || !m_bSessionActive) return; if (!pMonitor->m_bEnabled) @@ -2292,7 +2384,7 @@ void CCompositor::scheduleFrameForMonitor(CMonitor* pMonitor) { if (pMonitor->renderingActive) pMonitor->pendingFrame = true; - wlr_output_schedule_frame(pMonitor->output); + pMonitor->output->scheduleFrame(reason); } PHLWINDOW CCompositor::getWindowByRegex(const std::string& regexp) { @@ -2808,3 +2900,84 @@ PHLWINDOW CCompositor::windowForCPointer(CWindow* pWindow) { return {}; } + +static void checkDefaultCursorWarp(SP PNEWMONITOR, std::string monitorName) { + static auto PCURSORMONITOR = CConfigValue("cursor:default_monitor"); + static auto firstMonitorAdded = std::chrono::system_clock::now(); + static bool cursorDefaultDone = false; + static bool firstLaunch = true; + + const auto POS = PNEWMONITOR->middle(); + + // by default, cursor should be set to first monitor detected + // this is needed as a default if the monitor given in config above doesn't exist + if (firstLaunch) { + firstLaunch = false; + g_pCompositor->warpCursorTo(POS, true); + g_pInputManager->refocus(); + } + + if (cursorDefaultDone || *PCURSORMONITOR == STRVAL_EMPTY) + return; + + // after 10s, don't set cursor to default monitor + auto timePassedSec = std::chrono::duration_cast(std::chrono::system_clock::now() - firstMonitorAdded); + if (timePassedSec.count() > 10) { + cursorDefaultDone = true; + return; + } + + if (*PCURSORMONITOR == monitorName) { + cursorDefaultDone = true; + g_pCompositor->warpCursorTo(POS, true); + g_pInputManager->refocus(); + } +} + +void CCompositor::onNewMonitor(SP output) { + // add it to real + auto PNEWMONITOR = g_pCompositor->m_vRealMonitors.emplace_back(makeShared()); + if (std::string("HEADLESS-1") == output->name) { + g_pCompositor->m_pUnsafeOutput = PNEWMONITOR.get(); + output->name = "FALLBACK"; // we are allowed to do this :) + } + + Debug::log(LOG, "New output with name {}", output->name); + + PNEWMONITOR->szName = output->name; + PNEWMONITOR->output = output; + PNEWMONITOR->self = PNEWMONITOR; + const bool FALLBACK = g_pCompositor->m_pUnsafeOutput ? output == g_pCompositor->m_pUnsafeOutput->output : false; + PNEWMONITOR->ID = FALLBACK ? -1 : g_pCompositor->getNextAvailableMonitorID(output->name); + PNEWMONITOR->isUnsafeFallback = FALLBACK; + + EMIT_HOOK_EVENT("newMonitor", PNEWMONITOR); + + if (!FALLBACK) + PNEWMONITOR->onConnect(false); + + if (!PNEWMONITOR->m_bEnabled || FALLBACK) + return; + + // ready to process if we have a real monitor + + if ((!g_pHyprRenderer->m_pMostHzMonitor || PNEWMONITOR->refreshRate > g_pHyprRenderer->m_pMostHzMonitor->refreshRate) && PNEWMONITOR->m_bEnabled) + g_pHyprRenderer->m_pMostHzMonitor = PNEWMONITOR.get(); + + g_pCompositor->m_bReadyToProcess = true; + + g_pConfigManager->m_bWantsMonitorReload = true; + g_pCompositor->scheduleFrameForMonitor(PNEWMONITOR.get(), IOutput::AQ_SCHEDULE_NEW_MONITOR); + + checkDefaultCursorWarp(PNEWMONITOR, output->name); + + for (auto& w : g_pCompositor->m_vWindows) { + if (w->m_iMonitorID == PNEWMONITOR->ID) { + w->m_iLastSurfaceMonitorID = -1; + w->updateSurfaceScaleTransformDetails(); + } + } + + g_pHyprRenderer->damageMonitor(PNEWMONITOR.get()); + Events::listener_monitorFrame(PNEWMONITOR.get(), nullptr); +} diff --git a/src/Compositor.hpp b/src/Compositor.hpp index 4aec323f..58c5b33d 100644 --- a/src/Compositor.hpp +++ b/src/Compositor.hpp @@ -30,6 +30,9 @@ #include "plugins/PluginSystem.hpp" #include "helpers/Watchdog.hpp" +#include +#include + class CWLSurfaceResource; enum eManagersInitStage { @@ -43,22 +46,11 @@ class CCompositor { CCompositor(); ~CCompositor(); - // ------------------ WLR BASICS ------------------ // - wl_display* m_sWLDisplay; - wl_event_loop* m_sWLEventLoop; - wlr_backend* m_sWLRBackend; - wlr_session* m_sWLRSession; - wlr_renderer* m_sWLRRenderer; - wlr_allocator* m_sWLRAllocator; - wlr_compositor* m_sWLRCompositor; - wlr_subcompositor* m_sWLRSubCompositor; - wlr_drm* m_sWRLDRM; - wlr_drm_lease_v1_manager* m_sWRLDRMLeaseMgr; - wlr_egl* m_sWLREGL; - int m_iDRMFD; - wlr_linux_dmabuf_v1* m_sWLRLinuxDMABuf; - wlr_backend* m_sWLRHeadlessBackend; - // ------------------------------------------------- // + wl_display* m_sWLDisplay; + wl_event_loop* m_sWLEventLoop; + int m_iDRMFD = -1; + bool m_bInitialized = false; + SP m_pAqBackend; std::string m_szHyprTempDataRoot = ""; @@ -94,10 +86,9 @@ class CCompositor { bool m_bReadyToProcess = false; bool m_bSessionActive = true; bool m_bDPMSStateON = true; - bool m_bUnsafeState = false; // unsafe state is when there is no monitors. - bool m_bNextIsUnsafe = false; // because wlroots + bool m_bUnsafeState = false; // unsafe state is when there is no monitors. + bool m_bNextIsUnsafe = false; CMonitor* m_pUnsafeOutput = nullptr; // fallback output for the unsafe state - bool m_bExitTriggered = false; // For exit dispatcher bool m_bIsShuttingDown = false; // ------------------------------------------------- // @@ -116,8 +107,8 @@ class CCompositor { SP vectorToLayerPopupSurface(const Vector2D&, CMonitor* monitor, Vector2D*, PHLLS*); SP vectorWindowToSurface(const Vector2D&, PHLWINDOW, Vector2D& sl); Vector2D vectorToSurfaceLocal(const Vector2D&, PHLWINDOW, SP); - CMonitor* getMonitorFromOutput(wlr_output*); - CMonitor* getRealMonitorFromOutput(wlr_output*); + CMonitor* getMonitorFromOutput(SP); + CMonitor* getRealMonitorFromOutput(SP); PHLWINDOW getWindowFromSurface(SP); PHLWINDOW getWindowFromHandle(uint32_t); bool isWorkspaceVisible(PHLWORKSPACE); @@ -157,7 +148,7 @@ class CCompositor { void setWindowFullscreen(PHLWINDOW, bool, eFullscreenMode mode = FULLSCREEN_INVALID); void updateFullscreenFadeOnWorkspace(PHLWORKSPACE); PHLWINDOW getX11Parent(PHLWINDOW); - void scheduleFrameForMonitor(CMonitor*); + void scheduleFrameForMonitor(CMonitor*, Aquamarine::IOutput::scheduleFrameReason reason = Aquamarine::IOutput::AQ_SCHEDULE_CLIENT_UNKNOWN); void addToFadingOutSafe(PHLLS); void removeFromFadingOutSafe(PHLLS); void addToFadingOutSafe(PHLWINDOW); @@ -182,6 +173,7 @@ class CCompositor { void setPreferredTransformForSurface(SP pSurface, wl_output_transform transform); void updateSuspendedStates(); PHLWINDOW windowForCPointer(CWindow*); + void onNewMonitor(SP output); std::string explicitConfigPath; diff --git a/src/config/ConfigManager.cpp b/src/config/ConfigManager.cpp index 71349068..a5f18693 100644 --- a/src/config/ConfigManager.cpp +++ b/src/config/ConfigManager.cpp @@ -24,6 +24,7 @@ #include #include #include +#include using namespace Hyprutils::String; extern "C" char** environ; @@ -539,6 +540,7 @@ CConfigManager::CConfigManager() { m_pConfig->addConfigValue("cursor:enable_hyprcursor", Hyprlang::INT{1}); m_pConfig->addConfigValue("cursor:hide_on_key_press", Hyprlang::INT{0}); m_pConfig->addConfigValue("cursor:hide_on_touch", Hyprlang::INT{1}); + m_pConfig->addConfigValue("cursor:allow_dumb_copy", Hyprlang::INT{0}); m_pConfig->addConfigValue("autogenerated", Hyprlang::INT{0}); @@ -557,6 +559,8 @@ CConfigManager::CConfigManager() { m_pConfig->addConfigValue("group:groupbar:col.locked_active", Hyprlang::CConfigCustomValueType{&configHandleGradientSet, configHandleGradientDestroy, "0x66ff5500"}); m_pConfig->addConfigValue("group:groupbar:col.locked_inactive", Hyprlang::CConfigCustomValueType{&configHandleGradientSet, configHandleGradientDestroy, "0x66775500"}); + m_pConfig->addConfigValue("experimental:explicit_sync", Hyprlang::INT{0}); + // devices m_pConfig->addSpecialCategory("device", {"name"}); m_pConfig->addSpecialConfigValue("device", "sensitivity", {0.F}); @@ -1285,7 +1289,7 @@ void CConfigManager::dispatchExecOnce() { return; // update dbus env - if (g_pCompositor->m_sWLRSession) + if (g_pCompositor->m_pAqBackend->hasSession()) handleRawExec("", #ifdef USES_SYSTEMD "systemctl --user import-environment DISPLAY WAYLAND_DISPLAY HYPRLAND_INSTANCE_SIGNATURE XDG_CURRENT_DESKTOP QT_QPA_PLATFORMTHEME PATH XDG_DATA_DIRS && hash " @@ -1410,7 +1414,8 @@ void CConfigManager::ensureVRR(CMonitor* pMonitor) { if (USEVRR == 0) { if (m->vrrActive) { - wlr_output_state_set_adaptive_sync_enabled(m->state.wlr(), 0); + + m->output->state->setAdaptiveSync(false); if (!m->state.commit()) Debug::log(ERR, "Couldn't commit output {} in ensureVRR -> false", m->output->name); @@ -1419,11 +1424,11 @@ void CConfigManager::ensureVRR(CMonitor* pMonitor) { return; } else if (USEVRR == 1) { if (!m->vrrActive) { - wlr_output_state_set_adaptive_sync_enabled(m->state.wlr(), 1); + m->output->state->setAdaptiveSync(true); if (!m->state.test()) { Debug::log(LOG, "Pending output {} does not accept VRR.", m->output->name); - wlr_output_state_set_adaptive_sync_enabled(m->state.wlr(), 0); + m->output->state->setAdaptiveSync(false); } if (!m->state.commit()) @@ -1442,19 +1447,19 @@ void CConfigManager::ensureVRR(CMonitor* pMonitor) { const auto WORKSPACEFULL = PWORKSPACE->m_bHasFullscreenWindow && PWORKSPACE->m_efFullscreenMode == FULLSCREEN_FULL; - if (WORKSPACEFULL && m->output->adaptive_sync_status == WLR_OUTPUT_ADAPTIVE_SYNC_DISABLED) { - wlr_output_state_set_adaptive_sync_enabled(m->state.wlr(), 1); + if (WORKSPACEFULL) { + m->output->state->setAdaptiveSync(true); if (!m->state.test()) { Debug::log(LOG, "Pending output {} does not accept VRR.", m->output->name); - wlr_output_state_set_adaptive_sync_enabled(m->state.wlr(), 0); + m->output->state->setAdaptiveSync(false); } if (!m->state.commit()) Debug::log(ERR, "Couldn't commit output {} in ensureVRR -> true", m->output->name); - } else if (!WORKSPACEFULL && m->output->adaptive_sync_status == WLR_OUTPUT_ADAPTIVE_SYNC_ENABLED) { - wlr_output_state_set_adaptive_sync_enabled(m->state.wlr(), 0); + } else if (!WORKSPACEFULL) { + m->output->state->setAdaptiveSync(false); if (!m->state.commit()) Debug::log(ERR, "Couldn't commit output {} in ensureVRR -> false", m->output->name); diff --git a/src/debug/CrashReporter.cpp b/src/debug/CrashReporter.cpp index ce1a92ba..c25212fe 100644 --- a/src/debug/CrashReporter.cpp +++ b/src/debug/CrashReporter.cpp @@ -5,6 +5,7 @@ #include #include #include +#include #include "../plugins/PluginSystem.hpp" #include "../signal-safe.hpp" diff --git a/src/debug/HyprCtl.cpp b/src/debug/HyprCtl.cpp index 08d2bb57..b81cfeff 100644 --- a/src/debug/HyprCtl.cpp +++ b/src/debug/HyprCtl.cpp @@ -12,6 +12,8 @@ #include #include #include +#include +#include #include #include @@ -20,6 +22,7 @@ #include using namespace Hyprutils::String; +#include #include "../config/ConfigDataValues.hpp" #include "../config/ConfigValue.hpp" @@ -53,20 +56,15 @@ static std::string formatToString(uint32_t drmFormat) { static std::string availableModesForOutput(CMonitor* pMonitor, eHyprCtlOutputFormat format) { std::string result; - if (!wl_list_empty(&pMonitor->output->modes)) { - wlr_output_mode* mode; - - wl_list_for_each(mode, &pMonitor->output->modes, link) { - - if (format == FORMAT_NORMAL) - result += std::format("{}x{}@{:.2f}Hz ", mode->width, mode->height, mode->refresh / 1000.0); - else - result += std::format("\"{}x{}@{:.2f}Hz\",", mode->width, mode->height, mode->refresh / 1000.0); - } - - result.pop_back(); + for (auto& m : pMonitor->output->modes) { + if (format == FORMAT_NORMAL) + result += std::format("{}x{}@{:.2f}Hz ", m->pixelSize.x, m->pixelSize.y, m->refreshRate / 1000.0); + else + result += std::format("\"{}x{}@{:.2f}Hz\",", m->pixelSize.x, m->pixelSize.y, m->refreshRate / 1000.0); } + trimTrailingComma(result); + return result; } @@ -75,8 +73,10 @@ std::string CHyprCtl::getMonitorData(Hyprutils::Memory::CSharedPointer if (!m->output || m->ID == -1ull) return ""; - result += std::format( - R"#({{ + if (format == eHyprCtlOutputFormat::FORMAT_JSON) { + + result += std::format( + R"#({{ "id": {}, "name": "{}", "description": "{}", @@ -107,14 +107,27 @@ std::string CHyprCtl::getMonitorData(Hyprutils::Memory::CSharedPointer "currentFormat": "{}", "availableModes": [{}] }},)#", - m->ID, escapeJSONStrings(m->szName), escapeJSONStrings(m->szShortDescription), escapeJSONStrings(m->output->make ? m->output->make : ""), - escapeJSONStrings(m->output->model ? m->output->model : ""), escapeJSONStrings(m->output->serial ? m->output->serial : ""), (int)m->vecPixelSize.x, (int)m->vecPixelSize.y, - m->refreshRate, (int)m->vecPosition.x, (int)m->vecPosition.y, m->activeWorkspaceID(), (!m->activeWorkspace ? "" : escapeJSONStrings(m->activeWorkspace->m_szName)), - m->activeSpecialWorkspaceID(), escapeJSONStrings(m->activeSpecialWorkspace ? m->activeSpecialWorkspace->m_szName : ""), (int)m->vecReservedTopLeft.x, - (int)m->vecReservedTopLeft.y, (int)m->vecReservedBottomRight.x, (int)m->vecReservedBottomRight.y, m->scale, (int)m->transform, - (m == g_pCompositor->m_pLastMonitor ? "true" : "false"), (m->dpmsStatus ? "true" : "false"), - (m->output->adaptive_sync_status == WLR_OUTPUT_ADAPTIVE_SYNC_ENABLED ? "true" : "false"), (m->tearingState.activelyTearing ? "true" : "false"), - (m->m_bEnabled ? "false" : "true"), formatToString(m->drmFormat), availableModesForOutput(m.get(), format)); + + m->ID, escapeJSONStrings(m->szName), escapeJSONStrings(m->szShortDescription), escapeJSONStrings(m->output->make), escapeJSONStrings(m->output->model), + escapeJSONStrings(m->output->serial), (int)m->vecPixelSize.x, (int)m->vecPixelSize.y, m->refreshRate, (int)m->vecPosition.x, (int)m->vecPosition.y, + m->activeWorkspaceID(), (!m->activeWorkspace ? "" : escapeJSONStrings(m->activeWorkspace->m_szName)), m->activeSpecialWorkspaceID(), + escapeJSONStrings(m->activeSpecialWorkspace ? m->activeSpecialWorkspace->m_szName : ""), (int)m->vecReservedTopLeft.x, (int)m->vecReservedTopLeft.y, + (int)m->vecReservedBottomRight.x, (int)m->vecReservedBottomRight.y, m->scale, (int)m->transform, (m == g_pCompositor->m_pLastMonitor ? "true" : "false"), + (m->dpmsStatus ? "true" : "false"), (m->output->state->state().adaptiveSync ? "true" : "false"), (m->tearingState.activelyTearing ? "true" : "false"), + (m->m_bEnabled ? "false" : "true"), formatToString(m->output->state->state().drmFormat), availableModesForOutput(m.get(), format)); + + } else { + result += std::format("Monitor {} (ID {}):\n\t{}x{}@{:.5f} at {}x{}\n\tdescription: {}\n\tmake: {}\n\tmodel: {}\n\tserial: {}\n\tactive workspace: {} ({})\n\t" + "special workspace: {} ({})\n\treserved: {} {} {} {}\n\tscale: {:.2f}\n\ttransform: {}\n\tfocused: {}\n\t" + "dpmsStatus: {}\n\tvrr: {}\n\tactivelyTearing: {}\n\tdisabled: {}\n\tcurrentFormat: {}\n\tavailableModes: {}\n\n", + m->szName, m->ID, (int)m->vecPixelSize.x, (int)m->vecPixelSize.y, m->refreshRate, (int)m->vecPosition.x, (int)m->vecPosition.y, m->szShortDescription, + m->output->make, m->output->model, m->output->serial, m->activeWorkspaceID(), (!m->activeWorkspace ? "" : m->activeWorkspace->m_szName), + m->activeSpecialWorkspaceID(), (m->activeSpecialWorkspace ? m->activeSpecialWorkspace->m_szName : ""), (int)m->vecReservedTopLeft.x, + (int)m->vecReservedTopLeft.y, (int)m->vecReservedBottomRight.x, (int)m->vecReservedBottomRight.y, m->scale, (int)m->transform, + (m == g_pCompositor->m_pLastMonitor ? "yes" : "no"), (int)m->dpmsStatus, m->output->state->state().adaptiveSync, m->tearingState.activelyTearing, + !m->m_bEnabled, formatToString(m->output->state->state().drmFormat), availableModesForOutput(m.get(), format)); + } + return result; } @@ -144,16 +157,16 @@ std::string monitorsRequest(eHyprCtlOutputFormat format, std::string request) { if (!m->output || m->ID == -1ull) continue; - result += std::format( - "Monitor {} (ID {}):\n\t{}x{}@{:.5f} at {}x{}\n\tdescription: {}\n\tmake: {}\n\tmodel: {}\n\tserial: {}\n\tactive workspace: {} ({})\n\t" - "special workspace: {} ({})\n\treserved: {} {} {} {}\n\tscale: {:.2f}\n\ttransform: {}\n\tfocused: {}\n\t" - "dpmsStatus: {}\n\tvrr: {}\n\tactivelyTearing: {}\n\tdisabled: {}\n\tcurrentFormat: {}\n\tavailableModes: {}\n\n", - m->szName, m->ID, (int)m->vecPixelSize.x, (int)m->vecPixelSize.y, m->refreshRate, (int)m->vecPosition.x, (int)m->vecPosition.y, m->szShortDescription, - (m->output->make ? m->output->make : ""), (m->output->model ? m->output->model : ""), (m->output->serial ? m->output->serial : ""), m->activeWorkspaceID(), - (!m->activeWorkspace ? "" : m->activeWorkspace->m_szName), m->activeSpecialWorkspaceID(), (m->activeSpecialWorkspace ? m->activeSpecialWorkspace->m_szName : ""), - (int)m->vecReservedTopLeft.x, (int)m->vecReservedTopLeft.y, (int)m->vecReservedBottomRight.x, (int)m->vecReservedBottomRight.y, m->scale, (int)m->transform, - (m == g_pCompositor->m_pLastMonitor ? "yes" : "no"), (int)m->dpmsStatus, (int)(m->output->adaptive_sync_status == WLR_OUTPUT_ADAPTIVE_SYNC_ENABLED), - m->tearingState.activelyTearing, !m->m_bEnabled, formatToString(m->drmFormat), availableModesForOutput(m.get(), format)); + result += + std::format("Monitor {} (ID {}):\n\t{}x{}@{:.5f} at {}x{}\n\tdescription: {}\n\tmake: {}\n\tmodel: {}\n\tserial: {}\n\tactive workspace: {} ({})\n\t" + "special workspace: {} ({})\n\treserved: {} {} {} {}\n\tscale: {:.2f}\n\ttransform: {}\n\tfocused: {}\n\t" + "dpmsStatus: {}\n\tvrr: {}\n\tactivelyTearing: {}\n\tdisabled: {}\n\tcurrentFormat: {}\n\tavailableModes: {}\n\n", + m->szName, m->ID, (int)m->vecPixelSize.x, (int)m->vecPixelSize.y, m->refreshRate, (int)m->vecPosition.x, (int)m->vecPosition.y, m->szShortDescription, + m->output->make, m->output->model, m->output->serial, m->activeWorkspaceID(), (!m->activeWorkspace ? "" : m->activeWorkspace->m_szName), + m->activeSpecialWorkspaceID(), (m->activeSpecialWorkspace ? m->activeSpecialWorkspace->m_szName : ""), (int)m->vecReservedTopLeft.x, + (int)m->vecReservedTopLeft.y, (int)m->vecReservedBottomRight.x, (int)m->vecReservedBottomRight.y, m->scale, (int)m->transform, + (m == g_pCompositor->m_pLastMonitor ? "yes" : "no"), (int)m->dpmsStatus, (int)(m->output->state ? m->output->state->state().adaptiveSync : false), + m->tearingState.activelyTearing, !m->m_bEnabled, formatToString(m->output->state->state().drmFormat), availableModesForOutput(m.get(), format)); } } @@ -552,8 +565,7 @@ std::string devicesRequest(eHyprCtlOutputFormat format, std::string request) { "defaultSpeed": {:.5f} }},)#", (uintptr_t)m.get(), escapeJSONStrings(m->hlName), - wlr_input_device_is_libinput(&m->wlr()->base) ? libinput_device_config_accel_get_default_speed((libinput_device*)wlr_libinput_get_device_handle(&m->wlr()->base)) : - 0.f); + m->aq() && m->aq()->getLibinputHandle() ? libinput_device_config_accel_get_default_speed(m->aq()->getLibinputHandle()) : 0.f); } trimTrailingComma(result); @@ -611,9 +623,8 @@ std::string devicesRequest(eHyprCtlOutputFormat format, std::string request) { R"#( {{ "address": "0x{:x}", "type": "tabletTool", - "belongsTo": "0x{:x}" }},)#", - (uintptr_t)d.get(), d->wlr() ? (uintptr_t)d->wlr()->data : 0); + (uintptr_t)d.get()); } trimTrailingComma(result); @@ -641,7 +652,7 @@ std::string devicesRequest(eHyprCtlOutputFormat format, std::string request) { "address": "0x{:x}", "name": "{}" }},)#", - (uintptr_t)&d, escapeJSONStrings(d.pWlrDevice ? d.pWlrDevice->name : "")); + (uintptr_t)&d, escapeJSONStrings(d.pDevice ? d.pDevice->getName() : "")); } trimTrailingComma(result); @@ -654,9 +665,7 @@ std::string devicesRequest(eHyprCtlOutputFormat format, std::string request) { for (auto& m : g_pInputManager->m_vPointers) { result += std::format("\tMouse at {:x}:\n\t\t{}\n\t\t\tdefault speed: {:.5f}\n", (uintptr_t)m.get(), m->hlName, - (wlr_input_device_is_libinput(&m->wlr()->base) ? - libinput_device_config_accel_get_default_speed((libinput_device*)wlr_libinput_get_device_handle(&m->wlr()->base)) : - 0.f)); + (m->aq() && m->aq()->getLibinputHandle() ? libinput_device_config_accel_get_default_speed(m->aq()->getLibinputHandle()) : 0.f)); } result += "\n\nKeyboards:\n"; @@ -675,11 +684,11 @@ std::string devicesRequest(eHyprCtlOutputFormat format, std::string request) { } for (auto& d : g_pInputManager->m_vTablets) { - result += std::format("\tTablet at {:x}:\n\t\t{}\n\t\t\tsize: {}x{}mm\n", (uintptr_t)d.get(), d->hlName, d->wlr()->width_mm, d->wlr()->height_mm); + result += std::format("\tTablet at {:x}:\n\t\t{}\n\t\t\tsize: {}x{}mm\n", (uintptr_t)d.get(), d->hlName, d->aq()->physicalSize.x, d->aq()->physicalSize.y); } for (auto& d : g_pInputManager->m_vTabletTools) { - result += std::format("\tTablet Tool at {:x} (belongs to {:x})\n", (uintptr_t)d.get(), d->wlr() ? (uintptr_t)d->wlr()->data : 0); + result += std::format("\tTablet Tool at {:x}\n", (uintptr_t)d.get()); } result += "\n\nTouch:\n"; @@ -691,7 +700,7 @@ std::string devicesRequest(eHyprCtlOutputFormat format, std::string request) { result += "\n\nSwitches:\n"; for (auto& d : g_pInputManager->m_lSwitches) { - result += std::format("\tSwitch Device at {:x}:\n\t\t{}\n", (uintptr_t)&d, d.pWlrDevice ? d.pWlrDevice->name : ""); + result += std::format("\tSwitch Device at {:x}:\n\t\t{}\n", (uintptr_t)&d, d.pDevice ? d.pDevice->getName() : ""); } } @@ -1125,24 +1134,22 @@ std::string switchXKBLayoutRequest(eHyprCtlOutputFormat format, std::string requ if (PKEYBOARD == g_pInputManager->m_vKeyboards.end()) return "device not found"; - const auto PWLRKEYBOARD = (*PKEYBOARD)->wlr(); - const auto LAYOUTS = xkb_keymap_num_layouts(PWLRKEYBOARD->keymap); + const auto KEEB = *PKEYBOARD; + + const auto LAYOUTS = xkb_keymap_num_layouts(KEEB->xkbKeymap); xkb_layout_index_t activeLayout = 0; while (activeLayout < LAYOUTS) { - if (xkb_state_layout_index_is_active(PWLRKEYBOARD->xkb_state, activeLayout, XKB_STATE_LAYOUT_EFFECTIVE) == 1) + if (xkb_state_layout_index_is_active(KEEB->xkbState, activeLayout, XKB_STATE_LAYOUT_EFFECTIVE) == 1) break; activeLayout++; } - if (CMD == "next") { - wlr_keyboard_notify_modifiers(PWLRKEYBOARD, PWLRKEYBOARD->modifiers.depressed, PWLRKEYBOARD->modifiers.latched, PWLRKEYBOARD->modifiers.locked, - activeLayout > LAYOUTS ? 0 : activeLayout + 1); - } else if (CMD == "prev") { - wlr_keyboard_notify_modifiers(PWLRKEYBOARD, PWLRKEYBOARD->modifiers.depressed, PWLRKEYBOARD->modifiers.latched, PWLRKEYBOARD->modifiers.locked, - activeLayout == 0 ? LAYOUTS - 1 : activeLayout - 1); - } else { - + if (CMD == "next") + KEEB->updateModifiers(KEEB->modifiersState.depressed, KEEB->modifiersState.latched, KEEB->modifiersState.locked, activeLayout > LAYOUTS ? 0 : activeLayout + 1); + else if (CMD == "prev") + KEEB->updateModifiers(KEEB->modifiersState.depressed, KEEB->modifiersState.latched, KEEB->modifiersState.locked, activeLayout == 0 ? LAYOUTS - 1 : activeLayout - 1); + else { int requestedLayout = 0; try { requestedLayout = std::stoi(CMD); @@ -1152,7 +1159,7 @@ std::string switchXKBLayoutRequest(eHyprCtlOutputFormat format, std::string requ return "layout idx out of range of " + std::to_string(LAYOUTS); } - wlr_keyboard_notify_modifiers(PWLRKEYBOARD, PWLRKEYBOARD->modifiers.depressed, PWLRKEYBOARD->modifiers.latched, PWLRKEYBOARD->modifiers.locked, requestedLayout); + KEEB->updateModifiers(KEEB->modifiersState.depressed, KEEB->modifiersState.latched, KEEB->modifiersState.locked, requestedLayout); } return "ok"; @@ -1368,43 +1375,6 @@ std::string decorationRequest(eHyprCtlOutputFormat format, std::string request) return result; } -static bool addOutput(wlr_backend* backend, const std::string& type, const std::string& name) { - wlr_output* output = nullptr; - - if (type.empty() || type == "auto") { - if (wlr_backend_is_wl(backend)) - output = wlr_wl_output_create(backend); - else if (wlr_backend_is_headless(backend)) - output = wlr_headless_add_output(backend, 1920, 1080); - } else { - if (wlr_backend_is_wl(backend) && type == "wayland") - output = wlr_wl_output_create(backend); - else if (wlr_backend_is_headless(backend) && type == "headless") - output = wlr_headless_add_output(backend, 1920, 1080); - } - - if (output && !name.empty()) - g_pCompositor->getMonitorFromOutput(output)->szName = name; - - return output != nullptr; -} - -struct outputData { - std::string type; - std::string name; - bool added; -}; - -void createOutputIter(wlr_backend* backend, void* data) { - const auto DATA = static_cast(data); - - if (DATA->added) - return; - - if (addOutput(backend, DATA->type, DATA->name)) - DATA->added = true; -} - std::string dispatchOutput(eHyprCtlOutputFormat format, std::string request) { CVarList vars(request, 0, ' '); @@ -1413,15 +1383,36 @@ std::string dispatchOutput(eHyprCtlOutputFormat format, std::string request) { const auto MODE = vars[1]; + bool added = false; + + if (!vars[3].empty()) { + for (auto& m : g_pCompositor->m_vRealMonitors) { + if (m->szName == vars[3]) + return "Name already taken"; + } + } + if (MODE == "create" || MODE == "add") { if (g_pCompositor->getMonitorFromName(vars[3])) return "A real monitor already uses that name."; - outputData result{vars[2], vars[3], false}; + for (auto& impl : g_pCompositor->m_pAqBackend->getImplementations() | std::views::reverse) { + auto type = impl->type(); - wlr_multi_for_each_backend(g_pCompositor->m_sWLRBackend, createOutputIter, &result); + if (type == Aquamarine::AQ_BACKEND_HEADLESS && (vars[2] == "headless" || vars[2] == "auto")) { + added = true; + impl->createOutput(vars[3]); + break; + } - if (!result.added) + if (type == Aquamarine::AQ_BACKEND_WAYLAND && (vars[2] == "wayland" || vars[2] == "auto")) { + added = true; + impl->createOutput(vars[3]); + break; + } + } + + if (!added) return "no backend replied to the request"; } else if (MODE == "destroy" || MODE == "remove") { @@ -1433,7 +1424,7 @@ std::string dispatchOutput(eHyprCtlOutputFormat format, std::string request) { if (!PMONITOR->createdByUser) return "cannot remove a real display. Use the monitor keyword."; - wlr_output_destroy(PMONITOR->output); + PMONITOR->output->destroy(); } return "ok"; diff --git a/src/debug/Log.cpp b/src/debug/Log.cpp index 7547204a..c2939831 100644 --- a/src/debug/Log.cpp +++ b/src/debug/Log.cpp @@ -10,30 +10,6 @@ void Debug::init(const std::string& IS) { logFile = IS + (ISDEBUG ? "/hyprlandd.log" : "/hyprland.log"); } -void Debug::wlrLog(wlr_log_importance level, const char* fmt, va_list args) { - if (level > wlr_log_get_verbosity()) - return; - - char* outputStr = nullptr; - - vasprintf(&outputStr, fmt, args); - - std::string output = std::string(outputStr); - free(outputStr); - - rollingLog += output + "\n"; - - if (!disableLogs || !**disableLogs) { - std::ofstream ofs; - ofs.open(logFile, std::ios::out | std::ios::app); - ofs << "[wlr] " << output << "\n"; - ofs.close(); - } - - if (!disableStdout) - std::cout << output << "\n"; -} - void Debug::log(LogLevel level, std::string str) { if (level == TRACE && !trace) return; diff --git a/src/debug/Log.hpp b/src/debug/Log.hpp index e8cd80cf..33f3c9c1 100644 --- a/src/debug/Log.hpp +++ b/src/debug/Log.hpp @@ -67,6 +67,4 @@ namespace Debug { log(level, logMsg); } - - void wlrLog(wlr_log_importance level, const char* fmt, va_list args); }; diff --git a/src/desktop/Popup.cpp b/src/desktop/Popup.cpp index f0fd556c..131a26b5 100644 --- a/src/desktop/Popup.cpp +++ b/src/desktop/Popup.cpp @@ -55,7 +55,7 @@ void CPopup::initAllSignals() { } void CPopup::onNewPopup(SP popup) { - const auto POPUP = m_vChildren.emplace_back(std::make_unique(popup, this)).get(); + const auto POPUP = m_vChildren.emplace_back(makeShared(popup, this)).get(); Debug::log(LOG, "New popup at {:x}", (uintptr_t)POPUP); } @@ -250,7 +250,8 @@ void CPopup::recheckTree() { } void CPopup::recheckChildrenRecursive() { - for (auto& c : m_vChildren) { + auto cpy = m_vChildren; + for (auto& c : cpy) { c->onCommit(true); c->recheckChildrenRecursive(); } diff --git a/src/desktop/Popup.hpp b/src/desktop/Popup.hpp index 47e180a8..d045cd41 100644 --- a/src/desktop/Popup.hpp +++ b/src/desktop/Popup.hpp @@ -60,8 +60,8 @@ class CPopup { bool m_bMapped = false; // - std::vector> m_vChildren; - std::unique_ptr m_pSubsurfaceHead; + std::vector> m_vChildren; + std::unique_ptr m_pSubsurfaceHead; struct { CHyprSignalListener newPopup; diff --git a/src/desktop/Window.cpp b/src/desktop/Window.cpp index 4ea34156..7497957a 100644 --- a/src/desktop/Window.cpp +++ b/src/desktop/Window.cpp @@ -1155,7 +1155,8 @@ int CWindow::getRealBorderSize() { } bool CWindow::canBeTorn() { - return m_sWindowData.tearing.valueOr(m_bTearingHint); + static auto PTEARING = CConfigValue("general:allow_tearing"); + return m_sWindowData.tearing.valueOr(m_bTearingHint) && *PTEARING; } bool CWindow::shouldSendFullscreenState() { diff --git a/src/devices/IKeyboard.cpp b/src/devices/IKeyboard.cpp index cb294d1a..284a8295 100644 --- a/src/devices/IKeyboard.cpp +++ b/src/devices/IKeyboard.cpp @@ -2,7 +2,21 @@ #include "../defines.hpp" #include "../helpers/varlist/VarList.hpp" #include "../managers/input/InputManager.hpp" +#include "../managers/SeatManager.hpp" +#include "../config/ConfigManager.hpp" +#include +#include +#include +#define LED_COUNT 3 + +constexpr static std::array MODNAMES = { + XKB_MOD_NAME_SHIFT, XKB_MOD_NAME_CAPS, XKB_MOD_NAME_CTRL, XKB_MOD_NAME_ALT, XKB_MOD_NAME_NUM, "Mod3", XKB_MOD_NAME_LOGO, "Mod5", +}; + +constexpr static std::array LEDNAMES = {XKB_LED_NAME_NUM, XKB_LED_NAME_CAPS, XKB_LED_NAME_SCROLL}; + +// uint32_t IKeyboard::getCapabilities() { return HID_INPUT_CAPABILITY_KEYBOARD; } @@ -14,27 +28,149 @@ eHIDType IKeyboard::getType() { IKeyboard::~IKeyboard() { events.destroy.emit(); - if (!xkbTranslationState) - return; + clearManuallyAllocd(); +} - xkb_state_unref(xkbTranslationState); - xkbTranslationState = nullptr; +void IKeyboard::clearManuallyAllocd() { + if (xkbStaticState) + xkb_state_unref(xkbStaticState); + + if (xkbState) + xkb_state_unref(xkbState); + + if (xkbKeymap) + xkb_keymap_unref(xkbKeymap); + + if (xkbKeymapFD >= 0) + close(xkbKeymapFD); + + xkbKeymap = nullptr; + xkbState = nullptr; + xkbStaticState = nullptr; + xkbKeymapFD = -1; +} + +void IKeyboard::setKeymap(const SStringRuleNames& rules) { + currentRules = rules; + xkb_rule_names XKBRULES = { + .rules = rules.rules.c_str(), + .model = rules.model.c_str(), + .layout = rules.layout.c_str(), + .variant = rules.variant.c_str(), + .options = rules.options.c_str(), + }; + + const auto CONTEXT = xkb_context_new(XKB_CONTEXT_NO_FLAGS); + + if (!CONTEXT) { + Debug::log(ERR, "setKeymap: CONTEXT null??"); + return; + } + + clearManuallyAllocd(); + + Debug::log(LOG, "Attempting to create a keymap for layout {} with variant {} (rules: {}, model: {}, options: {})", rules.layout, rules.variant, rules.rules, rules.model, + rules.options); + + if (!xkbFilePath.empty()) { + auto path = absolutePath(xkbFilePath, g_pConfigManager->configCurrentPath); + + if (FILE* const KEYMAPFILE = fopen(path.c_str(), "r"); !KEYMAPFILE) + Debug::log(ERR, "Cannot open input:kb_file= file for reading"); + else { + xkbKeymap = xkb_keymap_new_from_file(CONTEXT, KEYMAPFILE, XKB_KEYMAP_FORMAT_TEXT_V1, XKB_KEYMAP_COMPILE_NO_FLAGS); + fclose(KEYMAPFILE); + } + } + + if (!xkbKeymap) + xkbKeymap = xkb_keymap_new_from_names(CONTEXT, &XKBRULES, XKB_KEYMAP_COMPILE_NO_FLAGS); + + if (!xkbKeymap) { + g_pConfigManager->addParseError("Invalid keyboard layout passed. ( rules: " + rules.rules + ", model: " + rules.model + ", variant: " + rules.variant + + ", options: " + rules.options + ", layout: " + rules.layout + " )"); + + Debug::log(ERR, "Keyboard layout {} with variant {} (rules: {}, model: {}, options: {}) couldn't have been loaded.", rules.layout, rules.variant, rules.rules, rules.model, + rules.options); + memset(&XKBRULES, 0, sizeof(XKBRULES)); + + currentRules.rules = ""; + currentRules.model = ""; + currentRules.variant = ""; + currentRules.options = ""; + currentRules.layout = "us"; + + xkbKeymap = xkb_keymap_new_from_names(CONTEXT, &XKBRULES, XKB_KEYMAP_COMPILE_NO_FLAGS); + } + + // set internal translation state + // demo sunao ni ienai + xkbStaticState = xkb_state_new(xkbKeymap); + + updateXKBTranslationState(xkbKeymap); + + const auto NUMLOCKON = g_pConfigManager->getDeviceInt(hlName, "numlock_by_default", "input:numlock_by_default"); + + if (NUMLOCKON == 1) { + // lock numlock + const auto IDX = xkb_map_mod_get_index(xkbKeymap, XKB_MOD_NAME_NUM); + + if (IDX != XKB_MOD_INVALID) + modifiersState.locked |= (uint32_t)1 << IDX; + + updateModifiers(modifiersState.depressed, modifiersState.latched, modifiersState.locked, modifiersState.group); + } + + for (size_t i = 0; i < LEDNAMES.size(); ++i) { + ledIndexes.at(i) = xkb_map_led_get_index(xkbKeymap, LEDNAMES.at(i)); + Debug::log(LOG, "xkb: LED index {} (name {}) got index {}", i, LEDNAMES.at(i), ledIndexes.at(i)); + } + + for (size_t i = 0; i < MODNAMES.size(); ++i) { + modIndexes.at(i) = xkb_map_mod_get_index(xkbKeymap, MODNAMES.at(i)); + Debug::log(LOG, "xkb: Mod index {} (name {}) got index {}", i, MODNAMES.at(i), modIndexes.at(i)); + } + + auto cKeymapStr = xkb_keymap_get_as_string(xkbKeymap, XKB_KEYMAP_FORMAT_TEXT_V1); + xkbKeymapString = cKeymapStr; + free(cKeymapStr); + + int rw, ro; + if (!allocateSHMFilePair(xkbKeymapString.length() + 1, &rw, &ro)) + Debug::log(ERR, "IKeyboard: failed to allocate shm pair for the keymap"); + else { + auto keymapFDDest = mmap(nullptr, xkbKeymapString.length() + 1, PROT_READ | PROT_WRITE, MAP_SHARED, rw, 0); + close(rw); + if (keymapFDDest == MAP_FAILED) { + Debug::log(ERR, "IKeyboard: failed to mmap a shm pair for the keymap"); + close(ro); + } else { + memcpy(keymapFDDest, xkbKeymapString.c_str(), xkbKeymapString.length()); + munmap(keymapFDDest, xkbKeymapString.length() + 1); + xkbKeymapFD = ro; + } + } + + xkb_context_unref(CONTEXT); + + g_pSeatManager->updateActiveKeyboardData(); } void IKeyboard::updateXKBTranslationState(xkb_keymap* const keymap) { - if (xkbTranslationState) - xkb_state_unref(xkbTranslationState); + if (xkbState) + xkb_state_unref(xkbState); + + xkbState = nullptr; if (keymap) { Debug::log(LOG, "Updating keyboard {:x}'s translation state from a provided keymap", (uintptr_t)this); - xkbTranslationState = xkb_state_new(keymap); + xkbState = xkb_state_new(keymap); return; } - const auto WLRKB = wlr(); - const auto KEYMAP = WLRKB->keymap; - const auto STATE = WLRKB->xkb_state; + const auto KEYMAP = xkbKeymap; + const auto STATE = xkbState; const auto LAYOUTSNUM = xkb_keymap_num_layouts(KEYMAP); const auto PCONTEXT = xkb_context_new(XKB_CONTEXT_NO_FLAGS); @@ -73,7 +209,7 @@ void IKeyboard::updateXKBTranslationState(xkb_keymap* const keymap) { KEYMAP = xkb_keymap_new_from_names(PCONTEXT, &rules, XKB_KEYMAP_COMPILE_NO_FLAGS); } - xkbTranslationState = xkb_state_new(KEYMAP); + xkbState = xkb_state_new(KEYMAP); xkb_keymap_unref(KEYMAP); xkb_context_unref(PCONTEXT); @@ -94,16 +230,15 @@ void IKeyboard::updateXKBTranslationState(xkb_keymap* const keymap) { const auto NEWKEYMAP = xkb_keymap_new_from_names(PCONTEXT, &rules, XKB_KEYMAP_COMPILE_NO_FLAGS); - xkbTranslationState = xkb_state_new(NEWKEYMAP); + xkbState = xkb_state_new(NEWKEYMAP); xkb_keymap_unref(NEWKEYMAP); xkb_context_unref(PCONTEXT); } std::string IKeyboard::getActiveLayout() { - const auto WLRKB = wlr(); - const auto KEYMAP = WLRKB->keymap; - const auto STATE = WLRKB->xkb_state; + const auto KEYMAP = xkbKeymap; + const auto STATE = xkbState; const auto LAYOUTSNUM = xkb_keymap_num_layouts(KEYMAP); for (uint32_t i = 0; i < LAYOUTSNUM; ++i) { @@ -120,14 +255,12 @@ std::string IKeyboard::getActiveLayout() { } void IKeyboard::updateLEDs() { - auto keyboard = wlr(); - - if (!keyboard || keyboard->xkb_state == nullptr) + if (xkbState == nullptr) return; uint32_t leds = 0; - for (uint32_t i = 0; i < WLR_LED_COUNT; ++i) { - if (xkb_state_led_index_is_active(keyboard->xkb_state, keyboard->led_indexes[i])) + for (uint32_t i = 0; i < LED_COUNT; ++i) { + if (xkb_state_led_index_is_active(xkbState, ledIndexes.at(i))) leds |= (1 << i); } @@ -135,13 +268,88 @@ void IKeyboard::updateLEDs() { } void IKeyboard::updateLEDs(uint32_t leds) { - auto keyboard = wlr(); - - if (!keyboard || keyboard->xkb_state == nullptr) + if (!xkbState) return; if (isVirtual() && g_pInputManager->shouldIgnoreVirtualKeyboard(self.lock())) return; - wlr_keyboard_led_update(keyboard, leds); + if (!aq()) + return; + + aq()->updateLEDs(leds); +} + +uint32_t IKeyboard::getModifiers() { + uint32_t modMask = modifiersState.depressed | modifiersState.latched; + uint32_t mods = 0; + for (size_t i = 0; i < modIndexes.size(); ++i) { + if (modIndexes.at(i) == XKB_MOD_INVALID) + continue; + + if (!(modMask & (1 << modIndexes.at(i)))) + continue; + + mods |= (1 << i); + } + + return mods; +} + +void IKeyboard::updateModifiers(uint32_t depressed, uint32_t latched, uint32_t locked, uint32_t group) { + if (!xkbState) + return; + + xkb_state_update_mask(xkbState, depressed, latched, locked, 0, 0, group); + + if (!updateModifiersState()) + return; + + updateLEDs(); +} + +bool IKeyboard::updateModifiersState() { + if (!xkbState) + return false; + + auto depressed = xkb_state_serialize_mods(xkbState, XKB_STATE_MODS_DEPRESSED); + auto latched = xkb_state_serialize_mods(xkbState, XKB_STATE_MODS_LATCHED); + auto locked = xkb_state_serialize_mods(xkbState, XKB_STATE_MODS_LOCKED); + auto group = xkb_state_serialize_layout(xkbState, XKB_STATE_LAYOUT_EFFECTIVE); + + if (depressed == modifiersState.depressed && latched == modifiersState.latched && locked == modifiersState.locked && group == modifiersState.group) + return false; + + modifiersState.depressed = depressed; + modifiersState.latched = latched; + modifiersState.locked = locked; + modifiersState.group = group; + + return true; +} + +void IKeyboard::updateXkbStateWithKey(uint32_t xkbKey, bool pressed) { + + const auto contains = std::find(pressedXKB.begin(), pressedXKB.end(), xkbKey) != pressedXKB.end(); + + if (contains && pressed) + return; + if (!contains && !pressed) + return; + + if (contains) + std::erase(pressedXKB, xkbKey); + else + pressedXKB.emplace_back(xkbKey); + + xkb_state_update_key(xkbState, xkbKey, pressed ? XKB_KEY_DOWN : XKB_KEY_UP); + + if (updateModifiersState()) { + keyboardEvents.modifiers.emit(SModifiersEvent{ + .depressed = modifiersState.depressed, + .latched = modifiersState.latched, + .locked = modifiersState.locked, + .group = modifiersState.group, + }); + } } diff --git a/src/devices/IKeyboard.hpp b/src/devices/IKeyboard.hpp index b1757a18..1ae6c7bc 100644 --- a/src/devices/IKeyboard.hpp +++ b/src/devices/IKeyboard.hpp @@ -7,15 +7,26 @@ #include -struct wlr_keyboard; +AQUAMARINE_FORWARD(IKeyboard); + +enum eKeyboardModifiers { + HL_MODIFIER_SHIFT = (1 << 0), + HL_MODIFIER_CAPS = (1 << 1), + HL_MODIFIER_CTRL = (1 << 2), + HL_MODIFIER_ALT = (1 << 3), + HL_MODIFIER_MOD2 = (1 << 4), + HL_MODIFIER_MOD3 = (1 << 5), + HL_MODIFIER_META = (1 << 6), + HL_MODIFIER_MOD5 = (1 << 7), +}; class IKeyboard : public IHID { public: virtual ~IKeyboard(); - virtual uint32_t getCapabilities(); - virtual eHIDType getType(); - virtual bool isVirtual() = 0; - virtual wlr_keyboard* wlr() = 0; + virtual uint32_t getCapabilities(); + virtual eHIDType getType(); + virtual bool isVirtual() = 0; + virtual SP aq() = 0; struct SKeyEvent { uint32_t timeMs = 0; @@ -24,6 +35,17 @@ class IKeyboard : public IHID { wl_keyboard_key_state state = WL_KEYBOARD_KEY_STATE_PRESSED; }; + struct SKeymapEvent { + xkb_keymap* keymap = nullptr; + }; + + struct SModifiersEvent { + uint32_t depressed = 0; + uint32_t latched = 0; + uint32_t locked = 0; + uint32_t group = 0; + }; + struct { CSignal key; CSignal modifiers; @@ -39,25 +61,46 @@ class IKeyboard : public IHID { std::string rules = ""; }; + void setKeymap(const SStringRuleNames& rules); void updateXKBTranslationState(xkb_keymap* const keymap = nullptr); std::string getActiveLayout(); void updateLEDs(); void updateLEDs(uint32_t leds); + uint32_t getModifiers(); + void updateModifiers(uint32_t depressed, uint32_t latched, uint32_t locked, uint32_t group); + bool updateModifiersState(); // rets whether changed + void updateXkbStateWithKey(uint32_t xkbKey, bool pressed); bool active = false; bool enabled = true; - xkb_layout_index_t activeLayout = 0; - xkb_state* xkbTranslationState = nullptr; + xkb_layout_index_t activeLayout = 0; + xkb_state * xkbState = nullptr, *xkbStaticState /* Static state: never gets modifiers or layout changes sent, used for keybinds. */ = nullptr; + xkb_keymap* xkbKeymap = nullptr; - std::string hlName = ""; - std::string xkbFilePath = ""; + struct { + uint32_t depressed = 0, latched = 0, locked = 0, group = 0; + } modifiersState; - SStringRuleNames currentRules; - int repeatRate = 0; - int repeatDelay = 0; - int numlockOn = -1; - bool resolveBindsBySym = false; + std::array ledIndexes = {XKB_MOD_INVALID}; + std::array modIndexes = {XKB_MOD_INVALID}; + uint32_t leds = 0; - WP self; + std::string hlName = ""; + std::string xkbFilePath = ""; + std::string xkbKeymapString = ""; + int xkbKeymapFD = -1; + + SStringRuleNames currentRules; + int repeatRate = 0; + int repeatDelay = 0; + int numlockOn = -1; + bool resolveBindsBySym = false; + + WP self; + + private: + void clearManuallyAllocd(); + + std::vector pressedXKB; }; diff --git a/src/devices/IPointer.hpp b/src/devices/IPointer.hpp index b2995b2f..5df47c04 100644 --- a/src/devices/IPointer.hpp +++ b/src/devices/IPointer.hpp @@ -5,17 +5,17 @@ #include "../macros.hpp" #include "../helpers/math/Math.hpp" -struct wlr_pointer; +AQUAMARINE_FORWARD(IPointer); /* Base class for a pointer. */ class IPointer : public IHID { public: - virtual uint32_t getCapabilities(); - virtual eHIDType getType(); - virtual bool isVirtual() = 0; - virtual wlr_pointer* wlr() = 0; + virtual uint32_t getCapabilities(); + virtual eHIDType getType(); + virtual bool isVirtual() = 0; + virtual SP aq() = 0; struct SMotionEvent { uint32_t timeMs = 0; diff --git a/src/devices/ITouch.hpp b/src/devices/ITouch.hpp index b9cbf2ae..cb8a6e90 100644 --- a/src/devices/ITouch.hpp +++ b/src/devices/ITouch.hpp @@ -5,14 +5,14 @@ #include "../macros.hpp" #include "../helpers/math/Math.hpp" -struct wlr_touch; +AQUAMARINE_FORWARD(ITouch); class ITouch : public IHID { public: - virtual uint32_t getCapabilities(); - virtual eHIDType getType(); - virtual bool isVirtual() = 0; - virtual wlr_touch* wlr() = 0; + virtual uint32_t getCapabilities(); + virtual eHIDType getType(); + virtual bool isVirtual() = 0; + virtual SP aq() = 0; struct SDownEvent { uint32_t timeMs = 0; diff --git a/src/devices/Keyboard.cpp b/src/devices/Keyboard.cpp index 17357edb..ae28c07d 100644 --- a/src/devices/Keyboard.cpp +++ b/src/devices/Keyboard.cpp @@ -1,7 +1,10 @@ #include "Keyboard.hpp" #include "../defines.hpp" +#include "../Compositor.hpp" -SP CKeyboard::create(wlr_keyboard* keeb) { +#include + +SP CKeyboard::create(SP keeb) { SP pKeeb = SP(new CKeyboard(keeb)); pKeeb->self = pKeeb; @@ -13,52 +16,41 @@ bool CKeyboard::isVirtual() { return false; } -wlr_keyboard* CKeyboard::wlr() { - return keyboard; +SP CKeyboard::aq() { + return keyboard.lock(); } -CKeyboard::CKeyboard(wlr_keyboard* keeb) : keyboard(keeb) { +CKeyboard::CKeyboard(SP keeb) : keyboard(keeb) { if (!keeb) return; - // clang-format off - hyprListener_destroy.initCallback(&keeb->base.events.destroy, [this] (void* owner, void* data) { - disconnectCallbacks(); - keyboard = nullptr; - events.destroy.emit(); - }, this, "CKeyboard"); + listeners.destroy = keeb->events.destroy.registerListener([this](std::any d) { + keyboard.reset(); + events.destroy.emit(); + }); - hyprListener_key.initCallback(&keeb->events.key, [this] (void* owner, void* data) { - auto E = (wlr_keyboard_key_event*)data; + listeners.key = keeb->events.key.registerListener([this](std::any d) { + auto E = std::any_cast(d); + + updateXkbStateWithKey(E.key + 8, E.pressed); keyboardEvents.key.emit(SKeyEvent{ - .timeMs = E->time_msec, - .keycode = E->keycode, - .updateMods = E->update_state, - .state = E->state, + .timeMs = E.timeMs, + .keycode = E.key, + .state = E.pressed ? WL_KEYBOARD_KEY_STATE_PRESSED : WL_KEYBOARD_KEY_STATE_RELEASED, }); - }, this, "CKeyboard"); + }); - hyprListener_keymap.initCallback(&keeb->events.keymap, [this] (void* owner, void* data) { - keyboardEvents.keymap.emit(); - }, this, "CKeyboard"); + listeners.modifiers = keeb->events.modifiers.registerListener([this](std::any d) { + updateModifiersState(); - hyprListener_modifiers.initCallback(&keeb->events.modifiers, [this] (void* owner, void* data) { - keyboardEvents.modifiers.emit(); - }, this, "CKeyboard"); + keyboardEvents.modifiers.emit(SModifiersEvent{ + .depressed = modifiersState.depressed, + .latched = modifiersState.latched, + .locked = modifiersState.locked, + .group = modifiersState.group, + }); + }); - hyprListener_repeatInfo.initCallback(&keeb->events.repeat_info, [this] (void* owner, void* data) { - keyboardEvents.repeatInfo.emit(); - }, this, "CKeyboard"); - // clang-format on - - deviceName = keeb->base.name ? keeb->base.name : "UNKNOWN"; -} - -void CKeyboard::disconnectCallbacks() { - hyprListener_destroy.removeCallback(); - hyprListener_key.removeCallback(); - hyprListener_keymap.removeCallback(); - hyprListener_repeatInfo.removeCallback(); - hyprListener_modifiers.removeCallback(); + deviceName = keeb->getName(); } diff --git a/src/devices/Keyboard.hpp b/src/devices/Keyboard.hpp index cf01a9a7..f6de43cb 100644 --- a/src/devices/Keyboard.hpp +++ b/src/devices/Keyboard.hpp @@ -4,21 +4,19 @@ class CKeyboard : public IKeyboard { public: - static SP create(wlr_keyboard* keeb); + static SP create(SP keeb); - virtual bool isVirtual(); - virtual wlr_keyboard* wlr(); + virtual bool isVirtual(); + virtual SP aq(); private: - CKeyboard(wlr_keyboard* keeb); + CKeyboard(SP keeb); - wlr_keyboard* keyboard = nullptr; + WP keyboard; - void disconnectCallbacks(); - - DYNLISTENER(destroy); - DYNLISTENER(key); - DYNLISTENER(modifiers); - DYNLISTENER(keymap); - DYNLISTENER(repeatInfo); + struct { + CHyprSignalListener destroy; + CHyprSignalListener key; + CHyprSignalListener modifiers; + } listeners; }; \ No newline at end of file diff --git a/src/devices/Mouse.cpp b/src/devices/Mouse.cpp index b860298c..ae89ed92 100644 --- a/src/devices/Mouse.cpp +++ b/src/devices/Mouse.cpp @@ -1,7 +1,8 @@ #include "Mouse.hpp" #include "../defines.hpp" +#include -SP CMouse::create(wlr_pointer* mouse) { +SP CMouse::create(SP mouse) { SP pMouse = SP(new CMouse(mouse)); pMouse->self = pMouse; @@ -9,166 +10,143 @@ SP CMouse::create(wlr_pointer* mouse) { return pMouse; } -CMouse::CMouse(wlr_pointer* mouse_) : mouse(mouse_) { +CMouse::CMouse(SP mouse_) : mouse(mouse_) { if (!mouse) return; - // clang-format off - hyprListener_destroy.initCallback(&mouse->base.events.destroy, [this] (void* owner, void* data) { - disconnectCallbacks(); - mouse = nullptr; + listeners.destroy = mouse->events.destroy.registerListener([this](std::any d) { + mouse.reset(); events.destroy.emit(); - }, this, "CMouse"); + }); - hyprListener_motion.initCallback(&mouse->events.motion, [this] (void* owner, void* data) { - auto E = (wlr_pointer_motion_event*)data; + listeners.motion = mouse->events.move.registerListener([this](std::any d) { + auto E = std::any_cast(d); pointerEvents.motion.emit(SMotionEvent{ - .timeMs = E->time_msec, - .delta = {E->delta_x, E->delta_y}, - .unaccel = {E->unaccel_dx, E->unaccel_dy}, + .timeMs = E.timeMs, + .delta = E.delta, + .unaccel = E.unaccel, }); - }, this, "CMouse"); + }); - hyprListener_motionAbsolute.initCallback(&mouse->events.motion_absolute, [this] (void* owner, void* data) { - auto E = (wlr_pointer_motion_absolute_event*)data; + listeners.motionAbsolute = mouse->events.warp.registerListener([this](std::any d) { + auto E = std::any_cast(d); pointerEvents.motionAbsolute.emit(SMotionAbsoluteEvent{ - .timeMs = E->time_msec, - .absolute = {E->x, E->y}, + .timeMs = E.timeMs, + .absolute = E.absolute, .device = self.lock(), }); - }, this, "CMouse"); + }); - hyprListener_button.initCallback(&mouse->events.button, [this] (void* owner, void* data) { - auto E = (wlr_pointer_button_event*)data; + listeners.button = mouse->events.button.registerListener([this](std::any d) { + auto E = std::any_cast(d); pointerEvents.button.emit(SButtonEvent{ - .timeMs = E->time_msec, - .button = E->button, - .state = (wl_pointer_button_state)E->state, + .timeMs = E.timeMs, + .button = E.button, + .state = E.pressed ? WL_POINTER_BUTTON_STATE_PRESSED : WL_POINTER_BUTTON_STATE_RELEASED, }); - }, this, "CMouse"); + }); - hyprListener_axis.initCallback(&mouse->events.axis, [this] (void* owner, void* data) { - auto E = (wlr_pointer_axis_event*)data; + listeners.axis = mouse->events.axis.registerListener([this](std::any d) { + auto E = std::any_cast(d); pointerEvents.axis.emit(SAxisEvent{ - .timeMs = E->time_msec, - .source = E->source, - .axis = E->orientation, - .relativeDirection = E->relative_direction, - .delta = E->delta, - .deltaDiscrete = E->delta_discrete, + .timeMs = E.timeMs, + .source = (wl_pointer_axis_source)E.source, + .axis = (wl_pointer_axis)E.axis, + .relativeDirection = (wl_pointer_axis_relative_direction)E.direction, + .delta = E.delta, + .deltaDiscrete = E.discrete, }); - }, this, "CMouse"); + }); - hyprListener_frame.initCallback(&mouse->events.frame, [this] (void* owner, void* data) { - pointerEvents.frame.emit(); - }, this, "CMouse"); + listeners.frame = mouse->events.frame.registerListener([this](std::any d) { pointerEvents.frame.emit(); }); - hyprListener_swipeBegin.initCallback(&mouse->events.swipe_begin, [this] (void* owner, void* data) { - auto E = (wlr_pointer_swipe_begin_event*)data; + listeners.swipeBegin = mouse->events.swipeBegin.registerListener([this](std::any d) { + auto E = std::any_cast(d); pointerEvents.swipeBegin.emit(SSwipeBeginEvent{ - .timeMs = E->time_msec, - .fingers = E->fingers, + .timeMs = E.timeMs, + .fingers = E.fingers, }); - }, this, "CMouse"); + }); - hyprListener_swipeEnd.initCallback(&mouse->events.swipe_end, [this] (void* owner, void* data) { - auto E = (wlr_pointer_swipe_end_event*)data; + listeners.swipeEnd = mouse->events.swipeEnd.registerListener([this](std::any d) { + auto E = std::any_cast(d); pointerEvents.swipeEnd.emit(SSwipeEndEvent{ - .timeMs = E->time_msec, - .cancelled = E->cancelled, + .timeMs = E.timeMs, + .cancelled = E.cancelled, }); - }, this, "CMouse"); + }); - hyprListener_swipeUpdate.initCallback(&mouse->events.swipe_update, [this] (void* owner, void* data) { - auto E = (wlr_pointer_swipe_update_event*)data; + listeners.swipeUpdate = mouse->events.swipeUpdate.registerListener([this](std::any d) { + auto E = std::any_cast(d); pointerEvents.swipeUpdate.emit(SSwipeUpdateEvent{ - .timeMs = E->time_msec, - .fingers = E->fingers, - .delta = {E->dx, E->dy}, + .timeMs = E.timeMs, + .fingers = E.fingers, + .delta = E.delta, }); - }, this, "CMouse"); + }); - hyprListener_pinchBegin.initCallback(&mouse->events.pinch_begin, [this] (void* owner, void* data) { - auto E = (wlr_pointer_pinch_begin_event*)data; + listeners.pinchBegin = mouse->events.pinchBegin.registerListener([this](std::any d) { + auto E = std::any_cast(d); pointerEvents.pinchBegin.emit(SPinchBeginEvent{ - .timeMs = E->time_msec, - .fingers = E->fingers, + .timeMs = E.timeMs, + .fingers = E.fingers, }); - }, this, "CMouse"); + }); - hyprListener_pinchEnd.initCallback(&mouse->events.pinch_end, [this] (void* owner, void* data) { - auto E = (wlr_pointer_pinch_end_event*)data; + listeners.pinchEnd = mouse->events.pinchEnd.registerListener([this](std::any d) { + auto E = std::any_cast(d); pointerEvents.pinchEnd.emit(SPinchEndEvent{ - .timeMs = E->time_msec, - .cancelled = E->cancelled, + .timeMs = E.timeMs, + .cancelled = E.cancelled, }); - }, this, "CMouse"); + }); - hyprListener_pinchUpdate.initCallback(&mouse->events.pinch_update, [this] (void* owner, void* data) { - auto E = (wlr_pointer_pinch_update_event*)data; + listeners.pinchUpdate = mouse->events.pinchUpdate.registerListener([this](std::any d) { + auto E = std::any_cast(d); pointerEvents.pinchUpdate.emit(SPinchUpdateEvent{ - .timeMs = E->time_msec, - .fingers = E->fingers, - .delta = {E->dx, E->dy}, - .scale = E->scale, - .rotation = E->rotation, + .timeMs = E.timeMs, + .fingers = E.fingers, + .delta = E.delta, + .scale = E.scale, + .rotation = E.rotation, }); - }, this, "CMouse"); + }); - hyprListener_holdBegin.initCallback(&mouse->events.hold_begin, [this] (void* owner, void* data) { - auto E = (wlr_pointer_hold_begin_event*)data; + listeners.holdBegin = mouse->events.holdBegin.registerListener([this](std::any d) { + auto E = std::any_cast(d); pointerEvents.holdBegin.emit(SHoldBeginEvent{ - .timeMs = E->time_msec, - .fingers = E->fingers, + .timeMs = E.timeMs, + .fingers = E.fingers, }); - }, this, "CMouse"); + }); - hyprListener_holdEnd.initCallback(&mouse->events.hold_end, [this] (void* owner, void* data) { - auto E = (wlr_pointer_hold_end_event*)data; + listeners.holdEnd = mouse->events.holdEnd.registerListener([this](std::any d) { + auto E = std::any_cast(d); pointerEvents.holdEnd.emit(SHoldEndEvent{ - .timeMs = E->time_msec, - .cancelled = E->cancelled, + .timeMs = E.timeMs, + .cancelled = E.cancelled, }); - }, this, "CMouse"); + }); - // clang-format on - - deviceName = mouse->base.name ? mouse->base.name : "UNKNOWN"; -} - -void CMouse::disconnectCallbacks() { - hyprListener_destroy.removeCallback(); - hyprListener_motion.removeCallback(); - hyprListener_motionAbsolute.removeCallback(); - hyprListener_button.removeCallback(); - hyprListener_axis.removeCallback(); - hyprListener_frame.removeCallback(); - hyprListener_swipeBegin.removeCallback(); - hyprListener_swipeEnd.removeCallback(); - hyprListener_swipeUpdate.removeCallback(); - hyprListener_pinchBegin.removeCallback(); - hyprListener_pinchEnd.removeCallback(); - hyprListener_pinchUpdate.removeCallback(); - hyprListener_holdBegin.removeCallback(); - hyprListener_holdEnd.removeCallback(); + deviceName = mouse->getName(); } bool CMouse::isVirtual() { return false; } -wlr_pointer* CMouse::wlr() { - return mouse; +SP CMouse::aq() { + return mouse.lock(); } diff --git a/src/devices/Mouse.hpp b/src/devices/Mouse.hpp index 40a65ca8..2b51fbe9 100644 --- a/src/devices/Mouse.hpp +++ b/src/devices/Mouse.hpp @@ -4,33 +4,34 @@ class CMouse : public IPointer { public: - static SP create(wlr_pointer* mouse); + static SP create(SP mouse); - virtual bool isVirtual(); - virtual wlr_pointer* wlr(); + virtual bool isVirtual(); + virtual SP aq(); private: - CMouse(wlr_pointer* mouse); + CMouse(SP mouse); - wlr_pointer* mouse = nullptr; + WP mouse; - void disconnectCallbacks(); + struct { + CHyprSignalListener destroy; - DYNLISTENER(destroy); - DYNLISTENER(motion); - DYNLISTENER(motionAbsolute); - DYNLISTENER(button); - DYNLISTENER(axis); - DYNLISTENER(frame); + CHyprSignalListener motion; + CHyprSignalListener motionAbsolute; + CHyprSignalListener button; + CHyprSignalListener axis; + CHyprSignalListener frame; - DYNLISTENER(swipeBegin); - DYNLISTENER(swipeEnd); - DYNLISTENER(swipeUpdate); + CHyprSignalListener swipeBegin; + CHyprSignalListener swipeEnd; + CHyprSignalListener swipeUpdate; - DYNLISTENER(pinchBegin); - DYNLISTENER(pinchEnd); - DYNLISTENER(pinchUpdate); + CHyprSignalListener pinchBegin; + CHyprSignalListener pinchEnd; + CHyprSignalListener pinchUpdate; - DYNLISTENER(holdBegin); - DYNLISTENER(holdEnd); + CHyprSignalListener holdBegin; + CHyprSignalListener holdEnd; + } listeners; }; diff --git a/src/devices/Tablet.cpp b/src/devices/Tablet.cpp index b5ab16c1..71ca8991 100644 --- a/src/devices/Tablet.cpp +++ b/src/devices/Tablet.cpp @@ -2,8 +2,9 @@ #include "../defines.hpp" #include "../protocols/Tablet.hpp" #include "../protocols/core/Compositor.hpp" +#include -SP CTablet::create(wlr_tablet* tablet) { +SP CTablet::create(SP tablet) { SP pTab = SP(new CTablet(tablet)); pTab->self = pTab; @@ -13,7 +14,7 @@ SP CTablet::create(wlr_tablet* tablet) { return pTab; } -SP CTabletTool::create(wlr_tablet_tool* tablet) { +SP CTabletTool::create(SP tablet) { SP pTab = SP(new CTabletTool(tablet)); pTab->self = pTab; @@ -23,7 +24,7 @@ SP CTabletTool::create(wlr_tablet_tool* tablet) { return pTab; } -SP CTabletPad::create(wlr_tablet_pad* tablet) { +SP CTabletPad::create(SP tablet) { SP pTab = SP(new CTabletPad(tablet)); pTab->self = pTab; @@ -33,33 +34,25 @@ SP CTabletPad::create(wlr_tablet_pad* tablet) { return pTab; } -SP CTabletTool::fromWlr(wlr_tablet_tool* tool) { - return ((CTabletTool*)tool->data)->self.lock(); -} - -SP CTablet::fromWlr(wlr_tablet* tablet) { - return ((CTablet*)tablet->data)->self.lock(); -} - -static uint32_t wlrUpdateToHl(uint32_t wlr) { +static uint32_t aqUpdateToHl(uint32_t aq) { uint32_t result = 0; - if (wlr & WLR_TABLET_TOOL_AXIS_X) + if (aq & Aquamarine::AQ_TABLET_TOOL_AXIS_X) result |= CTablet::eTabletToolAxes::HID_TABLET_TOOL_AXIS_X; - if (wlr & WLR_TABLET_TOOL_AXIS_Y) + if (aq & Aquamarine::AQ_TABLET_TOOL_AXIS_Y) result |= CTablet::eTabletToolAxes::HID_TABLET_TOOL_AXIS_Y; - if (wlr & WLR_TABLET_TOOL_AXIS_DISTANCE) + if (aq & Aquamarine::AQ_TABLET_TOOL_AXIS_DISTANCE) result |= CTablet::eTabletToolAxes::HID_TABLET_TOOL_AXIS_DISTANCE; - if (wlr & WLR_TABLET_TOOL_AXIS_PRESSURE) + if (aq & Aquamarine::AQ_TABLET_TOOL_AXIS_PRESSURE) result |= CTablet::eTabletToolAxes::HID_TABLET_TOOL_AXIS_PRESSURE; - if (wlr & WLR_TABLET_TOOL_AXIS_TILT_X) + if (aq & Aquamarine::AQ_TABLET_TOOL_AXIS_TILT_X) result |= CTablet::eTabletToolAxes::HID_TABLET_TOOL_AXIS_TILT_X; - if (wlr & WLR_TABLET_TOOL_AXIS_TILT_Y) + if (aq & Aquamarine::AQ_TABLET_TOOL_AXIS_TILT_Y) result |= CTablet::eTabletToolAxes::HID_TABLET_TOOL_AXIS_TILT_Y; - if (wlr & WLR_TABLET_TOOL_AXIS_ROTATION) + if (aq & Aquamarine::AQ_TABLET_TOOL_AXIS_ROTATION) result |= CTablet::eTabletToolAxes::HID_TABLET_TOOL_AXIS_ROTATION; - if (wlr & WLR_TABLET_TOOL_AXIS_SLIDER) + if (aq & Aquamarine::AQ_TABLET_TOOL_AXIS_SLIDER) result |= CTablet::eTabletToolAxes::HID_TABLET_TOOL_AXIS_SLIDER; - if (wlr & WLR_TABLET_TOOL_AXIS_WHEEL) + if (aq & Aquamarine::AQ_TABLET_TOOL_AXIS_WHEEL) result |= CTablet::eTabletToolAxes::HID_TABLET_TOOL_AXIS_WHEEL; return result; } @@ -68,97 +61,81 @@ uint32_t CTablet::getCapabilities() { return HID_INPUT_CAPABILITY_POINTER | HID_INPUT_CAPABILITY_TABLET; } -wlr_tablet* CTablet::wlr() { - return tablet; +SP CTablet::aq() { + return tablet.lock(); } -CTablet::CTablet(wlr_tablet* tablet_) : tablet(tablet_) { +CTablet::CTablet(SP tablet_) : tablet(tablet_) { if (!tablet) return; - tablet->data = this; - - // clang-format off - hyprListener_destroy.initCallback(&tablet->base.events.destroy, [this] (void* owner, void* data) { - tablet = nullptr; - disconnectCallbacks(); + listeners.destroy = tablet->events.destroy.registerListener([this](std::any d) { + tablet.reset(); events.destroy.emit(); - }, this, "CTablet"); + }); - hyprListener_axis.initCallback(&tablet->events.axis, [this] (void* owner, void* data) { - auto E = (wlr_tablet_tool_axis_event*)data; + listeners.axis = tablet->events.axis.registerListener([this](std::any d) { + auto E = std::any_cast(d); tabletEvents.axis.emit(SAxisEvent{ - .tool = E->tool, + .tool = E.tool, .tablet = self.lock(), - .timeMs = E->time_msec, - .updatedAxes = wlrUpdateToHl(E->updated_axes), - .axis = {E->x, E->y}, - .axisDelta = {E->dx, E->dy}, - .tilt = {E->tilt_x, E->tilt_y}, - .pressure = E->pressure, - .distance = E->distance, - .rotation = E->rotation, - .slider = E->slider, - .wheelDelta = E->wheel_delta, + .timeMs = E.timeMs, + .updatedAxes = aqUpdateToHl(E.updatedAxes), + .axis = E.absolute, + .axisDelta = E.delta, + .tilt = E.tilt, + .pressure = E.pressure, + .distance = E.distance, + .rotation = E.rotation, + .slider = E.slider, + .wheelDelta = E.wheelDelta, }); - }, this, "CTablet"); + }); - hyprListener_proximity.initCallback(&tablet->events.proximity, [this] (void* owner, void* data) { - auto E = (wlr_tablet_tool_proximity_event*)data; + listeners.proximity = tablet->events.proximity.registerListener([this](std::any d) { + auto E = std::any_cast(d); tabletEvents.proximity.emit(SProximityEvent{ - .tool = E->tool, + .tool = E.tool, .tablet = self.lock(), - .timeMs = E->time_msec, - .proximity = {E->x, E->y}, - .in = E->state == WLR_TABLET_TOOL_PROXIMITY_IN, + .timeMs = E.timeMs, + .proximity = E.absolute, + .in = E.in, }); - }, this, "CTablet"); + }); - hyprListener_tip.initCallback(&tablet->events.tip, [this] (void* owner, void* data) { - auto E = (wlr_tablet_tool_tip_event*)data; + listeners.tip = tablet->events.tip.registerListener([this](std::any d) { + auto E = std::any_cast(d); tabletEvents.tip.emit(STipEvent{ - .tool = E->tool, + .tool = E.tool, .tablet = self.lock(), - .timeMs = E->time_msec, - .tip = {E->x, E->y}, - .in = E->state == WLR_TABLET_TOOL_TIP_DOWN, + .timeMs = E.timeMs, + .tip = E.absolute, + .in = E.down, }); - }, this, "CTablet"); + }); - hyprListener_button.initCallback(&tablet->events.button, [this] (void* owner, void* data) { - auto E = (wlr_tablet_tool_button_event*)data; + listeners.button = tablet->events.button.registerListener([this](std::any d) { + auto E = std::any_cast(d); tabletEvents.button.emit(SButtonEvent{ - .tool = E->tool, + .tool = E.tool, .tablet = self.lock(), - .timeMs = E->time_msec, - .button = E->button, - .down = E->state == WLR_BUTTON_PRESSED, + .timeMs = E.timeMs, + .button = E.button, + .down = E.down, }); - }, this, "CTablet"); - // clang-format on + }); - deviceName = tablet->base.name ? tablet->base.name : "UNKNOWN"; + deviceName = tablet->getName(); } CTablet::~CTablet() { - if (tablet) - tablet->data = nullptr; - PROTO::tablet->recheckRegisteredDevices(); } -void CTablet::disconnectCallbacks() { - hyprListener_axis.removeCallback(); - hyprListener_button.removeCallback(); - hyprListener_destroy.removeCallback(); - hyprListener_proximity.removeCallback(); - hyprListener_tip.removeCallback(); -} - eHIDType CTablet::getType() { return HID_TYPE_TABLET; } @@ -167,138 +144,111 @@ uint32_t CTabletPad::getCapabilities() { return HID_INPUT_CAPABILITY_TABLET; } -wlr_tablet_pad* CTabletPad::wlr() { - return pad; +SP CTabletPad::aq() { + return pad.lock(); } eHIDType CTabletPad::getType() { return HID_TYPE_TABLET_PAD; } -CTabletPad::CTabletPad(wlr_tablet_pad* pad_) : pad(pad_) { +CTabletPad::CTabletPad(SP pad_) : pad(pad_) { if (!pad) return; - // clang-format off - hyprListener_destroy.initCallback(&pad->base.events.destroy, [this] (void* owner, void* data) { - pad = nullptr; - disconnectCallbacks(); + listeners.destroy = pad->events.destroy.registerListener([this](std::any d) { + pad.reset(); events.destroy.emit(); - }, this, "CTabletPad"); + }); - hyprListener_button.initCallback(&pad->events.button, [this] (void* owner, void* data) { - auto E = (wlr_tablet_pad_button_event*)data; + listeners.button = pad->events.button.registerListener([this](std::any d) { + auto E = std::any_cast(d); padEvents.button.emit(SButtonEvent{ - .timeMs = E->time_msec, - .button = E->button, - .down = E->state == WLR_BUTTON_PRESSED, - .mode = E->mode, - .group = E->group, + .timeMs = E.timeMs, + .button = E.button, + .down = E.down, + .mode = E.mode, + .group = E.group, }); - }, this, "CTabletPad"); + }); - hyprListener_ring.initCallback(&pad->events.ring, [this] (void* owner, void* data) { - auto E = (wlr_tablet_pad_ring_event*)data; + listeners.ring = pad->events.ring.registerListener([this](std::any d) { + auto E = std::any_cast(d); padEvents.ring.emit(SRingEvent{ - .timeMs = E->time_msec, - .finger = E->source == WLR_TABLET_PAD_RING_SOURCE_FINGER, - .ring = E->ring, - .position = E->position, - .mode = E->mode, + .timeMs = E.timeMs, + .finger = E.source == Aquamarine::ITabletPad::AQ_TABLET_PAD_RING_SOURCE_FINGER, + .ring = E.ring, + .position = E.pos, + .mode = E.mode, }); - }, this, "CTabletPad"); + }); - hyprListener_strip.initCallback(&pad->events.strip, [this] (void* owner, void* data) { - auto E = (wlr_tablet_pad_strip_event*)data; + listeners.strip = pad->events.strip.registerListener([this](std::any d) { + auto E = std::any_cast(d); padEvents.strip.emit(SStripEvent{ - .timeMs = E->time_msec, - .finger = E->source == WLR_TABLET_PAD_STRIP_SOURCE_FINGER, - .strip = E->strip, - .position = E->position, - .mode = E->mode, + .timeMs = E.timeMs, + .finger = E.source == Aquamarine::ITabletPad::AQ_TABLET_PAD_STRIP_SOURCE_FINGER, + .strip = E.strip, + .position = E.pos, + .mode = E.mode, }); - }, this, "CTabletPad"); + }); - hyprListener_attach.initCallback(&pad->events.attach_tablet, [this] (void* owner, void* data) { - if (!data) - return; - - padEvents.attach.emit(CTabletTool::fromWlr((wlr_tablet_tool*)data)); - }, this, "CTabletPad"); - // clang-format on + listeners.attach = pad->events.attach.registerListener([this](std::any d) { + ; // TODO: this doesn't do anything in aq atm + }); - deviceName = pad->base.name ? pad->base.name : "UNKNOWN"; + deviceName = pad->getName(); } CTabletPad::~CTabletPad() { PROTO::tablet->recheckRegisteredDevices(); } -void CTabletPad::disconnectCallbacks() { - hyprListener_ring.removeCallback(); - hyprListener_button.removeCallback(); - hyprListener_destroy.removeCallback(); - hyprListener_strip.removeCallback(); - hyprListener_attach.removeCallback(); -} - uint32_t CTabletTool::getCapabilities() { return HID_INPUT_CAPABILITY_POINTER | HID_INPUT_CAPABILITY_TABLET; } -wlr_tablet_tool* CTabletTool::wlr() { - return tool; +SP CTabletTool::aq() { + return tool.lock(); } eHIDType CTabletTool::getType() { return HID_TYPE_TABLET_TOOL; } -CTabletTool::CTabletTool(wlr_tablet_tool* tool_) : tool(tool_) { +CTabletTool::CTabletTool(SP tool_) : tool(tool_) { if (!tool) return; - // clang-format off - hyprListener_destroy.initCallback(&tool->events.destroy, [this] (void* owner, void* data) { - tool = nullptr; - disconnectCallbacks(); + listeners.destroyTool = tool->events.destroy.registerListener([this](std::any d) { + tool.reset(); events.destroy.emit(); - }, this, "CTabletTool"); - // clang-format on + }); - if (tool->tilt) + if (tool->capabilities & Aquamarine::ITabletTool::AQ_TABLET_TOOL_CAPABILITY_TILT) toolCapabilities |= HID_TABLET_TOOL_CAPABILITY_TILT; - if (tool->pressure) + if (tool->capabilities & Aquamarine::ITabletTool::AQ_TABLET_TOOL_CAPABILITY_PRESSURE) toolCapabilities |= HID_TABLET_TOOL_CAPABILITY_PRESSURE; - if (tool->distance) + if (tool->capabilities & Aquamarine::ITabletTool::AQ_TABLET_TOOL_CAPABILITY_DISTANCE) toolCapabilities |= HID_TABLET_TOOL_CAPABILITY_DISTANCE; - if (tool->rotation) + if (tool->capabilities & Aquamarine::ITabletTool::AQ_TABLET_TOOL_CAPABILITY_ROTATION) toolCapabilities |= HID_TABLET_TOOL_CAPABILITY_ROTATION; - if (tool->slider) + if (tool->capabilities & Aquamarine::ITabletTool::AQ_TABLET_TOOL_CAPABILITY_SLIDER) toolCapabilities |= HID_TABLET_TOOL_CAPABILITY_SLIDER; - if (tool->wheel) + if (tool->capabilities & Aquamarine::ITabletTool::AQ_TABLET_TOOL_CAPABILITY_WHEEL) toolCapabilities |= HID_TABLET_TOOL_CAPABILITY_WHEEL; - tool->data = this; - - deviceName = std::to_string(tool->hardware_serial) + std::to_string(tool->hardware_wacom); + deviceName = std::format("{:x}-{:x}", tool->serial, tool->id); } CTabletTool::~CTabletTool() { - if (tool) - tool->data = nullptr; - PROTO::tablet->recheckRegisteredDevices(); } -void CTabletTool::disconnectCallbacks() { - hyprListener_destroy.removeCallback(); - listeners.destroySurface.reset(); -} - SP CTabletTool::getSurface() { return pSurface.lock(); } diff --git a/src/devices/Tablet.hpp b/src/devices/Tablet.hpp index ada2cf89..0efbe796 100644 --- a/src/devices/Tablet.hpp +++ b/src/devices/Tablet.hpp @@ -6,9 +6,9 @@ #include "../helpers/math/Math.hpp" #include "../helpers/math/Math.hpp" -struct wlr_tablet; -struct wlr_tablet_tool; -struct wlr_tablet_pad; +AQUAMARINE_FORWARD(ITablet); +AQUAMARINE_FORWARD(ITabletTool); +AQUAMARINE_FORWARD(ITabletPad); class CTabletTool; class CTabletPad; @@ -21,13 +21,12 @@ class CWLSurfaceResource; */ class CTablet : public IHID { public: - static SP create(wlr_tablet* tablet); - static SP fromWlr(wlr_tablet* tablet); + static SP create(SP tablet); ~CTablet(); - virtual uint32_t getCapabilities(); - virtual eHIDType getType(); - wlr_tablet* wlr(); + virtual uint32_t getCapabilities(); + virtual eHIDType getType(); + SP aq(); enum eTabletToolAxes { HID_TABLET_TOOL_AXIS_X = (1 << 0), @@ -42,46 +41,46 @@ class CTablet : public IHID { }; struct SAxisEvent { - wlr_tablet_tool* tool; - SP tablet; + SP tool; + SP tablet; - uint32_t timeMs = 0; - uint32_t updatedAxes = 0; // eTabletToolAxes - Vector2D axis; - Vector2D axisDelta; - Vector2D tilt; - double pressure = 0; - double distance = 0; - double rotation = 0; - double slider = 0; - double wheelDelta = 0; + uint32_t timeMs = 0; + uint32_t updatedAxes = 0; // eTabletToolAxes + Vector2D axis; + Vector2D axisDelta; + Vector2D tilt; + double pressure = 0; + double distance = 0; + double rotation = 0; + double slider = 0; + double wheelDelta = 0; }; struct SProximityEvent { - wlr_tablet_tool* tool; - SP tablet; + SP tool; + SP tablet; - uint32_t timeMs = 0; - Vector2D proximity; - bool in = false; + uint32_t timeMs = 0; + Vector2D proximity; + bool in = false; }; struct STipEvent { - wlr_tablet_tool* tool; - SP tablet; + SP tool; + SP tablet; - uint32_t timeMs = 0; - Vector2D tip; - bool in = false; + uint32_t timeMs = 0; + Vector2D tip; + bool in = false; }; struct SButtonEvent { - wlr_tablet_tool* tool; - SP tablet; + SP tool; + SP tablet; - uint32_t timeMs = 0; - uint32_t button; - bool down = false; + uint32_t timeMs = 0; + uint32_t button; + bool down = false; }; struct { @@ -100,27 +99,27 @@ class CTablet : public IHID { CBox boundBox; // output-local private: - CTablet(wlr_tablet* tablet); + CTablet(SP tablet); - void disconnectCallbacks(); + WP tablet; - wlr_tablet* tablet = nullptr; - - DYNLISTENER(destroy); - DYNLISTENER(axis); - DYNLISTENER(proximity); - DYNLISTENER(tip); - DYNLISTENER(button); + struct { + CHyprSignalListener destroy; + CHyprSignalListener axis; + CHyprSignalListener proximity; + CHyprSignalListener tip; + CHyprSignalListener button; + } listeners; }; class CTabletPad : public IHID { public: - static SP create(wlr_tablet_pad* pad); + static SP create(SP pad); ~CTabletPad(); - virtual uint32_t getCapabilities(); - virtual eHIDType getType(); - wlr_tablet_pad* wlr(); + virtual uint32_t getCapabilities(); + virtual eHIDType getType(); + SP aq(); struct SButtonEvent { uint32_t timeMs = 0; @@ -159,23 +158,22 @@ class CTabletPad : public IHID { std::string hlName; private: - CTabletPad(wlr_tablet_pad* pad); + CTabletPad(SP pad); - void disconnectCallbacks(); + WP pad; - wlr_tablet_pad* pad = nullptr; - - DYNLISTENER(destroy); - DYNLISTENER(ring); - DYNLISTENER(strip); - DYNLISTENER(button); - DYNLISTENER(attach); + struct { + CHyprSignalListener destroy; + CHyprSignalListener ring; + CHyprSignalListener strip; + CHyprSignalListener button; + CHyprSignalListener attach; + } listeners; }; class CTabletTool : public IHID { public: - static SP create(wlr_tablet_tool* tool); - static SP fromWlr(wlr_tablet_tool* tool); + static SP create(SP tool); ~CTabletTool(); enum eTabletToolType { @@ -198,35 +196,31 @@ class CTabletTool : public IHID { HID_TABLET_TOOL_CAPABILITY_WHEEL = (1 << 5), }; - virtual uint32_t getCapabilities(); - wlr_tablet_tool* wlr(); - virtual eHIDType getType(); - SP getSurface(); - void setSurface(SP); + virtual uint32_t getCapabilities(); + SP aq(); + virtual eHIDType getType(); + SP getSurface(); + void setSurface(SP); - WP self; - Vector2D tilt; - bool active = false; // true if in proximity - uint32_t toolCapabilities = 0; + WP self; + Vector2D tilt; + bool active = false; // true if in proximity + uint32_t toolCapabilities = 0; - bool isDown = false; - std::vector buttonsDown; - Vector2D absolutePos; // last known absolute position. + bool isDown = false; + std::vector buttonsDown; + Vector2D absolutePos; // last known absolute position. - std::string hlName; + std::string hlName; private: - CTabletTool(wlr_tablet_tool* tool); + CTabletTool(SP tool); - void disconnectCallbacks(); - - WP pSurface; - - wlr_tablet_tool* tool = nullptr; - - DYNLISTENER(destroy); + WP pSurface; + WP tool; struct { CHyprSignalListener destroySurface; + CHyprSignalListener destroyTool; } listeners; }; \ No newline at end of file diff --git a/src/devices/TouchDevice.cpp b/src/devices/TouchDevice.cpp index 64c521a2..25b7b503 100644 --- a/src/devices/TouchDevice.cpp +++ b/src/devices/TouchDevice.cpp @@ -1,7 +1,8 @@ #include "TouchDevice.hpp" #include "../defines.hpp" +#include -SP CTouchDevice::create(wlr_touch* touch) { +SP CTouchDevice::create(SP touch) { SP pTouch = SP(new CTouchDevice(touch)); pTouch->self = pTouch; @@ -9,78 +10,63 @@ SP CTouchDevice::create(wlr_touch* touch) { return pTouch; } -CTouchDevice::CTouchDevice(wlr_touch* touch_) : touch(touch_) { +CTouchDevice::CTouchDevice(SP touch_) : touch(touch_) { if (!touch) return; - // clang-format off - hyprListener_destroy.initCallback(&touch->base.events.destroy, [this] (void* owner, void* data) { + listeners.destroy = touch->events.destroy.registerListener([this](std::any d) { events.destroy.emit(); - disconnectCallbacks(); - touch = nullptr; - }, this, "CTouchDevice"); + touch.reset(); + }); - hyprListener_down.initCallback(&touch->events.down, [this] (void* owner, void* data) { - auto E = (wlr_touch_down_event*)data; + listeners.down = touch->events.down.registerListener([this](std::any d) { + auto E = std::any_cast(d); touchEvents.down.emit(SDownEvent{ - .timeMs = E->time_msec, - .touchID = E->touch_id, - .pos = {E->x, E->y}, + .timeMs = E.timeMs, + .touchID = E.touchID, + .pos = E.pos, .device = self.lock(), }); - }, this, "CTouchDevice"); + }); - hyprListener_up.initCallback(&touch->events.up, [this] (void* owner, void* data) { - auto E = (wlr_touch_up_event*)data; + listeners.up = touch->events.up.registerListener([this](std::any d) { + auto E = std::any_cast(d); touchEvents.up.emit(SUpEvent{ - .timeMs = E->time_msec, - .touchID = E->touch_id + .timeMs = E.timeMs, + .touchID = E.touchID, }); - }, this, "CTouchDevice"); + }); - hyprListener_motion.initCallback(&touch->events.motion, [this] (void* owner, void* data) { - auto E = (wlr_touch_motion_event*)data; + listeners.motion = touch->events.move.registerListener([this](std::any d) { + auto E = std::any_cast(d); touchEvents.motion.emit(SMotionEvent{ - .timeMs = E->time_msec, - .touchID = E->touch_id, - .pos = {E->x, E->y}, + .timeMs = E.timeMs, + .touchID = E.touchID, + .pos = E.pos, }); - }, this, "CTouchDevice"); + }); - hyprListener_cancel.initCallback(&touch->events.cancel, [this] (void* owner, void* data) { - auto E = (wlr_touch_cancel_event*)data; + listeners.cancel = touch->events.cancel.registerListener([this](std::any d) { + auto E = std::any_cast(d); touchEvents.cancel.emit(SCancelEvent{ - .timeMs = E->time_msec, - .touchID = E->touch_id + .timeMs = E.timeMs, + .touchID = E.touchID, }); - }, this, "CTouchDevice"); + }); - hyprListener_frame.initCallback(&touch->events.frame, [this] (void* owner, void* data) { - touchEvents.frame.emit(); - }, this, "CTouchDevice"); + listeners.frame = touch->events.frame.registerListener([this](std::any d) { touchEvents.frame.emit(); }); - // clang-format on - - deviceName = touch->base.name ? touch->base.name : "UNKNOWN"; + deviceName = touch->getName(); } bool CTouchDevice::isVirtual() { return false; } -wlr_touch* CTouchDevice::wlr() { - return touch; -} - -void CTouchDevice::disconnectCallbacks() { - hyprListener_destroy.removeCallback(); - hyprListener_down.removeCallback(); - hyprListener_up.removeCallback(); - hyprListener_motion.removeCallback(); - hyprListener_cancel.removeCallback(); - hyprListener_frame.removeCallback(); +SP CTouchDevice::aq() { + return touch.lock(); } diff --git a/src/devices/TouchDevice.hpp b/src/devices/TouchDevice.hpp index 51eb76d4..b18df2d0 100644 --- a/src/devices/TouchDevice.hpp +++ b/src/devices/TouchDevice.hpp @@ -4,22 +4,22 @@ class CTouchDevice : public ITouch { public: - static SP create(wlr_touch* touch); + static SP create(SP touch); - virtual bool isVirtual(); - virtual wlr_touch* wlr(); + virtual bool isVirtual(); + virtual SP aq(); private: - CTouchDevice(wlr_touch* touch); + CTouchDevice(SP touch); - wlr_touch* touch = nullptr; + WP touch; - void disconnectCallbacks(); - - DYNLISTENER(destroy); - DYNLISTENER(down); - DYNLISTENER(up); - DYNLISTENER(motion); - DYNLISTENER(cancel); - DYNLISTENER(frame); + struct { + CHyprSignalListener destroy; + CHyprSignalListener down; + CHyprSignalListener up; + CHyprSignalListener motion; + CHyprSignalListener cancel; + CHyprSignalListener frame; + } listeners; }; \ No newline at end of file diff --git a/src/devices/VirtualKeyboard.cpp b/src/devices/VirtualKeyboard.cpp index e2be0078..654ca9f5 100644 --- a/src/devices/VirtualKeyboard.cpp +++ b/src/devices/VirtualKeyboard.cpp @@ -14,58 +14,37 @@ CVirtualKeyboard::CVirtualKeyboard(SP keeb_) : keybo if (!keeb_) return; - auto keeb = keeb_->wlr(); - - // clang-format off - hyprListener_destroy.initCallback(&keeb->base.events.destroy, [this] (void* owner, void* data) { - disconnectCallbacks(); + listeners.destroy = keeb_->events.destroy.registerListener([this](std::any d) { keyboard.reset(); - events.destroy.emit(); - }, this, "CVirtualKeyboard"); + events.destroy.emit(); + }); - hyprListener_key.initCallback(&keeb->events.key, [this] (void* owner, void* data) { - auto E = (wlr_keyboard_key_event*)data; - - keyboardEvents.key.emit(SKeyEvent{ - .timeMs = E->time_msec, - .keycode = E->keycode, - .updateMods = E->update_state, - .state = E->state, + listeners.key = keeb_->events.key.registerListener([this](std::any d) { keyboardEvents.key.emit(d); }); + listeners.modifiers = keeb_->events.modifiers.registerListener([this](std::any d) { + auto E = std::any_cast(d); + updateModifiers(E.depressed, E.latched, E.locked, E.group); + keyboardEvents.modifiers.emit(SModifiersEvent{ + .depressed = modifiersState.depressed, + .latched = modifiersState.latched, + .locked = modifiersState.locked, + .group = modifiersState.group, }); - }, this, "CVirtualKeyboard"); + }); + listeners.keymap = keeb_->events.keymap.registerListener([this](std::any d) { + auto E = std::any_cast(d); + xkbKeymap = xkb_keymap_ref(E.keymap); + keyboardEvents.keymap.emit(d); + }); - hyprListener_keymap.initCallback(&keeb->events.keymap, [this] (void* owner, void* data) { - keyboardEvents.keymap.emit(); - }, this, "CVirtualKeyboard"); - - hyprListener_modifiers.initCallback(&keeb->events.modifiers, [this] (void* owner, void* data) { - keyboardEvents.modifiers.emit(); - }, this, "CVirtualKeyboard"); - - hyprListener_repeatInfo.initCallback(&keeb->events.repeat_info, [this] (void* owner, void* data) { - keyboardEvents.repeatInfo.emit(); - }, this, "CVirtualKeyboard"); - // clang-format on - - deviceName = keeb->base.name ? keeb->base.name : "UNKNOWN"; + deviceName = keeb_->name; } bool CVirtualKeyboard::isVirtual() { return true; } -wlr_keyboard* CVirtualKeyboard::wlr() { - if (keyboard.expired()) - return nullptr; - return keyboard->wlr(); -} - -void CVirtualKeyboard::disconnectCallbacks() { - hyprListener_destroy.removeCallback(); - hyprListener_key.removeCallback(); - hyprListener_keymap.removeCallback(); - hyprListener_repeatInfo.removeCallback(); - hyprListener_modifiers.removeCallback(); +SP CVirtualKeyboard::aq() { + return nullptr; } wl_client* CVirtualKeyboard::getClient() { diff --git a/src/devices/VirtualKeyboard.hpp b/src/devices/VirtualKeyboard.hpp index 5ef88dd3..12a3907c 100644 --- a/src/devices/VirtualKeyboard.hpp +++ b/src/devices/VirtualKeyboard.hpp @@ -6,23 +6,22 @@ class CVirtualKeyboardV1Resource; class CVirtualKeyboard : public IKeyboard { public: - static SP create(SP keeb); + static SP create(SP keeb); - virtual bool isVirtual(); - virtual wlr_keyboard* wlr(); + virtual bool isVirtual(); + virtual SP aq(); - wl_client* getClient(); + wl_client* getClient(); private: CVirtualKeyboard(SP keeb); WP keyboard; - void disconnectCallbacks(); - - DYNLISTENER(destroy); - DYNLISTENER(key); - DYNLISTENER(modifiers); - DYNLISTENER(keymap); - DYNLISTENER(repeatInfo); + struct { + CHyprSignalListener destroy; + CHyprSignalListener key; + CHyprSignalListener modifiers; + CHyprSignalListener keymap; + } listeners; }; diff --git a/src/devices/VirtualPointer.cpp b/src/devices/VirtualPointer.cpp index c8ee3332..faca27dc 100644 --- a/src/devices/VirtualPointer.cpp +++ b/src/devices/VirtualPointer.cpp @@ -1,5 +1,6 @@ #include "VirtualPointer.hpp" #include "../protocols/VirtualPointer.hpp" +#include SP CVirtualPointer::create(SP resource) { SP pPointer = SP(new CVirtualPointer(resource)); @@ -13,165 +14,32 @@ CVirtualPointer::CVirtualPointer(SP resource) : point if (!resource->good()) return; - auto mouse = resource->wlr(); - - // clang-format off - hyprListener_destroy.initCallback(&mouse->base.events.destroy, [this] (void* owner, void* data) { - disconnectCallbacks(); + listeners.destroy = pointer->events.destroy.registerListener([this](std::any d) { + pointer.reset(); events.destroy.emit(); - }, this, "CVirtualPointer"); + }); - hyprListener_motion.initCallback(&mouse->events.motion, [this] (void* owner, void* data) { - auto E = (wlr_pointer_motion_event*)data; + listeners.motion = pointer->events.move.registerListener([this](std::any d) { pointerEvents.motion.emit(d); }); + listeners.motionAbsolute = pointer->events.warp.registerListener([this](std::any d) { pointerEvents.motionAbsolute.emit(d); }); + listeners.button = pointer->events.button.registerListener([this](std::any d) { pointerEvents.button.emit(d); }); + listeners.axis = pointer->events.axis.registerListener([this](std::any d) { pointerEvents.axis.emit(d); }); + listeners.frame = pointer->events.frame.registerListener([this](std::any d) { pointerEvents.frame.emit(); }); + listeners.swipeBegin = pointer->events.swipeBegin.registerListener([this](std::any d) { pointerEvents.swipeBegin.emit(d); }); + listeners.swipeEnd = pointer->events.swipeEnd.registerListener([this](std::any d) { pointerEvents.swipeEnd.emit(d); }); + listeners.swipeUpdate = pointer->events.swipeUpdate.registerListener([this](std::any d) { pointerEvents.swipeUpdate.emit(d); }); + listeners.pinchBegin = pointer->events.pinchBegin.registerListener([this](std::any d) { pointerEvents.pinchBegin.emit(d); }); + listeners.pinchEnd = pointer->events.pinchEnd.registerListener([this](std::any d) { pointerEvents.pinchEnd.emit(d); }); + listeners.pinchUpdate = pointer->events.pinchUpdate.registerListener([this](std::any d) { pointerEvents.pinchUpdate.emit(d); }); + listeners.holdBegin = pointer->events.holdBegin.registerListener([this](std::any d) { pointerEvents.holdBegin.emit(d); }); + listeners.holdEnd = pointer->events.holdEnd.registerListener([this](std::any d) { pointerEvents.holdEnd.emit(d); }); - pointerEvents.motion.emit(SMotionEvent{ - .timeMs = E->time_msec, - .delta = {E->delta_x, E->delta_y}, - .unaccel = {E->unaccel_dx, E->unaccel_dy}, - }); - }, this, "CVirtualPointer"); - - hyprListener_motionAbsolute.initCallback(&mouse->events.motion_absolute, [this] (void* owner, void* data) { - auto E = (wlr_pointer_motion_absolute_event*)data; - - pointerEvents.motionAbsolute.emit(SMotionAbsoluteEvent{ - .timeMs = E->time_msec, - .absolute = {E->x, E->y}, - .device = self.lock(), - }); - }, this, "CVirtualPointer"); - - hyprListener_button.initCallback(&mouse->events.button, [this] (void* owner, void* data) { - auto E = (wlr_pointer_button_event*)data; - - pointerEvents.button.emit(SButtonEvent{ - .timeMs = E->time_msec, - .button = E->button, - .state = (wl_pointer_button_state)E->state, - }); - }, this, "CVirtualPointer"); - - hyprListener_axis.initCallback(&mouse->events.axis, [this] (void* owner, void* data) { - auto E = (wlr_pointer_axis_event*)data; - - pointerEvents.axis.emit(SAxisEvent{ - .timeMs = E->time_msec, - .source = E->source, - .axis = E->orientation, - .relativeDirection = E->relative_direction, - .delta = E->delta, - .deltaDiscrete = E->delta_discrete, - }); - }, this, "CVirtualPointer"); - - hyprListener_frame.initCallback(&mouse->events.frame, [this] (void* owner, void* data) { - pointerEvents.frame.emit(); - }, this, "CVirtualPointer"); - - hyprListener_swipeBegin.initCallback(&mouse->events.swipe_begin, [this] (void* owner, void* data) { - auto E = (wlr_pointer_swipe_begin_event*)data; - - pointerEvents.swipeBegin.emit(SSwipeBeginEvent{ - .timeMs = E->time_msec, - .fingers = E->fingers, - }); - }, this, "CVirtualPointer"); - - hyprListener_swipeEnd.initCallback(&mouse->events.swipe_end, [this] (void* owner, void* data) { - auto E = (wlr_pointer_swipe_end_event*)data; - - pointerEvents.swipeEnd.emit(SSwipeEndEvent{ - .timeMs = E->time_msec, - .cancelled = E->cancelled, - }); - }, this, "CVirtualPointer"); - - hyprListener_swipeUpdate.initCallback(&mouse->events.swipe_update, [this] (void* owner, void* data) { - auto E = (wlr_pointer_swipe_update_event*)data; - - pointerEvents.swipeUpdate.emit(SSwipeUpdateEvent{ - .timeMs = E->time_msec, - .fingers = E->fingers, - .delta = {E->dx, E->dy}, - }); - }, this, "CVirtualPointer"); - - hyprListener_pinchBegin.initCallback(&mouse->events.pinch_begin, [this] (void* owner, void* data) { - auto E = (wlr_pointer_pinch_begin_event*)data; - - pointerEvents.pinchBegin.emit(SPinchBeginEvent{ - .timeMs = E->time_msec, - .fingers = E->fingers, - }); - }, this, "CVirtualPointer"); - - hyprListener_pinchEnd.initCallback(&mouse->events.pinch_end, [this] (void* owner, void* data) { - auto E = (wlr_pointer_pinch_end_event*)data; - - pointerEvents.pinchEnd.emit(SPinchEndEvent{ - .timeMs = E->time_msec, - .cancelled = E->cancelled, - }); - }, this, "CVirtualPointer"); - - hyprListener_pinchUpdate.initCallback(&mouse->events.pinch_update, [this] (void* owner, void* data) { - auto E = (wlr_pointer_pinch_update_event*)data; - - pointerEvents.pinchUpdate.emit(SPinchUpdateEvent{ - .timeMs = E->time_msec, - .fingers = E->fingers, - .delta = {E->dx, E->dy}, - .scale = E->scale, - .rotation = E->rotation, - }); - }, this, "CVirtualPointer"); - - hyprListener_holdBegin.initCallback(&mouse->events.hold_begin, [this] (void* owner, void* data) { - auto E = (wlr_pointer_hold_begin_event*)data; - - pointerEvents.holdBegin.emit(SHoldBeginEvent{ - .timeMs = E->time_msec, - .fingers = E->fingers, - }); - }, this, "CVirtualPointer"); - - hyprListener_holdEnd.initCallback(&mouse->events.hold_end, [this] (void* owner, void* data) { - auto E = (wlr_pointer_hold_end_event*)data; - - pointerEvents.holdEnd.emit(SHoldEndEvent{ - .timeMs = E->time_msec, - .cancelled = E->cancelled, - }); - }, this, "CVirtualPointer"); - - // clang-format on - - deviceName = mouse->base.name ? mouse->base.name : "UNKNOWN"; + deviceName = pointer->name; } bool CVirtualPointer::isVirtual() { return true; } -void CVirtualPointer::disconnectCallbacks() { - hyprListener_destroy.removeCallback(); - hyprListener_motion.removeCallback(); - hyprListener_motionAbsolute.removeCallback(); - hyprListener_button.removeCallback(); - hyprListener_axis.removeCallback(); - hyprListener_frame.removeCallback(); - hyprListener_swipeBegin.removeCallback(); - hyprListener_swipeEnd.removeCallback(); - hyprListener_swipeUpdate.removeCallback(); - hyprListener_pinchBegin.removeCallback(); - hyprListener_pinchEnd.removeCallback(); - hyprListener_pinchUpdate.removeCallback(); - hyprListener_holdBegin.removeCallback(); - hyprListener_holdEnd.removeCallback(); -} - -wlr_pointer* CVirtualPointer::wlr() { - if (pointer.expired()) - return nullptr; - return pointer->wlr(); +SP CVirtualPointer::aq() { + return nullptr; } diff --git a/src/devices/VirtualPointer.hpp b/src/devices/VirtualPointer.hpp index b22c8bf2..1ecfd842 100644 --- a/src/devices/VirtualPointer.hpp +++ b/src/devices/VirtualPointer.hpp @@ -6,33 +6,34 @@ class CVirtualPointerV1Resource; class CVirtualPointer : public IPointer { public: - static SP create(SP resource); + static SP create(SP resource); - virtual bool isVirtual(); - virtual wlr_pointer* wlr(); + virtual bool isVirtual(); + virtual SP aq(); private: CVirtualPointer(SP); WP pointer; - void disconnectCallbacks(); + struct { + CHyprSignalListener destroy; - DYNLISTENER(destroy); - DYNLISTENER(motion); - DYNLISTENER(motionAbsolute); - DYNLISTENER(button); - DYNLISTENER(axis); - DYNLISTENER(frame); + CHyprSignalListener motion; + CHyprSignalListener motionAbsolute; + CHyprSignalListener button; + CHyprSignalListener axis; + CHyprSignalListener frame; - DYNLISTENER(swipeBegin); - DYNLISTENER(swipeEnd); - DYNLISTENER(swipeUpdate); + CHyprSignalListener swipeBegin; + CHyprSignalListener swipeEnd; + CHyprSignalListener swipeUpdate; - DYNLISTENER(pinchBegin); - DYNLISTENER(pinchEnd); - DYNLISTENER(pinchUpdate); + CHyprSignalListener pinchBegin; + CHyprSignalListener pinchEnd; + CHyprSignalListener pinchUpdate; - DYNLISTENER(holdBegin); - DYNLISTENER(holdEnd); + CHyprSignalListener holdBegin; + CHyprSignalListener holdEnd; + } listeners; }; \ No newline at end of file diff --git a/src/events/Devices.cpp b/src/events/Devices.cpp deleted file mode 100644 index fedc844e..00000000 --- a/src/events/Devices.cpp +++ /dev/null @@ -1,50 +0,0 @@ -#include "Events.hpp" - -#include "../Compositor.hpp" -#include "../helpers/WLClasses.hpp" -#include "../managers/input/InputManager.hpp" -#include "../render/Renderer.hpp" - -// ---------------------------------------------------- // -// _____ ________ _______ _____ ______ _____ // -// | __ \| ____\ \ / /_ _/ ____| ____|/ ____| // -// | | | | |__ \ \ / / | || | | |__ | (___ // -// | | | | __| \ \/ / | || | | __| \___ \ // -// | |__| | |____ \ / _| || |____| |____ ____) | // -// |_____/|______| \/ |_____\_____|______|_____/ // -// // -// ---------------------------------------------------- // - -void Events::listener_newInput(wl_listener* listener, void* data) { - const auto DEVICE = (wlr_input_device*)data; - - switch (DEVICE->type) { - case WLR_INPUT_DEVICE_KEYBOARD: - Debug::log(LOG, "Attached a keyboard with name {}", DEVICE->name); - g_pInputManager->newKeyboard(DEVICE); - break; - case WLR_INPUT_DEVICE_POINTER: - Debug::log(LOG, "Attached a mouse with name {}", DEVICE->name); - g_pInputManager->newMouse(DEVICE); - break; - case WLR_INPUT_DEVICE_TOUCH: - Debug::log(LOG, "Attached a touch device with name {}", DEVICE->name); - g_pInputManager->newTouchDevice(DEVICE); - break; - case WLR_INPUT_DEVICE_TABLET: - Debug::log(LOG, "Attached a tablet with name {}", DEVICE->name); - g_pInputManager->newTablet(DEVICE); - break; - case WLR_INPUT_DEVICE_TABLET_PAD: - Debug::log(LOG, "Attached a tablet pad with name {}", DEVICE->name); - g_pInputManager->newTabletPad(DEVICE); - break; - case WLR_INPUT_DEVICE_SWITCH: - Debug::log(LOG, "Attached a switch device with name {}", DEVICE->name); - g_pInputManager->newSwitch(DEVICE); - break; - default: Debug::log(WARN, "Unrecognized input device plugged in: {}", DEVICE->name); break; - } - - g_pInputManager->updateCapabilities(); -} diff --git a/src/events/Events.hpp b/src/events/Events.hpp index f8eb9d2f..8e73f54a 100644 --- a/src/events/Events.hpp +++ b/src/events/Events.hpp @@ -8,16 +8,6 @@ // namespace Events { - // Monitor events - LISTENER(change); - LISTENER(newOutput); - - // DRM events - LISTENER(leaseRequest); - - // Layer events - LISTENER(newLayerSurface); - // Window events DYNLISTENFUNC(commitWindow); DYNLISTENFUNC(mapWindow); @@ -35,15 +25,6 @@ namespace Events { DYNLISTENFUNC(setOverrideRedirect); DYNLISTENFUNC(ackConfigure); - LISTENER(newInput); - - // Virt Ptr - LISTENER(newVirtPtr); - - // Various - LISTENER(requestSetSel); - LISTENER(requestSetPrimarySel); - // Monitor part 2 the sequel DYNLISTENFUNC(monitorFrame); DYNLISTENFUNC(monitorDestroy); @@ -52,16 +33,4 @@ namespace Events { DYNLISTENFUNC(monitorNeedsFrame); DYNLISTENFUNC(monitorCommit); DYNLISTENFUNC(monitorBind); - - // XWayland - LISTENER(surfaceXWayland); - - // Renderer destroy - LISTENER(RendererDestroy); - - // session - LISTENER(sessionActive); - - // Session Lock - LISTENER(newSessionLock); }; diff --git a/src/events/Misc.cpp b/src/events/Misc.cpp deleted file mode 100644 index 32f894ec..00000000 --- a/src/events/Misc.cpp +++ /dev/null @@ -1,54 +0,0 @@ -#include "Events.hpp" - -#include "../Compositor.hpp" -#include "../helpers/WLClasses.hpp" -#include "../managers/input/InputManager.hpp" -#include "../render/Renderer.hpp" -#include "../managers/CursorManager.hpp" - -// ------------------------------ // -// __ __ _____ _____ _____ // -// | \/ |_ _|/ ____|/ ____| // -// | \ / | | | | (___ | | // -// | |\/| | | | \___ \| | // -// | | | |_| |_ ____) | |____ // -// |_| |_|_____|_____/ \_____| // -// // -// ------------------------------ // - -void Events::listener_leaseRequest(wl_listener* listener, void* data) { - const auto REQUEST = (wlr_drm_lease_request_v1*)data; - struct wlr_drm_lease_v1* lease = wlr_drm_lease_request_v1_grant(REQUEST); - if (!lease) { - Debug::log(ERR, "Failed to grant lease request!"); - wlr_drm_lease_request_v1_reject(REQUEST); - } -} - -void Events::listener_RendererDestroy(wl_listener* listener, void* data) { - Debug::log(LOG, "!!Renderer destroyed!!"); -} - -void Events::listener_sessionActive(wl_listener* listener, void* data) { - if (g_pCompositor->m_sWLRSession->active) { - Debug::log(LOG, "Session got activated!"); - - g_pCompositor->m_bSessionActive = true; - - for (auto& m : g_pCompositor->m_vMonitors) { - g_pCompositor->scheduleFrameForMonitor(m.get()); - g_pHyprRenderer->applyMonitorRule(m.get(), &m->activeMonitorRule, true); - } - - g_pConfigManager->m_bWantsMonitorReload = true; - } else { - Debug::log(LOG, "Session got inactivated!"); - - g_pCompositor->m_bSessionActive = false; - - for (auto& m : g_pCompositor->m_vMonitors) { - m->noFrameSchedule = true; - m->framesToSkip = 1; - } - } -} diff --git a/src/events/Monitors.cpp b/src/events/Monitors.cpp index 2536e1f7..40b6f17e 100644 --- a/src/events/Monitors.cpp +++ b/src/events/Monitors.cpp @@ -5,6 +5,7 @@ #include "Events.hpp" #include "../debug/HyprCtl.hpp" #include "../config/ConfigValue.hpp" +#include // --------------------------------------------------------- // // __ __ ____ _ _ _____ _______ ____ _____ _____ // @@ -16,99 +17,10 @@ // // // --------------------------------------------------------- // -static void checkDefaultCursorWarp(SP PNEWMONITOR, std::string monitorName) { - - static auto PCURSORMONITOR = CConfigValue("cursor:default_monitor"); - static auto firstMonitorAdded = std::chrono::steady_clock::now(); - static bool cursorDefaultDone = false; - static bool firstLaunch = true; - - const auto POS = PNEWMONITOR->middle(); - - // by default, cursor should be set to first monitor detected - // this is needed as a default if the monitor given in config above doesn't exist - if (firstLaunch) { - firstLaunch = false; - g_pCompositor->warpCursorTo(POS, true); - g_pInputManager->refocus(); - } - - if (cursorDefaultDone || *PCURSORMONITOR == STRVAL_EMPTY) - return; - - // after 10s, don't set cursor to default monitor - auto timePassedSec = std::chrono::duration_cast(std::chrono::steady_clock::now() - firstMonitorAdded); - if (timePassedSec.count() > 10) { - cursorDefaultDone = true; - return; - } - - if (*PCURSORMONITOR == monitorName) { - cursorDefaultDone = true; - g_pCompositor->warpCursorTo(POS, true); - g_pInputManager->refocus(); - } -} - -void Events::listener_newOutput(wl_listener* listener, void* data) { - // new monitor added, let's accommodate for that. - const auto OUTPUT = (wlr_output*)data; - - if (!OUTPUT->name) { - Debug::log(ERR, "New monitor has no name?? Ignoring"); - return; - } - - // add it to real - auto PNEWMONITOR = g_pCompositor->m_vRealMonitors.emplace_back(makeShared()); - if (std::string("HEADLESS-1") == OUTPUT->name) - g_pCompositor->m_pUnsafeOutput = PNEWMONITOR.get(); - - PNEWMONITOR->output = OUTPUT; - PNEWMONITOR->self = PNEWMONITOR; - const bool FALLBACK = g_pCompositor->m_pUnsafeOutput ? OUTPUT == g_pCompositor->m_pUnsafeOutput->output : false; - PNEWMONITOR->ID = FALLBACK ? -1 : g_pCompositor->getNextAvailableMonitorID(OUTPUT->name); - PNEWMONITOR->isUnsafeFallback = FALLBACK; - - EMIT_HOOK_EVENT("newMonitor", PNEWMONITOR); - - if (!FALLBACK) - PNEWMONITOR->onConnect(false); - - if (!PNEWMONITOR->m_bEnabled || FALLBACK) - return; - - // ready to process if we have a real monitor - - if ((!g_pHyprRenderer->m_pMostHzMonitor || PNEWMONITOR->refreshRate > g_pHyprRenderer->m_pMostHzMonitor->refreshRate) && PNEWMONITOR->m_bEnabled) - g_pHyprRenderer->m_pMostHzMonitor = PNEWMONITOR.get(); - - g_pCompositor->m_bReadyToProcess = true; - - g_pConfigManager->m_bWantsMonitorReload = true; - g_pCompositor->scheduleFrameForMonitor(PNEWMONITOR.get()); - - checkDefaultCursorWarp(PNEWMONITOR, OUTPUT->name); - - for (auto& w : g_pCompositor->m_vWindows) { - if (w->m_iMonitorID == PNEWMONITOR->ID) { - w->m_iLastSurfaceMonitorID = -1; - w->updateSurfaceScaleTransformDetails(); - } - } -} - void Events::listener_monitorFrame(void* owner, void* data) { - if (g_pCompositor->m_bExitTriggered) { - // Only signal cleanup once - g_pCompositor->m_bExitTriggered = false; - g_pCompositor->cleanup(); - return; - } - CMonitor* const PMONITOR = (CMonitor*)owner; - if ((g_pCompositor->m_sWLRSession && !g_pCompositor->m_sWLRSession->active) || !g_pCompositor->m_bSessionActive || g_pCompositor->m_bUnsafeState) { + if ((g_pCompositor->m_pAqBackend->hasSession() && !g_pCompositor->m_pAqBackend->session->active) || !g_pCompositor->m_bSessionActive || g_pCompositor->m_bUnsafeState) { Debug::log(WARN, "Attempted to render frame on inactive session!"); if (g_pCompositor->m_bUnsafeState && std::ranges::any_of(g_pCompositor->m_vMonitors.begin(), g_pCompositor->m_vMonitors.end(), [&](auto& m) { @@ -172,12 +84,10 @@ void Events::listener_monitorFrame(void* owner, void* data) { } void Events::listener_monitorDestroy(void* owner, void* data) { - const auto OUTPUT = (wlr_output*)data; - - CMonitor* pMonitor = nullptr; + CMonitor* pMonitor = (CMonitor*)owner; for (auto& m : g_pCompositor->m_vRealMonitors) { - if (m->output == OUTPUT) { + if (m->output == pMonitor->output) { pMonitor = m.get(); break; } @@ -188,9 +98,6 @@ void Events::listener_monitorDestroy(void* owner, void* data) { Debug::log(LOG, "Destroy called for monitor {}", pMonitor->output->name); - if (pMonitor->output->idle_frame) - wl_event_source_remove(pMonitor->output->idle_frame); - pMonitor->onDisconnect(true); pMonitor->output = nullptr; @@ -201,44 +108,18 @@ void Events::listener_monitorDestroy(void* owner, void* data) { std::erase_if(g_pCompositor->m_vRealMonitors, [&](SP& el) { return el.get() == pMonitor; }); } -void Events::listener_monitorStateRequest(void* owner, void* data) { - const auto PMONITOR = (CMonitor*)owner; - const auto E = (wlr_output_event_request_state*)data; - - if (!PMONITOR->createdByUser) - return; - - const auto SIZE = E->state->mode ? Vector2D{E->state->mode->width, E->state->mode->height} : Vector2D{E->state->custom_mode.width, E->state->custom_mode.height}; - - PMONITOR->forceSize = SIZE; - - SMonitorRule rule = PMONITOR->activeMonitorRule; - rule.resolution = SIZE; - - g_pHyprRenderer->applyMonitorRule(PMONITOR, &rule); -} - -void Events::listener_monitorDamage(void* owner, void* data) { - const auto PMONITOR = (CMonitor*)owner; - const auto E = (wlr_output_event_damage*)data; - - PMONITOR->addDamage(E->damage); -} - void Events::listener_monitorNeedsFrame(void* owner, void* data) { const auto PMONITOR = (CMonitor*)owner; - g_pCompositor->scheduleFrameForMonitor(PMONITOR); + g_pCompositor->scheduleFrameForMonitor(PMONITOR, Aquamarine::IOutput::AQ_SCHEDULE_NEEDS_FRAME); } void Events::listener_monitorCommit(void* owner, void* data) { const auto PMONITOR = (CMonitor*)owner; - const auto E = (wlr_output_event_commit*)data; - - if (E->state->committed & WLR_OUTPUT_STATE_BUFFER) { - g_pProtocolManager->m_pScreencopyProtocolManager->onOutputCommit(PMONITOR, E); - g_pProtocolManager->m_pToplevelExportProtocolManager->onOutputCommit(PMONITOR, E); + if (true) { // FIXME: E->state->committed & WLR_OUTPUT_STATE_BUFFER + g_pProtocolManager->m_pScreencopyProtocolManager->onOutputCommit(PMONITOR); + g_pProtocolManager->m_pToplevelExportProtocolManager->onOutputCommit(PMONITOR); } } diff --git a/src/helpers/CursorShapes.hpp b/src/helpers/CursorShapes.hpp new file mode 100644 index 00000000..6f3c8a0e --- /dev/null +++ b/src/helpers/CursorShapes.hpp @@ -0,0 +1,43 @@ +#pragma once + +#include + +// clang-format off +constexpr std::array CURSOR_SHAPE_NAMES = { + "invalid", + "default", + "context-menu", + "help", + "pointer", + "progress", + "wait", + "cell", + "crosshair", + "text", + "vertical-text", + "alias", + "copy", + "move", + "no-drop", + "not-allowed", + "grab", + "grabbing", + "e-resize", + "n-resize", + "ne-resize", + "nw-resize", + "s-resize", + "se-resize", + "sw-resize", + "w-resize", + "ew-resize", + "ns-resize", + "nesw-resize", + "nwse-resize", + "col-resize", + "row-resize", + "all-scroll", + "zoom-in", + "zoom-out", +}; +// clang-format on \ No newline at end of file diff --git a/src/helpers/Format.cpp b/src/helpers/Format.cpp index 5251002c..afc8b1c5 100644 --- a/src/helpers/Format.cpp +++ b/src/helpers/Format.cpp @@ -3,6 +3,8 @@ #include "../includes.hpp" #include "debug/Log.hpp" #include "../macros.hpp" +#include +#include /* DRM formats are LE, while OGL is BE. The two primary formats @@ -309,3 +311,17 @@ uint32_t FormatUtils::glFormatToType(uint32_t gl) { #endif GL_UNSIGNED_BYTE; } + +std::string FormatUtils::drmFormatName(DRMFormat drm) { + auto n = drmGetFormatName(drm); + std::string name = n; + free(n); + return name; +} + +std::string FormatUtils::drmModifierName(uint64_t mod) { + auto n = drmGetFormatModifierName(mod); + std::string name = n; + free(n); + return name; +} diff --git a/src/helpers/Format.hpp b/src/helpers/Format.hpp index a1ef53f5..8269c5c3 100644 --- a/src/helpers/Format.hpp +++ b/src/helpers/Format.hpp @@ -1,7 +1,9 @@ #pragma once #include +#include #include "math/Math.hpp" +#include typedef uint32_t DRMFormat; typedef uint32_t SHMFormat; @@ -18,10 +20,7 @@ struct SPixelFormat { Vector2D blockSize; }; -struct SDRMFormat { - uint32_t format = 0; - std::vector mods; -}; +typedef Aquamarine::SDRMFormat SDRMFormat; namespace FormatUtils { SHMFormat drmToShm(DRMFormat drm); @@ -34,4 +33,6 @@ namespace FormatUtils { int minStride(const SPixelFormat* const fmt, int32_t width); uint32_t drmFormatToGL(DRMFormat drm); uint32_t glFormatToType(uint32_t gl); + std::string drmFormatName(DRMFormat drm); + std::string drmModifierName(uint64_t mod); }; diff --git a/src/helpers/MiscFunctions.cpp b/src/helpers/MiscFunctions.cpp index 712e4e50..53c0dc13 100644 --- a/src/helpers/MiscFunctions.cpp +++ b/src/helpers/MiscFunctions.cpp @@ -4,9 +4,12 @@ #include "../Compositor.hpp" #include "../managers/TokenManager.hpp" #include +#include +#include #include #include #include +#include #include #include #include diff --git a/src/helpers/MiscFunctions.hpp b/src/helpers/MiscFunctions.hpp index 33be7965..49e3bced 100644 --- a/src/helpers/MiscFunctions.hpp +++ b/src/helpers/MiscFunctions.hpp @@ -3,7 +3,6 @@ #include #include #include -#include #include "math/Math.hpp" #include #include diff --git a/src/helpers/Monitor.cpp b/src/helpers/Monitor.cpp index 20c2e81e..a23b9861 100644 --- a/src/helpers/Monitor.cpp +++ b/src/helpers/Monitor.cpp @@ -1,12 +1,18 @@ #include "Monitor.hpp" #include "MiscFunctions.hpp" +#include "math/Math.hpp" #include "../Compositor.hpp" #include "../config/ConfigValue.hpp" #include "../protocols/GammaControl.hpp" #include "../devices/ITouch.hpp" #include "../protocols/LayerShell.hpp" #include "../protocols/PresentationTime.hpp" +#include "../protocols/DRMLease.hpp" +#include "../protocols/core/Output.hpp" #include "../managers/PointerManager.hpp" +#include "../protocols/core/Compositor.hpp" +#include "sync/SyncTimeline.hpp" +#include #include using namespace Hyprutils::String; @@ -21,62 +27,73 @@ CMonitor::CMonitor() : state(this) { } CMonitor::~CMonitor() { - hyprListener_monitorDestroy.removeCallback(); - hyprListener_monitorFrame.removeCallback(); - hyprListener_monitorStateRequest.removeCallback(); - hyprListener_monitorDamage.removeCallback(); - hyprListener_monitorNeedsFrame.removeCallback(); - hyprListener_monitorCommit.removeCallback(); - hyprListener_monitorBind.removeCallback(); - events.destroy.emit(); } -static void onPresented(void* owner, void* data) { - const auto PMONITOR = (CMonitor*)owner; - auto E = (wlr_output_event_present*)data; - - PROTO::presentation->onPresented(PMONITOR, E->when, E->refresh, E->seq, E->flags); -} - void CMonitor::onConnect(bool noRule) { - hyprListener_monitorDestroy.removeCallback(); - hyprListener_monitorFrame.removeCallback(); - hyprListener_monitorStateRequest.removeCallback(); - hyprListener_monitorDamage.removeCallback(); - hyprListener_monitorNeedsFrame.removeCallback(); - hyprListener_monitorCommit.removeCallback(); - hyprListener_monitorBind.removeCallback(); - hyprListener_monitorPresented.removeCallback(); - hyprListener_monitorFrame.initCallback(&output->events.frame, &Events::listener_monitorFrame, this, "CMonitor"); - hyprListener_monitorDestroy.initCallback(&output->events.destroy, &Events::listener_monitorDestroy, this, "CMonitor"); - hyprListener_monitorStateRequest.initCallback(&output->events.request_state, &Events::listener_monitorStateRequest, this, "CMonitor"); - hyprListener_monitorDamage.initCallback(&output->events.damage, &Events::listener_monitorDamage, this, "CMonitor"); - hyprListener_monitorNeedsFrame.initCallback(&output->events.needs_frame, &Events::listener_monitorNeedsFrame, this, "CMonitor"); - hyprListener_monitorCommit.initCallback(&output->events.commit, &Events::listener_monitorCommit, this, "CMonitor"); - hyprListener_monitorBind.initCallback(&output->events.bind, &Events::listener_monitorBind, this, "CMonitor"); - hyprListener_monitorPresented.initCallback(&output->events.present, ::onPresented, this, "CMonitor"); - tearingState.canTear = wlr_backend_is_drm(output->backend); // tearing only works on drm + if (output->supportsExplicit) { + inTimeline = CSyncTimeline::create(output->getBackend()->drmFD()); + outTimeline = CSyncTimeline::create(output->getBackend()->drmFD()); + } + + listeners.frame = output->events.frame.registerListener([this](std::any d) { Events::listener_monitorFrame(this, nullptr); }); + listeners.destroy = output->events.destroy.registerListener([this](std::any d) { Events::listener_monitorDestroy(this, nullptr); }); + listeners.commit = output->events.commit.registerListener([this](std::any d) { Events::listener_monitorCommit(this, nullptr); }); + listeners.needsFrame = + output->events.needsFrame.registerListener([this](std::any d) { g_pCompositor->scheduleFrameForMonitor(this, Aquamarine::IOutput::AQ_SCHEDULE_NEEDS_FRAME); }); + listeners.presented = output->events.present.registerListener([this](std::any d) { + auto E = std::any_cast(d); + PROTO::presentation->onPresented(this, E.when, E.refresh, E.seq, E.flags); + }); + + listeners.state = output->events.state.registerListener([this](std::any d) { + auto E = std::any_cast(d); + + if (E.size == Vector2D{}) { + // an indication to re-set state + // we can't do much for createdByUser displays I think + if (createdByUser) + return; + + Debug::log(LOG, "Reapplying monitor rule for {} from a state request", szName); + g_pHyprRenderer->applyMonitorRule(this, &activeMonitorRule, true); + return; + } + + if (!createdByUser) + return; + + const auto SIZE = E.size; + + forceSize = SIZE; + + SMonitorRule rule = activeMonitorRule; + rule.resolution = SIZE; + + g_pHyprRenderer->applyMonitorRule(this, &rule); + }); + + tearingState.canTear = output->getBackend()->type() == Aquamarine::AQ_BACKEND_DRM; if (m_bEnabled) { - wlr_output_state_set_enabled(state.wlr(), true); + output->state->setEnabled(true); state.commit(); return; } szName = output->name; - szDescription = output->description ? output->description : ""; + szDescription = output->description; // remove comma character from description. This allow monitor specific rules to work on monitor with comma on their description std::erase(szDescription, ','); // field is backwards-compatible with intended usage of `szDescription` but excludes the parenthesized DRM node name suffix - szShortDescription = trim(std::format("{} {} {}", output->make ? output->make : "", output->model ? output->model : "", output->serial ? output->serial : "")); + szShortDescription = trim(std::format("{} {} {}", output->make, output->model, output->serial)); std::erase(szShortDescription, ','); - if (!wlr_backend_is_drm(output->backend)) - createdByUser = true; // should be true. WL, X11 and Headless backends should be addable / removable + if (output->getBackend()->type() != Aquamarine::AQ_BACKEND_DRM) + createdByUser = true; // should be true. WL and Headless backends should be addable / removable // get monitor rule that matches SMonitorRule monitorRule = g_pConfigManager->getMonitorRuleFor(*this); @@ -84,54 +101,23 @@ void CMonitor::onConnect(bool noRule) { // if it's disabled, disable and ignore if (monitorRule.disabled) { - wlr_output_state_set_scale(state.wlr(), 1); - wlr_output_state_set_transform(state.wlr(), WL_OUTPUT_TRANSFORM_NORMAL); - - auto PREFSTATE = wlr_output_preferred_mode(output); - - if (!PREFSTATE) { - wlr_output_mode* mode; - - wl_list_for_each(mode, &output->modes, link) { - wlr_output_state_set_mode(state.wlr(), mode); - - if (!wlr_output_test_state(output, state.wlr())) - continue; - - PREFSTATE = mode; - break; - } - } - - if (PREFSTATE) - wlr_output_state_set_mode(state.wlr(), PREFSTATE); - else - Debug::log(WARN, "No mode found for disabled output {}", output->name); - - wlr_output_state_set_enabled(state.wlr(), 0); + output->state->setEnabled(false); if (!state.commit()) Debug::log(ERR, "Couldn't commit disabled state on output {}", output->name); m_bEnabled = false; - hyprListener_monitorFrame.removeCallback(); + listeners.frame.reset(); return; } - if (output->non_desktop) { + if (output->nonDesktop) { Debug::log(LOG, "Not configuring non-desktop output"); - if (g_pCompositor->m_sWRLDRMLeaseMgr) { - wlr_drm_lease_v1_manager_offer_output(g_pCompositor->m_sWRLDRMLeaseMgr, output); - } - return; - } + if (PROTO::lease) + PROTO::lease->offer(self.lock()); - if (!m_bRenderingInitPassed) { - output->allocator = nullptr; - output->renderer = nullptr; - wlr_output_init_render(output, g_pCompositor->m_sWLRAllocator, g_pCompositor->m_sWLRRenderer); - m_bRenderingInitPassed = true; + return; } SP* thisWrapper = nullptr; @@ -151,14 +137,14 @@ void CMonitor::onConnect(bool noRule) { m_bEnabled = true; - wlr_output_state_set_enabled(state.wlr(), 1); + output->state->setEnabled(true); // set mode, also applies if (!noRule) g_pHyprRenderer->applyMonitorRule(this, &monitorRule, true); if (!state.commit()) - Debug::log(WARN, "wlr_output_commit_state failed in CMonitor::onCommit"); + Debug::log(WARN, "state.commit() failed in CMonitor::onCommit"); damage.setSize(vecTransformedSize); @@ -214,7 +200,7 @@ void CMonitor::onConnect(bool noRule) { renderTimer = wl_event_loop_add_timer(g_pCompositor->m_sWLEventLoop, ratHandler, this); - g_pCompositor->scheduleFrameForMonitor(this); + g_pCompositor->scheduleFrameForMonitor(this, Aquamarine::IOutput::AQ_SCHEDULE_NEW_MONITOR); PROTO::gamma->applyGammaToState(this); @@ -261,12 +247,10 @@ void CMonitor::onDisconnect(bool destroy) { g_pConfigManager->m_bWantsMonitorReload = true; } - hyprListener_monitorFrame.removeCallback(); - hyprListener_monitorPresented.removeCallback(); - hyprListener_monitorDamage.removeCallback(); - hyprListener_monitorNeedsFrame.removeCallback(); - hyprListener_monitorCommit.removeCallback(); - hyprListener_monitorBind.removeCallback(); + listeners.frame.reset(); + listeners.presented.reset(); + listeners.needsFrame.reset(); + listeners.commit.reset(); for (size_t i = 0; i < 4; ++i) { for (auto& ls : m_aLayerSurfaceLayers[i]) { @@ -316,10 +300,10 @@ void CMonitor::onDisconnect(bool destroy) { activeWorkspace->m_bVisible = false; activeWorkspace.reset(); - wlr_output_state_set_enabled(state.wlr(), false); + output->state->setEnabled(false); if (!state.commit()) - Debug::log(WARN, "wlr_output_commit_state failed in CMonitor::onDisconnect"); + Debug::log(WARN, "state.commit() failed in CMonitor::onDisconnect"); if (g_pCompositor->m_pLastMonitor.get() == this) g_pCompositor->setActiveMonitor(BACKUPMON ? BACKUPMON : g_pCompositor->m_pUnsafeOutput); @@ -344,9 +328,9 @@ void CMonitor::addDamage(const pixman_region32_t* rg) { static auto PZOOMFACTOR = CConfigValue("cursor:zoom_factor"); if (*PZOOMFACTOR != 1.f && g_pCompositor->getMonitorFromCursor() == this) { damage.damageEntire(); - g_pCompositor->scheduleFrameForMonitor(this); + g_pCompositor->scheduleFrameForMonitor(this, Aquamarine::IOutput::AQ_SCHEDULE_DAMAGE); } else if (damage.damage(rg)) - g_pCompositor->scheduleFrameForMonitor(this); + g_pCompositor->scheduleFrameForMonitor(this, Aquamarine::IOutput::AQ_SCHEDULE_DAMAGE); } void CMonitor::addDamage(const CRegion* rg) { @@ -357,11 +341,11 @@ void CMonitor::addDamage(const CBox* box) { static auto PZOOMFACTOR = CConfigValue("cursor:zoom_factor"); if (*PZOOMFACTOR != 1.f && g_pCompositor->getMonitorFromCursor() == this) { damage.damageEntire(); - g_pCompositor->scheduleFrameForMonitor(this); + g_pCompositor->scheduleFrameForMonitor(this, Aquamarine::IOutput::AQ_SCHEDULE_DAMAGE); } if (damage.damage(*box)) - g_pCompositor->scheduleFrameForMonitor(this); + g_pCompositor->scheduleFrameForMonitor(this, Aquamarine::IOutput::AQ_SCHEDULE_DAMAGE); } bool CMonitor::shouldSkipScheduleFrameOnMouseEvent() { @@ -369,8 +353,8 @@ bool CMonitor::shouldSkipScheduleFrameOnMouseEvent() { static auto PMINRR = CConfigValue("cursor:min_refresh_rate"); // skip scheduling extra frames for fullsreen apps with vrr - bool shouldSkip = *PNOBREAK && output->adaptive_sync_status == WLR_OUTPUT_ADAPTIVE_SYNC_ENABLED && activeWorkspace && activeWorkspace->m_bHasFullscreenWindow && - activeWorkspace->m_efFullscreenMode == FULLSCREEN_FULL; + bool shouldSkip = + *PNOBREAK && output->state->state().adaptiveSync && activeWorkspace && activeWorkspace->m_bHasFullscreenWindow && activeWorkspace->m_efFullscreenMode == FULLSCREEN_FULL; // keep requested minimum refresh rate if (shouldSkip && *PMINRR && lastPresentationTimer.getMillis() > 1000 / *PMINRR) { @@ -563,7 +547,7 @@ float CMonitor::getDefaultScale() { static constexpr double MMPERINCH = 25.4; const auto DIAGONALPX = sqrt(pow(vecPixelSize.x, 2) + pow(vecPixelSize.y, 2)); - const auto DIAGONALIN = sqrt(pow(output->phys_width / MMPERINCH, 2) + pow(output->phys_height / MMPERINCH, 2)); + const auto DIAGONALIN = sqrt(pow(output->physicalSize.x / MMPERINCH, 2) + pow(output->physicalSize.y / MMPERINCH, 2)); const auto PPI = DIAGONALPX / DIAGONALIN; @@ -767,11 +751,11 @@ Vector2D CMonitor::middle() { } void CMonitor::updateMatrix() { - wlr_matrix_identity(projMatrix.data()); + matrixIdentity(projMatrix.data()); if (transform != WL_OUTPUT_TRANSFORM_NORMAL) { - wlr_matrix_translate(projMatrix.data(), vecPixelSize.x / 2.0, vecPixelSize.y / 2.0); - wlr_matrix_transform(projMatrix.data(), transform); - wlr_matrix_translate(projMatrix.data(), -vecTransformedSize.x / 2.0, -vecTransformedSize.y / 2.0); + matrixTranslate(projMatrix.data(), vecPixelSize.x / 2.0, vecPixelSize.y / 2.0); + matrixTransform(projMatrix.data(), wlTransformToHyprutils(transform)); + matrixTranslate(projMatrix.data(), -vecTransformedSize.x / 2.0, -vecTransformedSize.y / 2.0); } } @@ -787,31 +771,124 @@ CBox CMonitor::logicalBox() { return {vecPosition, vecSize}; } +static void onDoneSource(void* data) { + auto pMonitor = (CMonitor*)data; + + if (!PROTO::outputs.contains(pMonitor->szName)) + return; + + PROTO::outputs.at(pMonitor->szName)->sendDone(); +} + +void CMonitor::scheduleDone() { + if (doneSource) + return; + + doneSource = wl_event_loop_add_idle(g_pCompositor->m_sWLEventLoop, ::onDoneSource, this); +} + +bool CMonitor::attemptDirectScanout() { + if (!mirrors.empty() || isMirror() || g_pHyprRenderer->m_bDirectScanoutBlocked) + return false; // do not DS if this monitor is being mirrored. Will break the functionality. + + if (g_pPointerManager->softwareLockedFor(self.lock())) + return false; + + const auto PCANDIDATE = solitaryClient.lock(); + + if (!PCANDIDATE) + return false; + + const auto PSURFACE = g_pXWaylandManager->getWindowSurface(PCANDIDATE); + + if (!PSURFACE || !PSURFACE->current.buffer || PSURFACE->current.buffer->size != vecPixelSize || PSURFACE->current.transform != transform) + return false; + + // we can't scanout shm buffers. + if (!PSURFACE->current.buffer->dmabuf().success) + return false; + + // FIXME: make sure the buffer actually follows the available scanout dmabuf formats + // and comes from the appropriate device. This may implode on multi-gpu!! + + output->state->setBuffer(PSURFACE->current.buffer); + output->state->setPresentationMode(Aquamarine::eOutputPresentationMode::AQ_OUTPUT_PRESENTATION_VSYNC); + + if (!state.test()) + return false; + + timespec now; + clock_gettime(CLOCK_MONOTONIC, &now); + Debug::log(TRACE, "presentFeedback for DS"); + PSURFACE->presentFeedback(&now, this, true); + + if (state.commit()) { + if (lastScanout.expired()) { + lastScanout = PCANDIDATE; + Debug::log(LOG, "Entered a direct scanout to {:x}: \"{}\"", (uintptr_t)PCANDIDATE.get(), PCANDIDATE->m_szTitle); + } + } else { + lastScanout.reset(); + return false; + } + + return true; +} + CMonitorState::CMonitorState(CMonitor* owner) { m_pOwner = owner; - wlr_output_state_init(&m_state); } CMonitorState::~CMonitorState() { - wlr_output_state_finish(&m_state); + ; } -wlr_output_state* CMonitorState::wlr() { - return &m_state; -} +void CMonitorState::ensureBufferPresent() { + if (!m_pOwner->output->state->state().enabled) { + Debug::log(TRACE, "CMonitorState::ensureBufferPresent: Ignoring, monitor is not enabled"); + return; + } -void CMonitorState::clear() { - wlr_output_state_finish(&m_state); - m_state = {0}; - wlr_output_state_init(&m_state); + if (m_pOwner->output->state->state().buffer) + return; + + // this is required for modesetting being possible and might be missing in case of first tests in the renderer + // where we test modes and buffers + Debug::log(LOG, "CMonitorState::ensureBufferPresent: no buffer, attaching one from the swapchain for modeset being possible"); + m_pOwner->output->state->setBuffer(m_pOwner->output->swapchain->next(nullptr)); + m_pOwner->output->swapchain->rollback(); // restore the counter, don't advance the swapchain } bool CMonitorState::commit() { - bool ret = wlr_output_commit_state(m_pOwner->output, &m_state); - clear(); + if (!updateSwapchain()) + return false; + + ensureBufferPresent(); + + bool ret = m_pOwner->output->commit(); return ret; } bool CMonitorState::test() { - return wlr_output_test_state(m_pOwner->output, &m_state); + if (!updateSwapchain()) + return false; + + ensureBufferPresent(); + + return m_pOwner->output->test(); +} + +bool CMonitorState::updateSwapchain() { + auto options = m_pOwner->output->swapchain->currentOptions(); + const auto& STATE = m_pOwner->output->state->state(); + const auto& MODE = STATE.mode ? STATE.mode : STATE.customMode; + if (!MODE) { + Debug::log(WARN, "updateSwapchain: No mode?"); + return true; + } + options.format = STATE.drmFormat; + options.scanout = true; + options.length = 2; + options.size = MODE->pixelSize; + return m_pOwner->output->swapchain->reconfigure(options); } diff --git a/src/helpers/Monitor.hpp b/src/helpers/Monitor.hpp index 8a2acdaf..32fc768a 100644 --- a/src/helpers/Monitor.hpp +++ b/src/helpers/Monitor.hpp @@ -12,6 +12,8 @@ #include #include "signal/Signal.hpp" #include "DamageRing.hpp" +#include +#include // Enum for the different types of auto directions, e.g. auto-left, auto-up. enum eAutoDirs { @@ -38,22 +40,21 @@ struct SMonitorRule { }; class CMonitor; +class CSyncTimeline; -// Class for wrapping the wlr state class CMonitorState { public: CMonitorState(CMonitor* owner); ~CMonitorState(); - wlr_output_state* wlr(); - void clear(); - // commit() will also clear() bool commit(); bool test(); + bool updateSwapchain(); private: - wlr_output_state m_state = {0}; - CMonitor* m_pOwner; + void ensureBufferPresent(); + + CMonitor* m_pOwner; }; class CMonitor { @@ -61,61 +62,69 @@ class CMonitor { CMonitor(); ~CMonitor(); - Vector2D vecPosition = Vector2D(-1, -1); // means unset - Vector2D vecXWaylandPosition = Vector2D(-1, -1); // means unset - Vector2D vecSize = Vector2D(0, 0); - Vector2D vecPixelSize = Vector2D(0, 0); - Vector2D vecTransformedSize = Vector2D(0, 0); + Vector2D vecPosition = Vector2D(-1, -1); // means unset + Vector2D vecXWaylandPosition = Vector2D(-1, -1); // means unset + Vector2D vecSize = Vector2D(0, 0); + Vector2D vecPixelSize = Vector2D(0, 0); + Vector2D vecTransformedSize = Vector2D(0, 0); - bool primary = false; + bool primary = false; - uint64_t ID = -1; - PHLWORKSPACE activeWorkspace = nullptr; - PHLWORKSPACE activeSpecialWorkspace = nullptr; - float setScale = 1; // scale set by cfg - float scale = 1; // real scale + uint64_t ID = -1; + PHLWORKSPACE activeWorkspace = nullptr; + PHLWORKSPACE activeSpecialWorkspace = nullptr; + float setScale = 1; // scale set by cfg + float scale = 1; // real scale - std::string szName = ""; - std::string szDescription = ""; - std::string szShortDescription = ""; + std::string szName = ""; + std::string szDescription = ""; + std::string szShortDescription = ""; - Vector2D vecReservedTopLeft = Vector2D(0, 0); - Vector2D vecReservedBottomRight = Vector2D(0, 0); + Vector2D vecReservedTopLeft = Vector2D(0, 0); + Vector2D vecReservedBottomRight = Vector2D(0, 0); - drmModeModeInfo customDrmMode = {}; + drmModeModeInfo customDrmMode = {}; - CMonitorState state; - CDamageRing damage; + CMonitorState state; + CDamageRing damage; - wlr_output* output = nullptr; - float refreshRate = 60; - int framesToSkip = 0; - int forceFullFrames = 0; - bool noFrameSchedule = false; - bool scheduledRecalc = false; - wl_output_transform transform = WL_OUTPUT_TRANSFORM_NORMAL; - float xwaylandScale = 1.f; - std::array projMatrix = {0}; - std::optional forceSize; - wlr_output_mode* currentMode = nullptr; + SP output; + float refreshRate = 60; + int framesToSkip = 0; + int forceFullFrames = 0; + bool noFrameSchedule = false; + bool scheduledRecalc = false; + wl_output_transform transform = WL_OUTPUT_TRANSFORM_NORMAL; + float xwaylandScale = 1.f; + std::array projMatrix = {0}; + std::optional forceSize; + SP currentMode; + SP cursorSwapchain; - bool dpmsStatus = true; - bool vrrActive = false; // this can be TRUE even if VRR is not active in the case that this display does not support it. - bool enabled10bit = false; // as above, this can be TRUE even if 10 bit failed. - bool createdByUser = false; - uint32_t drmFormat = DRM_FORMAT_INVALID; - bool isUnsafeFallback = false; + bool dpmsStatus = true; + bool vrrActive = false; // this can be TRUE even if VRR is not active in the case that this display does not support it. + bool enabled10bit = false; // as above, this can be TRUE even if 10 bit failed. + bool createdByUser = false; + bool isUnsafeFallback = false; - bool pendingFrame = false; // if we schedule a frame during rendering, reschedule it after - bool renderingActive = false; + bool pendingFrame = false; // if we schedule a frame during rendering, reschedule it after + bool renderingActive = false; - wl_event_source* renderTimer = nullptr; // for RAT - bool RATScheduled = false; - CTimer lastPresentationTimer; + wl_event_source* renderTimer = nullptr; // for RAT + bool RATScheduled = false; + CTimer lastPresentationTimer; - SMonitorRule activeMonitorRule; + bool isBeingLeased = false; - WP self; + SMonitorRule activeMonitorRule; + + // explicit sync + SP inTimeline; + SP outTimeline; + uint64_t lastWaitPoint = 0; + uint64_t commitSeq = 0; + + WP self; // mirroring CMonitor* pMirrorOf = nullptr; @@ -124,6 +133,9 @@ class CMonitor { // for tearing PHLWINDOWREF solitaryClient; + // for direct scanout + PHLWINDOWREF lastScanout; + struct { bool canTear = false; bool nextRenderTorn = false; @@ -143,15 +155,6 @@ class CMonitor { std::array, 4> m_aLayerSurfaceLayers; - DYNLISTENER(monitorFrame); - DYNLISTENER(monitorDestroy); - DYNLISTENER(monitorStateRequest); - DYNLISTENER(monitorDamage); - DYNLISTENER(monitorNeedsFrame); - DYNLISTENER(monitorCommit); - DYNLISTENER(monitorBind); - DYNLISTENER(monitorPresented); - // methods void onConnect(bool noRule); void onDisconnect(bool destroy = false); @@ -173,6 +176,8 @@ class CMonitor { int64_t activeWorkspaceID(); int64_t activeSpecialWorkspaceID(); CBox logicalBox(); + void scheduleDone(); + bool attemptDirectScanout(); bool m_bEnabled = false; bool m_bRenderingInitPassed = false; @@ -184,6 +189,17 @@ class CMonitor { } private: - void setupDefaultWS(const SMonitorRule&); - int findAvailableDefaultWS(); + void setupDefaultWS(const SMonitorRule&); + int findAvailableDefaultWS(); + + wl_event_source* doneSource = nullptr; + + struct { + CHyprSignalListener frame; + CHyprSignalListener destroy; + CHyprSignalListener state; + CHyprSignalListener needsFrame; + CHyprSignalListener presented; + CHyprSignalListener commit; + } listeners; }; diff --git a/src/helpers/WLClasses.hpp b/src/helpers/WLClasses.hpp index 6b25e76d..51f90166 100644 --- a/src/helpers/WLClasses.hpp +++ b/src/helpers/WLClasses.hpp @@ -15,6 +15,8 @@ class IPointer; class IKeyboard; class CWLSurfaceResource; +AQUAMARINE_FORWARD(ISwitch); + struct SRenderData { CMonitor* pMonitor; timespec* when; @@ -70,14 +72,14 @@ struct SSwipeGesture { }; struct SSwitchDevice { - wlr_input_device* pWlrDevice = nullptr; + WP pDevice; - int status = -1; // uninitialized - - DYNLISTENER(destroy); - DYNLISTENER(toggle); + struct { + CHyprSignalListener destroy; + CHyprSignalListener fire; + } listeners; bool operator==(const SSwitchDevice& other) const { - return pWlrDevice == other.pWlrDevice; + return pDevice == other.pDevice; } }; diff --git a/src/helpers/X11Stubs.hpp b/src/helpers/X11Stubs.hpp deleted file mode 100644 index 19bea6f8..00000000 --- a/src/helpers/X11Stubs.hpp +++ /dev/null @@ -1,7 +0,0 @@ -#pragma once - -inline bool wlr_backend_is_x11(void*) { - return false; -} - -inline void wlr_x11_output_create(void*) {} diff --git a/src/helpers/math/Math.cpp b/src/helpers/math/Math.cpp index 560f29c9..fccfd636 100644 --- a/src/helpers/math/Math.cpp +++ b/src/helpers/math/Math.cpp @@ -17,14 +17,14 @@ Hyprutils::Math::eTransform wlTransformToHyprutils(wl_output_transform t) { return Hyprutils::Math::eTransform::HYPRUTILS_TRANSFORM_NORMAL; } -static void matrixIdentity(float mat[9]) { +void matrixIdentity(float mat[9]) { static const float identity[9] = { 1.0f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f, 1.0f, }; memcpy(mat, identity, sizeof(identity)); } -static void matrixMultiply(float mat[9], const float a[9], const float b[9]) { +void matrixMultiply(float mat[9], const float a[9], const float b[9]) { float product[9]; product[0] = a[0] * b[0] + a[1] * b[3] + a[2] * b[6]; @@ -42,141 +42,56 @@ static void matrixMultiply(float mat[9], const float a[9], const float b[9]) { memcpy(mat, product, sizeof(product)); } -static void matrixTranspose(float mat[9], const float a[9]) { +void matrixTranspose(float mat[9], const float a[9]) { float transposition[9] = { a[0], a[3], a[6], a[1], a[4], a[7], a[2], a[5], a[8], }; memcpy(mat, transposition, sizeof(transposition)); } -static void matrixTranslate(float mat[9], float x, float y) { +void matrixTranslate(float mat[9], float x, float y) { float translate[9] = { 1.0f, 0.0f, x, 0.0f, 1.0f, y, 0.0f, 0.0f, 1.0f, }; matrixMultiply(mat, mat, translate); } -static void matrixScale(float mat[9], float x, float y) { +void matrixScale(float mat[9], float x, float y) { float scale[9] = { x, 0.0f, 0.0f, 0.0f, y, 0.0f, 0.0f, 0.0f, 1.0f, }; matrixMultiply(mat, mat, scale); } -static void matrixRotate(float mat[9], float rad) { +void matrixRotate(float mat[9], float rad) { float rotate[9] = { cos(rad), -sin(rad), 0.0f, sin(rad), cos(rad), 0.0f, 0.0f, 0.0f, 1.0f, }; matrixMultiply(mat, mat, rotate); } -static std::unordered_map> transforms = { - {HYPRUTILS_TRANSFORM_NORMAL, - { - 1.0f, - 0.0f, - 0.0f, - 0.0f, - 1.0f, - 0.0f, - 0.0f, - 0.0f, - 1.0f, - }}, - {HYPRUTILS_TRANSFORM_90, - { - 0.0f, - 1.0f, - 0.0f, - -1.0f, - 0.0f, - 0.0f, - 0.0f, - 0.0f, - 1.0f, - }}, - {HYPRUTILS_TRANSFORM_180, - { - -1.0f, - 0.0f, - 0.0f, - 0.0f, - -1.0f, - 0.0f, - 0.0f, - 0.0f, - 1.0f, - }}, - {HYPRUTILS_TRANSFORM_270, - { - 0.0f, - -1.0f, - 0.0f, - 1.0f, - 0.0f, - 0.0f, - 0.0f, - 0.0f, - 1.0f, - }}, - {HYPRUTILS_TRANSFORM_FLIPPED, - { - -1.0f, - 0.0f, - 0.0f, - 0.0f, - 1.0f, - 0.0f, - 0.0f, - 0.0f, - 1.0f, - }}, - {HYPRUTILS_TRANSFORM_FLIPPED_90, - { - 0.0f, - 1.0f, - 0.0f, - 1.0f, - 0.0f, - 0.0f, - 0.0f, - 0.0f, - 1.0f, - }}, - {HYPRUTILS_TRANSFORM_FLIPPED_180, - { - 1.0f, - 0.0f, - 0.0f, - 0.0f, - -1.0f, - 0.0f, - 0.0f, - 0.0f, - 1.0f, - }}, - {HYPRUTILS_TRANSFORM_FLIPPED_270, - { - 0.0f, - -1.0f, - 0.0f, - -1.0f, - 0.0f, - 0.0f, - 0.0f, - 0.0f, - 1.0f, - }}, -}; - -static void matrixTransform(float mat[9], eTransform transform) { - matrixMultiply(mat, mat, transforms.at(transform).data()); +const std::unordered_map>& getTransforms() { + static std::unordered_map> transforms = { + {HYPRUTILS_TRANSFORM_NORMAL, {1.0f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f, 1.0f}}, + {HYPRUTILS_TRANSFORM_90, {0.0f, 1.0f, 0.0f, -1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f}}, + {HYPRUTILS_TRANSFORM_180, {-1.0f, 0.0f, 0.0f, 0.0f, -1.0f, 0.0f, 0.0f, 0.0f, 1.0f}}, + {HYPRUTILS_TRANSFORM_270, {0.0f, -1.0f, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f}}, + {HYPRUTILS_TRANSFORM_FLIPPED, {-1.0f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f, 1.0f}}, + {HYPRUTILS_TRANSFORM_FLIPPED_90, {0.0f, 1.0f, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f}}, + {HYPRUTILS_TRANSFORM_FLIPPED_180, {1.0f, 0.0f, 0.0f, 0.0f, -1.0f, 0.0f, 0.0f, 0.0f, 1.0f}}, + {HYPRUTILS_TRANSFORM_FLIPPED_270, {0.0f, -1.0f, 0.0f, -1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f}}, + }; + return transforms; } -static void matrixProjection(float mat[9], int width, int height, eTransform transform) { +void matrixTransform(float mat[9], eTransform transform) { + matrixMultiply(mat, mat, getTransforms().at(transform).data()); +} + +void matrixProjection(float mat[9], int width, int height, eTransform transform) { memset(mat, 0, sizeof(*mat) * 9); - const float* t = transforms.at(transform).data(); + const float* t = getTransforms().at(transform).data(); float x = 2.0f / width; float y = 2.0f / height; @@ -219,3 +134,10 @@ void projectBox(float mat[9], CBox& box, eTransform transform, float rotation, c matrixMultiply(mat, projection, mat); } + +wl_output_transform invertTransform(wl_output_transform tr) { + if ((tr & WL_OUTPUT_TRANSFORM_90) && !(tr & WL_OUTPUT_TRANSFORM_FLIPPED)) + tr = (wl_output_transform)(tr ^ (int)WL_OUTPUT_TRANSFORM_180); + + return tr; +} diff --git a/src/helpers/math/Math.hpp b/src/helpers/math/Math.hpp index 4aa65c93..f57cef93 100644 --- a/src/helpers/math/Math.hpp +++ b/src/helpers/math/Math.hpp @@ -7,5 +7,14 @@ using namespace Hyprutils::Math; -eTransform wlTransformToHyprutils(wl_output_transform t); -void projectBox(float mat[9], CBox& box, eTransform transform, float rotation, const float projection[9]); +eTransform wlTransformToHyprutils(wl_output_transform t); +void projectBox(float mat[9], CBox& box, eTransform transform, float rotation, const float projection[9]); +void matrixProjection(float mat[9], int width, int height, eTransform transform); +void matrixTransform(float mat[9], eTransform transform); +void matrixRotate(float mat[9], float rad); +void matrixScale(float mat[9], float x, float y); +void matrixTranslate(float mat[9], float x, float y); +void matrixTranspose(float mat[9], const float a[9]); +void matrixMultiply(float mat[9], const float a[9], const float b[9]); +void matrixIdentity(float mat[9]); +wl_output_transform invertTransform(wl_output_transform tr); diff --git a/src/helpers/sync/SyncTimeline.cpp b/src/helpers/sync/SyncTimeline.cpp new file mode 100644 index 00000000..352120ea --- /dev/null +++ b/src/helpers/sync/SyncTimeline.cpp @@ -0,0 +1,190 @@ +#include "SyncTimeline.hpp" +#include "../../defines.hpp" +#include "../../managers/eventLoop/EventLoopManager.hpp" + +#include +#include + +SP CSyncTimeline::create(int drmFD_) { + auto timeline = SP(new CSyncTimeline); + timeline->drmFD = drmFD_; + timeline->self = timeline; + + if (drmSyncobjCreate(drmFD_, 0, &timeline->handle)) { + Debug::log(ERR, "CSyncTimeline: failed to create a drm syncobj??"); + return nullptr; + } + + return timeline; +} + +SP CSyncTimeline::create(int drmFD_, int drmSyncobjFD) { + auto timeline = SP(new CSyncTimeline); + timeline->drmFD = drmFD_; + timeline->self = timeline; + + if (drmSyncobjFDToHandle(drmFD_, drmSyncobjFD, &timeline->handle)) { + Debug::log(ERR, "CSyncTimeline: failed to create a drm syncobj from fd??"); + return nullptr; + } + + return timeline; +} + +CSyncTimeline::~CSyncTimeline() { + if (handle == 0) + return; + + drmSyncobjDestroy(drmFD, handle); +} + +std::optional CSyncTimeline::check(uint64_t point, uint32_t flags) { +#ifdef __FreeBSD__ + constexpr int ETIME_ERR = ETIMEDOUT; +#else + constexpr int ETIME_ERR = ETIME; +#endif + + uint32_t signaled = 0; + int ret = drmSyncobjTimelineWait(drmFD, &handle, &point, 1, 0, flags, &signaled); + if (ret != 0 && ret != -ETIME_ERR) { + Debug::log(ERR, "CSyncTimeline::check: drmSyncobjTimelineWait failed"); + return std::nullopt; + } + + return ret == 0; +} + +static int handleWaiterFD(int fd, uint32_t mask, void* data) { + auto waiter = (CSyncTimeline::SWaiter*)data; + + if (mask & (WL_EVENT_HANGUP | WL_EVENT_ERROR)) { + Debug::log(ERR, "handleWaiterFD: eventfd error"); + return 0; + } + + if (mask & WL_EVENT_READABLE) { + uint64_t value = 0; + if (read(fd, &value, sizeof(value)) <= 0) + Debug::log(ERR, "handleWaiterFD: failed to read from eventfd"); + } + + wl_event_source_remove(waiter->source); + waiter->source = nullptr; + + if (waiter->fn) + waiter->fn(); + + if (waiter->timeline) + waiter->timeline->removeWaiter(waiter); + + return 0; +} + +bool CSyncTimeline::addWaiter(const std::function& waiter, uint64_t point, uint32_t flags) { + auto w = makeShared(); + w->fn = waiter; + w->timeline = self; + + int eventFD = eventfd(0, EFD_CLOEXEC); + + if (eventFD < 0) { + Debug::log(ERR, "CSyncTimeline::addWaiter: failed to acquire an eventfd"); + return false; + } + + drm_syncobj_eventfd syncobjEventFD = { + .handle = handle, + .flags = flags, + .point = point, + .fd = eventFD, + }; + + if (drmIoctl(drmFD, DRM_IOCTL_SYNCOBJ_EVENTFD, &syncobjEventFD) != 0) { + Debug::log(ERR, "CSyncTimeline::addWaiter: drmIoctl failed"); + close(eventFD); + return false; + } + + w->source = wl_event_loop_add_fd(g_pEventLoopManager->m_sWayland.loop, eventFD, WL_EVENT_READABLE, ::handleWaiterFD, w.get()); + if (!w->source) { + Debug::log(ERR, "CSyncTimeline::addWaiter: wl_event_loop_add_fd failed"); + close(eventFD); + return false; + } + + waiters.emplace_back(w); + + return true; +} + +void CSyncTimeline::removeWaiter(SWaiter* w) { + if (w->source) { + wl_event_source_remove(w->source); + w->source = nullptr; + } + std::erase_if(waiters, [w](const auto& e) { return e.get() == w; }); +} + +int CSyncTimeline::exportAsSyncFileFD(uint64_t src) { + int sync = -1; + + uint32_t syncHandle = 0; + if (drmSyncobjCreate(drmFD, 0, &syncHandle)) { + Debug::log(ERR, "exportAsSyncFileFD: drmSyncobjCreate failed"); + return -1; + } + + if (drmSyncobjTransfer(drmFD, syncHandle, 0, handle, src, 0)) { + Debug::log(ERR, "exportAsSyncFileFD: drmSyncobjTransfer failed"); + drmSyncobjDestroy(drmFD, syncHandle); + return -1; + } + + if (drmSyncobjExportSyncFile(drmFD, syncHandle, &sync)) { + Debug::log(ERR, "exportAsSyncFileFD: drmSyncobjExportSyncFile failed"); + drmSyncobjDestroy(drmFD, syncHandle); + return -1; + } + + drmSyncobjDestroy(drmFD, syncHandle); + return sync; +} + +bool CSyncTimeline::importFromSyncFileFD(uint64_t dst, int fd) { + uint32_t syncHandle = 0; + + if (drmSyncobjCreate(drmFD, 0, &syncHandle)) { + Debug::log(ERR, "importFromSyncFileFD: drmSyncobjCreate failed"); + return false; + } + + if (drmSyncobjImportSyncFile(drmFD, syncHandle, fd)) { + Debug::log(ERR, "importFromSyncFileFD: drmSyncobjImportSyncFile failed"); + drmSyncobjDestroy(drmFD, syncHandle); + return false; + } + + if (drmSyncobjTransfer(drmFD, handle, dst, syncHandle, 0, 0)) { + Debug::log(ERR, "importFromSyncFileFD: drmSyncobjTransfer failed"); + drmSyncobjDestroy(drmFD, syncHandle); + return false; + } + + drmSyncobjDestroy(drmFD, syncHandle); + return true; +} + +bool CSyncTimeline::transfer(SP from, uint64_t fromPoint, uint64_t toPoint) { + if (drmFD != from->drmFD) { + Debug::log(ERR, "CSyncTimeline::transfer: cannot transfer timelines between gpus, {} -> {}", from->drmFD, drmFD); + return false; + } + + if (drmSyncobjTransfer(drmFD, handle, toPoint, from->handle, fromPoint, 0)) { + Debug::log(ERR, "CSyncTimeline::transfer: drmSyncobjTransfer failed"); + return false; + } + + return true; +} diff --git a/src/helpers/sync/SyncTimeline.hpp b/src/helpers/sync/SyncTimeline.hpp new file mode 100644 index 00000000..3d868a95 --- /dev/null +++ b/src/helpers/sync/SyncTimeline.hpp @@ -0,0 +1,47 @@ +#pragma once + +#include +#include +#include +#include +#include "../memory/Memory.hpp" + +/* + Hyprland synchronization timelines are based on the wlroots' ones, which + are based on Vk timeline semaphores: https://www.khronos.org/blog/vulkan-timeline-semaphores +*/ + +struct wl_event_source; + +class CSyncTimeline { + public: + static SP create(int drmFD_); + static SP create(int drmFD_, int drmSyncobjFD); + ~CSyncTimeline(); + + struct SWaiter { + std::function fn; + wl_event_source* source = nullptr; + WP timeline; + }; + + // check if the timeline point has been signaled + // flags: DRM_SYNCOBJ_WAIT_FLAGS_WAIT_FOR_SUBMIT or DRM_SYNCOBJ_WAIT_FLAGS_WAIT_AVAILABLE + // std::nullopt on fail + std::optional check(uint64_t point, uint32_t flags); + + bool addWaiter(const std::function& waiter, uint64_t point, uint32_t flags); + void removeWaiter(SWaiter*); + int exportAsSyncFileFD(uint64_t src); + bool importFromSyncFileFD(uint64_t dst, int fd); + bool transfer(SP from, uint64_t fromPoint, uint64_t toPoint); + + int drmFD = -1; + uint32_t handle = 0; + WP self; + + private: + CSyncTimeline() = default; + + std::vector> waiters; +}; diff --git a/src/includes.hpp b/src/includes.hpp index afec078a..8b3f3fad 100644 --- a/src/includes.hpp +++ b/src/includes.hpp @@ -16,78 +16,6 @@ #include #include #include -#include -#include -#include -#include - -#if true -// wlroots uses dumb-ass shit that makes it not compile on C++, let's fix that. -// https://github.com/swaywm/wlroots/issues/682 -// pthread first because it uses class in a C++ way and XWayland includes that... -#include - -#define class _class -#define namespace _namespace -#define static -#define delete delete_ - -extern "C" { -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include - -#if WLR_HAS_X11_BACKEND -#include -#endif -} - -#undef delete -#undef class -#undef namespace -#undef static -#endif #ifdef LEGACY_RENDERER #include @@ -99,10 +27,6 @@ extern "C" { #include #endif -#if !WLR_HAS_X11_BACKEND -#include "helpers/X11Stubs.hpp" -#endif - #ifdef NO_XWAYLAND #define XWAYLAND false #else diff --git a/src/macros.hpp b/src/macros.hpp index f1393cbd..b2adb036 100644 --- a/src/macros.hpp +++ b/src/macros.hpp @@ -105,3 +105,8 @@ class name; \ } \ } + +#define AQUAMARINE_FORWARD(name) \ + namespace Aquamarine { \ + class name; \ + } diff --git a/src/managers/AnimationManager.cpp b/src/managers/AnimationManager.cpp index 677b2109..dcc7a45f 100644 --- a/src/managers/AnimationManager.cpp +++ b/src/managers/AnimationManager.cpp @@ -259,7 +259,7 @@ void CAnimationManager::tick() { // manually schedule a frame if (PMONITOR) - g_pCompositor->scheduleFrameForMonitor(PMONITOR); + g_pCompositor->scheduleFrameForMonitor(PMONITOR, Aquamarine::IOutput::AQ_SCHEDULE_CURSOR_SHAPE); } // do it here, because if this alters the animation vars deque we would be in trouble above. diff --git a/src/managers/CursorManager.cpp b/src/managers/CursorManager.cpp index daa4f4be..3a13d10b 100644 --- a/src/managers/CursorManager.cpp +++ b/src/managers/CursorManager.cpp @@ -3,10 +3,11 @@ #include "../config/ConfigValue.hpp" #include "PointerManager.hpp" #include "../xwayland/XWayland.hpp" +#include +#include "../helpers/CursorShapes.hpp" extern "C" { -#include -#include +#include } static int cursorAnimTimer(void* data) { @@ -45,8 +46,7 @@ CCursorManager::CCursorManager() { if (m_iSize == 0) m_iSize = 24; - m_pWLRXCursorMgr = wlr_xcursor_manager_create(getenv("XCURSOR_THEME"), m_iSize); - wlr_xcursor_manager_load(m_pWLRXCursorMgr, 1.0); + xcursor.loadTheme(getenv("XCURSOR_THEME") ? getenv("XCURSOR_THEME") : "", m_iSize * std::ceil(m_fCursorScale)); m_pAnimationTimer = wl_event_loop_add_timer(g_pCompositor->m_sWLEventLoop, ::cursorAnimTimer, nullptr); @@ -56,9 +56,6 @@ CCursorManager::CCursorManager() { } CCursorManager::~CCursorManager() { - if (m_pWLRXCursorMgr) - wlr_xcursor_manager_destroy(m_pWLRXCursorMgr); - if (m_pAnimationTimer) wl_event_source_remove(m_pAnimationTimer); } @@ -67,54 +64,61 @@ void CCursorManager::dropBufferRef(CCursorManager::CCursorBuffer* ref) { std::erase_if(m_vCursorBuffers, [ref](const auto& buf) { return buf.get() == ref; }); } -static void cursorBufferDestroy(struct wlr_buffer* wlr_buffer) { - CCursorManager::CCursorBuffer::SCursorWlrBuffer* buffer = wl_container_of(wlr_buffer, buffer, base); - g_pCursorManager->dropBufferRef(buffer->parent); +CCursorManager::CCursorBuffer::CCursorBuffer(cairo_surface_t* surf, const Vector2D& size_, const Vector2D& hot_) : hotspot(hot_) { + surface = surf; + size = size_; + stride = cairo_image_surface_get_stride(surf); } -static bool cursorBufferBeginDataPtr(struct wlr_buffer* wlr_buffer, uint32_t flags, void** data, uint32_t* format, size_t* stride) { - CCursorManager::CCursorBuffer::SCursorWlrBuffer* buffer = wl_container_of(wlr_buffer, buffer, base); - - if (flags & WLR_BUFFER_DATA_PTR_ACCESS_WRITE) - return false; - - *data = buffer->pixelData ? buffer->pixelData : cairo_image_surface_get_data(buffer->surface); - *stride = buffer->stride; - *format = DRM_FORMAT_ARGB8888; - return true; -} - -static void cursorBufferEndDataPtr(struct wlr_buffer* wlr_buffer) { - ; -} - -// -static const wlr_buffer_impl bufferImpl = { - .destroy = cursorBufferDestroy, - .begin_data_ptr_access = cursorBufferBeginDataPtr, - .end_data_ptr_access = cursorBufferEndDataPtr, -}; - -CCursorManager::CCursorBuffer::CCursorBuffer(cairo_surface_t* surf, const Vector2D& size_, const Vector2D& hot_) : size(size_), hotspot(hot_) { - wlrBuffer.surface = surf; - wlr_buffer_init(&wlrBuffer.base, &bufferImpl, size.x, size.y); - wlrBuffer.parent = this; - wlrBuffer.stride = cairo_image_surface_get_stride(surf); -} - -CCursorManager::CCursorBuffer::CCursorBuffer(uint8_t* pixelData, const Vector2D& size_, const Vector2D& hot_) : size(size_), hotspot(hot_) { - wlrBuffer.pixelData = pixelData; - wlr_buffer_init(&wlrBuffer.base, &bufferImpl, size.x, size.y); - wlrBuffer.parent = this; - wlrBuffer.stride = 4 * size_.x; +CCursorManager::CCursorBuffer::CCursorBuffer(uint8_t* pixelData_, const Vector2D& size_, const Vector2D& hot_) : hotspot(hot_) { + pixelData = pixelData_; + size = size_; + stride = 4 * size_.x; } CCursorManager::CCursorBuffer::~CCursorBuffer() { - ; // will be freed in .destroy + ; } -wlr_buffer* CCursorManager::getCursorBuffer() { - return !m_vCursorBuffers.empty() ? &m_vCursorBuffers.back()->wlrBuffer.base : nullptr; +Aquamarine::eBufferCapability CCursorManager::CCursorBuffer::caps() { + return Aquamarine::eBufferCapability::BUFFER_CAPABILITY_DATAPTR; +} + +Aquamarine::eBufferType CCursorManager::CCursorBuffer::type() { + return Aquamarine::eBufferType::BUFFER_TYPE_SHM; +} + +void CCursorManager::CCursorBuffer::update(const Hyprutils::Math::CRegion& damage) { + ; +} + +bool CCursorManager::CCursorBuffer::isSynchronous() { + return true; +} + +bool CCursorManager::CCursorBuffer::good() { + return true; +} + +Aquamarine::SSHMAttrs CCursorManager::CCursorBuffer::shm() { + Aquamarine::SSHMAttrs attrs; + attrs.success = true; + attrs.format = DRM_FORMAT_ARGB8888; + attrs.size = size; + attrs.stride = stride; + return attrs; +} + +std::tuple CCursorManager::CCursorBuffer::beginDataPtr(uint32_t flags) { + return {pixelData ? pixelData : cairo_image_surface_get_data(surface), DRM_FORMAT_ARGB8888, stride}; +} + +void CCursorManager::CCursorBuffer::endDataPtr() { + ; +} + +SP CCursorManager::getCursorBuffer() { + return !m_vCursorBuffers.empty() ? m_vCursorBuffers.back() : nullptr; } void CCursorManager::setCursorSurface(SP surf, const Vector2D& hotspot) { @@ -127,34 +131,24 @@ void CCursorManager::setCursorSurface(SP surf, const Vector2D& hotsp } void CCursorManager::setXCursor(const std::string& name) { - if (!m_pWLRXCursorMgr) { - g_pPointerManager->resetCursorImage(); - return; - } - float scale = std::ceil(m_fCursorScale); - wlr_xcursor_manager_load(m_pWLRXCursorMgr, scale); - auto xcursor = wlr_xcursor_manager_get_xcursor(m_pWLRXCursorMgr, name.c_str(), scale); - if (!xcursor) { - Debug::log(ERR, "XCursor has no shape {}, retrying with left-ptr", name); - xcursor = wlr_xcursor_manager_get_xcursor(m_pWLRXCursorMgr, "left-ptr", scale); - } - - if (!xcursor || !xcursor->images[0]) { - Debug::log(ERR, "XCursor is broken. F this garbage."); + if (!xcursor.themeLoaded) { + Debug::log(ERR, "XCursor failed to find theme in setXCursor"); g_pPointerManager->resetCursorImage(); return; } - auto image = xcursor->images[0]; + auto& icon = xcursor.defaultCursor; + // try to get an icon we know if we have one + if (xcursor.cursors.contains(name)) + icon = xcursor.cursors.at(name); - m_vCursorBuffers.emplace_back( - std::make_unique(image->buffer, Vector2D{(int)image->width, (int)image->height}, Vector2D{(double)image->hotspot_x, (double)image->hotspot_y})); + m_vCursorBuffers.emplace_back(makeShared((uint8_t*)icon->pixels.data(), icon->size, icon->hotspot)); - g_pPointerManager->setCursorBuffer(getCursorBuffer(), Vector2D{(double)image->hotspot_x, (double)image->hotspot_y} / scale, scale); + g_pPointerManager->setCursorBuffer(getCursorBuffer(), icon->hotspot / scale, scale); if (m_vCursorBuffers.size() > 1) - wlr_buffer_drop(&m_vCursorBuffers.front()->wlrBuffer.base); + dropBufferRef(m_vCursorBuffers.at(0).get()); m_bOurBufferConnected = true; } @@ -196,14 +190,14 @@ void CCursorManager::setCursorFromName(const std::string& name) { } } - m_vCursorBuffers.emplace_back(std::make_unique(m_sCurrentCursorShapeData.images[0].surface, - Vector2D{m_sCurrentCursorShapeData.images[0].size, m_sCurrentCursorShapeData.images[0].size}, - Vector2D{m_sCurrentCursorShapeData.images[0].hotspotX, m_sCurrentCursorShapeData.images[0].hotspotY})); + m_vCursorBuffers.emplace_back(makeShared(m_sCurrentCursorShapeData.images[0].surface, + Vector2D{m_sCurrentCursorShapeData.images[0].size, m_sCurrentCursorShapeData.images[0].size}, + Vector2D{m_sCurrentCursorShapeData.images[0].hotspotX, m_sCurrentCursorShapeData.images[0].hotspotY})); g_pPointerManager->setCursorBuffer(getCursorBuffer(), Vector2D{m_sCurrentCursorShapeData.images[0].hotspotX, m_sCurrentCursorShapeData.images[0].hotspotY} / m_fCursorScale, m_fCursorScale); if (m_vCursorBuffers.size() > 1) - wlr_buffer_drop(&m_vCursorBuffers.front()->wlrBuffer.base); + dropBufferRef(m_vCursorBuffers.at(0).get()); m_bOurBufferConnected = true; @@ -225,7 +219,7 @@ void CCursorManager::tickAnimatedCursor() { if ((size_t)m_iCurrentAnimationFrame >= m_sCurrentCursorShapeData.images.size()) m_iCurrentAnimationFrame = 0; - m_vCursorBuffers.emplace_back(std::make_unique( + m_vCursorBuffers.emplace_back(makeShared( m_sCurrentCursorShapeData.images[m_iCurrentAnimationFrame].surface, Vector2D{m_sCurrentCursorShapeData.images[m_iCurrentAnimationFrame].size, m_sCurrentCursorShapeData.images[m_iCurrentAnimationFrame].size}, Vector2D{m_sCurrentCursorShapeData.images[m_iCurrentAnimationFrame].hotspotX, m_sCurrentCursorShapeData.images[m_iCurrentAnimationFrame].hotspotY})); @@ -256,10 +250,9 @@ void CCursorManager::setXWaylandCursor() { if (CURSOR.surface) { g_pXWayland->setCursor(cairo_image_surface_get_data(CURSOR.surface), cairo_image_surface_get_stride(CURSOR.surface), {CURSOR.size, CURSOR.size}, {CURSOR.hotspotX, CURSOR.hotspotY}); - } else if (const auto XCURSOR = wlr_xcursor_manager_get_xcursor(m_pWLRXCursorMgr, "left_ptr", 1); XCURSOR) { - g_pXWayland->setCursor(XCURSOR->images[0]->buffer, XCURSOR->images[0]->width * 4, {(int)XCURSOR->images[0]->width, (int)XCURSOR->images[0]->height}, - {(double)XCURSOR->images[0]->hotspot_x, (double)XCURSOR->images[0]->hotspot_y}); - } else + } else if (xcursor.themeLoaded) + g_pXWayland->setCursor((uint8_t*)xcursor.defaultCursor->pixels.data(), xcursor.defaultCursor->size.x * 4, xcursor.defaultCursor->size, xcursor.defaultCursor->hotspot); + else Debug::log(ERR, "CursorManager: no valid cursor for xwayland"); } @@ -284,7 +277,7 @@ void CCursorManager::updateTheme() { for (auto& m : g_pCompositor->m_vMonitors) { m->forceFullFrames = 5; - g_pCompositor->scheduleFrameForMonitor(m.get()); + g_pCompositor->scheduleFrameForMonitor(m.get(), Aquamarine::IOutput::AQ_SCHEDULE_CURSOR_SHAPE); } } @@ -303,37 +296,163 @@ bool CCursorManager::changeTheme(const std::string& name, const int size) { Debug::log(ERR, "Hyprcursor failed loading theme \"{}\", falling back to X.", name); - if (m_pWLRXCursorMgr) - wlr_xcursor_manager_destroy(m_pWLRXCursorMgr); + xcursor.loadTheme(name, size); - m_pWLRXCursorMgr = wlr_xcursor_manager_create(name.empty() ? "" : name.c_str(), size); - bool xSuccess = wlr_xcursor_manager_load(m_pWLRXCursorMgr, 1.0) == 1; + m_szTheme = name; + m_iSize = size; + updateTheme(); + return true; +} - // this basically checks if xcursor changed used theme to default but better - bool diffTheme = false; - wlr_xcursor_manager_theme* theme; - wl_list_for_each(theme, &m_pWLRXCursorMgr->scaled_themes, link) { - if (std::string{theme->theme->name} != name) { - diffTheme = true; - break; +// Taken from https://gitlab.freedesktop.org/xorg/lib/libxcursor/-/blob/master/src/library.c +// however modified to fit wayland cursor shape names better. +// _ -> - +// clang-format off +static std::array XCURSOR_STANDARD_NAMES = { + "X_cursor", + "default", // arrow + "ns-resize", // based-arrow-down + "ns-resize", // based-arrow-up + "boat", + "bogosity", + "sw-resize", // bottom-left-corner + "se-resize", // bottom-right-corner + "s-resize", // bottom-side + "bottom-tee", + "box-spiral", + "center-ptr", + "circle", + "clock", + "coffee-mug", + "cross", + "cross-reverse", + "crosshair", + "diamond-cross", + "dot", + "dotbox", + "double-arrow", + "draft-large", + "draft-small", + "draped-box", + "exchange", + "move", // fleur + "gobbler", + "gumby", + "pointer", // hand1 + "grabbing", // hand2 + "heart", + "icon", + "iron-cross", + "default", // left-ptr + "w-resize", // left-side + "left-tee", + "leftbutton", + "ll-angle", + "lr-angle", + "man", + "middlebutton", + "mouse", + "pencil", + "pirate", + "plus", + "help", // question-arrow + "right-ptr", + "e-resize", // right-side + "right-tee", + "rightbutton", + "rtl-logo", + "sailboat", + "ns-resize", // sb-down-arrow + "ew-resize", // sb-h-double-arrow + "ew-resize", // sb-left-arrow + "ew-resize", // sb-right-arrow + "n-resize", // sb-up-arrow + "s-resize", // sb-v-double-arrow + "shuttle", + "sizing", + "spider", + "spraycan", + "star", + "target", + "cell", // tcross + "nw-resize", // top-left-arrow + "nw-resize", // top-left-corner + "ne-resize", // top-right-corner + "n-resize", // top-side + "top-tee", + "trek", + "ul-angle", + "umbrella", + "ur-angle", + "wait", // watch + "text", // xterm +}; +// clang-format on + +void CCursorManager::SXCursorManager::loadTheme(const std::string& name, int size) { + if (lastLoadSize == size && themeName == name) + return; + + lastLoadSize = size; + themeLoaded = false; + themeName = name.empty() ? "default" : name; + + auto img = XcursorShapeLoadImage(2, themeName.c_str(), size); + + if (!img) { + Debug::log(ERR, "XCursor failed finding theme \"{}\". Trying size 24.", themeName); + size = 24; + img = XcursorShapeLoadImage(2, themeName.c_str(), size); + if (!img) { + Debug::log(ERR, "XCursor failed finding theme \"{}\".", themeName); + return; } } - if (xSuccess && !diffTheme) { - m_szTheme = name; - m_iSize = size; - updateTheme(); - return true; + defaultCursor = makeShared(); + defaultCursor->size = {(int)img->width, (int)img->height}; + defaultCursor->hotspot = {(int)img->xhot, (int)img->yhot}; + + defaultCursor->pixels.resize(img->width * img->height); + std::memcpy(defaultCursor->pixels.data(), img->pixels, img->width * img->height * sizeof(uint32_t)); + + themeLoaded = true; + + XcursorImageDestroy(img); + + // gather as many shapes as we can find. + cursors.clear(); + + for (auto& shape : CURSOR_SHAPE_NAMES) { + int id = -1; + for (size_t i = 0; i < XCURSOR_STANDARD_NAMES.size(); ++i) { + if (XCURSOR_STANDARD_NAMES.at(i) == std::string{shape}) { + id = i; + break; + } + } + + if (id < 0) { + Debug::log(LOG, "XCursor has no shape {}, skipping", shape); + continue; + } + + auto xImage = XcursorShapeLoadImage(id << 1 /* wtf xcursor? */, themeName.c_str(), size); + + if (!xImage) { + Debug::log(LOG, "XCursor failed to find a shape with name {}, skipping", shape); + continue; + } + + auto xcursor = makeShared(); + xcursor->size = {(int)xImage->width, (int)xImage->height}; + xcursor->hotspot = {(int)xImage->xhot, (int)xImage->yhot}; + + xcursor->pixels.resize(xImage->width * xImage->height); + std::memcpy(xcursor->pixels.data(), xImage->pixels, xImage->width * xImage->height * sizeof(uint32_t)); + + cursors.emplace(std::string{shape}, xcursor); + + XcursorImageDestroy(xImage); } - - Debug::log(ERR, "X also failed loading theme \"{}\", falling back to previous theme.", name); - - m_pHyprcursor = std::make_unique(m_szTheme.c_str(), hcLogger); - - wlr_xcursor_manager_destroy(m_pWLRXCursorMgr); - m_pWLRXCursorMgr = wlr_xcursor_manager_create(m_szTheme.c_str(), m_iSize); - wlr_xcursor_manager_load(m_pWLRXCursorMgr, 1.0); - - updateTheme(); - return false; } diff --git a/src/managers/CursorManager.hpp b/src/managers/CursorManager.hpp index 3ee98ca6..4324dfb4 100644 --- a/src/managers/CursorManager.hpp +++ b/src/managers/CursorManager.hpp @@ -6,47 +6,51 @@ #include "../includes.hpp" #include "../helpers/math/Math.hpp" #include "../helpers/memory/Memory.hpp" +#include "../macros.hpp" +#include -struct wlr_buffer; -struct wlr_xcursor_manager; class CWLSurface; +AQUAMARINE_FORWARD(IBuffer); + class CCursorManager { public: CCursorManager(); ~CCursorManager(); - wlr_buffer* getCursorBuffer(); + SP getCursorBuffer(); - void setCursorFromName(const std::string& name); - void setCursorSurface(SP surf, const Vector2D& hotspot); - void setXCursor(const std::string& name); + void setCursorFromName(const std::string& name); + void setCursorSurface(SP surf, const Vector2D& hotspot); + void setXCursor(const std::string& name); - bool changeTheme(const std::string& name, const int size); - void updateTheme(); - SCursorImageData dataFor(const std::string& name); // for xwayland - void setXWaylandCursor(); + bool changeTheme(const std::string& name, const int size); + void updateTheme(); + SCursorImageData dataFor(const std::string& name); // for xwayland + void setXWaylandCursor(); - void tickAnimatedCursor(); + void tickAnimatedCursor(); - class CCursorBuffer { + class CCursorBuffer : public Aquamarine::IBuffer { public: CCursorBuffer(cairo_surface_t* surf, const Vector2D& size, const Vector2D& hotspot); CCursorBuffer(uint8_t* pixelData, const Vector2D& size, const Vector2D& hotspot); ~CCursorBuffer(); - struct SCursorWlrBuffer { - wlr_buffer base; - cairo_surface_t* surface = nullptr; - bool dropped = false; - CCursorBuffer* parent = nullptr; - uint8_t* pixelData = nullptr; - size_t stride = 0; - } wlrBuffer; + virtual Aquamarine::eBufferCapability caps(); + virtual Aquamarine::eBufferType type(); + virtual void update(const Hyprutils::Math::CRegion& damage); + virtual bool isSynchronous(); // whether the updates to this buffer are synchronous, aka happen over cpu + virtual bool good(); + virtual Aquamarine::SSHMAttrs shm(); + virtual std::tuple beginDataPtr(uint32_t flags); + virtual void endDataPtr(); private: - Vector2D size; - Vector2D hotspot; + Vector2D hotspot; + cairo_surface_t* surface = nullptr; + uint8_t* pixelData = nullptr; + size_t stride = 0; friend class CCursorManager; }; @@ -56,7 +60,7 @@ class CCursorManager { bool m_bOurBufferConnected = false; private: - std::vector> m_vCursorBuffers; + std::vector> m_vCursorBuffers; std::unique_ptr m_pHyprcursor; @@ -70,8 +74,24 @@ class CCursorManager { int m_iCurrentAnimationFrame = 0; Hyprcursor::SCursorShapeData m_sCurrentCursorShapeData; - // xcursor fallback - wlr_xcursor_manager* m_pWLRXCursorMgr = nullptr; + // gangsta bootleg XCursor impl. Whenever Hyprland has to use + // an xcursor, just use the pointer. + struct SXCursor { + Vector2D size; + Vector2D hotspot; + std::vector pixels; // XPixel is a u32 + }; + + struct SXCursorManager { + void loadTheme(const std::string& name, int size); + + int lastLoadSize = 0; + + bool themeLoaded = false; + std::string themeName = ""; + SP defaultCursor; + std::unordered_map> cursors; + } xcursor; }; inline std::unique_ptr g_pCursorManager; \ No newline at end of file diff --git a/src/managers/KeybindManager.cpp b/src/managers/KeybindManager.cpp index eb8a3232..e9dfd1ae 100644 --- a/src/managers/KeybindManager.cpp +++ b/src/managers/KeybindManager.cpp @@ -4,10 +4,12 @@ #include "../protocols/LayerShell.hpp" #include "../protocols/ShortcutsInhibit.hpp" #include "../render/decorations/CHyprGroupBarDecoration.hpp" +#include "../devices/IKeyboard.hpp" #include "KeybindManager.hpp" #include "PointerManager.hpp" #include "Compositor.hpp" #include "TokenManager.hpp" +#include "eventLoop/EventLoopManager.hpp" #include "debug/Log.hpp" #include "helpers/varlist/VarList.hpp" @@ -15,6 +17,7 @@ #include #include #include +#include #include using namespace Hyprutils::String; @@ -157,37 +160,37 @@ uint32_t CKeybindManager::stringToModMask(std::string mods) { uint32_t modMask = 0; std::transform(mods.begin(), mods.end(), mods.begin(), ::toupper); if (mods.contains("SHIFT")) - modMask |= WLR_MODIFIER_SHIFT; + modMask |= HL_MODIFIER_SHIFT; if (mods.contains("CAPS")) - modMask |= WLR_MODIFIER_CAPS; + modMask |= HL_MODIFIER_CAPS; if (mods.contains("CTRL") || mods.contains("CONTROL")) - modMask |= WLR_MODIFIER_CTRL; + modMask |= HL_MODIFIER_CTRL; if (mods.contains("ALT") || mods.contains("MOD1")) - modMask |= WLR_MODIFIER_ALT; + modMask |= HL_MODIFIER_ALT; if (mods.contains("MOD2")) - modMask |= WLR_MODIFIER_MOD2; + modMask |= HL_MODIFIER_MOD2; if (mods.contains("MOD3")) - modMask |= WLR_MODIFIER_MOD3; - if (mods.contains("SUPER") || mods.contains("WIN") || mods.contains("LOGO") || mods.contains("MOD4")) - modMask |= WLR_MODIFIER_LOGO; + modMask |= HL_MODIFIER_MOD3; + if (mods.contains("SUPER") || mods.contains("WIN") || mods.contains("LOGO") || mods.contains("MOD4") || mods.contains("META")) + modMask |= HL_MODIFIER_META; if (mods.contains("MOD5")) - modMask |= WLR_MODIFIER_MOD5; + modMask |= HL_MODIFIER_MOD5; return modMask; } uint32_t CKeybindManager::keycodeToModifier(xkb_keycode_t keycode) { switch (keycode - 8) { - case KEY_LEFTMETA: return WLR_MODIFIER_LOGO; - case KEY_RIGHTMETA: return WLR_MODIFIER_LOGO; - case KEY_LEFTSHIFT: return WLR_MODIFIER_SHIFT; - case KEY_RIGHTSHIFT: return WLR_MODIFIER_SHIFT; - case KEY_LEFTCTRL: return WLR_MODIFIER_CTRL; - case KEY_RIGHTCTRL: return WLR_MODIFIER_CTRL; - case KEY_LEFTALT: return WLR_MODIFIER_ALT; - case KEY_RIGHTALT: return WLR_MODIFIER_ALT; - case KEY_CAPSLOCK: return WLR_MODIFIER_CAPS; - case KEY_NUMLOCK: return WLR_MODIFIER_MOD2; + case KEY_LEFTMETA: return HL_MODIFIER_META; + case KEY_RIGHTMETA: return HL_MODIFIER_META; + case KEY_LEFTSHIFT: return HL_MODIFIER_SHIFT; + case KEY_RIGHTSHIFT: return HL_MODIFIER_SHIFT; + case KEY_LEFTCTRL: return HL_MODIFIER_CTRL; + case KEY_RIGHTCTRL: return HL_MODIFIER_CTRL; + case KEY_LEFTALT: return HL_MODIFIER_ALT; + case KEY_RIGHTALT: return HL_MODIFIER_ALT; + case KEY_CAPSLOCK: return HL_MODIFIER_CAPS; + case KEY_NUMLOCK: return HL_MODIFIER_MOD2; default: return 0; } } @@ -366,8 +369,8 @@ bool CKeybindManager::onKeyEvent(std::any event, SP pKeyboard) { const auto KEYCODE = e.keycode + 8; // Because to xkbcommon it's +8 from libinput - const xkb_keysym_t keysym = xkb_state_key_get_one_sym(pKeyboard->resolveBindsBySym ? pKeyboard->xkbTranslationState : m_pXKBTranslationState, KEYCODE); - const xkb_keysym_t internalKeysym = xkb_state_key_get_one_sym(pKeyboard->wlr()->xkb_state, KEYCODE); + const xkb_keysym_t keysym = xkb_state_key_get_one_sym(pKeyboard->resolveBindsBySym ? pKeyboard->xkbStaticState : m_pXKBTranslationState, KEYCODE); + const xkb_keysym_t internalKeysym = xkb_state_key_get_one_sym(pKeyboard->xkbState, KEYCODE); if (handleInternalKeybinds(internalKeysym)) return true; @@ -554,7 +557,7 @@ int repeatKeyHandler(void* data) { Debug::log(LOG, "Keybind repeat triggered, calling dispatcher."); DISPATCHER->second((*ppActiveKeybind)->arg); - wl_event_source_timer_update(g_pKeybindManager->m_pActiveKeybindEventSource, 1000 / g_pSeatManager->keyboard->wlr()->repeat_info.rate); + wl_event_source_timer_update(g_pKeybindManager->m_pActiveKeybindEventSource, 1000 / g_pSeatManager->keyboard->repeatRate); return 0; } @@ -786,7 +789,7 @@ bool CKeybindManager::handleVT(xkb_keysym_t keysym) { // beyond this point, return true to not handle anything else. // we'll avoid printing shit to active windows. - if (g_pCompositor->m_sWLRSession) { + if (g_pCompositor->m_pAqBackend->hasSession()) { const unsigned int TTY = keysym - XKB_KEY_XF86Switch_VT_1 + 1; // vtnr is bugged for some reason. @@ -810,8 +813,7 @@ bool CKeybindManager::handleVT(xkb_keysym_t keysym) { Debug::log(LOG, "Switching from VT {} to VT {}", ttynum, TTY); - wlr_session_change_vt(g_pCompositor->m_sWLRSession, TTY); - return true; + g_pCompositor->m_pAqBackend->session->switchVT(TTY); } return true; @@ -893,6 +895,7 @@ uint64_t CKeybindManager::spawnRaw(std::string args) { for (auto& e : HLENV) { setenv(e.first.c_str(), e.second.c_str(), 1); } + setenv("WAYLAND_DISPLAY", g_pCompositor->m_szWLDisplaySocket.c_str(), 1); close(socket[0]); close(socket[1]); execl("/bin/sh", "/bin/sh", "-c", args.c_str(), nullptr); @@ -1659,7 +1662,7 @@ void CKeybindManager::renameWorkspace(std::string args) { } void CKeybindManager::exitHyprland(std::string argz) { - g_pCompositor->m_bExitTriggered = true; + g_pEventLoopManager->doLater([]() { g_pCompositor->cleanup(); }); } void CKeybindManager::moveCurrentWorkspaceToMonitor(std::string args) { @@ -2121,8 +2124,8 @@ void CKeybindManager::sendshortcut(std::string args) { const auto KEYPAIRSTRING = std::format("{}{}", (uintptr_t)KB.get(), KEY); if (!g_pKeybindManager->m_mKeyToCodeCache.contains(KEYPAIRSTRING)) { - xkb_keymap* km = KB->wlr()->keymap; - xkb_state* ks = KB->xkbTranslationState; + xkb_keymap* km = KB->xkbKeymap; + xkb_state* ks = KB->xkbState; xkb_keycode_t keycode_min, keycode_max; keycode_min = xkb_keymap_min_keycode(km); @@ -2259,7 +2262,7 @@ void CKeybindManager::dpms(std::string arg) { if (!port.empty() && m->szName != port) continue; - wlr_output_state_set_enabled(m->state.wlr(), enable); + m->output->state->setEnabled(enable); m->dpmsStatus = enable; diff --git a/src/managers/KeybindManager.hpp b/src/managers/KeybindManager.hpp index 2a256760..284280cd 100644 --- a/src/managers/KeybindManager.hpp +++ b/src/managers/KeybindManager.hpp @@ -6,6 +6,7 @@ #include "../Compositor.hpp" #include #include +#include #include "../devices/IPointer.hpp" class CInputManager; diff --git a/src/managers/PointerManager.cpp b/src/managers/PointerManager.cpp index 7090645f..cf10db71 100644 --- a/src/managers/PointerManager.cpp +++ b/src/managers/PointerManager.cpp @@ -6,133 +6,8 @@ #include "../protocols/core/Compositor.hpp" #include "eventLoop/EventLoopManager.hpp" #include "SeatManager.hpp" -#include -#include -#include - -// TODO: make nicer -// this will come with the eventual rewrite of wlr_drm, etc... -static bool wlr_drm_format_intersect(wlr_drm_format* dst, const wlr_drm_format* a, const wlr_drm_format* b) { - ASSERT(a->format == b->format); - - size_t capacity = a->len < b->len ? a->len : b->len; - uint64_t* modifiers = (uint64_t*)malloc(sizeof(*modifiers) * capacity); - if (!modifiers) - return false; - - struct wlr_drm_format fmt = { - .format = a->format, - .len = 0, - .capacity = capacity, - .modifiers = modifiers, - }; - - for (size_t i = 0; i < a->len; i++) { - for (size_t j = 0; j < b->len; j++) { - if (a->modifiers[i] == b->modifiers[j]) { - ASSERT(fmt.len < fmt.capacity); - fmt.modifiers[fmt.len++] = a->modifiers[i]; - break; - } - } - } - - wlr_drm_format_finish(dst); - *dst = fmt; - return true; -} - -static bool wlr_drm_format_copy(wlr_drm_format* dst, const wlr_drm_format* src) { - ASSERT(src->len <= src->capacity); - - uint64_t* modifiers = (uint64_t*)malloc(sizeof(*modifiers) * src->len); - if (!modifiers) - return false; - - memcpy(modifiers, src->modifiers, sizeof(*modifiers) * src->len); - - wlr_drm_format_finish(dst); - dst->capacity = src->len; - dst->len = src->len; - dst->format = src->format; - dst->modifiers = modifiers; - return true; -} - -static const wlr_drm_format_set* wlr_renderer_get_render_formats(wlr_renderer* r) { - if (!r->impl->get_render_formats) - return nullptr; - - return r->impl->get_render_formats(r); -} - -static bool output_pick_format(wlr_output* output, const wlr_drm_format_set* display_formats, wlr_drm_format* format, uint32_t fmt) { - - const wlr_drm_format_set* render_formats = wlr_renderer_get_render_formats(g_pCompositor->m_sWLRRenderer); - if (render_formats == NULL) { - wlr_log(WLR_ERROR, "Failed to get render formats"); - return false; - } - - const wlr_drm_format* render_format = wlr_drm_format_set_get(render_formats, fmt); - if (render_format == NULL) { - wlr_log(WLR_DEBUG, "Renderer doesn't support format 0x%" PRIX32, fmt); - return false; - } - - if (display_formats != NULL) { - const wlr_drm_format* display_format = wlr_drm_format_set_get(display_formats, fmt); - if (display_format == NULL) { - wlr_log(WLR_DEBUG, "Output doesn't support format 0x%" PRIX32, fmt); - return false; - } - if (!wlr_drm_format_intersect(format, display_format, render_format)) { - wlr_log(WLR_DEBUG, - "Failed to intersect display and render " - "modifiers for format 0x%" PRIX32 " on output %s", - fmt, output->name); - return false; - } - } else { - // The output can display any format - if (!wlr_drm_format_copy(format, render_format)) - return false; - } - - if (format->len == 0) { - wlr_drm_format_finish(format); - wlr_log(WLR_DEBUG, "Failed to pick output format"); - return false; - } - - return true; -} - -static bool output_pick_cursor_format(struct wlr_output* output, struct wlr_drm_format* format) { - struct wlr_allocator* allocator = output->allocator; - ASSERT(allocator != NULL); - - const struct wlr_drm_format_set* display_formats = NULL; - if (output->impl->get_cursor_formats) { - display_formats = output->impl->get_cursor_formats(output, allocator->buffer_caps); - if (display_formats == NULL) { - wlr_log(WLR_DEBUG, "Failed to get cursor display formats"); - return false; - } - } - - // Note: taken from https://gitlab.freedesktop.org/wlroots/wlroots/-/merge_requests/4596/diffs#diff-content-e3ea164da86650995728d70bd118f6aa8c386797 - // If this fails to find a shared modifier try to use a linear - // modifier. This avoids a scenario where the hardware cannot render to - // linear textures but only linear textures are supported for cursors, - // as is the case with Nvidia and VmWare GPUs - if (!output_pick_format(output, display_formats, format, DRM_FORMAT_ARGB8888)) { - // Clear the format as output_pick_format doesn't zero it - memset(format, 0, sizeof(*format)); - return output_pick_format(output, NULL, format, DRM_FORMAT_ARGB8888); - } - return true; -} +#include +#include CPointerManager::CPointerManager() { hooks.monitorAdded = g_pHookSystem->hookDynamic("newMonitor", [this](void* self, SCallbackInfo& info, std::any data) { @@ -201,6 +76,11 @@ void CPointerManager::unlockSoftwareForMonitor(SP mon) { updateCursorBackend(); } +bool CPointerManager::softwareLockedFor(SP mon) { + auto state = stateFor(mon); + return state->softwareLocks > 0 || state->hardwareFailed; +} + Vector2D CPointerManager::position() { return pointerPos; } @@ -216,7 +96,7 @@ SP CPointerManager::stateFor(SP return *it; } -void CPointerManager::setCursorBuffer(wlr_buffer* buf, const Vector2D& hotspot, const float& scale) { +void CPointerManager::setCursorBuffer(SP buf, const Vector2D& hotspot, const float& scale) { damageIfSoftware(); if (buf == currentCursorImage.pBuffer) { if (hotspot != currentCursorImage.hotspot || scale != currentCursorImage.scale) { @@ -232,10 +112,8 @@ void CPointerManager::setCursorBuffer(wlr_buffer* buf, const Vector2D& hotspot, resetCursorImage(false); if (buf) { - currentCursorImage.size = {buf->width, buf->height}; - currentCursorImage.pBuffer = wlr_buffer_lock(buf); - - currentCursorImage.hyprListener_destroyBuffer.initCallback(&buf->events.destroy, [this](void* owner, void* data) { resetCursorImage(); }, this, "CPointerManager"); + currentCursorImage.size = buf->size; + currentCursorImage.pBuffer = buf; } currentCursorImage.hotspot = hotspot; @@ -317,8 +195,8 @@ void CPointerManager::recheckEnteredOutputs() { // if we are using hw cursors, prevent // the cursor from being stuck at the last point. // if we are leaving it, move it to narnia. - if (!s->hardwareFailed && s->monitor->output->impl->move_cursor) - s->monitor->output->impl->move_cursor(s->monitor->output, -1337, -420); + if (!s->hardwareFailed && (s->monitor->output->getBackend()->capabilities() & Aquamarine::IBackendImplementation::eBackendCapabilities::AQ_BACKEND_CAPABILITY_POINTER)) + s->monitor->output->moveCursor({-1337, -420}); if (!currentCursorImage.surface) continue; @@ -339,16 +217,11 @@ void CPointerManager::resetCursorImage(bool apply) { currentCursorImage.destroySurface.reset(); currentCursorImage.commitSurface.reset(); currentCursorImage.surface.reset(); - } else if (currentCursorImage.pBuffer) { - wlr_buffer_unlock(currentCursorImage.pBuffer); - currentCursorImage.hyprListener_destroyBuffer.removeCallback(); + } else if (currentCursorImage.pBuffer) currentCursorImage.pBuffer = nullptr; - } - if (currentCursorImage.pBufferTexture) { - wlr_texture_destroy(currentCursorImage.pBufferTexture); - currentCursorImage.pBufferTexture = nullptr; - } + if (currentCursorImage.bufferTex) + currentCursorImage.bufferTex = nullptr; currentCursorImage.scale = 1.F; currentCursorImage.hotspot = {0, 0}; @@ -370,9 +243,8 @@ void CPointerManager::resetCursorImage(bool apply) { } if (ms->cursorFrontBuffer) { - if (ms->monitor->output->impl->set_cursor) - ms->monitor->output->impl->set_cursor(ms->monitor->output, nullptr, 0, 0); - wlr_buffer_unlock(ms->cursorFrontBuffer); + if (ms->monitor->output->getBackend()->capabilities() & Aquamarine::IBackendImplementation::eBackendCapabilities::AQ_BACKEND_CAPABILITY_POINTER) + ms->monitor->output->setCursor(nullptr, {}); ms->cursorFrontBuffer = nullptr; } } @@ -418,18 +290,18 @@ void CPointerManager::onCursorMoved() { continue; const auto CURSORPOS = getCursorPosForMonitor(m); - m->output->impl->move_cursor(m->output, CURSORPOS.x, CURSORPOS.y); + m->output->moveCursor(CURSORPOS); } } bool CPointerManager::attemptHardwareCursor(SP state) { auto output = state->monitor->output; - if (!output->impl->set_cursor) + if (!(output->getBackend()->capabilities() & Aquamarine::IBackendImplementation::eBackendCapabilities::AQ_BACKEND_CAPABILITY_POINTER)) return false; const auto CURSORPOS = getCursorPosForMonitor(state->monitor.lock()); - state->monitor->output->impl->move_cursor(state->monitor->output, CURSORPOS.x, CURSORPOS.y); + state->monitor->output->moveCursor(CURSORPOS); auto texture = getCurrentCursorTexture(); @@ -459,64 +331,62 @@ bool CPointerManager::attemptHardwareCursor(SP state, wlr_buffer* buf) { - if (!state->monitor->output->impl->set_cursor) +bool CPointerManager::setHWCursorBuffer(SP state, SP buf) { + if (!(state->monitor->output->getBackend()->capabilities() & Aquamarine::IBackendImplementation::eBackendCapabilities::AQ_BACKEND_CAPABILITY_POINTER)) return false; const auto HOTSPOT = transformedHotspot(state->monitor.lock()); Debug::log(TRACE, "[pointer] hw transformed hotspot for {}: {}", state->monitor->szName, HOTSPOT); - if (!state->monitor->output->impl->set_cursor(state->monitor->output, buf, HOTSPOT.x, HOTSPOT.y)) + if (!state->monitor->output->setCursor(buf, HOTSPOT)) return false; - wlr_buffer_unlock(state->cursorFrontBuffer); state->cursorFrontBuffer = buf; - g_pCompositor->scheduleFrameForMonitor(state->monitor.get()); - - if (buf) - wlr_buffer_lock(buf); + g_pCompositor->scheduleFrameForMonitor(state->monitor.get(), Aquamarine::IOutput::AQ_SCHEDULE_CURSOR_SHAPE); return true; } -wlr_buffer* CPointerManager::renderHWCursorBuffer(SP state, SP texture) { +SP CPointerManager::renderHWCursorBuffer(SP state, SP texture) { auto output = state->monitor->output; - int w = currentCursorImage.size.x, h = currentCursorImage.size.y; - if (output->impl->get_cursor_size) { - output->impl->get_cursor_size(output, &w, &h); + auto maxSize = output->cursorPlaneSize(); + auto cursorSize = currentCursorImage.size; - if (w < currentCursorImage.size.x || h < currentCursorImage.size.y) { - Debug::log(TRACE, "hardware cursor too big! {} > {}x{}", currentCursorImage.size, w, h); - return nullptr; - } - } - - if (w <= 0 || h <= 0) { - Debug::log(TRACE, "hw cursor for output {} failed the size checks ({}x{} is invalid)", state->monitor->szName, w, h); + if (maxSize == Vector2D{}) return nullptr; - } - if (!output->cursor_swapchain || Vector2D{w, h} != Vector2D{output->cursor_swapchain->width, output->cursor_swapchain->height}) { - wlr_drm_format fmt = {0}; - if (!output_pick_cursor_format(output, &fmt)) { - Debug::log(TRACE, "Failed to pick cursor format"); + if (maxSize != Vector2D{-1, -1}) { + if (cursorSize.x > maxSize.x || cursorSize.y > maxSize.y) { + Debug::log(TRACE, "hardware cursor too big! {} > {}", currentCursorImage.size, maxSize); return nullptr; } + } else + maxSize = cursorSize; - wlr_swapchain_destroy(output->cursor_swapchain); - output->cursor_swapchain = wlr_swapchain_create(output->allocator, w, h, &fmt); - wlr_drm_format_finish(&fmt); + if (!state->monitor->cursorSwapchain || maxSize != state->monitor->cursorSwapchain->currentOptions().size) { - if (!output->cursor_swapchain) { - Debug::log(TRACE, "Failed to create cursor swapchain"); + if (!state->monitor->cursorSwapchain) + state->monitor->cursorSwapchain = Aquamarine::CSwapchain::create(state->monitor->output->getBackend()->preferredAllocator(), state->monitor->output->getBackend()); + + auto options = state->monitor->cursorSwapchain->currentOptions(); + options.size = maxSize; + options.length = 2; + options.scanout = true; + options.cursor = true; + options.multigpu = state->monitor->output->getBackend()->preferredAllocator()->drmFD() != g_pCompositor->m_iDRMFD; + // We do not set the format. If it's unset (DRM_FORMAT_INVALID) then the swapchain will pick for us, + // but if it's set, we don't wanna change it. + + if (!state->monitor->cursorSwapchain->reconfigure(options)) { + Debug::log(TRACE, "Failed to reconfigure cursor swapchain"); return nullptr; } } - wlr_buffer* buf = wlr_swapchain_acquire(output->cursor_swapchain, nullptr); + auto buf = state->monitor->cursorSwapchain->next(nullptr); if (!buf) { Debug::log(TRACE, "Failed to acquire a buffer from the cursor swapchain"); return nullptr; @@ -525,16 +395,45 @@ wlr_buffer* CPointerManager::renderHWCursorBuffer(SPmakeEGLCurrent(); - g_pHyprOpenGL->m_RenderData.pMonitor = state->monitor.get(); // has to be set cuz allocs + g_pHyprOpenGL->m_RenderData.pMonitor = state->monitor.get(); + + auto RBO = g_pHyprRenderer->getOrCreateRenderbuffer(buf, state->monitor->cursorSwapchain->currentOptions().format); + if (!RBO) { + Debug::log(TRACE, "Failed to create cursor RB with format {}, mod {}", buf->dmabuf().format, buf->dmabuf().modifier); + static auto PDUMB = CConfigValue("cursor:allow_dumb_copy"); + if (!*PDUMB) + return nullptr; + + auto bufData = buf->beginDataPtr(0); + auto bufPtr = std::get<0>(bufData); + + // clear buffer + memset(bufPtr, 0, std::get<2>(bufData)); + + auto texBuffer = currentCursorImage.pBuffer ? currentCursorImage.pBuffer : currentCursorImage.surface->resource()->current.buffer; + + if (texBuffer) { + auto textAttrs = texBuffer->shm(); + auto texData = texBuffer->beginDataPtr(GBM_BO_TRANSFER_WRITE); + auto texPtr = std::get<0>(texData); + Debug::log(TRACE, "cursor texture {}x{} {} {} {}", textAttrs.size.x, textAttrs.size.y, (void*)texPtr, textAttrs.format, textAttrs.stride); + // copy cursor texture + for (int i = 0; i < texBuffer->shm().size.y; i++) + memcpy(bufPtr + i * buf->dmabuf().strides[0], texPtr + i * textAttrs.stride, textAttrs.stride); + } + + buf->endDataPtr(); + + return buf; + } - const auto RBO = g_pHyprRenderer->getOrCreateRenderbuffer(buf, DRM_FORMAT_ARGB8888); RBO->bind(); g_pHyprOpenGL->beginSimple(state->monitor.get(), damage, RBO); g_pHyprOpenGL->clear(CColor{0.F, 0.F, 0.F, 0.F}); CBox xbox = {{}, Vector2D{currentCursorImage.size / currentCursorImage.scale * state->monitor->scale}.round()}; - Debug::log(TRACE, "[pointer] monitor: {}, size: {}, hw buf: {}, scale: {:.2f}, monscale: {:.2f}, xbox: {}", state->monitor->szName, currentCursorImage.size, Vector2D{w, h}, + Debug::log(TRACE, "[pointer] monitor: {}, size: {}, hw buf: {}, scale: {:.2f}, monscale: {:.2f}, xbox: {}", state->monitor->szName, currentCursorImage.size, cursorSize, currentCursorImage.scale, state->monitor->scale, xbox.size()); g_pHyprOpenGL->renderTexture(texture, &xbox, 1.F); @@ -543,9 +442,7 @@ wlr_buffer* CPointerManager::renderHWCursorBuffer(SPm_RenderData.pMonitor = nullptr; - g_pHyprRenderer->onRenderbufferDestroy(RBO); - - wlr_buffer_unlock(buf); + g_pHyprRenderer->onRenderbufferDestroy(RBO.get()); return buf; } @@ -579,7 +476,7 @@ void CPointerManager::renderSoftwareCursorsFor(SP pMonitor, timespec* box.x = std::round(box.x); box.y = std::round(box.y); - g_pHyprOpenGL->renderTextureWithDamage(texture, &box, &damage, 1.F); + g_pHyprOpenGL->renderTextureWithDamage(texture, &box, &damage, 1.F, 0, false, false, currentCursorImage.waitTimeline, currentCursorImage.waitPoint); if (currentCursorImage.surface) currentCursorImage.surface->resource()->frame(now); @@ -587,17 +484,19 @@ void CPointerManager::renderSoftwareCursorsFor(SP pMonitor, timespec* Vector2D CPointerManager::getCursorPosForMonitor(SP pMonitor) { return CBox{pointerPos - pMonitor->vecPosition, {0, 0}} - //.transform(pMonitor->transform, pMonitor->vecTransformedSize.x / pMonitor->scale, pMonitor->vecTransformedSize.y / pMonitor->scale) + .transform(wlTransformToHyprutils(invertTransform(pMonitor->transform)), pMonitor->vecTransformedSize.x / pMonitor->scale, + pMonitor->vecTransformedSize.y / pMonitor->scale) .pos() * pMonitor->scale; } Vector2D CPointerManager::transformedHotspot(SP pMonitor) { - if (!pMonitor->output->cursor_swapchain) + if (!pMonitor->cursorSwapchain) return {}; // doesn't matter, we have no hw cursor, and this is only for hw cursors return CBox{currentCursorImage.hotspot * pMonitor->scale, {0, 0}} - .transform(wlTransformToHyprutils(wlr_output_transform_invert(pMonitor->transform)), pMonitor->output->cursor_swapchain->width, pMonitor->output->cursor_swapchain->height) + .transform(wlTransformToHyprutils(invertTransform(pMonitor->transform)), pMonitor->cursorSwapchain->currentOptions().size.x, + pMonitor->cursorSwapchain->currentOptions().size.y) .pos(); } @@ -799,10 +698,8 @@ SP CPointerManager::getCurrentCursorTexture() { return nullptr; if (currentCursorImage.pBuffer) { - if (!currentCursorImage.pBufferTexture) { - currentCursorImage.pBufferTexture = wlr_texture_from_buffer(g_pCompositor->m_sWLRRenderer, currentCursorImage.pBuffer); - currentCursorImage.bufferTex = makeShared(currentCursorImage.pBufferTexture); - } + if (!currentCursorImage.bufferTex) + currentCursorImage.bufferTex = makeShared(currentCursorImage.pBuffer); return currentCursorImage.bufferTex; } diff --git a/src/managers/PointerManager.hpp b/src/managers/PointerManager.hpp index da639340..cf4f1a94 100644 --- a/src/managers/PointerManager.hpp +++ b/src/managers/PointerManager.hpp @@ -6,13 +6,15 @@ #include "../helpers/math/Math.hpp" #include "../helpers/math/Math.hpp" #include "../desktop/WLSurface.hpp" +#include "../helpers/sync/SyncTimeline.hpp" #include class CMonitor; -struct wlr_input_device; class IHID; class CTexture; +AQUAMARINE_FORWARD(IBuffer); + /* The naming here is a bit confusing. CPointerManager manages the _position_ and _displaying_ of the cursor, @@ -37,7 +39,7 @@ class CPointerManager { void move(const Vector2D& deltaLogical); void warpAbsolute(Vector2D abs, SP dev); - void setCursorBuffer(wlr_buffer* buf, const Vector2D& hotspot, const float& scale); + void setCursorBuffer(SP buf, const Vector2D& hotspot, const float& scale); void setCursorSurface(SP buf, const Vector2D& hotspot); void resetCursorImage(bool apply = true); @@ -47,6 +49,7 @@ class CPointerManager { void unlockSoftwareForMonitor(CMonitor* pMonitor); void lockSoftwareAll(); void unlockSoftwareAll(); + bool softwareLockedFor(SP pMonitor); void renderSoftwareCursorsFor(SP pMonitor, timespec* now, CRegion& damage /* logical */, std::optional overridePos = {} /* monitor-local */); @@ -135,45 +138,42 @@ class CPointerManager { } currentMonitorLayout; struct { - wlr_buffer* pBuffer = nullptr; - SP bufferTex; - WP surface; - wlr_texture* pBufferTexture = nullptr; + SP pBuffer; + SP bufferTex; + WP surface; - Vector2D hotspot; - Vector2D size; - float scale = 1.F; + Vector2D hotspot; + Vector2D size; + float scale = 1.F; - CHyprSignalListener destroySurface; - CHyprSignalListener commitSurface; - DYNLISTENER(destroyBuffer); + CHyprSignalListener destroySurface; + CHyprSignalListener commitSurface; + SP waitTimeline = nullptr; + uint64_t waitPoint = 0; } currentCursorImage; // TODO: support various sizes per-output so we can have pixel-perfect cursors Vector2D pointerPos = {0, 0}; struct SMonitorPointerState { SMonitorPointerState(SP m) : monitor(m) {} - ~SMonitorPointerState() { - if (cursorFrontBuffer) - wlr_buffer_unlock(cursorFrontBuffer); - } + ~SMonitorPointerState() {} - WP monitor; + WP monitor; - int softwareLocks = 0; - bool hardwareFailed = false; - CBox box; // logical - bool entered = false; - bool hwApplied = false; + int softwareLocks = 0; + bool hardwareFailed = false; + CBox box; // logical + bool entered = false; + bool hwApplied = false; - wlr_buffer* cursorFrontBuffer = nullptr; + SP cursorFrontBuffer; }; std::vector> monitorStates; SP stateFor(SP mon); bool attemptHardwareCursor(SP state); - wlr_buffer* renderHWCursorBuffer(SP state, SP texture); - bool setHWCursorBuffer(SP state, wlr_buffer* buf); + SP renderHWCursorBuffer(SP state, SP texture); + bool setHWCursorBuffer(SP state, SP buf); struct { SP monitorAdded; diff --git a/src/managers/ProtocolManager.cpp b/src/managers/ProtocolManager.cpp index 74cebd0c..387cac8f 100644 --- a/src/managers/ProtocolManager.cpp +++ b/src/managers/ProtocolManager.cpp @@ -1,5 +1,7 @@ #include "ProtocolManager.hpp" +#include "../config/ConfigValue.hpp" + #include "../protocols/TearingControl.hpp" #include "../protocols/FractionalScale.hpp" #include "../protocols/XDGOutput.hpp" @@ -35,6 +37,8 @@ #include "../protocols/Viewporter.hpp" #include "../protocols/MesaDRM.hpp" #include "../protocols/LinuxDMABUF.hpp" +#include "../protocols/DRMLease.hpp" +#include "../protocols/DRMSyncobj.hpp" #include "../protocols/core/Seat.hpp" #include "../protocols/core/DataDevice.hpp" @@ -45,6 +49,10 @@ #include "../helpers/Monitor.hpp" #include "../render/Renderer.hpp" +#include "../Compositor.hpp" + +#include +#include void CProtocolManager::onMonitorModeChange(CMonitor* pMonitor) { const bool ISMIRROR = pMonitor->isMirror(); @@ -65,6 +73,8 @@ void CProtocolManager::onMonitorModeChange(CMonitor* pMonitor) { CProtocolManager::CProtocolManager() { + static const auto PENABLEEXPLICIT = CConfigValue("experimental:explicit_sync"); + // Outputs are a bit dumb, we have to agree. static auto P = g_pHookSystem->hookDynamic("monitorAdded", [this](void* self, SCallbackInfo& info, std::any param) { auto M = std::any_cast(param); @@ -131,6 +141,16 @@ CProtocolManager::CProtocolManager() { PROTO::primarySelection = std::make_unique(&zwp_primary_selection_device_manager_v1_interface, 1, "PrimarySelection"); PROTO::xwaylandShell = std::make_unique(&xwayland_shell_v1_interface, 1, "XWaylandShell"); + for (auto& b : g_pCompositor->m_pAqBackend->getImplementations()) { + if (b->type() != Aquamarine::AQ_BACKEND_DRM) + continue; + + PROTO::lease = std::make_unique(&wp_drm_lease_device_v1_interface, 1, "DRMLease"); + if (*PENABLEEXPLICIT) + PROTO::sync = std::make_unique(&wp_linux_drm_syncobj_manager_v1_interface, 1, "DRMSyncobj"); + break; + } + if (g_pHyprOpenGL->getDRMFormats().size() > 0) { PROTO::mesaDRM = std::make_unique(&wl_drm_interface, 2, "MesaDRM"); PROTO::linuxDma = std::make_unique(&zwp_linux_dmabuf_v1_interface, 5, "LinuxDMABUF"); diff --git a/src/managers/SeatManager.cpp b/src/managers/SeatManager.cpp index 6589c4bf..801ae55a 100644 --- a/src/managers/SeatManager.cpp +++ b/src/managers/SeatManager.cpp @@ -94,8 +94,8 @@ void CSeatManager::setKeyboard(SP KEEB) { } void CSeatManager::updateActiveKeyboardData() { - if (keyboard && keyboard->wlr()) - PROTO::seat->updateRepeatInfo(keyboard->wlr()->repeat_info.rate, keyboard->wlr()->repeat_info.delay); + if (keyboard) + PROTO::seat->updateRepeatInfo(keyboard->repeatRate, keyboard->repeatDelay); PROTO::seat->updateKeymap(); } @@ -103,7 +103,7 @@ void CSeatManager::setKeyboardFocus(SP surf) { if (state.keyboardFocus == surf) return; - if (!keyboard || !keyboard->wlr()) { + if (!keyboard) { Debug::log(ERR, "BUG THIS: setKeyboardFocus without a valid keyboard set"); return; } @@ -144,7 +144,7 @@ void CSeatManager::setKeyboardFocus(SP surf) { continue; k->sendEnter(surf); - k->sendMods(keyboard->wlr()->modifiers.depressed, keyboard->wlr()->modifiers.latched, keyboard->wlr()->modifiers.locked, keyboard->wlr()->modifiers.group); + k->sendMods(keyboard->modifiersState.depressed, keyboard->modifiersState.latched, keyboard->modifiersState.locked, keyboard->modifiersState.group); } } @@ -196,7 +196,7 @@ void CSeatManager::setPointerFocus(SP surf, const Vector2D& return; } - if (!mouse || !mouse->wlr()) { + if (!mouse) { Debug::log(ERR, "BUG THIS: setPointerFocus without a valid mouse set"); return; } diff --git a/src/managers/eventLoop/EventLoopManager.cpp b/src/managers/eventLoop/EventLoopManager.cpp index 0d1b0223..ed7a4f72 100644 --- a/src/managers/eventLoop/EventLoopManager.cpp +++ b/src/managers/eventLoop/EventLoopManager.cpp @@ -1,5 +1,6 @@ #include "EventLoopManager.hpp" #include "../../debug/Log.hpp" +#include "../../Compositor.hpp" #include #include @@ -7,6 +8,8 @@ #include #include +#include + #define TIMESPEC_NSEC_PER_SEC 1000000000L CEventLoopManager::CEventLoopManager(wl_display* display, wl_event_loop* wlEventLoop) { @@ -25,9 +28,21 @@ static int timerWrite(int fd, uint32_t mask, void* data) { return 1; } +static int aquamarineFDWrite(int fd, uint32_t mask, void* data) { + auto POLLFD = (Aquamarine::SPollFD*)data; + POLLFD->onSignal(); + return 1; +} + void CEventLoopManager::enterLoop() { m_sWayland.eventSource = wl_event_loop_add_fd(m_sWayland.loop, m_sTimers.timerfd, WL_EVENT_READABLE, timerWrite, nullptr); + aqPollFDs = g_pCompositor->m_pAqBackend->getPollFDs(); + for (auto& fd : aqPollFDs) { + m_sWayland.aqEventSources.emplace_back(wl_event_loop_add_fd(m_sWayland.loop, fd->fd, WL_EVENT_READABLE, aquamarineFDWrite, fd.get())); + fd->onSignal(); // dispatch outstanding + } + wl_display_run(m_sWayland.display); Debug::log(LOG, "Kicked off the event loop! :("); diff --git a/src/managers/eventLoop/EventLoopManager.hpp b/src/managers/eventLoop/EventLoopManager.hpp index 0b2f9578..39d8bbeb 100644 --- a/src/managers/eventLoop/EventLoopManager.hpp +++ b/src/managers/eventLoop/EventLoopManager.hpp @@ -7,6 +7,10 @@ #include "EventLoopTimer.hpp" +namespace Aquamarine { + struct SPollFD; +}; + class CEventLoopManager { public: CEventLoopManager(wl_display* display, wl_event_loop* wlEventLoop); @@ -33,9 +37,10 @@ class CEventLoopManager { private: struct { - wl_event_loop* loop = nullptr; - wl_display* display = nullptr; - wl_event_source* eventSource = nullptr; + wl_event_loop* loop = nullptr; + wl_display* display = nullptr; + wl_event_source* eventSource = nullptr; + std::vector aqEventSources; } m_sWayland; struct { @@ -43,7 +48,10 @@ class CEventLoopManager { int timerfd = -1; } m_sTimers; - SIdleData m_sIdle; + SIdleData m_sIdle; + std::vector> aqPollFDs; + + friend class CSyncTimeline; }; inline std::unique_ptr g_pEventLoopManager; \ No newline at end of file diff --git a/src/managers/input/InputManager.cpp b/src/managers/input/InputManager.cpp index 23e183d0..255023b9 100644 --- a/src/managers/input/InputManager.cpp +++ b/src/managers/input/InputManager.cpp @@ -1,6 +1,6 @@ #include "InputManager.hpp" #include "../../Compositor.hpp" -#include "wlr/types/wlr_switch.h" +#include #include #include #include "../../config/ConfigValue.hpp" @@ -28,6 +28,8 @@ #include "../../managers/PointerManager.hpp" #include "../../managers/SeatManager.hpp" +#include + CInputManager::CInputManager() { m_sListeners.setCursorShape = PROTO::cursorShape->events.setShape.registerListener([this](std::any data) { if (!cursorImageUnlocked()) @@ -189,8 +191,8 @@ void CInputManager::mouseMoveUnified(uint32_t time, bool refocus) { bool skipFrameSchedule = PMONITOR->shouldSkipScheduleFrameOnMouseEvent(); - if (!PMONITOR->solitaryClient.lock() && g_pHyprRenderer->shouldRenderCursor() && PMONITOR->output->software_cursor_locks > 0 && !skipFrameSchedule) - g_pCompositor->scheduleFrameForMonitor(PMONITOR); + if (!PMONITOR->solitaryClient.lock() && g_pHyprRenderer->shouldRenderCursor() && g_pPointerManager->softwareLockedFor(PMONITOR->self.lock()) && !skipFrameSchedule) + g_pCompositor->scheduleFrameForMonitor(PMONITOR, Aquamarine::IOutput::AQ_SCHEDULE_CURSOR_MOVE); PHLWINDOW forcedFocus = m_pForcedFocus.lock(); @@ -372,8 +374,8 @@ void CInputManager::mouseMoveUnified(uint32_t time, bool refocus) { foundSurface = g_pCompositor->vectorToLayerSurface(mouseCoords, &PMONITOR->m_aLayerSurfaceLayers[ZWLR_LAYER_SHELL_V1_LAYER_BACKGROUND], &surfaceCoords, &pFoundLayerSurface); - if (g_pCompositor->m_pLastMonitor->output->software_cursor_locks > 0 && !skipFrameSchedule) - g_pCompositor->scheduleFrameForMonitor(g_pCompositor->m_pLastMonitor.get()); + if (g_pPointerManager->softwareLockedFor(PMONITOR->self.lock()) > 0 && !skipFrameSchedule) + g_pCompositor->scheduleFrameForMonitor(g_pCompositor->m_pLastMonitor.get(), Aquamarine::IOutput::AQ_SCHEDULE_CURSOR_MOVE); // grabs if (g_pSeatManager->seatGrab && !g_pSeatManager->seatGrab->accepts(foundSurface)) { @@ -843,8 +845,8 @@ Vector2D CInputManager::getMouseCoordsInternal() { return g_pPointerManager->position(); } -void CInputManager::newKeyboard(wlr_input_device* keyboard) { - const auto PNEWKEYBOARD = m_vKeyboards.emplace_back(CKeyboard::create(wlr_keyboard_from_input_device(keyboard))); +void CInputManager::newKeyboard(SP keyboard) { + const auto PNEWKEYBOARD = m_vKeyboards.emplace_back(CKeyboard::create(keyboard)); setupKeyboard(PNEWKEYBOARD); @@ -856,14 +858,14 @@ void CInputManager::newVirtualKeyboard(SP keyboard) setupKeyboard(PNEWKEYBOARD); - Debug::log(LOG, "New virtual keyboard created, pointers Hypr: {:x} and WLR: {:x}", (uintptr_t)PNEWKEYBOARD.get(), (uintptr_t)keyboard->wlr()); + Debug::log(LOG, "New virtual keyboard created at {:x}", (uintptr_t)PNEWKEYBOARD.get()); } void CInputManager::setupKeyboard(SP keeb) { m_vHIDs.push_back(keeb); try { - keeb->hlName = getNameForNewDevice(keeb->wlr()->base.name); + keeb->hlName = getNameForNewDevice(keeb->deviceName); } catch (std::exception& e) { Debug::log(ERR, "Keyboard had no name???"); // logic error } @@ -962,83 +964,12 @@ void CInputManager::applyConfigToKeyboard(SP pKeyboard) { // we can ignore those and just apply } - wlr_keyboard_set_repeat_info(pKeyboard->wlr(), std::max(0, REPEATRATE), std::max(0, REPEATDELAY)); - - pKeyboard->repeatDelay = REPEATDELAY; - pKeyboard->repeatRate = REPEATRATE; + pKeyboard->repeatRate = std::max(0, REPEATRATE); + pKeyboard->repeatDelay = std::max(0, REPEATDELAY); pKeyboard->numlockOn = NUMLOCKON; pKeyboard->xkbFilePath = FILEPATH; - xkb_rule_names rules = {.rules = RULES.c_str(), .model = MODEL.c_str(), .layout = LAYOUT.c_str(), .variant = VARIANT.c_str(), .options = OPTIONS.c_str()}; - - pKeyboard->currentRules.rules = RULES; - pKeyboard->currentRules.model = MODEL; - pKeyboard->currentRules.variant = VARIANT; - pKeyboard->currentRules.options = OPTIONS; - pKeyboard->currentRules.layout = LAYOUT; - - const auto CONTEXT = xkb_context_new(XKB_CONTEXT_NO_FLAGS); - - if (!CONTEXT) { - Debug::log(ERR, "applyConfigToKeyboard: CONTEXT null??"); - return; - } - - Debug::log(LOG, "Attempting to create a keymap for layout {} with variant {} (rules: {}, model: {}, options: {})", rules.layout, rules.variant, rules.rules, rules.model, - rules.options); - - xkb_keymap* KEYMAP = NULL; - - if (!FILEPATH.empty()) { - auto path = absolutePath(FILEPATH, g_pConfigManager->configCurrentPath); - - if (FILE* const KEYMAPFILE = fopen(path.c_str(), "r"); !KEYMAPFILE) - Debug::log(ERR, "Cannot open input:kb_file= file for reading"); - else { - KEYMAP = xkb_keymap_new_from_file(CONTEXT, KEYMAPFILE, XKB_KEYMAP_FORMAT_TEXT_V1, XKB_KEYMAP_COMPILE_NO_FLAGS); - fclose(KEYMAPFILE); - } - } - - if (!KEYMAP) - KEYMAP = xkb_keymap_new_from_names(CONTEXT, &rules, XKB_KEYMAP_COMPILE_NO_FLAGS); - - if (!KEYMAP) { - g_pConfigManager->addParseError("Invalid keyboard layout passed. ( rules: " + RULES + ", model: " + MODEL + ", variant: " + VARIANT + ", options: " + OPTIONS + - ", layout: " + LAYOUT + " )"); - - Debug::log(ERR, "Keyboard layout {} with variant {} (rules: {}, model: {}, options: {}) couldn't have been loaded.", rules.layout, rules.variant, rules.rules, rules.model, - rules.options); - memset(&rules, 0, sizeof(rules)); - - pKeyboard->currentRules.rules = ""; - pKeyboard->currentRules.model = ""; - pKeyboard->currentRules.variant = ""; - pKeyboard->currentRules.options = ""; - pKeyboard->currentRules.layout = "us"; - - KEYMAP = xkb_keymap_new_from_names(CONTEXT, &rules, XKB_KEYMAP_COMPILE_NO_FLAGS); - } - - wlr_keyboard_set_keymap(pKeyboard->wlr(), KEYMAP); - - pKeyboard->updateXKBTranslationState(); - - wlr_keyboard_modifiers wlrMods = {0}; - - if (NUMLOCKON == 1) { - // lock numlock - const auto IDX = xkb_map_mod_get_index(KEYMAP, XKB_MOD_NAME_NUM); - - if (IDX != XKB_MOD_INVALID) - wlrMods.locked |= (uint32_t)1 << IDX; - } - - if (wlrMods.locked != 0) - wlr_keyboard_notify_modifiers(pKeyboard->wlr(), 0, 0, wlrMods.locked, 0); - - xkb_keymap_unref(KEYMAP); - xkb_context_unref(CONTEXT); + pKeyboard->setKeymap(IKeyboard::SStringRuleNames{LAYOUT, MODEL, VARIANT, OPTIONS, RULES}); const auto LAYOUTSTR = pKeyboard->getActiveLayout(); @@ -1053,11 +984,11 @@ void CInputManager::newVirtualMouse(SP mouse) { setupMouse(PMOUSE); - Debug::log(LOG, "New virtual mouse created, pointer WLR: {:x}", (uintptr_t)mouse->wlr()); + Debug::log(LOG, "New virtual mouse created"); } -void CInputManager::newMouse(wlr_input_device* mouse) { - const auto PMOUSE = m_vPointers.emplace_back(CMouse::create(wlr_pointer_from_input_device(mouse))); +void CInputManager::newMouse(SP mouse) { + const auto PMOUSE = m_vPointers.emplace_back(CMouse::create(mouse)); setupMouse(PMOUSE); @@ -1068,13 +999,13 @@ void CInputManager::setupMouse(SP mauz) { m_vHIDs.push_back(mauz); try { - mauz->hlName = getNameForNewDevice(mauz->wlr()->base.name); + mauz->hlName = getNameForNewDevice(mauz->deviceName); } catch (std::exception& e) { Debug::log(ERR, "Mouse had no name???"); // logic error } - if (wlr_input_device_is_libinput(&mauz->wlr()->base)) { - const auto LIBINPUTDEV = (libinput_device*)wlr_libinput_get_device_handle(&mauz->wlr()->base); + if (mauz->aq() && mauz->aq()->getLibinputHandle()) { + const auto LIBINPUTDEV = mauz->aq()->getLibinputHandle(); Debug::log(LOG, "New mouse has libinput sens {:.2f} ({:.2f}) with accel profile {} ({})", libinput_device_config_accel_get_speed(LIBINPUTDEV), libinput_device_config_accel_get_default_speed(LIBINPUTDEV), (int)libinput_device_config_accel_get_profile(LIBINPUTDEV), @@ -1120,8 +1051,8 @@ void CInputManager::setPointerConfigs() { } } - if (wlr_input_device_is_libinput(&m->wlr()->base)) { - const auto LIBINPUTDEV = (libinput_device*)wlr_libinput_get_device_handle(&m->wlr()->base); + if (m->aq() && m->aq()->getLibinputHandle()) { + const auto LIBINPUTDEV = m->aq()->getLibinputHandle(); double touchw = 0, touchh = 0; const auto ISTOUCHPAD = libinput_device_has_capability(LIBINPUTDEV, LIBINPUT_DEVICE_CAP_POINTER) && @@ -1261,16 +1192,14 @@ static void removeFromHIDs(WP hid) { } void CInputManager::destroyKeyboard(SP pKeyboard) { - if (pKeyboard->xkbTranslationState) - xkb_state_unref(pKeyboard->xkbTranslationState); - pKeyboard->xkbTranslationState = nullptr; + Debug::log(LOG, "Keyboard at {:x} removed", (uintptr_t)pKeyboard.get()); std::erase_if(m_vKeyboards, [pKeyboard](const auto& other) { return other == pKeyboard; }); if (m_vKeyboards.size() > 0) { bool found = false; for (auto& k : m_vKeyboards | std::views::reverse) { - if (!k->wlr()) + if (!k) continue; g_pSeatManager->setKeyboard(k); @@ -1287,6 +1216,8 @@ void CInputManager::destroyKeyboard(SP pKeyboard) { } void CInputManager::destroyPointer(SP mouse) { + Debug::log(LOG, "Pointer at {:x} removed", (uintptr_t)mouse.get()); + std::erase_if(m_vPointers, [mouse](const auto& other) { return other == mouse; }); g_pSeatManager->setMouse(m_vPointers.size() > 0 ? m_vPointers.front() : nullptr); @@ -1333,20 +1264,7 @@ void CInputManager::updateKeyboardsLeds(SP pKeyboard) { if (!pKeyboard) return; - auto keyboard = pKeyboard->wlr(); - - if (!keyboard || keyboard->xkb_state == nullptr) - return; - - uint32_t leds = 0; - for (uint32_t i = 0; i < WLR_LED_COUNT; ++i) { - if (xkb_state_led_index_is_active(keyboard->xkb_state, keyboard->led_indexes[i])) - leds |= (1 << i); - } - - for (auto& k : m_vKeyboards) { - k->updateLEDs(leds); - } + pKeyboard->updateLEDs(); } void CInputManager::onKeyboardKey(std::any event, SP pKeyboard) { @@ -1374,7 +1292,7 @@ void CInputManager::onKeyboardKey(std::any event, SP pKeyboard) { const auto IME = m_sIMERelay.m_pIME.lock(); if (IME && IME->hasGrab() && !DISALLOWACTION) { - IME->setKeyboard(pKeyboard->wlr()); + IME->setKeyboard(pKeyboard); IME->sendKey(e.timeMs, e.keycode, e.state); } else { g_pSeatManager->setKeyboard(pKeyboard); @@ -1392,15 +1310,14 @@ void CInputManager::onKeyboardMod(SP pKeyboard) { const bool DISALLOWACTION = pKeyboard->isVirtual() && shouldIgnoreVirtualKeyboard(pKeyboard); const auto ALLMODS = accumulateModsFromAllKBs(); - const auto PWLRKB = pKeyboard->wlr(); - auto MODS = PWLRKB->modifiers; + auto MODS = pKeyboard->modifiersState; MODS.depressed = ALLMODS; const auto IME = m_sIMERelay.m_pIME.lock(); if (IME && IME->hasGrab() && !DISALLOWACTION) { - IME->setKeyboard(PWLRKB); + IME->setKeyboard(pKeyboard); IME->sendMods(MODS.depressed, MODS.latched, MODS.locked, MODS.group); } else { g_pSeatManager->setKeyboard(pKeyboard); @@ -1409,12 +1326,12 @@ void CInputManager::onKeyboardMod(SP pKeyboard) { updateKeyboardsLeds(pKeyboard); - if (PWLRKB->modifiers.group != pKeyboard->activeLayout) { - pKeyboard->activeLayout = PWLRKB->modifiers.group; + if (pKeyboard->modifiersState.group != pKeyboard->activeLayout) { + pKeyboard->activeLayout = pKeyboard->modifiersState.group; const auto LAYOUT = pKeyboard->getActiveLayout(); - pKeyboard->updateXKBTranslationState(); + Debug::log(LOG, "LAYOUT CHANGED TO {} GROUP {}", LAYOUT, MODS.group); g_pEventManager->postEvent(SHyprIPCEvent{"activelayout", pKeyboard->hlName + "," + LAYOUT}); EMIT_HOOK_EVENT("activeLayout", (std::vector{pKeyboard, LAYOUT})); @@ -1524,10 +1441,10 @@ uint32_t CInputManager::accumulateModsFromAllKBs() { if (kb->isVirtual() && shouldIgnoreVirtualKeyboard(kb)) continue; - if (!kb->enabled || !kb->wlr()) + if (!kb->enabled) continue; - finalMask |= wlr_keyboard_get_modifiers(kb->wlr()); + finalMask |= kb->getModifiers(); } return finalMask; @@ -1543,12 +1460,12 @@ void CInputManager::disableAllKeyboards(bool virt) { } } -void CInputManager::newTouchDevice(wlr_input_device* pDevice) { - const auto PNEWDEV = m_vTouches.emplace_back(CTouchDevice::create(wlr_touch_from_input_device(pDevice))); +void CInputManager::newTouchDevice(SP pDevice) { + const auto PNEWDEV = m_vTouches.emplace_back(CTouchDevice::create(pDevice)); m_vHIDs.push_back(PNEWDEV); try { - PNEWDEV->hlName = getNameForNewDevice(pDevice->name); + PNEWDEV->hlName = getNameForNewDevice(PNEWDEV->deviceName); } catch (std::exception& e) { Debug::log(ERR, "Touch Device had no name???"); // logic error } @@ -1572,8 +1489,8 @@ void CInputManager::newTouchDevice(wlr_input_device* pDevice) { void CInputManager::setTouchDeviceConfigs(SP dev) { auto setConfig = [&](SP PTOUCHDEV) -> void { - if (wlr_input_device_is_libinput(&PTOUCHDEV->wlr()->base)) { - const auto LIBINPUTDEV = (libinput_device*)wlr_libinput_get_device_handle(&PTOUCHDEV->wlr()->base); + if (dev->aq() && dev->aq()->getLibinputHandle()) { + const auto LIBINPUTDEV = dev->aq()->getLibinputHandle(); const auto ENABLED = g_pConfigManager->getDeviceInt(PTOUCHDEV->hlName, "enabled", "input:touchdevice:enabled"); const auto mode = ENABLED ? LIBINPUT_CONFIG_SEND_EVENTS_ENABLED : LIBINPUT_CONFIG_SEND_EVENTS_DISABLED; @@ -1589,11 +1506,12 @@ void CInputManager::setTouchDeviceConfigs(SP dev) { bool bound = !output.empty() && output != STRVAL_EMPTY; const bool AUTODETECT = output == "[[Auto]]"; if (!bound && AUTODETECT) { - const auto DEFAULTOUTPUT = PTOUCHDEV->wlr()->output_name; - if (DEFAULTOUTPUT) { - output = DEFAULTOUTPUT; - bound = true; - } + // FIXME: + // const auto DEFAULTOUTPUT = PTOUCHDEV->wlr()->output_name; + // if (DEFAULTOUTPUT) { + // output = DEFAULTOUTPUT; + // bound = true; + // } } PTOUCHDEV->boundOutput = bound ? output : ""; const auto PMONITOR = bound ? g_pCompositor->getMonitorFromName(output) : nullptr; @@ -1617,9 +1535,9 @@ void CInputManager::setTouchDeviceConfigs(SP dev) { void CInputManager::setTabletConfigs() { for (auto& t : m_vTablets) { - if (wlr_input_device_is_libinput(&t->wlr()->base)) { + if (t->aq()->getLibinputHandle()) { const auto NAME = t->hlName; - const auto LIBINPUTDEV = (libinput_device*)wlr_libinput_get_device_handle(&t->wlr()->base); + const auto LIBINPUTDEV = t->aq()->getLibinputHandle(); const auto RELINPUT = g_pConfigManager->getDeviceInt(NAME, "relative_input", "input:tablet:relative_input"); t->relativeInput = RELINPUT; @@ -1647,51 +1565,37 @@ void CInputManager::setTabletConfigs() { const auto ACTIVE_AREA_SIZE = g_pConfigManager->getDeviceVec(NAME, "active_area_size", "input:tablet:active_area_size"); const auto ACTIVE_AREA_POS = g_pConfigManager->getDeviceVec(NAME, "active_area_position", "input:tablet:active_area_position"); if (ACTIVE_AREA_SIZE.x != 0 || ACTIVE_AREA_SIZE.y != 0) { - t->activeArea = CBox{ACTIVE_AREA_POS.x / t->wlr()->width_mm, ACTIVE_AREA_POS.y / t->wlr()->height_mm, (ACTIVE_AREA_POS.x + ACTIVE_AREA_SIZE.x) / t->wlr()->width_mm, - (ACTIVE_AREA_POS.y + ACTIVE_AREA_SIZE.y) / t->wlr()->height_mm}; + t->activeArea = CBox{ACTIVE_AREA_POS.x / t->aq()->physicalSize.x, ACTIVE_AREA_POS.y / t->aq()->physicalSize.y, + (ACTIVE_AREA_POS.x + ACTIVE_AREA_SIZE.x) / t->aq()->physicalSize.x, (ACTIVE_AREA_POS.y + ACTIVE_AREA_SIZE.y) / t->aq()->physicalSize.y}; } } } } -void CInputManager::newSwitch(wlr_input_device* pDevice) { - const auto PNEWDEV = &m_lSwitches.emplace_back(); - PNEWDEV->pWlrDevice = pDevice; +void CInputManager::newSwitch(SP pDevice) { + const auto PNEWDEV = &m_lSwitches.emplace_back(); + PNEWDEV->pDevice = pDevice; - Debug::log(LOG, "New switch with name \"{}\" added", pDevice->name); + Debug::log(LOG, "New switch with name \"{}\" added", pDevice->getName()); - PNEWDEV->hyprListener_destroy.initCallback(&pDevice->events.destroy, [&](void* owner, void* data) { destroySwitch((SSwitchDevice*)owner); }, PNEWDEV, "SwitchDevice"); + PNEWDEV->listeners.destroy = pDevice->events.destroy.registerListener([this, PNEWDEV](std::any d) { destroySwitch(PNEWDEV); }); - const auto PSWITCH = wlr_switch_from_input_device(pDevice); + PNEWDEV->listeners.fire = pDevice->events.fire.registerListener([PNEWDEV](std::any d) { + const auto NAME = PNEWDEV->pDevice->getName(); + const auto E = std::any_cast(d); - PNEWDEV->hyprListener_toggle.initCallback( - &PSWITCH->events.toggle, - [&](void* owner, void* data) { - const auto PDEVICE = (SSwitchDevice*)owner; - const auto NAME = std::string(PDEVICE->pWlrDevice->name); - const auto E = (wlr_switch_toggle_event*)data; + Debug::log(LOG, "Switch {} fired, triggering binds.", NAME); - if (PDEVICE->status != -1 && PDEVICE->status == E->switch_state) - return; + g_pKeybindManager->onSwitchEvent(NAME); - Debug::log(LOG, "Switch {} fired, triggering binds.", NAME); - - g_pKeybindManager->onSwitchEvent(NAME); - - switch (E->switch_state) { - case WLR_SWITCH_STATE_ON: - Debug::log(LOG, "Switch {} turn on, triggering binds.", NAME); - g_pKeybindManager->onSwitchOnEvent(NAME); - break; - case WLR_SWITCH_STATE_OFF: - Debug::log(LOG, "Switch {} turn off, triggering binds.", NAME); - g_pKeybindManager->onSwitchOffEvent(NAME); - break; - } - - PDEVICE->status = E->switch_state; - }, - PNEWDEV, "SwitchDevice"); + if (E.enable) { + Debug::log(LOG, "Switch {} turn on, triggering binds.", NAME); + g_pKeybindManager->onSwitchOnEvent(NAME); + } else { + Debug::log(LOG, "Switch {} turn off, triggering binds.", NAME); + g_pKeybindManager->onSwitchOffEvent(NAME); + } + }); } void CInputManager::destroySwitch(SSwitchDevice* pDevice) { diff --git a/src/managers/input/InputManager.hpp b/src/managers/input/InputManager.hpp index 85ae6197..ebf00b2d 100644 --- a/src/managers/input/InputManager.hpp +++ b/src/managers/input/InputManager.hpp @@ -18,6 +18,14 @@ class CVirtualKeyboardV1Resource; class CVirtualPointerV1Resource; class IKeyboard; +AQUAMARINE_FORWARD(IPointer); +AQUAMARINE_FORWARD(IKeyboard); +AQUAMARINE_FORWARD(ITouch); +AQUAMARINE_FORWARD(ISwitch); +AQUAMARINE_FORWARD(ITablet); +AQUAMARINE_FORWARD(ITabletTool); +AQUAMARINE_FORWARD(ITabletPad); + enum eClickBehaviorMode { CLICKMODE_DEFAULT = 0, CLICKMODE_KILL @@ -82,15 +90,14 @@ class CInputManager { void onKeyboardKey(std::any, SP); void onKeyboardMod(SP); - void newKeyboard(wlr_input_device*); + void newKeyboard(SP); void newVirtualKeyboard(SP); - void newMouse(wlr_input_device*); + void newMouse(SP); void newVirtualMouse(SP); - void newTouchDevice(wlr_input_device*); - void newSwitch(wlr_input_device*); - void newTabletTool(wlr_tablet_tool*); - void newTabletPad(wlr_input_device*); - void newTablet(wlr_input_device*); + void newTouchDevice(SP); + void newSwitch(SP); + void newTabletPad(SP); + void newTablet(SP); void destroyTouchDevice(SP); void destroyKeyboard(SP); void destroyPointer(SP); @@ -232,7 +239,7 @@ class CInputManager { void mouseMoveUnified(uint32_t, bool refocus = false); - SP ensureTabletToolPresent(wlr_tablet_tool*); + SP ensureTabletToolPresent(SP); void applyConfigToKeyboard(SP); diff --git a/src/managers/input/Tablets.cpp b/src/managers/input/Tablets.cpp index f1157e4b..5e50e851 100644 --- a/src/managers/input/Tablets.cpp +++ b/src/managers/input/Tablets.cpp @@ -62,7 +62,7 @@ static void refocusTablet(SP tab, SP tool, bool motion = f if (!motion) return; - if (LASTHLSURFACE->constraint() && tool->wlr()->type != WLR_TABLET_TOOL_TYPE_MOUSE) { + if (LASTHLSURFACE->constraint() && tool->aq()->type != Aquamarine::ITabletTool::AQ_TABLET_TOOL_TYPE_MOUSE) { // cursor logic will completely break here as the cursor will be locked. // let's just "map" the desired position to the constraint area. @@ -102,7 +102,7 @@ void CInputManager::onTabletAxis(CTablet::SAxisEvent e) { Vector2D delta = {std::isnan(dx) ? 0.0 : dx, std::isnan(dy) ? 0.0 : dy}; switch (e.tool->type) { - case WLR_TABLET_TOOL_TYPE_MOUSE: { + case Aquamarine::ITabletTool::AQ_TABLET_TOOL_TYPE_MOUSE: { g_pPointerManager->move(delta); break; } @@ -205,12 +205,12 @@ void CInputManager::onTabletProximity(CTablet::SProximityEvent e) { PROTO::idle->onActivity(); } -void CInputManager::newTablet(wlr_input_device* pDevice) { - const auto PNEWTABLET = m_vTablets.emplace_back(CTablet::create(wlr_tablet_from_input_device(pDevice))); +void CInputManager::newTablet(SP pDevice) { + const auto PNEWTABLET = m_vTablets.emplace_back(CTablet::create(pDevice)); m_vHIDs.push_back(PNEWTABLET); try { - PNEWTABLET->hlName = deviceNameToInternalString(pDevice->name); + PNEWTABLET->hlName = deviceNameToInternalString(pDevice->getName()); } catch (std::exception& e) { Debug::log(ERR, "Tablet had no name???"); // logic error } @@ -227,28 +227,32 @@ void CInputManager::newTablet(wlr_input_device* pDevice) { setTabletConfigs(); } -SP CInputManager::ensureTabletToolPresent(wlr_tablet_tool* pTool) { - if (pTool->data == nullptr) { - const auto PTOOL = m_vTabletTools.emplace_back(CTabletTool::create(pTool)); - m_vHIDs.push_back(PTOOL); +SP CInputManager::ensureTabletToolPresent(SP pTool) { - PTOOL->events.destroy.registerStaticListener( - [this](void* owner, std::any d) { - auto TOOL = ((CTabletTool*)owner)->self; - destroyTabletTool(TOOL.lock()); - }, - PTOOL.get()); + for (auto& t : m_vTabletTools) { + if (t->aq() == pTool) + return t; } - return CTabletTool::fromWlr(pTool); + const auto PTOOL = m_vTabletTools.emplace_back(CTabletTool::create(pTool)); + m_vHIDs.push_back(PTOOL); + + PTOOL->events.destroy.registerStaticListener( + [this](void* owner, std::any d) { + auto TOOL = ((CTabletTool*)owner)->self; + destroyTabletTool(TOOL.lock()); + }, + PTOOL.get()); + + return PTOOL; } -void CInputManager::newTabletPad(wlr_input_device* pDevice) { - const auto PNEWPAD = m_vTabletPads.emplace_back(CTabletPad::create(wlr_tablet_pad_from_input_device(pDevice))); +void CInputManager::newTabletPad(SP pDevice) { + const auto PNEWPAD = m_vTabletPads.emplace_back(CTabletPad::create(pDevice)); m_vHIDs.push_back(PNEWPAD); try { - PNEWPAD->hlName = deviceNameToInternalString(pDevice->name); + PNEWPAD->hlName = deviceNameToInternalString(pDevice->getName()); } catch (std::exception& e) { Debug::log(ERR, "Pad had no name???"); // logic error } @@ -259,7 +263,7 @@ void CInputManager::newTabletPad(wlr_input_device* pDevice) { destroyTabletPad(PAD.lock()); }, PNEWPAD.get()); - PNEWPAD->padEvents.button.registerStaticListener([this](void* owner, std::any e) { + PNEWPAD->padEvents.button.registerStaticListener([](void* owner, std::any e) { const auto E = std::any_cast(e); const auto PPAD = ((CTabletPad*)owner)->self.lock(); @@ -267,26 +271,25 @@ void CInputManager::newTabletPad(wlr_input_device* pDevice) { PROTO::tablet->buttonPad(PPAD, E.button, E.timeMs, E.down); }, PNEWPAD.get()); - PNEWPAD->padEvents.strip.registerStaticListener([this](void* owner, std::any e) { + PNEWPAD->padEvents.strip.registerStaticListener([](void* owner, std::any e) { const auto E = std::any_cast(e); const auto PPAD = ((CTabletPad*)owner)->self.lock(); PROTO::tablet->strip(PPAD, E.strip, E.position, E.finger, E.timeMs); }, PNEWPAD.get()); - PNEWPAD->padEvents.ring.registerStaticListener([this](void* owner, std::any e) { + PNEWPAD->padEvents.ring.registerStaticListener([](void* owner, std::any e) { const auto E = std::any_cast(e); const auto PPAD = ((CTabletPad*)owner)->self.lock(); PROTO::tablet->ring(PPAD, E.ring, E.position, E.finger, E.timeMs); }, PNEWPAD.get()); - PNEWPAD->padEvents.attach.registerStaticListener([this](void* owner, std::any e) { + PNEWPAD->padEvents.attach.registerStaticListener([](void* owner, std::any e) { const auto PPAD = ((CTabletPad*)owner)->self.lock(); const auto TOOL = std::any_cast>(e); PPAD->parent = TOOL; }, PNEWPAD.get()); - // clang-format on } diff --git a/src/meson.build b/src/meson.build index f6ae043d..71854fa4 100644 --- a/src/meson.build +++ b/src/meson.build @@ -2,14 +2,15 @@ globber = run_command('sh', '-c', 'find . -name "*.cpp" | sort', check: true) src = globber.stdout().strip().split('\n') executable('Hyprland', src, - cpp_args: ['-DWLR_USE_UNSTABLE'], link_args: '-rdynamic', cpp_pch: 'pch/pch.hpp', dependencies: [ server_protos, + dependency('aquamarine'), + dependency('gbm'), + dependency('xcursor'), dependency('wayland-server'), dependency('wayland-client'), - wlroots.get_variable('wlroots'), dependency('cairo'), dependency('hyprcursor', version: '>=0.1.7'), dependency('hyprlang', version: '>= 0.3.2'), diff --git a/src/plugins/PluginAPI.cpp b/src/plugins/PluginAPI.cpp index 6e09ba2c..098e3f12 100644 --- a/src/plugins/PluginAPI.cpp +++ b/src/plugins/PluginAPI.cpp @@ -2,6 +2,7 @@ #include "../Compositor.hpp" #include "../debug/HyprCtl.hpp" #include +#include #if defined(__DragonFly__) || defined(__FreeBSD__) || defined(__NetBSD__) #include diff --git a/src/protocols/CursorShape.cpp b/src/protocols/CursorShape.cpp index 2f25b22b..812afe53 100644 --- a/src/protocols/CursorShape.cpp +++ b/src/protocols/CursorShape.cpp @@ -1,48 +1,9 @@ #include "CursorShape.hpp" #include +#include "../helpers/CursorShapes.hpp" #define LOGM PROTO::cursorShape->protoLog -// clang-format off -constexpr const char* SHAPE_NAMES[] = { - "invalid", - "default", - "context-menu", - "help", - "pointer", - "progress", - "wait", - "cell", - "crosshair", - "text", - "vertical-text", - "alias", - "copy", - "move", - "no-drop", - "not-allowed", - "grab", - "grabbing", - "e-resize", - "n-resize", - "ne-resize", - "nw-resize", - "s-resize", - "se-resize", - "sw-resize", - "w-resize", - "ew-resize", - "ns-resize", - "nesw-resize", - "nwse-resize", - "col-resize", - "row-resize", - "all-scroll", - "zoom-in", - "zoom-out", -}; -// clang-format on - CCursorShapeProtocol::CCursorShapeProtocol(const wl_interface* iface, const int& ver, const std::string& name) : IWaylandProtocol(iface, ver, name) { ; } @@ -82,7 +43,7 @@ void CCursorShapeProtocol::createCursorShapeDevice(CWpCursorShapeManagerV1* pMgr } void CCursorShapeProtocol::onSetShape(CWpCursorShapeDeviceV1* pMgr, uint32_t serial, wpCursorShapeDeviceV1Shape shape) { - if ((uint32_t)shape == 0 || (uint32_t)shape > sizeof(SHAPE_NAMES)) { + if ((uint32_t)shape == 0 || (uint32_t)shape > CURSOR_SHAPE_NAMES.size()) { pMgr->error(WP_CURSOR_SHAPE_DEVICE_V1_ERROR_INVALID_SHAPE, "The shape is invalid"); return; } @@ -90,7 +51,7 @@ void CCursorShapeProtocol::onSetShape(CWpCursorShapeDeviceV1* pMgr, uint32_t ser SSetShapeEvent event; event.pMgr = pMgr; event.shape = shape; - event.shapeName = SHAPE_NAMES[shape]; + event.shapeName = CURSOR_SHAPE_NAMES.at(shape); events.setShape.emit(event); } \ No newline at end of file diff --git a/src/protocols/DRMLease.cpp b/src/protocols/DRMLease.cpp new file mode 100644 index 00000000..9f5b6312 --- /dev/null +++ b/src/protocols/DRMLease.cpp @@ -0,0 +1,302 @@ +#include "DRMLease.hpp" +#include "../Compositor.hpp" +#include +#include + +#define LOGM PROTO::lease->protoLog + +CDRMLeaseResource::CDRMLeaseResource(SP resource_, SP request) : resource(resource_) { + if (!good()) + return; + + resource->setOnDestroy([this](CWpDrmLeaseV1* r) { PROTO::lease->destroyResource(this); }); + resource->setDestroy([this](CWpDrmLeaseV1* r) { PROTO::lease->destroyResource(this); }); + + parent = request->parent; + requested = request->requested; + + for (auto& m : requested) { + if (!m->monitor || m->monitor->isBeingLeased) { + LOGM(ERR, "Rejecting lease: no monitor or monitor is being leased for {}", (m->monitor ? m->monitor->szName : "null")); + resource->sendFinished(); + return; + } + } + + // grant the lease if it is seemingly valid + + LOGM(LOG, "Leasing outputs: {}", [this]() { + std::string roll; + for (auto& o : requested) { + roll += std::format("{} ", o->monitor->szName); + } + return roll; + }()); + + std::vector> outputs; + for (auto& m : requested) { + outputs.emplace_back(m->monitor->output); + } + + auto aqlease = Aquamarine::CDRMLease::create(outputs); + if (!aqlease) { + LOGM(ERR, "Rejecting lease: backend failed to alloc a lease"); + resource->sendFinished(); + return; + } + + LOGM(LOG, "Granting lease, sending fd {}", aqlease->leaseFD); + + resource->sendLeaseFd(aqlease->leaseFD); + + lease = aqlease; + + for (auto& m : requested) { + m->monitor->isBeingLeased = true; + } + + listeners.destroyLease = lease->events.destroy.registerListener([this](std::any d) { + for (auto& m : requested) { + if (m && m->monitor) + m->monitor->isBeingLeased = false; + } + + resource->sendFinished(); + }); + + close(lease->leaseFD); +} + +bool CDRMLeaseResource::good() { + return resource->resource(); +} + +CDRMLeaseRequestResource::CDRMLeaseRequestResource(SP resource_) : resource(resource_) { + if (!good()) + return; + + resource->setOnDestroy([this](CWpDrmLeaseRequestV1* r) { PROTO::lease->destroyResource(this); }); + + resource->setRequestConnector([this](CWpDrmLeaseRequestV1* r, wl_resource* conn) { + if (!conn) { + resource->error(-1, "Null connector"); + return; + } + + auto CONNECTOR = CDRMLeaseConnectorResource::fromResource(conn); + + if (std::find(requested.begin(), requested.end(), CONNECTOR) != requested.end()) { + resource->error(WP_DRM_LEASE_REQUEST_V1_ERROR_DUPLICATE_CONNECTOR, "Connector already requested"); + return; + } + + // TODO: when (if) we add multi, make sure this is from the correct device. + + requested.emplace_back(CONNECTOR); + }); + + resource->setSubmit([this](CWpDrmLeaseRequestV1* r, uint32_t id) { + if (requested.empty()) { + resource->error(WP_DRM_LEASE_REQUEST_V1_ERROR_EMPTY_LEASE, "No connectors added"); + return; + } + + auto RESOURCE = makeShared(makeShared(resource->client(), resource->version(), -1), self.lock()); + if (!RESOURCE) { + resource->noMemory(); + return; + } + + PROTO::lease->m_vLeases.emplace_back(RESOURCE); + + // per protcol, after submit, this is dead. + PROTO::lease->destroyResource(this); + }); +} + +bool CDRMLeaseRequestResource::good() { + return resource->resource(); +} + +SP CDRMLeaseConnectorResource::fromResource(wl_resource* res) { + auto data = (CDRMLeaseConnectorResource*)(((CWpDrmLeaseConnectorV1*)wl_resource_get_user_data(res))->data()); + return data ? data->self.lock() : nullptr; +} + +CDRMLeaseConnectorResource::CDRMLeaseConnectorResource(SP resource_, SP monitor_) : monitor(monitor_), resource(resource_) { + if (!good()) + return; + + resource->setOnDestroy([this](CWpDrmLeaseConnectorV1* r) { PROTO::lease->destroyResource(this); }); + resource->setDestroy([this](CWpDrmLeaseConnectorV1* r) { PROTO::lease->destroyResource(this); }); + + resource->setData(this); + + listeners.destroyMonitor = monitor->events.destroy.registerListener([this](std::any d) { + resource->sendWithdrawn(); + dead = true; + }); +} + +bool CDRMLeaseConnectorResource::good() { + return resource->resource(); +} + +void CDRMLeaseConnectorResource::sendData() { + resource->sendName(monitor->szName.c_str()); + resource->sendDescription(monitor->szDescription.c_str()); + + auto AQDRMOutput = (Aquamarine::CDRMOutput*)monitor->output.get(); + resource->sendConnectorId(AQDRMOutput->getConnectorID()); + + resource->sendDone(); +} + +CDRMLeaseDeviceResource::CDRMLeaseDeviceResource(SP resource_) : resource(resource_) { + if (!good()) + return; + + resource->setOnDestroy([this](CWpDrmLeaseDeviceV1* r) { PROTO::lease->destroyResource(this); }); + resource->setRelease([this](CWpDrmLeaseDeviceV1* r) { PROTO::lease->destroyResource(this); }); + + resource->setCreateLeaseRequest([this](CWpDrmLeaseDeviceV1* r, uint32_t id) { + auto RESOURCE = makeShared(makeShared(resource->client(), resource->version(), id)); + if (!RESOURCE) { + resource->noMemory(); + return; + } + + RESOURCE->self = RESOURCE; + + PROTO::lease->m_vRequests.emplace_back(RESOURCE); + + LOGM(LOG, "New lease request {}", id); + + RESOURCE->parent = self; + }); + + int fd = ((Aquamarine::CDRMBackend*)PROTO::lease->primaryDevice->backend.get())->getNonMasterFD(); + if (fd < 0) { + LOGM(ERR, "Failed to dup fd in lease"); + return; + } + + LOGM(LOG, "Sending DRMFD {} to new lease device", fd); + resource->sendDrmFd(fd); + close(fd); + + for (auto& m : PROTO::lease->primaryDevice->offeredOutputs) { + sendConnector(m.lock()); + } + + resource->sendDone(); +} + +bool CDRMLeaseDeviceResource::good() { + return resource->resource(); +} + +void CDRMLeaseDeviceResource::sendConnector(SP monitor) { + if (std::find_if(connectorsSent.begin(), connectorsSent.end(), [monitor](const auto& e) { return e->monitor == monitor; }) != connectorsSent.end()) + return; + + auto RESOURCE = makeShared(makeShared(resource->client(), resource->version(), -1), monitor); + if (!RESOURCE) { + resource->noMemory(); + return; + } + + RESOURCE->parent = self; + RESOURCE->self = RESOURCE; + + LOGM(LOG, "Sending new connector {}", monitor->szName); + + connectorsSent.emplace_back(RESOURCE); + PROTO::lease->m_vConnectors.emplace_back(RESOURCE); + + resource->sendConnector(RESOURCE->resource.get()); + + RESOURCE->sendData(); +} + +CDRMLeaseDevice::CDRMLeaseDevice(SP drmBackend) : backend(drmBackend) { + auto drm = (Aquamarine::CDRMBackend*)drmBackend.get(); + + auto fd = drm->getNonMasterFD(); + + if (fd < 0) { + LOGM(ERR, "Failed to dup fd for drm node {}", drm->gpuName); + return; + } + + close(fd); + success = true; + name = drm->gpuName; +} + +CDRMLeaseProtocol::CDRMLeaseProtocol(const wl_interface* iface, const int& ver, const std::string& name) : IWaylandProtocol(iface, ver, name) { + for (auto& b : g_pCompositor->m_pAqBackend->getImplementations()) { + if (b->type() != Aquamarine::AQ_BACKEND_DRM) + continue; + + auto drm = ((Aquamarine::CDRMBackend*)b.get())->self.lock(); + + primaryDevice = makeShared(drm); + + if (primaryDevice->success) + break; + } + + if (!primaryDevice || primaryDevice->success) { + PROTO::lease.reset(); + return; + } +} + +void CDRMLeaseProtocol::bindManager(wl_client* client, void* data, uint32_t ver, uint32_t id) { + const auto RESOURCE = m_vManagers.emplace_back(makeShared(makeShared(client, ver, id))); + + if (!RESOURCE->good()) { + wl_client_post_no_memory(client); + m_vManagers.pop_back(); + return; + } + + RESOURCE->self = RESOURCE; +} + +void CDRMLeaseProtocol::destroyResource(CDRMLeaseDeviceResource* resource) { + std::erase_if(m_vManagers, [resource](const auto& e) { return e.get() == resource; }); +} + +void CDRMLeaseProtocol::destroyResource(CDRMLeaseConnectorResource* resource) { + std::erase_if(m_vConnectors, [resource](const auto& e) { return e.get() == resource; }); +} + +void CDRMLeaseProtocol::destroyResource(CDRMLeaseRequestResource* resource) { + std::erase_if(m_vRequests, [resource](const auto& e) { return e.get() == resource; }); +} + +void CDRMLeaseProtocol::destroyResource(CDRMLeaseResource* resource) { + std::erase_if(m_vLeases, [resource](const auto& e) { return e.get() == resource; }); +} + +void CDRMLeaseProtocol::offer(SP monitor) { + if (std::find(primaryDevice->offeredOutputs.begin(), primaryDevice->offeredOutputs.end(), monitor) != primaryDevice->offeredOutputs.end()) + return; + + if (monitor->output->getBackend()->type() != Aquamarine::AQ_BACKEND_DRM) + return; + + if (monitor->output->getBackend() != primaryDevice->backend) { + LOGM(ERR, "Monitor {} cannot be leased: primaryDevice lease is for a different device", monitor->szName); + return; + } + + primaryDevice->offeredOutputs.emplace_back(monitor); + + for (auto& m : m_vManagers) { + m->sendConnector(monitor); + m->resource->sendDone(); + } +} diff --git a/src/protocols/DRMLease.hpp b/src/protocols/DRMLease.hpp new file mode 100644 index 00000000..56eaa3db --- /dev/null +++ b/src/protocols/DRMLease.hpp @@ -0,0 +1,137 @@ +#pragma once + +#include +#include +#include +#include "WaylandProtocol.hpp" +#include "drm-lease-v1.hpp" +#include "../helpers/signal/Signal.hpp" + +/* + TODO: this protocol is not made for systems with multiple DRM nodes (e.g. multigpu) +*/ + +AQUAMARINE_FORWARD(CDRMBackend); +AQUAMARINE_FORWARD(CDRMLease); +class CDRMLeaseDeviceResource; +class CMonitor; +class CDRMLeaseProtocol; +class CDRMLeaseConnectorResource; +class CDRMLeaseRequestResource; + +class CDRMLeaseResource { + public: + CDRMLeaseResource(SP resource_, SP request); + + bool good(); + + WP parent; + std::vector> requested; + WP lease; + + int leaseFD = -1; + + struct { + CHyprSignalListener destroyLease; + } listeners; + + private: + SP resource; +}; + +class CDRMLeaseRequestResource { + public: + CDRMLeaseRequestResource(SP resource_); + + bool good(); + + WP parent; + WP self; + std::vector> requested; + + private: + SP resource; +}; + +class CDRMLeaseConnectorResource { + public: + CDRMLeaseConnectorResource(SP resource_, SP monitor_); + static SP fromResource(wl_resource*); + + bool good(); + void sendData(); + + WP self; + WP parent; + WP monitor; + bool dead = false; + + private: + SP resource; + + struct { + CHyprSignalListener destroyMonitor; + } listeners; + + friend class CDRMLeaseDeviceResource; +}; + +class CDRMLeaseDeviceResource { + public: + CDRMLeaseDeviceResource(SP resource_); + + bool good(); + void sendConnector(SP monitor); + + std::vector> connectorsSent; + + WP self; + + private: + SP resource; + + friend class CDRMLeaseProtocol; +}; + +class CDRMLeaseDevice { + public: + CDRMLeaseDevice(SP drmBackend); + + std::string name = ""; + bool success = false; + SP backend; + + std::vector> offeredOutputs; +}; + +class CDRMLeaseProtocol : public IWaylandProtocol { + public: + CDRMLeaseProtocol(const wl_interface* iface, const int& ver, const std::string& name); + + virtual void bindManager(wl_client* client, void* data, uint32_t ver, uint32_t id); + + void offer(SP monitor); + + private: + void destroyResource(CDRMLeaseDeviceResource* resource); + void destroyResource(CDRMLeaseConnectorResource* resource); + void destroyResource(CDRMLeaseRequestResource* resource); + void destroyResource(CDRMLeaseResource* resource); + + // + std::vector> m_vManagers; + std::vector> m_vConnectors; + std::vector> m_vRequests; + std::vector> m_vLeases; + + SP primaryDevice; + + friend class CDRMLeaseDeviceResource; + friend class CDRMLeaseConnectorResource; + friend class CDRMLeaseRequestResource; + friend class CDRMLeaseResource; +}; + +namespace PROTO { + inline UP lease; +}; diff --git a/src/protocols/DRMSyncobj.cpp b/src/protocols/DRMSyncobj.cpp new file mode 100644 index 00000000..41178109 --- /dev/null +++ b/src/protocols/DRMSyncobj.cpp @@ -0,0 +1,183 @@ +#include "DRMSyncobj.hpp" +#include + +#include "core/Compositor.hpp" +#include "../helpers/sync/SyncTimeline.hpp" +#include "../Compositor.hpp" + +#include + +#define LOGM PROTO::sync->protoLog + +CDRMSyncobjSurfaceResource::CDRMSyncobjSurfaceResource(SP resource_, SP surface_) : surface(surface_), resource(resource_) { + if (!good()) + return; + + resource->setData(this); + + resource->setOnDestroy([this](CWpLinuxDrmSyncobjSurfaceV1* r) { PROTO::sync->destroyResource(this); }); + resource->setDestroy([this](CWpLinuxDrmSyncobjSurfaceV1* r) { PROTO::sync->destroyResource(this); }); + + resource->setSetAcquirePoint([this](CWpLinuxDrmSyncobjSurfaceV1* r, wl_resource* timeline_, uint32_t hi, uint32_t lo) { + if (!surface) { + resource->error(WP_LINUX_DRM_SYNCOBJ_SURFACE_V1_ERROR_NO_SURFACE, "Surface is gone"); + return; + } + + auto timeline = CDRMSyncobjTimelineResource::fromResource(timeline_); + acquireTimeline = timeline; + acquirePoint = ((uint64_t)hi << 32) | (uint64_t)lo; + }); + + resource->setSetReleasePoint([this](CWpLinuxDrmSyncobjSurfaceV1* r, wl_resource* timeline_, uint32_t hi, uint32_t lo) { + if (!surface) { + resource->error(WP_LINUX_DRM_SYNCOBJ_SURFACE_V1_ERROR_NO_SURFACE, "Surface is gone"); + return; + } + + auto timeline = CDRMSyncobjTimelineResource::fromResource(timeline_); + releaseTimeline = timeline; + releasePoint = ((uint64_t)hi << 32) | (uint64_t)lo; + }); + + listeners.surfacePrecommit = surface->events.precommit.registerListener([this](std::any d) { + if (!!acquireTimeline != !!releaseTimeline) { + resource->error(acquireTimeline ? WP_LINUX_DRM_SYNCOBJ_SURFACE_V1_ERROR_NO_RELEASE_POINT : WP_LINUX_DRM_SYNCOBJ_SURFACE_V1_ERROR_NO_ACQUIRE_POINT, "Missing timeline"); + surface->pending.rejected = true; + return; + } + + if ((acquireTimeline || releaseTimeline) && !surface->pending.buffer) { + resource->error(WP_LINUX_DRM_SYNCOBJ_SURFACE_V1_ERROR_NO_BUFFER, "Missing buffer"); + surface->pending.rejected = true; + return; + } + + if (!acquireTimeline) + return; + + // wait for the acquire timeline to materialize + auto materialized = acquireTimeline->timeline->check(acquirePoint, DRM_SYNCOBJ_WAIT_FLAGS_WAIT_AVAILABLE); + if (!materialized.has_value()) { + LOGM(ERR, "Failed to check the acquire timeline"); + resource->noMemory(); + return; + } + + if (materialized) + return; + + surface->lockPendingState(); + acquireTimeline->timeline->addWaiter([this]() { surface->unlockPendingState(); }, acquirePoint, DRM_SYNCOBJ_WAIT_FLAGS_WAIT_AVAILABLE); + }); +} + +bool CDRMSyncobjSurfaceResource::good() { + return resource->resource(); +} + +CDRMSyncobjTimelineResource::CDRMSyncobjTimelineResource(SP resource_, int fd_) : fd(fd_), resource(resource_) { + if (!good()) + return; + + resource->setData(this); + + resource->setOnDestroy([this](CWpLinuxDrmSyncobjTimelineV1* r) { PROTO::sync->destroyResource(this); }); + resource->setDestroy([this](CWpLinuxDrmSyncobjTimelineV1* r) { PROTO::sync->destroyResource(this); }); + + timeline = CSyncTimeline::create(PROTO::sync->drmFD, fd); + + if (!timeline) { + resource->error(WP_LINUX_DRM_SYNCOBJ_MANAGER_V1_ERROR_INVALID_TIMELINE, "Timeline failed importing"); + return; + } +} + +SP CDRMSyncobjTimelineResource::fromResource(wl_resource* res) { + auto data = (CDRMSyncobjTimelineResource*)(((CWpLinuxDrmSyncobjTimelineV1*)wl_resource_get_user_data(res))->data()); + return data ? data->self.lock() : nullptr; +} + +bool CDRMSyncobjTimelineResource::good() { + return resource->resource(); +} + +CDRMSyncobjManagerResource::CDRMSyncobjManagerResource(SP resource_) : resource(resource_) { + if (!good()) + return; + + resource->setOnDestroy([this](CWpLinuxDrmSyncobjManagerV1* r) { PROTO::sync->destroyResource(this); }); + resource->setDestroy([this](CWpLinuxDrmSyncobjManagerV1* r) { PROTO::sync->destroyResource(this); }); + + resource->setGetSurface([this](CWpLinuxDrmSyncobjManagerV1* r, uint32_t id, wl_resource* surf) { + if (!surf) { + resource->error(-1, "Invalid surface"); + return; + } + + auto SURF = CWLSurfaceResource::fromResource(surf); + if (!SURF) { + resource->error(-1, "Invalid surface (2)"); + return; + } + + if (SURF->syncobj) { + resource->error(WP_LINUX_DRM_SYNCOBJ_MANAGER_V1_ERROR_SURFACE_EXISTS, "Surface already has a syncobj attached"); + return; + } + + auto RESOURCE = makeShared(makeShared(resource->client(), resource->version(), id), SURF); + if (!RESOURCE->good()) { + resource->noMemory(); + return; + } + + PROTO::sync->m_vSurfaces.emplace_back(RESOURCE); + SURF->syncobj = RESOURCE; + + LOGM(LOG, "New linux_syncobj at {:x} for surface {:x}", (uintptr_t)RESOURCE.get(), (uintptr_t)SURF.get()); + }); + + resource->setImportTimeline([this](CWpLinuxDrmSyncobjManagerV1* r, uint32_t id, int32_t fd) { + auto RESOURCE = makeShared(makeShared(resource->client(), resource->version(), id), fd); + if (!RESOURCE->good()) { + resource->noMemory(); + return; + } + + PROTO::sync->m_vTimelines.emplace_back(RESOURCE); + RESOURCE->self = RESOURCE; + + LOGM(LOG, "New linux_drm_timeline at {:x}", (uintptr_t)RESOURCE.get()); + }); +} + +bool CDRMSyncobjManagerResource::good() { + return resource->resource(); +} + +CDRMSyncobjProtocol::CDRMSyncobjProtocol(const wl_interface* iface, const int& ver, const std::string& name) : IWaylandProtocol(iface, ver, name) { + drmFD = g_pCompositor->m_iDRMFD; +} + +void CDRMSyncobjProtocol::bindManager(wl_client* client, void* data, uint32_t ver, uint32_t id) { + const auto RESOURCE = m_vManagers.emplace_back(makeShared(makeShared(client, ver, id))); + + if (!RESOURCE->good()) { + wl_client_post_no_memory(client); + m_vManagers.pop_back(); + return; + } +} + +void CDRMSyncobjProtocol::destroyResource(CDRMSyncobjManagerResource* resource) { + std::erase_if(m_vManagers, [resource](const auto& e) { return e.get() == resource; }); +} + +void CDRMSyncobjProtocol::destroyResource(CDRMSyncobjTimelineResource* resource) { + std::erase_if(m_vTimelines, [resource](const auto& e) { return e.get() == resource; }); +} + +void CDRMSyncobjProtocol::destroyResource(CDRMSyncobjSurfaceResource* resource) { + std::erase_if(m_vSurfaces, [resource](const auto& e) { return e.get() == resource; }); +} diff --git a/src/protocols/DRMSyncobj.hpp b/src/protocols/DRMSyncobj.hpp new file mode 100644 index 00000000..c1c884ff --- /dev/null +++ b/src/protocols/DRMSyncobj.hpp @@ -0,0 +1,82 @@ +#pragma once + +#include +#include +#include "WaylandProtocol.hpp" +#include "linux-drm-syncobj-v1.hpp" +#include "../helpers/signal/Signal.hpp" + +class CWLSurfaceResource; +class CDRMSyncobjTimelineResource; +class CSyncTimeline; + +class CDRMSyncobjSurfaceResource { + public: + CDRMSyncobjSurfaceResource(SP resource_, SP surface_); + + bool good(); + + WP surface; + WP acquireTimeline, releaseTimeline; + uint64_t acquirePoint = 0, releasePoint = 0; + + private: + SP resource; + + struct { + CHyprSignalListener surfacePrecommit; + } listeners; +}; + +class CDRMSyncobjTimelineResource { + public: + CDRMSyncobjTimelineResource(SP resource_, int fd_); + static SP fromResource(wl_resource*); + + bool good(); + + WP self; + int fd = -1; + SP timeline; + + private: + SP resource; +}; + +class CDRMSyncobjManagerResource { + public: + CDRMSyncobjManagerResource(SP resource_); + + bool good(); + + private: + SP resource; +}; + +class CDRMSyncobjProtocol : public IWaylandProtocol { + public: + CDRMSyncobjProtocol(const wl_interface* iface, const int& ver, const std::string& name); + + virtual void bindManager(wl_client* client, void* data, uint32_t ver, uint32_t id); + + private: + void destroyResource(CDRMSyncobjManagerResource* resource); + void destroyResource(CDRMSyncobjTimelineResource* resource); + void destroyResource(CDRMSyncobjSurfaceResource* resource); + + // + std::vector> m_vManagers; + std::vector> m_vTimelines; + std::vector> m_vSurfaces; + + // + int drmFD = -1; + + friend class CDRMSyncobjManagerResource; + friend class CDRMSyncobjTimelineResource; + friend class CDRMSyncobjSurfaceResource; +}; + +namespace PROTO { + inline UP sync; +}; diff --git a/src/protocols/GammaControl.cpp b/src/protocols/GammaControl.cpp index 7c3b39ce..494d9862 100644 --- a/src/protocols/GammaControl.cpp +++ b/src/protocols/GammaControl.cpp @@ -34,7 +34,7 @@ CGammaControl::CGammaControl(SP resource_, wl_resource* out } } - gammaSize = wlr_output_get_gamma_size(pMonitor->output); + gammaSize = pMonitor->output->getGammaSize(); if (gammaSize <= 0) { LOGM(ERR, "Output {} doesn't support gamma", pMonitor->szName); @@ -81,6 +81,24 @@ CGammaControl::CGammaControl(SP resource_, wl_resource* out gammaTableSet = true; close(fd); + + // translate the table to AQ format + std::vector red, green, blue; + red.resize(gammaTable.size() / 3); + green.resize(gammaTable.size() / 3); + blue.resize(gammaTable.size() / 3); + for (size_t i = 0; i < gammaTable.size() / 3; ++i) { + red.at(i) = gammaTable.at(i); + green.at(i) = gammaTable.at(gammaTable.size() / 3 + i); + blue.at(i) = gammaTable.at((gammaTable.size() / 3) * 2 + i); + } + + for (size_t i = 0; i < gammaTable.size() / 3; ++i) { + gammaTable.at(i * 3) = red.at(i); + gammaTable.at(i * 3 + 1) = green.at(i); + gammaTable.at(i * 3 + 2) = blue.at(i); + } + applyToMonitor(); }); @@ -95,7 +113,7 @@ CGammaControl::~CGammaControl() { return; // reset the LUT if the client dies for whatever reason and doesn't unset the gamma - wlr_output_state_set_gamma_lut(pMonitor->state.wlr(), 0, nullptr, nullptr, nullptr); + pMonitor->output->state->setGammaLut({}); } bool CGammaControl::good() { @@ -109,19 +127,15 @@ void CGammaControl::applyToMonitor() { LOGM(LOG, "setting to monitor {}", pMonitor->szName); if (!gammaTableSet) { - wlr_output_state_set_gamma_lut(pMonitor->state.wlr(), 0, nullptr, nullptr, nullptr); + pMonitor->output->state->setGammaLut({}); return; } - uint16_t* red = &gammaTable.at(0); - uint16_t* green = &gammaTable.at(gammaSize); - uint16_t* blue = &gammaTable.at(gammaSize * 2); - - wlr_output_state_set_gamma_lut(pMonitor->state.wlr(), gammaSize, red, green, blue); + pMonitor->output->state->setGammaLut(gammaTable); if (!pMonitor->state.test()) { LOGM(LOG, "setting to monitor {} failed", pMonitor->szName); - wlr_output_state_set_gamma_lut(pMonitor->state.wlr(), 0, nullptr, nullptr, nullptr); + pMonitor->output->state->setGammaLut({}); } g_pHyprRenderer->damageMonitor(pMonitor); diff --git a/src/protocols/GammaControl.hpp b/src/protocols/GammaControl.hpp index 93465b81..963eea5c 100644 --- a/src/protocols/GammaControl.hpp +++ b/src/protocols/GammaControl.hpp @@ -23,7 +23,7 @@ class CGammaControl { CMonitor* pMonitor = nullptr; size_t gammaSize = 0; bool gammaTableSet = false; - std::vector gammaTable; + std::vector gammaTable; // [r,g,b]+ void onMonitorDestroy(); diff --git a/src/protocols/InputMethodV2.cpp b/src/protocols/InputMethodV2.cpp index 24f7ad54..def4d837 100644 --- a/src/protocols/InputMethodV2.cpp +++ b/src/protocols/InputMethodV2.cpp @@ -4,6 +4,7 @@ #include "../devices/IKeyboard.hpp" #include #include "core/Compositor.hpp" +#include #define LOGM PROTO::ime->protoLog @@ -19,7 +20,7 @@ CInputMethodKeyboardGrabV2::CInputMethodKeyboardGrabV2(SPkeyboard->wlr()); + sendKeyboardData(g_pSeatManager->keyboard.lock()); } CInputMethodKeyboardGrabV2::~CInputMethodKeyboardGrabV2() { @@ -27,37 +28,36 @@ CInputMethodKeyboardGrabV2::~CInputMethodKeyboardGrabV2() { std::erase_if(owner->grabs, [](const auto& g) { return g.expired(); }); } -void CInputMethodKeyboardGrabV2::sendKeyboardData(wlr_keyboard* keyboard) { +void CInputMethodKeyboardGrabV2::sendKeyboardData(SP keyboard) { if (keyboard == pLastKeyboard) return; pLastKeyboard = keyboard; - int keymapFD = allocateSHMFile(keyboard->keymap_size); + int keymapFD = allocateSHMFile(keyboard->xkbKeymapString.length() + 1); if (keymapFD < 0) { LOGM(ERR, "Failed to create a keymap file for keyboard grab"); return; } - void* data = mmap(nullptr, keyboard->keymap_size, PROT_READ | PROT_WRITE, MAP_SHARED, keymapFD, 0); + void* data = mmap(nullptr, keyboard->xkbKeymapString.length() + 1, PROT_READ | PROT_WRITE, MAP_SHARED, keymapFD, 0); if (data == MAP_FAILED) { LOGM(ERR, "Failed to mmap a keymap file for keyboard grab"); close(keymapFD); return; } - memcpy(data, keyboard->keymap_string, keyboard->keymap_size); - munmap(data, keyboard->keymap_size); + memcpy(data, keyboard->xkbKeymapString.c_str(), keyboard->xkbKeymapString.length()); + munmap(data, keyboard->xkbKeymapString.length() + 1); - resource->sendKeymap(WL_KEYBOARD_KEYMAP_FORMAT_XKB_V1, keymapFD, keyboard->keymap_size); + resource->sendKeymap(WL_KEYBOARD_KEYMAP_FORMAT_XKB_V1, keymapFD, keyboard->xkbKeymapString.length() + 1); close(keymapFD); - const auto MODS = keyboard->modifiers; - sendMods(MODS.depressed, MODS.latched, MODS.locked, MODS.group); + sendMods(keyboard->modifiersState.depressed, keyboard->modifiersState.latched, keyboard->modifiersState.locked, keyboard->modifiersState.group); - resource->sendRepeatInfo(keyboard->repeat_info.rate, keyboard->repeat_info.delay); + resource->sendRepeatInfo(keyboard->repeatRate, keyboard->repeatDelay); } void CInputMethodKeyboardGrabV2::sendKey(uint32_t time, uint32_t key, wl_keyboard_key_state state) { @@ -316,7 +316,7 @@ void CInputMethodV2::sendMods(uint32_t depressed, uint32_t latched, uint32_t loc } } -void CInputMethodV2::setKeyboard(wlr_keyboard* keyboard) { +void CInputMethodV2::setKeyboard(SP keyboard) { for (auto& gw : grabs) { auto g = gw.lock(); diff --git a/src/protocols/InputMethodV2.hpp b/src/protocols/InputMethodV2.hpp index bc21270c..0b2c7a49 100644 --- a/src/protocols/InputMethodV2.hpp +++ b/src/protocols/InputMethodV2.hpp @@ -11,6 +11,7 @@ class CInputMethodKeyboardGrabV2; class CInputMethodPopupV2; +class IKeyboard; class CInputMethodV2 { public: @@ -58,7 +59,7 @@ class CInputMethodV2 { bool hasGrab(); void sendKey(uint32_t time, uint32_t key, wl_keyboard_key_state state); void sendMods(uint32_t depressed, uint32_t latched, uint32_t locked, uint32_t group); - void setKeyboard(wlr_keyboard* keyboard); + void setKeyboard(SP keyboard); wl_client* client(); wl_client* grabClient(); @@ -90,13 +91,13 @@ class CInputMethodKeyboardGrabV2 { void sendKey(uint32_t time, uint32_t key, wl_keyboard_key_state state); void sendMods(uint32_t depressed, uint32_t latched, uint32_t locked, uint32_t group); - void sendKeyboardData(wlr_keyboard* keyboard); + void sendKeyboardData(SP keyboard); private: SP resource; WP owner; - wlr_keyboard* pLastKeyboard = nullptr; // READ-ONLY + WP pLastKeyboard; }; class CInputMethodPopupV2 { diff --git a/src/protocols/LinuxDMABUF.cpp b/src/protocols/LinuxDMABUF.cpp index cf8f8730..0fbf832e 100644 --- a/src/protocols/LinuxDMABUF.cpp +++ b/src/protocols/LinuxDMABUF.cpp @@ -6,6 +6,7 @@ #include #include #include +#include #include "core/Compositor.hpp" #include "types/DMABuffer.hpp" #include "types/WLBuffer.hpp" @@ -22,21 +23,66 @@ static std::optional devIDFromFD(int fd) { return stat.st_rdev; } -CCompiledDMABUFFeedback::CCompiledDMABUFFeedback(dev_t device, std::vector tranches_) { +CDMABUFFormatTable::CDMABUFFormatTable(SDMABUFTranche _rendererTranche, std::vector, SDMABUFTranche>> tranches_) : + rendererTranche(_rendererTranche), monitorTranches(tranches_) { + + std::vector formatsVec; std::set> formats; - for (auto& t : tranches_) { - for (auto& fmt : t.formats) { - for (auto& mod : fmt.mods) { - formats.insert(std::make_pair<>(fmt.format, mod)); + + // insert formats into vec if they got inserted into set, meaning they're unique + size_t i = 0; + + rendererTranche.indicies.clear(); + for (auto& fmt : rendererTranche.formats) { + for (auto& mod : fmt.modifiers) { + auto format = std::make_pair<>(fmt.drmFormat, mod); + auto [_, inserted] = formats.insert(format); + if (inserted) { + // if it was inserted into set, then its unique and will have a new index in vec + rendererTranche.indicies.push_back(i++); + formatsVec.push_back(SDMABUFFormatTableEntry{ + .fmt = fmt.drmFormat, + .modifier = mod, + }); + } else { + // if it wasn't inserted then find its index in vec + auto it = + std::find_if(formatsVec.begin(), formatsVec.end(), [fmt, mod](const SDMABUFFormatTableEntry& oth) { return oth.fmt == fmt.drmFormat && oth.modifier == mod; }); + rendererTranche.indicies.push_back(it - formatsVec.begin()); } } } - tableLen = formats.size() * sizeof(SDMABUFFeedbackTableEntry); - int fds[2] = {0}; - allocateSHMFilePair(tableLen, &fds[0], &fds[1]); + for (auto& [monitor, tranche] : monitorTranches) { + tranche.indicies.clear(); + for (auto& fmt : tranche.formats) { + for (auto& mod : fmt.modifiers) { + // apparently these can implode on planes, so dont use them + if (mod == DRM_FORMAT_MOD_INVALID || mod == DRM_FORMAT_MOD_LINEAR) + continue; + auto format = std::make_pair<>(fmt.drmFormat, mod); + auto [_, inserted] = formats.insert(format); + if (inserted) { + tranche.indicies.push_back(i++); + formatsVec.push_back(SDMABUFFormatTableEntry{ + .fmt = fmt.drmFormat, + .modifier = mod, + }); + } else { + auto it = std::find_if(formatsVec.begin(), formatsVec.end(), + [fmt, mod](const SDMABUFFormatTableEntry& oth) { return oth.fmt == fmt.drmFormat && oth.modifier == mod; }); + tranche.indicies.push_back(it - formatsVec.begin()); + } + } + } + } - auto arr = (SDMABUFFeedbackTableEntry*)mmap(nullptr, tableLen, PROT_READ | PROT_WRITE, MAP_SHARED, fds[0], 0); + tableSize = formatsVec.size() * sizeof(SDMABUFFormatTableEntry); + + int fds[2] = {0}; + allocateSHMFilePair(tableSize, &fds[0], &fds[1]); + + auto arr = (SDMABUFFormatTableEntry*)mmap(nullptr, tableSize, PROT_READ | PROT_WRITE, MAP_SHARED, fds[0], 0); if (arr == MAP_FAILED) { LOGM(ERR, "mmap failed"); @@ -47,33 +93,18 @@ CCompiledDMABUFFeedback::CCompiledDMABUFFeedback(dev_t device, std::vector> formatsVec; - for (auto& f : formats) { - formatsVec.push_back(f); - } + std::copy(formatsVec.begin(), formatsVec.end(), arr); - size_t i = 0; - for (auto& [fmt, mod] : formatsVec) { - arr[i++] = SDMABUFFeedbackTableEntry{ - .fmt = fmt, - .modifier = mod, - }; - } + munmap(arr, tableSize); - munmap(arr, tableLen); - - mainDevice = device; - tableFD = fds[1]; - tranches = formatsVec; - - // TODO: maybe calculate indices? currently we send all as available which could be wrong? I ain't no kernel dev tho. + tableFD = fds[1]; } -CCompiledDMABUFFeedback::~CCompiledDMABUFFeedback() { +CDMABUFFormatTable::~CDMABUFFormatTable() { close(tableFD); } -CLinuxDMABuffer::CLinuxDMABuffer(uint32_t id, wl_client* client, SDMABUFAttrs attrs) { +CLinuxDMABuffer::CLinuxDMABuffer(uint32_t id, wl_client* client, Aquamarine::SDMABUFAttrs attrs) { buffer = makeShared(id, client, attrs); buffer->resource->buffer = buffer; @@ -103,7 +134,7 @@ CLinuxDMABBUFParamsResource::CLinuxDMABBUFParamsResource(SPsetOnDestroy([this](CZwpLinuxBufferParamsV1* r) { PROTO::linuxDma->destroyResource(this); }); resource->setDestroy([this](CZwpLinuxBufferParamsV1* r) { PROTO::linuxDma->destroyResource(this); }); - attrs = makeShared(); + attrs = makeShared(); attrs->success = true; @@ -190,7 +221,7 @@ void CLinuxDMABBUFParamsResource::create(uint32_t id) { return; } - LOGM(LOG, "Creating a dmabuf, with id {}: size {}, fmt {}, planes {}", id, attrs->size, attrs->format, attrs->planes); + LOGM(LOG, "Creating a dmabuf, with id {}: size {}, fmt {}, planes {}", id, attrs->size, FormatUtils::drmFormatName(attrs->format), attrs->planes); for (int i = 0; i < attrs->planes; ++i) { LOGM(LOG, " | plane {}: mod {} fd {} stride {} offset {}", i, attrs->modifier, attrs->fds[i], attrs->strides[i], attrs->offsets[i]); } @@ -277,32 +308,9 @@ CLinuxDMABUFFeedbackResource::CLinuxDMABUFFeedbackResource(SPsetOnDestroy([this](CZwpLinuxDmabufFeedbackV1* r) { PROTO::linuxDma->destroyResource(this); }); resource->setDestroy([this](CZwpLinuxDmabufFeedbackV1* r) { PROTO::linuxDma->destroyResource(this); }); - if (surface) - LOGM(ERR, "FIXME: surface feedback stub"); - - auto* feedback = PROTO::linuxDma->defaultFeedback.get(); - - resource->sendFormatTable(feedback->tableFD, feedback->tableLen); - - // send default feedback - struct wl_array deviceArr = { - .size = sizeof(feedback->mainDevice), - .data = (void*)&feedback->mainDevice, - }; - resource->sendMainDevice(&deviceArr); - resource->sendTrancheTargetDevice(&deviceArr); - resource->sendTrancheFlags((zwpLinuxDmabufFeedbackV1TrancheFlags)0); - - wl_array indices; - wl_array_init(&indices); - for (size_t i = 0; i < feedback->tranches.size(); ++i) { - *((uint16_t*)wl_array_add(&indices, sizeof(uint16_t))) = i; - } - resource->sendTrancheFormats(&indices); - wl_array_release(&indices); - resource->sendTrancheDone(); - - resource->sendDone(); + auto& formatTable = PROTO::linuxDma->formatTable; + resource->sendFormatTable(formatTable->tableFD, formatTable->tableSize); + sendDefaultFeedback(); } CLinuxDMABUFFeedbackResource::~CLinuxDMABUFFeedbackResource() { @@ -313,6 +321,41 @@ bool CLinuxDMABUFFeedbackResource::good() { return resource->resource(); } +void CLinuxDMABUFFeedbackResource::sendTranche(SDMABUFTranche& tranche) { + struct wl_array deviceArr = { + .size = sizeof(tranche.device), + .data = (void*)&tranche.device, + }; + resource->sendTrancheTargetDevice(&deviceArr); + + resource->sendTrancheFlags((zwpLinuxDmabufFeedbackV1TrancheFlags)tranche.flags); + + wl_array indices = { + .size = tranche.indicies.size() * sizeof(tranche.indicies.at(0)), + .data = tranche.indicies.data(), + }; + resource->sendTrancheFormats(&indices); + resource->sendTrancheDone(); +} + +// default tranche is based on renderer (egl) +void CLinuxDMABUFFeedbackResource::sendDefaultFeedback() { + auto mainDevice = PROTO::linuxDma->mainDevice; + auto& formatTable = PROTO::linuxDma->formatTable; + + struct wl_array deviceArr = { + .size = sizeof(mainDevice), + .data = (void*)&mainDevice, + }; + resource->sendMainDevice(&deviceArr); + + sendTranche(formatTable->rendererTranche); + + resource->sendDone(); + + lastFeedbackWasScanout = false; +} + CLinuxDMABUFResource::CLinuxDMABUFResource(SP resource_) : resource(resource_) { if (!good()) return; @@ -361,48 +404,81 @@ bool CLinuxDMABUFResource::good() { } void CLinuxDMABUFResource::sendMods() { - for (auto& [fmt, mod] : PROTO::linuxDma->defaultFeedback->tranches) { - if (resource->version() < 3) { - if (mod == DRM_FORMAT_MOD_INVALID) - resource->sendFormat(fmt); - continue; + for (auto& fmt : PROTO::linuxDma->formatTable->rendererTranche.formats) { + for (auto& mod : fmt.modifiers) { + if (resource->version() < 3) { + if (mod == DRM_FORMAT_MOD_INVALID || mod == DRM_FORMAT_MOD_LINEAR) + resource->sendFormat(fmt.drmFormat); + continue; + } + + // TODO: https://gitlab.freedesktop.org/xorg/xserver/-/issues/1166 + + resource->sendModifier(fmt.drmFormat, mod >> 32, mod & 0xFFFFFFFF); } - - // TODO: https://gitlab.freedesktop.org/xorg/xserver/-/issues/1166 - - resource->sendModifier(fmt, mod >> 32, mod & 0xFFFFFFFF); } } CLinuxDMABufV1Protocol::CLinuxDMABufV1Protocol(const wl_interface* iface, const int& ver, const std::string& name) : IWaylandProtocol(iface, ver, name) { static auto P = g_pHookSystem->hookDynamic("ready", [this](void* self, SCallbackInfo& info, std::any d) { - int rendererFD = wlr_renderer_get_drm_fd(g_pCompositor->m_sWLRRenderer); + int rendererFD = g_pCompositor->m_iDRMFD; auto dev = devIDFromFD(rendererFD); if (!dev.has_value()) { - LOGM(ERR, "failed to get drm dev"); - PROTO::linuxDma.reset(); + protoLog(ERR, "failed to get drm dev, disabling linux dmabuf"); + removeGlobal(); return; } mainDevice = *dev; - auto fmts = g_pHyprOpenGL->getDRMFormats(); - - SDMABufTranche tranche = { - .device = *dev, - .formats = fmts, + SDMABUFTranche eglTranche = { + .device = mainDevice, + .flags = 0, // renderer isnt for ds so dont set flag. + .formats = g_pHyprOpenGL->getDRMFormats(), }; - std::vector tches; - tches.push_back(tranche); + std::vector, SDMABUFTranche>> tches; - defaultFeedback = std::make_unique(*dev, tches); + if (g_pCompositor->m_pAqBackend->hasSession()) { + // this assumes there's only 1 device used for both scanout and rendering + // also that each monitor never changes its primary plane + + for (auto& mon : g_pCompositor->m_vMonitors) { + auto tranche = SDMABUFTranche{ + .device = mainDevice, + .flags = ZWP_LINUX_DMABUF_FEEDBACK_V1_TRANCHE_FLAGS_SCANOUT, + .formats = mon->output->getRenderFormats(), + }; + tches.push_back(std::make_pair<>(mon, tranche)); + } + + static auto monitorAdded = g_pHookSystem->hookDynamic("monitorAdded", [this](void* self, SCallbackInfo& info, std::any param) { + auto pMonitor = std::any_cast(param); + auto mon = pMonitor->self.lock(); + auto tranche = SDMABUFTranche{ + .device = mainDevice, + .flags = ZWP_LINUX_DMABUF_FEEDBACK_V1_TRANCHE_FLAGS_SCANOUT, + .formats = mon->output->getRenderFormats(), + }; + formatTable->monitorTranches.push_back(std::make_pair<>(mon, tranche)); + resetFormatTable(); + }); + + static auto monitorRemoved = g_pHookSystem->hookDynamic("monitorRemoved", [this](void* self, SCallbackInfo& info, std::any param) { + auto pMonitor = std::any_cast(param); + auto mon = pMonitor->self.lock(); + std::erase_if(formatTable->monitorTranches, [mon](std::pair, SDMABUFTranche> pair) { return pair.first == mon; }); + resetFormatTable(); + }); + } + + formatTable = std::make_unique(eglTranche, tches); drmDevice* device = nullptr; if (drmGetDeviceFromDevId(mainDevice, 0, &device) != 0) { - LOGM(ERR, "failed to get drm dev"); - PROTO::linuxDma.reset(); + protoLog(ERR, "failed to get drm dev, disabling linux dmabuf"); + removeGlobal(); return; } @@ -411,17 +487,51 @@ CLinuxDMABufV1Protocol::CLinuxDMABufV1Protocol(const wl_interface* iface, const mainDeviceFD = open(name, O_RDWR | O_CLOEXEC); drmFreeDevice(&device); if (mainDeviceFD < 0) { - LOGM(ERR, "failed to open drm dev"); - PROTO::linuxDma.reset(); + protoLog(ERR, "failed to open drm dev, disabling linux dmabuf"); + removeGlobal(); return; } } else { - LOGM(ERR, "DRM device {} has no render node!!", device->nodes[DRM_NODE_PRIMARY]); + protoLog(ERR, "DRM device {} has no render node, disabling linux dmabuf", device->nodes[DRM_NODE_PRIMARY] ? device->nodes[DRM_NODE_PRIMARY] : "null"); drmFreeDevice(&device); + removeGlobal(); } }); } +void CLinuxDMABufV1Protocol::resetFormatTable() { + if (!formatTable) + return; + + LOGM(LOG, "Resetting format table"); + + // this might be a big copy + auto newFormatTable = std::make_unique(formatTable->rendererTranche, formatTable->monitorTranches); + + for (auto& feedback : m_vFeedbacks) { + feedback->resource->sendFormatTable(newFormatTable->tableFD, newFormatTable->tableSize); + if (feedback->lastFeedbackWasScanout) { + SP mon; + auto HLSurface = CWLSurface::fromResource(feedback->surface); + if (auto w = HLSurface->getWindow(); w) + if (auto m = g_pCompositor->getMonitorFromID(w->m_iMonitorID); m) + mon = m->self.lock(); + + if (!mon) { + feedback->sendDefaultFeedback(); + return; + } + + updateScanoutTranche(feedback->surface, mon); + } else { + feedback->sendDefaultFeedback(); + } + } + + // delete old table after we sent new one + formatTable = std::move(newFormatTable); +} + CLinuxDMABufV1Protocol::~CLinuxDMABufV1Protocol() { if (mainDeviceFD >= 0) close(mainDeviceFD); @@ -452,3 +562,52 @@ void CLinuxDMABufV1Protocol::destroyResource(CLinuxDMABBUFParamsResource* resour void CLinuxDMABufV1Protocol::destroyResource(CLinuxDMABuffer* resource) { std::erase_if(m_vBuffers, [&](const auto& other) { return other.get() == resource; }); } + +void CLinuxDMABufV1Protocol::updateScanoutTranche(SP surface, SP pMonitor) { + SP feedbackResource; + for (auto& f : m_vFeedbacks) { + if (f->surface != surface) + continue; + + feedbackResource = f; + break; + } + + if (!feedbackResource) { + LOGM(LOG, "updateScanoutTranche: surface has no dmabuf_feedback"); + return; + } + + if (!pMonitor) { + LOGM(LOG, "updateScanoutTranche: resetting feedback"); + feedbackResource->sendDefaultFeedback(); + return; + } + + const auto& monitorTranchePair = std::find_if(formatTable->monitorTranches.begin(), formatTable->monitorTranches.end(), + [pMonitor](std::pair, SDMABUFTranche> pair) { return pair.first == pMonitor; }); + + if (monitorTranchePair == formatTable->monitorTranches.end()) { + LOGM(LOG, "updateScanoutTranche: monitor has no tranche"); + return; + } + + auto& monitorTranche = (*monitorTranchePair).second; + + LOGM(LOG, "updateScanoutTranche: sending a scanout tranche"); + + struct wl_array deviceArr = { + .size = sizeof(mainDevice), + .data = (void*)&mainDevice, + }; + feedbackResource->resource->sendMainDevice(&deviceArr); + + // prioritize scnaout tranche but have renderer fallback tranche + // also yes formats can be duped here because different tranche flags (ds and no ds) + feedbackResource->sendTranche(monitorTranche); + feedbackResource->sendTranche(formatTable->rendererTranche); + + feedbackResource->resource->sendDone(); + + feedbackResource->lastFeedbackWasScanout = true; +} diff --git a/src/protocols/LinuxDMABUF.hpp b/src/protocols/LinuxDMABUF.hpp index 2b8ce736..0e25cdc6 100644 --- a/src/protocols/LinuxDMABUF.hpp +++ b/src/protocols/LinuxDMABUF.hpp @@ -7,15 +7,16 @@ #include "wayland.hpp" #include "linux-dmabuf-v1.hpp" #include "../helpers/signal/Signal.hpp" +#include "../helpers/Format.hpp" +#include "../helpers/Monitor.hpp" +#include class CDMABuffer; -struct SDRMFormat; -struct SDMABUFAttrs; class CWLSurfaceResource; class CLinuxDMABuffer { public: - CLinuxDMABuffer(uint32_t id, wl_client* client, SDMABUFAttrs attrs); + CLinuxDMABuffer(uint32_t id, wl_client* client, Aquamarine::SDMABUFAttrs attrs); ~CLinuxDMABuffer(); bool good(); @@ -31,34 +32,29 @@ class CLinuxDMABuffer { }; #pragma pack(push, 1) -struct SDMABUFFeedbackTableEntry { +struct SDMABUFFormatTableEntry { uint32_t fmt = 0; char pad[4]; uint64_t modifier = 0; }; #pragma pack(pop) -class SCompiledDMABUFTranche { - dev_t device = 0; - uint32_t flags = 0; - std::vector indices; -}; - -struct SDMABufTranche { +struct SDMABUFTranche { dev_t device = 0; uint32_t flags = 0; std::vector formats; + std::vector indicies; }; -class CCompiledDMABUFFeedback { +class CDMABUFFormatTable { public: - CCompiledDMABUFFeedback(dev_t device, std::vector tranches); - ~CCompiledDMABUFFeedback(); + CDMABUFFormatTable(SDMABUFTranche rendererTranche, std::vector, SDMABUFTranche>> tranches); + ~CDMABUFFormatTable(); - dev_t mainDevice = 0; - int tableFD = -1; - size_t tableLen = 0; - std::vector> tranches; + int tableFD = -1; + size_t tableSize = 0; + SDMABUFTranche rendererTranche; + std::vector, SDMABUFTranche>> monitorTranches; }; class CLinuxDMABBUFParamsResource { @@ -66,12 +62,12 @@ class CLinuxDMABBUFParamsResource { CLinuxDMABBUFParamsResource(SP resource_); ~CLinuxDMABBUFParamsResource(); - bool good(); - void create(uint32_t id); // 0 means not immed + bool good(); + void create(uint32_t id); // 0 means not immed - SP attrs; - WP createdBuffer; - bool used = false; + SP attrs; + WP createdBuffer; + bool used = false; private: SP resource; @@ -86,11 +82,16 @@ class CLinuxDMABUFFeedbackResource { ~CLinuxDMABUFFeedbackResource(); bool good(); + void sendDefaultFeedback(); + void sendTranche(SDMABUFTranche& tranche); SP surface; // optional, for surface feedbacks private: SP resource; + bool lastFeedbackWasScanout = false; + + friend class CLinuxDMABufV1Protocol; }; class CLinuxDMABUFResource { @@ -110,6 +111,7 @@ class CLinuxDMABufV1Protocol : public IWaylandProtocol { ~CLinuxDMABufV1Protocol(); virtual void bindManager(wl_client* client, void* data, uint32_t ver, uint32_t id); + void updateScanoutTranche(SP surface, SP pMonitor); private: void destroyResource(CLinuxDMABUFResource* resource); @@ -117,13 +119,15 @@ class CLinuxDMABufV1Protocol : public IWaylandProtocol { void destroyResource(CLinuxDMABBUFParamsResource* resource); void destroyResource(CLinuxDMABuffer* resource); + void resetFormatTable(); + // std::vector> m_vManagers; std::vector> m_vFeedbacks; std::vector> m_vParams; std::vector> m_vBuffers; - UP defaultFeedback; + UP formatTable; dev_t mainDevice; int mainDeviceFD = -1; diff --git a/src/protocols/MesaDRM.cpp b/src/protocols/MesaDRM.cpp index 0bcf4a9c..ed412555 100644 --- a/src/protocols/MesaDRM.cpp +++ b/src/protocols/MesaDRM.cpp @@ -2,12 +2,11 @@ #include #include #include "../Compositor.hpp" -#include #include "types/WLBuffer.hpp" #define LOGM PROTO::mesaDRM->protoLog -CMesaDRMBufferResource::CMesaDRMBufferResource(uint32_t id, wl_client* client, SDMABUFAttrs attrs_) { +CMesaDRMBufferResource::CMesaDRMBufferResource(uint32_t id, wl_client* client, Aquamarine::SDMABUFAttrs attrs_) { LOGM(LOG, "Creating a Mesa dmabuf, with id {}: size {}, fmt {}, planes {}", id, attrs_.size, attrs_.format, attrs_.planes); for (int i = 0; i < attrs_.planes; ++i) { LOGM(LOG, " | plane {}: mod {} fd {} stride {} offset {}", i, attrs_.modifier, attrs_.fds[i], attrs_.strides[i], attrs_.offsets[i]); @@ -60,10 +59,27 @@ CMesaDRMResource::CMesaDRMResource(SP resource_) : resource(resource_) { return; } - SDMABUFAttrs attrs; + uint64_t mod = DRM_FORMAT_MOD_INVALID; + + auto fmts = g_pHyprOpenGL->getDRMFormats(); + for (auto& f : fmts) { + if (f.drmFormat != fmt) + continue; + + for (auto& m : f.modifiers) { + if (m == DRM_FORMAT_MOD_LINEAR) + continue; + + mod = m; + break; + } + break; + } + + Aquamarine::SDMABUFAttrs attrs; attrs.success = true; attrs.size = {w, h}; - attrs.modifier = DRM_FORMAT_MOD_INVALID; + attrs.modifier = mod; attrs.planes = 1; attrs.offsets[0] = off0; attrs.strides[0] = str0; @@ -87,7 +103,7 @@ CMesaDRMResource::CMesaDRMResource(SP resource_) : resource(resource_) { auto fmts = g_pHyprOpenGL->getDRMFormats(); for (auto& fmt : fmts) { - resource->sendFormat(fmt.format); + resource->sendFormat(fmt.drmFormat); } } @@ -97,10 +113,10 @@ bool CMesaDRMResource::good() { CMesaDRMProtocol::CMesaDRMProtocol(const wl_interface* iface, const int& ver, const std::string& name) : IWaylandProtocol(iface, ver, name) { drmDevice* dev = nullptr; - int drmFD = wlr_renderer_get_drm_fd(g_pCompositor->m_sWLRRenderer); + int drmFD = g_pCompositor->m_iDRMFD; if (drmGetDevice2(drmFD, 0, &dev) != 0) { - LOGM(ERR, "Failed to get device"); - PROTO::mesaDRM.reset(); + protoLog(ERR, "Failed to get device, disabling MesaDRM"); + removeGlobal(); return; } @@ -108,7 +124,15 @@ CMesaDRMProtocol::CMesaDRMProtocol(const wl_interface* iface, const int& ver, co nodeName = dev->nodes[DRM_NODE_RENDER]; } else { ASSERT(dev->available_nodes & (1 << DRM_NODE_PRIMARY)); - LOGM(WARN, "No DRM render node, falling back to primary {}", dev->nodes[DRM_NODE_PRIMARY]); + + if (!dev->nodes[DRM_NODE_PRIMARY]) { + protoLog(ERR, "No DRM render node available, both render and primary are null, disabling MesaDRM"); + drmFreeDevice(&dev); + removeGlobal(); + return; + } + + protoLog(WARN, "No DRM render node, falling back to primary {}", dev->nodes[DRM_NODE_PRIMARY]); nodeName = dev->nodes[DRM_NODE_PRIMARY]; } drmFreeDevice(&dev); diff --git a/src/protocols/MesaDRM.hpp b/src/protocols/MesaDRM.hpp index ad31a182..46811d68 100644 --- a/src/protocols/MesaDRM.hpp +++ b/src/protocols/MesaDRM.hpp @@ -10,7 +10,7 @@ class CMesaDRMBufferResource { public: - CMesaDRMBufferResource(uint32_t id, wl_client* client, SDMABUFAttrs attrs); + CMesaDRMBufferResource(uint32_t id, wl_client* client, Aquamarine::SDMABUFAttrs attrs); ~CMesaDRMBufferResource(); bool good(); diff --git a/src/protocols/OutputManagement.cpp b/src/protocols/OutputManagement.cpp index 68c50193..66f4c5f0 100644 --- a/src/protocols/OutputManagement.cpp +++ b/src/protocols/OutputManagement.cpp @@ -2,6 +2,8 @@ #include #include "../Compositor.hpp" +using namespace Aquamarine; + #define LOGM PROTO::outputManagement->protoLog COutputManager::COutputManager(SP resource_) : resource(resource_) { @@ -123,8 +125,8 @@ void COutputHead::sendAllData() { resource->sendName(pMonitor->szName.c_str()); resource->sendDescription(pMonitor->szDescription.c_str()); - if (pMonitor->output->phys_width > 0 && pMonitor->output->phys_height > 0) - resource->sendPhysicalSize(pMonitor->output->phys_width, pMonitor->output->phys_height); + if (pMonitor->output->physicalSize.x > 0 && pMonitor->output->physicalSize.y > 0) + resource->sendPhysicalSize(pMonitor->output->physicalSize.x, pMonitor->output->physicalSize.y); resource->sendEnabled(pMonitor->m_bEnabled); if (pMonitor->m_bEnabled) { @@ -133,12 +135,12 @@ void COutputHead::sendAllData() { resource->sendScale(wl_fixed_from_double(pMonitor->scale)); } - if (pMonitor->output->make && VERSION >= 2) - resource->sendMake(pMonitor->output->make); - if (pMonitor->output->model && VERSION >= 2) - resource->sendModel(pMonitor->output->model); - if (pMonitor->output->serial && VERSION >= 2) - resource->sendSerialNumber(pMonitor->output->serial); + if (!pMonitor->output->make.empty() && VERSION >= 2) + resource->sendMake(pMonitor->output->make.c_str()); + if (!pMonitor->output->model.empty() && VERSION >= 2) + resource->sendModel(pMonitor->output->model.c_str()); + if (!pMonitor->output->serial.empty() && VERSION >= 2) + resource->sendSerialNumber(pMonitor->output->serial.c_str()); if (VERSION >= 4) resource->sendAdaptiveSync(pMonitor->vrrActive ? ZWLR_OUTPUT_HEAD_V1_ADAPTIVE_SYNC_STATE_ENABLED : ZWLR_OUTPUT_HEAD_V1_ADAPTIVE_SYNC_STATE_DISABLED); @@ -146,12 +148,12 @@ void COutputHead::sendAllData() { // send all available modes if (modes.empty()) { - if (!wl_list_empty(&pMonitor->output->modes)) { - wlr_output_mode* mode; - - wl_list_for_each(mode, &pMonitor->output->modes, link) { - makeAndSendNewMode(mode); + if (!pMonitor->output->modes.empty()) { + for (auto& m : pMonitor->output->modes) { + makeAndSendNewMode(m); } + } else if (pMonitor->output->state->state().customMode) { + makeAndSendNewMode(pMonitor->output->state->state().customMode); } else makeAndSendNewMode(nullptr); } @@ -164,9 +166,9 @@ void COutputHead::sendAllData() { if (!m) continue; - if (m->mode == pMonitor->currentMode) { + if (m->mode == pMonitor->output->state->state().mode) { if (m->mode) - LOGM(LOG, " | sending current mode for {}: {}x{}@{}", pMonitor->szName, m->mode->width, m->mode->height, m->mode->refresh); + LOGM(LOG, " | sending current mode for {}: {}x{}@{}", pMonitor->szName, m->mode->pixelSize.x, m->mode->pixelSize.y, m->mode->refreshRate); else LOGM(LOG, " | sending current mode for {}: null (fake)", pMonitor->szName); resource->sendCurrentMode(m->resource.get()); @@ -197,7 +199,7 @@ void COutputHead::updateMode() { if (m->mode == pMonitor->currentMode) { if (m->mode) - LOGM(LOG, " | sending current mode for {}: {}x{}@{}", pMonitor->szName, m->mode->width, m->mode->height, m->mode->refresh); + LOGM(LOG, " | sending current mode for {}: {}x{}@{}", pMonitor->szName, m->mode->pixelSize.x, m->mode->pixelSize.y, m->mode->refreshRate); else LOGM(LOG, " | sending current mode for {}: null (fake)", pMonitor->szName); resource->sendCurrentMode(m->resource.get()); @@ -207,7 +209,7 @@ void COutputHead::updateMode() { } } -void COutputHead::makeAndSendNewMode(wlr_output_mode* mode) { +void COutputHead::makeAndSendNewMode(SP mode) { const auto RESOURCE = PROTO::outputManagement->m_vModes.emplace_back(makeShared(makeShared(resource->client(), resource->version(), 0), mode)); if (!RESOURCE->good()) { @@ -225,7 +227,7 @@ CMonitor* COutputHead::monitor() { return pMonitor; } -COutputMode::COutputMode(SP resource_, wlr_output_mode* mode_) : resource(resource_), mode(mode_) { +COutputMode::COutputMode(SP resource_, SP mode_) : resource(resource_), mode(mode_) { if (!good()) return; @@ -237,11 +239,11 @@ void COutputMode::sendAllData() { if (!mode) return; - LOGM(LOG, " | sending mode {}x{}@{}mHz, pref: {}", mode->width, mode->height, mode->refresh, mode->preferred); + LOGM(LOG, " | sending mode {}x{}@{}mHz, pref: {}", mode->pixelSize.x, mode->pixelSize.y, mode->refreshRate, mode->preferred); - resource->sendSize(mode->width, mode->height); - if (mode->refresh > 0) - resource->sendRefresh(mode->refresh); + resource->sendSize(mode->pixelSize.x, mode->pixelSize.y); + if (mode->refreshRate > 0) + resource->sendRefresh(mode->refreshRate); if (mode->preferred) resource->sendPreferred(); } @@ -250,8 +252,8 @@ bool COutputMode::good() { return resource->resource(); } -wlr_output_mode* COutputMode::getMode() { - return mode; +SP COutputMode::getMode() { + return mode.lock(); } COutputConfiguration::COutputConfiguration(SP resource_, SP owner_) : resource(resource_), owner(owner_) { @@ -364,8 +366,8 @@ bool COutputConfiguration::applyTestConfiguration(bool test) { newRule.disabled = false; if (head->committedProperties & COutputConfigurationHead::eCommittedProperties::OUTPUT_HEAD_COMMITTED_MODE) { - newRule.resolution = {head->state.mode->getMode()->width, head->state.mode->getMode()->height}; - newRule.refreshRate = head->state.mode->getMode()->refresh / 1000.F; + newRule.resolution = head->state.mode->getMode()->pixelSize; + newRule.refreshRate = head->state.mode->getMode()->refreshRate / 1000.F; } else if (head->committedProperties & COutputConfigurationHead::eCommittedProperties::OUTPUT_HEAD_COMMITTED_CUSTOM_MODE) { newRule.resolution = head->state.customMode.size; newRule.refreshRate = head->state.customMode.refresh / 1000.F; @@ -425,7 +427,7 @@ COutputConfigurationHead::COutputConfigurationHead(SPszName, MODE->getMode()->width, MODE->getMode()->height, MODE->getMode()->refresh); + LOGM(LOG, " | configHead for {}: set mode to {}x{}@{}", pMonitor->szName, MODE->getMode()->pixelSize.x, MODE->getMode()->pixelSize.y, MODE->getMode()->refreshRate); }); resource->setSetCustomMode([this](CZwlrOutputConfigurationHeadV1* r, int32_t w, int32_t h, int32_t refresh) { diff --git a/src/protocols/OutputManagement.hpp b/src/protocols/OutputManagement.hpp index 81ae9a71..36478d0b 100644 --- a/src/protocols/OutputManagement.hpp +++ b/src/protocols/OutputManagement.hpp @@ -6,6 +6,7 @@ #include "WaylandProtocol.hpp" #include "wlr-output-management-unstable-v1.hpp" #include "../helpers/signal/Signal.hpp" +#include class CMonitor; @@ -34,15 +35,15 @@ class COutputManager { class COutputMode { public: - COutputMode(SP resource_, wlr_output_mode* mode_); + COutputMode(SP resource_, SP mode_); - bool good(); - wlr_output_mode* getMode(); - void sendAllData(); + bool good(); + SP getMode(); + void sendAllData(); private: - SP resource; - wlr_output_mode* mode = nullptr; + SP resource; + WP mode; friend class COutputHead; friend class COutputManagementProtocol; @@ -61,7 +62,7 @@ class COutputHead { SP resource; CMonitor* pMonitor = nullptr; - void makeAndSendNewMode(wlr_output_mode* mode); + void makeAndSendNewMode(SP mode); void sendCurrentMode(); std::vector> modes; diff --git a/src/protocols/OutputPower.cpp b/src/protocols/OutputPower.cpp index ef287cfa..597b9871 100644 --- a/src/protocols/OutputPower.cpp +++ b/src/protocols/OutputPower.cpp @@ -17,7 +17,7 @@ COutputPower::COutputPower(SP resource_, CMonitor* pMonitor_ pMonitor->dpmsStatus = mode == ZWLR_OUTPUT_POWER_V1_MODE_ON; - wlr_output_state_set_enabled(pMonitor->state.wlr(), pMonitor->dpmsStatus); + pMonitor->output->state->setEnabled(mode == ZWLR_OUTPUT_POWER_V1_MODE_ON); if (!pMonitor->state.commit()) LOGM(ERR, "Couldn't set dpms to {} for {}", pMonitor->dpmsStatus, pMonitor->szName); diff --git a/src/protocols/PresentationTime.cpp b/src/protocols/PresentationTime.cpp index 3907bf1e..e9472fc3 100644 --- a/src/protocols/PresentationTime.cpp +++ b/src/protocols/PresentationTime.cpp @@ -3,6 +3,8 @@ #include "../helpers/Monitor.hpp" #include "../managers/HookSystemManager.hpp" #include "core/Compositor.hpp" +#include "core/Output.hpp" +#include #define LOGM PROTO::presentation->protoLog @@ -41,13 +43,11 @@ bool CPresentationFeedback::good() { } void CPresentationFeedback::sendQueued(SP data, timespec* when, uint32_t untilRefreshNs, uint64_t seq, uint32_t reportedFlags) { - auto client = resource->client(); - wl_resource* res; - wl_resource_for_each(res, &data->pMonitor->output->resources) { - if (client == wl_resource_get_client(res)) { - resource->sendSyncOutput(res); - break; - } + auto client = resource->client(); + + if (PROTO::outputs.contains(data->pMonitor->szName)) { + if (auto outputResource = PROTO::outputs.at(data->pMonitor->szName)->outputResourceFrom(client); outputResource) + resource->sendSyncOutput(outputResource->getResource()->resource()); } uint32_t flags = 0; @@ -55,9 +55,9 @@ void CPresentationFeedback::sendQueued(SP data, timespe flags |= WP_PRESENTATION_FEEDBACK_KIND_VSYNC; if (data->zeroCopy) flags |= WP_PRESENTATION_FEEDBACK_KIND_ZERO_COPY; - if (reportedFlags & WLR_OUTPUT_PRESENT_HW_CLOCK) + if (reportedFlags & Aquamarine::IOutput::AQ_OUTPUT_PRESENT_HW_CLOCK) flags |= WP_PRESENTATION_FEEDBACK_KIND_HW_CLOCK; - if (reportedFlags & WLR_OUTPUT_PRESENT_HW_COMPLETION) + if (reportedFlags & Aquamarine::IOutput::AQ_OUTPUT_PRESENT_HW_COMPLETION) flags |= WP_PRESENTATION_FEEDBACK_KIND_HW_COMPLETION; if (data->wasPresented && when) diff --git a/src/protocols/Screencopy.cpp b/src/protocols/Screencopy.cpp index 8a6285a1..5d1c9332 100644 --- a/src/protocols/Screencopy.cpp +++ b/src/protocols/Screencopy.cpp @@ -266,20 +266,17 @@ void CScreencopyProtocolManager::captureOutput(wl_client* client, wl_resource* r return; } - if (PFRAME->pMonitor->output->allocator && (PFRAME->pMonitor->output->allocator->buffer_caps & WLR_BUFFER_CAP_DMABUF)) { - PFRAME->dmabufFormat = PFRAME->pMonitor->output->render_format; - } else { - PFRAME->dmabufFormat = DRM_FORMAT_INVALID; - } + PFRAME->dmabufFormat = PFRAME->pMonitor->output->state->state().drmFormat; if (box.width == 0 && box.height == 0) PFRAME->box = {0, 0, (int)(PFRAME->pMonitor->vecSize.x), (int)(PFRAME->pMonitor->vecSize.y)}; else { PFRAME->box = box; } - int ow, oh; - wlr_output_effective_resolution(PFRAME->pMonitor->output, &ow, &oh); - PFRAME->box.transform(wlTransformToHyprutils(PFRAME->pMonitor->transform), ow, oh).scale(PFRAME->pMonitor->scale).round(); + + PFRAME->box.transform(wlTransformToHyprutils(PFRAME->pMonitor->transform), PFRAME->pMonitor->vecTransformedSize.x, PFRAME->pMonitor->vecTransformedSize.y) + .scale(PFRAME->pMonitor->scale) + .round(); PFRAME->shmStride = FormatUtils::minStride(PSHMINFO, PFRAME->box.w); @@ -383,10 +380,10 @@ void CScreencopyProtocolManager::copyFrame(wl_client* client, wl_resource* resou g_pHyprRenderer->damageMonitor(PFRAME->pMonitor); } -void CScreencopyProtocolManager::onOutputCommit(CMonitor* pMonitor, wlr_output_event_commit* e) { - m_pLastMonitorBackBuffer = e->state->buffer; +void CScreencopyProtocolManager::onOutputCommit(CMonitor* pMonitor) { + m_pLastMonitorBackBuffer = pMonitor->output->state->state().buffer; shareAllFrames(pMonitor); - m_pLastMonitorBackBuffer = nullptr; + m_pLastMonitorBackBuffer.reset(); } void CScreencopyProtocolManager::shareAllFrames(CMonitor* pMonitor) { @@ -473,11 +470,7 @@ void CScreencopyProtocolManager::sendFrameDamage(SScreencopyFrame* frame) { } bool CScreencopyProtocolManager::copyFrameShm(SScreencopyFrame* frame, timespec* now) { - wlr_texture* sourceTex = wlr_texture_from_buffer(g_pCompositor->m_sWLRRenderer, m_pLastMonitorBackBuffer); - if (!sourceTex) - return false; - - auto TEXTURE = makeShared(sourceTex); + auto TEXTURE = makeShared(m_pLastMonitorBackBuffer); auto shm = frame->buffer->shm(); auto [pixelData, fmt, bufLen] = frame->buffer->beginDataPtr(0); // no need for end, cuz it's shm @@ -487,10 +480,10 @@ bool CScreencopyProtocolManager::copyFrameShm(SScreencopyFrame* frame, timespec* g_pHyprRenderer->makeEGLCurrent(); CFramebuffer fb; - fb.alloc(frame->box.w, frame->box.h, g_pHyprRenderer->isNvidia() ? DRM_FORMAT_XBGR8888 : frame->pMonitor->drmFormat); + fb.alloc(frame->box.w, frame->box.h, g_pHyprRenderer->isNvidia() ? DRM_FORMAT_XBGR8888 : frame->pMonitor->output->state->state().drmFormat); if (!g_pHyprRenderer->beginRender(frame->pMonitor, fakeDamage, RENDER_MODE_FULL_FAKE, nullptr, &fb, true)) { - wlr_texture_destroy(sourceTex); + Debug::log(ERR, "Screencopy: can't copy: failed to begin rendering"); return false; } @@ -509,8 +502,8 @@ bool CScreencopyProtocolManager::copyFrameShm(SScreencopyFrame* frame, timespec* const auto PFORMAT = FormatUtils::getPixelFormatFromDRM(shm.format); if (!PFORMAT) { + Debug::log(ERR, "Screencopy: can't copy: failed to find a pixel format"); g_pHyprRenderer->endRender(); - wlr_texture_destroy(sourceTex); return false; } @@ -539,27 +532,24 @@ bool CScreencopyProtocolManager::copyFrameShm(SScreencopyFrame* frame, timespec* g_pHyprOpenGL->m_RenderData.pMonitor = nullptr; - wlr_texture_destroy(sourceTex); + Debug::log(TRACE, "Screencopy: copied frame via shm"); return true; } bool CScreencopyProtocolManager::copyFrameDmabuf(SScreencopyFrame* frame) { - wlr_texture* sourceTex = wlr_texture_from_buffer(g_pCompositor->m_sWLRRenderer, m_pLastMonitorBackBuffer); - if (!sourceTex) - return false; - - auto TEXTURE = makeShared(sourceTex); + auto TEXTURE = makeShared(m_pLastMonitorBackBuffer); CRegion fakeDamage = {0, 0, INT16_MAX, INT16_MAX}; - if (!g_pHyprRenderer->beginRender(frame->pMonitor, fakeDamage, RENDER_MODE_TO_BUFFER, frame->buffer.lock(), nullptr, true)) + if (!g_pHyprRenderer->beginRender(frame->pMonitor, fakeDamage, RENDER_MODE_TO_BUFFER, frame->buffer.lock(), nullptr, true)) { + Debug::log(ERR, "Screencopy: can't copy: failed to begin rendering to dma frame"); return false; + } - CBox monbox = - CBox{0, 0, frame->pMonitor->vecPixelSize.x, frame->pMonitor->vecPixelSize.y} - .translate({-frame->box.x, -frame->box.y}) // vvvv kinda ass-backwards but that's how I designed the renderer... sigh. - .transform(wlTransformToHyprutils(wlr_output_transform_invert(frame->pMonitor->output->transform)), frame->pMonitor->vecPixelSize.x, frame->pMonitor->vecPixelSize.y); + CBox monbox = CBox{0, 0, frame->pMonitor->vecPixelSize.x, frame->pMonitor->vecPixelSize.y} + .translate({-frame->box.x, -frame->box.y}) // vvvv kinda ass-backwards but that's how I designed the renderer... sigh. + .transform(wlTransformToHyprutils(invertTransform(frame->pMonitor->transform)), frame->pMonitor->vecPixelSize.x, frame->pMonitor->vecPixelSize.y); g_pHyprOpenGL->setMonitorTransformEnabled(true); g_pHyprOpenGL->setRenderModifEnabled(false); g_pHyprOpenGL->renderTexture(TEXTURE, &monbox, 1); @@ -569,7 +559,7 @@ bool CScreencopyProtocolManager::copyFrameDmabuf(SScreencopyFrame* frame) { g_pHyprOpenGL->m_RenderData.blockScreenShader = true; g_pHyprRenderer->endRender(); - wlr_texture_destroy(sourceTex); + Debug::log(TRACE, "Screencopy: copied frame via dma"); return true; } diff --git a/src/protocols/Screencopy.hpp b/src/protocols/Screencopy.hpp index be434285..4999773b 100644 --- a/src/protocols/Screencopy.hpp +++ b/src/protocols/Screencopy.hpp @@ -8,9 +8,10 @@ #include "../managers/HookSystemManager.hpp" #include "../helpers/Timer.hpp" #include "../managers/eventLoop/EventLoopTimer.hpp" +#include class CMonitor; -class IWLBuffer; +class IHLBuffer; enum eClientOwners { CLIENT_SCREENCOPY = 0, @@ -56,7 +57,7 @@ struct SScreencopyFrame { bool bufferDMA = false; - WP buffer; + WP buffer; CMonitor* pMonitor = nullptr; PHLWINDOWREF pWindow; @@ -79,7 +80,7 @@ class CScreencopyProtocolManager { void copyFrame(wl_client* client, wl_resource* resource, wl_resource* buffer); - void onOutputCommit(CMonitor* pMonitor, wlr_output_event_commit* e); + void onOutputCommit(CMonitor* pMonitor); private: wl_global* m_pGlobal = nullptr; @@ -93,7 +94,7 @@ class CScreencopyProtocolManager { std::vector m_vFramesAwaitingWrite; - wlr_buffer* m_pLastMonitorBackBuffer = nullptr; + SP m_pLastMonitorBackBuffer; void shareAllFrames(CMonitor* pMonitor); void shareFrame(SScreencopyFrame* frame); diff --git a/src/protocols/Tablet.cpp b/src/protocols/Tablet.cpp index 7b62f245..72c7cfde 100644 --- a/src/protocols/Tablet.cpp +++ b/src/protocols/Tablet.cpp @@ -5,6 +5,7 @@ #include "core/Seat.hpp" #include "core/Compositor.hpp" #include +#include #define LOGM PROTO::tablet->protoLog @@ -44,17 +45,17 @@ bool CTabletPadGroupV2Resource::good() { return resource->resource(); } -void CTabletPadGroupV2Resource::sendData(SP pad, wlr_tablet_pad_group* group) { - resource->sendModes(group->mode_count); +void CTabletPadGroupV2Resource::sendData(SP pad, SP group) { + resource->sendModes(group->modes); wl_array buttonArr; wl_array_init(&buttonArr); - wl_array_add(&buttonArr, group->button_count * sizeof(int)); - memcpy(buttonArr.data, group->buttons, group->button_count * sizeof(int)); + wl_array_add(&buttonArr, group->buttons.size() * sizeof(int)); + memcpy(buttonArr.data, group->buttons.data(), group->buttons.size() * sizeof(int)); resource->sendButtons(&buttonArr); wl_array_release(&buttonArr); - for (size_t i = 0; i < group->strip_count; ++i) { + for (size_t i = 0; i < group->strips.size(); ++i) { const auto RESOURCE = PROTO::tablet->m_vStrips.emplace_back(makeShared(makeShared(resource->client(), resource->version(), 0), i)); @@ -67,7 +68,7 @@ void CTabletPadGroupV2Resource::sendData(SP pad, wlr_tablet_pad_grou resource->sendStrip(RESOURCE->resource.get()); } - for (size_t i = 0; i < group->ring_count; ++i) { + for (size_t i = 0; i < group->rings.size(); ++i) { const auto RESOURCE = PROTO::tablet->m_vRings.emplace_back(makeShared(makeShared(resource->client(), resource->version(), 0), i)); @@ -97,23 +98,20 @@ bool CTabletPadV2Resource::good() { void CTabletPadV2Resource::sendData() { // this is dodgy as fuck. I hate wl_array. it's expanded wl_array_for_each because C++ would complain about the implicit casts - const char** path_ptr; - for (path_ptr = (const char**)(&pad->wlr()->paths)->data; (const char*)path_ptr < ((const char*)(&pad->wlr()->paths)->data + (&pad->wlr()->paths)->size); (path_ptr)++) { - resource->sendPath(*path_ptr); + for (auto& p : pad->aq()->paths) { + resource->sendPath(p.c_str()); } - resource->sendButtons(pad->wlr()->button_count); + resource->sendButtons(pad->aq()->buttons); - wlr_tablet_pad_group* group; - size_t i = 0; - wl_list_for_each(group, &pad->wlr()->groups, link) { - createGroup(group, i++); + for (size_t i = 0; i < pad->aq()->groups.size(); ++i) { + createGroup(pad->aq()->groups.at(i), i); } resource->sendDone(); } -void CTabletPadV2Resource::createGroup(wlr_tablet_pad_group* group, size_t idx) { +void CTabletPadV2Resource::createGroup(SP group, size_t idx) { const auto RESOURCE = PROTO::tablet->m_vGroups.emplace_back(makeShared(makeShared(resource->client(), resource->version(), 0), idx)); @@ -142,13 +140,10 @@ bool CTabletV2Resource::good() { void CTabletV2Resource::sendData() { resource->sendName(tablet->deviceName.c_str()); - resource->sendId(tablet->wlr()->usb_vendor_id, tablet->wlr()->usb_product_id); + resource->sendId(tablet->aq()->usbVendorID, tablet->aq()->usbProductID); - // this is dodgy as fuck. I hate wl_array. it's expanded wl_array_for_each because C++ would complain about the implicit casts - const char** path_ptr; - for (path_ptr = (const char**)(&tablet->wlr()->paths)->data; (const char*)path_ptr < ((const char*)(&tablet->wlr()->paths)->data + (&tablet->wlr()->paths)->size); - (path_ptr)++) { - resource->sendPath(*path_ptr); + for (auto& p : tablet->aq()->paths) { + resource->sendPath(p.c_str()); } resource->sendDone(); @@ -179,23 +174,23 @@ bool CTabletToolV2Resource::good() { } void CTabletToolV2Resource::sendData() { - static auto WLR_TYPE_TO_PROTO = [](uint32_t wlr) -> zwpTabletToolV2Type { - switch (wlr) { - case WLR_TABLET_TOOL_TYPE_PEN: return ZWP_TABLET_TOOL_V2_TYPE_PEN; - case WLR_TABLET_TOOL_TYPE_ERASER: return ZWP_TABLET_TOOL_V2_TYPE_ERASER; - case WLR_TABLET_TOOL_TYPE_BRUSH: return ZWP_TABLET_TOOL_V2_TYPE_BRUSH; - case WLR_TABLET_TOOL_TYPE_PENCIL: return ZWP_TABLET_TOOL_V2_TYPE_PENCIL; - case WLR_TABLET_TOOL_TYPE_AIRBRUSH: return ZWP_TABLET_TOOL_V2_TYPE_AIRBRUSH; - case WLR_TABLET_TOOL_TYPE_MOUSE: return ZWP_TABLET_TOOL_V2_TYPE_MOUSE; - case WLR_TABLET_TOOL_TYPE_LENS: return ZWP_TABLET_TOOL_V2_TYPE_LENS; + static auto AQ_TYPE_TO_PROTO = [](uint32_t aq) -> zwpTabletToolV2Type { + switch (aq) { + case Aquamarine::ITabletTool::AQ_TABLET_TOOL_TYPE_PEN: return ZWP_TABLET_TOOL_V2_TYPE_PEN; + case Aquamarine::ITabletTool::AQ_TABLET_TOOL_TYPE_ERASER: return ZWP_TABLET_TOOL_V2_TYPE_ERASER; + case Aquamarine::ITabletTool::AQ_TABLET_TOOL_TYPE_BRUSH: return ZWP_TABLET_TOOL_V2_TYPE_BRUSH; + case Aquamarine::ITabletTool::AQ_TABLET_TOOL_TYPE_PENCIL: return ZWP_TABLET_TOOL_V2_TYPE_PENCIL; + case Aquamarine::ITabletTool::AQ_TABLET_TOOL_TYPE_AIRBRUSH: return ZWP_TABLET_TOOL_V2_TYPE_AIRBRUSH; + case Aquamarine::ITabletTool::AQ_TABLET_TOOL_TYPE_MOUSE: return ZWP_TABLET_TOOL_V2_TYPE_MOUSE; + case Aquamarine::ITabletTool::AQ_TABLET_TOOL_TYPE_LENS: return ZWP_TABLET_TOOL_V2_TYPE_LENS; default: ASSERT(false); } UNREACHABLE(); }; - resource->sendType(WLR_TYPE_TO_PROTO(tool->wlr()->type)); - resource->sendHardwareSerial(tool->wlr()->hardware_serial >> 32, tool->wlr()->hardware_serial & 0xFFFFFFFF); - resource->sendHardwareIdWacom(tool->wlr()->hardware_wacom >> 32, tool->wlr()->hardware_wacom & 0xFFFFFFFF); + resource->sendType(AQ_TYPE_TO_PROTO(tool->aq()->type)); + resource->sendHardwareSerial(tool->aq()->serial >> 32, tool->aq()->serial & 0xFFFFFFFF); + resource->sendHardwareIdWacom(tool->aq()->id >> 32, tool->aq()->id & 0xFFFFFFFF); if (tool->toolCapabilities & CTabletTool::eTabletToolCapabilities::HID_TABLET_TOOL_CAPABILITY_DISTANCE) resource->sendCapability(zwpTabletToolV2Capability::ZWP_TABLET_TOOL_V2_CAPABILITY_DISTANCE); if (tool->toolCapabilities & CTabletTool::eTabletToolCapabilities::HID_TABLET_TOOL_CAPABILITY_PRESSURE) diff --git a/src/protocols/Tablet.hpp b/src/protocols/Tablet.hpp index 58f13c1a..1ebcb1e5 100644 --- a/src/protocols/Tablet.hpp +++ b/src/protocols/Tablet.hpp @@ -6,6 +6,7 @@ #include "WaylandProtocol.hpp" #include "tablet-v2.hpp" #include "../helpers/math/Math.hpp" +#include class CTablet; class CTabletTool; @@ -51,7 +52,7 @@ class CTabletPadGroupV2Resource { CTabletPadGroupV2Resource(SP resource_, size_t idx); bool good(); - void sendData(SP pad, wlr_tablet_pad_group* group); + void sendData(SP pad, SP group); std::vector> rings; std::vector> strips; @@ -83,7 +84,7 @@ class CTabletPadV2Resource { private: SP resource; - void createGroup(wlr_tablet_pad_group* group, size_t idx); + void createGroup(SP group, size_t idx); friend class CTabletSeat; friend class CTabletV2Protocol; diff --git a/src/protocols/ToplevelExport.cpp b/src/protocols/ToplevelExport.cpp index d4c66c3b..0e78e5f7 100644 --- a/src/protocols/ToplevelExport.cpp +++ b/src/protocols/ToplevelExport.cpp @@ -193,16 +193,11 @@ void CToplevelExportProtocolManager::captureToplevel(wl_client* client, wl_resou return; } - if (PMONITOR->output->allocator && (PMONITOR->output->allocator->buffer_caps & WLR_BUFFER_CAP_DMABUF)) { - PFRAME->dmabufFormat = PMONITOR->output->render_format; - } else { - PFRAME->dmabufFormat = DRM_FORMAT_INVALID; - } + PFRAME->dmabufFormat = PMONITOR->output->state->state().drmFormat; PFRAME->box = {0, 0, (int)(pWindow->m_vRealSize.value().x * PMONITOR->scale), (int)(pWindow->m_vRealSize.value().y * PMONITOR->scale)}; - int ow, oh; - wlr_output_effective_resolution(PMONITOR->output, &ow, &oh); - PFRAME->box.transform(wlTransformToHyprutils(PMONITOR->transform), ow, oh).round(); + + PFRAME->box.transform(wlTransformToHyprutils(PMONITOR->transform), PMONITOR->vecTransformedSize.x, PMONITOR->vecTransformedSize.y).round(); PFRAME->shmStride = FormatUtils::minStride(PSHMINFO, PFRAME->box.w); @@ -289,12 +284,10 @@ void CToplevelExportProtocolManager::copyFrame(wl_client* client, wl_resource* r m_vFramesAwaitingWrite.emplace_back(PFRAME); } -void CToplevelExportProtocolManager::onOutputCommit(CMonitor* pMonitor, wlr_output_event_commit* e) { +void CToplevelExportProtocolManager::onOutputCommit(CMonitor* pMonitor) { if (m_vFramesAwaitingWrite.empty()) return; // nothing to share - const auto PMONITOR = g_pCompositor->getMonitorFromOutput(e->output); - std::vector framesToRemove; // share frame if correct output @@ -306,7 +299,7 @@ void CToplevelExportProtocolManager::onOutputCommit(CMonitor* pMonitor, wlr_outp continue; } - if (PMONITOR != g_pCompositor->getMonitorFromID(PWINDOW->m_iMonitorID)) + if (pMonitor != g_pCompositor->getMonitorFromID(PWINDOW->m_iMonitorID)) continue; CBox geometry = {PWINDOW->m_vRealPosition.value().x, PWINDOW->m_vRealPosition.value().y, PWINDOW->m_vRealSize.value().x, PWINDOW->m_vRealSize.value().y}; @@ -370,7 +363,7 @@ bool CToplevelExportProtocolManager::copyFrameShm(SScreencopyFrame* frame, times g_pHyprRenderer->makeEGLCurrent(); CFramebuffer outFB; - outFB.alloc(PMONITOR->vecPixelSize.x, PMONITOR->vecPixelSize.y, g_pHyprRenderer->isNvidia() ? DRM_FORMAT_XBGR8888 : PMONITOR->drmFormat); + outFB.alloc(PMONITOR->vecPixelSize.x, PMONITOR->vecPixelSize.y, g_pHyprRenderer->isNvidia() ? DRM_FORMAT_XBGR8888 : PMONITOR->output->state->state().drmFormat); if (frame->overlayCursor) { g_pPointerManager->lockSoftwareForMonitor(PMONITOR->self.lock()); diff --git a/src/protocols/ToplevelExport.hpp b/src/protocols/ToplevelExport.hpp index f044a781..c3620d41 100644 --- a/src/protocols/ToplevelExport.hpp +++ b/src/protocols/ToplevelExport.hpp @@ -21,7 +21,7 @@ class CToplevelExportProtocolManager { void copyFrame(wl_client* client, wl_resource* resource, wl_resource* buffer, int32_t ignore_damage); void displayDestroy(); void onWindowUnmap(PHLWINDOW pWindow); - void onOutputCommit(CMonitor* pMonitor, wlr_output_event_commit* e); + void onOutputCommit(CMonitor* pMonitor); private: wl_global* m_pGlobal = nullptr; diff --git a/src/protocols/Viewporter.cpp b/src/protocols/Viewporter.cpp index 8cb69dbe..03c5775e 100644 --- a/src/protocols/Viewporter.cpp +++ b/src/protocols/Viewporter.cpp @@ -52,6 +52,21 @@ CViewportResource::CViewportResource(SP resource_, SPpending.viewport.hasSource = true; surface->pending.viewport.source = {x, y, w, h}; }); + + listeners.surfacePrecommit = surface->events.precommit.registerListener([this](std::any d) { + if (!surface || !surface->pending.buffer) + return; + + if (surface->pending.viewport.hasSource) { + auto& src = surface->pending.viewport.source; + + if (src.w + src.x > surface->pending.buffer->size.x || src.h + src.y > surface->pending.buffer->size.y) { + resource->error(WP_VIEWPORT_ERROR_BAD_VALUE, "Box doesn't fit"); + surface->pending.rejected = true; + return; + } + } + }); } CViewportResource::~CViewportResource() { @@ -66,20 +81,6 @@ bool CViewportResource::good() { return resource->resource(); } -void CViewportResource::verify() { - if (!surface) - return; - - if (surface->pending.viewport.hasSource) { - auto& src = surface->pending.viewport.source; - - if (src.w + src.x > surface->pending.size.x || src.h + src.y > surface->pending.size.y) { - resource->error(WP_VIEWPORT_ERROR_BAD_VALUE, "Box doesn't fit"); - return; - } - } -} - CViewporterResource::CViewporterResource(SP resource_) : resource(resource_) { if (!good()) return; diff --git a/src/protocols/Viewporter.hpp b/src/protocols/Viewporter.hpp index 01278203..3c2a4eef 100644 --- a/src/protocols/Viewporter.hpp +++ b/src/protocols/Viewporter.hpp @@ -15,11 +15,14 @@ class CViewportResource { ~CViewportResource(); bool good(); - void verify(); WP surface; private: SP resource; + + struct { + CHyprSignalListener surfacePrecommit; + } listeners; }; class CViewporterResource { diff --git a/src/protocols/VirtualKeyboard.cpp b/src/protocols/VirtualKeyboard.cpp index 009c277c..2642ec11 100644 --- a/src/protocols/VirtualKeyboard.cpp +++ b/src/protocols/VirtualKeyboard.cpp @@ -1,12 +1,9 @@ #include "VirtualKeyboard.hpp" #include +#include "../devices/IKeyboard.hpp" #define LOGM PROTO::virtualKeyboard->protoLog -static const struct wlr_keyboard_impl virtualKeyboardImpl = { - .name = "virtual-keyboard", -}; - CVirtualKeyboardV1Resource::CVirtualKeyboardV1Resource(SP resource_) : resource(resource_) { if (!good()) return; @@ -28,13 +25,17 @@ CVirtualKeyboardV1Resource::CVirtualKeyboardV1Resource(SP return; } - wlr_keyboard_key_event event = { - .time_msec = timeMs, - .keycode = key, - .update_state = false, - .state = (wl_keyboard_key_state)state, - }; - wlr_keyboard_notify_key(&keyboard, &event); + events.key.emit(IKeyboard::SKeyEvent{ + .timeMs = timeMs, + .keycode = key, + .state = (wl_keyboard_key_state)state, + }); + + const bool CONTAINS = std::find(pressed.begin(), pressed.end(), key) != pressed.end(); + if (state && !CONTAINS) + pressed.emplace_back(key); + else if (!state && CONTAINS) + std::erase(pressed, key); }); resource->setModifiers([this](CZwpVirtualKeyboardV1* r, uint32_t depressed, uint32_t latched, uint32_t locked, uint32_t group) { @@ -43,7 +44,12 @@ CVirtualKeyboardV1Resource::CVirtualKeyboardV1Resource(SP return; } - wlr_keyboard_notify_modifiers(&keyboard, depressed, latched, locked, group); + events.modifiers.emit(IKeyboard::SModifiersEvent{ + .depressed = depressed, + .latched = latched, + .locked = locked, + .group = group, + }); }); resource->setKeymap([this](CZwpVirtualKeyboardV1* r, uint32_t fmt, int32_t fd, uint32_t len) { @@ -75,7 +81,9 @@ CVirtualKeyboardV1Resource::CVirtualKeyboardV1Resource(SP return; } - wlr_keyboard_set_keymap(&keyboard, xkbKeymap); + events.keymap.emit(IKeyboard::SKeymapEvent{ + .keymap = xkbKeymap, + }); hasKeymap = true; xkb_keymap_unref(xkbKeymap); @@ -83,22 +91,17 @@ CVirtualKeyboardV1Resource::CVirtualKeyboardV1Resource(SP close(fd); }); - wlr_keyboard_init(&keyboard, &virtualKeyboardImpl, "CVirtualKeyboard"); + name = "hl-virtual-keyboard"; } CVirtualKeyboardV1Resource::~CVirtualKeyboardV1Resource() { events.destroy.emit(); - wlr_keyboard_finish(&keyboard); } bool CVirtualKeyboardV1Resource::good() { return resource->resource(); } -wlr_keyboard* CVirtualKeyboardV1Resource::wlr() { - return &keyboard; -} - wl_client* CVirtualKeyboardV1Resource::client() { return resource->resource() ? resource->client() : nullptr; } @@ -106,17 +109,16 @@ wl_client* CVirtualKeyboardV1Resource::client() { void CVirtualKeyboardV1Resource::releasePressed() { timespec now; clock_gettime(CLOCK_MONOTONIC, &now); - size_t keycodesNum = keyboard.num_keycodes; - for (size_t i = 0; i < keycodesNum; ++i) { - struct wlr_keyboard_key_event event = { - .time_msec = (now.tv_sec * 1000 + now.tv_nsec / 1000000), - .keycode = keyboard.keycodes[keycodesNum - i - 1], - .update_state = false, - .state = WL_KEYBOARD_KEY_STATE_RELEASED, - }; - wlr_keyboard_notify_key(&keyboard, &event); // updates num_keycodes + for (auto& p : pressed) { + events.key.emit(IKeyboard::SKeyEvent{ + .timeMs = now.tv_sec * 1000 + now.tv_nsec / 1000000, + .keycode = p, + .state = WL_KEYBOARD_KEY_STATE_RELEASED, + }); } + + pressed.clear(); } CVirtualKeyboardProtocol::CVirtualKeyboardProtocol(const wl_interface* iface, const int& ver, const std::string& name) : IWaylandProtocol(iface, ver, name) { diff --git a/src/protocols/VirtualKeyboard.hpp b/src/protocols/VirtualKeyboard.hpp index 447b5db9..93b63bb5 100644 --- a/src/protocols/VirtualKeyboard.hpp +++ b/src/protocols/VirtualKeyboard.hpp @@ -14,19 +14,24 @@ class CVirtualKeyboardV1Resource { struct { CSignal destroy; + CSignal key; + CSignal modifiers; + CSignal keymap; } events; - bool good(); - wlr_keyboard* wlr(); - wl_client* client(); + bool good(); + wl_client* client(); + + std::string name = ""; private: SP resource; - wlr_keyboard keyboard; void releasePressed(); bool hasKeymap = false; + + std::vector pressed; }; class CVirtualKeyboardProtocol : public IWaylandProtocol { diff --git a/src/protocols/VirtualPointer.cpp b/src/protocols/VirtualPointer.cpp index 1fb83888..bdeec32d 100644 --- a/src/protocols/VirtualPointer.cpp +++ b/src/protocols/VirtualPointer.cpp @@ -2,10 +2,6 @@ #define LOGM PROTO::virtualPointer->protoLog -static const wlr_pointer_impl pointerImpl = { - .name = "virtual-pointer-v1", -}; - CVirtualPointerV1Resource::CVirtualPointerV1Resource(SP resource_) : resource(resource_) { if (!good()) return; @@ -19,41 +15,30 @@ CVirtualPointerV1Resource::CVirtualPointerV1Resource(SP r PROTO::virtualPointer->destroyResource(this); }); - wlr_pointer_init(&pointer, &pointerImpl, "CVirtualPointerV1Resource"); - resource->setMotion([this](CZwlrVirtualPointerV1* r, uint32_t timeMs, wl_fixed_t dx, wl_fixed_t dy) { - wlr_pointer_motion_event event = { - .pointer = &pointer, - .time_msec = timeMs, - .delta_x = wl_fixed_to_double(dx), - .delta_y = wl_fixed_to_double(dy), - .unaccel_dx = wl_fixed_to_double(dx), - .unaccel_dy = wl_fixed_to_double(dy), - }; - wl_signal_emit_mutable(&pointer.events.motion, &event); + events.move.emit(IPointer::SMotionEvent{ + .timeMs = timeMs, + .delta = {wl_fixed_to_double(dx), wl_fixed_to_double(dy)}, + .unaccel = {wl_fixed_to_double(dx), wl_fixed_to_double(dy)}, + }); }); resource->setMotionAbsolute([this](CZwlrVirtualPointerV1* r, uint32_t timeMs, uint32_t x, uint32_t y, uint32_t xExtent, uint32_t yExtent) { if (!xExtent || !yExtent) return; - wlr_pointer_motion_absolute_event event = { - .pointer = &pointer, - .time_msec = timeMs, - .x = (double)x / xExtent, - .y = (double)y / yExtent, - }; - wl_signal_emit_mutable(&pointer.events.motion_absolute, &event); + events.warp.emit(IPointer::SMotionAbsoluteEvent{ + .timeMs = timeMs, + .absolute = {(double)x / xExtent, (double)y / yExtent}, + }); }); resource->setButton([this](CZwlrVirtualPointerV1* r, uint32_t timeMs, uint32_t button, uint32_t state) { - struct wlr_pointer_button_event event = { - .pointer = &pointer, - .time_msec = timeMs, - .button = button, - .state = (wl_pointer_button_state)state, - }; - wl_signal_emit_mutable(&pointer.events.button, &event); + events.button.emit(IPointer::SButtonEvent{ + .timeMs = timeMs, + .button = button, + .state = (wl_pointer_button_state)state, + }); }); resource->setAxis([this](CZwlrVirtualPointerV1* r, uint32_t timeMs, uint32_t axis_, wl_fixed_t value) { @@ -63,18 +48,18 @@ CVirtualPointerV1Resource::CVirtualPointerV1Resource(SP r } axis = axis_; - axisEvents[axis] = wlr_pointer_axis_event{.pointer = &pointer, .time_msec = timeMs, .orientation = (wl_pointer_axis)axis, .delta = wl_fixed_to_double(value)}; + axisEvents[axis] = IPointer::SAxisEvent{.timeMs = timeMs, .axis = (wl_pointer_axis)axis, .delta = wl_fixed_to_double(value)}; }); resource->setFrame([this](CZwlrVirtualPointerV1* r) { for (auto& e : axisEvents) { - if (!e.pointer) + if (!e.timeMs) continue; - wl_signal_emit_mutable(&pointer.events.axis, &e); - e.pointer = nullptr; + events.axis.emit(e); + e.timeMs = 0; } - wl_signal_emit_mutable(&pointer.events.frame, &pointer); + events.frame.emit(); }); resource->setAxisSource([this](CZwlrVirtualPointerV1* r, uint32_t source) { axisEvents[axis].source = (wl_pointer_axis_source)source; }); @@ -85,12 +70,11 @@ CVirtualPointerV1Resource::CVirtualPointerV1Resource(SP r return; } - axis = axis_; - axisEvents[axis].pointer = &pointer; - axisEvents[axis].time_msec = timeMs; - axisEvents[axis].orientation = (wl_pointer_axis)axis; - axisEvents[axis].delta = 0; - axisEvents[axis].delta_discrete = 0; + axis = axis_; + axisEvents[axis].timeMs = timeMs; + axisEvents[axis].axis = (wl_pointer_axis)axis; + axisEvents[axis].delta = 0; + axisEvents[axis].deltaDiscrete = 0; }); resource->setAxisDiscrete([this](CZwlrVirtualPointerV1* r, uint32_t timeMs, uint32_t axis_, wl_fixed_t value, int32_t discrete) { @@ -99,17 +83,15 @@ CVirtualPointerV1Resource::CVirtualPointerV1Resource(SP r return; } - axis = axis_; - axisEvents[axis].pointer = &pointer; - axisEvents[axis].time_msec = timeMs; - axisEvents[axis].orientation = (wl_pointer_axis)axis; - axisEvents[axis].delta = wl_fixed_to_double(value); - axisEvents[axis].delta_discrete = discrete * 120; + axis = axis_; + axisEvents[axis].timeMs = timeMs; + axisEvents[axis].axis = (wl_pointer_axis)axis; + axisEvents[axis].delta = wl_fixed_to_double(value); + axisEvents[axis].deltaDiscrete = discrete * 120; }); } CVirtualPointerV1Resource::~CVirtualPointerV1Resource() { - wlr_pointer_finish(&pointer); events.destroy.emit(); } @@ -117,10 +99,6 @@ bool CVirtualPointerV1Resource::good() { return resource->resource(); } -wlr_pointer* CVirtualPointerV1Resource::wlr() { - return &pointer; -} - wl_client* CVirtualPointerV1Resource::client() { return resource->client(); } diff --git a/src/protocols/VirtualPointer.hpp b/src/protocols/VirtualPointer.hpp index 59a7e739..ee5ee7e2 100644 --- a/src/protocols/VirtualPointer.hpp +++ b/src/protocols/VirtualPointer.hpp @@ -7,6 +7,7 @@ #include "WaylandProtocol.hpp" #include "wlr-virtual-pointer-unstable-v1.hpp" #include "../helpers/signal/Signal.hpp" +#include "../devices/IPointer.hpp" class CVirtualPointerV1Resource { public: @@ -15,19 +16,35 @@ class CVirtualPointerV1Resource { struct { CSignal destroy; + CSignal move; + CSignal warp; + CSignal button; + CSignal axis; + CSignal frame; + + CSignal swipeBegin; + CSignal swipeUpdate; + CSignal swipeEnd; + + CSignal pinchBegin; + CSignal pinchUpdate; + CSignal pinchEnd; + + CSignal holdBegin; + CSignal holdEnd; } events; - bool good(); - wlr_pointer* wlr(); - wl_client* client(); + bool good(); + wl_client* client(); + + std::string name; private: - SP resource; - wlr_pointer pointer; + SP resource; - uint32_t axis = 0; + uint32_t axis = 0; - std::array axisEvents; + std::array axisEvents; }; class CVirtualPointerProtocol : public IWaylandProtocol { diff --git a/src/protocols/XDGOutput.cpp b/src/protocols/XDGOutput.cpp index 03e58956..073aa502 100644 --- a/src/protocols/XDGOutput.cpp +++ b/src/protocols/XDGOutput.cpp @@ -75,8 +75,8 @@ void CXDGOutputProtocol::onManagerGetXDGOutput(CZxdgOutputManagerV1* mgr, uint32 if (XDGVER >= OUTPUT_NAME_SINCE_VERSION) pXDGOutput->resource->sendName(PMONITOR->szName.c_str()); - if (XDGVER >= OUTPUT_DESCRIPTION_SINCE_VERSION && PMONITOR->output->description) - pXDGOutput->resource->sendDescription(PMONITOR->output->description); + if (XDGVER >= OUTPUT_DESCRIPTION_SINCE_VERSION && !PMONITOR->output->description.empty()) + pXDGOutput->resource->sendDescription(PMONITOR->output->description.c_str()); pXDGOutput->sendDetails(); @@ -93,7 +93,7 @@ void CXDGOutputProtocol::updateAllOutputs() { o->sendDetails(); - wlr_output_schedule_done(o->monitor->output); + o->monitor->scheduleDone(); } } diff --git a/src/protocols/XDGShell.cpp b/src/protocols/XDGShell.cpp index 9c56df93..8276ed55 100644 --- a/src/protocols/XDGShell.cpp +++ b/src/protocols/XDGShell.cpp @@ -4,6 +4,7 @@ #include "../managers/SeatManager.hpp" #include "core/Seat.hpp" #include "core/Compositor.hpp" +#include #define LOGM PROTO::xdgShell->protoLog diff --git a/src/protocols/core/Compositor.cpp b/src/protocols/core/Compositor.cpp index 691267b0..5cd6005a 100644 --- a/src/protocols/core/Compositor.cpp +++ b/src/protocols/core/Compositor.cpp @@ -6,6 +6,9 @@ #include "Subcompositor.hpp" #include "../Viewporter.hpp" #include "../../helpers/Monitor.hpp" +#include "../PresentationTime.hpp" +#include "../DRMSyncobj.hpp" +#include "../../render/Renderer.hpp" #define LOGM PROTO::compositor->protoLog @@ -102,58 +105,14 @@ CWLSurfaceResource::CWLSurfaceResource(SP resource_) : resource(reso pending.size = tfs / pending.scale; } - if (viewportResource) - viewportResource->verify(); - pending.damage.intersect(CBox{{}, pending.size}); - auto previousBuffer = current.buffer; - CRegion previousBufferDamage = accumulateCurrentBufferDamage(); + events.precommit.emit(); + if (pending.rejected) + return; - current = pending; - pending.damage.clear(); - pending.bufferDamage.clear(); - - if (current.buffer && !bufferReleased) { - // without previous dolphin et al are weird vvv - //CRegion surfaceDamage = - // current.damage.copy().scale(current.scale).transform(current.transform, current.size.x, current.size.y).add(current.bufferDamage).add(previousBufferDamage); - current.buffer->update(CBox{{}, {INT32_MAX, INT32_MAX}}); // FIXME: figure this out to not use this hack. QT apps are wonky without this. - - // release the buffer if it's synchronous as update() has done everything thats needed - // so we can let the app know we're done. - if (current.buffer->isSynchronous()) { - current.buffer->sendRelease(); - bufferReleased = true; - } - } - - // TODO: we should _accumulate_ and not replace above if sync - if (role->role() == SURFACE_ROLE_SUBSURFACE) { - auto subsurface = (CWLSubsurfaceResource*)role.get(); - if (subsurface->sync) - return; - - events.commit.emit(); - } else { - // send commit to all synced surfaces in this tree. - breadthfirst( - [](SP surf, const Vector2D& offset, void* data) { - if (surf->role->role() == SURFACE_ROLE_SUBSURFACE) { - auto subsurface = (CWLSubsurfaceResource*)surf->role.get(); - if (!subsurface->sync) - return; - } - surf->events.commit.emit(); - }, - nullptr); - } - - // for async buffers, we can only release the buffer once we are unrefing it from current. - if (previousBuffer && !previousBuffer->isSynchronous() && !bufferReleased) { - previousBuffer->sendRelease(); - bufferReleased = true; - } + if (stateLocks <= 0) + commitPendingState(); }); resource->setDamage([this](CWlSurface* r, int32_t x, int32_t y, int32_t w, int32_t h) { pending.damage.add(CBox{x, y, w, h}); }); @@ -426,7 +385,97 @@ CRegion CWLSurfaceResource::accumulateCurrentBufferDamage() { Vector2D trc = current.transform % 2 == 1 ? Vector2D{current.buffer->size.y, current.buffer->size.x} : current.buffer->size; - return surfaceDamage.scale(current.scale).transform(wlTransformToHyprutils(wlr_output_transform_invert(current.transform)), trc.x, trc.y).add(current.bufferDamage); + return surfaceDamage.scale(current.scale).transform(wlTransformToHyprutils(invertTransform(current.transform)), trc.x, trc.y).add(current.bufferDamage); +} + +void CWLSurfaceResource::lockPendingState() { + stateLocks++; +} + +void CWLSurfaceResource::unlockPendingState() { + stateLocks--; + if (stateLocks <= 0) + commitPendingState(); +} + +void CWLSurfaceResource::commitPendingState() { + auto previousBuffer = current.buffer; + CRegion previousBufferDamage = accumulateCurrentBufferDamage(); + + current = pending; + pending.damage.clear(); + pending.bufferDamage.clear(); + + if (current.buffer && !bufferReleased) { + // without previous dolphin et al are weird vvv + //CRegion surfaceDamage = + // current.damage.copy().scale(current.scale).transform(current.transform, current.size.x, current.size.y).add(current.bufferDamage).add(previousBufferDamage); + current.buffer->update(CBox{{}, {INT32_MAX, INT32_MAX}}); // FIXME: figure this out to not use this hack. QT apps are wonky without this. + + // release the buffer if it's synchronous as update() has done everything thats needed + // so we can let the app know we're done. + if (current.buffer->isSynchronous()) { + current.buffer->sendReleaseWithSurface(self.lock()); + bufferReleased = true; + } + } + + // TODO: we should _accumulate_ and not replace above if sync + if (role->role() == SURFACE_ROLE_SUBSURFACE) { + auto subsurface = (CWLSubsurfaceResource*)role.get(); + if (subsurface->sync) + return; + + events.commit.emit(); + } else { + // send commit to all synced surfaces in this tree. + breadthfirst( + [](SP surf, const Vector2D& offset, void* data) { + if (surf->role->role() == SURFACE_ROLE_SUBSURFACE) { + auto subsurface = (CWLSubsurfaceResource*)surf->role.get(); + if (!subsurface->sync) + return; + } + surf->events.commit.emit(); + }, + nullptr); + } + + // for async buffers, we can only release the buffer once we are unrefing it from current. + if (previousBuffer && !previousBuffer->isSynchronous() && !bufferReleased) { + if (previousBuffer->lockedByBackend) { + previousBuffer->hlEvents.backendRelease = previousBuffer->events.backendRelease.registerListener([this, previousBuffer](std::any data) { + if (!self.expired()) // could be dead in the dtor + previousBuffer->sendReleaseWithSurface(self.lock()); + else + previousBuffer->sendRelease(); + previousBuffer->hlEvents.backendRelease.reset(); + bufferReleased = true; + }); + } else + previousBuffer->sendReleaseWithSurface(self.lock()); + + bufferReleased = true; + } +} + +void CWLSurfaceResource::presentFeedback(timespec* when, CMonitor* pMonitor, bool needsExplicitSync) { + frame(when); + auto FEEDBACK = makeShared(self.lock()); + FEEDBACK->attachMonitor(pMonitor); + FEEDBACK->discarded(); + PROTO::presentation->queueData(FEEDBACK); + + if (!pMonitor || !pMonitor->outTimeline || !syncobj || !needsExplicitSync) + return; + + // attach explicit sync + g_pHyprRenderer->explicitPresented.emplace_back(self.lock()); + + if (syncobj->acquirePoint > pMonitor->lastWaitPoint) { + Debug::log(TRACE, "presentFeedback lastWaitPoint {} -> {}", pMonitor->lastWaitPoint, syncobj->acquirePoint); + pMonitor->lastWaitPoint = syncobj->acquirePoint; + } } CWLCompositorResource::CWLCompositorResource(SP resource_) : resource(resource_) { diff --git a/src/protocols/core/Compositor.hpp b/src/protocols/core/Compositor.hpp index 2f276719..5e6413c8 100644 --- a/src/protocols/core/Compositor.hpp +++ b/src/protocols/core/Compositor.hpp @@ -24,6 +24,7 @@ class CWLSurface; class CWLSurfaceResource; class CWLSubsurfaceResource; class CViewportResource; +class CDRMSyncobjSurfaceResource; class CWLCallbackResource { public: @@ -74,6 +75,7 @@ class CWLSurfaceResource { Vector2D sourceSize(); struct { + CSignal precommit; CSignal commit; CSignal map; CSignal unmap; @@ -81,11 +83,11 @@ class CWLSurfaceResource { CSignal destroy; } events; - struct { + struct SState { CRegion opaque, input = CBox{{}, {INT32_MAX, INT32_MAX}}, damage, bufferDamage = CBox{{}, {INT32_MAX, INT32_MAX}} /* initial damage */; wl_output_transform transform = WL_OUTPUT_TRANSFORM_NORMAL; int scale = 1; - SP buffer; + SP buffer; SP texture; Vector2D offset; Vector2D size; @@ -95,6 +97,7 @@ class CWLSurfaceResource { Vector2D destination; CBox source; } viewport; + bool rejected = false; // void reset() { @@ -115,9 +118,13 @@ class CWLSurfaceResource { std::vector> subsurfaces; WP role; WP viewportResource; + WP syncobj; // may not be present void breadthfirst(std::function, const Vector2D&, void*)> fn, void* data); CRegion accumulateCurrentBufferDamage(); + void presentFeedback(timespec* when, CMonitor* pMonitor, bool needsExplicitSync = false); + void lockPendingState(); + void unlockPendingState(); // returns a pair: found surface (null if not found) and surface local coords. // localCoords param is relative to 0,0 of this surface @@ -130,7 +137,10 @@ class CWLSurfaceResource { // tracks whether we should release the buffer bool bufferReleased = false; + int stateLocks = 0; + void destroy(); + void commitPendingState(); void bfHelper(std::vector> nodes, std::function, const Vector2D&, void*)> fn, void* data); }; diff --git a/src/protocols/core/Output.cpp b/src/protocols/core/Output.cpp index 10daa15e..4ba23cbe 100644 --- a/src/protocols/core/Output.cpp +++ b/src/protocols/core/Output.cpp @@ -21,8 +21,8 @@ CWLOutputResource::CWLOutputResource(SP resource_, SP pMoni PROTO::outputs.at(monitor->szName)->destroyResource(this); }); - resource->sendGeometry(0, 0, monitor->output->phys_width, monitor->output->phys_height, monitor->output->subpixel, monitor->output->make ? monitor->output->make : "null", - monitor->output->model ? monitor->output->model : "null", monitor->transform); + resource->sendGeometry(0, 0, monitor->output->physicalSize.x, monitor->output->physicalSize.y, (wl_output_subpixel)monitor->output->subpixel, monitor->output->make.c_str(), + monitor->output->model.c_str(), monitor->transform); if (resource->version() >= 4) { resource->sendName(monitor->szName.c_str()); resource->sendDescription(monitor->szDescription.c_str()); @@ -115,3 +115,9 @@ void CWLOutputProtocol::remove() { bool CWLOutputProtocol::isDefunct() { return defunct; } + +void CWLOutputProtocol::sendDone() { + for (auto& r : m_vOutputs) { + r->resource->sendDone(); + } +} diff --git a/src/protocols/core/Output.hpp b/src/protocols/core/Output.hpp index 46981635..46e4057b 100644 --- a/src/protocols/core/Output.hpp +++ b/src/protocols/core/Output.hpp @@ -26,6 +26,8 @@ class CWLOutputResource { private: SP resource; wl_client* pClient = nullptr; + + friend class CWLOutputProtocol; }; class CWLOutputProtocol : public IWaylandProtocol { @@ -35,6 +37,7 @@ class CWLOutputProtocol : public IWaylandProtocol { virtual void bindManager(wl_client* client, void* data, uint32_t ver, uint32_t id); SP outputResourceFrom(wl_client* client); + void sendDone(); WP monitor; diff --git a/src/protocols/core/Seat.cpp b/src/protocols/core/Seat.cpp index 464a901c..21a47575 100644 --- a/src/protocols/core/Seat.cpp +++ b/src/protocols/core/Seat.cpp @@ -254,8 +254,8 @@ void CWLKeyboardResource::sendKeymap(SP keyboard) { int fd; uint32_t size; if (keyboard) { - fd = keyboard->wlr()->keymap_fd; - size = keyboard->wlr()->keymap_size; + fd = keyboard->xkbKeymapFD; + size = keyboard->xkbKeymapString.length() + 1; } else { fd = open("/dev/null", O_RDONLY | O_CLOEXEC); if (fd < 0) { diff --git a/src/protocols/core/Shm.cpp b/src/protocols/core/Shm.cpp index 4088949f..75c2134a 100644 --- a/src/protocols/core/Shm.cpp +++ b/src/protocols/core/Shm.cpp @@ -41,20 +41,20 @@ CWLSHMBuffer::~CWLSHMBuffer() { ; } -eBufferCapability CWLSHMBuffer::caps() { - return BUFFER_CAPABILITY_DATAPTR; +Aquamarine::eBufferCapability CWLSHMBuffer::caps() { + return Aquamarine::eBufferCapability::BUFFER_CAPABILITY_DATAPTR; } -eBufferType CWLSHMBuffer::type() { - return BUFFER_TYPE_SHM; +Aquamarine::eBufferType CWLSHMBuffer::type() { + return Aquamarine::eBufferType::BUFFER_TYPE_SHM; } bool CWLSHMBuffer::isSynchronous() { return true; } -SSHMAttrs CWLSHMBuffer::shm() { - SSHMAttrs attrs; +Aquamarine::SSHMAttrs CWLSHMBuffer::shm() { + Aquamarine::SSHMAttrs attrs; attrs.success = true; attrs.fd = pool->fd; attrs.format = FormatUtils::shmToDRM(fmt); @@ -188,11 +188,18 @@ CWLSHMProtocol::CWLSHMProtocol(const wl_interface* iface, const int& ver, const void CWLSHMProtocol::bindManager(wl_client* client, void* data, uint32_t ver, uint32_t id) { if (shmFormats.empty()) { - size_t len = 0; - const uint32_t* formats = wlr_renderer_get_shm_texture_formats(g_pCompositor->m_sWLRRenderer, &len); + shmFormats.push_back(WL_SHM_FORMAT_ARGB8888); + shmFormats.push_back(WL_SHM_FORMAT_XRGB8888); - for (size_t i = 0; i < len; ++i) { - shmFormats.push_back(FormatUtils::drmToShm(formats[i])); + static const std::array supportedShmFourccFormats = { + DRM_FORMAT_XBGR8888, DRM_FORMAT_ABGR8888, DRM_FORMAT_XRGB2101010, DRM_FORMAT_ARGB2101010, DRM_FORMAT_XBGR2101010, DRM_FORMAT_ABGR2101010, + }; + + for (auto& fmt : g_pHyprOpenGL->getDRMFormats()) { + if (std::find(supportedShmFourccFormats.begin(), supportedShmFourccFormats.end(), fmt.drmFormat) == supportedShmFourccFormats.end()) + continue; + + shmFormats.push_back(fmt.drmFormat); } } diff --git a/src/protocols/core/Shm.hpp b/src/protocols/core/Shm.hpp index 70a8b208..fab325fe 100644 --- a/src/protocols/core/Shm.hpp +++ b/src/protocols/core/Shm.hpp @@ -29,16 +29,16 @@ class CSHMPool { void resize(size_t size); }; -class CWLSHMBuffer : public IWLBuffer { +class CWLSHMBuffer : public IHLBuffer { public: CWLSHMBuffer(SP pool, uint32_t id, int32_t offset, const Vector2D& size, int32_t stride, uint32_t fmt); virtual ~CWLSHMBuffer(); - virtual eBufferCapability caps(); - virtual eBufferType type(); + virtual Aquamarine::eBufferCapability caps(); + virtual Aquamarine::eBufferType type(); virtual void update(const CRegion& damage); virtual bool isSynchronous(); - virtual SSHMAttrs shm(); + virtual Aquamarine::SSHMAttrs shm(); virtual std::tuple beginDataPtr(uint32_t flags); virtual void endDataPtr(); diff --git a/src/protocols/types/Buffer.cpp b/src/protocols/types/Buffer.cpp index 5ed942e1..0217f7e2 100644 --- a/src/protocols/types/Buffer.cpp +++ b/src/protocols/types/Buffer.cpp @@ -1,41 +1,10 @@ #include "Buffer.hpp" -#include "WLBuffer.hpp" -SDMABUFAttrs IWLBuffer::dmabuf() { - return SDMABUFAttrs{}; +void IHLBuffer::sendRelease() { + resource->sendRelease(); } -SSHMAttrs IWLBuffer::shm() { - return SSHMAttrs{}; -} - -std::tuple IWLBuffer::beginDataPtr(uint32_t flags) { - return {nullptr, 0, 0}; -} - -void IWLBuffer::endDataPtr() { - ; // empty -} - -void IWLBuffer::sendRelease() { - if (!resource || !resource->resource) - return; - resource->resource->sendRelease(); -} - -void IWLBuffer::lock() { - locks++; -} - -void IWLBuffer::unlock() { - locks--; - - ASSERT(locks >= 0); - - if (locks <= 0) - sendRelease(); -} - -bool IWLBuffer::locked() { - return locks; +void IHLBuffer::sendReleaseWithSurface(SP surf) { + if (resource && resource->good()) + resource->sendReleaseWithSurface(surf); } diff --git a/src/protocols/types/Buffer.hpp b/src/protocols/types/Buffer.hpp index 9999a4e9..ba8278f3 100644 --- a/src/protocols/types/Buffer.hpp +++ b/src/protocols/types/Buffer.hpp @@ -1,75 +1,29 @@ #pragma once #include "../../defines.hpp" -#include "../../helpers/signal/Signal.hpp" #include "../../render/Texture.hpp" +#include "./WLBuffer.hpp" -#include -#include +#include -enum eBufferCapability { - BUFFER_CAPABILITY_DATAPTR = (1 << 0), -}; - -enum eBufferType { - BUFFER_TYPE_DMABUF = 0, - BUFFER_TYPE_SHM, - BUFFER_TYPE_MISC, -}; - -class CWLBufferResource; - -struct SDMABUFAttrs { - bool success = false; - Vector2D size; - uint32_t format = 0; // fourcc - uint64_t modifier = 0; - - int planes = 1; - std::array offsets = {0}; - std::array strides = {0}; - std::array fds = {-1, -1, -1, -1}; -}; - -struct SSHMAttrs { - bool success = false; - int fd = 0; - uint32_t format = 0; - Vector2D size; - int stride = 0; - int64_t offset = 0; -}; - -class IWLBuffer { +class IHLBuffer : public Aquamarine::IBuffer { public: - virtual ~IWLBuffer() { + virtual ~IHLBuffer() { ; - }; + } + virtual Aquamarine::eBufferCapability caps() = 0; + virtual Aquamarine::eBufferType type() = 0; + virtual void update(const CRegion& damage) = 0; + virtual bool isSynchronous() = 0; // whether the updates to this buffer are synchronous, aka happen over cpu + virtual bool good() = 0; + virtual void sendRelease(); + virtual void sendReleaseWithSurface(SP); - virtual eBufferCapability caps() = 0; - virtual eBufferType type() = 0; - virtual void update(const CRegion& damage) = 0; - virtual bool isSynchronous() = 0; // whether the updates to this buffer are synchronous, aka happen over cpu - virtual SDMABUFAttrs dmabuf(); - virtual SSHMAttrs shm(); - virtual std::tuple beginDataPtr(uint32_t flags); - virtual void endDataPtr(); - virtual void sendRelease(); - virtual void lock(); - virtual void unlock(); - virtual bool locked(); - - Vector2D size; - bool opaque = false; - - SP resource; - - SP texture; + SP texture; + bool opaque = false; + SP resource; struct { - CSignal destroy; - } events; - - private: - int locks = 0; + CHyprSignalListener backendRelease; + } hlEvents; }; diff --git a/src/protocols/types/DMABuffer.cpp b/src/protocols/types/DMABuffer.cpp index 7c3a9886..63a26c76 100644 --- a/src/protocols/types/DMABuffer.cpp +++ b/src/protocols/types/DMABuffer.cpp @@ -3,7 +3,7 @@ #include "../../render/Renderer.hpp" #include "../../helpers/Format.hpp" -CDMABuffer::CDMABuffer(uint32_t id, wl_client* client, SDMABUFAttrs const& attrs_) : attrs(attrs_) { +CDMABuffer::CDMABuffer(uint32_t id, wl_client* client, Aquamarine::SDMABUFAttrs const& attrs_) : attrs(attrs_) { g_pHyprRenderer->makeEGLCurrent(); listeners.resourceDestroy = events.destroy.registerListener([this](std::any d) { @@ -31,12 +31,12 @@ CDMABuffer::~CDMABuffer() { closeFDs(); } -eBufferCapability CDMABuffer::caps() { - return BUFFER_CAPABILITY_DATAPTR; +Aquamarine::eBufferCapability CDMABuffer::caps() { + return Aquamarine::eBufferCapability::BUFFER_CAPABILITY_DATAPTR; } -eBufferType CDMABuffer::type() { - return BUFFER_TYPE_DMABUF; +Aquamarine::eBufferType CDMABuffer::type() { + return Aquamarine::eBufferType::BUFFER_TYPE_DMABUF; } void CDMABuffer::update(const CRegion& damage) { @@ -47,7 +47,7 @@ bool CDMABuffer::isSynchronous() { return false; } -SDMABUFAttrs CDMABuffer::dmabuf() { +Aquamarine::SDMABUFAttrs CDMABuffer::dmabuf() { return attrs; } diff --git a/src/protocols/types/DMABuffer.hpp b/src/protocols/types/DMABuffer.hpp index d07840b7..6977df4c 100644 --- a/src/protocols/types/DMABuffer.hpp +++ b/src/protocols/types/DMABuffer.hpp @@ -2,16 +2,16 @@ #include "Buffer.hpp" -class CDMABuffer : public IWLBuffer { +class CDMABuffer : public IHLBuffer { public: - CDMABuffer(uint32_t id, wl_client* client, SDMABUFAttrs const& attrs_); + CDMABuffer(uint32_t id, wl_client* client, Aquamarine::SDMABUFAttrs const& attrs_); virtual ~CDMABuffer(); - virtual eBufferCapability caps(); - virtual eBufferType type(); + virtual Aquamarine::eBufferCapability caps(); + virtual Aquamarine::eBufferType type(); virtual bool isSynchronous(); virtual void update(const CRegion& damage); - virtual SDMABUFAttrs dmabuf(); + virtual Aquamarine::SDMABUFAttrs dmabuf(); virtual std::tuple beginDataPtr(uint32_t flags); virtual void endDataPtr(); bool good(); @@ -21,7 +21,7 @@ class CDMABuffer : public IWLBuffer { bool success = false; private: - SDMABUFAttrs attrs; + Aquamarine::SDMABUFAttrs attrs; struct { CHyprSignalListener resourceDestroy; diff --git a/src/protocols/types/WLBuffer.cpp b/src/protocols/types/WLBuffer.cpp index e53538cb..d34a867d 100644 --- a/src/protocols/types/WLBuffer.cpp +++ b/src/protocols/types/WLBuffer.cpp @@ -1,5 +1,10 @@ #include "WLBuffer.hpp" #include "Buffer.hpp" +#include "../core/Compositor.hpp" +#include "../DRMSyncobj.hpp" +#include "../../helpers/sync/SyncTimeline.hpp" +#include "../../Compositor.hpp" +#include CWLBufferResource::CWLBufferResource(SP resource_) : resource(resource_) { if (!good()) @@ -27,6 +32,16 @@ void CWLBufferResource::sendRelease() { resource->sendRelease(); } +void CWLBufferResource::sendReleaseWithSurface(SP surf) { + sendRelease(); + + if (!surf || !surf->syncobj) + return; + + if (drmSyncobjTimelineSignal(g_pCompositor->m_iDRMFD, &surf->syncobj->releaseTimeline->timeline->handle, &surf->syncobj->releasePoint, 1)) + Debug::log(ERR, "sendReleaseWithSurface: drmSyncobjTimelineSignal failed"); +} + wl_resource* CWLBufferResource::getResource() { return resource->resource(); } diff --git a/src/protocols/types/WLBuffer.hpp b/src/protocols/types/WLBuffer.hpp index ac177965..59512128 100644 --- a/src/protocols/types/WLBuffer.hpp +++ b/src/protocols/types/WLBuffer.hpp @@ -7,7 +7,8 @@ #include "wayland.hpp" #include "../../helpers/signal/Signal.hpp" -class IWLBuffer; +class IHLBuffer; +class CWLSurfaceResource; class CWLBufferResource { public: @@ -16,9 +17,10 @@ class CWLBufferResource { bool good(); void sendRelease(); + void sendReleaseWithSurface(SP); wl_resource* getResource(); - WP buffer; + WP buffer; WP self; @@ -27,5 +29,5 @@ class CWLBufferResource { SP resource; - friend class IWLBuffer; + friend class IHLBuffer; }; diff --git a/src/render/OpenGL.cpp b/src/render/OpenGL.cpp index e127ec2d..b2b046ce 100644 --- a/src/render/OpenGL.cpp +++ b/src/render/OpenGL.cpp @@ -9,6 +9,9 @@ #include "../protocols/LayerShell.hpp" #include "../protocols/core/Compositor.hpp" #include +#include +#include +#include inline void loadGLProc(void* pProc, const char* name) { void* proc = (void*)eglGetProcAddress(name); @@ -19,17 +22,203 @@ inline void loadGLProc(void* pProc, const char* name) { *(void**)pProc = proc; } +static enum LogLevel eglLogToLevel(EGLint type) { + switch (type) { + case EGL_DEBUG_MSG_CRITICAL_KHR: return CRIT; + case EGL_DEBUG_MSG_ERROR_KHR: return ERR; + case EGL_DEBUG_MSG_WARN_KHR: return WARN; + case EGL_DEBUG_MSG_INFO_KHR: return LOG; + default: return LOG; + } +} + +static const char* eglErrorToString(EGLint error) { + switch (error) { + case EGL_SUCCESS: return "EGL_SUCCESS"; + case EGL_NOT_INITIALIZED: return "EGL_NOT_INITIALIZED"; + case EGL_BAD_ACCESS: return "EGL_BAD_ACCESS"; + case EGL_BAD_ALLOC: return "EGL_BAD_ALLOC"; + case EGL_BAD_ATTRIBUTE: return "EGL_BAD_ATTRIBUTE"; + case EGL_BAD_CONTEXT: return "EGL_BAD_CONTEXT"; + case EGL_BAD_CONFIG: return "EGL_BAD_CONFIG"; + case EGL_BAD_CURRENT_SURFACE: return "EGL_BAD_CURRENT_SURFACE"; + case EGL_BAD_DISPLAY: return "EGL_BAD_DISPLAY"; + case EGL_BAD_DEVICE_EXT: return "EGL_BAD_DEVICE_EXT"; + case EGL_BAD_SURFACE: return "EGL_BAD_SURFACE"; + case EGL_BAD_MATCH: return "EGL_BAD_MATCH"; + case EGL_BAD_PARAMETER: return "EGL_BAD_PARAMETER"; + case EGL_BAD_NATIVE_PIXMAP: return "EGL_BAD_NATIVE_PIXMAP"; + case EGL_BAD_NATIVE_WINDOW: return "EGL_BAD_NATIVE_WINDOW"; + case EGL_CONTEXT_LOST: return "EGL_CONTEXT_LOST"; + } + return "Unknown"; +} + +static void eglLog(EGLenum error, const char* command, EGLint type, EGLLabelKHR thread, EGLLabelKHR obj, const char* msg) { + Debug::log(eglLogToLevel(type), "[EGL] Command {} errored out with {} (0x{}): {}", command, eglErrorToString(error), error, msg); +} + +static int openRenderNode(int drmFd) { + auto renderName = drmGetRenderDeviceNameFromFd(drmFd); + if (!renderName) { + // This can happen on split render/display platforms, fallback to + // primary node + renderName = drmGetPrimaryDeviceNameFromFd(drmFd); + if (!renderName) { + Debug::log(ERR, "drmGetPrimaryDeviceNameFromFd failed"); + return -1; + } + Debug::log(LOG, "DRM dev {} has no render node, falling back to primary", renderName); + + drmVersion* render_version = drmGetVersion(drmFd); + if (render_version && render_version->name) { + Debug::log(LOG, "DRM dev versionName", render_version->name); + if (strcmp(render_version->name, "evdi") == 0) { + free(renderName); + renderName = (char*)malloc(sizeof(char) * 15); + strcpy(renderName, "/dev/dri/card0"); + } + drmFreeVersion(render_version); + } + } + + Debug::log(LOG, "openRenderNode got drm device {}", renderName); + + int renderFD = open(renderName, O_RDWR | O_CLOEXEC); + if (renderFD < 0) + Debug::log(ERR, "openRenderNode failed to open drm device {}", renderName); + + free(renderName); + return renderFD; +} + +void CHyprOpenGLImpl::initEGL(bool gbm) { + std::vector attrs; + if (m_sExts.KHR_display_reference) { + attrs.push_back(EGL_TRACK_REFERENCES_KHR); + attrs.push_back(EGL_TRUE); + } + + attrs.push_back(EGL_NONE); + + m_pEglDisplay = m_sProc.eglGetPlatformDisplayEXT(gbm ? EGL_PLATFORM_GBM_KHR : EGL_PLATFORM_DEVICE_EXT, gbm ? m_pGbmDevice : nullptr, attrs.data()); + if (m_pEglDisplay == EGL_NO_DISPLAY) + RASSERT(false, "EGL: failed to create a platform display"); + + attrs.clear(); + + EGLint major, minor; + if (eglInitialize(m_pEglDisplay, &major, &minor) == EGL_FALSE) + RASSERT(false, "EGL: failed to initialize a platform display"); + + const std::string EGLEXTENSIONS = (const char*)eglQueryString(m_pEglDisplay, EGL_EXTENSIONS); + + m_sExts.IMG_context_priority = EGLEXTENSIONS.contains("IMG_context_priority"); + m_sExts.EXT_create_context_robustness = EGLEXTENSIONS.contains("EXT_create_context_robustness"); + m_sExts.EXT_image_dma_buf_import = EGLEXTENSIONS.contains("EXT_image_dma_buf_import"); + m_sExts.EXT_image_dma_buf_import_modifiers = EGLEXTENSIONS.contains("EXT_image_dma_buf_import_modifiers"); + + if (m_sExts.IMG_context_priority) { + Debug::log(LOG, "EGL: IMG_context_priority supported, requesting high"); + attrs.push_back(EGL_CONTEXT_PRIORITY_LEVEL_IMG); + attrs.push_back(EGL_CONTEXT_PRIORITY_HIGH_IMG); + } + + if (m_sExts.EXT_create_context_robustness) { + Debug::log(LOG, "EGL: EXT_create_context_robustness supported, requesting lose on reset"); + attrs.push_back(EGL_CONTEXT_OPENGL_RESET_NOTIFICATION_STRATEGY_EXT); + attrs.push_back(EGL_LOSE_CONTEXT_ON_RESET_EXT); + } + + attrs.push_back(EGL_CONTEXT_MAJOR_VERSION); + attrs.push_back(3); + attrs.push_back(EGL_CONTEXT_MINOR_VERSION); + attrs.push_back(2); + attrs.push_back(EGL_CONTEXT_OPENGL_DEBUG); + attrs.push_back(ISDEBUG ? EGL_TRUE : EGL_FALSE); + + attrs.push_back(EGL_NONE); + + m_pEglContext = eglCreateContext(m_pEglDisplay, EGL_NO_CONFIG_KHR, EGL_NO_CONTEXT, attrs.data()); + if (m_pEglContext == EGL_NO_CONTEXT) + RASSERT(false, "EGL: failed to create a context"); + + if (m_sExts.IMG_context_priority) { + EGLint priority = EGL_CONTEXT_PRIORITY_MEDIUM_IMG; + eglQueryContext(m_pEglDisplay, m_pEglContext, EGL_CONTEXT_PRIORITY_LEVEL_IMG, &priority); + if (priority != EGL_CONTEXT_PRIORITY_HIGH_IMG) + Debug::log(ERR, "EGL: Failed to obtain a high priority context"); + else + Debug::log(LOG, "EGL: Got a high priority context"); + } + + eglMakeCurrent(m_pEglDisplay, EGL_NO_SURFACE, EGL_NO_SURFACE, m_pEglContext); +} + CHyprOpenGLImpl::CHyprOpenGLImpl() { - RASSERT(eglMakeCurrent(wlr_egl_get_display(g_pCompositor->m_sWLREGL), EGL_NO_SURFACE, EGL_NO_SURFACE, wlr_egl_get_context(g_pCompositor->m_sWLREGL)), - "Couldn't unset current EGL!"); + const std::string EGLEXTENSIONS = (const char*)eglQueryString(EGL_NO_DISPLAY, EGL_EXTENSIONS); - auto* const EXTENSIONS = (const char*)glGetString(GL_EXTENSIONS); - const std::string EGLEXTENSIONS = (const char*)eglQueryString(wlr_egl_get_display(g_pCompositor->m_sWLREGL), EGL_EXTENSIONS); - - RASSERT(EXTENSIONS, "Couldn't retrieve openGL extensions!"); + Debug::log(LOG, "Supported EGL extensions: ({}) {}", std::count(EGLEXTENSIONS.begin(), EGLEXTENSIONS.end(), ' '), EGLEXTENSIONS); m_iDRMFD = g_pCompositor->m_iDRMFD; + m_sExts.KHR_display_reference = EGLEXTENSIONS.contains("KHR_display_reference"); + + loadGLProc(&m_sProc.glEGLImageTargetRenderbufferStorageOES, "glEGLImageTargetRenderbufferStorageOES"); + loadGLProc(&m_sProc.eglCreateImageKHR, "eglCreateImageKHR"); + loadGLProc(&m_sProc.eglDestroyImageKHR, "eglDestroyImageKHR"); + loadGLProc(&m_sProc.eglQueryDmaBufFormatsEXT, "eglQueryDmaBufFormatsEXT"); + loadGLProc(&m_sProc.eglQueryDmaBufModifiersEXT, "eglQueryDmaBufModifiersEXT"); + loadGLProc(&m_sProc.glEGLImageTargetTexture2DOES, "glEGLImageTargetTexture2DOES"); + loadGLProc(&m_sProc.eglDebugMessageControlKHR, "eglDebugMessageControlKHR"); + loadGLProc(&m_sProc.eglGetPlatformDisplayEXT, "eglGetPlatformDisplayEXT"); + loadGLProc(&m_sProc.eglCreateSyncKHR, "eglCreateSyncKHR"); + loadGLProc(&m_sProc.eglDestroySyncKHR, "eglDestroySyncKHR"); + loadGLProc(&m_sProc.eglDupNativeFenceFDANDROID, "eglDupNativeFenceFDANDROID"); + loadGLProc(&m_sProc.eglWaitSyncKHR, "eglWaitSyncKHR"); + + RASSERT(m_sProc.eglCreateSyncKHR, "Display driver doesn't support eglCreateSyncKHR"); + RASSERT(m_sProc.eglDupNativeFenceFDANDROID, "Display driver doesn't support eglDupNativeFenceFDANDROID"); + RASSERT(m_sProc.eglWaitSyncKHR, "Display driver doesn't support eglWaitSyncKHR"); + + if (EGLEXTENSIONS.contains("EGL_EXT_device_base") || EGLEXTENSIONS.contains("EGL_EXT_device_enumeration")) + loadGLProc(&m_sProc.eglQueryDevicesEXT, "eglQueryDevicesEXT"); + + if (EGLEXTENSIONS.contains("EGL_EXT_device_base") || EGLEXTENSIONS.contains("EGL_EXT_device_query")) { + loadGLProc(&m_sProc.eglQueryDeviceStringEXT, "eglQueryDeviceStringEXT"); + loadGLProc(&m_sProc.eglQueryDisplayAttribEXT, "eglQueryDisplayAttribEXT"); + } + + if (EGLEXTENSIONS.contains("EGL_KHR_debug")) { + loadGLProc(&m_sProc.eglDebugMessageControlKHR, "eglDebugMessageControlKHR"); + static const EGLAttrib debugAttrs[] = { + EGL_DEBUG_MSG_CRITICAL_KHR, EGL_TRUE, EGL_DEBUG_MSG_ERROR_KHR, EGL_TRUE, EGL_DEBUG_MSG_WARN_KHR, EGL_TRUE, EGL_DEBUG_MSG_INFO_KHR, EGL_TRUE, EGL_NONE, + }; + m_sProc.eglDebugMessageControlKHR(::eglLog, debugAttrs); + } + + RASSERT(eglBindAPI(EGL_OPENGL_ES_API) != EGL_FALSE, "Couldn't bind to EGL's opengl ES API. This means your gpu driver f'd up. This is not a hyprland issue."); + + // if (m_sProc.eglQueryDevicesEXT) { + // // TODO: + // } + + if (EGLEXTENSIONS.contains("KHR_platform_gbm")) { + m_iGBMFD = openRenderNode(m_iDRMFD); + if (m_iGBMFD < 0) + RASSERT(false, "Couldn't open a gbm fd"); + + m_pGbmDevice = gbm_create_device(m_iGBMFD); + if (!m_pGbmDevice) + RASSERT(false, "Couldn't open a gbm device"); + + initEGL(true); + } else + RASSERT(false, "EGL does not support KHR_platform_gbm, this is an issue with your gpu driver."); + + auto* const EXTENSIONS = (const char*)glGetString(GL_EXTENSIONS); + RASSERT(EXTENSIONS, "Couldn't retrieve openGL extensions!"); + m_szExtensions = EXTENSIONS; Debug::log(LOG, "Creating the Hypr OpenGL Renderer!"); @@ -38,16 +227,7 @@ CHyprOpenGLImpl::CHyprOpenGLImpl() { Debug::log(LOG, "Renderer: {}", (char*)glGetString(GL_RENDERER)); Debug::log(LOG, "Supported extensions: ({}) {}", std::count(m_szExtensions.begin(), m_szExtensions.end(), ' '), m_szExtensions); - loadGLProc(&m_sProc.glEGLImageTargetRenderbufferStorageOES, "glEGLImageTargetRenderbufferStorageOES"); - loadGLProc(&m_sProc.eglCreateImageKHR, "eglCreateImageKHR"); - loadGLProc(&m_sProc.eglDestroyImageKHR, "eglDestroyImageKHR"); - loadGLProc(&m_sProc.eglQueryDmaBufFormatsEXT, "eglQueryDmaBufFormatsEXT"); - loadGLProc(&m_sProc.eglQueryDmaBufModifiersEXT, "eglQueryDmaBufModifiersEXT"); - loadGLProc(&m_sProc.glEGLImageTargetTexture2DOES, "glEGLImageTargetTexture2DOES"); - - m_sExts.EXT_read_format_bgra = m_szExtensions.contains("GL_EXT_read_format_bgra"); - m_sExts.EXT_image_dma_buf_import = EGLEXTENSIONS.contains("EXT_image_dma_buf_import"); - m_sExts.EXT_image_dma_buf_import_modifiers = EGLEXTENSIONS.contains("EXT_image_dma_buf_import_modifiers"); + m_sExts.EXT_read_format_bgra = m_szExtensions.contains("GL_EXT_read_format_bgra"); RASSERT(m_szExtensions.contains("GL_EXT_texture_format_BGRA8888"), "GL_EXT_texture_format_BGRA8888 support by the GPU driver is required"); @@ -74,7 +254,7 @@ CHyprOpenGLImpl::CHyprOpenGLImpl() { static auto P = g_pHookSystem->hookDynamic("preRender", [&](void* self, SCallbackInfo& info, std::any data) { preRender(std::any_cast(data)); }); - RASSERT(eglMakeCurrent(wlr_egl_get_display(g_pCompositor->m_sWLREGL), EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT), "Couldn't unset current EGL!"); + RASSERT(eglMakeCurrent(m_pEglDisplay, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT), "Couldn't unset current EGL!"); m_tGlobalTimer.reset(); } @@ -86,7 +266,7 @@ std::optional> CHyprOpenGLImpl::getModsForFormat(EGLint fo return std::nullopt; EGLint len = 0; - if (!m_sProc.eglQueryDmaBufModifiersEXT(wlr_egl_get_display(g_pCompositor->m_sWLREGL), format, 0, nullptr, nullptr, &len)) { + if (!m_sProc.eglQueryDmaBufModifiersEXT(m_pEglDisplay, format, 0, nullptr, nullptr, &len)) { Debug::log(ERR, "EGL: Failed to query mods"); return std::nullopt; } @@ -100,7 +280,7 @@ std::optional> CHyprOpenGLImpl::getModsForFormat(EGLint fo mods.resize(len); external.resize(len); - m_sProc.eglQueryDmaBufModifiersEXT(wlr_egl_get_display(g_pCompositor->m_sWLREGL), format, len, mods.data(), external.data(), &len); + m_sProc.eglQueryDmaBufModifiersEXT(m_pEglDisplay, format, len, mods.data(), external.data(), &len); std::vector result; bool linearIsExternal = false; @@ -139,9 +319,9 @@ void CHyprOpenGLImpl::initDRMFormats() { Debug::log(WARN, "EGL: No mod support"); } else { EGLint len = 0; - m_sProc.eglQueryDmaBufFormatsEXT(wlr_egl_get_display(g_pCompositor->m_sWLREGL), 0, nullptr, &len); + m_sProc.eglQueryDmaBufFormatsEXT(m_pEglDisplay, 0, nullptr, &len); formats.resize(len); - m_sProc.eglQueryDmaBufFormatsEXT(wlr_egl_get_display(g_pCompositor->m_sWLREGL), len, formats.data(), &len); + m_sProc.eglQueryDmaBufFormatsEXT(m_pEglDisplay, len, formats.data(), &len); } if (formats.size() == 0) { @@ -149,7 +329,7 @@ void CHyprOpenGLImpl::initDRMFormats() { return; } - wlr_log(WLR_DEBUG, "Supported DMA-BUF formats:"); + Debug::log(LOG, "Supported DMA-BUF formats:"); std::vector dmaFormats; @@ -170,8 +350,8 @@ void CHyprOpenGLImpl::initDRMFormats() { mods.push_back(DRM_FORMAT_MOD_INVALID); dmaFormats.push_back(SDRMFormat{ - .format = fmt, - .mods = mods, + .drmFormat = fmt, + .modifiers = mods, }); std::vector> modifierData; @@ -209,7 +389,7 @@ void CHyprOpenGLImpl::initDRMFormats() { drmFormats = dmaFormats; } -EGLImageKHR CHyprOpenGLImpl::createEGLImage(const SDMABUFAttrs& attrs) { +EGLImageKHR CHyprOpenGLImpl::createEGLImage(const Aquamarine::SDMABUFAttrs& attrs) { std::vector attribs; attribs.push_back(EGL_WIDTH); @@ -251,7 +431,7 @@ EGLImageKHR CHyprOpenGLImpl::createEGLImage(const SDMABUFAttrs& attrs) { attribs.push_back(EGL_NONE); - EGLImageKHR image = m_sProc.eglCreateImageKHR(wlr_egl_get_display(g_pCompositor->m_sWLREGL), EGL_NO_CONTEXT, EGL_LINUX_DMA_BUF_EXT, nullptr, (int*)attribs.data()); + EGLImageKHR image = m_sProc.eglCreateImageKHR(m_pEglDisplay, EGL_NO_CONTEXT, EGL_LINUX_DMA_BUF_EXT, nullptr, (int*)attribs.data()); if (image == EGL_NO_IMAGE_KHR) { Debug::log(ERR, "EGL: EGLCreateImageKHR failed: {}", eglGetError()); return EGL_NO_IMAGE_KHR; @@ -342,7 +522,8 @@ GLuint CHyprOpenGLImpl::compileShader(const GLuint& type, std::string src, bool } bool CHyprOpenGLImpl::passRequiresIntrospection(CMonitor* pMonitor) { - // passes requiring introspection are the ones that need to render blur. + // passes requiring introspection are the ones that need to render blur, + // or when we are rendering to a multigpu target static auto PBLUR = CConfigValue("decoration:blur:enabled"); static auto PXRAY = CConfigValue("decoration:blur:xray"); @@ -446,7 +627,7 @@ bool CHyprOpenGLImpl::passRequiresIntrospection(CMonitor* pMonitor) { return false; } -void CHyprOpenGLImpl::beginSimple(CMonitor* pMonitor, const CRegion& damage, CRenderbuffer* rb, CFramebuffer* fb) { +void CHyprOpenGLImpl::beginSimple(CMonitor* pMonitor, const CRegion& damage, SP rb, CFramebuffer* fb) { m_RenderData.pMonitor = pMonitor; #ifndef GLES2 @@ -472,12 +653,12 @@ void CHyprOpenGLImpl::beginSimple(CMonitor* pMonitor, const CRegion& damage, CRe matrixProjection(m_RenderData.projection, pMonitor->vecPixelSize.x, pMonitor->vecPixelSize.y, WL_OUTPUT_TRANSFORM_NORMAL); - wlr_matrix_identity(m_RenderData.monitorProjection.data()); + matrixIdentity(m_RenderData.monitorProjection.data()); if (pMonitor->transform != WL_OUTPUT_TRANSFORM_NORMAL) { const Vector2D tfmd = pMonitor->transform % 2 == 1 ? Vector2D{FBO->m_vSize.y, FBO->m_vSize.x} : FBO->m_vSize; - wlr_matrix_translate(m_RenderData.monitorProjection.data(), FBO->m_vSize.x / 2.0, FBO->m_vSize.y / 2.0); - wlr_matrix_transform(m_RenderData.monitorProjection.data(), pMonitor->transform); - wlr_matrix_translate(m_RenderData.monitorProjection.data(), -tfmd.x / 2.0, -tfmd.y / 2.0); + matrixTranslate(m_RenderData.monitorProjection.data(), FBO->m_vSize.x / 2.0, FBO->m_vSize.y / 2.0); + matrixTransform(m_RenderData.monitorProjection.data(), wlTransformToHyprutils(pMonitor->transform)); + matrixTranslate(m_RenderData.monitorProjection.data(), -tfmd.x / 2.0, -tfmd.y / 2.0); } m_RenderData.pCurrentMonData = &m_mMonitorRenderResources[pMonitor]; @@ -545,10 +726,10 @@ void CHyprOpenGLImpl::begin(CMonitor* pMonitor, const CRegion& damage_, CFramebu m_RenderData.pCurrentMonData->mirrorSwapFB.m_pStencilTex = m_RenderData.pCurrentMonData->stencilTex; m_RenderData.pCurrentMonData->offMainFB.m_pStencilTex = m_RenderData.pCurrentMonData->stencilTex; - m_RenderData.pCurrentMonData->offloadFB.alloc(pMonitor->vecPixelSize.x, pMonitor->vecPixelSize.y, pMonitor->drmFormat); - m_RenderData.pCurrentMonData->mirrorFB.alloc(pMonitor->vecPixelSize.x, pMonitor->vecPixelSize.y, pMonitor->drmFormat); - m_RenderData.pCurrentMonData->mirrorSwapFB.alloc(pMonitor->vecPixelSize.x, pMonitor->vecPixelSize.y, pMonitor->drmFormat); - m_RenderData.pCurrentMonData->offMainFB.alloc(pMonitor->vecPixelSize.x, pMonitor->vecPixelSize.y, pMonitor->drmFormat); + m_RenderData.pCurrentMonData->offloadFB.alloc(pMonitor->vecPixelSize.x, pMonitor->vecPixelSize.y, pMonitor->output->state->state().drmFormat); + m_RenderData.pCurrentMonData->mirrorFB.alloc(pMonitor->vecPixelSize.x, pMonitor->vecPixelSize.y, pMonitor->output->state->state().drmFormat); + m_RenderData.pCurrentMonData->mirrorSwapFB.alloc(pMonitor->vecPixelSize.x, pMonitor->vecPixelSize.y, pMonitor->output->state->state().drmFormat); + m_RenderData.pCurrentMonData->offMainFB.alloc(pMonitor->vecPixelSize.x, pMonitor->vecPixelSize.y, pMonitor->output->state->state().drmFormat); } if (m_RenderData.pCurrentMonData->monitorMirrorFB.isAllocated() && m_RenderData.pMonitor->mirrors.empty()) @@ -597,7 +778,7 @@ void CHyprOpenGLImpl::end() { TRACY_GPU_ZONE("RenderEnd"); - // end the render, copy the data to the WLR framebuffer + // end the render, copy the data to the main framebuffer if (m_bOffloadedFramebuffer) { m_RenderData.damage = m_RenderData.finalDamage; m_bEndFrame = true; @@ -915,11 +1096,8 @@ void CHyprOpenGLImpl::scissor(const CBox* pBox, bool transform) { CBox newBox = *pBox; if (transform) { - int w, h; - wlr_output_transformed_resolution(m_RenderData.pMonitor->output, &w, &h); - - const auto TR = wlTransformToHyprutils(wlr_output_transform_invert(m_RenderData.pMonitor->transform)); - newBox.transform(TR, w, h); + const auto TR = wlTransformToHyprutils(invertTransform(m_RenderData.pMonitor->transform)); + newBox.transform(TR, m_RenderData.pMonitor->vecTransformedSize.x, m_RenderData.pMonitor->vecTransformedSize.y); } glScissor(newBox.x, newBox.y, newBox.width, newBox.height); @@ -1008,18 +1186,18 @@ void CHyprOpenGLImpl::renderRectWithDamage(CBox* box, const CColor& col, CRegion box = &newBox; float matrix[9]; - projectBox(matrix, newBox, wlTransformToHyprutils(wlr_output_transform_invert(!m_bEndFrame ? WL_OUTPUT_TRANSFORM_NORMAL : m_RenderData.pMonitor->transform)), newBox.rot, - m_RenderData.monitorProjection.data()); // TODO: write own, don't use WLR here + projectBox(matrix, newBox, wlTransformToHyprutils(invertTransform(!m_bEndFrame ? WL_OUTPUT_TRANSFORM_NORMAL : m_RenderData.pMonitor->transform)), newBox.rot, + m_RenderData.monitorProjection.data()); float glMatrix[9]; - wlr_matrix_multiply(glMatrix, m_RenderData.projection, matrix); + matrixMultiply(glMatrix, m_RenderData.projection, matrix); glUseProgram(m_RenderData.pCurrentMonData->m_shQUAD.program); #ifndef GLES2 glUniformMatrix3fv(m_RenderData.pCurrentMonData->m_shQUAD.proj, 1, GL_TRUE, glMatrix); #else - wlr_matrix_transpose(glMatrix, glMatrix); + matrixTranspose(glMatrix, glMatrix); glUniformMatrix3fv(m_RenderData.pCurrentMonData->m_shQUAD.proj, 1, GL_FALSE, glMatrix); #endif @@ -1027,7 +1205,7 @@ void CHyprOpenGLImpl::renderRectWithDamage(CBox* box, const CColor& col, CRegion glUniform4f(m_RenderData.pCurrentMonData->m_shQUAD.color, col.r * col.a, col.g * col.a, col.b * col.a, col.a); CBox transformedBox = *box; - transformedBox.transform(wlTransformToHyprutils(wlr_output_transform_invert(m_RenderData.pMonitor->transform)), m_RenderData.pMonitor->vecTransformedSize.x, + transformedBox.transform(wlTransformToHyprutils(invertTransform(m_RenderData.pMonitor->transform)), m_RenderData.pMonitor->vecTransformedSize.x, m_RenderData.pMonitor->vecTransformedSize.y); const auto TOPLEFT = Vector2D(transformedBox.x, transformedBox.y); @@ -1072,16 +1250,17 @@ void CHyprOpenGLImpl::renderTexture(SP tex, CBox* pBox, float alpha, i scissor((CBox*)nullptr); } -void CHyprOpenGLImpl::renderTextureWithDamage(SP tex, CBox* pBox, CRegion* damage, float alpha, int round, bool discardActive, bool allowCustomUV) { +void CHyprOpenGLImpl::renderTextureWithDamage(SP tex, CBox* pBox, CRegion* damage, float alpha, int round, bool discardActive, bool allowCustomUV, + SP waitTimeline, uint64_t waitPoint) { RASSERT(m_RenderData.pMonitor, "Tried to render texture without begin()!"); - renderTextureInternalWithDamage(tex, pBox, alpha, damage, round, discardActive, false, allowCustomUV, true); + renderTextureInternalWithDamage(tex, pBox, alpha, damage, round, discardActive, false, allowCustomUV, true, waitTimeline, waitPoint); scissor((CBox*)nullptr); } void CHyprOpenGLImpl::renderTextureInternalWithDamage(SP tex, CBox* pBox, float alpha, CRegion* damage, int round, bool discardActive, bool noAA, bool allowCustomUV, - bool allowDim) { + bool allowDim, SP waitTimeline, uint64_t waitPoint) { RASSERT(m_RenderData.pMonitor, "Tried to render texture without begin()!"); RASSERT((tex->m_iTexID > 0), "Attempted to draw NULL texture!"); @@ -1099,12 +1278,19 @@ void CHyprOpenGLImpl::renderTextureInternalWithDamage(SP tex, CBox* pB static auto PDT = CConfigValue("debug:damage_tracking"); // get transform - const auto TRANSFORM = wlTransformToHyprutils(wlr_output_transform_invert(!m_bEndFrame ? WL_OUTPUT_TRANSFORM_NORMAL : m_RenderData.pMonitor->transform)); + const auto TRANSFORM = wlTransformToHyprutils(invertTransform(!m_bEndFrame ? WL_OUTPUT_TRANSFORM_NORMAL : m_RenderData.pMonitor->transform)); float matrix[9]; projectBox(matrix, newBox, TRANSFORM, newBox.rot, m_RenderData.monitorProjection.data()); float glMatrix[9]; - wlr_matrix_multiply(glMatrix, m_RenderData.projection, matrix); + matrixMultiply(glMatrix, m_RenderData.projection, matrix); + + if (waitTimeline != nullptr) { + if (!waitForTimelinePoint(waitTimeline, waitPoint)) { + Debug::log(ERR, "renderTextureInternalWithDamage: failed to wait for explicit sync point {}", waitPoint); + return; + } + } CShader* shader = nullptr; @@ -1151,7 +1337,7 @@ void CHyprOpenGLImpl::renderTextureInternalWithDamage(SP tex, CBox* pB #ifndef GLES2 glUniformMatrix3fv(shader->proj, 1, GL_TRUE, glMatrix); #else - wlr_matrix_transpose(glMatrix, glMatrix); + matrixTranspose(glMatrix, glMatrix); glUniformMatrix3fv(shader->proj, 1, GL_FALSE, glMatrix); #endif glUniform1i(shader->tex, 0); @@ -1187,7 +1373,7 @@ void CHyprOpenGLImpl::renderTextureInternalWithDamage(SP tex, CBox* pB } CBox transformedBox = newBox; - transformedBox.transform(wlTransformToHyprutils(wlr_output_transform_invert(m_RenderData.pMonitor->transform)), m_RenderData.pMonitor->vecTransformedSize.x, + transformedBox.transform(wlTransformToHyprutils(invertTransform(m_RenderData.pMonitor->transform)), m_RenderData.pMonitor->vecTransformedSize.x, m_RenderData.pMonitor->vecTransformedSize.y); const auto TOPLEFT = Vector2D(transformedBox.x, transformedBox.y); @@ -1262,12 +1448,12 @@ void CHyprOpenGLImpl::renderTexturePrimitive(SP tex, CBox* pBox) { m_RenderData.renderModif.applyToBox(newBox); // get transform - const auto TRANSFORM = wlTransformToHyprutils(wlr_output_transform_invert(!m_bEndFrame ? WL_OUTPUT_TRANSFORM_NORMAL : m_RenderData.pMonitor->transform)); + const auto TRANSFORM = wlTransformToHyprutils(invertTransform(!m_bEndFrame ? WL_OUTPUT_TRANSFORM_NORMAL : m_RenderData.pMonitor->transform)); float matrix[9]; projectBox(matrix, newBox, TRANSFORM, newBox.rot, m_RenderData.monitorProjection.data()); float glMatrix[9]; - wlr_matrix_multiply(glMatrix, m_RenderData.projection, matrix); + matrixMultiply(glMatrix, m_RenderData.projection, matrix); CShader* shader = &m_RenderData.pCurrentMonData->m_shPASSTHRURGBA; @@ -1279,7 +1465,7 @@ void CHyprOpenGLImpl::renderTexturePrimitive(SP tex, CBox* pBox) { #ifndef GLES2 glUniformMatrix3fv(shader->proj, 1, GL_TRUE, glMatrix); #else - wlr_matrix_transpose(glMatrix, glMatrix); + matrixTranspose(glMatrix, glMatrix); glUniformMatrix3fv(shader->proj, 1, GL_FALSE, glMatrix); #endif glUniform1i(shader->tex, 0); @@ -1316,12 +1502,12 @@ void CHyprOpenGLImpl::renderTextureMatte(SP tex, CBox* pBox, CFramebuf m_RenderData.renderModif.applyToBox(newBox); // get transform - const auto TRANSFORM = wlTransformToHyprutils(wlr_output_transform_invert(!m_bEndFrame ? WL_OUTPUT_TRANSFORM_NORMAL : m_RenderData.pMonitor->transform)); + const auto TRANSFORM = wlTransformToHyprutils(invertTransform(!m_bEndFrame ? WL_OUTPUT_TRANSFORM_NORMAL : m_RenderData.pMonitor->transform)); float matrix[9]; projectBox(matrix, newBox, TRANSFORM, newBox.rot, m_RenderData.monitorProjection.data()); float glMatrix[9]; - wlr_matrix_multiply(glMatrix, m_RenderData.projection, matrix); + matrixMultiply(glMatrix, m_RenderData.projection, matrix); CShader* shader = &m_RenderData.pCurrentMonData->m_shMATTE; @@ -1330,7 +1516,7 @@ void CHyprOpenGLImpl::renderTextureMatte(SP tex, CBox* pBox, CFramebuf #ifndef GLES2 glUniformMatrix3fv(shader->proj, 1, GL_TRUE, glMatrix); #else - wlr_matrix_transpose(glMatrix, glMatrix); + matrixTranspose(glMatrix, glMatrix); glUniformMatrix3fv(shader->proj, 1, GL_FALSE, glMatrix); #endif glUniform1i(shader->tex, 0); @@ -1374,13 +1560,13 @@ CFramebuffer* CHyprOpenGLImpl::blurMainFramebufferWithDamage(float a, CRegion* o glDisable(GL_STENCIL_TEST); // get transforms for the full monitor - const auto TRANSFORM = wlTransformToHyprutils(wlr_output_transform_invert(m_RenderData.pMonitor->transform)); + const auto TRANSFORM = wlTransformToHyprutils(invertTransform(m_RenderData.pMonitor->transform)); float matrix[9]; CBox MONITORBOX = {0, 0, m_RenderData.pMonitor->vecTransformedSize.x, m_RenderData.pMonitor->vecTransformedSize.y}; projectBox(matrix, MONITORBOX, TRANSFORM, 0, m_RenderData.monitorProjection.data()); float glMatrix[9]; - wlr_matrix_multiply(glMatrix, m_RenderData.projection, matrix); + matrixMultiply(glMatrix, m_RenderData.projection, matrix); // get the config settings static auto PBLURSIZE = CConfigValue("decoration:blur:size"); @@ -1390,9 +1576,9 @@ CFramebuffer* CHyprOpenGLImpl::blurMainFramebufferWithDamage(float a, CRegion* o // prep damage CRegion damage{*originalDamage}; - wlr_region_transform(damage.pixman(), damage.pixman(), wlr_output_transform_invert(m_RenderData.pMonitor->transform), m_RenderData.pMonitor->vecTransformedSize.x, - m_RenderData.pMonitor->vecTransformedSize.y); - wlr_region_expand(damage.pixman(), damage.pixman(), *PBLURPASSES > 10 ? pow(2, 15) : std::clamp(*PBLURSIZE, (int64_t)1, (int64_t)40) * pow(2, *PBLURPASSES)); + damage.transform(wlTransformToHyprutils(invertTransform(m_RenderData.pMonitor->transform)), m_RenderData.pMonitor->vecTransformedSize.x, + m_RenderData.pMonitor->vecTransformedSize.y); + damage.expand(*PBLURPASSES > 10 ? pow(2, 15) : std::clamp(*PBLURSIZE, (int64_t)1, (int64_t)40) * pow(2, *PBLURPASSES)); // helper const auto PMIRRORFB = &m_RenderData.pCurrentMonData->mirrorFB; @@ -1419,7 +1605,7 @@ CFramebuffer* CHyprOpenGLImpl::blurMainFramebufferWithDamage(float a, CRegion* o #ifndef GLES2 glUniformMatrix3fv(m_RenderData.pCurrentMonData->m_shBLURPREPARE.proj, 1, GL_TRUE, glMatrix); #else - wlr_matrix_transpose(glMatrix, glMatrix); + matrixTranspose(glMatrix, glMatrix); glUniformMatrix3fv(m_RenderData.pCurrentMonData->m_shBLURPREPARE.proj, 1, GL_FALSE, glMatrix); #endif glUniform1f(m_RenderData.pCurrentMonData->m_shBLURPREPARE.contrast, *PBLURCONTRAST); @@ -1464,7 +1650,7 @@ CFramebuffer* CHyprOpenGLImpl::blurMainFramebufferWithDamage(float a, CRegion* o #ifndef GLES2 glUniformMatrix3fv(pShader->proj, 1, GL_TRUE, glMatrix); #else - wlr_matrix_transpose(glMatrix, glMatrix); + matrixTranspose(glMatrix, glMatrix); glUniformMatrix3fv(pShader->proj, 1, GL_FALSE, glMatrix); #endif glUniform1f(pShader->radius, *PBLURSIZE * a); // this makes the blursize change with a @@ -1511,13 +1697,13 @@ CFramebuffer* CHyprOpenGLImpl::blurMainFramebufferWithDamage(float a, CRegion* o // and draw for (int i = 1; i <= *PBLURPASSES; ++i) { - wlr_region_scale(tempDamage.pixman(), damage.pixman(), 1.f / (1 << i)); + tempDamage = damage.copy().scale(1.f / (1 << i)); drawPass(&m_RenderData.pCurrentMonData->m_shBLUR1, &tempDamage); // down } for (int i = *PBLURPASSES - 1; i >= 0; --i) { - wlr_region_scale(tempDamage.pixman(), damage.pixman(), 1.f / (1 << i)); // when upsampling we make the region twice as big - drawPass(&m_RenderData.pCurrentMonData->m_shBLUR2, &tempDamage); // up + tempDamage = damage.copy().scale(1.f / (1 << i)); // when upsampling we make the region twice as big + drawPass(&m_RenderData.pCurrentMonData->m_shBLUR2, &tempDamage); // up } // finalize the image @@ -1541,7 +1727,7 @@ CFramebuffer* CHyprOpenGLImpl::blurMainFramebufferWithDamage(float a, CRegion* o #ifndef GLES2 glUniformMatrix3fv(m_RenderData.pCurrentMonData->m_shBLURFINISH.proj, 1, GL_TRUE, glMatrix); #else - wlr_matrix_transpose(glMatrix, glMatrix); + matrixTranspose(glMatrix, glMatrix); glUniformMatrix3fv(m_RenderData.pCurrentMonData->m_shBLURFINISH.proj, 1, GL_FALSE, glMatrix); #endif glUniform1f(m_RenderData.pCurrentMonData->m_shBLURFINISH.noise, *PBLURNOISE); @@ -1679,7 +1865,8 @@ void CHyprOpenGLImpl::preBlurForCurrentMonitor() { const auto POUTFB = blurMainFramebufferWithDamage(1, &fakeDamage); // render onto blurFB - m_RenderData.pCurrentMonData->blurFB.alloc(m_RenderData.pMonitor->vecPixelSize.x, m_RenderData.pMonitor->vecPixelSize.y, m_RenderData.pMonitor->drmFormat); + m_RenderData.pCurrentMonData->blurFB.alloc(m_RenderData.pMonitor->vecPixelSize.x, m_RenderData.pMonitor->vecPixelSize.y, + m_RenderData.pMonitor->output->state->state().drmFormat); m_RenderData.pCurrentMonData->blurFB.bind(); clear(CColor(0, 0, 0, 0)); @@ -1773,7 +1960,7 @@ void CHyprOpenGLImpl::renderTextureWithBlur(SP tex, CBox* pBox, float inverseOpaque = {0, 0, pBox->width, pBox->height}; } - wlr_region_scale(inverseOpaque.pixman(), inverseOpaque.pixman(), m_RenderData.pMonitor->scale); + inverseOpaque.scale(m_RenderData.pMonitor->scale); // vvv TODO: layered blur fbs? const bool USENEWOPTIMIZE = shouldUseNewBlurOptimizations(m_pCurrentLayer, m_pCurrentWindow.lock()) && !blockBlurOptimization; @@ -1872,11 +2059,11 @@ void CHyprOpenGLImpl::renderBorder(CBox* box, const CGradientValueData& grad, in round += round == 0 ? 0 : scaledBorderSize; float matrix[9]; - projectBox(matrix, newBox, wlTransformToHyprutils(wlr_output_transform_invert(!m_bEndFrame ? WL_OUTPUT_TRANSFORM_NORMAL : m_RenderData.pMonitor->transform)), newBox.rot, - m_RenderData.monitorProjection.data()); // TODO: write own, don't use WLR here + projectBox(matrix, newBox, wlTransformToHyprutils(invertTransform(!m_bEndFrame ? WL_OUTPUT_TRANSFORM_NORMAL : m_RenderData.pMonitor->transform)), newBox.rot, + m_RenderData.monitorProjection.data()); float glMatrix[9]; - wlr_matrix_multiply(glMatrix, m_RenderData.projection, matrix); + matrixMultiply(glMatrix, m_RenderData.projection, matrix); const auto BLEND = m_bBlend; blend(true); @@ -1886,7 +2073,7 @@ void CHyprOpenGLImpl::renderBorder(CBox* box, const CGradientValueData& grad, in #ifndef GLES2 glUniformMatrix3fv(m_RenderData.pCurrentMonData->m_shBORDER1.proj, 1, GL_TRUE, glMatrix); #else - wlr_matrix_transpose(glMatrix, glMatrix); + matrixTranspose(glMatrix, glMatrix); glUniformMatrix3fv(m_RenderData.pCurrentMonData->m_shBORDER1.proj, 1, GL_FALSE, glMatrix); #endif @@ -1898,7 +2085,7 @@ void CHyprOpenGLImpl::renderBorder(CBox* box, const CGradientValueData& grad, in glUniform1f(m_RenderData.pCurrentMonData->m_shBORDER1.alpha, a); CBox transformedBox = *box; - transformedBox.transform(wlTransformToHyprutils(wlr_output_transform_invert(m_RenderData.pMonitor->transform)), m_RenderData.pMonitor->vecTransformedSize.x, + transformedBox.transform(wlTransformToHyprutils(invertTransform(m_RenderData.pMonitor->transform)), m_RenderData.pMonitor->vecTransformedSize.x, m_RenderData.pMonitor->vecTransformedSize.y); const auto TOPLEFT = Vector2D(transformedBox.x, transformedBox.y); @@ -1949,14 +2136,14 @@ void CHyprOpenGLImpl::makeRawWindowSnapshot(PHLWINDOW pWindow, CFramebuffer* pFr // we need to "damage" the entire monitor // so that we render the entire window - // this is temporary, doesnt mess with the actual wlr damage + // this is temporary, doesnt mess with the actual damage CRegion fakeDamage{0, 0, (int)PMONITOR->vecTransformedSize.x, (int)PMONITOR->vecTransformedSize.y}; g_pHyprRenderer->makeEGLCurrent(); pFramebuffer->m_pStencilTex = m_RenderData.pCurrentMonData->stencilTex; - pFramebuffer->alloc(PMONITOR->vecPixelSize.x, PMONITOR->vecPixelSize.y, PMONITOR->drmFormat); + pFramebuffer->alloc(PMONITOR->vecPixelSize.x, PMONITOR->vecPixelSize.y, PMONITOR->output->state->state().drmFormat); g_pHyprRenderer->beginRender(PMONITOR, fakeDamage, RENDER_MODE_FULL_FAKE, nullptr, pFramebuffer); @@ -2000,7 +2187,7 @@ void CHyprOpenGLImpl::makeWindowSnapshot(PHLWINDOW pWindow) { // we need to "damage" the entire monitor // so that we render the entire window - // this is temporary, doesnt mess with the actual wlr damage + // this is temporary, doesnt mess with the actual damage CRegion fakeDamage{0, 0, (int)PMONITOR->vecTransformedSize.x, (int)PMONITOR->vecTransformedSize.y}; PHLWINDOWREF ref{pWindow}; @@ -2009,7 +2196,7 @@ void CHyprOpenGLImpl::makeWindowSnapshot(PHLWINDOW pWindow) { const auto PFRAMEBUFFER = &m_mWindowFramebuffers[ref]; - PFRAMEBUFFER->alloc(PMONITOR->vecPixelSize.x, PMONITOR->vecPixelSize.y, PMONITOR->drmFormat); + PFRAMEBUFFER->alloc(PMONITOR->vecPixelSize.x, PMONITOR->vecPixelSize.y, PMONITOR->output->state->state().drmFormat); g_pHyprRenderer->beginRender(PMONITOR, fakeDamage, RENDER_MODE_FULL_FAKE, nullptr, PFRAMEBUFFER); @@ -2049,14 +2236,14 @@ void CHyprOpenGLImpl::makeLayerSnapshot(PHLLS pLayer) { // we need to "damage" the entire monitor // so that we render the entire window - // this is temporary, doesnt mess with the actual wlr damage + // this is temporary, doesnt mess with the actual damage CRegion fakeDamage{0, 0, (int)PMONITOR->vecTransformedSize.x, (int)PMONITOR->vecTransformedSize.y}; g_pHyprRenderer->makeEGLCurrent(); const auto PFRAMEBUFFER = &m_mLayerFramebuffers[pLayer]; - PFRAMEBUFFER->alloc(PMONITOR->vecPixelSize.x, PMONITOR->vecPixelSize.y, PMONITOR->drmFormat); + PFRAMEBUFFER->alloc(PMONITOR->vecPixelSize.x, PMONITOR->vecPixelSize.y, PMONITOR->output->state->state().drmFormat); g_pHyprRenderer->beginRender(PMONITOR, fakeDamage, RENDER_MODE_FULL_FAKE, nullptr, PFRAMEBUFFER); @@ -2178,11 +2365,11 @@ void CHyprOpenGLImpl::renderRoundedShadow(CBox* box, int round, int range, const const auto col = color; float matrix[9]; - projectBox(matrix, newBox, wlTransformToHyprutils(wlr_output_transform_invert(!m_bEndFrame ? WL_OUTPUT_TRANSFORM_NORMAL : m_RenderData.pMonitor->transform)), newBox.rot, - m_RenderData.monitorProjection.data()); // TODO: write own, don't use WLR here + projectBox(matrix, newBox, wlTransformToHyprutils(invertTransform(!m_bEndFrame ? WL_OUTPUT_TRANSFORM_NORMAL : m_RenderData.pMonitor->transform)), newBox.rot, + m_RenderData.monitorProjection.data()); float glMatrix[9]; - wlr_matrix_multiply(glMatrix, m_RenderData.projection, matrix); + matrixMultiply(glMatrix, m_RenderData.projection, matrix); glEnable(GL_BLEND); @@ -2191,7 +2378,7 @@ void CHyprOpenGLImpl::renderRoundedShadow(CBox* box, int round, int range, const #ifndef GLES2 glUniformMatrix3fv(m_RenderData.pCurrentMonData->m_shSHADOW.proj, 1, GL_TRUE, glMatrix); #else - wlr_matrix_transpose(glMatrix, glMatrix); + matrixTranspose(glMatrix, glMatrix); glUniformMatrix3fv(m_RenderData.pCurrentMonData->m_shSHADOW.proj, 1, GL_FALSE, glMatrix); #endif glUniform4f(m_RenderData.pCurrentMonData->m_shSHADOW.color, col.r, col.g, col.b, col.a * a); @@ -2238,7 +2425,8 @@ void CHyprOpenGLImpl::renderRoundedShadow(CBox* box, int round, int range, const void CHyprOpenGLImpl::saveBufferForMirror(CBox* box) { if (!m_RenderData.pCurrentMonData->monitorMirrorFB.isAllocated()) - m_RenderData.pCurrentMonData->monitorMirrorFB.alloc(m_RenderData.pMonitor->vecPixelSize.x, m_RenderData.pMonitor->vecPixelSize.y, m_RenderData.pMonitor->drmFormat); + m_RenderData.pCurrentMonData->monitorMirrorFB.alloc(m_RenderData.pMonitor->vecPixelSize.x, m_RenderData.pMonitor->vecPixelSize.y, + m_RenderData.pMonitor->output->state->state().drmFormat); m_RenderData.pCurrentMonData->monitorMirrorFB.bind(); @@ -2270,11 +2458,11 @@ void CHyprOpenGLImpl::renderMirrored() { return; // replace monitor projection to undo the mirrored monitor's projection - wlr_matrix_identity(monitor->projMatrix.data()); - wlr_matrix_translate(monitor->projMatrix.data(), monitor->vecPixelSize.x / 2.0, monitor->vecPixelSize.y / 2.0); - wlr_matrix_transform(monitor->projMatrix.data(), monitor->transform); - wlr_matrix_transform(monitor->projMatrix.data(), wlr_output_transform_invert(mirrored->transform)); - wlr_matrix_translate(monitor->projMatrix.data(), -monitor->vecTransformedSize.x / 2.0, -monitor->vecTransformedSize.y / 2.0); + matrixIdentity(m_RenderData.monitorProjection.data()); + matrixTranslate(m_RenderData.monitorProjection.data(), monitor->vecPixelSize.x / 2.0, monitor->vecPixelSize.y / 2.0); + matrixTransform(m_RenderData.monitorProjection.data(), wlTransformToHyprutils(monitor->transform)); + matrixTransform(m_RenderData.monitorProjection.data(), wlTransformToHyprutils(invertTransform(mirrored->transform))); + matrixTranslate(m_RenderData.monitorProjection.data(), -monitor->vecTransformedSize.x / 2.0, -monitor->vecTransformedSize.y / 2.0); // clear stuff outside of mirrored area (e.g. when changing to mirrored) clear(CColor(0, 0, 0, 0)); @@ -2282,7 +2470,7 @@ void CHyprOpenGLImpl::renderMirrored() { renderTexture(PFB->m_cTex, &monbox, 1.f, 0, false, false); // reset matrix for further drawing - monitor->updateMatrix(); + m_RenderData.monitorProjection = monitor->projMatrix; } void CHyprOpenGLImpl::renderSplash(cairo_t* const CAIRO, cairo_surface_t* const CAIROSURFACE, double offsetY, const Vector2D& size) { @@ -2338,7 +2526,7 @@ void CHyprOpenGLImpl::createBGTextureForMonitor(CMonitor* pMonitor) { const auto PFB = &m_mMonitorBGFBs[pMonitor]; PFB->release(); - PFB->alloc(pMonitor->vecPixelSize.x, pMonitor->vecPixelSize.y, pMonitor->drmFormat); + PFB->alloc(pMonitor->vecPixelSize.x, pMonitor->vecPixelSize.y, pMonitor->output->state->state().drmFormat); Debug::log(LOG, "Allocated texture for BGTex"); // TODO: use relative paths to the installation @@ -2474,6 +2662,9 @@ void CHyprOpenGLImpl::clearWithTex() { void CHyprOpenGLImpl::destroyMonitorResources(CMonitor* pMonitor) { g_pHyprRenderer->makeEGLCurrent(); + if (!g_pHyprOpenGL) + return; + auto RESIT = g_pHyprOpenGL->m_mMonitorRenderResources.find(pMonitor); if (RESIT != g_pHyprOpenGL->m_mMonitorRenderResources.end()) { RESIT->second.mirrorFB.release(); @@ -2500,8 +2691,8 @@ void CHyprOpenGLImpl::saveMatrix() { } void CHyprOpenGLImpl::setMatrixScaleTranslate(const Vector2D& translate, const float& scale) { - wlr_matrix_scale(m_RenderData.projection, scale, scale); - wlr_matrix_translate(m_RenderData.projection, translate.x, translate.y); + matrixScale(m_RenderData.projection, scale, scale); + matrixTranslate(m_RenderData.projection, translate.x, translate.y); } void CHyprOpenGLImpl::restoreMatrix() { @@ -2533,29 +2724,63 @@ void CHyprOpenGLImpl::setRenderModifEnabled(bool enabled) { } uint32_t CHyprOpenGLImpl::getPreferredReadFormat(CMonitor* pMonitor) { - GLint glf = -1, glt = -1, as = 0; - /*glGetIntegerv(GL_IMPLEMENTATION_COLOR_READ_FORMAT, &glf); - glGetIntegerv(GL_IMPLEMENTATION_COLOR_READ_TYPE, &glt); - glGetIntegerv(GL_ALPHA_BITS, &as);*/ - - if (glf == 0 || glt == 0) { - glf = FormatUtils::drmFormatToGL(pMonitor->drmFormat); - glt = FormatUtils::glFormatToType(glf); - } - - if (const auto FMT = FormatUtils::getPixelFormatFromGL(glf, glt, as > 0); FMT) - return FMT->drmFormat; - - if (m_sExts.EXT_read_format_bgra) - return DRM_FORMAT_XRGB8888; - - return DRM_FORMAT_XBGR8888; + return pMonitor->output->state->state().drmFormat; } std::vector CHyprOpenGLImpl::getDRMFormats() { return drmFormats; } +SP CHyprOpenGLImpl::createEGLSync(int fenceFD) { + std::vector attribs; + int dupFd = -1; + if (fenceFD > 0) { + int dupFd = fcntl(fenceFD, F_DUPFD_CLOEXEC, 0); + if (dupFd < 0) { + Debug::log(ERR, "createEGLSync: dup failed"); + return nullptr; + } + + attribs.push_back(EGL_SYNC_NATIVE_FENCE_FD_ANDROID); + attribs.push_back(dupFd); + attribs.push_back(EGL_NONE); + } + + EGLSyncKHR sync = m_sProc.eglCreateSyncKHR(m_pEglDisplay, EGL_SYNC_NATIVE_FENCE_ANDROID, attribs.data()); + if (sync == EGL_NO_SYNC_KHR) { + Debug::log(ERR, "eglCreateSyncKHR failed"); + if (dupFd >= 0) + close(dupFd); + return nullptr; + } + + auto eglsync = SP(new CEGLSync); + eglsync->sync = sync; + return eglsync; +} + +bool CHyprOpenGLImpl::waitForTimelinePoint(SP timeline, uint64_t point) { + int fd = timeline->exportAsSyncFileFD(point); + if (fd < 0) { + Debug::log(ERR, "waitForTimelinePoint: failed to get a fd from explicit timeline"); + return false; + } + + auto sync = g_pHyprOpenGL->createEGLSync(fd); + close(fd); + if (!sync) { + Debug::log(ERR, "waitForTimelinePoint: failed to get an eglsync from explicit timeline"); + return false; + } + + if (!sync->wait()) { + Debug::log(ERR, "waitForTimelinePoint: failed to wait on an eglsync from explicit timeline"); + return false; + } + + return true; +} + void SRenderModifData::applyToBox(CBox& box) { if (!enabled) return; @@ -2616,3 +2841,35 @@ float SRenderModifData::combinedScale() { } return scale; } + +CEGLSync::~CEGLSync() { + if (sync == EGL_NO_SYNC_KHR) + return; + + if (g_pHyprOpenGL->m_sProc.eglDestroySyncKHR(g_pHyprOpenGL->m_pEglDisplay, sync) != EGL_TRUE) + Debug::log(ERR, "eglDestroySyncKHR failed"); +} + +int CEGLSync::dupFenceFD() { + if (sync == EGL_NO_SYNC_KHR) + return -1; + + int fd = g_pHyprOpenGL->m_sProc.eglDupNativeFenceFDANDROID(g_pHyprOpenGL->m_pEglDisplay, sync); + if (fd == EGL_NO_NATIVE_FENCE_FD_ANDROID) { + Debug::log(ERR, "eglDupNativeFenceFDANDROID failed"); + return -1; + } + + return fd; +} + +bool CEGLSync::wait() { + if (sync == EGL_NO_SYNC_KHR) + return false; + + if (g_pHyprOpenGL->m_sProc.eglWaitSyncKHR(g_pHyprOpenGL->m_pEglDisplay, sync, 0) != EGL_TRUE) { + Debug::log(ERR, "eglWaitSyncKHR failed"); + return false; + } + return true; +} diff --git a/src/render/OpenGL.hpp b/src/render/OpenGL.hpp index 814b80fe..712b87f3 100644 --- a/src/render/OpenGL.hpp +++ b/src/render/OpenGL.hpp @@ -6,6 +6,8 @@ #include "../helpers/Timer.hpp" #include "../helpers/math/Math.hpp" #include "../helpers/Format.hpp" +#include "../helpers/sync/SyncTimeline.hpp" +#include #include #include #include @@ -18,10 +20,14 @@ #include "Transformer.hpp" #include "Renderbuffer.hpp" +#include +#include #include +#include #include "../debug/TracyDefines.hpp" +struct gbm_device; class CHyprRenderer; inline const float fullVerts[] = { @@ -119,6 +125,21 @@ struct SCurrentRenderData { float discardOpacity = 0.f; }; +class CEGLSync { + public: + ~CEGLSync(); + + EGLSyncKHR sync = nullptr; + + int dupFenceFD(); + bool wait(); + + private: + CEGLSync() = default; + + friend class CHyprOpenGLImpl; +}; + class CGradientValueData; class CHyprOpenGLImpl { @@ -126,14 +147,15 @@ class CHyprOpenGLImpl { CHyprOpenGLImpl(); void begin(CMonitor*, const CRegion& damage, CFramebuffer* fb = nullptr, std::optional finalDamage = {}); - void beginSimple(CMonitor*, const CRegion& damage, CRenderbuffer* rb = nullptr, CFramebuffer* fb = nullptr); + void beginSimple(CMonitor*, const CRegion& damage, SP rb = nullptr, CFramebuffer* fb = nullptr); void end(); void renderRect(CBox*, const CColor&, int round = 0); void renderRectWithBlur(CBox*, const CColor&, int round = 0, float blurA = 1.f, bool xray = false); void renderRectWithDamage(CBox*, const CColor&, CRegion* damage, int round = 0); void renderTexture(SP, CBox*, float a, int round = 0, bool discardActive = false, bool allowCustomUV = false); - void renderTextureWithDamage(SP, CBox*, CRegion* damage, float a, int round = 0, bool discardActive = false, bool allowCustomUV = false); + void renderTextureWithDamage(SP, CBox*, CRegion* damage, float a, int round = 0, bool discardActive = false, bool allowCustomUV = false, + SP waitTimeline = nullptr, uint64_t waitPoint = 0); void renderTextureWithBlur(SP, CBox*, float a, SP pSurface, int round = 0, bool blockBlurOptimization = false, float blurA = 1.f); void renderRoundedShadow(CBox*, int round, int range, const CColor& color, float a = 1.0); void renderBorder(CBox*, const CGradientValueData&, int round, int borderSize, float a = 1.0, int outerRound = -1 /* use round */); @@ -182,12 +204,19 @@ class CHyprOpenGLImpl { uint32_t getPreferredReadFormat(CMonitor* pMonitor); std::vector getDRMFormats(); - EGLImageKHR createEGLImage(const SDMABUFAttrs& attrs); + EGLImageKHR createEGLImage(const Aquamarine::SDMABUFAttrs& attrs); + SP createEGLSync(int fenceFD); + bool waitForTimelinePoint(SP timeline, uint64_t point); SCurrentRenderData m_RenderData; GLint m_iCurrentOutputFb = 0; + int m_iGBMFD = -1; + gbm_device* m_pGbmDevice = nullptr; + EGLContext m_pEglContext = nullptr; + EGLDisplay m_pEglDisplay = nullptr; + bool m_bReloadScreenShader = true; // at launch it can be set PHLWINDOWREF m_pCurrentWindow; // hack to get the current rendered window @@ -205,12 +234,24 @@ class CHyprOpenGLImpl { PFNEGLDESTROYIMAGEKHRPROC eglDestroyImageKHR = nullptr; PFNEGLQUERYDMABUFFORMATSEXTPROC eglQueryDmaBufFormatsEXT = nullptr; PFNEGLQUERYDMABUFMODIFIERSEXTPROC eglQueryDmaBufModifiersEXT = nullptr; + PFNEGLGETPLATFORMDISPLAYEXTPROC eglGetPlatformDisplayEXT = nullptr; + PFNEGLDEBUGMESSAGECONTROLKHRPROC eglDebugMessageControlKHR = nullptr; + PFNEGLQUERYDEVICESEXTPROC eglQueryDevicesEXT = nullptr; + PFNEGLQUERYDEVICESTRINGEXTPROC eglQueryDeviceStringEXT = nullptr; + PFNEGLQUERYDISPLAYATTRIBEXTPROC eglQueryDisplayAttribEXT = nullptr; + PFNEGLCREATESYNCKHRPROC eglCreateSyncKHR = nullptr; + PFNEGLDESTROYSYNCKHRPROC eglDestroySyncKHR = nullptr; + PFNEGLDUPNATIVEFENCEFDANDROIDPROC eglDupNativeFenceFDANDROID = nullptr; + PFNEGLWAITSYNCKHRPROC eglWaitSyncKHR = nullptr; } m_sProc; struct { bool EXT_read_format_bgra = false; bool EXT_image_dma_buf_import = false; bool EXT_image_dma_buf_import_modifiers = false; + bool KHR_display_reference = false; + bool IMG_context_priority = false; + bool EXT_create_context_robustness = false; } m_sExts; private: @@ -220,7 +261,7 @@ class CHyprOpenGLImpl { std::vector drmFormats; bool m_bHasModifiers = false; - int m_iDRMFD; + int m_iDRMFD = -1; std::string m_szExtensions; bool m_bFakeFrame = false; @@ -238,6 +279,7 @@ class CHyprOpenGLImpl { void createBGTextureForMonitor(CMonitor*); void initShaders(); void initDRMFormats(); + void initEGL(bool gbm); // std::optional> getModsForFormat(EGLint format); @@ -246,7 +288,7 @@ class CHyprOpenGLImpl { CFramebuffer* blurMainFramebufferWithDamage(float a, CRegion* damage); void renderTextureInternalWithDamage(SP, CBox* pBox, float a, CRegion* damage, int round = 0, bool discardOpaque = false, bool noAA = false, - bool allowCustomUV = false, bool allowDim = false); + bool allowCustomUV = false, bool allowDim = false, SP = nullptr, uint64_t waitPoint = 0); void renderTexturePrimitive(SP tex, CBox* pBox); void renderSplash(cairo_t* const, cairo_surface_t* const, double offset, const Vector2D& size); diff --git a/src/render/Renderbuffer.cpp b/src/render/Renderbuffer.cpp index 3f591d13..58ed88d6 100644 --- a/src/render/Renderbuffer.cpp +++ b/src/render/Renderbuffer.cpp @@ -2,6 +2,8 @@ #include "OpenGL.hpp" #include "../Compositor.hpp" #include "../protocols/types/Buffer.hpp" +#include +#include #include @@ -15,58 +17,17 @@ CRenderbuffer::~CRenderbuffer() { m_sFramebuffer.release(); glDeleteRenderbuffers(1, &m_iRBO); - g_pHyprOpenGL->m_sProc.eglDestroyImageKHR(wlr_egl_get_display(g_pCompositor->m_sWLREGL), m_iImage); + g_pHyprOpenGL->m_sProc.eglDestroyImageKHR(g_pHyprOpenGL->m_pEglDisplay, m_iImage); } -CRenderbuffer::CRenderbuffer(wlr_buffer* buffer, uint32_t format) : m_pWlrBuffer(buffer), m_uDrmFormat(format) { - - // EVIL, but we can't include a hidden header because nixos is fucking special - static EGLImageKHR (*PWLREGLCREATEIMAGEFROMDMABUF)(wlr_egl*, wlr_dmabuf_attributes*, bool*); - static bool symbolFound = false; - if (!symbolFound) { - PWLREGLCREATEIMAGEFROMDMABUF = reinterpret_cast(dlsym(RTLD_DEFAULT, "wlr_egl_create_image_from_dmabuf")); - - symbolFound = true; - - RASSERT(PWLREGLCREATEIMAGEFROMDMABUF, "wlr_egl_create_image_from_dmabuf was not found in wlroots!"); - - Debug::log(LOG, "CRenderbuffer: wlr_egl_create_image_from_dmabuf found at {:x}", (uintptr_t)PWLREGLCREATEIMAGEFROMDMABUF); - } - // end evil hack - - struct wlr_dmabuf_attributes dmabuf = {0}; - if (!wlr_buffer_get_dmabuf(buffer, &dmabuf)) - throw std::runtime_error("wlr_buffer_get_dmabuf failed"); - - bool externalOnly; - m_iImage = PWLREGLCREATEIMAGEFROMDMABUF(g_pCompositor->m_sWLREGL, &dmabuf, &externalOnly); - if (m_iImage == EGL_NO_IMAGE_KHR) - throw std::runtime_error("wlr_egl_create_image_from_dmabuf failed"); - - glGenRenderbuffers(1, &m_iRBO); - glBindRenderbuffer(GL_RENDERBUFFER, m_iRBO); - g_pHyprOpenGL->m_sProc.glEGLImageTargetRenderbufferStorageOES(GL_RENDERBUFFER, (GLeglImageOES)m_iImage); - glBindRenderbuffer(GL_RENDERBUFFER, 0); - - glGenFramebuffers(1, &m_sFramebuffer.m_iFb); - m_sFramebuffer.m_vSize = {buffer->width, buffer->height}; - m_sFramebuffer.bind(); - glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, m_iRBO); - - if (glCheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE) - throw std::runtime_error("rbo: glCheckFramebufferStatus failed"); - - glBindFramebuffer(GL_FRAMEBUFFER, 0); - - hyprListener_destroyBuffer.initCallback(&buffer->events.destroy, [this](void* owner, void* data) { g_pHyprRenderer->onRenderbufferDestroy(this); }, this, "CRenderbuffer"); -} - -CRenderbuffer::CRenderbuffer(SP buffer, uint32_t format) : m_pHLBuffer(buffer), m_uDrmFormat(format) { +CRenderbuffer::CRenderbuffer(SP buffer, uint32_t format) : m_pHLBuffer(buffer), m_uDrmFormat(format) { auto dma = buffer->dmabuf(); m_iImage = g_pHyprOpenGL->createEGLImage(dma); - if (m_iImage == EGL_NO_IMAGE_KHR) - throw std::runtime_error("createEGLImage failed"); + if (m_iImage == EGL_NO_IMAGE_KHR) { + Debug::log(ERR, "rb: createEGLImage failed"); + return; + } glGenRenderbuffers(1, &m_iRBO); glBindRenderbuffer(GL_RENDERBUFFER, m_iRBO); @@ -78,10 +39,20 @@ CRenderbuffer::CRenderbuffer(SP buffer, uint32_t format) : m_pHLBuffe m_sFramebuffer.bind(); glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, m_iRBO); - if (glCheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE) - throw std::runtime_error("rbo: glCheckFramebufferStatus failed"); + if (glCheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE) { + Debug::log(ERR, "rbo: glCheckFramebufferStatus failed"); + return; + } glBindFramebuffer(GL_FRAMEBUFFER, 0); + + listeners.destroyBuffer = buffer->events.destroy.registerListener([this](std::any d) { g_pHyprRenderer->onRenderbufferDestroy(this); }); + + m_bGood = true; +} + +bool CRenderbuffer::good() { + return m_bGood; } void CRenderbuffer::bind() { diff --git a/src/render/Renderbuffer.hpp b/src/render/Renderbuffer.hpp index ed7050c5..e6bfa909 100644 --- a/src/render/Renderbuffer.hpp +++ b/src/render/Renderbuffer.hpp @@ -1,30 +1,35 @@ #pragma once +#include "../helpers/signal/Signal.hpp" +#include "../helpers/memory/Memory.hpp" +#include "../helpers/WLListener.hpp" #include "Framebuffer.hpp" +#include class CMonitor; -class IWLBuffer; class CRenderbuffer { public: - CRenderbuffer(wlr_buffer* buffer, uint32_t format); - CRenderbuffer(SP buffer, uint32_t format); + CRenderbuffer(SP buffer, uint32_t format); ~CRenderbuffer(); - void bind(); - void bindFB(); - void unbind(); - CFramebuffer* getFB(); - uint32_t getFormat(); + bool good(); + void bind(); + void bindFB(); + void unbind(); + CFramebuffer* getFB(); + uint32_t getFormat(); - wlr_buffer* m_pWlrBuffer = nullptr; - WP m_pHLBuffer = {}; - - DYNLISTENER(destroyBuffer); + WP m_pHLBuffer; private: - EGLImageKHR m_iImage = 0; + void* m_iImage = nullptr; GLuint m_iRBO = 0; CFramebuffer m_sFramebuffer; uint32_t m_uDrmFormat = 0; + bool m_bGood = false; + + struct { + CHyprSignalListener destroyBuffer; + } listeners; }; \ No newline at end of file diff --git a/src/render/Renderer.cpp b/src/render/Renderer.cpp index a7f3c941..82dfc887 100644 --- a/src/render/Renderer.cpp +++ b/src/render/Renderer.cpp @@ -2,6 +2,8 @@ #include "../Compositor.hpp" #include "../helpers/math/Math.hpp" #include +#include +#include #include "../config/ConfigValue.hpp" #include "../managers/CursorManager.hpp" #include "../managers/PointerManager.hpp" @@ -13,6 +15,10 @@ #include "../protocols/PresentationTime.hpp" #include "../protocols/core/DataDevice.hpp" #include "../protocols/core/Compositor.hpp" +#include "../protocols/DRMSyncobj.hpp" +#include "../protocols/LinuxDMABUF.hpp" +#include "../helpers/sync/SyncTimeline.hpp" +#include "debug/Log.hpp" extern "C" { #include @@ -25,11 +31,11 @@ static int cursorTicker(void* data) { } CHyprRenderer::CHyprRenderer() { - if (g_pCompositor->m_sWLRSession) { - wlr_device* dev; - wl_list_for_each(dev, &g_pCompositor->m_sWLRSession->devices, link) { - const auto DRMV = drmGetVersion(dev->fd); - + if (g_pCompositor->m_pAqBackend->hasSession()) { + for (auto& dev : g_pCompositor->m_pAqBackend->session->sessionDevices) { + const auto DRMV = drmGetVersion(dev->fd); + if (!DRMV) + continue; std::string name = std::string{DRMV->name, DRMV->name_len}; std::transform(name.begin(), name.end(), name.begin(), tolower); @@ -42,7 +48,7 @@ CHyprRenderer::CHyprRenderer() { drmFreeVersion(DRMV); } } else { - Debug::log(LOG, "m_sWLRSession is null, omitting full DRM node checks"); + Debug::log(LOG, "Aq backend has no session, omitting full DRM node checks"); const auto DRMV = drmGetVersion(g_pCompositor->m_iDRMFD); @@ -108,6 +114,14 @@ static void renderSurface(SP surface, int x, int y, void* da if (!TEXTURE->m_iTexID) return; + // explicit sync: wait for the timeline, if any + if (surface->syncobj && surface->syncobj->acquireTimeline) { + if (!g_pHyprOpenGL->waitForTimelinePoint(surface->syncobj->acquireTimeline->timeline, surface->syncobj->acquirePoint)) { + Debug::log(ERR, "Renderer: failed to wait for explicit timeline"); + return; + } + } + TRACY_GPU_ZONE("RenderSurface"); double outputX = -RDATA->pMonitor->vecPosition.x, outputY = -RDATA->pMonitor->vecPosition.y; @@ -167,12 +181,10 @@ static void renderSurface(SP surface, int x, int y, void* da if (windowBox.width <= 1 || windowBox.height <= 1) { if (!g_pHyprRenderer->m_bBlockSurfaceFeedback) { - surface->frame(RDATA->when); - auto FEEDBACK = makeShared(surface); - FEEDBACK->attachMonitor(RDATA->pMonitor); - FEEDBACK->discarded(); - PROTO::presentation->queueData(FEEDBACK); + Debug::log(TRACE, "presentFeedback for invisible surface"); + surface->presentFeedback(RDATA->when, RDATA->pMonitor); } + return; // invisible } @@ -225,11 +237,8 @@ static void renderSurface(SP surface, int x, int y, void* da } if (!g_pHyprRenderer->m_bBlockSurfaceFeedback) { - surface->frame(RDATA->when); - auto FEEDBACK = makeShared(surface); - FEEDBACK->attachMonitor(RDATA->pMonitor); - FEEDBACK->presented(); - PROTO::presentation->queueData(FEEDBACK); + Debug::log(TRACE, "presentFeedback for visible surface"); + surface->presentFeedback(RDATA->when, RDATA->pMonitor); } g_pHyprOpenGL->blend(true); @@ -1079,53 +1088,6 @@ void CHyprRenderer::calculateUVForSurface(PHLWINDOW pWindow, SPmirrors.empty() || pMonitor->isMirror() || m_bDirectScanoutBlocked) - // return false; // do not DS if this monitor is being mirrored. Will break the functionality. - - // if (!wlr_output_is_direct_scanout_allowed(pMonitor->output)) - // return false; - - // const auto PCANDIDATE = pMonitor->solitaryClient.lock(); - - // if (!PCANDIDATE) - // return false; - - // const auto PSURFACE = g_pXWaylandManager->getWindowSurface(PCANDIDATE); - - // if (!PSURFACE || PSURFACE->current.scale != pMonitor->output->scale || PSURFACE->current.transform != pMonitor->output->transform) - // return false; - - // // finally, we should be GTG. - // wlr_output_state_set_buffer(pMonitor->state.wlr(), &PSURFACE->buffer->base); - - // if (!wlr_output_test_state(pMonitor->output, pMonitor->state.wlr())) - // return false; - - // timespec now; - // clock_gettime(CLOCK_MONOTONIC, &now); - // PSURFACE->frame(&now); - // auto FEEDBACK = makeShared(PSURFACE); - // FEEDBACK->attachMonitor(pMonitor); - // FEEDBACK->presented(); - // FEEDBACK->setPresentationType(true); - // PROTO::presentation->queueData(FEEDBACK); - - // if (pMonitor->state.commit()) { - // if (m_pLastScanout.expired()) { - // m_pLastScanout = PCANDIDATE; - // Debug::log(LOG, "Entered a direct scanout to {:x}: \"{}\"", (uintptr_t)PCANDIDATE.get(), PCANDIDATE->m_szTitle); - // } - // } else { - // m_pLastScanout.reset(); - // return false; - // } - - // return true; -} - void CHyprRenderer::renderMonitor(CMonitor* pMonitor) { static std::chrono::high_resolution_clock::time_point renderStart = std::chrono::high_resolution_clock::now(); static std::chrono::high_resolution_clock::time_point renderStartOverlay = std::chrono::high_resolution_clock::now(); @@ -1177,7 +1139,7 @@ void CHyprRenderer::renderMonitor(CMonitor* pMonitor) { pMonitor->framesToSkip -= 1; if (!pMonitor->noFrameSchedule) - g_pCompositor->scheduleFrameForMonitor(pMonitor); + g_pCompositor->scheduleFrameForMonitor(pMonitor, Aquamarine::IOutput::AQ_SCHEDULE_RENDER_MONITOR); else Debug::log(LOG, "NoFrameSchedule hit for {}.", pMonitor->szName); @@ -1205,6 +1167,9 @@ void CHyprRenderer::renderMonitor(CMonitor* pMonitor) { g_pLayoutManager->getCurrentLayout()->recalculateMonitor(pMonitor->ID); } + if (!pMonitor->output->needsFrame && pMonitor->forceFullFrames == 0) + return; + // tearing and DS first bool shouldTear = false; if (pMonitor->tearingState.nextRenderTorn) { @@ -1230,11 +1195,11 @@ void CHyprRenderer::renderMonitor(CMonitor* pMonitor) { } if (!*PNODIRECTSCANOUT && !shouldTear) { - if (attemptDirectScanout(pMonitor)) { + if (pMonitor->attemptDirectScanout()) { return; - } else if (!m_pLastScanout.expired()) { + } else if (!pMonitor->lastScanout.expired()) { Debug::log(LOG, "Left a direct scanout."); - m_pLastScanout.reset(); + pMonitor->lastScanout.reset(); } } @@ -1249,7 +1214,7 @@ void CHyprRenderer::renderMonitor(CMonitor* pMonitor) { clock_gettime(CLOCK_MONOTONIC, &now); // check the damage - bool hasChanged = pMonitor->output->needs_frame || pMonitor->damage.hasChanged(); + bool hasChanged = pMonitor->output->needsFrame || pMonitor->damage.hasChanged(); if (!hasChanged && *PDAMAGETRACKINGMODE != DAMAGE_TRACKING_NONE && pMonitor->forceFullFrames == 0 && damageBlinkCleanup == 0) return; @@ -1295,7 +1260,6 @@ void CHyprRenderer::renderMonitor(CMonitor* pMonitor) { CRegion damage, finalDamage; if (!beginRender(pMonitor, damage, RENDER_MODE_NORMAL)) { Debug::log(ERR, "renderer: couldn't beginRender()!"); - pMonitor->state.clear(); return; } @@ -1316,11 +1280,11 @@ void CHyprRenderer::renderMonitor(CMonitor* pMonitor) { *PBLURPASSES > 10 ? pow(2, 15) : std::clamp(*PBLURSIZE, (int64_t)1, (int64_t)40) * pow(2, *PBLURPASSES); // is this 2^pass? I don't know but it works... I think. // now, prep the damage, get the extended damage region - wlr_region_expand(damage.pixman(), damage.pixman(), BLURRADIUS); // expand for proper blurring + damage.expand(BLURRADIUS); // expand for proper blurring finalDamage = damage; - wlr_region_expand(damage.pixman(), damage.pixman(), BLURRADIUS); // expand for proper blurring 2 + damage.expand(BLURRADIUS); // expand for proper blurring } else finalDamage = damage; } @@ -1396,10 +1360,10 @@ void CHyprRenderer::renderMonitor(CMonitor* pMonitor) { TRACY_GPU_COLLECT; if (!pMonitor->mirrors.empty()) { - CRegion frameDamage{}; + CRegion frameDamage{finalDamage}; - const auto TRANSFORM = wlr_output_transform_invert(pMonitor->output->transform); - wlr_region_transform(frameDamage.pixman(), finalDamage.pixman(), TRANSFORM, (int)pMonitor->vecTransformedSize.x, (int)pMonitor->vecTransformedSize.y); + const auto TRANSFORM = invertTransform(pMonitor->transform); + frameDamage.transform(wlTransformToHyprutils(TRANSFORM), pMonitor->vecTransformedSize.x, pMonitor->vecTransformedSize.y); if (*PDAMAGETRACKINGMODE == DAMAGE_TRACKING_NONE || *PDAMAGETRACKINGMODE == DAMAGE_TRACKING_MONITOR) frameDamage.add(0, 0, (int)pMonitor->vecTransformedSize.x, (int)pMonitor->vecTransformedSize.y); @@ -1414,18 +1378,16 @@ void CHyprRenderer::renderMonitor(CMonitor* pMonitor) { EMIT_HOOK_EVENT("render", RENDER_POST); - pMonitor->state.wlr()->tearing_page_flip = shouldTear; + pMonitor->output->state->setPresentationMode(shouldTear ? Aquamarine::eOutputPresentationMode::AQ_OUTPUT_PRESENTATION_IMMEDIATE : + Aquamarine::eOutputPresentationMode::AQ_OUTPUT_PRESENTATION_VSYNC); - if (!pMonitor->state.commit()) { - pMonitor->damage.damageEntire(); - return; - } + commitPendingAndDoExplicitSync(pMonitor); if (shouldTear) pMonitor->tearingState.busy = true; if (*PDAMAGEBLINK || *PVFR == 0 || pMonitor->pendingFrame) - g_pCompositor->scheduleFrameForMonitor(pMonitor); + g_pCompositor->scheduleFrameForMonitor(pMonitor, Aquamarine::IOutput::AQ_SCHEDULE_RENDER_MONITOR); pMonitor->pendingFrame = false; @@ -1442,6 +1404,63 @@ void CHyprRenderer::renderMonitor(CMonitor* pMonitor) { } } +bool CHyprRenderer::commitPendingAndDoExplicitSync(CMonitor* pMonitor) { + static auto PENABLEEXPLICIT = CConfigValue("experimental:explicit_sync"); + + // apply timelines for explicit sync + pMonitor->output->state->resetExplicitFences(); + + bool anyExplicit = !explicitPresented.empty(); + if (anyExplicit) { + Debug::log(TRACE, "Explicit sync presented begin"); + auto inFence = pMonitor->inTimeline->exportAsSyncFileFD(pMonitor->lastWaitPoint); + if (inFence < 0) + Debug::log(ERR, "Export lastWaitPoint {} as sync explicitInFence failed", pMonitor->lastWaitPoint); + + pMonitor->output->state->setExplicitInFence(inFence); + + for (auto& e : explicitPresented) { + Debug::log(TRACE, "Explicit sync presented releasePoint {}", e->syncobj && e->syncobj->releaseTimeline ? e->syncobj->releasePoint : -1); + if (!e->syncobj || !e->syncobj->releaseTimeline) + continue; + e->syncobj->releaseTimeline->timeline->transfer(pMonitor->outTimeline, pMonitor->commitSeq, e->syncobj->releasePoint); + } + + explicitPresented.clear(); + auto outFence = pMonitor->outTimeline->exportAsSyncFileFD(pMonitor->commitSeq); + if (outFence < 0) + Debug::log(ERR, "Export commitSeq {} as sync explicitOutFence failed", pMonitor->commitSeq); + + pMonitor->output->state->setExplicitOutFence(outFence); + Debug::log(TRACE, "Explicit sync presented end"); + } + + pMonitor->lastWaitPoint = 0; + + bool ok = pMonitor->state.commit(); + if (!ok) { + Debug::log(TRACE, "Monitor state commit failed"); + // rollback the buffer to avoid writing to the front buffer that is being + // displayed + pMonitor->output->swapchain->rollback(); + pMonitor->damage.damageEntire(); + } + + if (!*PENABLEEXPLICIT) + return ok; + + if (pMonitor->output->state->state().explicitInFence >= 0) + close(pMonitor->output->state->state().explicitInFence); + + if (pMonitor->output->state->state().explicitOutFence >= 0) { + if (ok) + pMonitor->outTimeline->importFromSyncFileFD(pMonitor->commitSeq, pMonitor->output->state->state().explicitOutFence); + close(pMonitor->output->state->state().explicitOutFence); + } + + return ok; +} + void CHyprRenderer::renderWorkspace(CMonitor* pMonitor, PHLWORKSPACE pWorkspace, timespec* now, const CBox& geometry) { Vector2D translate = {geometry.x, geometry.y}; float scale = (float)geometry.width / pMonitor->vecPixelSize.x; @@ -1480,33 +1499,11 @@ void CHyprRenderer::sendFrameEventsToWorkspace(CMonitor* pMonitor, PHLWORKSPACE } } -void CHyprRenderer::setWindowScanoutMode(PHLWINDOW pWindow) { - // FIXME: fix when moved to new impl - // if (!g_pCompositor->m_sWLRLinuxDMABuf || g_pSessionLockManager->isSessionLocked()) - // return; +void CHyprRenderer::setSurfaceScanoutMode(SP surface, SP monitor) { + if (!PROTO::linuxDma) + return; - // if (!pWindow->m_bIsFullscreen) { - // wlr_linux_dmabuf_v1_set_surface_feedback(g_pCompositor->m_sWLRLinuxDMABuf, pWindow->m_pWLSurface->resource(), nullptr); - // Debug::log(LOG, "Scanout mode OFF set for {}", pWindow); - // return; - // } - - // const auto PMONITOR = g_pCompositor->getMonitorFromID(pWindow->m_iMonitorID); - - // const wlr_linux_dmabuf_feedback_v1_init_options INIT_OPTIONS = { - // .main_renderer = g_pCompositor->m_sWLRRenderer, - // .scanout_primary_output = PMONITOR->output, - // }; - - // wlr_linux_dmabuf_feedback_v1 feedback = {0}; - - // if (!wlr_linux_dmabuf_feedback_v1_init_with_options(&feedback, &INIT_OPTIONS)) - // return; - - // wlr_linux_dmabuf_v1_set_surface_feedback(g_pCompositor->m_sWLRLinuxDMABuf, pWindow->m_pWLSurface->resource(), &feedback); - // wlr_linux_dmabuf_feedback_v1_finish(&feedback); - - // Debug::log(LOG, "Scanout mode ON set for {}", pWindow); + PROTO::linuxDma->updateScanoutTranche(surface, monitor); } // taken from Sway. @@ -1572,7 +1569,7 @@ void CHyprRenderer::arrangeLayerArray(CMonitor* pMonitor, const std::vectorvecPosition.x, pMonitor->vecPosition.y, pMonitor->vecSize.x, pMonitor->vecSize.y}; for (auto& ls : layerSurfaces) { - if (ls->fadingOut || ls->readyToDelete || !ls->layerSurface || ls->noProcess) + if (!ls || ls->fadingOut || ls->readyToDelete || !ls->layerSurface || ls->noProcess) continue; const auto PLAYER = ls->layerSurface; @@ -1708,7 +1705,7 @@ void CHyprRenderer::damageSurface(SP pSurface, double x, dou damageBox.scale(scale); // schedule frame events - g_pCompositor->scheduleFrameForMonitor(g_pCompositor->getMonitorFromVector(Vector2D(x, y))); + g_pCompositor->scheduleFrameForMonitor(g_pCompositor->getMonitorFromVector(Vector2D(x, y)), Aquamarine::IOutput::AQ_SCHEDULE_DAMAGE); if (damageBox.empty()) return; @@ -1820,13 +1817,13 @@ void CHyprRenderer::damageMirrorsWith(CMonitor* pMonitor, const CRegion& pRegion monbox.x = (monitor->vecTransformedSize.x - monbox.w) / 2; monbox.y = (monitor->vecTransformedSize.y - monbox.h) / 2; - wlr_region_scale(transformed.pixman(), transformed.pixman(), scale); + transformed.scale(scale); transformed.transform(wlTransformToHyprutils(mirrored->transform), mirrored->vecPixelSize.x * scale, mirrored->vecPixelSize.y * scale); transformed.translate(Vector2D(monbox.x, monbox.y)); mirror->addDamage(&transformed); - g_pCompositor->scheduleFrameForMonitor(mirror); + g_pCompositor->scheduleFrameForMonitor(mirror, Aquamarine::IOutput::AQ_SCHEDULE_DAMAGE); } } @@ -1869,7 +1866,7 @@ bool CHyprRenderer::applyMonitorRule(CMonitor* pMonitor, SMonitorRule* pMonitorR } // don't touch VR headsets - if (pMonitor->output->non_desktop) + if (pMonitor->output->nonDesktop) return true; if (!pMonitor->m_bEnabled) { @@ -1900,7 +1897,10 @@ bool CHyprRenderer::applyMonitorRule(CMonitor* pMonitor, SMonitorRule* pMonitorR // Needed in case we are switching from a custom modeline to a standard mode pMonitor->customDrmMode = {}; pMonitor->currentMode = nullptr; - bool autoScale = false; + + pMonitor->output->state->setFormat(DRM_FORMAT_XRGB8888); + + bool autoScale = false; if (RULE->scale > 0.1) { pMonitor->scale = RULE->scale; @@ -1910,38 +1910,35 @@ bool CHyprRenderer::applyMonitorRule(CMonitor* pMonitor, SMonitorRule* pMonitorR pMonitor->scale = DEFAULTSCALE; } - wlr_output_state_set_scale(pMonitor->state.wlr(), pMonitor->scale); - pMonitor->setScale = pMonitor->scale; - - wlr_output_state_set_transform(pMonitor->state.wlr(), RULE->transform); + pMonitor->setScale = pMonitor->scale; pMonitor->transform = RULE->transform; - const auto WLRREFRESHRATE = (wlr_backend_is_wl(pMonitor->output->backend) || wlr_backend_is_x11(pMonitor->output->backend)) ? 0 : RULE->refreshRate * 1000; + const auto WLRREFRESHRATE = pMonitor->output->getBackend()->type() == Aquamarine::eBackendType::AQ_BACKEND_DRM ? RULE->refreshRate * 1000 : 0; // loop over modes and choose an appropriate one. if (RULE->resolution != Vector2D() && RULE->resolution != Vector2D(-1, -1) && RULE->resolution != Vector2D(-1, -2)) { - if (!wl_list_empty(&pMonitor->output->modes) && RULE->drmMode.type != DRM_MODE_TYPE_USERDEF) { - wlr_output_mode* mode; - bool found = false; + if (!pMonitor->output->modes.empty() && RULE->drmMode.type != DRM_MODE_TYPE_USERDEF) { + bool found = false; - wl_list_for_each(mode, &pMonitor->output->modes, link) { + for (auto& mode : pMonitor->output->modes) { // if delta of refresh rate, w and h chosen and mode is < 1 we accept it - if (DELTALESSTHAN(mode->width, RULE->resolution.x, 1) && DELTALESSTHAN(mode->height, RULE->resolution.y, 1) && - DELTALESSTHAN(mode->refresh / 1000.f, RULE->refreshRate, 1)) { - wlr_output_state_set_mode(pMonitor->state.wlr(), mode); + if (DELTALESSTHAN(mode->pixelSize.x, RULE->resolution.x, 1) && DELTALESSTHAN(mode->pixelSize.y, RULE->resolution.y, 1) && + DELTALESSTHAN(mode->refreshRate / 1000.f, RULE->refreshRate, 1)) { + pMonitor->output->state->setMode(mode); - if (!wlr_output_test_state(pMonitor->output, pMonitor->state.wlr())) { - Debug::log(LOG, "Monitor {}: REJECTED available mode: {}x{}@{:2f}!", pMonitor->output->name, mode->width, mode->height, mode->refresh / 1000.f); + if (!pMonitor->state.test()) { + Debug::log(LOG, "Monitor {}: REJECTED available mode: {}x{}@{:2f}!", pMonitor->output->name, mode->pixelSize.x, mode->pixelSize.y, + mode->refreshRate / 1000.f); continue; } Debug::log(LOG, "Monitor {}: requested {:X0}@{:2f}, found available mode: {}x{}@{}mHz, applying.", pMonitor->output->name, RULE->resolution, - (float)RULE->refreshRate, mode->width, mode->height, mode->refresh); + (float)RULE->refreshRate, mode->pixelSize.x, mode->pixelSize.y, mode->refreshRate); found = true; - pMonitor->refreshRate = mode->refresh / 1000.f; - pMonitor->vecSize = Vector2D(mode->width, mode->height); + pMonitor->refreshRate = mode->refreshRate / 1000.f; + pMonitor->vecSize = mode->pixelSize; pMonitor->currentMode = mode; break; @@ -1949,14 +1946,14 @@ bool CHyprRenderer::applyMonitorRule(CMonitor* pMonitor, SMonitorRule* pMonitorR } if (!found) { - wlr_output_state_set_custom_mode(pMonitor->state.wlr(), (int)RULE->resolution.x, (int)RULE->resolution.y, WLRREFRESHRATE); + pMonitor->output->state->setCustomMode(makeShared(Aquamarine::SOutputMode{.pixelSize = RULE->resolution, .refreshRate = WLRREFRESHRATE})); pMonitor->vecSize = RULE->resolution; pMonitor->refreshRate = RULE->refreshRate; - if (!wlr_output_test_state(pMonitor->output, pMonitor->state.wlr())) { + if (!pMonitor->state.test()) { Debug::log(ERR, "Custom resolution FAILED, falling back to preferred"); - const auto PREFERREDMODE = wlr_output_preferred_mode(pMonitor->output); + const auto PREFERREDMODE = pMonitor->output->preferredMode(); if (!PREFERREDMODE) { Debug::log(ERR, "Monitor {} has NO PREFERRED MODE, and an INVALID one was requested: {:X0}@{:2f}", pMonitor->ID, RULE->resolution, @@ -1965,13 +1962,13 @@ bool CHyprRenderer::applyMonitorRule(CMonitor* pMonitor, SMonitorRule* pMonitorR } // Preferred is valid - wlr_output_state_set_mode(pMonitor->state.wlr(), PREFERREDMODE); + pMonitor->output->state->setMode(PREFERREDMODE); Debug::log(ERR, "Monitor {} got an invalid requested mode: {:X0}@{:2f}, using the preferred one instead: {}x{}@{:2f}", pMonitor->output->name, RULE->resolution, - (float)RULE->refreshRate, PREFERREDMODE->width, PREFERREDMODE->height, PREFERREDMODE->refresh / 1000.f); + (float)RULE->refreshRate, PREFERREDMODE->pixelSize.x, PREFERREDMODE->pixelSize.y, PREFERREDMODE->refreshRate / 1000.f); - pMonitor->refreshRate = PREFERREDMODE->refresh / 1000.f; - pMonitor->vecSize = Vector2D(PREFERREDMODE->width, PREFERREDMODE->height); + pMonitor->refreshRate = PREFERREDMODE->refreshRate / 1000.f; + pMonitor->vecSize = PREFERREDMODE->pixelSize; pMonitor->currentMode = PREFERREDMODE; } else { Debug::log(LOG, "Set a custom mode {:X0}@{:2f} (mode not found in monitor modes)", RULE->resolution, (float)RULE->refreshRate); @@ -1982,30 +1979,30 @@ bool CHyprRenderer::applyMonitorRule(CMonitor* pMonitor, SMonitorRule* pMonitorR bool fail = false; if (RULE->drmMode.type == DRM_MODE_TYPE_USERDEF) { - if (!wlr_output_is_drm(pMonitor->output)) { + if (pMonitor->output->getBackend()->type() != Aquamarine::eBackendType::AQ_BACKEND_DRM) { Debug::log(ERR, "Tried to set custom modeline on non-DRM output"); fail = true; } else { - auto* mode = wlr_drm_connector_add_mode(pMonitor->output, &RULE->drmMode); - if (mode) { - wlr_output_state_set_mode(pMonitor->state.wlr(), mode); - pMonitor->customDrmMode = RULE->drmMode; - } else { - Debug::log(ERR, "wlr_drm_connector_add_mode failed"); - fail = true; - } + // FIXME: + // auto* mode = wlr_drm_connector_add_mode(pMonitor->output, &RULE->drmMode); + // if (mode) { + // wlr_output_state_set_mode(pMonitor->state.wlr(), mode); + // pMonitor->customDrmMode = RULE->drmMode; + // } else { + // Debug::log(ERR, "wlr_drm_connector_add_mode failed"); + // fail = true; + // } } - } else { - wlr_output_state_set_custom_mode(pMonitor->state.wlr(), (int)RULE->resolution.x, (int)RULE->resolution.y, WLRREFRESHRATE); - } + } else + pMonitor->output->state->setCustomMode(makeShared(Aquamarine::SOutputMode{.pixelSize = RULE->resolution, .refreshRate = WLRREFRESHRATE})); pMonitor->vecSize = RULE->resolution; pMonitor->refreshRate = RULE->refreshRate; - if (fail || !wlr_output_test_state(pMonitor->output, pMonitor->state.wlr())) { + if (fail || !pMonitor->state.test()) { Debug::log(ERR, "Custom resolution FAILED, falling back to preferred"); - const auto PREFERREDMODE = wlr_output_preferred_mode(pMonitor->output); + const auto PREFERREDMODE = pMonitor->output->preferredMode(); if (!PREFERREDMODE) { Debug::log(ERR, "Monitor {} has NO PREFERRED MODE, and an INVALID one was requested: {:X0}@{:2f}", pMonitor->output->name, RULE->resolution, @@ -2014,48 +2011,47 @@ bool CHyprRenderer::applyMonitorRule(CMonitor* pMonitor, SMonitorRule* pMonitorR } // Preferred is valid - wlr_output_state_set_mode(pMonitor->state.wlr(), PREFERREDMODE); + pMonitor->output->state->setMode(PREFERREDMODE); Debug::log(ERR, "Monitor {} got an invalid requested mode: {:X0}@{:2f}, using the preferred one instead: {}x{}@{:2f}", pMonitor->output->name, RULE->resolution, - (float)RULE->refreshRate, PREFERREDMODE->width, PREFERREDMODE->height, PREFERREDMODE->refresh / 1000.f); + (float)RULE->refreshRate, PREFERREDMODE->pixelSize.x, PREFERREDMODE->pixelSize.y, PREFERREDMODE->refreshRate / 1000.f); - pMonitor->refreshRate = PREFERREDMODE->refresh / 1000.f; - pMonitor->vecSize = Vector2D(PREFERREDMODE->width, PREFERREDMODE->height); + pMonitor->refreshRate = PREFERREDMODE->refreshRate / 1000.f; + pMonitor->vecSize = PREFERREDMODE->pixelSize; pMonitor->customDrmMode = {}; - } else { + } else Debug::log(LOG, "Set a custom mode {:X0}@{:2f} (mode not found in monitor modes)", RULE->resolution, (float)RULE->refreshRate); - } } } else if (RULE->resolution != Vector2D()) { - if (!wl_list_empty(&pMonitor->output->modes)) { - wlr_output_mode* mode; - float currentWidth = 0; - float currentHeight = 0; - float currentRefresh = 0; - bool success = false; + if (!pMonitor->output->modes.empty()) { + float currentWidth = 0; + float currentHeight = 0; + float currentRefresh = 0; + bool success = false; //(-1,-1) indicates a preference to refreshrate over resolution, (-1,-2) preference to resolution if (RULE->resolution == Vector2D(-1, -1)) { - wl_list_for_each(mode, &pMonitor->output->modes, link) { - if ((mode->width >= currentWidth && mode->height >= currentHeight && mode->refresh >= (currentRefresh - 1000.f)) || mode->refresh > (currentRefresh + 3000.f)) { - wlr_output_state_set_mode(pMonitor->state.wlr(), mode); - if (wlr_output_test_state(pMonitor->output, pMonitor->state.wlr())) { - currentWidth = mode->width; - currentHeight = mode->height; - currentRefresh = mode->refresh; + for (auto& mode : pMonitor->output->modes) { + if ((mode->pixelSize.x >= currentWidth && mode->pixelSize.y >= currentHeight && mode->refreshRate >= (currentRefresh - 1000.f)) || + mode->refreshRate > (currentRefresh + 3000.f)) { + pMonitor->output->state->setMode(mode); + if (pMonitor->state.test()) { + currentWidth = mode->pixelSize.x; + currentHeight = mode->pixelSize.y; + currentRefresh = mode->refreshRate; success = true; } } } } else { - wl_list_for_each(mode, &pMonitor->output->modes, link) { - if ((mode->width >= currentWidth && mode->height >= currentHeight && mode->refresh >= (currentRefresh - 1000.f)) || - (mode->width > currentWidth && mode->height > currentHeight)) { - wlr_output_state_set_mode(pMonitor->state.wlr(), mode); - if (wlr_output_test_state(pMonitor->output, pMonitor->state.wlr())) { - currentWidth = mode->width; - currentHeight = mode->height; - currentRefresh = mode->refresh; + for (auto& mode : pMonitor->output->modes) { + if ((mode->pixelSize.x >= currentWidth && mode->pixelSize.y >= currentHeight && mode->refreshRate >= (currentRefresh - 1000.f)) || + (mode->pixelSize.x > currentWidth && mode->pixelSize.y > currentHeight)) { + pMonitor->output->state->setMode(mode); + if (pMonitor->state.test()) { + currentWidth = mode->pixelSize.x; + currentHeight = mode->pixelSize.y; + currentRefresh = mode->refreshRate; success = true; } } @@ -2063,10 +2059,12 @@ bool CHyprRenderer::applyMonitorRule(CMonitor* pMonitor, SMonitorRule* pMonitorR } if (!success) { - Debug::log(LOG, "Monitor {}: REJECTED mode: {:X0}@{:2f}! Falling back to preferred: {}x{}@{:2f}", pMonitor->output->name, RULE->resolution, - (float)RULE->refreshRate, mode->width, mode->height, mode->refresh / 1000.f); + if (pMonitor->output->state->state().mode) + Debug::log(LOG, "Monitor {}: REJECTED mode: {:X0}@{:2f}! Falling back to preferred: {}x{}@{:2f}", pMonitor->output->name, RULE->resolution, + (float)RULE->refreshRate, pMonitor->output->state->state().mode->pixelSize.x, pMonitor->output->state->state().mode->pixelSize.y, + pMonitor->output->state->state().mode->refreshRate / 1000.f); - const auto PREFERREDMODE = wlr_output_preferred_mode(pMonitor->output); + const auto PREFERREDMODE = pMonitor->output->preferredMode(); if (!PREFERREDMODE) { Debug::log(ERR, "Monitor {} has NO PREFERRED MODE, and an INVALID one was requested: {:X0}@{:2f}", pMonitor->ID, RULE->resolution, (float)RULE->refreshRate); @@ -2074,13 +2072,13 @@ bool CHyprRenderer::applyMonitorRule(CMonitor* pMonitor, SMonitorRule* pMonitorR } // Preferred is valid - wlr_output_state_set_mode(pMonitor->state.wlr(), PREFERREDMODE); + pMonitor->output->state->setMode(PREFERREDMODE); Debug::log(ERR, "Monitor {} got an invalid requested mode: {:X0}@{:2f}, using the preferred one instead: {}x{}@{:2f}", pMonitor->output->name, RULE->resolution, - (float)RULE->refreshRate, PREFERREDMODE->width, PREFERREDMODE->height, PREFERREDMODE->refresh / 1000.f); + (float)RULE->refreshRate, PREFERREDMODE->pixelSize.x, PREFERREDMODE->pixelSize.y, PREFERREDMODE->refreshRate / 1000.f); - pMonitor->refreshRate = PREFERREDMODE->refresh / 1000.f; - pMonitor->vecSize = Vector2D(PREFERREDMODE->width, PREFERREDMODE->height); + pMonitor->refreshRate = PREFERREDMODE->refreshRate / 1000.f; + pMonitor->vecSize = PREFERREDMODE->pixelSize; pMonitor->currentMode = PREFERREDMODE; } else { @@ -2091,27 +2089,26 @@ bool CHyprRenderer::applyMonitorRule(CMonitor* pMonitor, SMonitorRule* pMonitorR } } } else { - const auto PREFERREDMODE = wlr_output_preferred_mode(pMonitor->output); + const auto PREFERREDMODE = pMonitor->output->preferredMode(); if (!PREFERREDMODE) { Debug::log(ERR, "Monitor {} has NO PREFERRED MODE", pMonitor->output->name); - if (!wl_list_empty(&pMonitor->output->modes)) { - wlr_output_mode* mode; + if (!pMonitor->output->modes.empty()) { + for (auto& mode : pMonitor->output->modes) { + pMonitor->output->state->setMode(mode); - wl_list_for_each(mode, &pMonitor->output->modes, link) { - wlr_output_state_set_mode(pMonitor->state.wlr(), mode); - - if (!wlr_output_test_state(pMonitor->output, pMonitor->state.wlr())) { - Debug::log(LOG, "Monitor {}: REJECTED available mode: {}x{}@{:2f}!", pMonitor->output->name, mode->width, mode->height, mode->refresh / 1000.f); + if (!pMonitor->state.test()) { + Debug::log(LOG, "Monitor {}: REJECTED available mode: {}x{}@{:2f}!", pMonitor->output->name, mode->pixelSize.x, mode->pixelSize.y, + mode->refreshRate / 1000.f); continue; } Debug::log(LOG, "Monitor {}: requested {:X0}@{:2f}, found available mode: {}x{}@{}mHz, applying.", pMonitor->output->name, RULE->resolution, - (float)RULE->refreshRate, mode->width, mode->height, mode->refresh); + (float)RULE->refreshRate, mode->pixelSize.x, mode->pixelSize.y, mode->refreshRate); - pMonitor->refreshRate = mode->refresh / 1000.f; - pMonitor->vecSize = Vector2D(mode->width, mode->height); + pMonitor->refreshRate = mode->refreshRate / 1000.f; + pMonitor->vecSize = mode->pixelSize; pMonitor->currentMode = mode; break; @@ -2119,21 +2116,49 @@ bool CHyprRenderer::applyMonitorRule(CMonitor* pMonitor, SMonitorRule* pMonitorR } } else { // Preferred is valid - wlr_output_state_set_mode(pMonitor->state.wlr(), PREFERREDMODE); + pMonitor->output->state->setMode(PREFERREDMODE); - pMonitor->vecSize = Vector2D(PREFERREDMODE->width, PREFERREDMODE->height); - pMonitor->refreshRate = PREFERREDMODE->refresh / 1000.f; + pMonitor->vecSize = PREFERREDMODE->pixelSize; + pMonitor->refreshRate = PREFERREDMODE->refreshRate / 1000.f; pMonitor->currentMode = PREFERREDMODE; Debug::log(LOG, "Setting preferred mode for {}", pMonitor->output->name); } } - pMonitor->vrrActive = pMonitor->state.wlr()->adaptive_sync_enabled // disabled here, will be tested in CConfigManager::ensureVRR() - || pMonitor->createdByUser; // wayland backend doesn't allow for disabling adaptive_sync + pMonitor->vrrActive = pMonitor->output->state->state().adaptiveSync // disabled here, will be tested in CConfigManager::ensureVRR() + || pMonitor->createdByUser; // wayland backend doesn't allow for disabling adaptive_sync pMonitor->vecPixelSize = pMonitor->vecSize; + // clang-format off + static const std::array>, 2> formats{ + std::vector>{ /* 10-bit */ + {"DRM_FORMAT_XRGB2101010", DRM_FORMAT_XRGB2101010}, {"DRM_FORMAT_XBGR2101010", DRM_FORMAT_XBGR2101010}, {"DRM_FORMAT_XRGB8888", DRM_FORMAT_XRGB8888}, {"DRM_FORMAT_XBGR8888", DRM_FORMAT_XBGR8888}, {"DRM_FORMAT_INVALID", DRM_FORMAT_INVALID} + }, + std::vector>{ /* 8-bit */ + {"DRM_FORMAT_XRGB8888", DRM_FORMAT_XRGB8888}, {"DRM_FORMAT_XBGR8888", DRM_FORMAT_XBGR8888}, {"DRM_FORMAT_INVALID", DRM_FORMAT_INVALID} + } + }; + // clang-format on + + bool set10bit = false; + + for (auto& fmt : formats[(int)!RULE->enable10bit]) { + pMonitor->output->state->setFormat(fmt.second); + + if (!pMonitor->state.test()) { + Debug::log(ERR, "output {} failed basic test on format {}", pMonitor->szName, fmt.first); + } else { + Debug::log(LOG, "output {} succeeded basic test on format {}", pMonitor->szName, fmt.first); + if (RULE->enable10bit && fmt.first.contains("101010")) + set10bit = true; + break; + } + } + + pMonitor->enabled10bit = set10bit; + Vector2D logicalSize = pMonitor->vecPixelSize / pMonitor->scale; if (!*PDISABLESCALECHECKS && (logicalSize.x != std::round(logicalSize.x) || logicalSize.y != std::round(logicalSize.y))) { // invalid scale, will produce fractional pixels. @@ -2145,10 +2170,9 @@ bool CHyprRenderer::applyMonitorRule(CMonitor* pMonitor, SMonitorRule* pMonitorR double scaleZero = searchScale / 120.0; Vector2D logicalZero = pMonitor->vecPixelSize / scaleZero; - if (logicalZero == logicalZero.round()) { + if (logicalZero == logicalZero.round()) pMonitor->scale = scaleZero; - wlr_output_state_set_scale(pMonitor->state.wlr(), pMonitor->scale); - } else { + else { for (size_t i = 1; i < 90; ++i) { double scaleUp = (searchScale + i) / 120.0; double scaleDown = (searchScale - i) / 120.0; @@ -2185,57 +2209,21 @@ bool CHyprRenderer::applyMonitorRule(CMonitor* pMonitor, SMonitorRule* pMonitorR } else pMonitor->scale = searchScale; } - - // for wlroots, that likes flooring, we have to do this. - double logicalX = std::round(pMonitor->vecPixelSize.x / pMonitor->scale); - logicalX += 0.1; - - wlr_output_state_set_scale(pMonitor->state.wlr(), pMonitor->vecPixelSize.x / logicalX); } } - // clang-format off - static const std::array>, 2> formats{ - std::vector>{ /* 10-bit */ - {"DRM_FORMAT_XRGB2101010", DRM_FORMAT_XRGB2101010}, {"DRM_FORMAT_XBGR2101010", DRM_FORMAT_XBGR2101010}, {"DRM_FORMAT_XRGB8888", DRM_FORMAT_XRGB8888}, {"DRM_FORMAT_XBGR8888", DRM_FORMAT_XBGR8888}, {"DRM_FORMAT_INVALID", DRM_FORMAT_INVALID} - }, - std::vector>{ /* 8-bit */ - {"DRM_FORMAT_XRGB8888", DRM_FORMAT_XRGB8888}, {"DRM_FORMAT_XBGR8888", DRM_FORMAT_XBGR8888}, {"DRM_FORMAT_INVALID", DRM_FORMAT_INVALID} - } - }; - // clang-format on - - bool set10bit = false; - pMonitor->drmFormat = DRM_FORMAT_INVALID; - - for (auto& fmt : formats[(int)!RULE->enable10bit]) { - wlr_output_state_set_render_format(pMonitor->state.wlr(), fmt.second); - - if (!wlr_output_test_state(pMonitor->output, pMonitor->state.wlr())) { - Debug::log(ERR, "output {} failed basic test on format {}", pMonitor->szName, fmt.first); - } else { - Debug::log(LOG, "output {} succeeded basic test on format {}", pMonitor->szName, fmt.first); - if (RULE->enable10bit && fmt.first.contains("101010")) - set10bit = true; - - pMonitor->drmFormat = fmt.second; - break; - } - } - - pMonitor->enabled10bit = set10bit; + pMonitor->output->scheduleFrame(); if (!pMonitor->state.commit()) Debug::log(ERR, "Couldn't commit output named {}", pMonitor->output->name); - int x, y; - wlr_output_transformed_resolution(pMonitor->output, &x, &y); - pMonitor->vecSize = (Vector2D(x, y) / pMonitor->scale).round(); - pMonitor->vecTransformedSize = Vector2D(x, y); + Vector2D xfmd = pMonitor->transform % 2 == 1 ? Vector2D{pMonitor->vecPixelSize.y, pMonitor->vecPixelSize.x} : pMonitor->vecPixelSize; + pMonitor->vecSize = (xfmd / pMonitor->scale).round(); + pMonitor->vecTransformedSize = xfmd; if (pMonitor->createdByUser) { CBox transformedBox = {0, 0, pMonitor->vecTransformedSize.x, pMonitor->vecTransformedSize.y}; - transformedBox.transform(wlTransformToHyprutils(wlr_output_transform_invert(pMonitor->output->transform)), pMonitor->vecTransformedSize.x, pMonitor->vecTransformedSize.y); + transformedBox.transform(wlTransformToHyprutils(invertTransform(pMonitor->transform)), pMonitor->vecTransformedSize.x, pMonitor->vecTransformedSize.y); pMonitor->vecPixelSize = Vector2D(transformedBox.width, transformedBox.height); } @@ -2245,7 +2233,6 @@ bool CHyprRenderer::applyMonitorRule(CMonitor* pMonitor, SMonitorRule* pMonitorR if (WAS10B != pMonitor->enabled10bit || OLDRES != pMonitor->vecPixelSize) g_pHyprOpenGL->destroyMonitorResources(pMonitor); - // updato wlroots g_pCompositor->arrangeMonitors(); pMonitor->damage.setSize(pMonitor->vecTransformedSize); @@ -2260,9 +2247,6 @@ bool CHyprRenderer::applyMonitorRule(CMonitor* pMonitor, SMonitorRule* pMonitorR // updato us arrangeLayersForMonitor(pMonitor->ID); - // frame skip - pMonitor->framesToSkip = 1; - // reload to fix mirrors g_pConfigManager->m_bWantsMonitorReload = true; @@ -2329,7 +2313,7 @@ void CHyprRenderer::ensureCursorRenderingMode() { Debug::log(LOG, "Hiding the cursor (hl-mandated)"); for (auto& m : g_pCompositor->m_vMonitors) { - if (m->output->software_cursor_locks == 0) + if (!g_pPointerManager->softwareLockedFor(m)) continue; g_pHyprRenderer->damageMonitor(m.get()); // TODO: maybe just damage the cursor area? @@ -2341,7 +2325,7 @@ void CHyprRenderer::ensureCursorRenderingMode() { Debug::log(LOG, "Showing the cursor (hl-mandated)"); for (auto& m : g_pCompositor->m_vMonitors) { - if (m->output->software_cursor_locks == 0) + if (!g_pPointerManager->softwareLockedFor(m)) continue; g_pHyprRenderer->damageMonitor(m.get()); // TODO: maybe just damage the cursor area? @@ -2570,37 +2554,37 @@ void CHyprRenderer::recheckSolitaryForMonitor(CMonitor* pMonitor) { pMonitor->solitaryClient = PCANDIDATE; } -CRenderbuffer* CHyprRenderer::getOrCreateRenderbuffer(wlr_buffer* buffer, uint32_t fmt) { - auto it = std::find_if(m_vRenderbuffers.begin(), m_vRenderbuffers.end(), [&](const auto& other) { return other->m_pWlrBuffer == buffer; }); - - if (it != m_vRenderbuffers.end()) - return it->get(); - - return m_vRenderbuffers.emplace_back(std::make_unique(buffer, fmt)).get(); -} - -CRenderbuffer* CHyprRenderer::getOrCreateRenderbuffer(SP buffer, uint32_t fmt) { +SP CHyprRenderer::getOrCreateRenderbuffer(SP buffer, uint32_t fmt) { auto it = std::find_if(m_vRenderbuffers.begin(), m_vRenderbuffers.end(), [&](const auto& other) { return other->m_pHLBuffer == buffer; }); if (it != m_vRenderbuffers.end()) - return it->get(); + return *it; - return m_vRenderbuffers.emplace_back(std::make_unique(buffer, fmt)).get(); + auto buf = makeShared(buffer, fmt); + + if (!buf->good()) + return nullptr; + + m_vRenderbuffers.emplace_back(buf); + return buf; } void CHyprRenderer::makeEGLCurrent() { - if (!g_pCompositor) + if (!g_pCompositor || !g_pHyprOpenGL) return; - if (eglGetCurrentContext() != wlr_egl_get_context(g_pCompositor->m_sWLREGL)) - eglMakeCurrent(wlr_egl_get_display(g_pCompositor->m_sWLREGL), EGL_NO_SURFACE, EGL_NO_SURFACE, wlr_egl_get_context(g_pCompositor->m_sWLREGL)); + if (eglGetCurrentContext() != g_pHyprOpenGL->m_pEglContext) + eglMakeCurrent(g_pHyprOpenGL->m_pEglDisplay, EGL_NO_SURFACE, EGL_NO_SURFACE, g_pHyprOpenGL->m_pEglContext); } void CHyprRenderer::unsetEGL() { - eglMakeCurrent(wlr_egl_get_display(g_pCompositor->m_sWLREGL), EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT); + if (!g_pHyprOpenGL) + return; + + eglMakeCurrent(g_pHyprOpenGL->m_pEglDisplay, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT); } -bool CHyprRenderer::beginRender(CMonitor* pMonitor, CRegion& damage, eRenderMode mode, SP buffer, CFramebuffer* fb, bool simple) { +bool CHyprRenderer::beginRender(CMonitor* pMonitor, CRegion& damage, eRenderMode mode, SP buffer, CFramebuffer* fb, bool simple) { makeEGLCurrent(); @@ -2618,35 +2602,33 @@ bool CHyprRenderer::beginRender(CMonitor* pMonitor, CRegion& damage, eRenderMode return true; } - int bufferAge = 0; + /* This is a constant expression, as we always use double-buffering in our swapchain + TODO: Rewrite the CDamageRing to take advantage of that maybe? It's made to support longer swapchains atm because we used to do wlroots */ + static constexpr const int HL_BUFFER_AGE = 2; if (!buffer) { - if (!wlr_output_configure_primary_swapchain(pMonitor->output, pMonitor->state.wlr(), &pMonitor->output->swapchain)) { - Debug::log(ERR, "Failed to configure primary swapchain for {}", pMonitor->szName); - return false; - } - - m_pCurrentWlrBuffer = wlr_swapchain_acquire(pMonitor->output->swapchain, &bufferAge); - if (!m_pCurrentWlrBuffer) { + m_pCurrentBuffer = pMonitor->output->swapchain->next(nullptr); + if (!m_pCurrentBuffer) { Debug::log(ERR, "Failed to acquire swapchain buffer for {}", pMonitor->szName); return false; } } else - m_pCurrentHLBuffer = buffer; + m_pCurrentBuffer = buffer; try { - if (m_pCurrentWlrBuffer) - m_pCurrentRenderbuffer = getOrCreateRenderbuffer(m_pCurrentWlrBuffer, pMonitor->drmFormat); - else - m_pCurrentRenderbuffer = getOrCreateRenderbuffer(m_pCurrentHLBuffer.lock(), pMonitor->drmFormat); + m_pCurrentRenderbuffer = getOrCreateRenderbuffer(m_pCurrentBuffer, pMonitor->output->state->state().drmFormat); } catch (std::exception& e) { Debug::log(ERR, "getOrCreateRenderbuffer failed for {}", pMonitor->szName); - wlr_buffer_unlock(m_pCurrentWlrBuffer); + return false; + } + + if (!m_pCurrentRenderbuffer) { + Debug::log(ERR, "failed to start a render pass for output {}, no RBO could be obtained", pMonitor->szName); return false; } if (mode == RENDER_MODE_NORMAL) { - damage = pMonitor->damage.getBufferDamage(bufferAge); + damage = pMonitor->damage.getBufferDamage(HL_BUFFER_AGE); pMonitor->damage.rotate(); } @@ -2662,6 +2644,9 @@ bool CHyprRenderer::beginRender(CMonitor* pMonitor, CRegion& damage, eRenderMode void CHyprRenderer::endRender() { const auto PMONITOR = g_pHyprOpenGL->m_RenderData.pMonitor; static auto PNVIDIAANTIFLICKER = CConfigValue("opengl:nvidia_anti_flicker"); + static auto PENABLEEXPLICIT = CConfigValue("experimental:explicit_sync"); + + PMONITOR->commitSeq++; if (m_eRenderMode != RENDER_MODE_TO_BUFFER_READ_ONLY) g_pHyprOpenGL->end(); @@ -2674,29 +2659,57 @@ void CHyprRenderer::endRender() { if (m_eRenderMode == RENDER_MODE_FULL_FAKE) return; - if (isNvidia() && *PNVIDIAANTIFLICKER) - glFinish(); - else - glFlush(); - if (m_eRenderMode == RENDER_MODE_NORMAL) { - wlr_output_state_set_buffer(PMONITOR->state.wlr(), m_pCurrentWlrBuffer); - unsetEGL(); // flush the context - } + PMONITOR->output->state->setBuffer(m_pCurrentBuffer); - wlr_buffer_unlock(m_pCurrentWlrBuffer); + if (PMONITOR->inTimeline && *PENABLEEXPLICIT) { + auto sync = g_pHyprOpenGL->createEGLSync(-1); + if (!sync) { + m_pCurrentRenderbuffer->unbind(); + m_pCurrentRenderbuffer = nullptr; + m_pCurrentBuffer = nullptr; + Debug::log(ERR, "renderer: couldn't create an EGLSync for out in endRender"); + return; + } + + auto dupedfd = sync->dupFenceFD(); + sync.reset(); + if (dupedfd < 0) { + m_pCurrentRenderbuffer->unbind(); + m_pCurrentRenderbuffer = nullptr; + m_pCurrentBuffer = nullptr; + Debug::log(ERR, "renderer: couldn't dup an EGLSync fence for out in endRender"); + return; + } + + bool ok = PMONITOR->inTimeline->importFromSyncFileFD(PMONITOR->commitSeq, dupedfd); + close(dupedfd); + if (!ok) { + m_pCurrentRenderbuffer->unbind(); + m_pCurrentRenderbuffer = nullptr; + m_pCurrentBuffer = nullptr; + Debug::log(ERR, "renderer: couldn't import from sync file fd in endRender"); + return; + } + } else { + if (isNvidia() && *PNVIDIAANTIFLICKER) + glFinish(); + else + glFlush(); + } + } m_pCurrentRenderbuffer->unbind(); m_pCurrentRenderbuffer = nullptr; - m_pCurrentWlrBuffer = nullptr; + m_pCurrentBuffer = nullptr; } void CHyprRenderer::onRenderbufferDestroy(CRenderbuffer* rb) { std::erase_if(m_vRenderbuffers, [&](const auto& rbo) { return rbo.get() == rb; }); } -CRenderbuffer* CHyprRenderer::getCurrentRBO() { +SP CHyprRenderer::getCurrentRBO() { return m_pCurrentRenderbuffer; } diff --git a/src/render/Renderer.hpp b/src/render/Renderer.hpp index 8f404c88..72efe8c4 100644 --- a/src/render/Renderer.hpp +++ b/src/render/Renderer.hpp @@ -12,7 +12,7 @@ struct SMonitorRule; class CWorkspace; class CWindow; class CInputPopup; -class IWLBuffer; +class IHLBuffer; // TODO: add fuller damage tracking for updating only parts of a window enum DAMAGETRACKINGMODES { @@ -69,35 +69,35 @@ class CHyprRenderer { void setCursorSurface(SP surf, int hotspotX, int hotspotY, bool force = false); void setCursorFromName(const std::string& name, bool force = false); void onRenderbufferDestroy(CRenderbuffer* rb); - CRenderbuffer* getCurrentRBO(); + SP getCurrentRBO(); bool isNvidia(); void makeEGLCurrent(); void unsetEGL(); // if RENDER_MODE_NORMAL, provided damage will be written to. // otherwise, it will be the one used. - bool beginRender(CMonitor* pMonitor, CRegion& damage, eRenderMode mode = RENDER_MODE_NORMAL, SP buffer = {}, CFramebuffer* fb = nullptr, bool simple = false); - void endRender(); + bool beginRender(CMonitor* pMonitor, CRegion& damage, eRenderMode mode = RENDER_MODE_NORMAL, SP buffer = {}, CFramebuffer* fb = nullptr, bool simple = false); + void endRender(); - bool m_bBlockSurfaceFeedback = false; - bool m_bRenderingSnapshot = false; - PHLWINDOWREF m_pLastScanout; - CMonitor* m_pMostHzMonitor = nullptr; - bool m_bDirectScanoutBlocked = false; + bool m_bBlockSurfaceFeedback = false; + bool m_bRenderingSnapshot = false; + CMonitor* m_pMostHzMonitor = nullptr; + bool m_bDirectScanoutBlocked = false; DAMAGETRACKINGMODES damageTrackingModeFromStr(const std::string&); - bool attemptDirectScanout(CMonitor*); - void setWindowScanoutMode(PHLWINDOW); - void initiateManualCrash(); + void setSurfaceScanoutMode(SP surface, SP monitor); // nullptr monitor resets + void initiateManualCrash(); - bool m_bCrashingInProgress = false; - float m_fCrashingDistort = 0.5f; - wl_event_source* m_pCrashingLoop = nullptr; - wl_event_source* m_pCursorTicker = nullptr; + bool m_bCrashingInProgress = false; + float m_fCrashingDistort = 0.5f; + wl_event_source* m_pCrashingLoop = nullptr; + wl_event_source* m_pCursorTicker = nullptr; - CTimer m_tRenderTimer; + CTimer m_tRenderTimer; + + std::vector> explicitPresented; struct { int hotspotX; @@ -107,26 +107,27 @@ class CHyprRenderer { } m_sLastCursorData; private: - void arrangeLayerArray(CMonitor*, const std::vector&, bool, CBox*); - void renderWorkspaceWindowsFullscreen(CMonitor*, PHLWORKSPACE, timespec*); // renders workspace windows (fullscreen) (tiled, floating, pinned, but no special) - void renderWorkspaceWindows(CMonitor*, PHLWORKSPACE, timespec*); // renders workspace windows (no fullscreen) (tiled, floating, pinned, but no special) - void renderWindow(PHLWINDOW, CMonitor*, timespec*, bool, eRenderPassMode, bool ignorePosition = false, bool ignoreAllGeometry = false); - void renderLayer(PHLLS, CMonitor*, timespec*, bool popups = false); - void renderSessionLockSurface(SSessionLockSurface*, CMonitor*, timespec*); - void renderDragIcon(CMonitor*, timespec*); - void renderIMEPopup(CInputPopup*, CMonitor*, timespec*); - void renderWorkspace(CMonitor* pMonitor, PHLWORKSPACE pWorkspace, timespec* now, const CBox& geometry); - void sendFrameEventsToWorkspace(CMonitor* pMonitor, PHLWORKSPACE pWorkspace, timespec* now); // sends frame displayed events but doesn't actually render anything - void renderAllClientsForWorkspace(CMonitor* pMonitor, PHLWORKSPACE pWorkspace, timespec* now, const Vector2D& translate = {0, 0}, const float& scale = 1.f); + void arrangeLayerArray(CMonitor*, const std::vector&, bool, CBox*); + void renderWorkspaceWindowsFullscreen(CMonitor*, PHLWORKSPACE, timespec*); // renders workspace windows (fullscreen) (tiled, floating, pinned, but no special) + void renderWorkspaceWindows(CMonitor*, PHLWORKSPACE, timespec*); // renders workspace windows (no fullscreen) (tiled, floating, pinned, but no special) + void renderWindow(PHLWINDOW, CMonitor*, timespec*, bool, eRenderPassMode, bool ignorePosition = false, bool ignoreAllGeometry = false); + void renderLayer(PHLLS, CMonitor*, timespec*, bool popups = false); + void renderSessionLockSurface(SSessionLockSurface*, CMonitor*, timespec*); + void renderDragIcon(CMonitor*, timespec*); + void renderIMEPopup(CInputPopup*, CMonitor*, timespec*); + void renderWorkspace(CMonitor* pMonitor, PHLWORKSPACE pWorkspace, timespec* now, const CBox& geometry); + void sendFrameEventsToWorkspace(CMonitor* pMonitor, PHLWORKSPACE pWorkspace, timespec* now); // sends frame displayed events but doesn't actually render anything + void renderAllClientsForWorkspace(CMonitor* pMonitor, PHLWORKSPACE pWorkspace, timespec* now, const Vector2D& translate = {0, 0}, const float& scale = 1.f); - bool m_bCursorHidden = false; - bool m_bCursorHasSurface = false; - CRenderbuffer* m_pCurrentRenderbuffer = nullptr; - wlr_buffer* m_pCurrentWlrBuffer = nullptr; - WP m_pCurrentHLBuffer = {}; - eRenderMode m_eRenderMode = RENDER_MODE_NORMAL; + bool commitPendingAndDoExplicitSync(CMonitor* pMonitor); - bool m_bNvidia = false; + bool m_bCursorHidden = false; + bool m_bCursorHasSurface = false; + SP m_pCurrentRenderbuffer = nullptr; + SP m_pCurrentBuffer; + eRenderMode m_eRenderMode = RENDER_MODE_NORMAL; + + bool m_bNvidia = false; struct { bool hiddenOnTouch = false; @@ -134,9 +135,8 @@ class CHyprRenderer { bool hiddenOnKeyboard = false; } m_sCursorHiddenConditions; - CRenderbuffer* getOrCreateRenderbuffer(wlr_buffer* buffer, uint32_t fmt); - CRenderbuffer* getOrCreateRenderbuffer(SP buffer, uint32_t fmt); - std::vector> m_vRenderbuffers; + SP getOrCreateRenderbuffer(SP buffer, uint32_t fmt); + std::vector> m_vRenderbuffers; friend class CHyprOpenGLImpl; friend class CToplevelExportProtocolManager; diff --git a/src/render/Texture.cpp b/src/render/Texture.cpp index 46c501a0..0f5b4c4c 100644 --- a/src/render/Texture.cpp +++ b/src/render/Texture.cpp @@ -9,7 +9,7 @@ CTexture::CTexture() { } CTexture::~CTexture() { - if (m_bNonOwning || !g_pCompositor || g_pCompositor->m_bIsShuttingDown || !g_pHyprRenderer) + if (!g_pCompositor || g_pCompositor->m_bIsShuttingDown || !g_pHyprRenderer) return; g_pHyprRenderer->makeEGLCurrent(); @@ -17,6 +17,45 @@ CTexture::~CTexture() { } CTexture::CTexture(uint32_t drmFormat, uint8_t* pixels, uint32_t stride, const Vector2D& size_) { + createFromShm(drmFormat, pixels, stride, size_); +} + +CTexture::CTexture(const Aquamarine::SDMABUFAttrs& attrs, void* image) { + createFromDma(attrs, image); +} + +CTexture::CTexture(const SP buffer) { + if (!buffer) + return; + + auto attrs = buffer->dmabuf(); + + if (!attrs.success) { + // attempt shm + auto shm = buffer->shm(); + + if (!shm.success) { + Debug::log(ERR, "Cannot create a texture: buffer has no dmabuf or shm"); + return; + } + + auto [pixelData, fmt, bufLen] = buffer->beginDataPtr(0); + + createFromShm(fmt, pixelData, bufLen, shm.size); + return; + } + + auto image = g_pHyprOpenGL->createEGLImage(buffer->dmabuf()); + + if (!image) { + Debug::log(ERR, "Cannot create a texture: failed to create an EGLImage"); + return; + } + + createFromDma(attrs, image); +} + +void CTexture::createFromShm(uint32_t drmFormat, uint8_t* pixels, uint32_t stride, const Vector2D& size_) { g_pHyprRenderer->makeEGLCurrent(); const auto format = FormatUtils::getPixelFormatFromDRM(drmFormat); @@ -41,24 +80,7 @@ CTexture::CTexture(uint32_t drmFormat, uint8_t* pixels, uint32_t stride, const V GLCALL(glBindTexture(GL_TEXTURE_2D, 0)); } -CTexture::CTexture(wlr_texture* tex) { - RASSERT(wlr_texture_is_gles2(tex), "wlr_texture provided to CTexture that isn't GLES2!"); - wlr_gles2_texture_attribs attrs; - wlr_gles2_texture_get_attribs(tex, &attrs); - - m_iTarget = attrs.target; - m_iTexID = attrs.tex; - m_bNonOwning = true; - - if (m_iTarget == GL_TEXTURE_2D) - m_iType = attrs.has_alpha ? TEXTURE_RGBA : TEXTURE_RGBX; - else - m_iType = TEXTURE_EXTERNAL; - - m_vSize = Vector2D((int)tex->width, (int)tex->height); -} - -CTexture::CTexture(const SDMABUFAttrs& attrs, void* image) { +void CTexture::createFromDma(const Aquamarine::SDMABUFAttrs& attrs, void* image) { if (!g_pHyprOpenGL->m_sProc.glEGLImageTargetTexture2DOES) { Debug::log(ERR, "Cannot create a dmabuf texture: no glEGLImageTargetTexture2DOES"); return; @@ -119,7 +141,7 @@ void CTexture::destroyTexture() { } if (m_pEglImage) - g_pHyprOpenGL->m_sProc.eglDestroyImageKHR(wlr_egl_get_display(g_pCompositor->m_sWLREGL), m_pEglImage); + g_pHyprOpenGL->m_sProc.eglDestroyImageKHR(g_pHyprOpenGL->m_pEglDisplay, m_pEglImage); m_pEglImage = nullptr; } diff --git a/src/render/Texture.hpp b/src/render/Texture.hpp index c80e943d..0da95300 100644 --- a/src/render/Texture.hpp +++ b/src/render/Texture.hpp @@ -1,9 +1,9 @@ #pragma once #include "../defines.hpp" +#include -class IWLBuffer; -struct SDMABUFAttrs; +class IHLBuffer; HYPRUTILS_FORWARD(Math, CRegion); enum TEXTURETYPE { @@ -23,10 +23,10 @@ class CTexture { CTexture(const CTexture&) = delete; CTexture(uint32_t drmFormat, uint8_t* pixels, uint32_t stride, const Vector2D& size); - CTexture(wlr_texture*); + CTexture(const SP buffer); // this ctor takes ownership of the eglImage. - CTexture(const SDMABUFAttrs&, void* image); + CTexture(const Aquamarine::SDMABUFAttrs&, void* image); ~CTexture(); void destroyTexture(); @@ -37,6 +37,9 @@ class CTexture { GLenum m_iTarget = GL_TEXTURE_2D; GLuint m_iTexID = 0; Vector2D m_vSize; - void* m_pEglImage = nullptr; - bool m_bNonOwning = false; // wlr + void* m_pEglImage = nullptr; + + private: + void createFromShm(uint32_t drmFormat, uint8_t* pixels, uint32_t stride, const Vector2D& size); + void createFromDma(const Aquamarine::SDMABUFAttrs&, void* image); }; \ No newline at end of file diff --git a/src/signal-safe.hpp b/src/signal-safe.hpp index 70320ad1..3a38f043 100644 --- a/src/signal-safe.hpp +++ b/src/signal-safe.hpp @@ -1,6 +1,7 @@ #pragma once #include "defines.hpp" +#include template class MaxLengthCString { diff --git a/src/xwayland/Server.cpp b/src/xwayland/Server.cpp index e2dab412..3f4e7b43 100644 --- a/src/xwayland/Server.cpp +++ b/src/xwayland/Server.cpp @@ -18,12 +18,13 @@ #include #include #include +#include // TODO: cleanup static bool set_cloexec(int fd, bool cloexec) { int flags = fcntl(fd, F_GETFD); if (flags == -1) { - wlr_log_errno(WLR_ERROR, "fcntl failed"); + Debug::log(ERR, "fcntl failed"); return false; } if (cloexec) { @@ -32,7 +33,7 @@ static bool set_cloexec(int fd, bool cloexec) { flags = flags & ~FD_CLOEXEC; } if (fcntl(fd, F_SETFD, flags) == -1) { - wlr_log_errno(WLR_ERROR, "fcntl failed"); + Debug::log(ERR, "fcntl failed"); return false; } return true; @@ -44,7 +45,7 @@ static int openSocket(struct sockaddr_un* addr, size_t path_size) { fd = socket(AF_UNIX, SOCK_STREAM, 0); if (fd < 0) { - wlr_log_errno(WLR_ERROR, "Failed to create socket %c%s", addr->sun_path[0] ? addr->sun_path[0] : '@', addr->sun_path + 1); + Debug::log(ERR, "failed to create socket {}{}", addr->sun_path[0] ? addr->sun_path[0] : '@', addr->sun_path + 1); return -1; } if (!set_cloexec(fd, true)) { @@ -57,12 +58,12 @@ static int openSocket(struct sockaddr_un* addr, size_t path_size) { } if (bind(fd, (struct sockaddr*)addr, size) < 0) { rc = errno; - wlr_log_errno(WLR_ERROR, "Failed to bind socket %c%s", addr->sun_path[0] ? addr->sun_path[0] : '@', addr->sun_path + 1); + Debug::log(ERR, "failed to bind socket {}{}", addr->sun_path[0] ? addr->sun_path[0] : '@', addr->sun_path + 1); goto cleanup; } if (listen(fd, 1) < 0) { rc = errno; - wlr_log_errno(WLR_ERROR, "Failed to listen to socket %c%s", addr->sun_path[0] ? addr->sun_path[0] : '@', addr->sun_path + 1); + Debug::log(ERR, "failed to listen to socket {}{}", addr->sun_path[0] ? addr->sun_path[0] : '@', addr->sun_path + 1); goto cleanup; } diff --git a/src/xwayland/XWM.cpp b/src/xwayland/XWM.cpp index b34d0cfe..b55df7fc 100644 --- a/src/xwayland/XWM.cpp +++ b/src/xwayland/XWM.cpp @@ -299,8 +299,8 @@ void CXWM::handleClientMessage(xcb_client_message_event_t* e) { auto id = e->data.data32[0]; auto resource = wl_client_get_object(g_pXWayland->pServer->xwaylandClient, id); if (resource) { - auto wlrSurface = CWLSurfaceResource::fromResource(resource); - associate(XSURF, wlrSurface); + auto surf = CWLSurfaceResource::fromResource(resource); + associate(XSURF, surf); } } else if (e->type == HYPRATOMS["WL_SURFACE_SERIAL"]) { if (XSURF->wlSerial) { @@ -755,7 +755,7 @@ void CXWM::getVisual() { } if (visualtype == NULL) { - wlr_log(WLR_DEBUG, "No 32 bit visualtype\n"); + Debug::log(LOG, "xwm: No 32-bit visualtype"); return; } @@ -768,7 +768,7 @@ void CXWM::getRenderFormat() { xcb_render_query_pict_formats_cookie_t cookie = xcb_render_query_pict_formats(connection); xcb_render_query_pict_formats_reply_t* reply = xcb_render_query_pict_formats_reply(connection, cookie, NULL); if (!reply) { - wlr_log(WLR_ERROR, "Did not get any reply from xcb_render_query_pict_formats"); + Debug::log(LOG, "xwm: No xcb_render_query_pict_formats_reply_t reply"); return; } xcb_render_pictforminfo_iterator_t iter = xcb_render_query_pict_formats_formats_iterator(reply); @@ -783,7 +783,7 @@ void CXWM::getRenderFormat() { } if (format == NULL) { - wlr_log(WLR_DEBUG, "No 32 bit render format"); + Debug::log(LOG, "xwm: No 32-bit render format"); free(reply); return; } diff --git a/subprojects/wlroots-hyprland b/subprojects/wlroots-hyprland deleted file mode 160000 index 422207db..00000000 --- a/subprojects/wlroots-hyprland +++ /dev/null @@ -1 +0,0 @@ -Subproject commit 422207dbcf0949e28042403edab539159282885e From cf373d315e9fb060576ed407bd5ee2dfb8a6d2e2 Mon Sep 17 00:00:00 2001 From: khachbe Date: Sun, 21 Jul 2024 13:59:09 +0200 Subject: [PATCH 0118/2181] touch: add touch swipe invert config (#6940) --- src/config/ConfigManager.cpp | 1 + src/managers/input/Touch.cpp | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/src/config/ConfigManager.cpp b/src/config/ConfigManager.cpp index a5f18693..6928a802 100644 --- a/src/config/ConfigManager.cpp +++ b/src/config/ConfigManager.cpp @@ -519,6 +519,7 @@ CConfigManager::CConfigManager() { m_pConfig->addConfigValue("gestures:workspace_swipe_forever", Hyprlang::INT{0}); m_pConfig->addConfigValue("gestures:workspace_swipe_use_r", Hyprlang::INT{0}); m_pConfig->addConfigValue("gestures:workspace_swipe_touch", Hyprlang::INT{0}); + m_pConfig->addConfigValue("gestures:workspace_swipe_touch_invert", Hyprlang::INT{0}); m_pConfig->addConfigValue("xwayland:use_nearest_neighbor", Hyprlang::INT{1}); m_pConfig->addConfigValue("xwayland:force_zero_scaling", Hyprlang::INT{0}); diff --git a/src/managers/input/Touch.cpp b/src/managers/input/Touch.cpp index a1f949c2..736a2ae5 100644 --- a/src/managers/input/Touch.cpp +++ b/src/managers/input/Touch.cpp @@ -103,7 +103,7 @@ void CInputManager::onTouchMove(ITouch::SMotionEvent e) { return; const bool VERTANIMS = m_sActiveSwipe.pWorkspaceBegin->m_vRenderOffset.getConfig()->pValues->internalStyle == "slidevert" || m_sActiveSwipe.pWorkspaceBegin->m_vRenderOffset.getConfig()->pValues->internalStyle.starts_with("slidefadevert"); - static auto PSWIPEINVR = CConfigValue("gestures:workspace_swipe_invert"); + static auto PSWIPEINVR = CConfigValue("gestures:workspace_swipe_touch_invert"); static auto PSWIPEDIST = CConfigValue("gestures:workspace_swipe_distance"); const auto SWIPEDISTANCE = std::clamp(*PSWIPEDIST, (int64_t)1LL, (int64_t)UINT32_MAX); // Handle the workspace swipe if there is one From 043b859ea2ec8173d8a0f1f90012fcca82275d22 Mon Sep 17 00:00:00 2001 From: Vaxry Date: Sun, 21 Jul 2024 16:42:43 +0200 Subject: [PATCH 0119/2181] hyprpm: init submodules after resets ref #6948 --- hyprpm/src/core/PluginManager.cpp | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/hyprpm/src/core/PluginManager.cpp b/hyprpm/src/core/PluginManager.cpp index 7d7cc079..036609f3 100644 --- a/hyprpm/src/core/PluginManager.cpp +++ b/hyprpm/src/core/PluginManager.cpp @@ -172,6 +172,9 @@ bool CPluginManager::addNewPluginRepo(const std::string& url, const std::string& std::cerr << "\n" << Colors::RED << "✖" << Colors::RESET << " Could not check out revision " << rev << ". shell returned:\n" << ret << "\n"; return false; } + ret = execAndGet("git -C " + m_szWorkingPluginDirectory + " submodule update --init"); + if (m_bVerbose) + std::cout << Colors::BLUE << "[v] " << Colors::RESET << "git submodule update --init returned: " << ret << "\n"; } progress.m_iSteps = 1; @@ -226,6 +229,12 @@ bool CPluginManager::addNewPluginRepo(const std::string& url, const std::string& progress.printMessageAbove(std::string{Colors::GREEN} + "✔" + Colors::RESET + " commit pin " + plugin + " matched hl, resetting"); execAndGet("cd " + m_szWorkingPluginDirectory + " && git reset --hard --recurse-submodules " + plugin); + + ret = execAndGet("git -C " + m_szWorkingPluginDirectory + " submodule update --init"); + if (m_bVerbose) + std::cout << Colors::BLUE << "[v] " << Colors::RESET << "git submodule update --init returned: " << ret << "\n"; + + break; } } From efcbcd7297e2c9b06e3cd5d3296d47504f502cee Mon Sep 17 00:00:00 2001 From: Vaxry Date: Sun, 21 Jul 2024 16:45:40 +0200 Subject: [PATCH 0120/2181] input: fix invalid usage of dev in setTouchDeviceConfigs ref #6943 --- src/managers/input/InputManager.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/managers/input/InputManager.cpp b/src/managers/input/InputManager.cpp index 255023b9..492d2805 100644 --- a/src/managers/input/InputManager.cpp +++ b/src/managers/input/InputManager.cpp @@ -1488,9 +1488,9 @@ void CInputManager::newTouchDevice(SP pDevice) { } void CInputManager::setTouchDeviceConfigs(SP dev) { - auto setConfig = [&](SP PTOUCHDEV) -> void { - if (dev->aq() && dev->aq()->getLibinputHandle()) { - const auto LIBINPUTDEV = dev->aq()->getLibinputHandle(); + auto setConfig = [](SP PTOUCHDEV) -> void { + if (PTOUCHDEV->aq() && PTOUCHDEV->aq()->getLibinputHandle()) { + const auto LIBINPUTDEV = PTOUCHDEV->aq()->getLibinputHandle(); const auto ENABLED = g_pConfigManager->getDeviceInt(PTOUCHDEV->hlName, "enabled", "input:touchdevice:enabled"); const auto mode = ENABLED ? LIBINPUT_CONFIG_SEND_EVENTS_ENABLED : LIBINPUT_CONFIG_SEND_EVENTS_DISABLED; From f7fb7e7e49e3b47f9b72c55fbf2d093e1a7981f5 Mon Sep 17 00:00:00 2001 From: Vaxry Date: Sun, 21 Jul 2024 17:27:15 +0200 Subject: [PATCH 0121/2181] xwayland: avoid unfocusing on OR child focuses fixes #6698 --- src/xwayland/XWM.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/xwayland/XWM.cpp b/src/xwayland/XWM.cpp index b55df7fc..0eaa16be 100644 --- a/src/xwayland/XWM.cpp +++ b/src/xwayland/XWM.cpp @@ -398,10 +398,10 @@ void CXWM::focusWindow(SP surf) { focusedSurface = surf; - // send state to all surfaces, sometimes we might lose some + // send state to all toplevel surfaces, sometimes we might lose some // that could still stick with the focused atom for (auto& s : mappedSurfaces) { - if (!s) + if (!s || s->overrideRedirect) continue; sendState(s.lock()); @@ -879,7 +879,7 @@ void CXWM::activateSurface(SP surf, bool activate) { if ((surf == focusedSurface && activate) || (surf && surf->overrideRedirect)) return; - if (!activate || !surf) { + if (!surf || (!activate || !surf->overrideRedirect /* if we are focusing on an OR child, don't unfocus parent */)) { setActiveWindow((uint32_t)XCB_WINDOW_NONE); focusWindow(nullptr); } else { From 7f624d2236162db847c70ce1caa12851e77e60eb Mon Sep 17 00:00:00 2001 From: Vaxry Date: Sun, 21 Jul 2024 17:41:26 +0200 Subject: [PATCH 0122/2181] xwayland: fixup WM_SIZE_HINTS handling according to ICCCM --- src/managers/XWaylandManager.cpp | 20 ++++++++++++++------ 1 file changed, 14 insertions(+), 6 deletions(-) diff --git a/src/managers/XWaylandManager.cpp b/src/managers/XWaylandManager.cpp index e702a172..f329dbe1 100644 --- a/src/managers/XWaylandManager.cpp +++ b/src/managers/XWaylandManager.cpp @@ -76,13 +76,21 @@ void CHyprXWaylandManager::getGeometryForWindow(PHLWINDOW pWindow, CBox* pbox) { const auto SIZEHINTS = pWindow->m_pXWaylandSurface->sizeHints.get(); if (SIZEHINTS && pWindow->m_iX11Type != 2) { - pbox->x = SIZEHINTS->x; - pbox->y = SIZEHINTS->y; - pbox->width = SIZEHINTS->width; - pbox->height = SIZEHINTS->height; - } else { + // WM_SIZE_HINTS' x,y,w,h is deprecated it seems. + // Source: https://x.org/releases/X11R7.6/doc/xorg-docs/specs/ICCCM/icccm.html#wm_normal_hints_property + pbox->x = pWindow->m_pXWaylandSurface->geometry.x; + pbox->y = pWindow->m_pXWaylandSurface->geometry.y; + + if ((SIZEHINTS->flags & 0x2 /* ICCCM USSize */) || (SIZEHINTS->flags & 0x8 /* ICCCM PSize */)) { + pbox->w = SIZEHINTS->base_width; + pbox->h = SIZEHINTS->base_height; + } else { + pbox->w = pWindow->m_pXWaylandSurface->geometry.w; + pbox->h = pWindow->m_pXWaylandSurface->geometry.h; + } + } else *pbox = pWindow->m_pXWaylandSurface->geometry; - } + } else if (pWindow->m_pXDGSurface) *pbox = pWindow->m_pXDGSurface->current.geometry; } From faa157e1626fb56b5f01ac0597518cc41bf1c40b Mon Sep 17 00:00:00 2001 From: Mihai Fufezan Date: Thu, 18 Jul 2024 21:18:07 +0300 Subject: [PATCH 0123/2181] gitignore: add CMake residual files --- .gitignore | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/.gitignore b/.gitignore index 3601f422..78f794fc 100644 --- a/.gitignore +++ b/.gitignore @@ -7,6 +7,9 @@ cmake_install.cmake install_manifest.txt compile_commands.json CTestTestfile.cmake +CPackConfig.cmake +CPackSourceConfig.cmake +hyprland.pc _deps build/ @@ -15,6 +18,9 @@ result* /.idea/ .envrc .cache +.direnv +/.cmake/ +/.worktree/ *.o protocols/*.c* @@ -31,5 +37,3 @@ gmon.out PKGBUILD src/version.h - -.direnv From 928d1dd38a6e4a791d4a4374a4a3bf02311adbb2 Mon Sep 17 00:00:00 2001 From: Mihai Fufezan Date: Thu, 18 Jul 2024 21:27:03 +0300 Subject: [PATCH 0124/2181] CMake, Meson, Nix: replace props.json with VERSION --- CMakeLists.txt | 4 ++-- VERSION | 1 + meson.build | 2 +- nix/overlays.nix | 5 ++--- props.json | 3 --- 5 files changed, 6 insertions(+), 9 deletions(-) create mode 100644 VERSION delete mode 100644 props.json diff --git a/CMakeLists.txt b/CMakeLists.txt index e951b874..b65d361e 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -4,8 +4,8 @@ include(CheckIncludeFile) include(GNUInstallDirs) # Get version -file(READ ${CMAKE_CURRENT_SOURCE_DIR}/props.json PROPS) -string(JSON VER GET ${PROPS} version) +file(READ "${CMAKE_SOURCE_DIR}/VERSION" VER_RAW) +string(STRIP ${VER_RAW} VER) project(Hyprland DESCRIPTION "A Modern C++ Wayland Compositor" diff --git a/VERSION b/VERSION new file mode 100644 index 00000000..6599454d --- /dev/null +++ b/VERSION @@ -0,0 +1 @@ +0.41.2 diff --git a/meson.build b/meson.build index b8101f6c..4446ea0f 100644 --- a/meson.build +++ b/meson.build @@ -1,5 +1,5 @@ project('Hyprland', 'cpp', 'c', - version : run_command('jq', '-r', '.version', join_paths(meson.source_root(), 'props.json'), check: true).stdout().strip(), + version : run_command('cat', join_paths(meson.source_root(), 'VERSION'), check: true).stdout().strip(), default_options : [ 'warning_level=2', 'default_library=static', diff --git a/nix/overlays.nix b/nix/overlays.nix index 9d100d51..d8979b45 100644 --- a/nix/overlays.nix +++ b/nix/overlays.nix @@ -3,13 +3,12 @@ lib, inputs, }: let - props = builtins.fromJSON (builtins.readFile ../props.json); - mkDate = longDate: (lib.concatStringsSep "-" [ (builtins.substring 0 4 longDate) (builtins.substring 4 2 longDate) (builtins.substring 6 2 longDate) ]); + version = lib.removeSuffix "\n" (builtins.readFile ../VERSION); in { # Contains what a user is most likely to care about: # Hyprland itself, XDPH and the Share Picker. @@ -33,7 +32,7 @@ in { in { hyprland = final.callPackage ./default.nix { stdenv = final.gcc13Stdenv; - version = "${props.version}+date=${date}_${self.shortRev or "dirty"}"; + version = "${version}+date=${date}_${self.shortRev or "dirty"}"; commit = self.rev or ""; inherit date; }; diff --git a/props.json b/props.json deleted file mode 100644 index 2ff7562e..00000000 --- a/props.json +++ /dev/null @@ -1,3 +0,0 @@ -{ - "version": "0.41.2" -} \ No newline at end of file From db1f5cd13732bc440b8e5e353d87cdf7faaf1872 Mon Sep 17 00:00:00 2001 From: Mihai Fufezan Date: Thu, 18 Jul 2024 21:27:41 +0300 Subject: [PATCH 0125/2181] CMake: fmt --- CMakeLists.txt | 427 +++++++++++++++++++++++++++---------------------- 1 file changed, 236 insertions(+), 191 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index b65d361e..2bd4e0d5 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -7,10 +7,10 @@ include(GNUInstallDirs) file(READ "${CMAKE_SOURCE_DIR}/VERSION" VER_RAW) string(STRIP ${VER_RAW} VER) -project(Hyprland - DESCRIPTION "A Modern C++ Wayland Compositor" - VERSION ${VER} -) +project( + Hyprland + DESCRIPTION "A Modern C++ Wayland Compositor" + VERSION ${VER}) set(HYPRLAND_VERSION ${VER}) set(PREFIX ${CMAKE_INSTALL_PREFIX}) @@ -21,32 +21,30 @@ set(CMAKE_MESSAGE_LOG_LEVEL "STATUS") message(STATUS "Gathering git info") -# Get git info -# hash and branch -execute_process( - COMMAND ./scripts/generateVersion.sh - WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}) +# Get git info hash and branch +execute_process(COMMAND ./scripts/generateVersion.sh + WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}) # udis add_subdirectory("subprojects/udis86") if(CMAKE_BUILD_TYPE) - string(TOLOWER ${CMAKE_BUILD_TYPE} BUILDTYPE_LOWER) - if(BUILDTYPE_LOWER STREQUAL "release") - # Pass. - elseif(BUILDTYPE_LOWER STREQUAL "debug") - # Pass. - elseif(BUILDTYPE_LOWER STREQUAL "relwithdebinfo") - set(BUILDTYPE_LOWER "debugoptimized") - elseif(BUILDTYPE_LOWER STREQUAL "minsizerel") - set(BUILDTYPE_LOWER "minsize") - elseif(BUILDTYPE_LOWER STREQUAL "none") - set(BUILDTYPE_LOWER "plain") - else() - set(BUILDTYPE_LOWER "release") - endif() -else() + string(TOLOWER ${CMAKE_BUILD_TYPE} BUILDTYPE_LOWER) + if(BUILDTYPE_LOWER STREQUAL "release") + # Pass. + elseif(BUILDTYPE_LOWER STREQUAL "debug") + # Pass. + elseif(BUILDTYPE_LOWER STREQUAL "relwithdebinfo") + set(BUILDTYPE_LOWER "debugoptimized") + elseif(BUILDTYPE_LOWER STREQUAL "minsizerel") + set(BUILDTYPE_LOWER "minsize") + elseif(BUILDTYPE_LOWER STREQUAL "none") + set(BUILDTYPE_LOWER "plain") + else() set(BUILDTYPE_LOWER "release") + endif() +else() + set(BUILDTYPE_LOWER "release") endif() find_package(PkgConfig REQUIRED) @@ -58,22 +56,24 @@ message(STATUS "Found wayland-protocols at ${WAYLAND_PROTOCOLS_DIR}") pkg_get_variable(WAYLAND_SERVER_DIR wayland-server pkgdatadir) if(CMAKE_BUILD_TYPE MATCHES Debug OR CMAKE_BUILD_TYPE MATCHES DEBUG) - message(STATUS "Configuring Hyprland in Debug with CMake") - add_compile_definitions(HYPRLAND_DEBUG) + message(STATUS "Configuring Hyprland in Debug with CMake") + add_compile_definitions(HYPRLAND_DEBUG) else() - add_compile_options(-O3) - message(STATUS "Configuring Hyprland in Release with CMake") + add_compile_options(-O3) + message(STATUS "Configuring Hyprland in Release with CMake") endif() -include_directories( - . - "src/" - "subprojects/udis86/" - "protocols/") +include_directories(. "src/" "subprojects/udis86/" "protocols/") set(CMAKE_CXX_STANDARD 23) -add_compile_options(-Wall -Wextra -Wno-unused-parameter -Wno-unused-value - -Wno-missing-field-initializers -Wno-narrowing -Wno-pointer-arith - -fmacro-prefix-map=${CMAKE_SOURCE_DIR}/=) +add_compile_options( + -Wall + -Wextra + -Wno-unused-parameter + -Wno-unused-value + -Wno-missing-field-initializers + -Wno-narrowing + -Wno-pointer-arith + -fmacro-prefix-map=${CMAKE_SOURCE_DIR}/=) set(CMAKE_EXECUTABLE_ENABLE_EXPORTS TRUE) set(CMAKE_EXPORT_COMPILE_COMMANDS TRUE) @@ -83,20 +83,39 @@ message(STATUS "Checking deps...") find_package(Threads REQUIRED) if(LEGACY_RENDERER) - set(GLES_VERSION "GLES2") + set(GLES_VERSION "GLES2") else() - set(GLES_VERSION "GLES3") + set(GLES_VERSION "GLES3") endif() find_package(OpenGL REQUIRED COMPONENTS ${GLES_VERSION}) -pkg_check_modules(deps REQUIRED IMPORTED_TARGET - aquamarine - xkbcommon uuid - wayland-server wayland-client wayland-cursor wayland-protocols - cairo pango pangocairo pixman-1 xcursor - libdrm libinput hwdata libseat libdisplay-info libliftoff libudev gbm - hyprlang>=0.3.2 hyprcursor>=0.1.7 hyprutils>=0.2.0 -) +pkg_check_modules( + deps + REQUIRED + IMPORTED_TARGET + aquamarine + xkbcommon + uuid + wayland-server + wayland-client + wayland-cursor + wayland-protocols + cairo + pango + pangocairo + pixman-1 + xcursor + libdrm + libinput + hwdata + libseat + libdisplay-info + libliftoff + libudev + gbm + hyprlang>=0.3.2 + hyprcursor>=0.1.7 + hyprutils>=0.2.0) find_package(hyprwayland-scanner 0.3.10 REQUIRED) @@ -104,8 +123,8 @@ file(GLOB_RECURSE SRCFILES "src/*.cpp") set(TRACY_CPP_FILES "") if(USE_TRACY) - set(TRACY_CPP_FILES "subprojects/tracy/public/TracyClient.cpp") - message(STATUS "Tracy enabled, TRACY_CPP_FILES: " ${TRACY_CPP_FILES}) + set(TRACY_CPP_FILES "subprojects/tracy/public/TracyClient.cpp") + message(STATUS "Tracy enabled, TRACY_CPP_FILES: " ${TRACY_CPP_FILES}) endif() add_executable(Hyprland ${SRCFILES} ${TRACY_CPP_FILES}) @@ -113,75 +132,88 @@ add_executable(Hyprland ${SRCFILES} ${TRACY_CPP_FILES}) set(USE_GPROF ON) if(CMAKE_BUILD_TYPE MATCHES Debug OR CMAKE_BUILD_TYPE MATCHES DEBUG) - message(STATUS "Setting debug flags") + message(STATUS "Setting debug flags") - if (WITH_ASAN) - message(STATUS "Enabling ASan") + if(WITH_ASAN) + message(STATUS "Enabling ASan") - target_link_libraries(Hyprland asan) - target_compile_options(Hyprland PUBLIC -fsanitize=address) + target_link_libraries(Hyprland asan) + target_compile_options(Hyprland PUBLIC -fsanitize=address) + endif() + + if(USE_TRACY) + message(STATUS "Tracy is turned on") + + option(TRACY_ENABLE "" ON) + option(TRACY_ON_DEMAND "" ON) + add_subdirectory(subprojects/tracy) + + target_link_libraries(Hyprland Tracy::TracyClient) + + if(USE_TRACY_GPU) + message(STATUS "Tracy GPU Profiling is turned on") + add_compile_definitions(USE_TRACY_GPU) endif() + endif() - if(USE_TRACY) - message(STATUS "Tracy is turned on") - - option( TRACY_ENABLE "" ON) - option( TRACY_ON_DEMAND "" ON) - add_subdirectory (subprojects/tracy) - - target_link_libraries(Hyprland Tracy::TracyClient) - - if(USE_TRACY_GPU) - message(STATUS "Tracy GPU Profiling is turned on") - add_compile_definitions(USE_TRACY_GPU) - endif() - endif() - - add_compile_options(-fno-pie -fno-builtin) - add_link_options(-no-pie -fno-builtin) - if(USE_GPROF) - add_compile_options(-pg) - add_link_options(-pg) - endif() + add_compile_options(-fno-pie -fno-builtin) + add_link_options(-no-pie -fno-builtin) + if(USE_GPROF) + add_compile_options(-pg) + add_link_options(-pg) + endif() endif() check_include_file("execinfo.h" EXECINFOH) if(EXECINFOH) - message(STATUS "Configuration supports execinfo") - add_compile_definitions(HAS_EXECINFO) + message(STATUS "Configuration supports execinfo") + add_compile_definitions(HAS_EXECINFO) endif() include(CheckLibraryExists) check_library_exists(execinfo backtrace "" HAVE_LIBEXECINFO) if(HAVE_LIBEXECINFO) - target_link_libraries(Hyprland execinfo) + target_link_libraries(Hyprland execinfo) endif() check_include_file("sys/timerfd.h" HAS_TIMERFD) pkg_check_modules(epoll IMPORTED_TARGET epoll-shim) if(NOT HAS_TIMERFD AND epoll_FOUND) - target_link_libraries(Hyprland PkgConfig::epoll) + target_link_libraries(Hyprland PkgConfig::epoll) endif() if(LEGACY_RENDERER) - message(STATUS "Using the legacy GLES2 renderer!") - add_compile_definitions(LEGACY_RENDERER) + message(STATUS "Using the legacy GLES2 renderer!") + add_compile_definitions(LEGACY_RENDERER) endif() if(NO_XWAYLAND) - message(STATUS "Using the NO_XWAYLAND flag, disabling XWayland!") - add_compile_definitions(NO_XWAYLAND) + message(STATUS "Using the NO_XWAYLAND flag, disabling XWayland!") + add_compile_definitions(NO_XWAYLAND) else() - message(STATUS "XWAYLAND Enabled (NO_XWAYLAND not defined) checking deps...") - pkg_check_modules(xdeps REQUIRED IMPORTED_TARGET xcb xwayland xcb-util xcb-render xcb-xfixes xcb-icccm xcb-composite xcb-res xcb-ewmh xcb-errors) - target_link_libraries(Hyprland PkgConfig::xdeps) + message(STATUS "XWAYLAND Enabled (NO_XWAYLAND not defined) checking deps...") + pkg_check_modules( + xdeps + REQUIRED + IMPORTED_TARGET + xcb + xwayland + xcb-util + xcb-render + xcb-xfixes + xcb-icccm + xcb-composite + xcb-res + xcb-ewmh + xcb-errors) + target_link_libraries(Hyprland PkgConfig::xdeps) endif() if(NO_SYSTEMD) - message(STATUS "SYSTEMD support is disabled...") + message(STATUS "SYSTEMD support is disabled...") else() - message(STATUS "SYSTEMD support is requested (NO_SYSTEMD not defined)...") - add_compile_definitions(USES_SYSTEMD) + message(STATUS "SYSTEMD support is requested (NO_SYSTEMD not defined)...") + add_compile_definitions(USES_SYSTEMD) endif() set(CPACK_PROJECT_NAME ${PROJECT_NAME}) @@ -190,7 +222,8 @@ include(CPack) message(STATUS "Setting precompiled headers") -target_precompile_headers(Hyprland PRIVATE $<$:src/pch/pch.hpp>) +target_precompile_headers(Hyprland PRIVATE + $<$:src/pch/pch.hpp>) message(STATUS "Setting link libraries") @@ -200,104 +233,115 @@ target_link_libraries(Hyprland rt PkgConfig::deps) add_custom_target(generate-protocol-headers) function(protocol protoPath protoName external) - if (external) - set(path ${CMAKE_SOURCE_DIR}/${protoPath}) - else() - set(path ${WAYLAND_PROTOCOLS_DIR}/${protoPath}) - endif() + 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}-protocol.h - COMMAND ${WaylandScanner} server-header ${path} protocols/${protoName}-protocol.h - WORKING_DIRECTORY ${CMAKE_SOURCE_DIR} - ) - add_custom_command( - OUTPUT ${CMAKE_SOURCE_DIR}/protocols/${protoName}-protocol.c - COMMAND ${WaylandScanner} private-code ${path} protocols/${protoName}-protocol.c - WORKING_DIRECTORY ${CMAKE_SOURCE_DIR} - ) - target_sources(Hyprland PRIVATE ${CMAKE_SOURCE_DIR}/protocols/${protoName}-protocol.h ${CMAKE_SOURCE_DIR}/protocols/${protoName}-protocol.c) - target_sources(generate-protocol-headers PRIVATE ${CMAKE_SOURCE_DIR}/protocols/${protoName}-protocol.h) + add_custom_command( + OUTPUT ${CMAKE_SOURCE_DIR}/protocols/${protoName}-protocol.h + COMMAND ${WaylandScanner} server-header ${path} + protocols/${protoName}-protocol.h + WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}) + add_custom_command( + OUTPUT ${CMAKE_SOURCE_DIR}/protocols/${protoName}-protocol.c + COMMAND ${WaylandScanner} private-code ${path} + protocols/${protoName}-protocol.c + WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}) + target_sources( + Hyprland PRIVATE ${CMAKE_SOURCE_DIR}/protocols/${protoName}-protocol.h + ${CMAKE_SOURCE_DIR}/protocols/${protoName}-protocol.c) + target_sources(generate-protocol-headers + PRIVATE ${CMAKE_SOURCE_DIR}/protocols/${protoName}-protocol.h) endfunction() -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 ${path}/${protoName}.xml ${CMAKE_SOURCE_DIR}/protocols/ - WORKING_DIRECTORY ${CMAKE_SOURCE_DIR} - ) - target_sources(Hyprland PRIVATE protocols/${protoName}.cpp protocols/${protoName}.hpp) - target_sources(generate-protocol-headers PRIVATE ${CMAKE_SOURCE_DIR}/protocols/${protoName}.hpp) +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 ${path}/${protoName}.xml + ${CMAKE_SOURCE_DIR}/protocols/ + WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}) + target_sources(Hyprland PRIVATE protocols/${protoName}.cpp + protocols/${protoName}.hpp) + target_sources(generate-protocol-headers + PRIVATE ${CMAKE_SOURCE_DIR}/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 ${WAYLAND_SERVER_DIR}/wayland.xml ${CMAKE_SOURCE_DIR}/protocols/ - WORKING_DIRECTORY ${CMAKE_SOURCE_DIR} - ) - target_sources(Hyprland PRIVATE protocols/wayland.cpp protocols/wayland.hpp) - target_sources(generate-protocol-headers PRIVATE ${CMAKE_SOURCE_DIR}/protocols/wayland.hpp) + add_custom_command( + OUTPUT ${CMAKE_SOURCE_DIR}/protocols/wayland.cpp + ${CMAKE_SOURCE_DIR}/protocols/wayland.hpp + COMMAND hyprwayland-scanner --wayland-enums + ${WAYLAND_SERVER_DIR}/wayland.xml ${CMAKE_SOURCE_DIR}/protocols/ + WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}) + target_sources(Hyprland PRIVATE protocols/wayland.cpp protocols/wayland.hpp) + target_sources(generate-protocol-headers + PRIVATE ${CMAKE_SOURCE_DIR}/protocols/wayland.hpp) endfunction() -target_link_libraries(Hyprland - OpenGL::EGL - OpenGL::GL - Threads::Threads - libudis86 - uuid -) +target_link_libraries(Hyprland OpenGL::EGL OpenGL::GL Threads::Threads + libudis86 uuid) -protocol("protocols/wlr-screencopy-unstable-v1.xml" "wlr-screencopy-unstable-v1" true) -protocol("subprojects/hyprland-protocols/protocols/hyprland-global-shortcuts-v1.xml" "hyprland-global-shortcuts-v1" true) -protocol("subprojects/hyprland-protocols/protocols/hyprland-toplevel-export-v1.xml" "hyprland-toplevel-export-v1" true) -protocol("unstable/text-input/text-input-unstable-v1.xml" "text-input-unstable-v1" false) +protocol("protocols/wlr-screencopy-unstable-v1.xml" + "wlr-screencopy-unstable-v1" true) +protocol( + "subprojects/hyprland-protocols/protocols/hyprland-global-shortcuts-v1.xml" + "hyprland-global-shortcuts-v1" true) +protocol( + "subprojects/hyprland-protocols/protocols/hyprland-toplevel-export-v1.xml" + "hyprland-toplevel-export-v1" true) +protocol("unstable/text-input/text-input-unstable-v1.xml" + "text-input-unstable-v1" false) -protocolNew("protocols" "wlr-gamma-control-unstable-v1" true) -protocolNew("protocols" "wlr-foreign-toplevel-management-unstable-v1" true) -protocolNew("protocols" "wlr-output-power-management-unstable-v1" true) -protocolNew("protocols" "virtual-keyboard-unstable-v1" true) -protocolNew("protocols" "wlr-virtual-pointer-unstable-v1" true) -protocolNew("protocols" "input-method-unstable-v2" true) -protocolNew("protocols" "wlr-output-management-unstable-v1" true) -protocolNew("protocols" "kde-server-decoration" true) -protocolNew("protocols" "wlr-data-control-unstable-v1" true) -protocolNew("subprojects/hyprland-protocols/protocols" "hyprland-focus-grab-v1" true) -protocolNew("protocols" "wlr-layer-shell-unstable-v1" true) -protocolNew("protocols" "wayland-drm" true) -protocolNew("staging/tearing-control" "tearing-control-v1" false) -protocolNew("staging/fractional-scale" "fractional-scale-v1" false) -protocolNew("unstable/xdg-output" "xdg-output-unstable-v1" false) -protocolNew("staging/cursor-shape" "cursor-shape-v1" false) -protocolNew("unstable/idle-inhibit" "idle-inhibit-unstable-v1" false) -protocolNew("unstable/relative-pointer" "relative-pointer-unstable-v1" false) -protocolNew("unstable/xdg-decoration" "xdg-decoration-unstable-v1" false) -protocolNew("staging/alpha-modifier" "alpha-modifier-v1" false) -protocolNew("staging/ext-foreign-toplevel-list" "ext-foreign-toplevel-list-v1" false) -protocolNew("unstable/pointer-gestures" "pointer-gestures-unstable-v1" false) -protocolNew("unstable/keyboard-shortcuts-inhibit" "keyboard-shortcuts-inhibit-unstable-v1" false) -protocolNew("unstable/text-input" "text-input-unstable-v3" false) -protocolNew("unstable/pointer-constraints" "pointer-constraints-unstable-v1" false) -protocolNew("staging/xdg-activation" "xdg-activation-v1" false) -protocolNew("staging/ext-idle-notify" "ext-idle-notify-v1" false) -protocolNew("staging/ext-session-lock" "ext-session-lock-v1" false) -protocolNew("stable/tablet" "tablet-v2" false) -protocolNew("stable/presentation-time" "presentation-time" false) -protocolNew("stable/xdg-shell" "xdg-shell" false) -protocolNew("unstable/primary-selection" "primary-selection-unstable-v1" false) -protocolNew("staging/xwayland-shell" "xwayland-shell-v1" false) -protocolNew("stable/viewporter" "viewporter" false) -protocolNew("stable/linux-dmabuf" "linux-dmabuf-v1" false) -protocolNew("staging/drm-lease" "drm-lease-v1" false) -protocolNew("staging/linux-drm-syncobj" "linux-drm-syncobj-v1" false) +protocolnew("protocols" "wlr-gamma-control-unstable-v1" true) +protocolnew("protocols" "wlr-foreign-toplevel-management-unstable-v1" true) +protocolnew("protocols" "wlr-output-power-management-unstable-v1" true) +protocolnew("protocols" "virtual-keyboard-unstable-v1" true) +protocolnew("protocols" "wlr-virtual-pointer-unstable-v1" true) +protocolnew("protocols" "input-method-unstable-v2" true) +protocolnew("protocols" "wlr-output-management-unstable-v1" true) +protocolnew("protocols" "kde-server-decoration" true) +protocolnew("protocols" "wlr-data-control-unstable-v1" true) +protocolnew("subprojects/hyprland-protocols/protocols" "hyprland-focus-grab-v1" + true) +protocolnew("protocols" "wlr-layer-shell-unstable-v1" true) +protocolnew("protocols" "wayland-drm" true) +protocolnew("staging/tearing-control" "tearing-control-v1" false) +protocolnew("staging/fractional-scale" "fractional-scale-v1" false) +protocolnew("unstable/xdg-output" "xdg-output-unstable-v1" false) +protocolnew("staging/cursor-shape" "cursor-shape-v1" false) +protocolnew("unstable/idle-inhibit" "idle-inhibit-unstable-v1" false) +protocolnew("unstable/relative-pointer" "relative-pointer-unstable-v1" false) +protocolnew("unstable/xdg-decoration" "xdg-decoration-unstable-v1" false) +protocolnew("staging/alpha-modifier" "alpha-modifier-v1" false) +protocolnew("staging/ext-foreign-toplevel-list" "ext-foreign-toplevel-list-v1" + false) +protocolnew("unstable/pointer-gestures" "pointer-gestures-unstable-v1" false) +protocolnew("unstable/keyboard-shortcuts-inhibit" + "keyboard-shortcuts-inhibit-unstable-v1" false) +protocolnew("unstable/text-input" "text-input-unstable-v3" false) +protocolnew("unstable/pointer-constraints" "pointer-constraints-unstable-v1" + false) +protocolnew("staging/xdg-activation" "xdg-activation-v1" false) +protocolnew("staging/ext-idle-notify" "ext-idle-notify-v1" false) +protocolnew("staging/ext-session-lock" "ext-session-lock-v1" false) +protocolnew("stable/tablet" "tablet-v2" false) +protocolnew("stable/presentation-time" "presentation-time" false) +protocolnew("stable/xdg-shell" "xdg-shell" false) +protocolnew("unstable/primary-selection" "primary-selection-unstable-v1" false) +protocolnew("staging/xwayland-shell" "xwayland-shell-v1" false) +protocolnew("stable/viewporter" "viewporter" false) +protocolnew("stable/linux-dmabuf" "linux-dmabuf-v1" false) +protocolnew("staging/drm-lease" "drm-lease-v1" false) +protocolnew("staging/linux-drm-syncobj" "linux-drm-syncobj-v1" false) -protocolWayland() +protocolwayland() # tools add_subdirectory(hyprctl) @@ -306,12 +350,12 @@ add_subdirectory(hyprpm) # binary and symlink install(TARGETS Hyprland) -install(CODE "execute_process( \ +install( + CODE "execute_process( \ COMMAND ${CMAKE_COMMAND} -E create_symlink \ ${CMAKE_INSTALL_FULL_BINDIR}/Hyprland \ ${CMAKE_INSTALL_FULL_BINDIR}/hyprland - )" -) + )") # session file install(FILES ${CMAKE_SOURCE_DIR}/example/hyprland.desktop @@ -319,8 +363,7 @@ install(FILES ${CMAKE_SOURCE_DIR}/example/hyprland.desktop # wallpapers file(GLOB_RECURSE WALLPAPERS "assets/wall*") -install(FILES ${WALLPAPERS} - DESTINATION ${CMAKE_INSTALL_DATADIR}/hyprland) +install(FILES ${WALLPAPERS} DESTINATION ${CMAKE_INSTALL_DATADIR}/hyprland) # default config install(FILES ${CMAKE_SOURCE_DIR}/example/hyprland.conf @@ -332,9 +375,7 @@ install(FILES ${CMAKE_SOURCE_DIR}/assets/hyprland-portals.conf # man pages file(GLOB_RECURSE MANPAGES "docs/*.1") -install(FILES ${MANPAGES} - DESTINATION ${CMAKE_INSTALL_MANDIR}/man1) - +install(FILES ${MANPAGES} DESTINATION ${CMAKE_INSTALL_MANDIR}/man1) # pkgconfig entry install(FILES ${CMAKE_BINARY_DIR}/hyprland.pc @@ -342,12 +383,16 @@ install(FILES ${CMAKE_BINARY_DIR}/hyprland.pc # protocol headers set(HEADERS_PROTO "${CMAKE_CURRENT_SOURCE_DIR}/protocols") -install(DIRECTORY ${HEADERS_PROTO} - DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/hyprland - FILES_MATCHING PATTERN "*.h*") +install( + DIRECTORY ${HEADERS_PROTO} + DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/hyprland + FILES_MATCHING + PATTERN "*.h*") # hyprland headers set(HEADERS_SRC "${CMAKE_CURRENT_SOURCE_DIR}/src") -install(DIRECTORY ${HEADERS_SRC} - DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/hyprland - FILES_MATCHING PATTERN "*.h*") +install( + DIRECTORY ${HEADERS_SRC} + DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/hyprland + FILES_MATCHING + PATTERN "*.h*") From e6fc9873b5e10e7ac00085da7d599776ed72f297 Mon Sep 17 00:00:00 2001 From: Mihai Fufezan Date: Sun, 21 Jul 2024 19:31:36 +0300 Subject: [PATCH 0126/2181] flake.lock: update --- flake.lock | 36 ++++++++++++++++++------------------ 1 file changed, 18 insertions(+), 18 deletions(-) diff --git a/flake.lock b/flake.lock index b2cc9703..f61f18a1 100644 --- a/flake.lock +++ b/flake.lock @@ -16,11 +16,11 @@ ] }, "locked": { - "lastModified": 1721487522, - "narHash": "sha256-aF3uwUwUK2CgbItoMe3IJF0yidIEWcDx47AiH5y8VKk=", + "lastModified": 1721571743, + "narHash": "sha256-hat7wggtDISBJD8kTo5MTrT+IsY/Ha2MwgjmqqijoCA=", "owner": "hyprwm", "repo": "aquamarine", - "rev": "acfea3bd1d9e756c7152e639240d52c6628844b0", + "rev": "601f6cf95cbe4fef02dc7faf34bba58566c914e9", "type": "github" }, "original": { @@ -42,11 +42,11 @@ ] }, "locked": { - "lastModified": 1720108799, - "narHash": "sha256-AxRkTJlbB8r7aG6gvc7IaLhc2T9TO4/8uqanKRxukBQ=", + "lastModified": 1721330371, + "narHash": "sha256-aYlHTWylczLt6ERJyg6E66Y/XSCbVL7leVcRuJmVbpI=", "owner": "hyprwm", "repo": "hyprcursor", - "rev": "a5c0d57325c5f0814c39110a70ca19c070ae9486", + "rev": "4493a972b48f9c3014befbbf381ed5fff91a65dc", "type": "github" }, "original": { @@ -93,11 +93,11 @@ ] }, "locked": { - "lastModified": 1720381373, - "narHash": "sha256-lyC/EZdHULsaAKVryK11lgHY9u6pXr7qR4irnxNWC7k=", + "lastModified": 1721324361, + "narHash": "sha256-BiJKO0IIdnSwHQBSrEJlKlFr753urkLE48wtt0UhNG4=", "owner": "hyprwm", "repo": "hyprlang", - "rev": "5df0174fd09de4ac5475233d65ffc703e89b82eb", + "rev": "adbefbf49664a6c2c8bf36b6487fd31e3eb68086", "type": "github" }, "original": { @@ -116,11 +116,11 @@ ] }, "locked": { - "lastModified": 1721071737, - "narHash": "sha256-qmC9jGfbE4+EIBbbSAkrfR/p49wShjpv4/KztgE/P54=", + "lastModified": 1721324102, + "narHash": "sha256-WAZ0X6yJW1hFG6otkHBfyJDKRpNP5stsRqdEuHrFRpk=", "owner": "hyprwm", "repo": "hyprutils", - "rev": "eb1ceff2b87f6820789249f63faa8e9dcb54d05f", + "rev": "962582a090bc233c4de9d9897f46794280288989", "type": "github" }, "original": { @@ -139,11 +139,11 @@ ] }, "locked": { - "lastModified": 1720215857, - "narHash": "sha256-JPdL+Qul+jEueAn8CARfcWP83eJgwkhMejQYfDvrgvU=", + "lastModified": 1721324119, + "narHash": "sha256-SOOqIT27/X792+vsLSeFdrNTF+OSRp5qXv6Te+fb2Qg=", "owner": "hyprwm", "repo": "hyprwayland-scanner", - "rev": "d5fa094ca27e0039be5e94c0a80ae433145af8bb", + "rev": "a048a6cb015340bd82f97c1f40a4b595ca85cc30", "type": "github" }, "original": { @@ -154,11 +154,11 @@ }, "nixpkgs": { "locked": { - "lastModified": 1720957393, - "narHash": "sha256-oedh2RwpjEa+TNxhg5Je9Ch6d3W1NKi7DbRO1ziHemA=", + "lastModified": 1721379653, + "narHash": "sha256-8MUgifkJ7lkZs3u99UDZMB4kbOxvMEXQZ31FO3SopZ0=", "owner": "NixOS", "repo": "nixpkgs", - "rev": "693bc46d169f5af9c992095736e82c3488bf7dbb", + "rev": "1d9c2c9b3e71b9ee663d11c5d298727dace8d374", "type": "github" }, "original": { From 3b6bcd6ddcfebd1fed0694aa2c0bd9753f4d5d46 Mon Sep 17 00:00:00 2001 From: Vaxry Date: Sun, 21 Jul 2024 19:25:01 +0200 Subject: [PATCH 0127/2181] presentation-feedback: fix invalid values sent after aq merge --- src/protocols/PresentationTime.cpp | 10 +++++++++- src/protocols/core/Compositor.cpp | 2 +- 2 files changed, 10 insertions(+), 2 deletions(-) diff --git a/src/protocols/PresentationTime.cpp b/src/protocols/PresentationTime.cpp index e9472fc3..a2fc270c 100644 --- a/src/protocols/PresentationTime.cpp +++ b/src/protocols/PresentationTime.cpp @@ -60,7 +60,7 @@ void CPresentationFeedback::sendQueued(SP data, timespe if (reportedFlags & Aquamarine::IOutput::AQ_OUTPUT_PRESENT_HW_COMPLETION) flags |= WP_PRESENTATION_FEEDBACK_KIND_HW_COMPLETION; - if (data->wasPresented && when) + if (data->wasPresented) resource->sendPresented((uint32_t)(when->tv_sec >> 32), (uint32_t)(when->tv_sec & 0xFFFFFFFF), (uint32_t)(when->tv_nsec), untilRefreshNs, (uint32_t)(seq >> 32), (uint32_t)(seq & 0xFFFFFFFF), (wpPresentationFeedbackKind)flags); else @@ -104,6 +104,14 @@ void CPresentationProtocol::onGetFeedback(CWpPresentation* pMgr, wl_resource* su } void CPresentationProtocol::onPresented(CMonitor* pMonitor, timespec* when, uint32_t untilRefreshNs, uint64_t seq, uint32_t reportedFlags) { + timespec now; + timespec* presentedAt = when; + if (!presentedAt) { + // just put the current time, we don't have anything better + clock_gettime(CLOCK_MONOTONIC, &now); + when = &now; + } + for (auto& feedback : m_vFeedbacks) { if (!feedback->surface) continue; diff --git a/src/protocols/core/Compositor.cpp b/src/protocols/core/Compositor.cpp index 5cd6005a..d11ba40c 100644 --- a/src/protocols/core/Compositor.cpp +++ b/src/protocols/core/Compositor.cpp @@ -463,7 +463,7 @@ void CWLSurfaceResource::presentFeedback(timespec* when, CMonitor* pMonitor, boo frame(when); auto FEEDBACK = makeShared(self.lock()); FEEDBACK->attachMonitor(pMonitor); - FEEDBACK->discarded(); + FEEDBACK->presented(); PROTO::presentation->queueData(FEEDBACK); if (!pMonitor || !pMonitor->outTimeline || !syncobj || !needsExplicitSync) From cbaac6deafb857662d630efbca8b0ebac0f11b44 Mon Sep 17 00:00:00 2001 From: Vaxry Date: Sun, 21 Jul 2024 20:02:48 +0200 Subject: [PATCH 0128/2181] xwm: drop invalid case for clearing X focus fixes #6955 --- src/xwayland/XWM.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/xwayland/XWM.cpp b/src/xwayland/XWM.cpp index 0eaa16be..81c59cc2 100644 --- a/src/xwayland/XWM.cpp +++ b/src/xwayland/XWM.cpp @@ -879,7 +879,7 @@ void CXWM::activateSurface(SP surf, bool activate) { if ((surf == focusedSurface && activate) || (surf && surf->overrideRedirect)) return; - if (!surf || (!activate || !surf->overrideRedirect /* if we are focusing on an OR child, don't unfocus parent */)) { + if (!surf) { setActiveWindow((uint32_t)XCB_WINDOW_NONE); focusWindow(nullptr); } else { From 341fb4497fc6b5e6097361c2820a4cd4d1c6ccab Mon Sep 17 00:00:00 2001 From: Vaxry Date: Sun, 21 Jul 2024 22:05:53 +0200 Subject: [PATCH 0129/2181] wayland/compositor: fixup buffer damage tracking for wl_shm buffers remove qt hack, fixup conditions fixes #6844 --- src/protocols/core/Compositor.cpp | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/src/protocols/core/Compositor.cpp b/src/protocols/core/Compositor.cpp index d11ba40c..12647811 100644 --- a/src/protocols/core/Compositor.cpp +++ b/src/protocols/core/Compositor.cpp @@ -84,7 +84,7 @@ CWLSurfaceResource::CWLSurfaceResource(SP resource_) : resource(reso Vector2D oldBufSize = current.buffer ? current.buffer->size : Vector2D{}; Vector2D newBufSize = pending.buffer ? pending.buffer->size : Vector2D{}; - if (oldBufSize != newBufSize) + if (oldBufSize != newBufSize || current.buffer != pending.buffer) pending.bufferDamage = CBox{{}, {INT32_MAX, INT32_MAX}}; bufferReleased = false; @@ -407,10 +407,7 @@ void CWLSurfaceResource::commitPendingState() { pending.bufferDamage.clear(); if (current.buffer && !bufferReleased) { - // without previous dolphin et al are weird vvv - //CRegion surfaceDamage = - // current.damage.copy().scale(current.scale).transform(current.transform, current.size.x, current.size.y).add(current.bufferDamage).add(previousBufferDamage); - current.buffer->update(CBox{{}, {INT32_MAX, INT32_MAX}}); // FIXME: figure this out to not use this hack. QT apps are wonky without this. + current.buffer->update(accumulateCurrentBufferDamage()); // release the buffer if it's synchronous as update() has done everything thats needed // so we can let the app know we're done. From 33e933e2a020c874037df568d6c033ae20f30bf7 Mon Sep 17 00:00:00 2001 From: Vaxry Date: Sun, 21 Jul 2024 22:09:29 +0200 Subject: [PATCH 0130/2181] renderer: drop redundant spammy trace log --- src/render/Renderer.cpp | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/src/render/Renderer.cpp b/src/render/Renderer.cpp index 82dfc887..724bd69c 100644 --- a/src/render/Renderer.cpp +++ b/src/render/Renderer.cpp @@ -236,10 +236,8 @@ static void renderSurface(SP surface, int x, int y, void* da g_pHyprOpenGL->renderTexture(TEXTURE, &windowBox, ALPHA, rounding, false, true); } - if (!g_pHyprRenderer->m_bBlockSurfaceFeedback) { - Debug::log(TRACE, "presentFeedback for visible surface"); + if (!g_pHyprRenderer->m_bBlockSurfaceFeedback) surface->presentFeedback(RDATA->when, RDATA->pMonitor); - } g_pHyprOpenGL->blend(true); From 672bf1f8670b200da57e2f6de4e9ed7efd8c98fc Mon Sep 17 00:00:00 2001 From: Vaxry Date: Sun, 21 Jul 2024 23:25:20 +0200 Subject: [PATCH 0131/2181] compositor: ignore setting surface scanout if DS is disabled --- src/Compositor.cpp | 6 +++++- src/render/Renderer.cpp | 2 +- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/src/Compositor.cpp b/src/Compositor.cpp index c7a0cfb1..02ca5363 100644 --- a/src/Compositor.cpp +++ b/src/Compositor.cpp @@ -2285,6 +2285,8 @@ void CCompositor::updateFullscreenFadeOnWorkspace(PHLWORKSPACE pWorkspace) { } void CCompositor::setWindowFullscreen(PHLWINDOW pWindow, bool on, eFullscreenMode mode) { + static auto PNODIRECTSCANOUT = CConfigValue("misc:no_direct_scanout"); + if (!validMapped(pWindow) || g_pCompositor->m_bUnsafeState) return; @@ -2333,7 +2335,9 @@ void CCompositor::setWindowFullscreen(PHLWINDOW pWindow, bool on, eFullscreenMod return; // send a scanout tranche if we are entering fullscreen, and send a regular one if we aren't. - g_pHyprRenderer->setSurfaceScanoutMode(pWindow->m_pWLSurface->resource(), on ? PMONITOR->self.lock() : nullptr); + // ignore if DS is disabled. + if (!*PNODIRECTSCANOUT) + g_pHyprRenderer->setSurfaceScanoutMode(pWindow->m_pWLSurface->resource(), on ? PMONITOR->self.lock() : nullptr); g_pConfigManager->ensureVRR(PMONITOR); } diff --git a/src/render/Renderer.cpp b/src/render/Renderer.cpp index 724bd69c..84d607b8 100644 --- a/src/render/Renderer.cpp +++ b/src/render/Renderer.cpp @@ -236,7 +236,7 @@ static void renderSurface(SP surface, int x, int y, void* da g_pHyprOpenGL->renderTexture(TEXTURE, &windowBox, ALPHA, rounding, false, true); } - if (!g_pHyprRenderer->m_bBlockSurfaceFeedback) + if (!g_pHyprRenderer->m_bBlockSurfaceFeedback) surface->presentFeedback(RDATA->when, RDATA->pMonitor); g_pHyprOpenGL->blend(true); From 5979ceb56b165ee35809a0eeda5f4be1aedbb7b6 Mon Sep 17 00:00:00 2001 From: Vaxry Date: Mon, 22 Jul 2024 12:37:54 +0200 Subject: [PATCH 0132/2181] surface: fixup logical damage size calculations fixes #6618 --- src/desktop/WLSurface.cpp | 41 +++++++++++++++++++++++++++------------ src/desktop/WLSurface.hpp | 21 ++++++++++---------- src/render/Renderer.cpp | 2 +- 3 files changed, 41 insertions(+), 23 deletions(-) diff --git a/src/desktop/WLSurface.cpp b/src/desktop/WLSurface.cpp index 97335d27..a7a2e5aa 100644 --- a/src/desktop/WLSurface.cpp +++ b/src/desktop/WLSurface.cpp @@ -74,6 +74,16 @@ Vector2D CWLSurface::correctSmallVec() const { return Vector2D{(O->m_vReportedSize.x - SIZE.x) / 2, (O->m_vReportedSize.y - SIZE.y) / 2}.clamp({}, {INFINITY, INFINITY}) * (O->m_vRealSize.value() / O->m_vReportedSize); } +Vector2D CWLSurface::correctSmallVecBuf() const { + if (!exists() || !small() || m_bFillIgnoreSmall || !m_pResource->current.buffer) + return {}; + + const auto SIZE = getViewporterCorrectedSize(); + const auto BS = m_pResource->current.buffer->size; + + return Vector2D{(BS.x - SIZE.x) / 2, (BS.y - SIZE.y) / 2}.clamp({}, {INFINITY, INFINITY}); +} + Vector2D CWLSurface::getViewporterCorrectedSize() const { if (!exists() || !m_pResource->current.buffer) return {}; @@ -81,16 +91,15 @@ Vector2D CWLSurface::getViewporterCorrectedSize() const { return m_pResource->current.viewport.hasDestination ? m_pResource->current.viewport.destination : m_pResource->current.buffer->size; } -CRegion CWLSurface::logicalDamage() const { +CRegion CWLSurface::computeDamage() const { if (!m_pResource->current.buffer) return {}; CRegion damage = m_pResource->accumulateCurrentBufferDamage(); damage.transform(wlTransformToHyprutils(m_pResource->current.transform), m_pResource->current.buffer->size.x, m_pResource->current.buffer->size.y); - damage.scale(1.0 / m_pResource->current.scale); - const auto VPSIZE = getViewporterCorrectedSize(); - const auto CORRECTVEC = correctSmallVec(); + const auto BUFSIZE = m_pResource->current.buffer->size; + const auto CORRECTVEC = correctSmallVecBuf(); if (m_pResource->current.viewport.hasSource) damage.intersect(m_pResource->current.viewport.source); @@ -98,9 +107,17 @@ CRegion CWLSurface::logicalDamage() const { const auto SCALEDSRCSIZE = m_pResource->current.viewport.hasSource ? m_pResource->current.viewport.source.size() * m_pResource->current.scale : m_pResource->current.buffer->size; - damage.scale({VPSIZE.x / SCALEDSRCSIZE.x, VPSIZE.y / SCALEDSRCSIZE.y}); + damage.scale({BUFSIZE.x / SCALEDSRCSIZE.x, BUFSIZE.y / SCALEDSRCSIZE.y}); damage.translate(CORRECTVEC); + // go from buffer coords in the damage to hl logical + + const auto BOX = getSurfaceBoxGlobal(); + const Vector2D SCALE = BOX.has_value() ? BOX->size() / m_pResource->current.buffer->size : + Vector2D{1.0 / m_pResource->current.scale, 1.0 / m_pResource->current.scale /* Wrong... but we can't really do better */}; + + damage.scale(SCALE); + return damage; } @@ -141,27 +158,27 @@ void CWLSurface::init() { Debug::log(LOG, "CWLSurface {:x} called init()", (uintptr_t)this); } -PHLWINDOW CWLSurface::getWindow() { +PHLWINDOW CWLSurface::getWindow() const { return m_pWindowOwner.lock(); } -PHLLS CWLSurface::getLayer() { +PHLLS CWLSurface::getLayer() const { return m_pLayerOwner.lock(); } -CPopup* CWLSurface::getPopup() { +CPopup* CWLSurface::getPopup() const { return m_pPopupOwner; } -CSubsurface* CWLSurface::getSubsurface() { +CSubsurface* CWLSurface::getSubsurface() const { return m_pSubsurfaceOwner; } -bool CWLSurface::desktopComponent() { +bool CWLSurface::desktopComponent() const { return !m_pLayerOwner.expired() || !m_pWindowOwner.expired() || m_pSubsurfaceOwner || m_pPopupOwner; } -std::optional CWLSurface::getSurfaceBoxGlobal() { +std::optional CWLSurface::getSurfaceBoxGlobal() const { if (!desktopComponent()) return {}; @@ -181,7 +198,7 @@ void CWLSurface::appendConstraint(WP constraint) { m_pConstraint = constraint; } -SP CWLSurface::constraint() { +SP CWLSurface::constraint() const { return m_pConstraint.lock(); } diff --git a/src/desktop/WLSurface.hpp b/src/desktop/WLSurface.hpp index 447f4582..bb476e0f 100644 --- a/src/desktop/WLSurface.hpp +++ b/src/desktop/WLSurface.hpp @@ -33,22 +33,23 @@ class CWLSurface { SP resource() const; bool exists() const; - bool small() const; // means surface is smaller than the requested size - Vector2D correctSmallVec() const; // returns a corrective vector for small() surfaces + bool small() const; // means surface is smaller than the requested size + Vector2D correctSmallVec() const; // returns a corrective vector for small() surfaces + Vector2D correctSmallVecBuf() const; // returns a corrective vector for small() surfaces, in BL coords Vector2D getViewporterCorrectedSize() const; - CRegion logicalDamage() const; + CRegion computeDamage() const; // logical coordinates. May be wrong if the surface is unassigned bool visible(); // getters for owners. - PHLWINDOW getWindow(); - PHLLS getLayer(); - CPopup* getPopup(); - CSubsurface* getSubsurface(); + PHLWINDOW getWindow() const; + PHLLS getLayer() const; + CPopup* getPopup() const; + CSubsurface* getSubsurface() const; // desktop components misc utils - std::optional getSurfaceBoxGlobal(); + std::optional getSurfaceBoxGlobal() const; void appendConstraint(WP constraint); - SP constraint(); + SP constraint() const; // allow stretching. Useful for plugins. bool m_bFillIgnoreSmall = false; @@ -107,7 +108,7 @@ class CWLSurface { void destroy(); void init(); - bool desktopComponent(); + bool desktopComponent() const; struct { CHyprSignalListener destroy; diff --git a/src/render/Renderer.cpp b/src/render/Renderer.cpp index 84d607b8..835fed91 100644 --- a/src/render/Renderer.cpp +++ b/src/render/Renderer.cpp @@ -1693,7 +1693,7 @@ void CHyprRenderer::damageSurface(SP pSurface, double x, dou return; const auto WLSURF = CWLSurface::fromResource(pSurface); - CRegion damageBox = WLSURF ? WLSURF->logicalDamage() : CRegion{}; + CRegion damageBox = WLSURF ? WLSURF->computeDamage() : CRegion{}; if (!WLSURF) { Debug::log(ERR, "BUG THIS: No CWLSurface for surface in damageSurface!!!"); return; From 1797319a0785cf9ae4f406d40bc27b032c6f5fb2 Mon Sep 17 00:00:00 2001 From: Vaxry Date: Mon, 22 Jul 2024 13:01:55 +0200 Subject: [PATCH 0133/2181] renderer: untransform textures matching display transform fixes #6754 This will break if the client uses a transform that is not equal to the display, reverting to old behavior. Combining transforms is left as a todo for the future. --- src/protocols/core/Compositor.cpp | 3 +++ src/render/OpenGL.cpp | 10 +++++++--- src/render/Texture.hpp | 13 ++++++++----- 3 files changed, 18 insertions(+), 8 deletions(-) diff --git a/src/protocols/core/Compositor.cpp b/src/protocols/core/Compositor.cpp index 12647811..f1c83531 100644 --- a/src/protocols/core/Compositor.cpp +++ b/src/protocols/core/Compositor.cpp @@ -406,6 +406,9 @@ void CWLSurfaceResource::commitPendingState() { pending.damage.clear(); pending.bufferDamage.clear(); + if (current.buffer && current.buffer->texture) + current.buffer->texture->m_eTransform = wlTransformToHyprutils(current.transform); + if (current.buffer && !bufferReleased) { current.buffer->update(accumulateCurrentBufferDamage()); diff --git a/src/render/OpenGL.cpp b/src/render/OpenGL.cpp index b2b046ce..fef69f7c 100644 --- a/src/render/OpenGL.cpp +++ b/src/render/OpenGL.cpp @@ -1277,9 +1277,13 @@ void CHyprOpenGLImpl::renderTextureInternalWithDamage(SP tex, CBox* pB static auto PDIMINACTIVE = CConfigValue("decoration:dim_inactive"); static auto PDT = CConfigValue("debug:damage_tracking"); - // get transform - const auto TRANSFORM = wlTransformToHyprutils(invertTransform(!m_bEndFrame ? WL_OUTPUT_TRANSFORM_NORMAL : m_RenderData.pMonitor->transform)); - float matrix[9]; + // get the needed transform for this texture + const bool TRANSFORMS_MATCH = wlTransformToHyprutils(m_RenderData.pMonitor->transform) == tex->m_eTransform; // FIXME: combine them properly!!! + eTransform TRANSFORM = HYPRUTILS_TRANSFORM_NORMAL; + if (m_bEndFrame || TRANSFORMS_MATCH) + TRANSFORM = wlTransformToHyprutils(invertTransform(m_RenderData.pMonitor->transform)); + + float matrix[9]; projectBox(matrix, newBox, TRANSFORM, newBox.rot, m_RenderData.monitorProjection.data()); float glMatrix[9]; diff --git a/src/render/Texture.hpp b/src/render/Texture.hpp index 0da95300..a54be8c5 100644 --- a/src/render/Texture.hpp +++ b/src/render/Texture.hpp @@ -2,9 +2,11 @@ #include "../defines.hpp" #include +#include class IHLBuffer; HYPRUTILS_FORWARD(Math, CRegion); +using namespace Hyprutils::Math; enum TEXTURETYPE { TEXTURE_INVALID, // Invalid @@ -33,11 +35,12 @@ class CTexture { void allocate(); void update(uint32_t drmFormat, uint8_t* pixels, uint32_t stride, const CRegion& damage); - TEXTURETYPE m_iType = TEXTURE_RGBA; - GLenum m_iTarget = GL_TEXTURE_2D; - GLuint m_iTexID = 0; - Vector2D m_vSize; - void* m_pEglImage = nullptr; + TEXTURETYPE m_iType = TEXTURE_RGBA; + GLenum m_iTarget = GL_TEXTURE_2D; + GLuint m_iTexID = 0; + Vector2D m_vSize = {}; + void* m_pEglImage = nullptr; + eTransform m_eTransform = HYPRUTILS_TRANSFORM_NORMAL; private: void createFromShm(uint32_t drmFormat, uint8_t* pixels, uint32_t stride, const Vector2D& size); From 3132f0275e78bdf1a78aee4ccd2944e9e5ba95bd Mon Sep 17 00:00:00 2001 From: Vaxry Date: Mon, 22 Jul 2024 13:05:06 +0200 Subject: [PATCH 0134/2181] touch: set lastInputTouch on every event --- src/managers/input/Touch.cpp | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/src/managers/input/Touch.cpp b/src/managers/input/Touch.cpp index 736a2ae5..7863140b 100644 --- a/src/managers/input/Touch.cpp +++ b/src/managers/input/Touch.cpp @@ -6,6 +6,8 @@ #include "../SeatManager.hpp" void CInputManager::onTouchDown(ITouch::SDownEvent e) { + m_bLastInputTouch = true; + static auto PSWIPETOUCH = CConfigValue("gestures:workspace_swipe_touch"); static auto PGAPSOUTDATA = CConfigValue("general:gaps_out"); auto* const PGAPSOUT = (CCssGapData*)(PGAPSOUTDATA.ptr())->getData(); @@ -54,8 +56,6 @@ void CInputManager::onTouchDown(ITouch::SDownEvent e) { } } - m_bLastInputTouch = true; - m_sTouchData.touchFocusWindow = m_pFoundWindowToFocus; m_sTouchData.touchFocusSurface = m_pFoundSurfaceToFocus; m_sTouchData.touchFocusLS = m_pFoundLSToFocus; @@ -83,6 +83,8 @@ void CInputManager::onTouchDown(ITouch::SDownEvent e) { } void CInputManager::onTouchUp(ITouch::SUpEvent e) { + m_bLastInputTouch = true; + EMIT_HOOK_EVENT_CANCELLABLE("touchUp", e); if (m_sActiveSwipe.pWorkspaceBegin) { // If there was a swipe from this finger, end it. @@ -96,6 +98,8 @@ void CInputManager::onTouchUp(ITouch::SUpEvent e) { } void CInputManager::onTouchMove(ITouch::SMotionEvent e) { + m_bLastInputTouch = true; + EMIT_HOOK_EVENT_CANCELLABLE("touchMove", e); if (m_sActiveSwipe.pWorkspaceBegin) { // Do nothing if this is using a different finger. From 511e9ccdd199a90a7378fae1f950de6a315cc406 Mon Sep 17 00:00:00 2001 From: UjinT34 <41110182+UjinT34@users.noreply.github.com> Date: Mon, 22 Jul 2024 14:15:40 +0300 Subject: [PATCH 0135/2181] xwm: Fix xwayland black window bug after losing focus (#6966) * fix xwayland black window bug * resend normal state --- src/xwayland/XWM.cpp | 22 +++++++++++++++++++++- src/xwayland/XWM.hpp | 1 + 2 files changed, 22 insertions(+), 1 deletion(-) diff --git a/src/xwayland/XWM.cpp b/src/xwayland/XWM.cpp index 81c59cc2..bb69afda 100644 --- a/src/xwayland/XWM.cpp +++ b/src/xwayland/XWM.cpp @@ -378,6 +378,20 @@ void CXWM::handleFocusIn(xcb_focus_in_event_t* e) { focusWindow(focusedSurface.lock()); } +void CXWM::handleFocusOut(xcb_focus_out_event_t* e) { + Debug::log(TRACE, "[xwm] focusOut mode={}, detail={}, event={}", e->mode, e->detail, e->event); + + const auto XSURF = windowForXID(e->event); + + if (!XSURF) + return; + + Debug::log(TRACE, "[xwm] focusOut for {} {} {} surface {}", XSURF->mapped ? "mapped" : "unmapped", XSURF->fullscreen ? "fullscreen" : "windowed", + XSURF == focusedSurface ? "focused" : "unfocused", XSURF->state.title); + + // do something? +} + void CXWM::sendWMMessage(SP surf, xcb_client_message_data_t* data, uint32_t mask) { xcb_client_message_event_t event = { .response_type = XCB_CLIENT_MESSAGE, @@ -674,9 +688,10 @@ int CXWM::onEvent(int fd, uint32_t mask) { case XCB_PROPERTY_NOTIFY: handlePropertyNotify((xcb_property_notify_event_t*)event); break; case XCB_CLIENT_MESSAGE: handleClientMessage((xcb_client_message_event_t*)event); break; case XCB_FOCUS_IN: handleFocusIn((xcb_focus_in_event_t*)event); break; + case XCB_FOCUS_OUT: handleFocusOut((xcb_focus_out_event_t*)event); break; case 0: handleError((xcb_value_error_t*)event); break; default: { - ; + Debug::log(TRACE, "[xwm] unhandled event {}", event->response_type & XCB_EVENT_RESPONSE_TYPE_MASK); } } free(event); @@ -891,6 +906,11 @@ void CXWM::activateSurface(SP surf, bool activate) { } void CXWM::sendState(SP surf) { + Debug::log(TRACE, "[xwm] sendState for {} {} {} surface {}", surf->mapped ? "mapped" : "unmapped", surf->fullscreen ? "fullscreen" : "windowed", + surf == focusedSurface ? "focused" : "unfocused", surf->state.title); + if (surf->fullscreen && surf->mapped && surf == focusedSurface) + surf->setWithdrawn(false); // resend normal state + if (surf->withdrawn) { xcb_delete_property(connection, surf->xID, HYPRATOMS["_NET_WM_STATE"]); return; diff --git a/src/xwayland/XWM.hpp b/src/xwayland/XWM.hpp index 88606416..4f6f3f7c 100644 --- a/src/xwayland/XWM.hpp +++ b/src/xwayland/XWM.hpp @@ -104,6 +104,7 @@ class CXWM { void handlePropertyNotify(xcb_property_notify_event_t* e); void handleClientMessage(xcb_client_message_event_t* e); void handleFocusIn(xcb_focus_in_event_t* e); + void handleFocusOut(xcb_focus_out_event_t* e); void handleError(xcb_value_error_t* e); bool handleSelectionEvent(xcb_generic_event_t* e); From d03fa94c2ca1a642959e31adc4fcc2447a3cc623 Mon Sep 17 00:00:00 2001 From: diniamo <55629891+diniamo@users.noreply.github.com> Date: Mon, 22 Jul 2024 11:16:25 +0000 Subject: [PATCH 0136/2181] core: avoid locking 2 wayland sockets (#6971) * fix: avoid locking 2 wayland sockets * format * fix formatting --- src/Compositor.cpp | 69 ++++++++++++++-------------------------------- src/Compositor.hpp | 4 +-- src/main.cpp | 4 +-- 3 files changed, 24 insertions(+), 53 deletions(-) diff --git a/src/Compositor.cpp b/src/Compositor.cpp index 02ca5363..e3ef664d 100644 --- a/src/Compositor.cpp +++ b/src/Compositor.cpp @@ -207,7 +207,7 @@ void CCompositor::setRandomSplash() { static std::vector> pendingOutputs; // -void CCompositor::initServer() { +void CCompositor::initServer(std::string socketName, int socketFd) { m_sWLDisplay = wl_display_create(); @@ -267,16 +267,25 @@ void CCompositor::initServer() { m_iDRMFD = m_pAqBackend->drmFD(); Debug::log(LOG, "Running on DRMFD: {}", m_iDRMFD); - // get socket, avoid using 0 - for (int candidate = 1; candidate <= 32; candidate++) { - const auto CANDIDATESTR = ("wayland-" + std::to_string(candidate)); - const auto RETVAL = wl_display_add_socket(m_sWLDisplay, CANDIDATESTR.c_str()); + if (!socketName.empty() && socketFd != -1) { + fcntl(socketFd, F_SETFD, FD_CLOEXEC); + const auto RETVAL = wl_display_add_socket_fd(m_sWLDisplay, socketFd); if (RETVAL >= 0) { - m_szWLDisplaySocket = CANDIDATESTR; - Debug::log(LOG, "wl_display_add_socket for {} succeeded with {}", CANDIDATESTR, RETVAL); - break; - } else { - Debug::log(WARN, "wl_display_add_socket for {} returned {}: skipping candidate {}", CANDIDATESTR, RETVAL, candidate); + m_szWLDisplaySocket = socketName; + Debug::log(LOG, "wl_display_add_socket_fd for {} succeeded with {}", socketName, RETVAL); + } else + Debug::log(WARN, "wl_display_add_socket_fd for {} returned {}: skipping", socketName, RETVAL); + } else { + // get socket, avoid using 0 + for (int candidate = 1; candidate <= 32; candidate++) { + const auto CANDIDATESTR = ("wayland-" + std::to_string(candidate)); + const auto RETVAL = wl_display_add_socket(m_sWLDisplay, CANDIDATESTR.c_str()); + if (RETVAL >= 0) { + m_szWLDisplaySocket = CANDIDATESTR; + Debug::log(LOG, "wl_display_add_socket for {} succeeded with {}", CANDIDATESTR, RETVAL); + break; + } else + Debug::log(WARN, "wl_display_add_socket for {} returned {}: skipping candidate {}", CANDIDATESTR, RETVAL, candidate); } } @@ -292,7 +301,6 @@ void CCompositor::initServer() { throwError("m_szWLDisplaySocket was null! (wl_display_add_socket and wl_display_add_socket_auto failed)"); } - Debug::log(LOG, "Setting WAYLAND_DISPLAY to {}", m_szWLDisplaySocket); setenv("WAYLAND_DISPLAY", m_szWLDisplaySocket.c_str(), 1); setenv("XDG_SESSION_TYPE", "wayland", 1); @@ -631,44 +639,7 @@ void CCompositor::prepareFallbackOutput() { headless->createOutput(); } -void CCompositor::startCompositor(std::string socketName, int socketFd) { - if (!socketName.empty() && socketFd != -1) { - fcntl(socketFd, F_SETFD, FD_CLOEXEC); - const auto RETVAL = wl_display_add_socket_fd(m_sWLDisplay, socketFd); - if (RETVAL >= 0) { - m_szWLDisplaySocket = socketName; - Debug::log(LOG, "wl_display_add_socket_fd for {} succeeded with {}", socketName, RETVAL); - } else - Debug::log(WARN, "wl_display_add_socket_fd for {} returned {}: skipping", socketName, RETVAL); - } else { - // get socket, avoid using 0 - for (int candidate = 1; candidate <= 32; candidate++) { - const auto CANDIDATESTR = ("wayland-" + std::to_string(candidate)); - const auto RETVAL = wl_display_add_socket(m_sWLDisplay, CANDIDATESTR.c_str()); - if (RETVAL >= 0) { - m_szWLDisplaySocket = CANDIDATESTR; - Debug::log(LOG, "wl_display_add_socket for {} succeeded with {}", CANDIDATESTR, RETVAL); - break; - } else - Debug::log(WARN, "wl_display_add_socket for {} returned {}: skipping candidate {}", CANDIDATESTR, RETVAL, candidate); - } - } - - if (m_szWLDisplaySocket.empty()) { - Debug::log(WARN, "All candidates failed, trying wl_display_add_socket_auto"); - const auto SOCKETSTR = wl_display_add_socket_auto(m_sWLDisplay); - if (SOCKETSTR) - m_szWLDisplaySocket = SOCKETSTR; - } - - if (m_szWLDisplaySocket.empty()) { - Debug::log(CRIT, "m_szWLDisplaySocket NULL!"); - throwError("m_szWLDisplaySocket was null! (wl_display_add_socket and wl_display_add_socket_auto failed)"); - } - - setenv("WAYLAND_DISPLAY", m_szWLDisplaySocket.c_str(), 1); - setenv("XDG_SESSION_TYPE", "wayland", 1); - +void CCompositor::startCompositor() { signal(SIGPIPE, SIG_IGN); if (m_pAqBackend->hasSession() /* Session-less Hyprland usually means a nest, don't update the env in that case */) { diff --git a/src/Compositor.hpp b/src/Compositor.hpp index 58c5b33d..a274ca58 100644 --- a/src/Compositor.hpp +++ b/src/Compositor.hpp @@ -69,8 +69,8 @@ class CCompositor { std::unordered_map m_mMonitorIDMap; - void initServer(); - void startCompositor(std::string socketName, int socketFd); + void initServer(std::string socketName, int socketFd); + void startCompositor(); void cleanup(); void createLockFile(); void removeLockFile(); diff --git a/src/main.cpp b/src/main.cpp index 1ac3ab8b..3e51c6c8 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -147,7 +147,7 @@ int main(int argc, char** argv) { return 1; } - g_pCompositor->initServer(); + g_pCompositor->initServer(socketName, socketFd); if (!envEnabled("HYPRLAND_NO_RT")) Init::gainRealTime(); @@ -155,7 +155,7 @@ int main(int argc, char** argv) { Debug::log(LOG, "Hyprland init finished."); // If all's good to go, start. - g_pCompositor->startCompositor(socketName, socketFd); + g_pCompositor->startCompositor(); g_pCompositor->m_bIsShuttingDown = true; From 83a5395eaa99fecef777827fff1de486c06b6180 Mon Sep 17 00:00:00 2001 From: diniamo Date: Mon, 22 Jul 2024 13:45:34 +0200 Subject: [PATCH 0137/2181] flake: update xdph --- flake.lock | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/flake.lock b/flake.lock index f61f18a1..f9933958 100644 --- a/flake.lock +++ b/flake.lock @@ -209,11 +209,11 @@ ] }, "locked": { - "lastModified": 1720194466, - "narHash": "sha256-Rizg9efi6ue95zOp0MeIV2ZedNo+5U9G2l6yirgBUnA=", + "lastModified": 1721648131, + "narHash": "sha256-cyyxu/oj4QEFp3CVx2WeXa9T4OAUyynuBJHGkBZSxJI=", "owner": "hyprwm", "repo": "xdg-desktop-portal-hyprland", - "rev": "b9b97e5ba23fe7bd5fa4df54696102e8aa863cf6", + "rev": "663be9cad424b170b28b9fa8a61042d721007f3b", "type": "github" }, "original": { From 5bae7f150b228d3bf677d09fd0c320328b0d0ff0 Mon Sep 17 00:00:00 2001 From: Vaxry Date: Mon, 22 Jul 2024 16:56:51 +0200 Subject: [PATCH 0138/2181] wayland/output: avoid sending events to dead outputs ref #6835 --- src/managers/ProtocolManager.cpp | 8 +++++--- src/protocols/core/Output.cpp | 5 +++-- src/protocols/core/Output.hpp | 6 ++++-- 3 files changed, 12 insertions(+), 7 deletions(-) diff --git a/src/managers/ProtocolManager.cpp b/src/managers/ProtocolManager.cpp index 387cac8f..5a44680f 100644 --- a/src/managers/ProtocolManager.cpp +++ b/src/managers/ProtocolManager.cpp @@ -66,8 +66,7 @@ void CProtocolManager::onMonitorModeChange(CMonitor* pMonitor) { else if (!ISMIRROR && (!PROTO::outputs.contains(pMonitor->szName) || PROTO::outputs.at(pMonitor->szName)->isDefunct())) { if (PROTO::outputs.contains(pMonitor->szName)) PROTO::outputs.erase(pMonitor->szName); - PROTO::outputs.emplace(pMonitor->szName, - std::make_unique(&wl_output_interface, 4, std::format("WLOutput ({})", pMonitor->szName), pMonitor->self.lock())); + PROTO::outputs.emplace(pMonitor->szName, makeShared(&wl_output_interface, 4, std::format("WLOutput ({})", pMonitor->szName), pMonitor->self.lock())); } } @@ -86,7 +85,10 @@ CProtocolManager::CProtocolManager() { if (PROTO::outputs.contains(M->szName)) PROTO::outputs.erase(M->szName); - PROTO::outputs.emplace(M->szName, std::make_unique(&wl_output_interface, 4, std::format("WLOutput ({})", M->szName), M->self.lock())); + + auto ref = makeShared(&wl_output_interface, 4, std::format("WLOutput ({})", M->szName), M->self.lock()); + PROTO::outputs.emplace(M->szName, ref); + ref->self = ref; m_mModeChangeListeners[M->szName] = M->events.modeChanged.registerListener([M, this](std::any d) { onMonitorModeChange(M); }); }); diff --git a/src/protocols/core/Output.cpp b/src/protocols/core/Output.cpp index 4ba23cbe..878d1484 100644 --- a/src/protocols/core/Output.cpp +++ b/src/protocols/core/Output.cpp @@ -49,7 +49,7 @@ SP CWLOutputResource::getResource() { } void CWLOutputResource::updateState() { - if (!monitor) + if (!monitor || (owner && owner->defunct)) return; if (resource->version() >= 2) @@ -83,7 +83,8 @@ void CWLOutputProtocol::bindManager(wl_client* client, void* data, uint32_t ver, return; } - RESOURCE->self = RESOURCE; + RESOURCE->self = RESOURCE; + RESOURCE->owner = self; } void CWLOutputProtocol::destroyResource(CWLOutputResource* resource) { diff --git a/src/protocols/core/Output.hpp b/src/protocols/core/Output.hpp index 46e4057b..49c32ec1 100644 --- a/src/protocols/core/Output.hpp +++ b/src/protocols/core/Output.hpp @@ -8,6 +8,7 @@ #include "../../helpers/signal/Signal.hpp" class CMonitor; +class CWLOutputProtocol; class CWLOutputResource { public: @@ -20,7 +21,7 @@ class CWLOutputResource { void updateState(); WP monitor; - + WP owner; WP self; private: @@ -40,6 +41,7 @@ class CWLOutputProtocol : public IWaylandProtocol { void sendDone(); WP monitor; + WP self; // will mark the protocol for removal, will be removed when no. of bound outputs is 0 (or when overwritten by a new global) void remove(); @@ -61,5 +63,5 @@ class CWLOutputProtocol : public IWaylandProtocol { }; namespace PROTO { - inline std::unordered_map> outputs; + inline std::unordered_map> outputs; }; From 87db950189d87eb00d01b9df9959b36ba0f4d5c7 Mon Sep 17 00:00:00 2001 From: Vaxry Date: Mon, 22 Jul 2024 16:57:35 +0200 Subject: [PATCH 0139/2181] wl_seat: avoid sending events to objects without caps ref #6835 --- src/protocols/core/Seat.cpp | 69 +++++++++++++++++++++++++++++++++++++ 1 file changed, 69 insertions(+) diff --git a/src/protocols/core/Seat.cpp b/src/protocols/core/Seat.cpp index 21a47575..7a295372 100644 --- a/src/protocols/core/Seat.cpp +++ b/src/protocols/core/Seat.cpp @@ -27,6 +27,9 @@ void CWLTouchResource::sendDown(SP surface, uint32_t timeMs, if (!owner) return; + if (!(PROTO::seat->currentCaps & eHIDCapabilityType::HID_INPUT_CAPABILITY_TOUCH)) + return; + ASSERT(surface->client() == owner->client()); currentSurface = surface; @@ -41,6 +44,9 @@ void CWLTouchResource::sendUp(uint32_t timeMs, int32_t id) { if (!owner) return; + if (!(PROTO::seat->currentCaps & eHIDCapabilityType::HID_INPUT_CAPABILITY_TOUCH)) + return; + resource->sendUp(g_pSeatManager->nextSerial(owner.lock()), timeMs, id); fingers--; if (fingers <= 0) { @@ -54,6 +60,9 @@ void CWLTouchResource::sendMotion(uint32_t timeMs, int32_t id, const Vector2D& l if (!owner) return; + if (!(PROTO::seat->currentCaps & eHIDCapabilityType::HID_INPUT_CAPABILITY_TOUCH)) + return; + resource->sendMotion(timeMs, id, wl_fixed_from_double(local.x), wl_fixed_from_double(local.y)); } @@ -61,6 +70,9 @@ void CWLTouchResource::sendFrame() { if (!owner) return; + if (!(PROTO::seat->currentCaps & eHIDCapabilityType::HID_INPUT_CAPABILITY_TOUCH)) + return; + resource->sendFrame(); } @@ -68,6 +80,9 @@ void CWLTouchResource::sendCancel() { if (!owner || !currentSurface) return; + if (!(PROTO::seat->currentCaps & eHIDCapabilityType::HID_INPUT_CAPABILITY_TOUCH)) + return; + resource->sendCancel(); } @@ -75,6 +90,9 @@ void CWLTouchResource::sendShape(int32_t id, const Vector2D& shape) { if (!owner || !currentSurface || resource->version() < 6) return; + if (!(PROTO::seat->currentCaps & eHIDCapabilityType::HID_INPUT_CAPABILITY_TOUCH)) + return; + resource->sendShape(id, wl_fixed_from_double(shape.x), wl_fixed_from_double(shape.y)); } @@ -82,6 +100,9 @@ void CWLTouchResource::sendOrientation(int32_t id, double angle) { if (!owner || !currentSurface || resource->version() < 6) return; + if (!(PROTO::seat->currentCaps & eHIDCapabilityType::HID_INPUT_CAPABILITY_TOUCH)) + return; + resource->sendOrientation(id, wl_fixed_from_double(angle)); } @@ -113,6 +134,9 @@ void CWLPointerResource::sendEnter(SP surface, const Vector2 if (!owner || currentSurface == surface) return; + if (!(PROTO::seat->currentCaps & eHIDCapabilityType::HID_INPUT_CAPABILITY_POINTER)) + return; + if (currentSurface) { LOGM(WARN, "requested CWLPointerResource::sendEnter without sendLeave first."); sendLeave(); @@ -130,6 +154,9 @@ void CWLPointerResource::sendLeave() { if (!owner || !currentSurface) return; + if (!(PROTO::seat->currentCaps & eHIDCapabilityType::HID_INPUT_CAPABILITY_POINTER)) + return; + // release all buttons unless we have a dnd going on in which case // the events shall be lost. if (!PROTO::data->dndActive()) { @@ -151,6 +178,9 @@ void CWLPointerResource::sendMotion(uint32_t timeMs, const Vector2D& local) { if (!owner || !currentSurface) return; + if (!(PROTO::seat->currentCaps & eHIDCapabilityType::HID_INPUT_CAPABILITY_POINTER)) + return; + resource->sendMotion(timeMs, wl_fixed_from_double(local.x), wl_fixed_from_double(local.y)); } @@ -158,6 +188,9 @@ void CWLPointerResource::sendButton(uint32_t timeMs, uint32_t button, wl_pointer if (!owner || !currentSurface) return; + if (!(PROTO::seat->currentCaps & eHIDCapabilityType::HID_INPUT_CAPABILITY_POINTER)) + return; + if (state == WL_POINTER_BUTTON_STATE_RELEASED && std::find(pressedButtons.begin(), pressedButtons.end(), button) == pressedButtons.end()) { LOGM(ERR, "sendButton release on a non-pressed button"); return; @@ -178,6 +211,9 @@ void CWLPointerResource::sendAxis(uint32_t timeMs, wl_pointer_axis axis, double if (!owner || !currentSurface) return; + if (!(PROTO::seat->currentCaps & eHIDCapabilityType::HID_INPUT_CAPABILITY_POINTER)) + return; + resource->sendAxis(timeMs, axis, wl_fixed_from_double(value)); } @@ -185,6 +221,9 @@ void CWLPointerResource::sendFrame() { if (!owner || resource->version() < 5) return; + if (!(PROTO::seat->currentCaps & eHIDCapabilityType::HID_INPUT_CAPABILITY_POINTER)) + return; + resource->sendFrame(); } @@ -192,6 +231,9 @@ void CWLPointerResource::sendAxisSource(wl_pointer_axis_source source) { if (!owner || !currentSurface || resource->version() < 5) return; + if (!(PROTO::seat->currentCaps & eHIDCapabilityType::HID_INPUT_CAPABILITY_POINTER)) + return; + resource->sendAxisSource(source); } @@ -199,6 +241,9 @@ void CWLPointerResource::sendAxisStop(uint32_t timeMs, wl_pointer_axis axis) { if (!owner || !currentSurface || resource->version() < 5) return; + if (!(PROTO::seat->currentCaps & eHIDCapabilityType::HID_INPUT_CAPABILITY_POINTER)) + return; + resource->sendAxisStop(timeMs, axis); } @@ -206,6 +251,9 @@ void CWLPointerResource::sendAxisDiscrete(wl_pointer_axis axis, int32_t discrete if (!owner || !currentSurface || resource->version() < 5) return; + if (!(PROTO::seat->currentCaps & eHIDCapabilityType::HID_INPUT_CAPABILITY_POINTER)) + return; + resource->sendAxisDiscrete(axis, discrete); } @@ -213,6 +261,9 @@ void CWLPointerResource::sendAxisValue120(wl_pointer_axis axis, int32_t value120 if (!owner || !currentSurface || resource->version() < 8) return; + if (!(PROTO::seat->currentCaps & eHIDCapabilityType::HID_INPUT_CAPABILITY_POINTER)) + return; + resource->sendAxisValue120(axis, value120); } @@ -220,6 +271,9 @@ void CWLPointerResource::sendAxisRelativeDirection(wl_pointer_axis axis, wl_poin if (!owner || !currentSurface || resource->version() < 9) return; + if (!(PROTO::seat->currentCaps & eHIDCapabilityType::HID_INPUT_CAPABILITY_POINTER)) + return; + resource->sendAxisRelativeDirection(axis, direction); } @@ -250,6 +304,9 @@ void CWLKeyboardResource::sendKeymap(SP keyboard) { if (!keyboard) return; + if (!(PROTO::seat->currentCaps & eHIDCapabilityType::HID_INPUT_CAPABILITY_KEYBOARD)) + return; + wl_keyboard_keymap_format format = keyboard ? WL_KEYBOARD_KEYMAP_FORMAT_XKB_V1 : WL_KEYBOARD_KEYMAP_FORMAT_NO_KEYMAP; int fd; uint32_t size; @@ -275,6 +332,9 @@ void CWLKeyboardResource::sendEnter(SP surface) { if (!owner || currentSurface == surface) return; + if (!(PROTO::seat->currentCaps & eHIDCapabilityType::HID_INPUT_CAPABILITY_KEYBOARD)) + return; + if (currentSurface) { LOGM(WARN, "requested CWLKeyboardResource::sendEnter without sendLeave first."); sendLeave(); @@ -297,6 +357,9 @@ void CWLKeyboardResource::sendLeave() { if (!owner || !currentSurface) return; + if (!(PROTO::seat->currentCaps & eHIDCapabilityType::HID_INPUT_CAPABILITY_KEYBOARD)) + return; + resource->sendLeave(g_pSeatManager->nextSerial(owner.lock()), currentSurface->getResource().get()); currentSurface.reset(); listeners.destroySurface.reset(); @@ -306,6 +369,9 @@ void CWLKeyboardResource::sendKey(uint32_t timeMs, uint32_t key, wl_keyboard_key if (!owner || !currentSurface) return; + if (!(PROTO::seat->currentCaps & eHIDCapabilityType::HID_INPUT_CAPABILITY_KEYBOARD)) + return; + resource->sendKey(g_pSeatManager->nextSerial(owner.lock()), timeMs, key, state); } @@ -313,6 +379,9 @@ void CWLKeyboardResource::sendMods(uint32_t depressed, uint32_t latched, uint32_ if (!owner || !currentSurface) return; + if (!(PROTO::seat->currentCaps & eHIDCapabilityType::HID_INPUT_CAPABILITY_KEYBOARD)) + return; + resource->sendModifiers(g_pSeatManager->nextSerial(owner.lock()), depressed, latched, locked, group); } From 77b134e23baf769aecdf2ea8ed14d55d00228ce1 Mon Sep 17 00:00:00 2001 From: Vaxry Date: Mon, 22 Jul 2024 17:24:24 +0200 Subject: [PATCH 0140/2181] virtual-pointer: fixup virtual pointer warp events fixes #6976 --- src/devices/VirtualPointer.cpp | 7 ++++++- src/managers/PointerManager.cpp | 2 +- 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/src/devices/VirtualPointer.cpp b/src/devices/VirtualPointer.cpp index faca27dc..f9a1c409 100644 --- a/src/devices/VirtualPointer.cpp +++ b/src/devices/VirtualPointer.cpp @@ -20,7 +20,12 @@ CVirtualPointer::CVirtualPointer(SP resource) : point }); listeners.motion = pointer->events.move.registerListener([this](std::any d) { pointerEvents.motion.emit(d); }); - listeners.motionAbsolute = pointer->events.warp.registerListener([this](std::any d) { pointerEvents.motionAbsolute.emit(d); }); + listeners.motionAbsolute = pointer->events.warp.registerListener([this](std::any d) { + // we need to unpack the event and add our device here because it's required to calculate the position correctly + auto E = std::any_cast(d); + E.device = self.lock(); + pointerEvents.motionAbsolute.emit(E); + }); listeners.button = pointer->events.button.registerListener([this](std::any d) { pointerEvents.button.emit(d); }); listeners.axis = pointer->events.axis.registerListener([this](std::any d) { pointerEvents.axis.emit(d); }); listeners.frame = pointer->events.frame.registerListener([this](std::any d) { pointerEvents.frame.emit(); }); diff --git a/src/managers/PointerManager.cpp b/src/managers/PointerManager.cpp index cf10db71..b1542fed 100644 --- a/src/managers/PointerManager.cpp +++ b/src/managers/PointerManager.cpp @@ -620,7 +620,7 @@ void CPointerManager::move(const Vector2D& deltaLogical) { void CPointerManager::warpAbsolute(Vector2D abs, SP dev) { SP currentMonitor = g_pCompositor->m_pLastMonitor.lock(); - if (!currentMonitor) + if (!currentMonitor || !dev) return; if (!std::isnan(abs.x)) From e8374e07927826f43d30803b6db00c3b88482e7e Mon Sep 17 00:00:00 2001 From: Ikalco <73481042+ikalco@users.noreply.github.com> Date: Mon, 22 Jul 2024 11:06:11 -0500 Subject: [PATCH 0141/2181] debug: get rid of useless 1s in logs (#6969) * get rid of 1s in logs lol * replace WLR with AQ in logs --- src/Compositor.cpp | 10 +++++----- src/desktop/LayerSurface.cpp | 6 +++--- src/helpers/Monitor.cpp | 2 +- src/managers/input/IdleInhibitor.cpp | 2 +- src/managers/input/InputManager.cpp | 8 ++++---- src/protocols/AlphaModifier.cpp | 4 ++-- src/protocols/FractionalScale.cpp | 4 ++-- src/protocols/ToplevelExport.cpp | 2 +- src/xwayland/XWM.cpp | 2 +- 9 files changed, 20 insertions(+), 20 deletions(-) diff --git a/src/Compositor.cpp b/src/Compositor.cpp index e3ef664d..24098bee 100644 --- a/src/Compositor.cpp +++ b/src/Compositor.cpp @@ -1100,7 +1100,7 @@ void CCompositor::focusSurface(SP pSurface, PHLWINDOW pWindo return; if (g_pSeatManager->seatGrab && !g_pSeatManager->seatGrab->accepts(pSurface)) { - Debug::log(LOG, "surface {:x} won't receive kb focus becuase grab rejected it", (uintptr_t)pSurface); + Debug::log(LOG, "surface {:x} won't receive kb focus becuase grab rejected it", (uintptr_t)pSurface.get()); return; } @@ -1123,9 +1123,9 @@ void CCompositor::focusSurface(SP pSurface, PHLWINDOW pWindo g_pSeatManager->setKeyboardFocus(pSurface); if (pWindowOwner) - Debug::log(LOG, "Set keyboard focus to surface {:x}, with {}", (uintptr_t)pSurface, pWindowOwner); + Debug::log(LOG, "Set keyboard focus to surface {:x}, with {}", (uintptr_t)pSurface.get(), pWindowOwner); else - Debug::log(LOG, "Set keyboard focus to surface {:x}", (uintptr_t)pSurface); + Debug::log(LOG, "Set keyboard focus to surface {:x}", (uintptr_t)pSurface.get()); g_pXWaylandManager->activateSurface(pSurface, true); m_pLastFocus = pSurface; @@ -2836,7 +2836,7 @@ void CCompositor::setPreferredScaleForSurface(SP pSurface, d const auto PSURFACE = CWLSurface::fromResource(pSurface); if (!PSURFACE) { - Debug::log(WARN, "Orphaned CWLSurfaceResource {:x} in setPreferredScaleForSurface", (uintptr_t)pSurface); + Debug::log(WARN, "Orphaned CWLSurfaceResource {:x} in setPreferredScaleForSurface", (uintptr_t)pSurface.get()); return; } @@ -2849,7 +2849,7 @@ void CCompositor::setPreferredTransformForSurface(SP pSurfac const auto PSURFACE = CWLSurface::fromResource(pSurface); if (!PSURFACE) { - Debug::log(WARN, "Orphaned CWLSurfaceResource {:x} in setPreferredTransformForSurface", (uintptr_t)pSurface); + Debug::log(WARN, "Orphaned CWLSurfaceResource {:x} in setPreferredTransformForSurface", (uintptr_t)pSurface.get()); return; } diff --git a/src/desktop/LayerSurface.cpp b/src/desktop/LayerSurface.cpp index 9a891531..83b0992f 100644 --- a/src/desktop/LayerSurface.cpp +++ b/src/desktop/LayerSurface.cpp @@ -74,7 +74,7 @@ CLayerSurface::~CLayerSurface() { } void CLayerSurface::onDestroy() { - Debug::log(LOG, "LayerSurface {:x} destroyed", (uintptr_t)layerSurface); + Debug::log(LOG, "LayerSurface {:x} destroyed", (uintptr_t)layerSurface.get()); const auto PMONITOR = g_pCompositor->getMonitorFromID(monitorID); @@ -114,7 +114,7 @@ void CLayerSurface::onDestroy() { } void CLayerSurface::onMap() { - Debug::log(LOG, "LayerSurface {:x} mapped", (uintptr_t)layerSurface); + Debug::log(LOG, "LayerSurface {:x} mapped", (uintptr_t)layerSurface.get()); mapped = true; interactivity = layerSurface->current.interactivity; @@ -177,7 +177,7 @@ void CLayerSurface::onMap() { } void CLayerSurface::onUnmap() { - Debug::log(LOG, "LayerSurface {:x} unmapped", (uintptr_t)layerSurface); + Debug::log(LOG, "LayerSurface {:x} unmapped", (uintptr_t)layerSurface.get()); g_pEventManager->postEvent(SHyprIPCEvent{"closelayer", layerSurface->layerNamespace}); EMIT_HOOK_EVENT("closeLayer", self.lock()); diff --git a/src/helpers/Monitor.cpp b/src/helpers/Monitor.cpp index a23b9861..635427d1 100644 --- a/src/helpers/Monitor.cpp +++ b/src/helpers/Monitor.cpp @@ -148,7 +148,7 @@ void CMonitor::onConnect(bool noRule) { damage.setSize(vecTransformedSize); - Debug::log(LOG, "Added new monitor with name {} at {:j0} with size {:j0}, pointer {:x}", output->name, vecPosition, vecPixelSize, (uintptr_t)output); + Debug::log(LOG, "Added new monitor with name {} at {:j0} with size {:j0}, pointer {:x}", output->name, vecPosition, vecPixelSize, (uintptr_t)output.get()); setupDefaultWS(monitorRule); diff --git a/src/managers/input/IdleInhibitor.cpp b/src/managers/input/IdleInhibitor.cpp index a38acdbf..da2429bc 100644 --- a/src/managers/input/IdleInhibitor.cpp +++ b/src/managers/input/IdleInhibitor.cpp @@ -7,7 +7,7 @@ void CInputManager::newIdleInhibitor(std::any inhibitor) { const auto PINHIBIT = m_vIdleInhibitors.emplace_back(std::make_unique()).get(); PINHIBIT->inhibitor = std::any_cast>(inhibitor); - Debug::log(LOG, "New idle inhibitor registered for surface {:x}", (uintptr_t)PINHIBIT->inhibitor->surface); + Debug::log(LOG, "New idle inhibitor registered for surface {:x}", (uintptr_t)PINHIBIT->inhibitor->surface.get()); PINHIBIT->inhibitor->listeners.destroy = PINHIBIT->inhibitor->resource->events.destroy.registerListener([this, PINHIBIT](std::any data) { std::erase_if(m_vIdleInhibitors, [PINHIBIT](const auto& other) { return other.get() == PINHIBIT; }); diff --git a/src/managers/input/InputManager.cpp b/src/managers/input/InputManager.cpp index 492d2805..e2c62367 100644 --- a/src/managers/input/InputManager.cpp +++ b/src/managers/input/InputManager.cpp @@ -228,7 +228,7 @@ void CInputManager::mouseMoveUnified(uint32_t time, bool refocus) { return; } else - Debug::log(ERR, "BUG THIS: Null SURF/CONSTRAINT in mouse refocus. Ignoring constraints. {:x} {:x}", (uintptr_t)SURF, (uintptr_t)CONSTRAINT.get()); + Debug::log(ERR, "BUG THIS: Null SURF/CONSTRAINT in mouse refocus. Ignoring constraints. {:x} {:x}", (uintptr_t)SURF.get(), (uintptr_t)CONSTRAINT.get()); } // if we are holding a pointer button, @@ -570,7 +570,7 @@ void CInputManager::processMouseRequest(std::any E) { auto e = std::any_cast(E); - Debug::log(LOG, "cursorImage request: surface {:x}", (uintptr_t)e.surf); + Debug::log(LOG, "cursorImage request: surface {:x}", (uintptr_t)e.surf.get()); if (e.surf != m_sCursorSurfaceInfo.wlSurface->resource()) { m_sCursorSurfaceInfo.wlSurface->unassign(); @@ -850,7 +850,7 @@ void CInputManager::newKeyboard(SP keyboard) { setupKeyboard(PNEWKEYBOARD); - Debug::log(LOG, "New keyboard created, pointers Hypr: {:x} and WLR: {:x}", (uintptr_t)PNEWKEYBOARD.get(), (uintptr_t)keyboard); + Debug::log(LOG, "New keyboard created, pointers Hypr: {:x} and AQ: {:x}", (uintptr_t)PNEWKEYBOARD.get(), (uintptr_t)keyboard.get()); } void CInputManager::newVirtualKeyboard(SP keyboard) { @@ -992,7 +992,7 @@ void CInputManager::newMouse(SP mouse) { setupMouse(PMOUSE); - Debug::log(LOG, "New mouse created, pointer WLR: {:x}", (uintptr_t)mouse); + Debug::log(LOG, "New mouse created, pointer AQ: {:x}", (uintptr_t)mouse.get()); } void CInputManager::setupMouse(SP mauz) { diff --git a/src/protocols/AlphaModifier.cpp b/src/protocols/AlphaModifier.cpp index 04dcd0a8..38b8c800 100644 --- a/src/protocols/AlphaModifier.cpp +++ b/src/protocols/AlphaModifier.cpp @@ -87,7 +87,7 @@ void CAlphaModifierProtocol::destroyModifier(CAlphaModifier* modifier) { void CAlphaModifierProtocol::onGetSurface(CWpAlphaModifierV1* pMgr, uint32_t id, SP surface) { if (std::find_if(m_mAlphaModifiers.begin(), m_mAlphaModifiers.end(), [surface](const auto& e) { return e.first == surface; }) != m_mAlphaModifiers.end()) { - LOGM(ERR, "AlphaModifier already present for surface {:x}", (uintptr_t)surface); + LOGM(ERR, "AlphaModifier already present for surface {:x}", (uintptr_t)surface.get()); pMgr->error(WP_ALPHA_MODIFIER_V1_ERROR_ALREADY_CONSTRUCTED, "AlphaModifier already present"); return; } @@ -100,4 +100,4 @@ void CAlphaModifierProtocol::onGetSurface(CWpAlphaModifierV1* pMgr, uint32_t id, m_mAlphaModifiers.erase(surface); return; } -} \ No newline at end of file +} diff --git a/src/protocols/FractionalScale.cpp b/src/protocols/FractionalScale.cpp index 6d225e99..5bf56c5a 100644 --- a/src/protocols/FractionalScale.cpp +++ b/src/protocols/FractionalScale.cpp @@ -28,7 +28,7 @@ void CFractionalScaleProtocol::onManagerResourceDestroy(wl_resource* res) { void CFractionalScaleProtocol::onGetFractionalScale(CWpFractionalScaleManagerV1* pMgr, uint32_t id, SP surface) { for (auto& [k, v] : m_mAddons) { if (k == surface) { - LOGM(ERR, "Surface {:x} already has a fractionalScale addon", (uintptr_t)surface); + LOGM(ERR, "Surface {:x} already has a fractionalScale addon", (uintptr_t)surface.get()); pMgr->error(WP_FRACTIONAL_SCALE_MANAGER_V1_ERROR_FRACTIONAL_SCALE_EXISTS, "Fractional scale already exists"); return; } @@ -80,4 +80,4 @@ bool CFractionalScaleAddon::good() { SP CFractionalScaleAddon::surf() { return surface.lock(); -} \ No newline at end of file +} diff --git a/src/protocols/ToplevelExport.cpp b/src/protocols/ToplevelExport.cpp index 0e78e5f7..e982ad6f 100644 --- a/src/protocols/ToplevelExport.cpp +++ b/src/protocols/ToplevelExport.cpp @@ -221,7 +221,7 @@ void CToplevelExportProtocolManager::copyFrame(wl_client* client, wl_resource* r const auto PWINDOW = PFRAME->pWindow.lock(); if (!validMapped(PWINDOW)) { - Debug::log(ERR, "Client requested sharing of window handle {:x} which is gone!", (uintptr_t)PWINDOW.get()); + Debug::log(ERR, "Client requested sharing of window handle {:x} which is gone!", PWINDOW); hyprland_toplevel_export_frame_v1_send_failed(PFRAME->resource); removeFrame(PFRAME); return; diff --git a/src/xwayland/XWM.cpp b/src/xwayland/XWM.cpp index bb69afda..498710a4 100644 --- a/src/xwayland/XWM.cpp +++ b/src/xwayland/XWM.cpp @@ -937,7 +937,7 @@ void CXWM::onNewSurface(SP surf) { if (surf->client() != g_pXWayland->pServer->xwaylandClient) return; - Debug::log(LOG, "[xwm] New XWayland surface at {:x}", (uintptr_t)surf); + Debug::log(LOG, "[xwm] New XWayland surface at {:x}", (uintptr_t)surf.get()); const auto WLID = surf->id(); From f17f8b219c699ab52f3d784cad90bdef5bb78188 Mon Sep 17 00:00:00 2001 From: Vaxry Date: Mon, 22 Jul 2024 19:05:24 +0200 Subject: [PATCH 0142/2181] pointer/hw: extend cursor swapchain to 3 otherwise on some commits we draw twice and we draw over the front buffer --- src/managers/PointerManager.cpp | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/managers/PointerManager.cpp b/src/managers/PointerManager.cpp index b1542fed..55bd0509 100644 --- a/src/managers/PointerManager.cpp +++ b/src/managers/PointerManager.cpp @@ -373,7 +373,10 @@ SP CPointerManager::renderHWCursorBuffer(SPmonitor->cursorSwapchain->currentOptions(); options.size = maxSize; - options.length = 2; + // TODO: this is a band-aid. If the current cursor image has not yet been committed (no rendering has yet been done) + // we should revert the swapchain and avoid rendering to the front buffer. + // as a band-aid, extend the swapchain to 3 as we sometimes double-render on a cursor shape change. + options.length = 3; options.scanout = true; options.cursor = true; options.multigpu = state->monitor->output->getBackend()->preferredAllocator()->drmFD() != g_pCompositor->m_iDRMFD; From 4c3b03516209a49244a8f044143c1162752b8a7a Mon Sep 17 00:00:00 2001 From: Vaxry Date: Mon, 22 Jul 2024 19:19:37 +0200 Subject: [PATCH 0143/2181] pointer/hw: rollback the swapchain on multiple renders without a commit fixes the hack --- src/managers/PointerManager.cpp | 21 +++++++++++++++++---- src/managers/PointerManager.hpp | 6 ++++-- 2 files changed, 21 insertions(+), 6 deletions(-) diff --git a/src/managers/PointerManager.cpp b/src/managers/PointerManager.cpp index 55bd0509..3b425688 100644 --- a/src/managers/PointerManager.cpp +++ b/src/managers/PointerManager.cpp @@ -24,6 +24,14 @@ CPointerManager::CPointerManager() { }, nullptr); }); + + hooks.monitorPreRender = g_pHookSystem->hookDynamic("preRender", [this](void* self, SCallbackInfo& info, std::any data) { + auto state = stateFor(std::any_cast(data)->self.lock()); + if (!state) + return; + + state->cursorRendered = false; + }); } void CPointerManager::lockSoftwareAll() { @@ -373,10 +381,7 @@ SP CPointerManager::renderHWCursorBuffer(SPmonitor->cursorSwapchain->currentOptions(); options.size = maxSize; - // TODO: this is a band-aid. If the current cursor image has not yet been committed (no rendering has yet been done) - // we should revert the swapchain and avoid rendering to the front buffer. - // as a band-aid, extend the swapchain to 3 as we sometimes double-render on a cursor shape change. - options.length = 3; + options.length = 2; options.scanout = true; options.cursor = true; options.multigpu = state->monitor->output->getBackend()->preferredAllocator()->drmFD() != g_pCompositor->m_iDRMFD; @@ -389,6 +394,14 @@ SP CPointerManager::renderHWCursorBuffer(SPcursorRendered) + state->monitor->cursorSwapchain->rollback(); + + state->cursorRendered = true; + auto buf = state->monitor->cursorSwapchain->next(nullptr); if (!buf) { Debug::log(TRACE, "Failed to acquire a buffer from the cursor swapchain"); diff --git a/src/managers/PointerManager.hpp b/src/managers/PointerManager.hpp index cf4f1a94..4a4c4f61 100644 --- a/src/managers/PointerManager.hpp +++ b/src/managers/PointerManager.hpp @@ -163,8 +163,9 @@ class CPointerManager { int softwareLocks = 0; bool hardwareFailed = false; CBox box; // logical - bool entered = false; - bool hwApplied = false; + bool entered = false; + bool hwApplied = false; + bool cursorRendered = false; SP cursorFrontBuffer; }; @@ -177,6 +178,7 @@ class CPointerManager { struct { SP monitorAdded; + SP monitorPreRender; } hooks; }; From 7c68236a51291e71db04233d04eae65f4ebd594f Mon Sep 17 00:00:00 2001 From: Vaxry Date: Mon, 22 Jul 2024 23:05:22 +0200 Subject: [PATCH 0144/2181] egl: avoid setting debug mode and handle legacyrenderer ref #6973 --- src/render/OpenGL.cpp | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/src/render/OpenGL.cpp b/src/render/OpenGL.cpp index fef69f7c..15b3cad8 100644 --- a/src/render/OpenGL.cpp +++ b/src/render/OpenGL.cpp @@ -130,12 +130,15 @@ void CHyprOpenGLImpl::initEGL(bool gbm) { attrs.push_back(EGL_LOSE_CONTEXT_ON_RESET_EXT); } +#ifndef GLES2 attrs.push_back(EGL_CONTEXT_MAJOR_VERSION); attrs.push_back(3); attrs.push_back(EGL_CONTEXT_MINOR_VERSION); attrs.push_back(2); - attrs.push_back(EGL_CONTEXT_OPENGL_DEBUG); - attrs.push_back(ISDEBUG ? EGL_TRUE : EGL_FALSE); +#else + attrs.push_back(EGL_CONTEXT_CLIENT_VERSION); + attrs.push_back(2); +#endif attrs.push_back(EGL_NONE); From 3c758db95c129ed6ca7ce0c1b5b82ad6e189488d Mon Sep 17 00:00:00 2001 From: Sam Lakerveld Date: Mon, 22 Jul 2024 23:36:58 +0200 Subject: [PATCH 0145/2181] renderer/layer-shell: use explicitly set exclusiveEdge (#6984) --- src/protocols/LayerShell.cpp | 2 ++ src/render/Renderer.cpp | 7 ++++--- 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/src/protocols/LayerShell.cpp b/src/protocols/LayerShell.cpp index fd66ba5e..029f261d 100644 --- a/src/protocols/LayerShell.cpp +++ b/src/protocols/LayerShell.cpp @@ -152,6 +152,8 @@ CLayerShellResource::CLayerShellResource(SP resource_, SPsetSetExclusiveEdge([this](CZwlrLayerSurfaceV1* r, zwlrLayerSurfaceV1Anchor anchor) { + // TODO: validate anchor + pending.committed |= STATE_EDGE; pending.exclusiveEdge = anchor; }); diff --git a/src/render/Renderer.cpp b/src/render/Renderer.cpp index 835fed91..d8de7ba8 100644 --- a/src/render/Renderer.cpp +++ b/src/render/Renderer.cpp @@ -1506,7 +1506,8 @@ void CHyprRenderer::setSurfaceScanoutMode(SP surface, SP 0) { + if ((exclusiveEdge == edges[i].singular_anchor || anchor == edges[i].singular_anchor || anchor == edges[i].anchor_triplet) && exclusive + edges[i].margin > 0) { if (edges[i].positive_axis) { *edges[i].positive_axis += exclusive + edges[i].margin; } @@ -1638,7 +1639,7 @@ void CHyprRenderer::arrangeLayerArray(CMonitor* pMonitor, const std::vectorgeometry = box; - applyExclusive(*usableArea, PSTATE->anchor, PSTATE->exclusive, PSTATE->margin.top, PSTATE->margin.right, PSTATE->margin.bottom, PSTATE->margin.left); + applyExclusive(*usableArea, PSTATE->anchor, PSTATE->exclusive, PSTATE->exclusiveEdge, PSTATE->margin.top, PSTATE->margin.right, PSTATE->margin.bottom, PSTATE->margin.left); if (Vector2D{box.width, box.height} != OLDSIZE) ls->layerSurface->configure(box.size()); From 752604cfe954bd96bd6b5aca3e80dafb6a426cfb Mon Sep 17 00:00:00 2001 From: Mihai Fufezan Date: Tue, 23 Jul 2024 20:40:33 +0300 Subject: [PATCH 0146/2181] Nix: remove meson (used by wlroots) --- nix/default.nix | 13 +++++-------- 1 file changed, 5 insertions(+), 8 deletions(-) diff --git a/nix/default.nix b/nix/default.nix index 7775b729..e4e12f43 100644 --- a/nix/default.nix +++ b/nix/default.nix @@ -31,7 +31,6 @@ libuuid, libxkbcommon, mesa, - meson, pango, pciutils, pcre2, @@ -90,7 +89,6 @@ assert lib.assertMsg (!hidpiXWayland) "The option `hidpiXWayland` has been remov jq makeWrapper cmake - meson # for wlroots ninja pkg-config python3 # for udis86 @@ -114,10 +112,12 @@ assert lib.assertMsg (!hidpiXWayland) "The option `hidpiXWayland` has been remov hyprcursor hyprlang hyprutils - libGL - libdrm libdatrie + libdisplay-info + libdrm + libGL libinput + libliftoff libselinux libsepol libthai @@ -127,13 +127,10 @@ assert lib.assertMsg (!hidpiXWayland) "The option `hidpiXWayland` has been remov pango pciutils pcre2 + seatd tomlplusplus wayland wayland-protocols - # for wlroots - seatd - libdisplay-info - libliftoff ] (lib.optionals stdenv.hostPlatform.isMusl [libexecinfo]) (lib.optionals enableXWayland [ From 077494ee85c8fa4c6ae74ad8d749feea826294d2 Mon Sep 17 00:00:00 2001 From: Vaxry Date: Tue, 23 Jul 2024 19:56:42 +0200 Subject: [PATCH 0147/2181] surface: fix zero_scaling xwayland damage --- src/desktop/WLSurface.cpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/desktop/WLSurface.cpp b/src/desktop/WLSurface.cpp index a7a2e5aa..90924145 100644 --- a/src/desktop/WLSurface.cpp +++ b/src/desktop/WLSurface.cpp @@ -118,6 +118,9 @@ CRegion CWLSurface::computeDamage() const { damage.scale(SCALE); + if (m_pWindowOwner) + damage.scale(m_pWindowOwner->m_fX11SurfaceScaledBy); // fix xwayland:force_zero_scaling stuff that will be fucked by the above a bit + return damage; } From a5f58a31268da95e36c0918ac75589c05e81b892 Mon Sep 17 00:00:00 2001 From: Ikalco <73481042+ikalco@users.noreply.github.com> Date: Tue, 23 Jul 2024 13:03:15 -0500 Subject: [PATCH 0148/2181] layer-shell: validate exclusiveEdge and don't set it as top by default (#7006) * validate exclusiveEdge and don't set it as top by default * make sure exclusive edge anchor is within bounds --- src/protocols/LayerShell.cpp | 12 ++++++++++-- src/protocols/LayerShell.hpp | 2 +- 2 files changed, 11 insertions(+), 3 deletions(-) diff --git a/src/protocols/LayerShell.cpp b/src/protocols/LayerShell.cpp index 029f261d..4e733b35 100644 --- a/src/protocols/LayerShell.cpp +++ b/src/protocols/LayerShell.cpp @@ -11,7 +11,7 @@ void CLayerShellResource::SState::reset() { exclusive = 0; interactivity = ZWLR_LAYER_SURFACE_V1_KEYBOARD_INTERACTIVITY_NONE; layer = ZWLR_LAYER_SHELL_V1_LAYER_BOTTOM; - exclusiveEdge = ZWLR_LAYER_SURFACE_V1_ANCHOR_TOP; + exclusiveEdge = (zwlrLayerSurfaceV1Anchor)0; desiredSize = {}; margin = {0, 0, 0, 0}; } @@ -152,7 +152,15 @@ CLayerShellResource::CLayerShellResource(SP resource_, SPsetSetExclusiveEdge([this](CZwlrLayerSurfaceV1* r, zwlrLayerSurfaceV1Anchor anchor) { - // TODO: validate anchor + if (anchor > (ZWLR_LAYER_SURFACE_V1_ANCHOR_TOP | ZWLR_LAYER_SURFACE_V1_ANCHOR_BOTTOM | ZWLR_LAYER_SURFACE_V1_ANCHOR_LEFT | ZWLR_LAYER_SURFACE_V1_ANCHOR_RIGHT)) { + r->error(ZWLR_LAYER_SURFACE_V1_ERROR_INVALID_EXCLUSIVE_EDGE, "Invalid exclusive edge"); + return; + } + + if (!pending.anchor || !(pending.anchor & anchor)) { + r->error(ZWLR_LAYER_SURFACE_V1_ERROR_INVALID_EXCLUSIVE_EDGE, "Exclusive edge doesn't align with anchor"); + return; + } pending.committed |= STATE_EDGE; pending.exclusiveEdge = anchor; diff --git a/src/protocols/LayerShell.hpp b/src/protocols/LayerShell.hpp index 6d29248a..221d95c0 100644 --- a/src/protocols/LayerShell.hpp +++ b/src/protocols/LayerShell.hpp @@ -47,7 +47,7 @@ class CLayerShellResource : public ISurfaceRole { Vector2D desiredSize; zwlrLayerSurfaceV1KeyboardInteractivity interactivity = ZWLR_LAYER_SURFACE_V1_KEYBOARD_INTERACTIVITY_NONE; zwlrLayerShellV1Layer layer = ZWLR_LAYER_SHELL_V1_LAYER_BOTTOM; - zwlrLayerSurfaceV1Anchor exclusiveEdge = ZWLR_LAYER_SURFACE_V1_ANCHOR_TOP; + zwlrLayerSurfaceV1Anchor exclusiveEdge = (zwlrLayerSurfaceV1Anchor)0; uint32_t committed = 0; struct { From 8a4548e4302b1cc00fca368a7cc2e3171516420c Mon Sep 17 00:00:00 2001 From: Vaxry Date: Tue, 23 Jul 2024 23:38:50 +0200 Subject: [PATCH 0149/2181] window: drop ack requirement for applying pending reported size fixes #6533 --- src/events/Windows.cpp | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/src/events/Windows.cpp b/src/events/Windows.cpp index 516ac2ae..a5511e17 100644 --- a/src/events/Windows.cpp +++ b/src/events/Windows.cpp @@ -702,12 +702,7 @@ void Events::listener_commitWindow(void* owner, void* data) { if (!PWINDOW->m_bIsMapped || PWINDOW->isHidden()) return; - if (PWINDOW->m_bIsX11) - PWINDOW->m_vReportedSize = PWINDOW->m_vPendingReportedSize; // apply pending size. We pinged, the window ponged. - else if (PWINDOW->m_pPendingSizeAck.has_value()) { - PWINDOW->m_vReportedSize = PWINDOW->m_pPendingSizeAck->second; - PWINDOW->m_pPendingSizeAck.reset(); - } + PWINDOW->m_vReportedSize = PWINDOW->m_vPendingReportedSize; // apply pending size. We pinged, the window ponged. if (!PWINDOW->m_bIsX11 && !PWINDOW->m_bIsFullscreen && PWINDOW->m_bIsFloating) { const auto MINSIZE = PWINDOW->m_pXDGSurface->toplevel->current.minSize; From e2efecc24e6534f46352cab13975778e3f0b5735 Mon Sep 17 00:00:00 2001 From: Leon Date: Wed, 24 Jul 2024 00:38:15 +0200 Subject: [PATCH 0150/2181] flake: update aquamarine --- flake.lock | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/flake.lock b/flake.lock index f9933958..4545c61d 100644 --- a/flake.lock +++ b/flake.lock @@ -16,11 +16,11 @@ ] }, "locked": { - "lastModified": 1721571743, - "narHash": "sha256-hat7wggtDISBJD8kTo5MTrT+IsY/Ha2MwgjmqqijoCA=", + "lastModified": 1721755137, + "narHash": "sha256-DcJkFNaHGRMIkexx/ol2oNiUFT/zqnZH6dwODdHubIU=", "owner": "hyprwm", "repo": "aquamarine", - "rev": "601f6cf95cbe4fef02dc7faf34bba58566c914e9", + "rev": "4c72cd4d0b0368ce78bf94ea7f23d47670f0d429", "type": "github" }, "original": { From 2da3cfb4220af818b8b44fcc52c9b9b54cbe155e Mon Sep 17 00:00:00 2001 From: Leon <99900077+leon-erd@users.noreply.github.com> Date: Wed, 24 Jul 2024 10:59:50 +0200 Subject: [PATCH 0151/2181] touch: fix touch swipe invert config (#7014) --- src/managers/input/Touch.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/managers/input/Touch.cpp b/src/managers/input/Touch.cpp index 7863140b..40af4b1e 100644 --- a/src/managers/input/Touch.cpp +++ b/src/managers/input/Touch.cpp @@ -14,7 +14,7 @@ void CInputManager::onTouchDown(ITouch::SDownEvent e) { // TODO: WORKSPACERULE.gapsOut.value_or() auto gapsOut = *PGAPSOUT; static auto PBORDERSIZE = CConfigValue("general:border_size"); - static auto PSWIPEINVR = CConfigValue("gestures:workspace_swipe_invert"); + static auto PSWIPEINVR = CConfigValue("gestures:workspace_swipe_touch_invert"); EMIT_HOOK_EVENT_CANCELLABLE("touchDown", e); auto PMONITOR = g_pCompositor->getMonitorFromName(!e.device->boundOutput.empty() ? e.device->boundOutput : ""); From 99088eaed806d9268967baf09bc09cdb987c5357 Mon Sep 17 00:00:00 2001 From: Vaxry Date: Wed, 24 Jul 2024 11:07:22 +0200 Subject: [PATCH 0152/2181] compositor: simplify getWindowFromSurface --- src/Compositor.cpp | 11 +++-------- 1 file changed, 3 insertions(+), 8 deletions(-) diff --git a/src/Compositor.cpp b/src/Compositor.cpp index 24098bee..7caaa98a 100644 --- a/src/Compositor.cpp +++ b/src/Compositor.cpp @@ -1184,15 +1184,10 @@ SP CCompositor::vectorToLayerSurface(const Vector2D& pos, st } PHLWINDOW CCompositor::getWindowFromSurface(SP pSurface) { - for (auto& w : m_vWindows) { - if (!w->m_bIsMapped || w->m_bFadingOut) - continue; + if (!pSurface || !pSurface->hlSurface) + return nullptr; - if (w->m_pWLSurface->resource() == pSurface) - return w; - } - - return nullptr; + return pSurface->hlSurface->getWindow(); } PHLWINDOW CCompositor::getWindowFromHandle(uint32_t handle) { From 72bce7efd5b302412f13485af27985965ddf830f Mon Sep 17 00:00:00 2001 From: MightyPlaza <123664421+MightyPlaza@users.noreply.github.com> Date: Wed, 24 Jul 2024 12:10:36 +0000 Subject: [PATCH 0153/2181] keybinds: add bindp and noshortcutsinhibit (#7017) --- src/config/ConfigManager.cpp | 8 +++++-- src/config/ConfigManager.hpp | 1 + src/desktop/Window.hpp | 37 +++++++++++++++--------------- src/managers/KeybindManager.cpp | 7 +++--- src/managers/KeybindManager.hpp | 1 + src/protocols/ShortcutsInhibit.cpp | 3 +++ 6 files changed, 34 insertions(+), 23 deletions(-) diff --git a/src/config/ConfigManager.cpp b/src/config/ConfigManager.cpp index 6928a802..5a8f2bd2 100644 --- a/src/config/ConfigManager.cpp +++ b/src/config/ConfigManager.cpp @@ -1983,6 +1983,7 @@ std::optional CConfigManager::handleBind(const std::string& command bool ignoreMods = false; bool multiKey = false; bool hasDescription = false; + bool dontInhibit = false; const auto BINDARGS = command.substr(4); for (auto& arg : BINDARGS) { @@ -2004,6 +2005,8 @@ std::optional CConfigManager::handleBind(const std::string& command multiKey = true; } else if (arg == 'd') { hasDescription = true; + } else if (arg == 'p') { + dontInhibit = true; } else { return "bind: invalid flag"; } @@ -2072,8 +2075,9 @@ std::optional CConfigManager::handleBind(const std::string& command return "Invalid catchall, catchall keybinds are only allowed in submaps."; } - g_pKeybindManager->addKeybind(SKeybind{parsedKey.key, KEYSYMS, parsedKey.keycode, parsedKey.catchAll, MOD, MODS, HANDLER, COMMAND, locked, m_szCurrentSubmap, DESCRIPTION, - release, repeat, mouse, nonConsuming, transparent, ignoreMods, multiKey, hasDescription}); + g_pKeybindManager->addKeybind(SKeybind{ + parsedKey.key, KEYSYMS, parsedKey.keycode, parsedKey.catchAll, MOD, MODS, HANDLER, COMMAND, locked, m_szCurrentSubmap, DESCRIPTION, release, + repeat, mouse, nonConsuming, transparent, ignoreMods, multiKey, hasDescription, dontInhibit}); } return {}; diff --git a/src/config/ConfigManager.hpp b/src/config/ConfigManager.hpp index df7c202b..b4a49b7a 100644 --- a/src/config/ConfigManager.hpp +++ b/src/config/ConfigManager.hpp @@ -182,6 +182,7 @@ class CConfigManager { {"nomaxsize", [](PHLWINDOW pWindow) { return &pWindow->m_sWindowData.noMaxSize; }}, {"norounding", [](PHLWINDOW pWindow) { return &pWindow->m_sWindowData.noRounding; }}, {"noshadow", [](PHLWINDOW pWindow) { return &pWindow->m_sWindowData.noShadow; }}, + {"noshortcutsinhibit", [](PHLWINDOW pWindow) { return &pWindow->m_sWindowData.noShortcutsInhibit; }}, {"opaque", [](PHLWINDOW pWindow) { return &pWindow->m_sWindowData.opaque; }}, {"forcergbx", [](PHLWINDOW pWindow) { return &pWindow->m_sWindowData.RGBX; }}, {"immediate", [](PHLWINDOW pWindow) { return &pWindow->m_sWindowData.tearing; }}, diff --git a/src/desktop/Window.hpp b/src/desktop/Window.hpp index 60189fac..108b804c 100644 --- a/src/desktop/Window.hpp +++ b/src/desktop/Window.hpp @@ -153,24 +153,25 @@ struct SWindowData { CWindowOverridableVar alphaInactive = SAlphaValue{1.f, false}; CWindowOverridableVar alphaFullscreen = SAlphaValue{1.f, false}; - CWindowOverridableVar allowsInput = false; - CWindowOverridableVar dimAround = false; - CWindowOverridableVar decorate = true; - CWindowOverridableVar focusOnActivate = false; - CWindowOverridableVar keepAspectRatio = false; - CWindowOverridableVar nearestNeighbor = false; - CWindowOverridableVar noAnim = false; - CWindowOverridableVar noBorder = false; - CWindowOverridableVar noBlur = false; - CWindowOverridableVar noDim = false; - CWindowOverridableVar noFocus = false; - CWindowOverridableVar noMaxSize = false; - CWindowOverridableVar noRounding = false; - CWindowOverridableVar noShadow = false; - CWindowOverridableVar opaque = false; - CWindowOverridableVar RGBX = false; - CWindowOverridableVar tearing = false; - CWindowOverridableVar xray = false; + CWindowOverridableVar allowsInput = false; + CWindowOverridableVar dimAround = false; + CWindowOverridableVar decorate = true; + CWindowOverridableVar focusOnActivate = false; + CWindowOverridableVar keepAspectRatio = false; + CWindowOverridableVar nearestNeighbor = false; + CWindowOverridableVar noAnim = false; + CWindowOverridableVar noBorder = false; + CWindowOverridableVar noBlur = false; + CWindowOverridableVar noDim = false; + CWindowOverridableVar noFocus = false; + CWindowOverridableVar noMaxSize = false; + CWindowOverridableVar noRounding = false; + CWindowOverridableVar noShadow = false; + CWindowOverridableVar noShortcutsInhibit = false; + CWindowOverridableVar opaque = false; + CWindowOverridableVar RGBX = false; + CWindowOverridableVar tearing = false; + CWindowOverridableVar xray = false; CWindowOverridableVar rounding; CWindowOverridableVar borderSize; diff --git a/src/managers/KeybindManager.cpp b/src/managers/KeybindManager.cpp index e9dfd1ae..185426dd 100644 --- a/src/managers/KeybindManager.cpp +++ b/src/managers/KeybindManager.cpp @@ -607,10 +607,8 @@ bool CKeybindManager::handleKeybinds(const uint32_t modmask, const SPressedKeyWi static auto PDISABLEINHIBIT = CConfigValue("binds:disable_keybind_grabbing"); - if (!*PDISABLEINHIBIT && PROTO::shortcutsInhibit->isInhibited()) { + if (!*PDISABLEINHIBIT && PROTO::shortcutsInhibit->isInhibited()) Debug::log(LOG, "Keybind handling is disabled due to an inhibitor"); - return false; - } for (auto& k : m_lKeybinds) { const bool SPECIALDISPATCHER = k.handler == "global" || k.handler == "pass" || k.handler == "sendshortcut" || k.handler == "mouse"; @@ -619,6 +617,9 @@ bool CKeybindManager::handleKeybinds(const uint32_t modmask, const SPressedKeyWi const bool IGNORECONDITIONS = SPECIALDISPATCHER && !pressed && SPECIALTRIGGERED; // ignore mods. Pass, global dispatchers should be released immediately once the key is released. + if (!k.dontInhibit && !*PDISABLEINHIBIT && PROTO::shortcutsInhibit->isInhibited()) + continue; + if (!k.locked && g_pSessionLockManager->isSessionLocked()) continue; diff --git a/src/managers/KeybindManager.hpp b/src/managers/KeybindManager.hpp index 284280cd..e3ba2f2d 100644 --- a/src/managers/KeybindManager.hpp +++ b/src/managers/KeybindManager.hpp @@ -34,6 +34,7 @@ struct SKeybind { bool ignoreMods = false; bool multiKey = false; bool hasDescription = false; + bool dontInhibit = false; // DO NOT INITIALIZE bool shadowed = false; diff --git a/src/protocols/ShortcutsInhibit.cpp b/src/protocols/ShortcutsInhibit.cpp index 211a7a01..226fccb6 100644 --- a/src/protocols/ShortcutsInhibit.cpp +++ b/src/protocols/ShortcutsInhibit.cpp @@ -73,6 +73,9 @@ bool CKeyboardShortcutsInhibitProtocol::isInhibited() { if (!g_pCompositor->m_pLastFocus) return false; + if (g_pCompositor->getWindowFromSurface(g_pCompositor->m_pLastFocus.lock())->m_sWindowData.noShortcutsInhibit.valueOrDefault()) + return false; + for (auto& in : m_vInhibitors) { if (in->surface() != g_pCompositor->m_pLastFocus) continue; From fe1975488725c006f4dc4575c1eb1df84ed1a893 Mon Sep 17 00:00:00 2001 From: Vaxry Date: Wed, 24 Jul 2024 16:26:44 +0200 Subject: [PATCH 0154/2181] shortcutsInhibit: fix crash --- src/protocols/ShortcutsInhibit.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/protocols/ShortcutsInhibit.cpp b/src/protocols/ShortcutsInhibit.cpp index 226fccb6..1a0433e6 100644 --- a/src/protocols/ShortcutsInhibit.cpp +++ b/src/protocols/ShortcutsInhibit.cpp @@ -73,7 +73,7 @@ bool CKeyboardShortcutsInhibitProtocol::isInhibited() { if (!g_pCompositor->m_pLastFocus) return false; - if (g_pCompositor->getWindowFromSurface(g_pCompositor->m_pLastFocus.lock())->m_sWindowData.noShortcutsInhibit.valueOrDefault()) + if (const auto PWINDOW = g_pCompositor->getWindowFromSurface(g_pCompositor->m_pLastFocus.lock()); PWINDOW && PWINDOW->m_sWindowData.noShortcutsInhibit.valueOrDefault()) return false; for (auto& in : m_vInhibitors) { From f2b6ebbf5427c319c7b3c9621a98751598b360f9 Mon Sep 17 00:00:00 2001 From: MightyPlaza <123664421+MightyPlaza@users.noreply.github.com> Date: Wed, 24 Jul 2024 15:42:45 +0000 Subject: [PATCH 0155/2181] keybinds: remove toggleopaque (#7024) modified: src/managers/KeybindManager.cpp modified: src/managers/KeybindManager.hpp --- src/managers/KeybindManager.cpp | 12 ------------ src/managers/KeybindManager.hpp | 1 - 2 files changed, 13 deletions(-) diff --git a/src/managers/KeybindManager.cpp b/src/managers/KeybindManager.cpp index 185426dd..fda27598 100644 --- a/src/managers/KeybindManager.cpp +++ b/src/managers/KeybindManager.cpp @@ -101,7 +101,6 @@ CKeybindManager::CKeybindManager() { m_mDispatchers["pass"] = pass; m_mDispatchers["sendshortcut"] = sendshortcut; m_mDispatchers["layoutmsg"] = layoutmsg; - m_mDispatchers["toggleopaque"] = toggleOpaque; m_mDispatchers["dpms"] = dpms; m_mDispatchers["movewindowpixel"] = moveWindow; m_mDispatchers["resizewindowpixel"] = resizeWindow; @@ -2237,17 +2236,6 @@ void CKeybindManager::layoutmsg(std::string msg) { g_pLayoutManager->getCurrentLayout()->layoutMessage(hd, msg); } -void CKeybindManager::toggleOpaque(std::string unused) { - const auto PWINDOW = g_pCompositor->m_pLastWindow.lock(); - - if (!PWINDOW) - return; - - PWINDOW->m_sWindowData.opaque = CWindowOverridableVar(!PWINDOW->m_sWindowData.opaque.valueOrDefault(), PRIORITY_SET_PROP); - - g_pHyprRenderer->damageWindow(PWINDOW); -} - void CKeybindManager::dpms(std::string arg) { bool enable = arg.starts_with("on"); std::string port = ""; diff --git a/src/managers/KeybindManager.hpp b/src/managers/KeybindManager.hpp index e3ba2f2d..7201df04 100644 --- a/src/managers/KeybindManager.hpp +++ b/src/managers/KeybindManager.hpp @@ -190,7 +190,6 @@ class CKeybindManager { static void pass(std::string); static void sendshortcut(std::string); static void layoutmsg(std::string); - static void toggleOpaque(std::string); static void dpms(std::string); static void swapnext(std::string); static void swapActiveWorkspaces(std::string); From b16fb9770ca984fb4e0f44e188b0786180afb8ba Mon Sep 17 00:00:00 2001 From: Vaxry Date: Wed, 24 Jul 2024 17:48:38 +0200 Subject: [PATCH 0156/2181] egl: support getting the device via platform_device a neat EXT --- src/render/OpenGL.cpp | 93 ++++++++++++++++++++++++++++++++++++------- src/render/OpenGL.hpp | 2 + 2 files changed, 81 insertions(+), 14 deletions(-) diff --git a/src/render/OpenGL.cpp b/src/render/OpenGL.cpp index 15b3cad8..ab7f566a 100644 --- a/src/render/OpenGL.cpp +++ b/src/render/OpenGL.cpp @@ -101,7 +101,7 @@ void CHyprOpenGLImpl::initEGL(bool gbm) { attrs.push_back(EGL_NONE); - m_pEglDisplay = m_sProc.eglGetPlatformDisplayEXT(gbm ? EGL_PLATFORM_GBM_KHR : EGL_PLATFORM_DEVICE_EXT, gbm ? m_pGbmDevice : nullptr, attrs.data()); + m_pEglDisplay = m_sProc.eglGetPlatformDisplayEXT(gbm ? EGL_PLATFORM_GBM_KHR : EGL_PLATFORM_DEVICE_EXT, gbm ? m_pGbmDevice : m_pEglDevice, attrs.data()); if (m_pEglDisplay == EGL_NO_DISPLAY) RASSERT(false, "EGL: failed to create a platform display"); @@ -158,6 +158,60 @@ void CHyprOpenGLImpl::initEGL(bool gbm) { eglMakeCurrent(m_pEglDisplay, EGL_NO_SURFACE, EGL_NO_SURFACE, m_pEglContext); } +static bool drmDeviceHasName(const drmDevice* device, const std::string& name) { + for (size_t i = 0; i < DRM_NODE_MAX; i++) { + if (!(device->available_nodes & (1 << i))) + continue; + + if (device->nodes[i] == name) + return true; + } + return false; +} + +EGLDeviceEXT CHyprOpenGLImpl::eglDeviceFromDRMFD(int drmFD) { + EGLint nDevices = 0; + if (!m_sProc.eglQueryDevicesEXT(0, nullptr, &nDevices)) { + Debug::log(ERR, "eglDeviceFromDRMFD: eglQueryDevicesEXT failed"); + return EGL_NO_DEVICE_EXT; + } + + if (nDevices <= 0) { + Debug::log(ERR, "eglDeviceFromDRMFD: no devices"); + return EGL_NO_DEVICE_EXT; + } + + std::vector devices; + devices.resize(nDevices); + + if (!m_sProc.eglQueryDevicesEXT(nDevices, devices.data(), &nDevices)) { + Debug::log(ERR, "eglDeviceFromDRMFD: eglQueryDevicesEXT failed (2)"); + return EGL_NO_DEVICE_EXT; + } + + drmDevice* drmDev = nullptr; + if (int ret = drmGetDevice(drmFD, &drmDev); ret < 0) { + Debug::log(ERR, "eglDeviceFromDRMFD: drmGetDevice failed"); + return EGL_NO_DEVICE_EXT; + } + + for (auto& d : devices) { + auto devName = m_sProc.eglQueryDeviceStringEXT(d, EGL_DRM_DEVICE_FILE_EXT); + if (!devName) + continue; + + if (drmDeviceHasName(drmDev, devName)) { + Debug::log(LOG, "eglDeviceFromDRMFD: Using device {}", devName); + drmFreeDevice(&drmDev); + return d; + } + } + + drmFreeDevice(&drmDev); + Debug::log(LOG, "eglDeviceFromDRMFD: No drm devices found"); + return EGL_NO_DEVICE_EXT; +} + CHyprOpenGLImpl::CHyprOpenGLImpl() { const std::string EGLEXTENSIONS = (const char*)eglQueryString(EGL_NO_DISPLAY, EGL_EXTENSIONS); @@ -202,22 +256,33 @@ CHyprOpenGLImpl::CHyprOpenGLImpl() { RASSERT(eglBindAPI(EGL_OPENGL_ES_API) != EGL_FALSE, "Couldn't bind to EGL's opengl ES API. This means your gpu driver f'd up. This is not a hyprland issue."); - // if (m_sProc.eglQueryDevicesEXT) { - // // TODO: - // } + bool success = false; + if (EGLEXTENSIONS.contains("EXT_platform_device") || !m_sProc.eglQueryDevicesEXT || !m_sProc.eglQueryDeviceStringEXT) { + m_pEglDevice = eglDeviceFromDRMFD(m_iDRMFD); - if (EGLEXTENSIONS.contains("KHR_platform_gbm")) { - m_iGBMFD = openRenderNode(m_iDRMFD); - if (m_iGBMFD < 0) - RASSERT(false, "Couldn't open a gbm fd"); + if (m_pEglDevice != EGL_NO_DEVICE_EXT) { + success = true; + initEGL(false); + } + } - m_pGbmDevice = gbm_create_device(m_iGBMFD); - if (!m_pGbmDevice) - RASSERT(false, "Couldn't open a gbm device"); + if (!success) { + Debug::log(WARN, "EGL: EXT_platform_device or EGL_EXT_device_query not supported, using gbm"); + if (EGLEXTENSIONS.contains("KHR_platform_gbm")) { + success = true; + m_iGBMFD = openRenderNode(m_iDRMFD); + if (m_iGBMFD < 0) + RASSERT(false, "Couldn't open a gbm fd"); - initEGL(true); - } else - RASSERT(false, "EGL does not support KHR_platform_gbm, this is an issue with your gpu driver."); + m_pGbmDevice = gbm_create_device(m_iGBMFD); + if (!m_pGbmDevice) + RASSERT(false, "Couldn't open a gbm device"); + + initEGL(true); + } + } + + RASSERT(success, "EGL does not support KHR_platform_gbm or EXT_platform_device, this is an issue with your gpu driver."); auto* const EXTENSIONS = (const char*)glGetString(GL_EXTENSIONS); RASSERT(EXTENSIONS, "Couldn't retrieve openGL extensions!"); diff --git a/src/render/OpenGL.hpp b/src/render/OpenGL.hpp index 712b87f3..5c4ee811 100644 --- a/src/render/OpenGL.hpp +++ b/src/render/OpenGL.hpp @@ -216,6 +216,7 @@ class CHyprOpenGLImpl { gbm_device* m_pGbmDevice = nullptr; EGLContext m_pEglContext = nullptr; EGLDisplay m_pEglDisplay = nullptr; + EGLDeviceEXT m_pEglDevice = nullptr; bool m_bReloadScreenShader = true; // at launch it can be set @@ -280,6 +281,7 @@ class CHyprOpenGLImpl { void initShaders(); void initDRMFormats(); void initEGL(bool gbm); + EGLDeviceEXT eglDeviceFromDRMFD(int drmFD); // std::optional> getModsForFormat(EGLint format); From 735e3c6c56d22059ee6340c0327e4b5a9154f013 Mon Sep 17 00:00:00 2001 From: MightyPlaza <123664421+MightyPlaza@users.noreply.github.com> Date: Wed, 24 Jul 2024 17:05:54 +0000 Subject: [PATCH 0157/2181] crashreporter: add date and flags to crash report (#7028) modified: src/debug/CrashReporter.cpp --- src/debug/CrashReporter.cpp | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/src/debug/CrashReporter.cpp b/src/debug/CrashReporter.cpp index c25212fe..c31975b8 100644 --- a/src/debug/CrashReporter.cpp +++ b/src/debug/CrashReporter.cpp @@ -105,7 +105,19 @@ void CrashReporter::createAndSaveCrash(int sig) { finalCrashReport += GIT_COMMIT_HASH; finalCrashReport += "\nTag: "; finalCrashReport += GIT_TAG; - finalCrashReport += "\n\n"; + finalCrashReport += "\nDate: "; + finalCrashReport += GIT_COMMIT_DATE; + finalCrashReport += "\nFlags:\n"; +#ifdef LEGACY_RENDERER + finalCrashReport += "legacyrenderer\n"; +#endif +#ifndef ISDEBUG + finalCrashReport += "debug\n"; +#endif +#ifdef NO_XWAYLAND + finalCrashReport += "no xwayland\n"; +#endif + finalCrashReport += "\n"; if (g_pPluginSystem && g_pPluginSystem->pluginCount() > 0) { finalCrashReport += "Hyprland seems to be running with plugins. This crash might not be Hyprland's fault.\nPlugins:\n"; From 3e543d2ce8ba64abb4d226dbb88c4513474501cf Mon Sep 17 00:00:00 2001 From: Ikalco <73481042+ikalco@users.noreply.github.com> Date: Wed, 24 Jul 2024 12:07:36 -0500 Subject: [PATCH 0158/2181] core: Properly shutdown wl display (#7018) * correctly destroy wayland globals * properly shutdown and cleanup hyprland * appease the nitpick gods and some comments --- src/Compositor.cpp | 24 +++++---- src/Compositor.hpp | 1 + src/main.cpp | 6 +-- src/managers/KeybindManager.cpp | 2 +- src/managers/ProtocolManager.cpp | 54 +++++++++++++++++++++ src/managers/ProtocolManager.hpp | 1 + src/managers/eventLoop/EventLoopManager.cpp | 6 +++ src/protocols/GlobalShortcuts.cpp | 11 ++++- src/protocols/GlobalShortcuts.hpp | 7 ++- src/protocols/Screencopy.cpp | 9 +++- src/protocols/Screencopy.hpp | 21 ++++---- src/protocols/TextInputV1.cpp | 11 ++++- src/protocols/TextInputV1.hpp | 28 ++++++----- src/protocols/ToplevelExport.cpp | 9 +++- src/protocols/ToplevelExport.hpp | 23 ++++----- src/protocols/WaylandProtocol.cpp | 3 +- src/protocols/WaylandProtocol.hpp | 5 +- 17 files changed, 161 insertions(+), 60 deletions(-) diff --git a/src/Compositor.cpp b/src/Compositor.cpp index 7caaa98a..36f483fd 100644 --- a/src/Compositor.cpp +++ b/src/Compositor.cpp @@ -43,7 +43,7 @@ int handleCritSignal(int signo, void* data) { Debug::log(LOG, "Hyprland received signal {}", signo); if (signo == SIGTERM || signo == SIGINT || signo == SIGKILL) - g_pCompositor->cleanup(); + g_pCompositor->stopCompositor(); return 0; } @@ -193,7 +193,8 @@ CCompositor::CCompositor() { } CCompositor::~CCompositor() { - cleanup(); + if (!m_bIsShuttingDown) + cleanup(); } void CCompositor::setRandomSplash() { @@ -432,8 +433,16 @@ void CCompositor::cleanEnvironment() { } } +void CCompositor::stopCompositor() { + Debug::log(LOG, "Hyprland is stopping!"); + + // this stops the wayland loop, wl_display_run + wl_display_terminate(m_sWLDisplay); + m_bIsShuttingDown = true; +} + void CCompositor::cleanup() { - if (!m_sWLDisplay || m_bIsShuttingDown) + if (!m_sWLDisplay) return; signal(SIGABRT, SIG_DFL); @@ -507,13 +516,8 @@ void CCompositor::cleanup() { if (m_critSigSource) wl_event_source_remove(m_critSigSource); - wl_event_loop_destroy(m_sWLEventLoop); - wl_display_terminate(m_sWLDisplay); - m_sWLDisplay = nullptr; - - std::string waylandSocket = std::string{getenv("XDG_RUNTIME_DIR")} + "/" + m_szWLDisplaySocket; - std::filesystem::remove(waylandSocket); - std::filesystem::remove(waylandSocket + ".lock"); + // this frees all wayland resources, including sockets + wl_display_destroy(m_sWLDisplay); } void CCompositor::initManagers(eManagersInitStage stage) { diff --git a/src/Compositor.hpp b/src/Compositor.hpp index a274ca58..da390b44 100644 --- a/src/Compositor.hpp +++ b/src/Compositor.hpp @@ -71,6 +71,7 @@ class CCompositor { void initServer(std::string socketName, int socketFd); void startCompositor(); + void stopCompositor(); void cleanup(); void createLockFile(); void removeLockFile(); diff --git a/src/main.cpp b/src/main.cpp index 3e51c6c8..e85b0a22 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -157,11 +157,9 @@ int main(int argc, char** argv) { // If all's good to go, start. g_pCompositor->startCompositor(); - g_pCompositor->m_bIsShuttingDown = true; + g_pCompositor->cleanup(); - // If we are here it means we got yote. - Debug::log(LOG, "Hyprland reached the end."); - g_pCompositor.reset(); + Debug::log(LOG, "Hyprland has reached the end."); return EXIT_SUCCESS; } diff --git a/src/managers/KeybindManager.cpp b/src/managers/KeybindManager.cpp index fda27598..ed76575a 100644 --- a/src/managers/KeybindManager.cpp +++ b/src/managers/KeybindManager.cpp @@ -1662,7 +1662,7 @@ void CKeybindManager::renameWorkspace(std::string args) { } void CKeybindManager::exitHyprland(std::string argz) { - g_pEventLoopManager->doLater([]() { g_pCompositor->cleanup(); }); + g_pCompositor->stopCompositor(); } void CKeybindManager::moveCurrentWorkspaceToMonitor(std::string args) { diff --git a/src/managers/ProtocolManager.cpp b/src/managers/ProtocolManager.cpp index 5a44680f..ef2260cc 100644 --- a/src/managers/ProtocolManager.cpp +++ b/src/managers/ProtocolManager.cpp @@ -166,3 +166,57 @@ CProtocolManager::CProtocolManager() { m_pGlobalShortcutsProtocolManager = std::make_unique(); m_pScreencopyProtocolManager = std::make_unique(); } + +CProtocolManager::~CProtocolManager() { + // this is dumb but i don't want to replace all 600 PROTO with the right thing + + // Output + PROTO::outputs.clear(); + + // Core + PROTO::seat.reset(); + PROTO::data.reset(); + PROTO::compositor.reset(); + PROTO::subcompositor.reset(); + PROTO::shm.reset(); + + // Extensions + PROTO::viewport.reset(); + PROTO::tearing.reset(); + PROTO::fractional.reset(); + PROTO::xdgOutput.reset(); + PROTO::cursorShape.reset(); + PROTO::idleInhibit.reset(); + PROTO::relativePointer.reset(); + PROTO::xdgDecoration.reset(); + PROTO::alphaModifier.reset(); + PROTO::gamma.reset(); + PROTO::foreignToplevel.reset(); + PROTO::pointerGestures.reset(); + PROTO::foreignToplevelWlr.reset(); + PROTO::shortcutsInhibit.reset(); + PROTO::textInputV3.reset(); + PROTO::constraints.reset(); + PROTO::outputPower.reset(); + PROTO::activation.reset(); + PROTO::idle.reset(); + PROTO::sessionLock.reset(); + PROTO::ime.reset(); + PROTO::virtualKeyboard.reset(); + PROTO::virtualPointer.reset(); + PROTO::outputManagement.reset(); + PROTO::serverDecorationKDE.reset(); + PROTO::focusGrab.reset(); + PROTO::tablet.reset(); + PROTO::layerShell.reset(); + PROTO::presentation.reset(); + PROTO::xdgShell.reset(); + PROTO::dataWlr.reset(); + PROTO::primarySelection.reset(); + PROTO::xwaylandShell.reset(); + + PROTO::lease.reset(); + PROTO::sync.reset(); + PROTO::mesaDRM.reset(); + PROTO::linuxDma.reset(); +} diff --git a/src/managers/ProtocolManager.hpp b/src/managers/ProtocolManager.hpp index 91fb82a0..6a780bdc 100644 --- a/src/managers/ProtocolManager.hpp +++ b/src/managers/ProtocolManager.hpp @@ -12,6 +12,7 @@ class CProtocolManager { public: CProtocolManager(); + ~CProtocolManager(); // TODO: rewrite to use the new protocol framework std::unique_ptr m_pToplevelExportProtocolManager; diff --git a/src/managers/eventLoop/EventLoopManager.cpp b/src/managers/eventLoop/EventLoopManager.cpp index ed7a4f72..3131531a 100644 --- a/src/managers/eventLoop/EventLoopManager.cpp +++ b/src/managers/eventLoop/EventLoopManager.cpp @@ -19,8 +19,14 @@ CEventLoopManager::CEventLoopManager(wl_display* display, wl_event_loop* wlEvent } CEventLoopManager::~CEventLoopManager() { + for (auto& eventSource : m_sWayland.aqEventSources) { + wl_event_source_remove(eventSource); + } + if (m_sWayland.eventSource) wl_event_source_remove(m_sWayland.eventSource); + if (m_sIdle.eventSource) + wl_event_source_remove(m_sIdle.eventSource); } static int timerWrite(int fd, uint32_t mask, void* data) { diff --git a/src/protocols/GlobalShortcuts.cpp b/src/protocols/GlobalShortcuts.cpp index b376cae3..898f0e07 100644 --- a/src/protocols/GlobalShortcuts.cpp +++ b/src/protocols/GlobalShortcuts.cpp @@ -8,13 +8,20 @@ static void bindManagerInt(wl_client* client, void* data, uint32_t version, uint } static void handleDisplayDestroy(struct wl_listener* listener, void* data) { - g_pProtocolManager->m_pGlobalShortcutsProtocolManager->displayDestroy(); + CGlobalShortcutsProtocolManager* proto = wl_container_of(listener, proto, m_liDisplayDestroy); + proto->displayDestroy(); } void CGlobalShortcutsProtocolManager::displayDestroy() { + wl_list_remove(&m_liDisplayDestroy.link); + wl_list_init(&m_liDisplayDestroy.link); wl_global_destroy(m_pGlobal); } +CGlobalShortcutsProtocolManager::~CGlobalShortcutsProtocolManager() { + displayDestroy(); +} + CGlobalShortcutsProtocolManager::CGlobalShortcutsProtocolManager() { m_pGlobal = wl_global_create(g_pCompositor->m_sWLDisplay, &hyprland_global_shortcuts_manager_v1_interface, GLOBAL_SHORTCUTS_VERSION, this, bindManagerInt); @@ -148,4 +155,4 @@ void CGlobalShortcutsProtocolManager::destroyShortcut(wl_resource* resource) { for (auto& c : m_vClients) { std::erase_if(c->shortcuts, [&](const auto& other) { return other->resource == resource; }); } -} \ No newline at end of file +} diff --git a/src/protocols/GlobalShortcuts.hpp b/src/protocols/GlobalShortcuts.hpp index 07c484c6..5fd03465 100644 --- a/src/protocols/GlobalShortcuts.hpp +++ b/src/protocols/GlobalShortcuts.hpp @@ -17,6 +17,8 @@ struct SShortcutClient { class CGlobalShortcutsProtocolManager { public: CGlobalShortcutsProtocolManager(); + ~CGlobalShortcutsProtocolManager(); + void bindManager(wl_client* client, void* data, uint32_t version, uint32_t id); void displayDestroy(); @@ -29,11 +31,12 @@ class CGlobalShortcutsProtocolManager { std::vector getAllShortcuts(); + wl_listener m_liDisplayDestroy; + private: std::vector> m_vClients; SShortcutClient* clientFromWlClient(wl_client* client); wl_global* m_pGlobal = nullptr; - wl_listener m_liDisplayDestroy; -}; \ No newline at end of file +}; diff --git a/src/protocols/Screencopy.cpp b/src/protocols/Screencopy.cpp index 5d1c9332..98cb0be9 100644 --- a/src/protocols/Screencopy.cpp +++ b/src/protocols/Screencopy.cpp @@ -16,15 +16,22 @@ static void bindManagerInt(wl_client* client, void* data, uint32_t version, uint } static void handleDisplayDestroy(struct wl_listener* listener, void* data) { - g_pProtocolManager->m_pScreencopyProtocolManager->displayDestroy(); + CScreencopyProtocolManager* proto = wl_container_of(listener, proto, m_liDisplayDestroy); + proto->displayDestroy(); } void CScreencopyProtocolManager::displayDestroy() { + wl_list_remove(&m_liDisplayDestroy.link); + wl_list_init(&m_liDisplayDestroy.link); wl_global_destroy(m_pGlobal); } static SScreencopyFrame* frameFromResource(wl_resource*); +CScreencopyProtocolManager::~CScreencopyProtocolManager() { + displayDestroy(); +} + CScreencopyProtocolManager::CScreencopyProtocolManager() { m_pGlobal = wl_global_create(g_pCompositor->m_sWLDisplay, &zwlr_screencopy_manager_v1_interface, SCREENCOPY_VERSION, this, bindManagerInt); diff --git a/src/protocols/Screencopy.hpp b/src/protocols/Screencopy.hpp index 4999773b..d564e432 100644 --- a/src/protocols/Screencopy.hpp +++ b/src/protocols/Screencopy.hpp @@ -70,17 +70,20 @@ struct SScreencopyFrame { class CScreencopyProtocolManager { public: CScreencopyProtocolManager(); + ~CScreencopyProtocolManager(); - void bindManager(wl_client* client, void* data, uint32_t version, uint32_t id); - void removeClient(CScreencopyClient* client, bool force = false); - void removeFrame(SScreencopyFrame* frame, bool force = false); - void displayDestroy(); + void bindManager(wl_client* client, void* data, uint32_t version, uint32_t id); + void removeClient(CScreencopyClient* client, bool force = false); + void removeFrame(SScreencopyFrame* frame, bool force = false); + void displayDestroy(); - void captureOutput(wl_client* client, wl_resource* resource, uint32_t frame, int32_t overlay_cursor, wl_resource* output, CBox box = {0, 0, 0, 0}); + void captureOutput(wl_client* client, wl_resource* resource, uint32_t frame, int32_t overlay_cursor, wl_resource* output, CBox box = {0, 0, 0, 0}); - void copyFrame(wl_client* client, wl_resource* resource, wl_resource* buffer); + void copyFrame(wl_client* client, wl_resource* resource, wl_resource* buffer); - void onOutputCommit(CMonitor* pMonitor); + void onOutputCommit(CMonitor* pMonitor); + + wl_listener m_liDisplayDestroy; private: wl_global* m_pGlobal = nullptr; @@ -90,8 +93,6 @@ class CScreencopyProtocolManager { SP m_pSoftwareCursorTimer; bool m_bTimerArmed = false; - wl_listener m_liDisplayDestroy; - std::vector m_vFramesAwaitingWrite; SP m_pLastMonitorBackBuffer; @@ -103,4 +104,4 @@ class CScreencopyProtocolManager { bool copyFrameShm(SScreencopyFrame* frame, timespec* now); friend class CScreencopyClient; -}; \ No newline at end of file +}; diff --git a/src/protocols/TextInputV1.cpp b/src/protocols/TextInputV1.cpp index 7c16ef8c..12068671 100644 --- a/src/protocols/TextInputV1.cpp +++ b/src/protocols/TextInputV1.cpp @@ -10,13 +10,20 @@ static void bindManagerInt(wl_client* client, void* data, uint32_t version, uint } static void handleDisplayDestroy(struct wl_listener* listener, void* data) { - g_pProtocolManager->m_pTextInputV1ProtocolManager->displayDestroy(); + CTextInputV1ProtocolManager* proto = wl_container_of(listener, proto, m_liDisplayDestroy); + proto->displayDestroy(); } void CTextInputV1ProtocolManager::displayDestroy() { + wl_list_remove(&m_liDisplayDestroy.link); + wl_list_init(&m_liDisplayDestroy.link); wl_global_destroy(m_pGlobal); } +CTextInputV1ProtocolManager::~CTextInputV1ProtocolManager() { + displayDestroy(); +} + CTextInputV1ProtocolManager::CTextInputV1ProtocolManager() { m_pGlobal = wl_global_create(g_pCompositor->m_sWLDisplay, &zwp_text_input_manager_v1_interface, TEXT_INPUT_VERSION, this, bindManagerInt); @@ -220,4 +227,4 @@ void CTextInputV1ProtocolManager::handleCommitState(wl_client* client, wl_resour void CTextInputV1ProtocolManager::handleInvokeAction(wl_client* client, wl_resource* resource, uint32_t button, uint32_t index) { ; -} \ No newline at end of file +} diff --git a/src/protocols/TextInputV1.hpp b/src/protocols/TextInputV1.hpp index 0a1203f0..e56a8990 100644 --- a/src/protocols/TextInputV1.hpp +++ b/src/protocols/TextInputV1.hpp @@ -47,6 +47,7 @@ struct STextInputV1 { class CTextInputV1ProtocolManager { public: CTextInputV1ProtocolManager(); + ~CTextInputV1ProtocolManager(); void bindManager(wl_client* client, void* data, uint32_t version, uint32_t id); void createTI(wl_client* client, wl_resource* resource, uint32_t id); @@ -55,21 +56,22 @@ class CTextInputV1ProtocolManager { void displayDestroy(); // handlers for tiv1 - void handleActivate(wl_client* client, wl_resource* resource, wl_resource* seat, wl_resource* surface); - void handleDeactivate(wl_client* client, wl_resource* resource, wl_resource* seat); - void handleShowInputPanel(wl_client* client, wl_resource* resource); - void handleHideInputPanel(wl_client* client, wl_resource* resource); - void handleReset(wl_client* client, wl_resource* resource); - void handleSetSurroundingText(wl_client* client, wl_resource* resource, const char* text, uint32_t cursor, uint32_t anchor); - void handleSetContentType(wl_client* client, wl_resource* resource, uint32_t hint, uint32_t purpose); - void handleSetCursorRectangle(wl_client* client, wl_resource* resource, int32_t x, int32_t y, int32_t width, int32_t height); - void handleSetPreferredLanguage(wl_client* client, wl_resource* resource, const char* language); - void handleCommitState(wl_client* client, wl_resource* resource, uint32_t serial); - void handleInvokeAction(wl_client* client, wl_resource* resource, uint32_t button, uint32_t index); + void handleActivate(wl_client* client, wl_resource* resource, wl_resource* seat, wl_resource* surface); + void handleDeactivate(wl_client* client, wl_resource* resource, wl_resource* seat); + void handleShowInputPanel(wl_client* client, wl_resource* resource); + void handleHideInputPanel(wl_client* client, wl_resource* resource); + void handleReset(wl_client* client, wl_resource* resource); + void handleSetSurroundingText(wl_client* client, wl_resource* resource, const char* text, uint32_t cursor, uint32_t anchor); + void handleSetContentType(wl_client* client, wl_resource* resource, uint32_t hint, uint32_t purpose); + void handleSetCursorRectangle(wl_client* client, wl_resource* resource, int32_t x, int32_t y, int32_t width, int32_t height); + void handleSetPreferredLanguage(wl_client* client, wl_resource* resource, const char* language); + void handleCommitState(wl_client* client, wl_resource* resource, uint32_t serial); + void handleInvokeAction(wl_client* client, wl_resource* resource, uint32_t button, uint32_t index); + + wl_listener m_liDisplayDestroy; private: wl_global* m_pGlobal = nullptr; - wl_listener m_liDisplayDestroy; std::vector> m_pClients; -}; \ No newline at end of file +}; diff --git a/src/protocols/ToplevelExport.cpp b/src/protocols/ToplevelExport.cpp index e982ad6f..28f49c6a 100644 --- a/src/protocols/ToplevelExport.cpp +++ b/src/protocols/ToplevelExport.cpp @@ -15,13 +15,20 @@ static void bindManagerInt(wl_client* client, void* data, uint32_t version, uint } static void handleDisplayDestroy(struct wl_listener* listener, void* data) { - g_pProtocolManager->m_pToplevelExportProtocolManager->displayDestroy(); + CToplevelExportProtocolManager* proto = wl_container_of(listener, proto, m_liDisplayDestroy); + proto->displayDestroy(); } void CToplevelExportProtocolManager::displayDestroy() { + wl_list_remove(&m_liDisplayDestroy.link); + wl_list_init(&m_liDisplayDestroy.link); wl_global_destroy(m_pGlobal); } +CToplevelExportProtocolManager::~CToplevelExportProtocolManager() { + displayDestroy(); +} + CToplevelExportProtocolManager::CToplevelExportProtocolManager() { #ifndef GLES32 diff --git a/src/protocols/ToplevelExport.hpp b/src/protocols/ToplevelExport.hpp index c3620d41..71a6df18 100644 --- a/src/protocols/ToplevelExport.hpp +++ b/src/protocols/ToplevelExport.hpp @@ -13,23 +13,24 @@ class CWindow; class CToplevelExportProtocolManager { public: CToplevelExportProtocolManager(); + ~CToplevelExportProtocolManager(); - void bindManager(wl_client* client, void* data, uint32_t version, uint32_t id); - void captureToplevel(wl_client* client, wl_resource* resource, uint32_t frame, int32_t overlay_cursor, PHLWINDOW handle); - void removeClient(CScreencopyClient* client, bool force = false); - void removeFrame(SScreencopyFrame* frame, bool force = false); - void copyFrame(wl_client* client, wl_resource* resource, wl_resource* buffer, int32_t ignore_damage); - void displayDestroy(); - void onWindowUnmap(PHLWINDOW pWindow); - void onOutputCommit(CMonitor* pMonitor); + void bindManager(wl_client* client, void* data, uint32_t version, uint32_t id); + void captureToplevel(wl_client* client, wl_resource* resource, uint32_t frame, int32_t overlay_cursor, PHLWINDOW handle); + void removeClient(CScreencopyClient* client, bool force = false); + void removeFrame(SScreencopyFrame* frame, bool force = false); + void copyFrame(wl_client* client, wl_resource* resource, wl_resource* buffer, int32_t ignore_damage); + void displayDestroy(); + void onWindowUnmap(PHLWINDOW pWindow); + void onOutputCommit(CMonitor* pMonitor); + + wl_listener m_liDisplayDestroy; private: wl_global* m_pGlobal = nullptr; std::list m_lFrames; std::list m_lClients; - wl_listener m_liDisplayDestroy; - std::vector m_vFramesAwaitingWrite; void shareFrame(SScreencopyFrame* frame); @@ -38,4 +39,4 @@ class CToplevelExportProtocolManager { void sendDamage(SScreencopyFrame* frame); friend class CScreencopyClient; -}; \ No newline at end of file +}; diff --git a/src/protocols/WaylandProtocol.cpp b/src/protocols/WaylandProtocol.cpp index 23a6721c..71c43300 100644 --- a/src/protocols/WaylandProtocol.cpp +++ b/src/protocols/WaylandProtocol.cpp @@ -6,7 +6,8 @@ static void bindManagerInternal(wl_client* client, void* data, uint32_t ver, uin } static void displayDestroyInternal(struct wl_listener* listener, void* data) { - ((IWaylandProtocol*)data)->onDisplayDestroy(); + IWaylandProtocol* proto = wl_container_of(listener, proto, m_liDisplayDestroy); + proto->onDisplayDestroy(); } void IWaylandProtocol::onDisplayDestroy() { diff --git a/src/protocols/WaylandProtocol.hpp b/src/protocols/WaylandProtocol.hpp index b443e253..6154fa30 100644 --- a/src/protocols/WaylandProtocol.hpp +++ b/src/protocols/WaylandProtocol.hpp @@ -26,8 +26,9 @@ class IWaylandProtocol { Debug::log(level, std::format("[{}] ", m_szName) + std::vformat(fmt.get(), std::make_format_args(args...))); }; + wl_listener m_liDisplayDestroy; + private: std::string m_szName; wl_global* m_pGlobal = nullptr; - wl_listener m_liDisplayDestroy; -}; \ No newline at end of file +}; From a0be3de0e89f42b98d00bf0d87ad10af843d58d6 Mon Sep 17 00:00:00 2001 From: MightyPlaza <123664421+MightyPlaza@users.noreply.github.com> Date: Wed, 24 Jul 2024 18:00:25 +0000 Subject: [PATCH 0159/2181] keybinds: handle monitor change in moveWindowIntoGroup (#7030) modified: src/managers/KeybindManager.cpp --- src/managers/KeybindManager.cpp | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/managers/KeybindManager.cpp b/src/managers/KeybindManager.cpp index ed76575a..4232ea64 100644 --- a/src/managers/KeybindManager.cpp +++ b/src/managers/KeybindManager.cpp @@ -2478,6 +2478,11 @@ void CKeybindManager::moveWindowIntoGroup(PHLWINDOW pWindow, PHLWINDOW pWindowIn g_pLayoutManager->getCurrentLayout()->onWindowRemoved(pWindow); // This removes groupped property! + if (pWindow->m_iMonitorID != pWindowInDirection->m_iMonitorID) { + pWindow->moveToWorkspace(pWindowInDirection->m_pWorkspace); + pWindow->m_iMonitorID = pWindowInDirection->m_iMonitorID; + } + static auto USECURRPOS = CConfigValue("group:insert_after_current"); pWindowInDirection = *USECURRPOS ? pWindowInDirection : pWindowInDirection->getGroupTail(); From 381cb2d8330d09f8994ca01591fb3e3737e6a67a Mon Sep 17 00:00:00 2001 From: Mihai Fufezan Date: Wed, 24 Jul 2024 23:51:23 +0300 Subject: [PATCH 0160/2181] flake.lock: update aquamarine --- flake.lock | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/flake.lock b/flake.lock index 4545c61d..e8f7e259 100644 --- a/flake.lock +++ b/flake.lock @@ -16,11 +16,11 @@ ] }, "locked": { - "lastModified": 1721755137, - "narHash": "sha256-DcJkFNaHGRMIkexx/ol2oNiUFT/zqnZH6dwODdHubIU=", + "lastModified": 1721853718, + "narHash": "sha256-QEkCryhEMBW8maWEbwN0LoJIjdt640FviwMeJpghJXM=", "owner": "hyprwm", "repo": "aquamarine", - "rev": "4c72cd4d0b0368ce78bf94ea7f23d47670f0d429", + "rev": "353dc1b7299d43f08de44276b93ae32726ff9d70", "type": "github" }, "original": { From 391f1ae838e936e909d0f3de8a5bf0387d22f80d Mon Sep 17 00:00:00 2001 From: Anton Lazarev <22821309+antonok-edm@users.noreply.github.com> Date: Wed, 24 Jul 2024 15:16:47 -0700 Subject: [PATCH 0161/2181] input: don't simulate mouse movement on focus change in follow_mouse = 2/3 if no_warps is false (#7015) --- src/managers/KeybindManager.cpp | 31 ++++++++++++++++++++++--------- 1 file changed, 22 insertions(+), 9 deletions(-) diff --git a/src/managers/KeybindManager.cpp b/src/managers/KeybindManager.cpp index 4232ea64..44826fff 100644 --- a/src/managers/KeybindManager.cpp +++ b/src/managers/KeybindManager.cpp @@ -281,13 +281,18 @@ bool CKeybindManager::tryMoveFocusToMonitor(CMonitor* monitor) { return false; const auto LASTMONITOR = g_pCompositor->m_pLastMonitor.get(); + if (!LASTMONITOR) + return false; if (LASTMONITOR == monitor) { Debug::log(LOG, "Tried to move to active monitor"); return false; } - const auto PWORKSPACE = g_pCompositor->m_pLastMonitor->activeWorkspace; - const auto PNEWMAINWORKSPACE = monitor->activeWorkspace; + static auto PFOLLOWMOUSE = CConfigValue("input:follow_mouse"); + static auto PNOWARPS = CConfigValue("cursor:no_warps"); + + const auto PWORKSPACE = g_pCompositor->m_pLastMonitor->activeWorkspace; + const auto PNEWMAINWORKSPACE = monitor->activeWorkspace; g_pInputManager->unconstrainMouse(); PNEWMAINWORKSPACE->rememberPrevWorkspace(PWORKSPACE); @@ -300,9 +305,11 @@ bool CKeybindManager::tryMoveFocusToMonitor(CMonitor* monitor) { g_pCompositor->focusWindow(PNEWWINDOW); PNEWWINDOW->warpCursor(); - g_pInputManager->m_pForcedFocus = PNEWWINDOW; - g_pInputManager->simulateMouseMovement(); - g_pInputManager->m_pForcedFocus.reset(); + if (*PNOWARPS == 0 || *PFOLLOWMOUSE < 2) { + g_pInputManager->m_pForcedFocus = PNEWWINDOW; + g_pInputManager->simulateMouseMovement(); + g_pInputManager->m_pForcedFocus.reset(); + } } else { g_pCompositor->focusWindow(nullptr); g_pCompositor->warpCursorTo(monitor->middle()); @@ -313,7 +320,10 @@ bool CKeybindManager::tryMoveFocusToMonitor(CMonitor* monitor) { } void CKeybindManager::switchToWindow(PHLWINDOW PWINDOWTOCHANGETO) { - const auto PLASTWINDOW = g_pCompositor->m_pLastWindow.lock(); + static auto PFOLLOWMOUSE = CConfigValue("input:follow_mouse"); + static auto PNOWARPS = CConfigValue("cursor:no_warps"); + + const auto PLASTWINDOW = g_pCompositor->m_pLastWindow.lock(); if (PWINDOWTOCHANGETO == PLASTWINDOW || !PWINDOWTOCHANGETO) return; @@ -337,9 +347,12 @@ void CKeybindManager::switchToWindow(PHLWINDOW PWINDOWTOCHANGETO) { g_pCompositor->focusWindow(PWINDOWTOCHANGETO); PWINDOWTOCHANGETO->warpCursor(); - g_pInputManager->m_pForcedFocus = PWINDOWTOCHANGETO; - g_pInputManager->simulateMouseMovement(); - g_pInputManager->m_pForcedFocus.reset(); + // Move mouse focus to the new window if required by current follow_mouse and warp modes + if (*PNOWARPS == 0 || *PFOLLOWMOUSE < 2) { + g_pInputManager->m_pForcedFocus = PWINDOWTOCHANGETO; + g_pInputManager->simulateMouseMovement(); + g_pInputManager->m_pForcedFocus.reset(); + } if (PLASTWINDOW && PLASTWINDOW->m_iMonitorID != PWINDOWTOCHANGETO->m_iMonitorID) { // event From 4beac91cbd791657cc53d6e483eb41bf4df1ec0c Mon Sep 17 00:00:00 2001 From: MightyPlaza <123664421+MightyPlaza@users.noreply.github.com> Date: Wed, 24 Jul 2024 22:19:15 +0000 Subject: [PATCH 0162/2181] keybinds: add safeguard to mousebinds (#7034) modified: src/managers/KeybindManager.cpp --- src/managers/KeybindManager.cpp | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/src/managers/KeybindManager.cpp b/src/managers/KeybindManager.cpp index 44826fff..caa2b137 100644 --- a/src/managers/KeybindManager.cpp +++ b/src/managers/KeybindManager.cpp @@ -2366,7 +2366,7 @@ void CKeybindManager::mouse(std::string args) { const auto PRESSED = args[0] == '1'; if (ARGS[0] == "movewindow") { - if (PRESSED) { + if (PRESSED && g_pInputManager->dragMode == MBIND_INVALID) { g_pKeybindManager->m_bIsMouseBindActive = true; const auto mouseCoords = g_pInputManager->getMouseCoordsInternal(); @@ -2380,7 +2380,7 @@ void CKeybindManager::mouse(std::string args) { g_pInputManager->dragMode = MBIND_MOVE; g_pLayoutManager->getCurrentLayout()->onBeginDragWindow(); - } else { + } else if (!PRESSED && g_pInputManager->dragMode == MBIND_MOVE) { g_pKeybindManager->m_bIsMouseBindActive = false; if (!g_pInputManager->currentlyDraggedWindow.expired()) { @@ -2390,7 +2390,7 @@ void CKeybindManager::mouse(std::string args) { } } } else if (ARGS[0] == "resizewindow") { - if (PRESSED) { + if (PRESSED && g_pInputManager->dragMode == MBIND_INVALID) { g_pKeybindManager->m_bIsMouseBindActive = true; g_pInputManager->currentlyDraggedWindow = @@ -2404,7 +2404,8 @@ void CKeybindManager::mouse(std::string args) { } } catch (std::exception& e) { g_pInputManager->dragMode = MBIND_RESIZE; } g_pLayoutManager->getCurrentLayout()->onBeginDragWindow(); - } else { + } else if (!PRESSED && + (g_pInputManager->dragMode == MBIND_RESIZE_FORCE_RATIO || g_pInputManager->dragMode == MBIND_RESIZE_BLOCK_RATIO || g_pInputManager->dragMode == MBIND_RESIZE)) { g_pKeybindManager->m_bIsMouseBindActive = false; if (!g_pInputManager->currentlyDraggedWindow.expired()) { From daf5fad19034def8062acfd32e66bea78c62aaff Mon Sep 17 00:00:00 2001 From: Vaxry Date: Thu, 25 Jul 2024 13:02:05 +0200 Subject: [PATCH 0163/2181] keyboard: properly update keymap state and fd on keymap changes needed for virtual keyboards that impose their own layouts. fixes #6991 --- src/devices/IKeyboard.cpp | 42 ++++++++++++++++++++++++--------- src/devices/IKeyboard.hpp | 28 +++++++++++++--------- src/devices/VirtualKeyboard.cpp | 9 +++++-- 3 files changed, 55 insertions(+), 24 deletions(-) diff --git a/src/devices/IKeyboard.cpp b/src/devices/IKeyboard.cpp index 284a8295..09a18477 100644 --- a/src/devices/IKeyboard.cpp +++ b/src/devices/IKeyboard.cpp @@ -51,6 +51,11 @@ void IKeyboard::clearManuallyAllocd() { } void IKeyboard::setKeymap(const SStringRuleNames& rules) { + if (keymapOverridden) { + Debug::log(LOG, "Ignoring setKeymap: keymap is overridden"); + return; + } + currentRules = rules; xkb_rule_names XKBRULES = { .rules = rules.rules.c_str(), @@ -103,10 +108,6 @@ void IKeyboard::setKeymap(const SStringRuleNames& rules) { xkbKeymap = xkb_keymap_new_from_names(CONTEXT, &XKBRULES, XKB_KEYMAP_COMPILE_NO_FLAGS); } - // set internal translation state - // demo sunao ni ienai - xkbStaticState = xkb_state_new(xkbKeymap); - updateXKBTranslationState(xkbKeymap); const auto NUMLOCKON = g_pConfigManager->getDeviceInt(hlName, "numlock_by_default", "input:numlock_by_default"); @@ -131,6 +132,20 @@ void IKeyboard::setKeymap(const SStringRuleNames& rules) { Debug::log(LOG, "xkb: Mod index {} (name {}) got index {}", i, MODNAMES.at(i), modIndexes.at(i)); } + updateKeymapFD(); + + xkb_context_unref(CONTEXT); + + g_pSeatManager->updateActiveKeyboardData(); +} + +void IKeyboard::updateKeymapFD() { + Debug::log(LOG, "Updating keymap fd for keyboard {}", deviceName); + + if (xkbKeymapFD >= 0) + close(xkbKeymapFD); + xkbKeymapFD = -1; + auto cKeymapStr = xkb_keymap_get_as_string(xkbKeymap, XKB_KEYMAP_FORMAT_TEXT_V1); xkbKeymapString = cKeymapStr; free(cKeymapStr); @@ -151,21 +166,24 @@ void IKeyboard::setKeymap(const SStringRuleNames& rules) { } } - xkb_context_unref(CONTEXT); - - g_pSeatManager->updateActiveKeyboardData(); + Debug::log(LOG, "Updated keymap fd to {}", xkbKeymapFD); } void IKeyboard::updateXKBTranslationState(xkb_keymap* const keymap) { + if (xkbStaticState) + xkb_state_unref(xkbStaticState); + if (xkbState) xkb_state_unref(xkbState); - xkbState = nullptr; + xkbState = nullptr; + xkbStaticState = nullptr; if (keymap) { Debug::log(LOG, "Updating keyboard {:x}'s translation state from a provided keymap", (uintptr_t)this); - xkbState = xkb_state_new(keymap); + xkbStaticState = xkb_state_new(keymap); + xkbState = xkb_state_new(keymap); return; } @@ -209,7 +227,8 @@ void IKeyboard::updateXKBTranslationState(xkb_keymap* const keymap) { KEYMAP = xkb_keymap_new_from_names(PCONTEXT, &rules, XKB_KEYMAP_COMPILE_NO_FLAGS); } - xkbState = xkb_state_new(KEYMAP); + xkbState = xkb_state_new(KEYMAP); + xkbStaticState = xkb_state_new(KEYMAP); xkb_keymap_unref(KEYMAP); xkb_context_unref(PCONTEXT); @@ -230,7 +249,8 @@ void IKeyboard::updateXKBTranslationState(xkb_keymap* const keymap) { const auto NEWKEYMAP = xkb_keymap_new_from_names(PCONTEXT, &rules, XKB_KEYMAP_COMPILE_NO_FLAGS); - xkbState = xkb_state_new(NEWKEYMAP); + xkbState = xkb_state_new(NEWKEYMAP); + xkbStaticState = xkb_state_new(NEWKEYMAP); xkb_keymap_unref(NEWKEYMAP); xkb_context_unref(PCONTEXT); diff --git a/src/devices/IKeyboard.hpp b/src/devices/IKeyboard.hpp index 1ae6c7bc..2ff8a190 100644 --- a/src/devices/IKeyboard.hpp +++ b/src/devices/IKeyboard.hpp @@ -61,18 +61,24 @@ class IKeyboard : public IHID { std::string rules = ""; }; - void setKeymap(const SStringRuleNames& rules); - void updateXKBTranslationState(xkb_keymap* const keymap = nullptr); - std::string getActiveLayout(); - void updateLEDs(); - void updateLEDs(uint32_t leds); - uint32_t getModifiers(); - void updateModifiers(uint32_t depressed, uint32_t latched, uint32_t locked, uint32_t group); - bool updateModifiersState(); // rets whether changed - void updateXkbStateWithKey(uint32_t xkbKey, bool pressed); + void setKeymap(const SStringRuleNames& rules); + void updateXKBTranslationState(xkb_keymap* const keymap = nullptr); + std::string getActiveLayout(); + void updateLEDs(); + void updateLEDs(uint32_t leds); + uint32_t getModifiers(); + void updateModifiers(uint32_t depressed, uint32_t latched, uint32_t locked, uint32_t group); + bool updateModifiersState(); // rets whether changed + void updateXkbStateWithKey(uint32_t xkbKey, bool pressed); + void updateKeymapFD(); - bool active = false; - bool enabled = true; + bool active = false; + bool enabled = true; + + // if the keymap is overridden by the implementation, + // don't try to set keyboard rules anymore, to avoid overwriting the requested one. + // e.g. Virtual keyboards with custom maps. + bool keymapOverridden = false; xkb_layout_index_t activeLayout = 0; xkb_state * xkbState = nullptr, *xkbStaticState /* Static state: never gets modifiers or layout changes sent, used for keybinds. */ = nullptr; diff --git a/src/devices/VirtualKeyboard.cpp b/src/devices/VirtualKeyboard.cpp index 654ca9f5..548711c2 100644 --- a/src/devices/VirtualKeyboard.cpp +++ b/src/devices/VirtualKeyboard.cpp @@ -31,8 +31,13 @@ CVirtualKeyboard::CVirtualKeyboard(SP keeb_) : keybo }); }); listeners.keymap = keeb_->events.keymap.registerListener([this](std::any d) { - auto E = std::any_cast(d); - xkbKeymap = xkb_keymap_ref(E.keymap); + auto E = std::any_cast(d); + if (xkbKeymap) + xkb_keymap_unref(xkbKeymap); + xkbKeymap = xkb_keymap_ref(E.keymap); + keymapOverridden = true; + updateXKBTranslationState(xkbKeymap); + updateKeymapFD(); keyboardEvents.keymap.emit(d); }); From cd942ad12d9d2030963e3dd5fbfe2d181013c750 Mon Sep 17 00:00:00 2001 From: Vaxry Date: Thu, 25 Jul 2024 13:10:53 +0200 Subject: [PATCH 0164/2181] keyboard: update xkb state after key event fixes #6946 --- src/devices/Keyboard.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/devices/Keyboard.cpp b/src/devices/Keyboard.cpp index ae28c07d..0a8f6b57 100644 --- a/src/devices/Keyboard.cpp +++ b/src/devices/Keyboard.cpp @@ -32,13 +32,13 @@ CKeyboard::CKeyboard(SP keeb) : keyboard(keeb) { listeners.key = keeb->events.key.registerListener([this](std::any d) { auto E = std::any_cast(d); - updateXkbStateWithKey(E.key + 8, E.pressed); - keyboardEvents.key.emit(SKeyEvent{ .timeMs = E.timeMs, .keycode = E.key, .state = E.pressed ? WL_KEYBOARD_KEY_STATE_PRESSED : WL_KEYBOARD_KEY_STATE_RELEASED, }); + + updateXkbStateWithKey(E.key + 8, E.pressed); }); listeners.modifiers = keeb->events.modifiers.registerListener([this](std::any d) { From a0d15a0b7b066cbb1b08ac54cf882c2c55467e4a Mon Sep 17 00:00:00 2001 From: Vaxry Date: Thu, 25 Jul 2024 14:12:08 +0200 Subject: [PATCH 0165/2181] wayland/compositor: release buffers on unmap XWayland does not use the regular commit(null) method to unmap, which results in buffers never being released. release the buffers if present and un-released in the unmap() handler ref #6584 --- src/protocols/core/Compositor.cpp | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/src/protocols/core/Compositor.cpp b/src/protocols/core/Compositor.cpp index f1c83531..a31b1fb4 100644 --- a/src/protocols/core/Compositor.cpp +++ b/src/protocols/core/Compositor.cpp @@ -336,6 +336,17 @@ void CWLSurfaceResource::unmap() { mapped = false; events.unmap.emit(); + + // release the buffers. + // this is necessary for XWayland to function correctly, + // as it does not unmap via the traditional commit(null buffer) method, but via the X11 protocol. + if (!bufferReleased && current.buffer) + current.buffer->sendRelease(); + if (pending.buffer) + pending.buffer->sendRelease(); + + pending.buffer.reset(); + current.buffer.reset(); } void CWLSurfaceResource::error(int code, const std::string& str) { From 33a5c8ce325e1657ec5571b57e05c6378706f4cd Mon Sep 17 00:00:00 2001 From: Vaxry Date: Thu, 25 Jul 2024 15:29:39 +0200 Subject: [PATCH 0166/2181] config: avoid using initial ws tracking for exec-once --- src/config/ConfigManager.cpp | 2 ++ src/config/ConfigManager.hpp | 8 +++++--- src/managers/KeybindManager.cpp | 2 +- 3 files changed, 8 insertions(+), 4 deletions(-) diff --git a/src/config/ConfigManager.cpp b/src/config/ConfigManager.cpp index 5a8f2bd2..657d7aff 100644 --- a/src/config/ConfigManager.cpp +++ b/src/config/ConfigManager.cpp @@ -1299,12 +1299,14 @@ void CConfigManager::dispatchExecOnce() { "dbus-update-activation-environment --systemd WAYLAND_DISPLAY XDG_CURRENT_DESKTOP HYPRLAND_INSTANCE_SIGNATURE QT_QPA_PLATFORMTHEME PATH XDG_DATA_DIRS"); firstExecDispatched = true; + isLaunchingExecOnce = true; for (auto& c : firstExecRequests) { handleRawExec("", c); } firstExecRequests.clear(); // free some kb of memory :P + isLaunchingExecOnce = false; // set input, fixes some certain issues g_pInputManager->setKeyboardLayout(); diff --git a/src/config/ConfigManager.hpp b/src/config/ConfigManager.hpp index b4a49b7a..454a12c0 100644 --- a/src/config/ConfigManager.hpp +++ b/src/config/ConfigManager.hpp @@ -129,9 +129,6 @@ class CConfigManager { void performMonitorReload(); void appendMonitorRule(const SMonitorRule&); bool replaceMonitorRule(const SMonitorRule&); - bool m_bWantsMonitorReload = false; - bool m_bForceReload = false; - bool m_bNoMonitorReload = false; void ensureMonitorStatus(); void ensureVRR(CMonitor* pMonitor = nullptr); @@ -192,6 +189,11 @@ class CConfigManager { std::unordered_map*(PHLWINDOW)>> miWindowProperties = { {"rounding", [](PHLWINDOW pWindow) { return &pWindow->m_sWindowData.rounding; }}, {"bordersize", [](PHLWINDOW pWindow) { return &pWindow->m_sWindowData.borderSize; }}}; + bool m_bWantsMonitorReload = false; + bool m_bForceReload = false; + bool m_bNoMonitorReload = false; + bool isLaunchingExecOnce = false; // For exec-once to skip initial ws tracking + private: std::unique_ptr m_pConfig; diff --git a/src/managers/KeybindManager.cpp b/src/managers/KeybindManager.cpp index caa2b137..22d9c3d7 100644 --- a/src/managers/KeybindManager.cpp +++ b/src/managers/KeybindManager.cpp @@ -36,7 +36,7 @@ using namespace Hyprutils::String; static std::vector> getHyprlandLaunchEnv() { static auto PINITIALWSTRACKING = CConfigValue("misc:initial_workspace_tracking"); - if (!*PINITIALWSTRACKING) + if (!*PINITIALWSTRACKING || g_pConfigManager->isLaunchingExecOnce) return {}; const auto PMONITOR = g_pCompositor->m_pLastMonitor; From 57371b93a058d17affb0ca92f13b8d40582b3ea0 Mon Sep 17 00:00:00 2001 From: vaxerski Date: Fri, 26 Jul 2024 19:53:24 +0200 Subject: [PATCH 0167/2181] renderer: drastically optimize bg texture creation stop loading 20MB images every time, dumbass --- src/render/OpenGL.cpp | 141 +++++++++++++++++++++++++----------------- src/render/OpenGL.hpp | 3 + 2 files changed, 86 insertions(+), 58 deletions(-) diff --git a/src/render/OpenGL.cpp b/src/render/OpenGL.cpp index ab7f566a..5e52403d 100644 --- a/src/render/OpenGL.cpp +++ b/src/render/OpenGL.cpp @@ -2571,7 +2571,7 @@ void CHyprOpenGLImpl::renderSplash(cairo_t* const CAIRO, cairo_surface_t* const textW /= PANGO_SCALE; textH /= PANGO_SCALE; - cairo_move_to(CAIRO, (size.x - textW) / 2.0, size.y - textH * 2 + offsetY); + cairo_move_to(CAIRO, (size.x - textW) / 2.0, size.y - textH - offsetY); pango_cairo_show_layout(CAIRO, layoutText); pango_font_description_free(pangoFD); @@ -2580,16 +2580,48 @@ void CHyprOpenGLImpl::renderSplash(cairo_t* const CAIRO, cairo_surface_t* const cairo_surface_flush(CAIROSURFACE); } +void CHyprOpenGLImpl::createBackgroundTexture(const std::string& texPath) { + const auto CAIROSURFACE = cairo_image_surface_create_from_png(texPath.c_str()); + const auto CAIROFORMAT = cairo_image_surface_get_format(CAIROSURFACE); + + m_pBackgroundTexture = makeShared(); + + m_pBackgroundTexture->allocate(); + m_pBackgroundTexture->m_vSize = {cairo_image_surface_get_width(CAIROSURFACE), cairo_image_surface_get_height(CAIROSURFACE)}; + + const GLint glIFormat = CAIROFORMAT == CAIRO_FORMAT_RGB96F ? +#ifdef GLES2 + GL_RGB32F_EXT : +#else + GL_RGB32F : +#endif + GL_RGBA; + const GLint glFormat = CAIROFORMAT == CAIRO_FORMAT_RGB96F ? GL_RGB : GL_RGBA; + const GLint glType = CAIROFORMAT == CAIRO_FORMAT_RGB96F ? GL_FLOAT : GL_UNSIGNED_BYTE; + + const auto DATA = cairo_image_surface_get_data(CAIROSURFACE); + glBindTexture(GL_TEXTURE_2D, m_pBackgroundTexture->m_iTexID); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); +#ifndef GLES2 + if (CAIROFORMAT != CAIRO_FORMAT_RGB96F) { + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_R, GL_BLUE); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_B, GL_RED); + } +#endif + glTexImage2D(GL_TEXTURE_2D, 0, glIFormat, m_pBackgroundTexture->m_vSize.x, m_pBackgroundTexture->m_vSize.y, 0, glFormat, glType, DATA); +} + void CHyprOpenGLImpl::createBGTextureForMonitor(CMonitor* pMonitor) { RASSERT(m_RenderData.pMonitor, "Tried to createBGTex without begin()!"); - static auto PRENDERTEX = CConfigValue("misc:disable_hyprland_logo"); - static auto PNOSPLASH = CConfigValue("misc:disable_splash_rendering"); - static auto PFORCEWALLPAPER = CConfigValue("misc:force_default_wallpaper"); + Debug::log(LOG, "Creating a texture for BGTex"); - const auto FORCEWALLPAPER = std::clamp(*PFORCEWALLPAPER, static_cast(-1L), static_cast(2L)); + static auto PRENDERTEX = CConfigValue("misc:disable_hyprland_logo"); + static auto PNOSPLASH = CConfigValue("misc:disable_splash_rendering"); + static auto PFORCEWALLPAPER = CConfigValue("misc:force_default_wallpaper"); - static std::string texPath = ""; + const auto FORCEWALLPAPER = std::clamp(*PFORCEWALLPAPER, static_cast(-1L), static_cast(2L)); if (*PRENDERTEX) return; @@ -2599,12 +2631,12 @@ void CHyprOpenGLImpl::createBGTextureForMonitor(CMonitor* pMonitor) { PFB->release(); PFB->alloc(pMonitor->vecPixelSize.x, pMonitor->vecPixelSize.y, pMonitor->output->state->state().drmFormat); - Debug::log(LOG, "Allocated texture for BGTex"); - // TODO: use relative paths to the installation - // or configure the paths at build time - if (texPath.empty()) { - texPath = "/usr/share/hyprland/wall"; + if (!m_pBackgroundTexture) { + // TODO: use relative paths to the installation + // or configure the paths at build time + std::string texPath = ""; + texPath = "/usr/share/hyprland/wall"; // get the adequate tex if (FORCEWALLPAPER == -1) { @@ -2625,84 +2657,77 @@ void CHyprOpenGLImpl::createBGTextureForMonitor(CMonitor* pMonitor) { if (!std::filesystem::exists(texPath)) return; // the texture will be empty, oh well. We'll clear with a solid color anyways. } + + createBackgroundTexture(texPath); } // create a new one with cairo SP tex = makeShared(); - const auto CAIROISURFACE = cairo_image_surface_create_from_png(texPath.c_str()); - const auto CAIROFORMAT = cairo_image_surface_get_format(CAIROISURFACE); - tex->allocate(); - const Vector2D IMAGESIZE = {cairo_image_surface_get_width(CAIROISURFACE), cairo_image_surface_get_height(CAIROISURFACE)}; - // calc the target box - const double MONRATIO = m_RenderData.pMonitor->vecTransformedSize.x / m_RenderData.pMonitor->vecTransformedSize.y; - const double WPRATIO = IMAGESIZE.x / IMAGESIZE.y; - - Vector2D origin; - double scale; - - if (MONRATIO > WPRATIO) { - scale = m_RenderData.pMonitor->vecTransformedSize.x / IMAGESIZE.x; - - origin.y = (m_RenderData.pMonitor->vecTransformedSize.y - IMAGESIZE.y * scale) / 2.0; - } else { - scale = m_RenderData.pMonitor->vecTransformedSize.y / IMAGESIZE.y; - - origin.x = (m_RenderData.pMonitor->vecTransformedSize.x - IMAGESIZE.x * scale) / 2.0; - } - - const Vector2D scaledSize = IMAGESIZE * scale; - - const auto CAIROSURFACE = cairo_image_surface_create(CAIROFORMAT, scaledSize.x, scaledSize.y); - const auto CAIRO = cairo_create(CAIROSURFACE); + const auto CAIROSURFACE = cairo_image_surface_create(CAIRO_FORMAT_ARGB32, pMonitor->vecPixelSize.x, pMonitor->vecPixelSize.y); + const auto CAIRO = cairo_create(CAIROSURFACE); cairo_set_antialias(CAIRO, CAIRO_ANTIALIAS_GOOD); - cairo_scale(CAIRO, scale, scale); - cairo_rectangle(CAIRO, 0, 0, 100, 100); - cairo_set_source_surface(CAIRO, CAIROISURFACE, 0, 0); + cairo_save(CAIRO); + cairo_set_source_rgba(CAIRO, 0, 0, 0, 0); + cairo_set_operator(CAIRO, CAIRO_OPERATOR_SOURCE); cairo_paint(CAIRO); + cairo_restore(CAIRO); if (!*PNOSPLASH) - renderSplash(CAIRO, CAIROSURFACE, origin.y * WPRATIO / MONRATIO * scale, IMAGESIZE); + renderSplash(CAIRO, CAIROSURFACE, 0.02 * pMonitor->vecPixelSize.y, pMonitor->vecPixelSize); cairo_surface_flush(CAIROSURFACE); - CBox box = {origin.x, origin.y, IMAGESIZE.x * scale, IMAGESIZE.y * scale}; - tex->m_vSize = IMAGESIZE * scale; + tex->m_vSize = pMonitor->vecPixelSize; // copy the data to an OpenGL texture we have - const GLint glIFormat = CAIROFORMAT == CAIRO_FORMAT_RGB96F ? -#ifdef GLES2 - GL_RGB32F_EXT : -#else - GL_RGB32F : -#endif - GL_RGBA; - const GLint glFormat = CAIROFORMAT == CAIRO_FORMAT_RGB96F ? GL_RGB : GL_RGBA; - const GLint glType = CAIROFORMAT == CAIRO_FORMAT_RGB96F ? GL_FLOAT : GL_UNSIGNED_BYTE; + const GLint glFormat = GL_RGBA; + const GLint glType = GL_UNSIGNED_BYTE; const auto DATA = cairo_image_surface_get_data(CAIROSURFACE); glBindTexture(GL_TEXTURE_2D, tex->m_iTexID); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); #ifndef GLES2 - if (CAIROFORMAT != CAIRO_FORMAT_RGB96F) { - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_R, GL_BLUE); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_B, GL_RED); - } + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_R, GL_BLUE); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_B, GL_RED); #endif - glTexImage2D(GL_TEXTURE_2D, 0, glIFormat, tex->m_vSize.x, tex->m_vSize.y, 0, glFormat, glType, DATA); + glTexImage2D(GL_TEXTURE_2D, 0, glFormat, tex->m_vSize.x, tex->m_vSize.y, 0, glFormat, glType, DATA); cairo_surface_destroy(CAIROSURFACE); - cairo_surface_destroy(CAIROISURFACE); cairo_destroy(CAIRO); // render the texture to our fb PFB->bind(); CRegion fakeDamage{0, 0, INT16_MAX, INT16_MAX}; - renderTextureInternalWithDamage(tex, &box, 1.0, &fakeDamage); + + blend(true); + clear(CColor{0, 0, 0, 1}); + + // first render the background + if (m_pBackgroundTexture) { + const double MONRATIO = m_RenderData.pMonitor->vecTransformedSize.x / m_RenderData.pMonitor->vecTransformedSize.y; + const double WPRATIO = m_pBackgroundTexture->m_vSize.x / m_pBackgroundTexture->m_vSize.y; + Vector2D origin; + double scale = 1.0; + + if (MONRATIO > WPRATIO) { + scale = m_RenderData.pMonitor->vecTransformedSize.x / m_pBackgroundTexture->m_vSize.x; + origin.y = (m_RenderData.pMonitor->vecTransformedSize.y - m_pBackgroundTexture->m_vSize.y * scale) / 2.0; + } else { + scale = m_RenderData.pMonitor->vecTransformedSize.y / m_pBackgroundTexture->m_vSize.y; + origin.x = (m_RenderData.pMonitor->vecTransformedSize.x - m_pBackgroundTexture->m_vSize.x * scale) / 2.0; + } + + CBox texbox = CBox{origin, m_pBackgroundTexture->m_vSize * scale}; + renderTextureInternalWithDamage(m_pBackgroundTexture, &texbox, 1.0, &fakeDamage); + } + + CBox monbox = {{}, pMonitor->vecPixelSize}; + renderTextureInternalWithDamage(tex, &monbox, 1.0, &fakeDamage); // bind back if (m_RenderData.currentFB) diff --git a/src/render/OpenGL.hpp b/src/render/OpenGL.hpp index 5c4ee811..41e80ee5 100644 --- a/src/render/OpenGL.hpp +++ b/src/render/OpenGL.hpp @@ -274,6 +274,8 @@ class CHyprOpenGLImpl { CShader m_sFinalScreenShader; CTimer m_tGlobalTimer; + SP m_pBackgroundTexture; + void logShaderError(const GLuint&, bool program = false); GLuint createProgram(const std::string&, const std::string&, bool dynamic = false); GLuint compileShader(const GLuint&, std::string, bool dynamic = false); @@ -282,6 +284,7 @@ class CHyprOpenGLImpl { void initDRMFormats(); void initEGL(bool gbm); EGLDeviceEXT eglDeviceFromDRMFD(int drmFD); + void createBackgroundTexture(const std::string& path); // std::optional> getModsForFormat(EGLint format); From 76610d9fb0ba5a2d495a963773c38b717d76776f Mon Sep 17 00:00:00 2001 From: vaxerski Date: Sat, 27 Jul 2024 13:03:43 +0200 Subject: [PATCH 0168/2181] opengl: destroy cairo image surface after use --- src/render/OpenGL.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/render/OpenGL.cpp b/src/render/OpenGL.cpp index 5e52403d..39f6614e 100644 --- a/src/render/OpenGL.cpp +++ b/src/render/OpenGL.cpp @@ -2610,6 +2610,8 @@ void CHyprOpenGLImpl::createBackgroundTexture(const std::string& texPath) { } #endif glTexImage2D(GL_TEXTURE_2D, 0, glIFormat, m_pBackgroundTexture->m_vSize.x, m_pBackgroundTexture->m_vSize.y, 0, glFormat, glType, DATA); + + cairo_surface_destroy(CAIROSURFACE); } void CHyprOpenGLImpl::createBGTextureForMonitor(CMonitor* pMonitor) { From 682865632fe986d179ca07e45ae89e65b8058b33 Mon Sep 17 00:00:00 2001 From: vaxerski Date: Sat, 27 Jul 2024 13:58:30 +0200 Subject: [PATCH 0169/2181] xwayland: fix high cpu idle usage fixes #7051 --- src/xwayland/XWM.cpp | 17 ++++++++++------- 1 file changed, 10 insertions(+), 7 deletions(-) diff --git a/src/xwayland/XWM.cpp b/src/xwayland/XWM.cpp index 498710a4..f6b6864c 100644 --- a/src/xwayland/XWM.cpp +++ b/src/xwayland/XWM.cpp @@ -153,13 +153,16 @@ static bool lookupParentExists(SP XSURF, SP } void CXWM::readProp(SP XSURF, uint32_t atom, xcb_get_property_reply_t* reply) { - std::string propName = std::format("{}?", atom); - for (auto& ha : HYPRATOMS) { - if (ha.second != atom) - continue; + std::string propName; + if (Debug::trace) { + propName = std::format("{}?", atom); + for (auto& ha : HYPRATOMS) { + if (ha.second != atom) + continue; - propName = ha.first; - break; + propName = ha.first; + break; + } } if (atom == XCB_ATOM_WM_CLASS) { @@ -536,7 +539,7 @@ bool CXWM::handleSelectionPropertyNotify(xcb_property_notify_event_t* e) { // Debug::log(ERR, "[xwm] FIXME: CXWM::handleSelectionPropertyNotify stub"); - return false; + return true; } void CXWM::handleSelectionRequest(xcb_selection_request_event_t* e) { From 534fdb5a375b65821adce3fec5d1622fc546b8b4 Mon Sep 17 00:00:00 2001 From: Mihai Fufezan Date: Sat, 27 Jul 2024 15:57:52 +0300 Subject: [PATCH 0170/2181] flake.lock: update --- flake.lock | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/flake.lock b/flake.lock index e8f7e259..90d09c39 100644 --- a/flake.lock +++ b/flake.lock @@ -16,11 +16,11 @@ ] }, "locked": { - "lastModified": 1721853718, - "narHash": "sha256-QEkCryhEMBW8maWEbwN0LoJIjdt640FviwMeJpghJXM=", + "lastModified": 1721992626, + "narHash": "sha256-GFDSPWxOqEkNrbuSfyoQHGIaRhJNapn2Rv0EEmBGR9A=", "owner": "hyprwm", "repo": "aquamarine", - "rev": "353dc1b7299d43f08de44276b93ae32726ff9d70", + "rev": "f95d1509370b7f40ef356ff69a332bd0356ab044", "type": "github" }, "original": { @@ -154,11 +154,11 @@ }, "nixpkgs": { "locked": { - "lastModified": 1721379653, - "narHash": "sha256-8MUgifkJ7lkZs3u99UDZMB4kbOxvMEXQZ31FO3SopZ0=", + "lastModified": 1721924956, + "narHash": "sha256-Sb1jlyRO+N8jBXEX9Pg9Z1Qb8Bw9QyOgLDNMEpmjZ2M=", "owner": "NixOS", "repo": "nixpkgs", - "rev": "1d9c2c9b3e71b9ee663d11c5d298727dace8d374", + "rev": "5ad6a14c6bf098e98800b091668718c336effc95", "type": "github" }, "original": { @@ -209,11 +209,11 @@ ] }, "locked": { - "lastModified": 1721648131, - "narHash": "sha256-cyyxu/oj4QEFp3CVx2WeXa9T4OAUyynuBJHGkBZSxJI=", + "lastModified": 1721755049, + "narHash": "sha256-O17b38bQnmfxv7It3OnVYx7fp1seEdI7xxnw5vJFv30=", "owner": "hyprwm", "repo": "xdg-desktop-portal-hyprland", - "rev": "663be9cad424b170b28b9fa8a61042d721007f3b", + "rev": "5555f467f68ce7cdf1060991c24263073b95e9da", "type": "github" }, "original": { From 963816b9a6524a99a6716fa1aa30b2c4f369d2f0 Mon Sep 17 00:00:00 2001 From: vaxerski Date: Sat, 27 Jul 2024 15:03:52 +0200 Subject: [PATCH 0171/2181] layersurface: fixup focus issues in onUnmap fixes #6929 --- src/desktop/LayerSurface.cpp | 5 ++++- src/desktop/WLSurface.cpp | 9 +++++++++ src/desktop/WLSurface.hpp | 1 + 3 files changed, 14 insertions(+), 1 deletion(-) diff --git a/src/desktop/LayerSurface.cpp b/src/desktop/LayerSurface.cpp index 83b0992f..2252adca 100644 --- a/src/desktop/LayerSurface.cpp +++ b/src/desktop/LayerSurface.cpp @@ -212,8 +212,11 @@ void CLayerSurface::onUnmap() { return; // refocus if needed - if (WASLASTFOCUS) + // vvvvvvvvvvvvv if there is a last focus and the last focus is not keyboard focusable, fallback to window + if (WASLASTFOCUS || (g_pCompositor->m_pLastFocus && !g_pCompositor->m_pLastFocus->hlSurface->keyboardFocusable())) g_pInputManager->refocusLastWindow(PMONITOR); + else if (g_pCompositor->m_pLastFocus) + g_pSeatManager->setKeyboardFocus(g_pCompositor->m_pLastFocus.lock()); CBox geomFixed = {geometry.x + PMONITOR->vecPosition.x, geometry.y + PMONITOR->vecPosition.y, geometry.width, geometry.height}; g_pHyprRenderer->damageBox(&geomFixed); diff --git a/src/desktop/WLSurface.cpp b/src/desktop/WLSurface.cpp index 90924145..e1348a90 100644 --- a/src/desktop/WLSurface.cpp +++ b/src/desktop/WLSurface.cpp @@ -1,6 +1,7 @@ #include "WLSurface.hpp" #include "../Compositor.hpp" #include "../protocols/core/Compositor.hpp" +#include "../protocols/LayerShell.hpp" void CWLSurface::assign(SP pSurface) { m_pResource = pSurface; @@ -222,3 +223,11 @@ SP CWLSurface::fromResource(SP pSurface) { return nullptr; return pSurface->hlSurface.lock(); } + +bool CWLSurface::keyboardFocusable() const { + if (m_pWindowOwner || m_pPopupOwner || m_pSubsurfaceOwner) + return true; + if (m_pLayerOwner) + return m_pLayerOwner->layerSurface->current.interactivity != ZWLR_LAYER_SURFACE_V1_KEYBOARD_INTERACTIVITY_NONE; + return false; +} diff --git a/src/desktop/WLSurface.hpp b/src/desktop/WLSurface.hpp index bb476e0f..a962b882 100644 --- a/src/desktop/WLSurface.hpp +++ b/src/desktop/WLSurface.hpp @@ -39,6 +39,7 @@ class CWLSurface { Vector2D getViewporterCorrectedSize() const; CRegion computeDamage() const; // logical coordinates. May be wrong if the surface is unassigned bool visible(); + bool keyboardFocusable() const; // getters for owners. PHLWINDOW getWindow() const; From ec672b1ab95e341a0dcb6679592ae4e5eea9b1cf Mon Sep 17 00:00:00 2001 From: Ikalco <73481042+ikalco@users.noreply.github.com> Date: Sat, 27 Jul 2024 10:02:02 -0500 Subject: [PATCH 0172/2181] protocols: move screencopy and toplevel export to hyprwayland-scanner (#7065) * move screencopy and toplevel export to hyprwayland-scanner * oops --- CMakeLists.txt | 13 +- protocols/meson.build | 4 +- src/events/Monitors.cpp | 6 +- src/events/Windows.cpp | 3 +- src/managers/ProtocolManager.cpp | 8 +- src/managers/ProtocolManager.hpp | 5 +- src/protocols/Screencopy.cpp | 671 +++++++++++++------------------ src/protocols/Screencopy.hpp | 152 +++---- src/protocols/ToplevelExport.cpp | 526 +++++++++++------------- src/protocols/ToplevelExport.hpp | 103 ++++- src/render/Renderer.hpp | 2 +- 11 files changed, 695 insertions(+), 798 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 2bd4e0d5..8a27d81b 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -288,17 +288,16 @@ endfunction() target_link_libraries(Hyprland OpenGL::EGL OpenGL::GL Threads::Threads libudis86 uuid) -protocol("protocols/wlr-screencopy-unstable-v1.xml" - "wlr-screencopy-unstable-v1" true) protocol( "subprojects/hyprland-protocols/protocols/hyprland-global-shortcuts-v1.xml" "hyprland-global-shortcuts-v1" true) -protocol( - "subprojects/hyprland-protocols/protocols/hyprland-toplevel-export-v1.xml" - "hyprland-toplevel-export-v1" true) -protocol("unstable/text-input/text-input-unstable-v1.xml" - "text-input-unstable-v1" false) +protocol( + "unstable/text-input/text-input-unstable-v1.xml" + "text-input-unstable-v1" false) + +protocolnew("subprojects/hyprland-protocols/protocols" "hyprland-toplevel-export-v1" true) +protocolnew("protocols" "wlr-screencopy-unstable-v1" true) protocolnew("protocols" "wlr-gamma-control-unstable-v1" true) protocolnew("protocols" "wlr-foreign-toplevel-management-unstable-v1" true) protocolnew("protocols" "wlr-output-power-management-unstable-v1" true) diff --git a/protocols/meson.build b/protocols/meson.build index 5cdeb160..35b2b29b 100644 --- a/protocols/meson.build +++ b/protocols/meson.build @@ -25,8 +25,6 @@ hyprwayland_scanner = find_program( protocols = [ [wl_protocol_dir, 'unstable/text-input/text-input-unstable-v1.xml'], - ['wlr-screencopy-unstable-v1.xml'], - [hl_protocol_dir, 'protocols/hyprland-toplevel-export-v1.xml'], [hl_protocol_dir, 'protocols/hyprland-global-shortcuts-v1.xml'] ] @@ -42,6 +40,8 @@ new_protocols = [ ['wlr-layer-shell-unstable-v1.xml'], ['wayland-drm.xml'], ['wlr-data-control-unstable-v1.xml'], + ['wlr-screencopy-unstable-v1.xml'], + [hl_protocol_dir, 'protocols/hyprland-toplevel-export-v1.xml'], [hl_protocol_dir, 'protocols/hyprland-focus-grab-v1.xml'], [wl_protocol_dir, 'staging/tearing-control/tearing-control-v1.xml'], [wl_protocol_dir, 'staging/fractional-scale/fractional-scale-v1.xml'], diff --git a/src/events/Monitors.cpp b/src/events/Monitors.cpp index 40b6f17e..b2778062 100644 --- a/src/events/Monitors.cpp +++ b/src/events/Monitors.cpp @@ -5,6 +5,8 @@ #include "Events.hpp" #include "../debug/HyprCtl.hpp" #include "../config/ConfigValue.hpp" +#include "../protocols/Screencopy.hpp" +#include "../protocols/ToplevelExport.hpp" #include // --------------------------------------------------------- // @@ -118,8 +120,8 @@ void Events::listener_monitorCommit(void* owner, void* data) { const auto PMONITOR = (CMonitor*)owner; if (true) { // FIXME: E->state->committed & WLR_OUTPUT_STATE_BUFFER - g_pProtocolManager->m_pScreencopyProtocolManager->onOutputCommit(PMONITOR); - g_pProtocolManager->m_pToplevelExportProtocolManager->onOutputCommit(PMONITOR); + PROTO::screencopy->onOutputCommit(PMONITOR); + PROTO::toplevelExport->onOutputCommit(PMONITOR); } } diff --git a/src/events/Windows.cpp b/src/events/Windows.cpp index a5511e17..0e1037b6 100644 --- a/src/events/Windows.cpp +++ b/src/events/Windows.cpp @@ -10,6 +10,7 @@ #include "../protocols/LayerShell.hpp" #include "../protocols/XDGShell.hpp" #include "../protocols/core/Compositor.hpp" +#include "../protocols/ToplevelExport.hpp" #include "../xwayland/XSurface.hpp" #include @@ -601,7 +602,7 @@ void Events::listener_unmapWindow(void* owner, void* data) { g_pEventManager->postEvent(SHyprIPCEvent{"closewindow", std::format("{:x}", PWINDOW)}); EMIT_HOOK_EVENT("closeWindow", PWINDOW); - g_pProtocolManager->m_pToplevelExportProtocolManager->onWindowUnmap(PWINDOW); + PROTO::toplevelExport->onWindowUnmap(PWINDOW); if (PWINDOW->m_bIsFullscreen) g_pCompositor->setWindowFullscreen(PWINDOW, false, FULLSCREEN_FULL); diff --git a/src/managers/ProtocolManager.cpp b/src/managers/ProtocolManager.cpp index ef2260cc..3704befb 100644 --- a/src/managers/ProtocolManager.cpp +++ b/src/managers/ProtocolManager.cpp @@ -39,6 +39,8 @@ #include "../protocols/LinuxDMABUF.hpp" #include "../protocols/DRMLease.hpp" #include "../protocols/DRMSyncobj.hpp" +#include "../protocols/Screencopy.hpp" +#include "../protocols/ToplevelExport.hpp" #include "../protocols/core/Seat.hpp" #include "../protocols/core/DataDevice.hpp" @@ -142,6 +144,8 @@ CProtocolManager::CProtocolManager() { PROTO::dataWlr = std::make_unique(&zwlr_data_control_manager_v1_interface, 2, "DataDeviceWlr"); PROTO::primarySelection = std::make_unique(&zwp_primary_selection_device_manager_v1_interface, 1, "PrimarySelection"); PROTO::xwaylandShell = std::make_unique(&xwayland_shell_v1_interface, 1, "XWaylandShell"); + PROTO::screencopy = std::make_unique(&zwlr_screencopy_manager_v1_interface, 3, "Screencopy"); + PROTO::toplevelExport = std::make_unique(&hyprland_toplevel_export_manager_v1_interface, 2, "ToplevelExport"); for (auto& b : g_pCompositor->m_pAqBackend->getImplementations()) { if (b->type() != Aquamarine::AQ_BACKEND_DRM) @@ -161,10 +165,8 @@ CProtocolManager::CProtocolManager() { // Old protocol implementations. // TODO: rewrite them to use hyprwayland-scanner. - m_pToplevelExportProtocolManager = std::make_unique(); m_pTextInputV1ProtocolManager = std::make_unique(); m_pGlobalShortcutsProtocolManager = std::make_unique(); - m_pScreencopyProtocolManager = std::make_unique(); } CProtocolManager::~CProtocolManager() { @@ -214,6 +216,8 @@ CProtocolManager::~CProtocolManager() { PROTO::dataWlr.reset(); PROTO::primarySelection.reset(); PROTO::xwaylandShell.reset(); + PROTO::screencopy.reset(); + PROTO::toplevelExport.reset(); PROTO::lease.reset(); PROTO::sync.reset(); diff --git a/src/managers/ProtocolManager.hpp b/src/managers/ProtocolManager.hpp index 6a780bdc..62653e89 100644 --- a/src/managers/ProtocolManager.hpp +++ b/src/managers/ProtocolManager.hpp @@ -1,10 +1,9 @@ #pragma once #include "../defines.hpp" -#include "../protocols/ToplevelExport.hpp" #include "../protocols/TextInputV1.hpp" #include "../protocols/GlobalShortcuts.hpp" -#include "../protocols/Screencopy.hpp" +#include "../helpers/Monitor.hpp" #include "../helpers/memory/Memory.hpp" #include "../helpers/signal/Signal.hpp" #include @@ -15,10 +14,8 @@ class CProtocolManager { ~CProtocolManager(); // TODO: rewrite to use the new protocol framework - std::unique_ptr m_pToplevelExportProtocolManager; std::unique_ptr m_pTextInputV1ProtocolManager; std::unique_ptr m_pGlobalShortcutsProtocolManager; - std::unique_ptr m_pScreencopyProtocolManager; private: std::unordered_map m_mModeChangeListeners; diff --git a/src/protocols/Screencopy.cpp b/src/protocols/Screencopy.cpp index 98cb0be9..a8afba84 100644 --- a/src/protocols/Screencopy.cpp +++ b/src/protocols/Screencopy.cpp @@ -9,245 +9,39 @@ #include -#define SCREENCOPY_VERSION 3 +#define LOGM PROTO::screencopy->protoLog -static void bindManagerInt(wl_client* client, void* data, uint32_t version, uint32_t id) { - g_pProtocolManager->m_pScreencopyProtocolManager->bindManager(client, data, version, id); +CScreencopyFrame::~CScreencopyFrame() { + if (buffer && buffer->locked()) + buffer->unlock(); } -static void handleDisplayDestroy(struct wl_listener* listener, void* data) { - CScreencopyProtocolManager* proto = wl_container_of(listener, proto, m_liDisplayDestroy); - proto->displayDestroy(); -} +CScreencopyFrame::CScreencopyFrame(SP resource_, int32_t overlay_cursor, wl_resource* output, CBox box_) : resource(resource_) { + if (!good()) + return; -void CScreencopyProtocolManager::displayDestroy() { - wl_list_remove(&m_liDisplayDestroy.link); - wl_list_init(&m_liDisplayDestroy.link); - wl_global_destroy(m_pGlobal); -} + overlayCursor = !!overlay_cursor; + pMonitor = CWLOutputResource::fromResource(output)->monitor.get(); -static SScreencopyFrame* frameFromResource(wl_resource*); - -CScreencopyProtocolManager::~CScreencopyProtocolManager() { - displayDestroy(); -} - -CScreencopyProtocolManager::CScreencopyProtocolManager() { - - m_pGlobal = wl_global_create(g_pCompositor->m_sWLDisplay, &zwlr_screencopy_manager_v1_interface, SCREENCOPY_VERSION, this, bindManagerInt); - - if (!m_pGlobal) { - Debug::log(ERR, "ScreencopyProtocolManager could not start! Screensharing will not work!"); + if (!pMonitor) { + LOGM(ERR, "Client requested sharing of a monitor that doesnt exist"); + resource->sendFailed(); + PROTO::screencopy->destroyResource(this); return; } - m_liDisplayDestroy.notify = handleDisplayDestroy; - wl_display_add_destroy_listener(g_pCompositor->m_sWLDisplay, &m_liDisplayDestroy); - - Debug::log(LOG, "ScreencopyProtocolManager started successfully!"); - - m_pSoftwareCursorTimer = makeShared( - std::nullopt, - [this](SP self, void* data) { - // TODO: make it per-monitor - for (auto& m : g_pCompositor->m_vMonitors) { - g_pPointerManager->unlockSoftwareForMonitor(m); - } - m_bTimerArmed = false; - - Debug::log(LOG, "[screencopy] Releasing software cursor lock"); - }, - nullptr); - g_pEventLoopManager->addTimer(m_pSoftwareCursorTimer); -} - -static void handleCaptureOutput(wl_client* client, wl_resource* resource, uint32_t frame, int32_t overlay_cursor, wl_resource* output) { - g_pProtocolManager->m_pScreencopyProtocolManager->captureOutput(client, resource, frame, overlay_cursor, output); -} - -static void handleCaptureRegion(wl_client* client, wl_resource* resource, uint32_t frame, int32_t overlay_cursor, wl_resource* output, int32_t x, int32_t y, int32_t width, - int32_t height) { - g_pProtocolManager->m_pScreencopyProtocolManager->captureOutput(client, resource, frame, overlay_cursor, output, {x, y, width, height}); -} - -static void handleDestroy(wl_client* client, wl_resource* resource) { - wl_resource_destroy(resource); -} - -static void handleCopyFrame(wl_client* client, wl_resource* resource, wl_resource* buffer) { - const auto PFRAME = frameFromResource(resource); - - if (!PFRAME) - return; - - g_pProtocolManager->m_pScreencopyProtocolManager->copyFrame(client, resource, buffer); -} - -static void handleCopyWithDamage(wl_client* client, wl_resource* resource, wl_resource* buffer) { - const auto PFRAME = frameFromResource(resource); - - if (!PFRAME) - return; - - PFRAME->withDamage = true; - handleCopyFrame(client, resource, buffer); -} - -static void handleDestroyFrame(wl_client* client, wl_resource* resource) { - wl_resource_destroy(resource); -} - -static const struct zwlr_screencopy_manager_v1_interface screencopyMgrImpl = { - .capture_output = handleCaptureOutput, - .capture_output_region = handleCaptureRegion, - .destroy = handleDestroy, -}; - -static const struct zwlr_screencopy_frame_v1_interface screencopyFrameImpl = { - .copy = handleCopyFrame, - .destroy = handleDestroyFrame, - .copy_with_damage = handleCopyWithDamage, -}; - -static CScreencopyClient* clientFromResource(wl_resource* resource) { - ASSERT(wl_resource_instance_of(resource, &zwlr_screencopy_manager_v1_interface, &screencopyMgrImpl)); - return (CScreencopyClient*)wl_resource_get_user_data(resource); -} - -static SScreencopyFrame* frameFromResource(wl_resource* resource) { - ASSERT(wl_resource_instance_of(resource, &zwlr_screencopy_frame_v1_interface, &screencopyFrameImpl)); - return (SScreencopyFrame*)wl_resource_get_user_data(resource); -} - -void CScreencopyProtocolManager::removeClient(CScreencopyClient* client, bool force) { - if (!client) - return; - - if (!force) { - if (!client || client->ref <= 0) - return; - - if (--client->ref != 0) - return; - } - - m_lClients.remove(*client); // TODO: this doesn't get cleaned up after sharing app exits??? - - for (auto& f : m_lFrames) { - // avoid dangling ptrs - if (f.client == client) - f.client = nullptr; - } -} - -static void handleManagerResourceDestroy(wl_resource* resource) { - const auto PCLIENT = clientFromResource(resource); - - g_pProtocolManager->m_pScreencopyProtocolManager->removeClient(PCLIENT, true); -} - -CScreencopyClient::~CScreencopyClient() { - g_pHookSystem->unhook(tickCallback); -} - -CScreencopyClient::CScreencopyClient() { - lastMeasure.reset(); - lastFrame.reset(); - tickCallback = g_pHookSystem->hookDynamic("tick", [&](void* self, SCallbackInfo& info, std::any data) { onTick(); }); -} - -void CScreencopyClient::onTick() { - if (lastMeasure.getMillis() < 500) - return; - - framesInLastHalfSecond = frameCounter; - frameCounter = 0; - lastMeasure.reset(); - - const auto LASTFRAMEDELTA = lastFrame.getMillis() / 1000.0; - const bool FRAMEAWAITING = std::ranges::any_of(g_pProtocolManager->m_pScreencopyProtocolManager->m_lFrames, [&](const auto& frame) { return frame.client == this; }) || - std::ranges::any_of(g_pProtocolManager->m_pToplevelExportProtocolManager->m_lFrames, [&](const auto& frame) { return frame.client == this; }); - - if (framesInLastHalfSecond > 3 && !sentScreencast) { - EMIT_HOOK_EVENT("screencast", (std::vector{1, (uint64_t)framesInLastHalfSecond, (uint64_t)clientOwner})); - g_pEventManager->postEvent(SHyprIPCEvent{"screencast", "1," + std::to_string(clientOwner)}); - sentScreencast = true; - } else if (framesInLastHalfSecond < 4 && sentScreencast && LASTFRAMEDELTA > 1.0 && !FRAMEAWAITING) { - EMIT_HOOK_EVENT("screencast", (std::vector{0, (uint64_t)framesInLastHalfSecond, (uint64_t)clientOwner})); - g_pEventManager->postEvent(SHyprIPCEvent{"screencast", "0," + std::to_string(clientOwner)}); - sentScreencast = false; - } -} - -void CScreencopyProtocolManager::bindManager(wl_client* client, void* data, uint32_t version, uint32_t id) { - const auto PCLIENT = &m_lClients.emplace_back(); - - PCLIENT->resource = wl_resource_create(client, &zwlr_screencopy_manager_v1_interface, version, id); - - if (!PCLIENT->resource) { - Debug::log(ERR, "ScreencopyProtocolManager could not bind! (out of memory?)"); - m_lClients.remove(*PCLIENT); - wl_client_post_no_memory(client); - return; - } - - PCLIENT->ref = 1; - - wl_resource_set_implementation(PCLIENT->resource, &screencopyMgrImpl, PCLIENT, handleManagerResourceDestroy); - - Debug::log(LOG, "ScreencopyProtocolManager bound successfully!"); -} - -static void handleFrameResourceDestroy(wl_resource* resource) { - const auto PFRAME = frameFromResource(resource); - - g_pProtocolManager->m_pScreencopyProtocolManager->removeFrame(PFRAME); -} - -void CScreencopyProtocolManager::removeFrame(SScreencopyFrame* frame, bool force) { - if (!frame) - return; - - std::erase_if(m_vFramesAwaitingWrite, [&](const auto& other) { return other == frame; }); - - wl_resource_set_user_data(frame->resource, nullptr); - if (frame->buffer && frame->buffer->locked()) - frame->buffer->unlock(); - removeClient(frame->client, force); - m_lFrames.remove(*frame); -} - -void CScreencopyProtocolManager::captureOutput(wl_client* client, wl_resource* resource, uint32_t frame, int32_t overlay_cursor, wl_resource* output, CBox box) { - const auto PCLIENT = clientFromResource(resource); - - const auto PFRAME = &m_lFrames.emplace_back(); - PFRAME->overlayCursor = !!overlay_cursor; - PFRAME->resource = wl_resource_create(client, &zwlr_screencopy_frame_v1_interface, wl_resource_get_version(resource), frame); - PFRAME->pMonitor = CWLOutputResource::fromResource(output)->monitor.get(); - - if (!PFRAME->pMonitor) { - Debug::log(ERR, "client requested sharing of a monitor that doesnt exist"); - zwlr_screencopy_frame_v1_send_failed(PFRAME->resource); - removeFrame(PFRAME); - return; - } - - if (!PFRAME->resource) { - Debug::log(ERR, "Couldn't alloc frame for sharing! (no memory)"); - removeFrame(PFRAME); - wl_client_post_no_memory(client); - return; - } - - wl_resource_set_implementation(PFRAME->resource, &screencopyFrameImpl, PFRAME, handleFrameResourceDestroy); - - PFRAME->client = PCLIENT; - PCLIENT->ref++; + resource->setOnDestroy([this](CZwlrScreencopyFrameV1* pMgr) { PROTO::screencopy->destroyResource(this); }); + resource->setDestroy([this](CZwlrScreencopyFrameV1* pFrame) { PROTO::screencopy->destroyResource(this); }); + resource->setCopy([this](CZwlrScreencopyFrameV1* pFrame, wl_resource* res) { this->copy(pFrame, res); }); + resource->setCopyWithDamage([this](CZwlrScreencopyFrameV1* pFrame, wl_resource* res) { + withDamage = true; + this->copy(pFrame, res); + }); g_pHyprRenderer->makeEGLCurrent(); - if (g_pHyprOpenGL->m_mMonitorRenderResources.contains(PFRAME->pMonitor)) { - const auto& RDATA = g_pHyprOpenGL->m_mMonitorRenderResources.at(PFRAME->pMonitor); + if (g_pHyprOpenGL->m_mMonitorRenderResources.contains(pMonitor)) { + const auto& RDATA = g_pHyprOpenGL->m_mMonitorRenderResources.at(pMonitor); // bind the fb for its format. Suppress gl errors. #ifndef GLES2 glBindFramebuffer(GL_READ_FRAMEBUFFER, RDATA.offloadFB.m_iFb); @@ -255,246 +49,212 @@ void CScreencopyProtocolManager::captureOutput(wl_client* client, wl_resource* r glBindFramebuffer(GL_FRAMEBUFFER, RDATA.offloadFB.m_iFb); #endif } else - Debug::log(ERR, "No RDATA in screencopy???"); + LOGM(ERR, "No RDATA in screencopy???"); - PFRAME->shmFormat = g_pHyprOpenGL->getPreferredReadFormat(PFRAME->pMonitor); - if (PFRAME->shmFormat == DRM_FORMAT_INVALID) { - Debug::log(ERR, "No format supported by renderer in capture output"); - zwlr_screencopy_frame_v1_send_failed(PFRAME->resource); - removeFrame(PFRAME); + shmFormat = g_pHyprOpenGL->getPreferredReadFormat(pMonitor); + if (shmFormat == DRM_FORMAT_INVALID) { + LOGM(ERR, "No format supported by renderer in capture output"); + resource->sendFailed(); + PROTO::screencopy->destroyResource(this); return; } - const auto PSHMINFO = FormatUtils::getPixelFormatFromDRM(PFRAME->shmFormat); + const auto PSHMINFO = FormatUtils::getPixelFormatFromDRM(shmFormat); if (!PSHMINFO) { - Debug::log(ERR, "No pixel format supported by renderer in capture output"); - zwlr_screencopy_frame_v1_send_failed(PFRAME->resource); - removeFrame(PFRAME); + LOGM(ERR, "No pixel format supported by renderer in capture output"); + resource->sendFailed(); + PROTO::screencopy->destroyResource(this); return; } - PFRAME->dmabufFormat = PFRAME->pMonitor->output->state->state().drmFormat; + dmabufFormat = pMonitor->output->state->state().drmFormat; - if (box.width == 0 && box.height == 0) - PFRAME->box = {0, 0, (int)(PFRAME->pMonitor->vecSize.x), (int)(PFRAME->pMonitor->vecSize.y)}; + if (box_.width == 0 && box_.height == 0) + box = {0, 0, (int)(pMonitor->vecSize.x), (int)(pMonitor->vecSize.y)}; else { - PFRAME->box = box; + box = box_; } - PFRAME->box.transform(wlTransformToHyprutils(PFRAME->pMonitor->transform), PFRAME->pMonitor->vecTransformedSize.x, PFRAME->pMonitor->vecTransformedSize.y) - .scale(PFRAME->pMonitor->scale) - .round(); + box.transform(wlTransformToHyprutils(pMonitor->transform), pMonitor->vecTransformedSize.x, pMonitor->vecTransformedSize.y).scale(pMonitor->scale).round(); - PFRAME->shmStride = FormatUtils::minStride(PSHMINFO, PFRAME->box.w); + shmStride = FormatUtils::minStride(PSHMINFO, box.w); - zwlr_screencopy_frame_v1_send_buffer(PFRAME->resource, FormatUtils::drmToShm(PFRAME->shmFormat), PFRAME->box.width, PFRAME->box.height, PFRAME->shmStride); + resource->sendBuffer(FormatUtils::drmToShm(shmFormat), box.width, box.height, shmStride); - if (wl_resource_get_version(resource) >= 3) { - if (PFRAME->dmabufFormat != DRM_FORMAT_INVALID) { - zwlr_screencopy_frame_v1_send_linux_dmabuf(PFRAME->resource, PFRAME->dmabufFormat, PFRAME->box.width, PFRAME->box.height); + if (resource->version() >= 3) { + if (dmabufFormat != DRM_FORMAT_INVALID) { + resource->sendLinuxDmabuf(dmabufFormat, box.width, box.height); } - zwlr_screencopy_frame_v1_send_buffer_done(PFRAME->resource); + resource->sendBufferDone(); } } -void CScreencopyProtocolManager::copyFrame(wl_client* client, wl_resource* resource, wl_resource* buffer) { - const auto PFRAME = frameFromResource(resource); - - if (!PFRAME) { - Debug::log(ERR, "No frame in copyFrame??"); +void CScreencopyFrame::copy(CZwlrScreencopyFrameV1* pFrame, wl_resource* buffer_) { + if (!good()) { + LOGM(ERR, "No frame in copyFrame??"); return; } - if (!g_pCompositor->monitorExists(PFRAME->pMonitor)) { - Debug::log(ERR, "client requested sharing of a monitor that is gone"); - zwlr_screencopy_frame_v1_send_failed(PFRAME->resource); - removeFrame(PFRAME); + if (!g_pCompositor->monitorExists(pMonitor)) { + LOGM(ERR, "Client requested sharing of a monitor that is gone"); + resource->sendFailed(); + PROTO::screencopy->destroyResource(this); return; } - const auto PBUFFER = CWLBufferResource::fromResource(buffer); + const auto PBUFFER = CWLBufferResource::fromResource(buffer_); if (!PBUFFER) { - Debug::log(ERR, "[sc] invalid buffer in {:x}", (uintptr_t)PFRAME); - wl_resource_post_error(PFRAME->resource, ZWLR_SCREENCOPY_FRAME_V1_ERROR_INVALID_BUFFER, "invalid buffer"); - removeFrame(PFRAME); + LOGM(ERR, "Invalid buffer in {:x}", (uintptr_t)this); + resource->error(ZWLR_SCREENCOPY_FRAME_V1_ERROR_INVALID_BUFFER, "invalid buffer"); + PROTO::screencopy->destroyResource(this); return; } PBUFFER->buffer->lock(); - if (PBUFFER->buffer->size != PFRAME->box.size()) { - Debug::log(ERR, "[sc] invalid dimensions in {:x}", (uintptr_t)PFRAME); - wl_resource_post_error(PFRAME->resource, ZWLR_SCREENCOPY_FRAME_V1_ERROR_INVALID_BUFFER, "invalid buffer dimensions"); - removeFrame(PFRAME); + if (PBUFFER->buffer->size != box.size()) { + LOGM(ERR, "Invalid dimensions in {:x}", (uintptr_t)this); + resource->error(ZWLR_SCREENCOPY_FRAME_V1_ERROR_INVALID_BUFFER, "invalid buffer dimensions"); + PROTO::screencopy->destroyResource(this); return; } - if (PFRAME->buffer) { - Debug::log(ERR, "[sc] buffer used in {:x}", (uintptr_t)PFRAME); - wl_resource_post_error(PFRAME->resource, ZWLR_SCREENCOPY_FRAME_V1_ERROR_ALREADY_USED, "frame already used"); - removeFrame(PFRAME); + if (buffer) { + LOGM(ERR, "Buffer used in {:x}", (uintptr_t)this); + resource->error(ZWLR_SCREENCOPY_FRAME_V1_ERROR_ALREADY_USED, "frame already used"); + PROTO::screencopy->destroyResource(this); return; } if (auto attrs = PBUFFER->buffer->dmabuf(); attrs.success) { - PFRAME->bufferDMA = true; + bufferDMA = true; - if (attrs.format != PFRAME->dmabufFormat) { - Debug::log(ERR, "[sc] invalid buffer dma format in {:x}", (uintptr_t)PFRAME); - wl_resource_post_error(PFRAME->resource, ZWLR_SCREENCOPY_FRAME_V1_ERROR_INVALID_BUFFER, "invalid buffer format"); - removeFrame(PFRAME); + if (attrs.format != dmabufFormat) { + LOGM(ERR, "Invalid buffer dma format in {:x}", (uintptr_t)pFrame); + resource->error(ZWLR_SCREENCOPY_FRAME_V1_ERROR_INVALID_BUFFER, "invalid buffer format"); + PROTO::screencopy->destroyResource(this); return; } } else if (auto attrs = PBUFFER->buffer->shm(); attrs.success) { - if (attrs.format != PFRAME->shmFormat) { - Debug::log(ERR, "[sc] invalid buffer shm format in {:x}", (uintptr_t)PFRAME); - wl_resource_post_error(PFRAME->resource, ZWLR_SCREENCOPY_FRAME_V1_ERROR_INVALID_BUFFER, "invalid buffer format"); - removeFrame(PFRAME); + if (attrs.format != shmFormat) { + LOGM(ERR, "Invalid buffer shm format in {:x}", (uintptr_t)pFrame); + resource->error(ZWLR_SCREENCOPY_FRAME_V1_ERROR_INVALID_BUFFER, "invalid buffer format"); + PROTO::screencopy->destroyResource(this); return; - } else if ((int)attrs.stride != PFRAME->shmStride) { - Debug::log(ERR, "[sc] invalid buffer shm stride in {:x}", (uintptr_t)PFRAME); - wl_resource_post_error(PFRAME->resource, ZWLR_SCREENCOPY_FRAME_V1_ERROR_INVALID_BUFFER, "invalid buffer stride"); - removeFrame(PFRAME); + } else if ((int)attrs.stride != shmStride) { + LOGM(ERR, "Invalid buffer shm stride in {:x}", (uintptr_t)pFrame); + resource->error(ZWLR_SCREENCOPY_FRAME_V1_ERROR_INVALID_BUFFER, "invalid buffer stride"); + PROTO::screencopy->destroyResource(this); return; } } else { - Debug::log(ERR, "[sc] invalid buffer type in {:x}", (uintptr_t)PFRAME); - wl_resource_post_error(PFRAME->resource, ZWLR_SCREENCOPY_FRAME_V1_ERROR_INVALID_BUFFER, "invalid buffer type"); - removeFrame(PFRAME); + LOGM(ERR, "Invalid buffer type in {:x}", (uintptr_t)pFrame); + resource->error(ZWLR_SCREENCOPY_FRAME_V1_ERROR_INVALID_BUFFER, "invalid buffer type"); + PROTO::screencopy->destroyResource(this); return; } - PFRAME->buffer = PBUFFER->buffer; + buffer = PBUFFER->buffer; - m_vFramesAwaitingWrite.emplace_back(PFRAME); + PROTO::screencopy->m_vFramesAwaitingWrite.emplace_back(self); g_pHyprRenderer->m_bDirectScanoutBlocked = true; - if (PFRAME->overlayCursor && !PFRAME->lockedSWCursors) { - PFRAME->lockedSWCursors = true; + if (overlayCursor && !lockedSWCursors) { + lockedSWCursors = true; // TODO: make it per-monitor - if (!m_bTimerArmed) { + if (!PROTO::screencopy->m_bTimerArmed) { for (auto& m : g_pCompositor->m_vMonitors) { g_pPointerManager->lockSoftwareForMonitor(m); } - m_bTimerArmed = true; - Debug::log(LOG, "[screencopy] Locking sw cursors due to screensharing"); + PROTO::screencopy->m_bTimerArmed = true; + LOGM(LOG, "Locking sw cursors due to screensharing"); } - m_pSoftwareCursorTimer->updateTimeout(std::chrono::seconds(1)); + PROTO::screencopy->m_pSoftwareCursorTimer->updateTimeout(std::chrono::seconds(1)); } - if (!PFRAME->withDamage) - g_pHyprRenderer->damageMonitor(PFRAME->pMonitor); + if (!withDamage) + g_pHyprRenderer->damageMonitor(pMonitor); } -void CScreencopyProtocolManager::onOutputCommit(CMonitor* pMonitor) { - m_pLastMonitorBackBuffer = pMonitor->output->state->state().buffer; - shareAllFrames(pMonitor); - m_pLastMonitorBackBuffer.reset(); -} - -void CScreencopyProtocolManager::shareAllFrames(CMonitor* pMonitor) { - if (m_vFramesAwaitingWrite.empty()) - return; // nothing to share - - std::vector framesToRemove; - - // share frame if correct output - for (auto& f : m_vFramesAwaitingWrite) { - if (!f->pMonitor || !f->buffer) { - framesToRemove.push_back(f); - continue; - } - - if (f->pMonitor != pMonitor) - continue; - - shareFrame(f); - - f->client->lastFrame.reset(); - ++f->client->frameCounter; - - framesToRemove.push_back(f); - } - - for (auto& f : framesToRemove) { - removeFrame(f); - } - - if (m_vFramesAwaitingWrite.empty()) { - g_pHyprRenderer->m_bDirectScanoutBlocked = false; - } -} - -void CScreencopyProtocolManager::shareFrame(SScreencopyFrame* frame) { - if (!frame->buffer) +void CScreencopyFrame::share() { + if (!buffer || !pMonitor) return; timespec now; clock_gettime(CLOCK_MONOTONIC, &now); - uint32_t flags = 0; - if (frame->bufferDMA) { - if (!copyFrameDmabuf(frame)) { - Debug::log(ERR, "[sc] dmabuf copy failed in {:x}", (uintptr_t)frame); - zwlr_screencopy_frame_v1_send_failed(frame->resource); + if (bufferDMA) { + if (!copyDmabuf()) { + LOGM(ERR, "Dmabuf copy failed in {:x}", (uintptr_t)this); + resource->sendFailed(); return; } } else { - if (!copyFrameShm(frame, &now)) { - Debug::log(ERR, "[sc] shm copy failed in {:x}", (uintptr_t)frame); - zwlr_screencopy_frame_v1_send_failed(frame->resource); + if (!copyShm()) { + LOGM(ERR, "Shm copy failed in {:x}", (uintptr_t)this); + resource->sendFailed(); return; } } - zwlr_screencopy_frame_v1_send_flags(frame->resource, flags); - sendFrameDamage(frame); + resource->sendFlags((zwlrScreencopyFrameV1Flags)0); + if (withDamage) { + // TODO: add a damage ring for this. + resource->sendDamage(0, 0, buffer->size.x, buffer->size.y); + } + uint32_t tvSecHi = (sizeof(now.tv_sec) > 4) ? now.tv_sec >> 32 : 0; uint32_t tvSecLo = now.tv_sec & 0xFFFFFFFF; - zwlr_screencopy_frame_v1_send_ready(frame->resource, tvSecHi, tvSecLo, now.tv_nsec); + resource->sendReady(tvSecHi, tvSecLo, now.tv_nsec); } -void CScreencopyProtocolManager::sendFrameDamage(SScreencopyFrame* frame) { - if (!frame->withDamage) - return; +bool CScreencopyFrame::copyDmabuf() { + auto TEXTURE = makeShared(pMonitor->output->state->state().buffer); - // TODO: - // add a damage ring for this. + CRegion fakeDamage = {0, 0, INT16_MAX, INT16_MAX}; - // for (auto& RECT : frame->pMonitor->lastFrameDamage.getRects()) { + if (!g_pHyprRenderer->beginRender(pMonitor, fakeDamage, RENDER_MODE_TO_BUFFER, buffer.lock(), nullptr, true)) { + LOGM(ERR, "Can't copy: failed to begin rendering to dma frame"); + return false; + } - // if (frame->buffer->width < 1 || frame->buffer->height < 1 || frame->buffer->width - RECT.x1 < 1 || frame->buffer->height - RECT.y1 < 1) { - // Debug::log(ERR, "[sc] Failed to send damage"); - // break; - // } + CBox monbox = CBox{0, 0, pMonitor->vecPixelSize.x, pMonitor->vecPixelSize.y} + .translate({-box.x, -box.y}) // vvvv kinda ass-backwards but that's how I designed the renderer... sigh. + .transform(wlTransformToHyprutils(invertTransform(pMonitor->transform)), pMonitor->vecPixelSize.x, pMonitor->vecPixelSize.y); + g_pHyprOpenGL->setMonitorTransformEnabled(true); + g_pHyprOpenGL->setRenderModifEnabled(false); + g_pHyprOpenGL->renderTexture(TEXTURE, &monbox, 1); + g_pHyprOpenGL->setRenderModifEnabled(true); + g_pHyprOpenGL->setMonitorTransformEnabled(false); - // zwlr_screencopy_frame_v1_send_damage(frame->resource, std::clamp(RECT.x1, 0, frame->buffer->width), std::clamp(RECT.y1, 0, frame->buffer->height), - // std::clamp(RECT.x2 - RECT.x1, 0, frame->buffer->width - RECT.x1), std::clamp(RECT.y2 - RECT.y1, 0, frame->buffer->height - RECT.y1)); - // } + g_pHyprOpenGL->m_RenderData.blockScreenShader = true; + g_pHyprRenderer->endRender(); - zwlr_screencopy_frame_v1_send_damage(frame->resource, 0, 0, frame->buffer->size.x, frame->buffer->size.y); + LOGM(TRACE, "Copied frame via dma"); + + return true; } -bool CScreencopyProtocolManager::copyFrameShm(SScreencopyFrame* frame, timespec* now) { - auto TEXTURE = makeShared(m_pLastMonitorBackBuffer); +bool CScreencopyFrame::copyShm() { + auto TEXTURE = makeShared(pMonitor->output->state->state().buffer); - auto shm = frame->buffer->shm(); - auto [pixelData, fmt, bufLen] = frame->buffer->beginDataPtr(0); // no need for end, cuz it's shm + auto shm = buffer->shm(); + auto [pixelData, fmt, bufLen] = buffer->beginDataPtr(0); // no need for end, cuz it's shm CRegion fakeDamage = {0, 0, INT16_MAX, INT16_MAX}; g_pHyprRenderer->makeEGLCurrent(); CFramebuffer fb; - fb.alloc(frame->box.w, frame->box.h, g_pHyprRenderer->isNvidia() ? DRM_FORMAT_XBGR8888 : frame->pMonitor->output->state->state().drmFormat); + fb.alloc(box.w, box.h, g_pHyprRenderer->isNvidia() ? DRM_FORMAT_XBGR8888 : pMonitor->output->state->state().drmFormat); - if (!g_pHyprRenderer->beginRender(frame->pMonitor, fakeDamage, RENDER_MODE_FULL_FAKE, nullptr, &fb, true)) { - Debug::log(ERR, "Screencopy: can't copy: failed to begin rendering"); + if (!g_pHyprRenderer->beginRender(pMonitor, fakeDamage, RENDER_MODE_FULL_FAKE, nullptr, &fb, true)) { + LOGM(ERR, "Can't copy: failed to begin rendering"); return false; } - CBox monbox = CBox{0, 0, frame->pMonitor->vecTransformedSize.x, frame->pMonitor->vecTransformedSize.y}.translate({-frame->box.x, -frame->box.y}); + CBox monbox = CBox{0, 0, pMonitor->vecTransformedSize.x, pMonitor->vecTransformedSize.y}.translate({-box.x, -box.y}); g_pHyprOpenGL->setMonitorTransformEnabled(true); g_pHyprOpenGL->setRenderModifEnabled(false); g_pHyprOpenGL->renderTexture(TEXTURE, &monbox, 1); @@ -509,7 +269,7 @@ bool CScreencopyProtocolManager::copyFrameShm(SScreencopyFrame* frame, timespec* const auto PFORMAT = FormatUtils::getPixelFormatFromDRM(shm.format); if (!PFORMAT) { - Debug::log(ERR, "Screencopy: can't copy: failed to find a pixel format"); + LOGM(ERR, "Can't copy: failed to find a pixel format"); g_pHyprRenderer->endRender(); return false; } @@ -520,53 +280,164 @@ bool CScreencopyProtocolManager::copyFrameShm(SScreencopyFrame* frame, timespec* g_pHyprRenderer->endRender(); g_pHyprRenderer->makeEGLCurrent(); - g_pHyprOpenGL->m_RenderData.pMonitor = frame->pMonitor; + g_pHyprOpenGL->m_RenderData.pMonitor = pMonitor; fb.bind(); glPixelStorei(GL_PACK_ALIGNMENT, 1); const auto drmFmt = FormatUtils::getPixelFormatFromDRM(shm.format); - uint32_t packStride = FormatUtils::minStride(drmFmt, frame->box.w); + uint32_t packStride = FormatUtils::minStride(drmFmt, box.w); if (packStride == (uint32_t)shm.stride) { - glReadPixels(0, 0, frame->box.w, frame->box.h, glFormat, PFORMAT->glType, pixelData); + glReadPixels(0, 0, box.w, box.h, glFormat, PFORMAT->glType, pixelData); } else { - for (size_t i = 0; i < frame->box.h; ++i) { + for (size_t i = 0; i < box.h; ++i) { uint32_t y = i; - glReadPixels(0, y, frame->box.w, 1, glFormat, PFORMAT->glType, ((unsigned char*)pixelData) + i * shm.stride); + glReadPixels(0, y, box.w, 1, glFormat, PFORMAT->glType, ((unsigned char*)pixelData) + i * shm.stride); } } g_pHyprOpenGL->m_RenderData.pMonitor = nullptr; - Debug::log(TRACE, "Screencopy: copied frame via shm"); + LOGM(TRACE, "Copied frame via shm"); return true; } -bool CScreencopyProtocolManager::copyFrameDmabuf(SScreencopyFrame* frame) { - auto TEXTURE = makeShared(m_pLastMonitorBackBuffer); +bool CScreencopyFrame::good() { + return resource->resource(); +} - CRegion fakeDamage = {0, 0, INT16_MAX, INT16_MAX}; +CScreencopyClient::~CScreencopyClient() { + g_pHookSystem->unhook(tickCallback); +} - if (!g_pHyprRenderer->beginRender(frame->pMonitor, fakeDamage, RENDER_MODE_TO_BUFFER, frame->buffer.lock(), nullptr, true)) { - Debug::log(ERR, "Screencopy: can't copy: failed to begin rendering to dma frame"); - return false; +CScreencopyClient::CScreencopyClient(SP resource_) : resource(resource_) { + if (!good()) + return; + + resource->setDestroy([this](CZwlrScreencopyManagerV1* pMgr) { PROTO::screencopy->destroyResource(this); }); + resource->setOnDestroy([this](CZwlrScreencopyManagerV1* pMgr) { PROTO::screencopy->destroyResource(this); }); + resource->setCaptureOutput( + [this](CZwlrScreencopyManagerV1* pMgr, uint32_t frame, int32_t overlayCursor, wl_resource* output) { this->captureOutput(frame, overlayCursor, output, {}); }); + resource->setCaptureOutputRegion([this](CZwlrScreencopyManagerV1* pMgr, uint32_t frame, int32_t overlayCursor, wl_resource* output, int32_t x, int32_t y, int32_t w, + int32_t h) { this->captureOutput(frame, overlayCursor, output, {x, y, w, h}); }); + + lastMeasure.reset(); + lastFrame.reset(); + tickCallback = g_pHookSystem->hookDynamic("tick", [&](void* self, SCallbackInfo& info, std::any data) { onTick(); }); +} + +void CScreencopyClient::captureOutput(uint32_t frame, int32_t overlayCursor_, wl_resource* output, CBox box) { + const auto FRAME = PROTO::screencopy->m_vFrames.emplace_back( + makeShared(makeShared(resource->client(), resource->version(), frame), overlayCursor_, output, box)); + + if (!FRAME->good()) { + LOGM(ERR, "Couldn't alloc frame for sharing! (no memory)"); + resource->noMemory(); + PROTO::screencopy->destroyResource(FRAME.get()); + return; } - CBox monbox = CBox{0, 0, frame->pMonitor->vecPixelSize.x, frame->pMonitor->vecPixelSize.y} - .translate({-frame->box.x, -frame->box.y}) // vvvv kinda ass-backwards but that's how I designed the renderer... sigh. - .transform(wlTransformToHyprutils(invertTransform(frame->pMonitor->transform)), frame->pMonitor->vecPixelSize.x, frame->pMonitor->vecPixelSize.y); - g_pHyprOpenGL->setMonitorTransformEnabled(true); - g_pHyprOpenGL->setRenderModifEnabled(false); - g_pHyprOpenGL->renderTexture(TEXTURE, &monbox, 1); - g_pHyprOpenGL->setRenderModifEnabled(true); - g_pHyprOpenGL->setMonitorTransformEnabled(false); - - g_pHyprOpenGL->m_RenderData.blockScreenShader = true; - g_pHyprRenderer->endRender(); - - Debug::log(TRACE, "Screencopy: copied frame via dma"); - - return true; + FRAME->self = FRAME; + FRAME->client = self; +} + +void CScreencopyClient::onTick() { + if (lastMeasure.getMillis() < 500) + return; + + framesInLastHalfSecond = frameCounter; + frameCounter = 0; + lastMeasure.reset(); + + const auto LASTFRAMEDELTA = lastFrame.getMillis() / 1000.0; + const bool FRAMEAWAITING = std::ranges::any_of(PROTO::screencopy->m_vFrames, [&](const auto& frame) { return frame->client.get() == this; }); + + if (framesInLastHalfSecond > 3 && !sentScreencast) { + EMIT_HOOK_EVENT("screencast", (std::vector{1, (uint64_t)framesInLastHalfSecond, (uint64_t)clientOwner})); + g_pEventManager->postEvent(SHyprIPCEvent{"screencast", "1," + std::to_string(clientOwner)}); + sentScreencast = true; + } else if (framesInLastHalfSecond < 4 && sentScreencast && LASTFRAMEDELTA > 1.0 && !FRAMEAWAITING) { + EMIT_HOOK_EVENT("screencast", (std::vector{0, (uint64_t)framesInLastHalfSecond, (uint64_t)clientOwner})); + g_pEventManager->postEvent(SHyprIPCEvent{"screencast", "0," + std::to_string(clientOwner)}); + sentScreencast = false; + } +} + +bool CScreencopyClient::good() { + return resource->resource(); +} + +CScreencopyProtocol::CScreencopyProtocol(const wl_interface* iface, const int& ver, const std::string& name) : IWaylandProtocol(iface, ver, name) { + m_pSoftwareCursorTimer = makeShared( + std::nullopt, + [this](SP self, void* data) { + // TODO: make it per-monitor + for (auto& m : g_pCompositor->m_vMonitors) { + g_pPointerManager->unlockSoftwareForMonitor(m); + } + m_bTimerArmed = false; + + LOGM(LOG, "Releasing software cursor lock"); + }, + nullptr); + g_pEventLoopManager->addTimer(m_pSoftwareCursorTimer); +} + +void CScreencopyProtocol::bindManager(wl_client* client, void* data, uint32_t ver, uint32_t id) { + const auto CLIENT = m_vClients.emplace_back(makeShared(makeShared(client, ver, id))); + + if (!CLIENT->good()) { + LOGM(LOG, "Failed to bind client! (out of memory)"); + CLIENT->resource->noMemory(); + m_vClients.pop_back(); + return; + } + + CLIENT->self = CLIENT; + + LOGM(LOG, "Bound client successfully!"); +} + +void CScreencopyProtocol::destroyResource(CScreencopyClient* client) { + std::erase_if(m_vClients, [&](const auto& other) { return other.get() == client; }); + std::erase_if(m_vFrames, [&](const auto& other) { return other->client.get() == client; }); + std::erase_if(m_vFramesAwaitingWrite, [&](const auto& other) { return other->client.get() == client; }); +} + +void CScreencopyProtocol::destroyResource(CScreencopyFrame* frame) { + std::erase_if(m_vFrames, [&](const auto& other) { return other.get() == frame; }); + std::erase_if(m_vFramesAwaitingWrite, [&](const auto& other) { return other.get() == frame; }); +} + +void CScreencopyProtocol::onOutputCommit(CMonitor* pMonitor) { + if (m_vFramesAwaitingWrite.empty()) { + g_pHyprRenderer->m_bDirectScanoutBlocked = false; + return; // nothing to share + } + + std::vector> framesToRemove; + + // share frame if correct output + for (auto& f : m_vFramesAwaitingWrite) { + if (!f->pMonitor || !f->buffer) { + framesToRemove.push_back(f); + continue; + } + + if (f->pMonitor != pMonitor) + continue; + + f->share(); + + f->client->lastFrame.reset(); + ++f->client->frameCounter; + + framesToRemove.push_back(f); + } + + for (auto& f : framesToRemove) { + destroyResource(f.get()); + } } diff --git a/src/protocols/Screencopy.hpp b/src/protocols/Screencopy.hpp index d564e432..cbc56edb 100644 --- a/src/protocols/Screencopy.hpp +++ b/src/protocols/Screencopy.hpp @@ -1,7 +1,8 @@ #pragma once #include "../defines.hpp" -#include "wlr-screencopy-unstable-v1-protocol.h" +#include "wlr-screencopy-unstable-v1.hpp" +#include "WaylandProtocol.hpp" #include #include @@ -20,88 +21,93 @@ enum eClientOwners { class CScreencopyClient { public: - CScreencopyClient(); + CScreencopyClient(SP resource_); ~CScreencopyClient(); - int ref = 0; - wl_resource* resource = nullptr; + bool good(); - eClientOwners clientOwner = CLIENT_SCREENCOPY; + WP self; + eClientOwners clientOwner = CLIENT_SCREENCOPY; - int frameCounter = 0; - int framesInLastHalfSecond = 0; - CTimer lastMeasure; - CTimer lastFrame; - bool sentScreencast = false; - - void onTick(); - SP tickCallback; - - bool operator==(const CScreencopyClient& other) const { - return resource == other.resource; - } -}; - -struct SScreencopyFrame { - wl_resource* resource = nullptr; - CScreencopyClient* client = nullptr; - - uint32_t shmFormat = 0; - uint32_t dmabufFormat = 0; - CBox box = {}; - int shmStride = 0; - - bool overlayCursor = false; - bool withDamage = false; - bool lockedSWCursors = false; - - bool bufferDMA = false; - - WP buffer; - - CMonitor* pMonitor = nullptr; - PHLWINDOWREF pWindow; - - bool operator==(const SScreencopyFrame& other) const { - return resource == other.resource && client == other.client; - } -}; - -class CScreencopyProtocolManager { - public: - CScreencopyProtocolManager(); - ~CScreencopyProtocolManager(); - - void bindManager(wl_client* client, void* data, uint32_t version, uint32_t id); - void removeClient(CScreencopyClient* client, bool force = false); - void removeFrame(SScreencopyFrame* frame, bool force = false); - void displayDestroy(); - - void captureOutput(wl_client* client, wl_resource* resource, uint32_t frame, int32_t overlay_cursor, wl_resource* output, CBox box = {0, 0, 0, 0}); - - void copyFrame(wl_client* client, wl_resource* resource, wl_resource* buffer); - - void onOutputCommit(CMonitor* pMonitor); - - wl_listener m_liDisplayDestroy; + CTimer lastFrame; + int frameCounter = 0; private: - wl_global* m_pGlobal = nullptr; - std::list m_lFrames; - std::list m_lClients; + SP resource; - SP m_pSoftwareCursorTimer; - bool m_bTimerArmed = false; + int framesInLastHalfSecond = 0; + CTimer lastMeasure; + bool sentScreencast = false; - std::vector m_vFramesAwaitingWrite; + SP tickCallback; + void onTick(); - SP m_pLastMonitorBackBuffer; + void captureOutput(uint32_t frame, int32_t overlayCursor, wl_resource* output, CBox box); - void shareAllFrames(CMonitor* pMonitor); - void shareFrame(SScreencopyFrame* frame); - void sendFrameDamage(SScreencopyFrame* frame); - bool copyFrameDmabuf(SScreencopyFrame* frame); - bool copyFrameShm(SScreencopyFrame* frame, timespec* now); + friend class CScreencopyProtocol; +}; +class CScreencopyFrame { + public: + CScreencopyFrame(SP resource, int32_t overlay_cursor, wl_resource* output, CBox box); + ~CScreencopyFrame(); + + bool good(); + + SP self; + WP client; + + private: + SP resource; + + CMonitor* pMonitor = nullptr; + bool overlayCursor = false; + bool withDamage = false; + bool lockedSWCursors = false; + + WP buffer; + bool bufferDMA = false; + uint32_t shmFormat = 0; + uint32_t dmabufFormat = 0; + int shmStride = 0; + CBox box = {}; + + void copy(CZwlrScreencopyFrameV1* pFrame, wl_resource* buffer); + bool copyDmabuf(); + bool copyShm(); + void share(); + + friend class CScreencopyProtocol; +}; + +class CScreencopyProtocol : public IWaylandProtocol { + public: + CScreencopyProtocol(const wl_interface* iface, const int& ver, const std::string& name); + + virtual void bindManager(wl_client* client, void* data, uint32_t version, uint32_t id); + void destroyResource(CScreencopyClient* resource); + void destroyResource(CScreencopyFrame* resource); + + void onOutputCommit(CMonitor* pMonitor); + + private: + std::vector> m_vFrames; + std::vector> m_vFramesAwaitingWrite; + std::vector> m_vClients; + + SP m_pSoftwareCursorTimer; + bool m_bTimerArmed = false; + + void shareAllFrames(CMonitor* pMonitor); + void shareFrame(CScreencopyFrame* frame); + void sendFrameDamage(CScreencopyFrame* frame); + bool copyFrameDmabuf(CScreencopyFrame* frame); + bool copyFrameShm(CScreencopyFrame* frame, timespec* now); + + friend class CScreencopyFrame; friend class CScreencopyClient; }; + +namespace PROTO { + inline UP screencopy; +}; diff --git a/src/protocols/ToplevelExport.cpp b/src/protocols/ToplevelExport.cpp index 28f49c6a..fb3fde2b 100644 --- a/src/protocols/ToplevelExport.cpp +++ b/src/protocols/ToplevelExport.cpp @@ -8,363 +8,240 @@ #include -#define TOPLEVEL_EXPORT_VERSION 2 +#define LOGM PROTO::toplevelExport->protoLog -static void bindManagerInt(wl_client* client, void* data, uint32_t version, uint32_t id) { - g_pProtocolManager->m_pToplevelExportProtocolManager->bindManager(client, data, version, id); -} - -static void handleDisplayDestroy(struct wl_listener* listener, void* data) { - CToplevelExportProtocolManager* proto = wl_container_of(listener, proto, m_liDisplayDestroy); - proto->displayDestroy(); -} - -void CToplevelExportProtocolManager::displayDestroy() { - wl_list_remove(&m_liDisplayDestroy.link); - wl_list_init(&m_liDisplayDestroy.link); - wl_global_destroy(m_pGlobal); -} - -CToplevelExportProtocolManager::~CToplevelExportProtocolManager() { - displayDestroy(); -} - -CToplevelExportProtocolManager::CToplevelExportProtocolManager() { - -#ifndef GLES32 - Debug::log(WARN, "Toplevel sharing is not supported on LEGACY_RENDERER!"); - return; -#endif - - m_pGlobal = wl_global_create(g_pCompositor->m_sWLDisplay, &hyprland_toplevel_export_manager_v1_interface, TOPLEVEL_EXPORT_VERSION, this, bindManagerInt); - - if (!m_pGlobal) { - Debug::log(ERR, "ToplevelExportManager could not start! Sharing windows will not work!"); - return; - } - - m_liDisplayDestroy.notify = handleDisplayDestroy; - wl_display_add_destroy_listener(g_pCompositor->m_sWLDisplay, &m_liDisplayDestroy); - - Debug::log(LOG, "ToplevelExportManager started successfully!"); -} - -static void handleCaptureToplevel(wl_client* client, wl_resource* resource, uint32_t frame, int32_t overlay_cursor, uint32_t handle) { - g_pProtocolManager->m_pToplevelExportProtocolManager->captureToplevel(client, resource, frame, overlay_cursor, g_pCompositor->getWindowFromHandle(handle)); -} - -static void handleCaptureToplevelWithWlr(wl_client* client, wl_resource* resource, uint32_t frame, int32_t overlay_cursor, wl_resource* handle) { - g_pProtocolManager->m_pToplevelExportProtocolManager->captureToplevel(client, resource, frame, overlay_cursor, PROTO::foreignToplevelWlr->windowFromHandleResource(handle)); -} - -static void handleDestroy(wl_client* client, wl_resource* resource) { - wl_resource_destroy(resource); -} - -static void handleCopyFrame(wl_client* client, wl_resource* resource, wl_resource* buffer, int32_t ignore_damage) { - g_pProtocolManager->m_pToplevelExportProtocolManager->copyFrame(client, resource, buffer, ignore_damage); -} - -static void handleDestroyFrame(wl_client* client, wl_resource* resource) { - wl_resource_destroy(resource); -} - -static const struct hyprland_toplevel_export_manager_v1_interface toplevelExportManagerImpl = { - .capture_toplevel = handleCaptureToplevel, - .destroy = handleDestroy, - .capture_toplevel_with_wlr_toplevel_handle = handleCaptureToplevelWithWlr, -}; - -static const struct hyprland_toplevel_export_frame_v1_interface toplevelFrameImpl = {.copy = handleCopyFrame, .destroy = handleDestroyFrame}; - -// -static CScreencopyClient* clientFromResource(wl_resource* resource) { - ASSERT(wl_resource_instance_of(resource, &hyprland_toplevel_export_manager_v1_interface, &toplevelExportManagerImpl)); - return (CScreencopyClient*)wl_resource_get_user_data(resource); -} - -static SScreencopyFrame* frameFromResource(wl_resource* resource) { - ASSERT(wl_resource_instance_of(resource, &hyprland_toplevel_export_frame_v1_interface, &toplevelFrameImpl)); - return (SScreencopyFrame*)wl_resource_get_user_data(resource); -} - -void CToplevelExportProtocolManager::removeClient(CScreencopyClient* client, bool force) { - if (!force) { - if (!client || client->ref <= 0) - return; - - if (--client->ref != 0) - return; - } - - m_lClients.remove(*client); // TODO: this doesn't get cleaned up after sharing app exits??? -} - -static void handleManagerResourceDestroy(wl_resource* resource) { - const auto PCLIENT = clientFromResource(resource); - - g_pProtocolManager->m_pToplevelExportProtocolManager->removeClient(PCLIENT, true); -} - -void CToplevelExportProtocolManager::bindManager(wl_client* client, void* data, uint32_t version, uint32_t id) { - const auto PCLIENT = &m_lClients.emplace_back(); - - PCLIENT->clientOwner = CLIENT_TOPLEVEL_EXPORT; - PCLIENT->resource = wl_resource_create(client, &hyprland_toplevel_export_manager_v1_interface, version, id); - - if (!PCLIENT->resource) { - Debug::log(ERR, "ToplevelExportManager could not bind! (out of memory?)"); - m_lClients.remove(*PCLIENT); - wl_client_post_no_memory(client); - return; - } - - PCLIENT->ref = 1; - - wl_resource_set_implementation(PCLIENT->resource, &toplevelExportManagerImpl, PCLIENT, handleManagerResourceDestroy); - - Debug::log(LOG, "ToplevelExportManager bound successfully!"); -} - -static void handleFrameResourceDestroy(wl_resource* resource) { - const auto PFRAME = frameFromResource(resource); - - g_pProtocolManager->m_pToplevelExportProtocolManager->removeFrame(PFRAME); -} - -void CToplevelExportProtocolManager::removeFrame(SScreencopyFrame* frame, bool force) { - if (!frame) +CToplevelExportClient::CToplevelExportClient(SP resource_) : resource(resource_) { + if (!good()) return; - std::erase_if(m_vFramesAwaitingWrite, [&](const auto& other) { return other == frame; }); + resource->setOnDestroy([this](CHyprlandToplevelExportManagerV1* pMgr) { PROTO::toplevelExport->destroyResource(this); }); + resource->setDestroy([this](CHyprlandToplevelExportManagerV1* pMgr) { PROTO::toplevelExport->destroyResource(this); }); + resource->setCaptureToplevel([this](CHyprlandToplevelExportManagerV1* pMgr, uint32_t frame, int32_t overlayCursor, uint32_t handle) { + this->captureToplevel(pMgr, frame, overlayCursor, g_pCompositor->getWindowFromHandle(handle)); + }); + resource->setCaptureToplevelWithWlrToplevelHandle([this](CHyprlandToplevelExportManagerV1* pMgr, uint32_t frame, int32_t overlayCursor, wl_resource* handle) { + this->captureToplevel(pMgr, frame, overlayCursor, PROTO::foreignToplevelWlr->windowFromHandleResource(handle)); + }); - wl_resource_set_user_data(frame->resource, nullptr); - if (frame->buffer && frame->buffer->locked() > 0) - frame->buffer->unlock(); - removeClient(frame->client, force); - m_lFrames.remove(*frame); + lastMeasure.reset(); + lastFrame.reset(); + tickCallback = g_pHookSystem->hookDynamic("tick", [&](void* self, SCallbackInfo& info, std::any data) { onTick(); }); } -void CToplevelExportProtocolManager::captureToplevel(wl_client* client, wl_resource* resource, uint32_t frame, int32_t overlay_cursor, PHLWINDOW pWindow) { - const auto PCLIENT = clientFromResource(resource); - +void CToplevelExportClient::captureToplevel(CHyprlandToplevelExportManagerV1* pMgr, uint32_t frame, int32_t overlayCursor_, PHLWINDOW handle) { // create a frame - const auto PFRAME = &m_lFrames.emplace_back(); - PFRAME->overlayCursor = !!overlay_cursor; - PFRAME->resource = wl_resource_create(client, &hyprland_toplevel_export_frame_v1_interface, wl_resource_get_version(resource), frame); - PFRAME->pWindow = pWindow; + const auto FRAME = PROTO::toplevelExport->m_vFrames.emplace_back( + makeShared(makeShared(resource->client(), resource->version(), frame), overlayCursor_, handle)); + + if (!FRAME->good()) { + LOGM(ERR, "Couldn't alloc frame for sharing! (no memory)"); + resource->noMemory(); + PROTO::toplevelExport->destroyResource(FRAME.get()); + return; + } + + FRAME->self = FRAME; + FRAME->client = self; +} + +void CToplevelExportClient::onTick() { + if (lastMeasure.getMillis() < 500) + return; + + framesInLastHalfSecond = frameCounter; + frameCounter = 0; + lastMeasure.reset(); + + const auto LASTFRAMEDELTA = lastFrame.getMillis() / 1000.0; + const bool FRAMEAWAITING = std::ranges::any_of(PROTO::toplevelExport->m_vFrames, [&](const auto& frame) { return frame->client.get() == this; }); + + if (framesInLastHalfSecond > 3 && !sentScreencast) { + EMIT_HOOK_EVENT("screencast", (std::vector{1, (uint64_t)framesInLastHalfSecond, (uint64_t)clientOwner})); + g_pEventManager->postEvent(SHyprIPCEvent{"screencast", "1," + std::to_string(clientOwner)}); + sentScreencast = true; + } else if (framesInLastHalfSecond < 4 && sentScreencast && LASTFRAMEDELTA > 1.0 && !FRAMEAWAITING) { + EMIT_HOOK_EVENT("screencast", (std::vector{0, (uint64_t)framesInLastHalfSecond, (uint64_t)clientOwner})); + g_pEventManager->postEvent(SHyprIPCEvent{"screencast", "0," + std::to_string(clientOwner)}); + sentScreencast = false; + } +} + +bool CToplevelExportClient::good() { + return resource->resource(); +} + +CToplevelExportFrame::~CToplevelExportFrame() { + if (buffer && buffer->locked()) + buffer->unlock(); +} + +CToplevelExportFrame::CToplevelExportFrame(SP resource_, int32_t overlayCursor_, PHLWINDOW pWindow_) : resource(resource_), pWindow(pWindow_) { + if (!good()) + return; + + overlayCursor = !!overlayCursor_; if (!pWindow) { - Debug::log(ERR, "Client requested sharing of window handle {:x} which does not exist!", pWindow); - hyprland_toplevel_export_frame_v1_send_failed(PFRAME->resource); - removeFrame(PFRAME); + LOGM(ERR, "Client requested sharing of window handle {:x} which does not exist!", pWindow); + resource->sendFailed(); + PROTO::toplevelExport->destroyResource(this); return; } if (!pWindow->m_bIsMapped || pWindow->isHidden()) { - Debug::log(ERR, "Client requested sharing of window handle {:x} which is not shareable!", pWindow); - hyprland_toplevel_export_frame_v1_send_failed(PFRAME->resource); - removeFrame(PFRAME); + LOGM(ERR, "Client requested sharing of window handle {:x} which is not shareable!", pWindow); + resource->sendFailed(); + PROTO::toplevelExport->destroyResource(this); return; } - if (!PFRAME->resource) { - Debug::log(ERR, "Couldn't alloc frame for sharing! (no memory)"); - m_lFrames.remove(*PFRAME); - wl_client_post_no_memory(client); - return; - } - - wl_resource_set_implementation(PFRAME->resource, &toplevelFrameImpl, PFRAME, handleFrameResourceDestroy); - - PFRAME->client = PCLIENT; - PCLIENT->ref++; + resource->setOnDestroy([this](CHyprlandToplevelExportFrameV1* pFrame) { PROTO::toplevelExport->destroyResource(this); }); + resource->setDestroy([this](CHyprlandToplevelExportFrameV1* pFrame) { PROTO::toplevelExport->destroyResource(this); }); + resource->setCopy([this](CHyprlandToplevelExportFrameV1* pFrame, wl_resource* res, int32_t ignoreDamage) { this->copy(pFrame, res, ignoreDamage); }); const auto PMONITOR = g_pCompositor->getMonitorFromID(pWindow->m_iMonitorID); g_pHyprRenderer->makeEGLCurrent(); - PFRAME->shmFormat = g_pHyprOpenGL->getPreferredReadFormat(PMONITOR); - if (PFRAME->shmFormat == DRM_FORMAT_INVALID) { - Debug::log(ERR, "No format supported by renderer in capture toplevel"); - hyprland_toplevel_export_frame_v1_send_failed(resource); - removeFrame(PFRAME); + shmFormat = g_pHyprOpenGL->getPreferredReadFormat(PMONITOR); + if (shmFormat == DRM_FORMAT_INVALID) { + LOGM(ERR, "No format supported by renderer in capture toplevel"); + resource->sendFailed(); + PROTO::toplevelExport->destroyResource(this); return; } - const auto PSHMINFO = FormatUtils::getPixelFormatFromDRM(PFRAME->shmFormat); + const auto PSHMINFO = FormatUtils::getPixelFormatFromDRM(shmFormat); if (!PSHMINFO) { - Debug::log(ERR, "No pixel format supported by renderer in capture toplevel"); - hyprland_toplevel_export_frame_v1_send_failed(resource); - removeFrame(PFRAME); + LOGM(ERR, "No pixel format supported by renderer in capture toplevel"); + resource->sendFailed(); + PROTO::toplevelExport->destroyResource(this); return; } - PFRAME->dmabufFormat = PMONITOR->output->state->state().drmFormat; + dmabufFormat = PMONITOR->output->state->state().drmFormat; - PFRAME->box = {0, 0, (int)(pWindow->m_vRealSize.value().x * PMONITOR->scale), (int)(pWindow->m_vRealSize.value().y * PMONITOR->scale)}; + box = {0, 0, (int)(pWindow->m_vRealSize.value().x * PMONITOR->scale), (int)(pWindow->m_vRealSize.value().y * PMONITOR->scale)}; - PFRAME->box.transform(wlTransformToHyprutils(PMONITOR->transform), PMONITOR->vecTransformedSize.x, PMONITOR->vecTransformedSize.y).round(); + box.transform(wlTransformToHyprutils(PMONITOR->transform), PMONITOR->vecTransformedSize.x, PMONITOR->vecTransformedSize.y).round(); - PFRAME->shmStride = FormatUtils::minStride(PSHMINFO, PFRAME->box.w); + shmStride = FormatUtils::minStride(PSHMINFO, box.w); - hyprland_toplevel_export_frame_v1_send_buffer(PFRAME->resource, FormatUtils::drmToShm(PFRAME->shmFormat), PFRAME->box.width, PFRAME->box.height, PFRAME->shmStride); + resource->sendBuffer(FormatUtils::drmToShm(shmFormat), box.width, box.height, shmStride); - if (PFRAME->dmabufFormat != DRM_FORMAT_INVALID) { - hyprland_toplevel_export_frame_v1_send_linux_dmabuf(PFRAME->resource, PFRAME->dmabufFormat, PFRAME->box.width, PFRAME->box.height); + if (dmabufFormat != DRM_FORMAT_INVALID) { + resource->sendLinuxDmabuf(dmabufFormat, box.width, box.height); } - hyprland_toplevel_export_frame_v1_send_buffer_done(PFRAME->resource); + resource->sendBufferDone(); } -void CToplevelExportProtocolManager::copyFrame(wl_client* client, wl_resource* resource, wl_resource* buffer, int32_t ignore_damage) { - const auto PFRAME = frameFromResource(resource); - - if (!PFRAME) { - Debug::log(ERR, "No frame in copyFrame??"); +void CToplevelExportFrame::copy(CHyprlandToplevelExportFrameV1* pFrame, wl_resource* buffer_, int32_t ignoreDamage) { + if (!good()) { + LOGM(ERR, "No frame in copyFrame??"); return; } - const auto PWINDOW = PFRAME->pWindow.lock(); - - if (!validMapped(PWINDOW)) { - Debug::log(ERR, "Client requested sharing of window handle {:x} which is gone!", PWINDOW); - hyprland_toplevel_export_frame_v1_send_failed(PFRAME->resource); - removeFrame(PFRAME); + if (!validMapped(pWindow)) { + LOGM(ERR, "Client requested sharing of window handle {:x} which is gone!", pWindow); + resource->sendFailed(); + PROTO::toplevelExport->destroyResource(this); return; } - if (!PWINDOW->m_bIsMapped || PWINDOW->isHidden()) { - Debug::log(ERR, "Client requested sharing of window handle {:x} which is not shareable (2)!", PWINDOW); - hyprland_toplevel_export_frame_v1_send_failed(PFRAME->resource); - removeFrame(PFRAME); + if (!pWindow->m_bIsMapped || pWindow->isHidden()) { + LOGM(ERR, "Client requested sharing of window handle {:x} which is not shareable (2)!", pWindow); + resource->sendFailed(); + PROTO::toplevelExport->destroyResource(this); return; } - const auto PBUFFER = CWLBufferResource::fromResource(buffer); + const auto PBUFFER = CWLBufferResource::fromResource(buffer_); if (!PBUFFER) { - wl_resource_post_error(PFRAME->resource, HYPRLAND_TOPLEVEL_EXPORT_FRAME_V1_ERROR_INVALID_BUFFER, "invalid buffer"); - removeFrame(PFRAME); + resource->error(HYPRLAND_TOPLEVEL_EXPORT_FRAME_V1_ERROR_INVALID_BUFFER, "invalid buffer"); + PROTO::toplevelExport->destroyResource(this); return; } PBUFFER->buffer->lock(); - if (PBUFFER->buffer->size != PFRAME->box.size()) { - wl_resource_post_error(PFRAME->resource, HYPRLAND_TOPLEVEL_EXPORT_FRAME_V1_ERROR_INVALID_BUFFER, "invalid buffer dimensions"); - removeFrame(PFRAME); + if (PBUFFER->buffer->size != box.size()) { + resource->error(HYPRLAND_TOPLEVEL_EXPORT_FRAME_V1_ERROR_INVALID_BUFFER, "invalid buffer dimensions"); + PROTO::toplevelExport->destroyResource(this); return; } - if (PFRAME->buffer) { - wl_resource_post_error(PFRAME->resource, HYPRLAND_TOPLEVEL_EXPORT_FRAME_V1_ERROR_ALREADY_USED, "frame already used"); - removeFrame(PFRAME); + if (buffer) { + resource->error(HYPRLAND_TOPLEVEL_EXPORT_FRAME_V1_ERROR_ALREADY_USED, "frame already used"); + PROTO::toplevelExport->destroyResource(this); return; } if (auto attrs = PBUFFER->buffer->dmabuf(); attrs.success) { - PFRAME->bufferDMA = true; + bufferDMA = true; - if (attrs.format != PFRAME->dmabufFormat) { - wl_resource_post_error(PFRAME->resource, HYPRLAND_TOPLEVEL_EXPORT_FRAME_V1_ERROR_INVALID_BUFFER, "invalid buffer format"); - removeFrame(PFRAME); + if (attrs.format != dmabufFormat) { + resource->error(HYPRLAND_TOPLEVEL_EXPORT_FRAME_V1_ERROR_INVALID_BUFFER, "invalid buffer format"); + PROTO::toplevelExport->destroyResource(this); return; } } else if (auto attrs = PBUFFER->buffer->shm(); attrs.success) { - if (attrs.format != PFRAME->shmFormat) { - wl_resource_post_error(PFRAME->resource, HYPRLAND_TOPLEVEL_EXPORT_FRAME_V1_ERROR_INVALID_BUFFER, "invalid buffer format"); - removeFrame(PFRAME); + if (attrs.format != shmFormat) { + resource->error(HYPRLAND_TOPLEVEL_EXPORT_FRAME_V1_ERROR_INVALID_BUFFER, "invalid buffer format"); + PROTO::toplevelExport->destroyResource(this); return; - } else if ((int)attrs.stride != PFRAME->shmStride) { - wl_resource_post_error(PFRAME->resource, HYPRLAND_TOPLEVEL_EXPORT_FRAME_V1_ERROR_INVALID_BUFFER, "invalid buffer stride"); - removeFrame(PFRAME); + } else if ((int)attrs.stride != shmStride) { + resource->error(HYPRLAND_TOPLEVEL_EXPORT_FRAME_V1_ERROR_INVALID_BUFFER, "invalid buffer stride"); + PROTO::toplevelExport->destroyResource(this); return; } } else { - wl_resource_post_error(PFRAME->resource, HYPRLAND_TOPLEVEL_EXPORT_FRAME_V1_ERROR_INVALID_BUFFER, "invalid buffer type"); - removeFrame(PFRAME); + resource->error(HYPRLAND_TOPLEVEL_EXPORT_FRAME_V1_ERROR_INVALID_BUFFER, "invalid buffer type"); + PROTO::toplevelExport->destroyResource(this); return; } - PFRAME->buffer = PBUFFER->buffer; + buffer = PBUFFER->buffer; - m_vFramesAwaitingWrite.emplace_back(PFRAME); + PROTO::toplevelExport->m_vFramesAwaitingWrite.emplace_back(self); } -void CToplevelExportProtocolManager::onOutputCommit(CMonitor* pMonitor) { - if (m_vFramesAwaitingWrite.empty()) - return; // nothing to share - - std::vector framesToRemove; - - // share frame if correct output - for (auto& f : m_vFramesAwaitingWrite) { - const auto PWINDOW = f->pWindow.lock(); - - if (!validMapped(PWINDOW)) { - framesToRemove.push_back(f); - continue; - } - - if (pMonitor != g_pCompositor->getMonitorFromID(PWINDOW->m_iMonitorID)) - continue; - - CBox geometry = {PWINDOW->m_vRealPosition.value().x, PWINDOW->m_vRealPosition.value().y, PWINDOW->m_vRealSize.value().x, PWINDOW->m_vRealSize.value().y}; - - if (geometry.intersection({pMonitor->vecPosition, pMonitor->vecSize}).empty()) - continue; - - shareFrame(f); - - f->client->lastFrame.reset(); - ++f->client->frameCounter; - - framesToRemove.push_back(f); - } - - for (auto& f : framesToRemove) { - removeFrame(f); - } -} - -void CToplevelExportProtocolManager::shareFrame(SScreencopyFrame* frame) { - if (!frame->buffer || !validMapped(frame->pWindow)) +void CToplevelExportFrame::share() { + if (!buffer || !validMapped(pWindow)) return; timespec now; clock_gettime(CLOCK_MONOTONIC, &now); - uint32_t flags = 0; - if (frame->bufferDMA) { - if (!copyFrameDmabuf(frame, &now)) { - hyprland_toplevel_export_frame_v1_send_failed(frame->resource); + if (bufferDMA) { + if (!copyDmabuf(&now)) { + resource->sendFailed(); return; } } else { - if (!copyFrameShm(frame, &now)) { - hyprland_toplevel_export_frame_v1_send_failed(frame->resource); + if (!copyShm(&now)) { + resource->sendFailed(); return; } } - hyprland_toplevel_export_frame_v1_send_flags(frame->resource, flags); - sendDamage(frame); + resource->sendFlags((hyprlandToplevelExportFrameV1Flags)0); + + if (!ignoreDamage) { + resource->sendDamage(0, 0, box.width, box.height); + } + uint32_t tvSecHi = (sizeof(now.tv_sec) > 4) ? now.tv_sec >> 32 : 0; uint32_t tvSecLo = now.tv_sec & 0xFFFFFFFF; - hyprland_toplevel_export_frame_v1_send_ready(frame->resource, tvSecHi, tvSecLo, now.tv_nsec); + resource->sendReady(tvSecHi, tvSecLo, now.tv_nsec); } -void CToplevelExportProtocolManager::sendDamage(SScreencopyFrame* frame) { - // TODO: send proper dmg - hyprland_toplevel_export_frame_v1_send_damage(frame->resource, 0, 0, frame->box.width, frame->box.height); -} - -bool CToplevelExportProtocolManager::copyFrameShm(SScreencopyFrame* frame, timespec* now) { - auto shm = frame->buffer->shm(); - auto [pixelData, fmt, bufLen] = frame->buffer->beginDataPtr(0); // no need for end, cuz it's shm +bool CToplevelExportFrame::copyShm(timespec* now) { + auto shm = buffer->shm(); + auto [pixelData, fmt, bufLen] = buffer->beginDataPtr(0); // no need for end, cuz it's shm // render the client - const auto PMONITOR = g_pCompositor->getMonitorFromID(frame->pWindow->m_iMonitorID); + const auto PMONITOR = g_pCompositor->getMonitorFromID(pWindow->m_iMonitorID); CRegion fakeDamage{0, 0, PMONITOR->vecPixelSize.x * 10, PMONITOR->vecPixelSize.y * 10}; g_pHyprRenderer->makeEGLCurrent(); @@ -372,7 +249,7 @@ bool CToplevelExportProtocolManager::copyFrameShm(SScreencopyFrame* frame, times CFramebuffer outFB; outFB.alloc(PMONITOR->vecPixelSize.x, PMONITOR->vecPixelSize.y, g_pHyprRenderer->isNvidia() ? DRM_FORMAT_XBGR8888 : PMONITOR->output->state->state().drmFormat); - if (frame->overlayCursor) { + if (overlayCursor) { g_pPointerManager->lockSoftwareForMonitor(PMONITOR->self.lock()); g_pPointerManager->damageCursor(PMONITOR->self.lock()); } @@ -383,12 +260,12 @@ bool CToplevelExportProtocolManager::copyFrameShm(SScreencopyFrame* frame, times g_pHyprOpenGL->clear(CColor(0, 0, 0, 1.0)); // render client at 0,0 - g_pHyprRenderer->m_bBlockSurfaceFeedback = g_pHyprRenderer->shouldRenderWindow(frame->pWindow.lock()); // block the feedback to avoid spamming the surface if it's visible - g_pHyprRenderer->renderWindow(frame->pWindow.lock(), PMONITOR, now, false, RENDER_PASS_ALL, true, true); + g_pHyprRenderer->m_bBlockSurfaceFeedback = g_pHyprRenderer->shouldRenderWindow(pWindow); // block the feedback to avoid spamming the surface if it's visible + g_pHyprRenderer->renderWindow(pWindow, PMONITOR, now, false, RENDER_PASS_ALL, true, true); g_pHyprRenderer->m_bBlockSurfaceFeedback = false; - if (frame->overlayCursor) - g_pPointerManager->renderSoftwareCursorsFor(PMONITOR->self.lock(), now, fakeDamage, g_pInputManager->getMouseCoordsInternal() - frame->pWindow->m_vRealPosition.value()); + if (overlayCursor) + g_pPointerManager->renderSoftwareCursorsFor(PMONITOR->self.lock(), now, fakeDamage, g_pInputManager->getMouseCoordsInternal() - pWindow->m_vRealPosition.value()); const auto PFORMAT = FormatUtils::getPixelFormatFromDRM(shm.format); if (!PFORMAT) { @@ -410,9 +287,9 @@ bool CToplevelExportProtocolManager::copyFrameShm(SScreencopyFrame* frame, times glPixelStorei(GL_PACK_ALIGNMENT, 1); auto glFormat = PFORMAT->flipRB ? GL_BGRA_EXT : GL_RGBA; - glReadPixels(0, 0, frame->box.width, frame->box.height, glFormat, PFORMAT->glType, pixelData); + glReadPixels(0, 0, box.width, box.height, glFormat, PFORMAT->glType, pixelData); - if (frame->overlayCursor) { + if (overlayCursor) { g_pPointerManager->unlockSoftwareForMonitor(PMONITOR->self.lock()); g_pPointerManager->damageCursor(PMONITOR->self.lock()); } @@ -420,31 +297,112 @@ bool CToplevelExportProtocolManager::copyFrameShm(SScreencopyFrame* frame, times return true; } -bool CToplevelExportProtocolManager::copyFrameDmabuf(SScreencopyFrame* frame, timespec* now) { - const auto PMONITOR = g_pCompositor->getMonitorFromID(frame->pWindow->m_iMonitorID); +bool CToplevelExportFrame::copyDmabuf(timespec* now) { + const auto PMONITOR = g_pCompositor->getMonitorFromID(pWindow->m_iMonitorID); CRegion fakeDamage{0, 0, INT16_MAX, INT16_MAX}; - if (!g_pHyprRenderer->beginRender(PMONITOR, fakeDamage, RENDER_MODE_TO_BUFFER, frame->buffer.lock())) + if (overlayCursor) { + g_pPointerManager->lockSoftwareForMonitor(PMONITOR->self.lock()); + g_pPointerManager->damageCursor(PMONITOR->self.lock()); + } + + if (!g_pHyprRenderer->beginRender(PMONITOR, fakeDamage, RENDER_MODE_TO_BUFFER, buffer.lock())) return false; g_pHyprOpenGL->clear(CColor(0, 0, 0, 1.0)); - g_pHyprRenderer->m_bBlockSurfaceFeedback = g_pHyprRenderer->shouldRenderWindow(frame->pWindow.lock()); // block the feedback to avoid spamming the surface if it's visible - g_pHyprRenderer->renderWindow(frame->pWindow.lock(), PMONITOR, now, false, RENDER_PASS_ALL, true, true); + g_pHyprRenderer->m_bBlockSurfaceFeedback = g_pHyprRenderer->shouldRenderWindow(pWindow); // block the feedback to avoid spamming the surface if it's visible + g_pHyprRenderer->renderWindow(pWindow, PMONITOR, now, false, RENDER_PASS_ALL, true, true); g_pHyprRenderer->m_bBlockSurfaceFeedback = false; - if (frame->overlayCursor) - g_pPointerManager->renderSoftwareCursorsFor(PMONITOR->self.lock(), now, fakeDamage, g_pInputManager->getMouseCoordsInternal() - frame->pWindow->m_vRealPosition.value()); + if (overlayCursor) + g_pPointerManager->renderSoftwareCursorsFor(PMONITOR->self.lock(), now, fakeDamage, g_pInputManager->getMouseCoordsInternal() - pWindow->m_vRealPosition.value()); g_pHyprOpenGL->m_RenderData.blockScreenShader = true; g_pHyprRenderer->endRender(); + + if (overlayCursor) { + g_pPointerManager->unlockSoftwareForMonitor(PMONITOR->self.lock()); + g_pPointerManager->damageCursor(PMONITOR->self.lock()); + } + return true; } -void CToplevelExportProtocolManager::onWindowUnmap(PHLWINDOW pWindow) { - for (auto& f : m_lFrames) { - if (f.pWindow.lock() == pWindow) - f.pWindow.reset(); +bool CToplevelExportFrame::good() { + return resource->resource(); +} + +CToplevelExportProtocol::CToplevelExportProtocol(const wl_interface* iface, const int& ver, const std::string& name) : IWaylandProtocol(iface, ver, name) { + ; +} + +void CToplevelExportProtocol::bindManager(wl_client* client, void* data, uint32_t ver, uint32_t id) { + const auto CLIENT = m_vClients.emplace_back(makeShared(makeShared(client, ver, id))); + + if (!CLIENT->good()) { + LOGM(LOG, "Failed to bind client! (out of memory)"); + wl_client_post_no_memory(client); + m_vClients.pop_back(); + return; + } + + CLIENT->self = CLIENT; + + LOGM(LOG, "Bound client successfully!"); +} + +void CToplevelExportProtocol::destroyResource(CToplevelExportClient* client) { + std::erase_if(m_vClients, [&](const auto& other) { return other.get() == client; }); + std::erase_if(m_vFrames, [&](const auto& other) { return other->client.get() == client; }); + std::erase_if(m_vFramesAwaitingWrite, [&](const auto& other) { return other->client.get() == client; }); +} + +void CToplevelExportProtocol::destroyResource(CToplevelExportFrame* frame) { + std::erase_if(m_vFrames, [&](const auto& other) { return other.get() == frame; }); + std::erase_if(m_vFramesAwaitingWrite, [&](const auto& other) { return other.get() == frame; }); +} + +void CToplevelExportProtocol::onOutputCommit(CMonitor* pMonitor) { + if (m_vFramesAwaitingWrite.empty()) + return; // nothing to share + + std::vector> framesToRemove; + + // share frame if correct output + for (auto& f : m_vFramesAwaitingWrite) { + if (!f->pWindow || !validMapped(f->pWindow)) { + framesToRemove.push_back(f); + continue; + } + + const auto PWINDOW = f->pWindow; + + if (pMonitor != g_pCompositor->getMonitorFromID(PWINDOW->m_iMonitorID)) + continue; + + CBox geometry = {PWINDOW->m_vRealPosition.value().x, PWINDOW->m_vRealPosition.value().y, PWINDOW->m_vRealSize.value().x, PWINDOW->m_vRealSize.value().y}; + + if (geometry.intersection({pMonitor->vecPosition, pMonitor->vecSize}).empty()) + continue; + + f->share(); + + f->client->lastFrame.reset(); + ++f->client->frameCounter; + + framesToRemove.push_back(f); + } + + for (auto& f : framesToRemove) { + destroyResource(f.get()); + } +} + +void CToplevelExportProtocol::onWindowUnmap(PHLWINDOW pWindow) { + for (auto& f : m_vFrames) { + if (f->pWindow == pWindow) + f->pWindow.reset(); } } diff --git a/src/protocols/ToplevelExport.hpp b/src/protocols/ToplevelExport.hpp index 71a6df18..638b69f0 100644 --- a/src/protocols/ToplevelExport.hpp +++ b/src/protocols/ToplevelExport.hpp @@ -1,7 +1,8 @@ #pragma once #include "../defines.hpp" -#include "hyprland-toplevel-export-v1-protocol.h" +#include "hyprland-toplevel-export-v1.hpp" +#include "WaylandProtocol.hpp" #include "Screencopy.hpp" #include @@ -10,33 +11,91 @@ class CMonitor; class CWindow; -class CToplevelExportProtocolManager { +class CToplevelExportClient { public: - CToplevelExportProtocolManager(); - ~CToplevelExportProtocolManager(); + CToplevelExportClient(SP resource_); - void bindManager(wl_client* client, void* data, uint32_t version, uint32_t id); - void captureToplevel(wl_client* client, wl_resource* resource, uint32_t frame, int32_t overlay_cursor, PHLWINDOW handle); - void removeClient(CScreencopyClient* client, bool force = false); - void removeFrame(SScreencopyFrame* frame, bool force = false); - void copyFrame(wl_client* client, wl_resource* resource, wl_resource* buffer, int32_t ignore_damage); - void displayDestroy(); - void onWindowUnmap(PHLWINDOW pWindow); - void onOutputCommit(CMonitor* pMonitor); + bool good(); - wl_listener m_liDisplayDestroy; + WP self; + eClientOwners clientOwner = CLIENT_TOPLEVEL_EXPORT; + + CTimer lastFrame; + int frameCounter = 0; private: - wl_global* m_pGlobal = nullptr; - std::list m_lFrames; - std::list m_lClients; + SP resource; - std::vector m_vFramesAwaitingWrite; + int framesInLastHalfSecond = 0; + CTimer lastMeasure; + bool sentScreencast = false; - void shareFrame(SScreencopyFrame* frame); - bool copyFrameDmabuf(SScreencopyFrame* frame, timespec* now); - bool copyFrameShm(SScreencopyFrame* frame, timespec* now); - void sendDamage(SScreencopyFrame* frame); + SP tickCallback; + void onTick(); - friend class CScreencopyClient; + void captureToplevel(CHyprlandToplevelExportManagerV1* pMgr, uint32_t frame, int32_t overlayCursor, PHLWINDOW handle); + + friend class CToplevelExportProtocol; +}; + +class CToplevelExportFrame { + public: + CToplevelExportFrame(SP resource_, int32_t overlayCursor, PHLWINDOW pWindow); + ~CToplevelExportFrame(); + + bool good(); + + SP self; + WP client; + + private: + SP resource; + + PHLWINDOW pWindow; + bool overlayCursor = false; + bool ignoreDamage = false; + bool lockedSWCursors = false; + + WP buffer; + bool bufferDMA = false; + uint32_t shmFormat = 0; + uint32_t dmabufFormat = 0; + int shmStride = 0; + CBox box = {}; + + void copy(CHyprlandToplevelExportFrameV1* pFrame, wl_resource* buffer, int32_t ignoreDamage); + bool copyDmabuf(timespec* now); + bool copyShm(timespec* now); + void share(); + + friend class CToplevelExportProtocol; +}; + +class CToplevelExportProtocol : IWaylandProtocol { + public: + CToplevelExportProtocol(const wl_interface* iface, const int& ver, const std::string& name); + + void bindManager(wl_client* client, void* data, uint32_t ver, uint32_t id); + void destroyResource(CToplevelExportClient* client); + void destroyResource(CToplevelExportFrame* frame); + + void onWindowUnmap(PHLWINDOW pWindow); + void onOutputCommit(CMonitor* pMonitor); + + private: + std::vector> m_vClients; + std::vector> m_vFrames; + std::vector> m_vFramesAwaitingWrite; + + void shareFrame(CToplevelExportFrame* frame); + bool copyFrameDmabuf(CToplevelExportFrame* frame, timespec* now); + bool copyFrameShm(CToplevelExportFrame* frame, timespec* now); + void sendDamage(CToplevelExportFrame* frame); + + friend class CToplevelExportClient; + friend class CToplevelExportFrame; +}; + +namespace PROTO { + inline UP toplevelExport; }; diff --git a/src/render/Renderer.hpp b/src/render/Renderer.hpp index 72efe8c4..a9397cac 100644 --- a/src/render/Renderer.hpp +++ b/src/render/Renderer.hpp @@ -139,7 +139,7 @@ class CHyprRenderer { std::vector> m_vRenderbuffers; friend class CHyprOpenGLImpl; - friend class CToplevelExportProtocolManager; + friend class CToplevelExportFrame; friend class CInputManager; friend class CPointerManager; }; From daed75219fa7b4ec345337ec99f816e94bda338c Mon Sep 17 00:00:00 2001 From: vaxerski Date: Sat, 27 Jul 2024 17:03:49 +0200 Subject: [PATCH 0173/2181] wayland/compositor: fixup double buffer releases fixes #7043 --- src/protocols/core/Compositor.cpp | 19 ++++++++----------- src/protocols/core/Compositor.hpp | 3 --- src/protocols/types/WLBuffer.cpp | 1 + src/protocols/types/WLBuffer.hpp | 2 ++ 4 files changed, 11 insertions(+), 14 deletions(-) diff --git a/src/protocols/core/Compositor.cpp b/src/protocols/core/Compositor.cpp index a31b1fb4..76907cc2 100644 --- a/src/protocols/core/Compositor.cpp +++ b/src/protocols/core/Compositor.cpp @@ -79,6 +79,8 @@ CWLSurfaceResource::CWLSurfaceResource(SP resource_) : resource(reso pending.buffer = res && res->buffer ? res->buffer.lock() : nullptr; pending.size = res && res->buffer ? res->buffer->size : Vector2D{}; pending.texture = res && res->buffer ? res->buffer->texture : nullptr; + if (res) + res->released = false; } Vector2D oldBufSize = current.buffer ? current.buffer->size : Vector2D{}; @@ -86,8 +88,6 @@ CWLSurfaceResource::CWLSurfaceResource(SP resource_) : resource(reso if (oldBufSize != newBufSize || current.buffer != pending.buffer) pending.bufferDamage = CBox{{}, {INT32_MAX, INT32_MAX}}; - - bufferReleased = false; }); resource->setCommit([this](CWlSurface* r) { @@ -340,9 +340,9 @@ void CWLSurfaceResource::unmap() { // release the buffers. // this is necessary for XWayland to function correctly, // as it does not unmap via the traditional commit(null buffer) method, but via the X11 protocol. - if (!bufferReleased && current.buffer) + if (current.buffer && !current.buffer->resource->released) current.buffer->sendRelease(); - if (pending.buffer) + if (pending.buffer && !pending.buffer->resource->released) pending.buffer->sendRelease(); pending.buffer.reset(); @@ -420,15 +420,13 @@ void CWLSurfaceResource::commitPendingState() { if (current.buffer && current.buffer->texture) current.buffer->texture->m_eTransform = wlTransformToHyprutils(current.transform); - if (current.buffer && !bufferReleased) { + if (current.buffer && !current.buffer->resource->released) { current.buffer->update(accumulateCurrentBufferDamage()); // release the buffer if it's synchronous as update() has done everything thats needed // so we can let the app know we're done. - if (current.buffer->isSynchronous()) { + if (current.buffer->isSynchronous()) current.buffer->sendReleaseWithSurface(self.lock()); - bufferReleased = true; - } } // TODO: we should _accumulate_ and not replace above if sync @@ -453,7 +451,7 @@ void CWLSurfaceResource::commitPendingState() { } // for async buffers, we can only release the buffer once we are unrefing it from current. - if (previousBuffer && !previousBuffer->isSynchronous() && !bufferReleased) { + if (previousBuffer && !previousBuffer->isSynchronous() && !previousBuffer->resource->released) { if (previousBuffer->lockedByBackend) { previousBuffer->hlEvents.backendRelease = previousBuffer->events.backendRelease.registerListener([this, previousBuffer](std::any data) { if (!self.expired()) // could be dead in the dtor @@ -461,12 +459,11 @@ void CWLSurfaceResource::commitPendingState() { else previousBuffer->sendRelease(); previousBuffer->hlEvents.backendRelease.reset(); - bufferReleased = true; }); } else previousBuffer->sendReleaseWithSurface(self.lock()); - bufferReleased = true; + previousBuffer->resource->released = true; // set it here regardless so we dont set more listeners for backendRelease } } diff --git a/src/protocols/core/Compositor.hpp b/src/protocols/core/Compositor.hpp index 5e6413c8..85bd0d37 100644 --- a/src/protocols/core/Compositor.hpp +++ b/src/protocols/core/Compositor.hpp @@ -134,9 +134,6 @@ class CWLSurfaceResource { SP resource; wl_client* pClient = nullptr; - // tracks whether we should release the buffer - bool bufferReleased = false; - int stateLocks = 0; void destroy(); diff --git a/src/protocols/types/WLBuffer.cpp b/src/protocols/types/WLBuffer.cpp index d34a867d..e42094b1 100644 --- a/src/protocols/types/WLBuffer.cpp +++ b/src/protocols/types/WLBuffer.cpp @@ -29,6 +29,7 @@ bool CWLBufferResource::good() { } void CWLBufferResource::sendRelease() { + released = true; resource->sendRelease(); } diff --git a/src/protocols/types/WLBuffer.hpp b/src/protocols/types/WLBuffer.hpp index 59512128..f4424abc 100644 --- a/src/protocols/types/WLBuffer.hpp +++ b/src/protocols/types/WLBuffer.hpp @@ -24,6 +24,8 @@ class CWLBufferResource { WP self; + bool released = false; + private: CWLBufferResource(SP resource_); From 84227eb587688596b63a5b48848d32083d9680cf Mon Sep 17 00:00:00 2001 From: MahouShoujoMivutilde <14999778+MahouShoujoMivutilde@users.noreply.github.com> Date: Sat, 27 Jul 2024 18:43:45 +0300 Subject: [PATCH 0174/2181] input: Fix `hyprctl switchxkblayout` not actually changing layout (#7070) Emits `SModifiersEvent` in `updateModifiers()` Before the patch: Changing layout with `hyprctl switchxkblayout ...` results in: * active keymap in `hyprctl devices` is changed * no event * no layout is actually changed UNTIL you press one of the mod keys (Alt | Shift | Super | Ctrl) After: * active keymap in `hyprctl devices` changed * activelayout IPC event emitted * layout is changed This fixes https://github.com/hyprwm/Hyprland/issues/7044 --- src/devices/IKeyboard.cpp | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/src/devices/IKeyboard.cpp b/src/devices/IKeyboard.cpp index 09a18477..e3517bf1 100644 --- a/src/devices/IKeyboard.cpp +++ b/src/devices/IKeyboard.cpp @@ -325,6 +325,13 @@ void IKeyboard::updateModifiers(uint32_t depressed, uint32_t latched, uint32_t l if (!updateModifiersState()) return; + keyboardEvents.modifiers.emit(SModifiersEvent{ + .depressed = modifiersState.depressed, + .latched = modifiersState.latched, + .locked = modifiersState.locked, + .group = modifiersState.group, + }); + updateLEDs(); } From 729b47d46d0c749efbffe01ea863a124fad562b4 Mon Sep 17 00:00:00 2001 From: vaxerski Date: Sat, 27 Jul 2024 17:49:27 +0200 Subject: [PATCH 0175/2181] input: refocus last window on keyboard unfocusable surfaces fixes #4460 --- src/managers/input/InputManager.cpp | 7 +++++++ src/protocols/core/Compositor.hpp | 8 ++++---- 2 files changed, 11 insertions(+), 4 deletions(-) diff --git a/src/managers/input/InputManager.cpp b/src/managers/input/InputManager.cpp index e2c62367..7d2e7a0e 100644 --- a/src/managers/input/InputManager.cpp +++ b/src/managers/input/InputManager.cpp @@ -17,6 +17,7 @@ #include "../../protocols/LayerShell.hpp" #include "../../protocols/core/Seat.hpp" #include "../../protocols/core/DataDevice.hpp" +#include "../../protocols/core/Compositor.hpp" #include "../../protocols/XDGShell.hpp" #include "../../devices/Mouse.hpp" @@ -1382,6 +1383,12 @@ void CInputManager::refocusLastWindow(CMonitor* pMonitor) { g_pCompositor->focusWindow(PLASTWINDOW); } else { // otherwise fall back to a normal refocus. + + if (foundSurface && !foundSurface->hlSurface->keyboardFocusable()) { + const auto PLASTWINDOW = g_pCompositor->m_pLastWindow.lock(); + g_pCompositor->focusWindow(PLASTWINDOW); + } + refocus(); } } diff --git a/src/protocols/core/Compositor.hpp b/src/protocols/core/Compositor.hpp index 85bd0d37..1fa6926a 100644 --- a/src/protocols/core/Compositor.hpp +++ b/src/protocols/core/Compositor.hpp @@ -134,11 +134,11 @@ class CWLSurfaceResource { SP resource; wl_client* pClient = nullptr; - int stateLocks = 0; + int stateLocks = 0; - void destroy(); - void commitPendingState(); - void bfHelper(std::vector> nodes, std::function, const Vector2D&, void*)> fn, void* data); + void destroy(); + void commitPendingState(); + void bfHelper(std::vector> nodes, std::function, const Vector2D&, void*)> fn, void* data); }; class CWLCompositorResource { From 024327154425c76a2932d644d76990a00b5fcdac Mon Sep 17 00:00:00 2001 From: vaxerski Date: Sat, 27 Jul 2024 18:08:22 +0200 Subject: [PATCH 0176/2181] layer-shell: properly map and unmap surface and propagate unmap events --- src/desktop/LayerSurface.cpp | 4 ++++ src/protocols/LayerShell.cpp | 2 ++ src/protocols/LayerShell.hpp | 1 + 3 files changed, 7 insertions(+) diff --git a/src/desktop/LayerSurface.cpp b/src/desktop/LayerSurface.cpp index 2252adca..f3db4b61 100644 --- a/src/desktop/LayerSurface.cpp +++ b/src/desktop/LayerSurface.cpp @@ -119,6 +119,8 @@ void CLayerSurface::onMap() { mapped = true; interactivity = layerSurface->current.interactivity; + layerSurface->surface->map(); + // this layer might be re-mapped. fadingOut = false; g_pCompositor->removeFromFadingOutSafe(self.lock()); @@ -190,6 +192,7 @@ void CLayerSurface::onUnmap() { g_pCompositor->addToFadingOutSafe(self.lock()); mapped = false; + layerSurface->surface->unmap(); startAnimation(false); return; @@ -201,6 +204,7 @@ void CLayerSurface::onUnmap() { startAnimation(false); mapped = false; + layerSurface->surface->unmap(); g_pCompositor->addToFadingOutSafe(self.lock()); diff --git a/src/protocols/LayerShell.cpp b/src/protocols/LayerShell.cpp index 4e733b35..e018c3d0 100644 --- a/src/protocols/LayerShell.cpp +++ b/src/protocols/LayerShell.cpp @@ -38,6 +38,8 @@ CLayerShellResource::CLayerShellResource(SP resource_, SPdestroyResource(this); }); + listeners.unmapSurface = surf_->events.unmap.registerListener([this](std::any d) { events.unmap.emit(); }); + listeners.commitSurface = surf_->events.commit.registerListener([this](std::any d) { current = pending; pending.committed = 0; diff --git a/src/protocols/LayerShell.hpp b/src/protocols/LayerShell.hpp index 221d95c0..ee0b7859 100644 --- a/src/protocols/LayerShell.hpp +++ b/src/protocols/LayerShell.hpp @@ -70,6 +70,7 @@ class CLayerShellResource : public ISurfaceRole { struct { CHyprSignalListener commitSurface; CHyprSignalListener destroySurface; + CHyprSignalListener unmapSurface; } listeners; bool closed = false; From 141cd09bd3315aedc075d451fd120a9504886ec1 Mon Sep 17 00:00:00 2001 From: vaxerski Date: Sat, 27 Jul 2024 18:13:41 +0200 Subject: [PATCH 0177/2181] renderer: use session lock alpha for rendering lacking locks --- src/render/Renderer.cpp | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/render/Renderer.cpp b/src/render/Renderer.cpp index d8de7ba8..0bf4c9f3 100644 --- a/src/render/Renderer.cpp +++ b/src/render/Renderer.cpp @@ -824,8 +824,9 @@ void CHyprRenderer::renderAllClientsForWorkspace(CMonitor* pMonitor, PHLWORKSPAC if (g_pSessionLockManager->isSessionLocked() && !g_pSessionLockManager->isSessionLockPresent()) { // locked with no exclusive, draw only red - CBox boxe = {0, 0, INT16_MAX, INT16_MAX}; - g_pHyprOpenGL->renderRect(&boxe, CColor(1.0, 0.2, 0.2, 1.0)); + CBox boxe = {0, 0, INT16_MAX, INT16_MAX}; + const float A = g_pSessionLockManager->getRedScreenAlphaForMonitor(pMonitor->ID); + g_pHyprOpenGL->renderRect(&boxe, CColor(1.0, 0.2, 0.2, A)); return; } From ae638d997d45e6183adafc6942b1b8fcc70f8928 Mon Sep 17 00:00:00 2001 From: vaxerski Date: Sat, 27 Jul 2024 18:15:47 +0200 Subject: [PATCH 0178/2181] configmgr: fix warning --- src/config/ConfigManager.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/config/ConfigManager.cpp b/src/config/ConfigManager.cpp index 657d7aff..65eab579 100644 --- a/src/config/ConfigManager.cpp +++ b/src/config/ConfigManager.cpp @@ -642,7 +642,7 @@ std::optional CConfigManager::generateConfig(std::string configPath Debug::log(WARN, "Creating config home directory"); try { std::filesystem::create_directories(parentPath); - } catch (std::exception e) { throw e; } + } catch (std::exception& e) { throw e; } } Debug::log(WARN, "No config file found; attempting to generate."); From ad711ef421fea4cfe03661ebebd465d070925437 Mon Sep 17 00:00:00 2001 From: MightyPlaza <123664421+MightyPlaza@users.noreply.github.com> Date: Sat, 27 Jul 2024 16:46:19 +0000 Subject: [PATCH 0179/2181] input: unify removing currentlyDraggedWindow (#7071) modified: src/desktop/Window.cpp modified: src/events/Windows.cpp modified: src/layout/IHyprLayout.cpp modified: src/managers/KeybindManager.cpp modified: src/managers/KeybindManager.hpp modified: src/managers/input/InputManager.cpp --- src/desktop/Window.cpp | 8 +-- src/events/Windows.cpp | 3 + src/layout/IHyprLayout.cpp | 13 ++-- src/managers/KeybindManager.cpp | 108 ++++++++++++---------------- src/managers/KeybindManager.hpp | 3 +- src/managers/input/InputManager.cpp | 2 +- 6 files changed, 58 insertions(+), 79 deletions(-) diff --git a/src/desktop/Window.cpp b/src/desktop/Window.cpp index 7497957a..f635d367 100644 --- a/src/desktop/Window.cpp +++ b/src/desktop/Window.cpp @@ -477,13 +477,7 @@ void unregisterVar(void* ptr) { void CWindow::onUnmap() { static auto PCLOSEONLASTSPECIAL = CConfigValue("misc:close_special_on_empty"); - - if (g_pCompositor->m_pLastWindow.lock().get() == this) - g_pCompositor->m_pLastWindow.reset(); - if (g_pInputManager->currentlyDraggedWindow.lock().get() == this) - g_pInputManager->currentlyDraggedWindow.reset(); - - static auto PINITIALWSTRACKING = CConfigValue("misc:initial_workspace_tracking"); + static auto PINITIALWSTRACKING = CConfigValue("misc:initial_workspace_tracking"); if (!m_szInitialWorkspaceToken.empty()) { const auto TOKEN = g_pTokenManager->getToken(m_szInitialWorkspaceToken); diff --git a/src/events/Windows.cpp b/src/events/Windows.cpp index 0e1037b6..b2abb65c 100644 --- a/src/events/Windows.cpp +++ b/src/events/Windows.cpp @@ -627,6 +627,9 @@ void Events::listener_unmapWindow(void* owner, void* data) { g_pInputManager->releaseAllMouseButtons(); } + if (PWINDOW == g_pInputManager->currentlyDraggedWindow.lock()) + g_pKeybindManager->changeMouseBindMode(MBIND_INVALID); + // remove the fullscreen window status from workspace if we closed it const auto PWORKSPACE = PWINDOW->m_pWorkspace; diff --git a/src/layout/IHyprLayout.cpp b/src/layout/IHyprLayout.cpp index 528cea72..0738b71c 100644 --- a/src/layout/IHyprLayout.cpp +++ b/src/layout/IHyprLayout.cpp @@ -187,7 +187,7 @@ void IHyprLayout::onBeginDragWindow() { // Window will be floating. Let's check if it's valid. It should be, but I don't like crashing. if (!validMapped(DRAGGINGWINDOW)) { Debug::log(ERR, "Dragging attempted on an invalid window!"); - g_pInputManager->currentlyDraggedWindow.reset(); + g_pKeybindManager->changeMouseBindMode(MBIND_INVALID); return; } @@ -200,7 +200,7 @@ void IHyprLayout::onBeginDragWindow() { if (PWORKSPACE->m_bHasFullscreenWindow && (!DRAGGINGWINDOW->m_bCreatedOverFullscreen || !DRAGGINGWINDOW->m_bIsFloating)) { Debug::log(LOG, "Rejecting drag on a fullscreen workspace. (window under fullscreen)"); - g_pInputManager->currentlyDraggedWindow.reset(); + g_pKeybindManager->changeMouseBindMode(MBIND_INVALID); return; } @@ -288,7 +288,6 @@ void IHyprLayout::onEndDragWindow() { } g_pInputManager->unsetCursorImage(); - g_pInputManager->currentlyDraggedWindow.reset(); g_pInputManager->m_bWasDraggingWindow = true; @@ -325,12 +324,14 @@ void IHyprLayout::onEndDragWindow() { } void IHyprLayout::onMouseMove(const Vector2D& mousePos) { + if (g_pInputManager->currentlyDraggedWindow.expired()) + return; + const auto DRAGGINGWINDOW = g_pInputManager->currentlyDraggedWindow.lock(); // Window invalid or drag begin size 0,0 meaning we rejected it. - if (!validMapped(DRAGGINGWINDOW) || m_vBeginDragSizeXY == Vector2D()) { - onEndDragWindow(); - g_pInputManager->currentlyDraggedWindow.reset(); + if ((!validMapped(DRAGGINGWINDOW) || m_vBeginDragSizeXY == Vector2D())) { + g_pKeybindManager->changeMouseBindMode(MBIND_INVALID); return; } diff --git a/src/managers/KeybindManager.cpp b/src/managers/KeybindManager.cpp index 22d9c3d7..038f6401 100644 --- a/src/managers/KeybindManager.cpp +++ b/src/managers/KeybindManager.cpp @@ -242,27 +242,14 @@ void CKeybindManager::updateXKBTranslationState() { } bool CKeybindManager::ensureMouseBindState() { - if (!m_bIsMouseBindActive) + if (!g_pInputManager->currentlyDraggedWindow) return false; if (!g_pInputManager->currentlyDraggedWindow.expired()) { - PHLWINDOW lastDraggedWindow = g_pInputManager->currentlyDraggedWindow.lock(); - - m_bIsMouseBindActive = false; - g_pLayoutManager->getCurrentLayout()->onEndDragWindow(); - g_pInputManager->currentlyDraggedWindow.reset(); - g_pInputManager->dragMode = MBIND_INVALID; - - g_pCompositor->updateWorkspaceWindows(lastDraggedWindow->workspaceID()); - g_pCompositor->updateWorkspaceWindowData(lastDraggedWindow->workspaceID()); - g_pLayoutManager->getCurrentLayout()->recalculateMonitor(lastDraggedWindow->m_iMonitorID); - g_pCompositor->updateAllWindowsAnimatedDecorationValues(); - + changeMouseBindMode(MBIND_INVALID); return true; } - m_bIsMouseBindActive = false; - return false; } @@ -540,10 +527,7 @@ bool CKeybindManager::onMouseEvent(const IPointer::SButtonEvent& e) { } void CKeybindManager::resizeWithBorder(const IPointer::SButtonEvent& e) { - if (e.state == WL_POINTER_BUTTON_STATE_PRESSED) - mouse("1resizewindow"); - else - mouse("0resizewindow"); + changeMouseBindMode(e.state == WL_POINTER_BUTTON_STATE_PRESSED ? MBIND_RESIZE : MBIND_INVALID); } void CKeybindManager::onSwitchEvent(const std::string& switchName) { @@ -971,7 +955,8 @@ static void toggleActiveFloatingCore(std::string args, std::optional float return; // remove drag status - g_pInputManager->currentlyDraggedWindow.reset(); + if (!g_pInputManager->currentlyDraggedWindow.expired()) + g_pKeybindManager->changeMouseBindMode(MBIND_INVALID); if (PWINDOW->m_sGroupData.pNextWindow.lock() && PWINDOW->m_sGroupData.pNextWindow.lock() != PWINDOW) { const auto PCURRENT = PWINDOW->getGroupCurrent(); @@ -2365,55 +2350,50 @@ void CKeybindManager::mouse(std::string args) { const auto ARGS = CVarList(args.substr(1), 2, ' '); const auto PRESSED = args[0] == '1'; + if (!PRESSED) { + changeMouseBindMode(MBIND_INVALID); + return; + } + if (ARGS[0] == "movewindow") { - if (PRESSED && g_pInputManager->dragMode == MBIND_INVALID) { - g_pKeybindManager->m_bIsMouseBindActive = true; - - const auto mouseCoords = g_pInputManager->getMouseCoordsInternal(); - PHLWINDOW pWindow = g_pCompositor->vectorToWindowUnified(mouseCoords, RESERVED_EXTENTS | INPUT_EXTENTS | ALLOW_FLOATING); - - if (pWindow && !pWindow->m_bIsFullscreen) - pWindow->checkInputOnDecos(INPUT_TYPE_DRAG_START, mouseCoords); - - if (g_pInputManager->currentlyDraggedWindow.expired()) - g_pInputManager->currentlyDraggedWindow = pWindow; - - g_pInputManager->dragMode = MBIND_MOVE; - g_pLayoutManager->getCurrentLayout()->onBeginDragWindow(); - } else if (!PRESSED && g_pInputManager->dragMode == MBIND_MOVE) { - g_pKeybindManager->m_bIsMouseBindActive = false; - - if (!g_pInputManager->currentlyDraggedWindow.expired()) { - g_pLayoutManager->getCurrentLayout()->onEndDragWindow(); - g_pInputManager->currentlyDraggedWindow.reset(); - g_pInputManager->dragMode = MBIND_INVALID; + changeMouseBindMode(MBIND_MOVE); + } else { + try { + switch (std::stoi(ARGS[1])) { + case 1: changeMouseBindMode(MBIND_RESIZE_FORCE_RATIO); break; + case 2: changeMouseBindMode(MBIND_RESIZE_BLOCK_RATIO); break; + default: changeMouseBindMode(MBIND_RESIZE); } - } - } else if (ARGS[0] == "resizewindow") { - if (PRESSED && g_pInputManager->dragMode == MBIND_INVALID) { - g_pKeybindManager->m_bIsMouseBindActive = true; + } catch (std::exception& e) { changeMouseBindMode(MBIND_RESIZE); } + } +} - g_pInputManager->currentlyDraggedWindow = - g_pCompositor->vectorToWindowUnified(g_pInputManager->getMouseCoordsInternal(), RESERVED_EXTENTS | INPUT_EXTENTS | ALLOW_FLOATING); +void CKeybindManager::changeMouseBindMode(const eMouseBindMode MODE) { + if (MODE != MBIND_INVALID) { + if (!g_pInputManager->currentlyDraggedWindow.expired() || g_pInputManager->dragMode != MBIND_INVALID) + return; - try { - switch (std::stoi(ARGS[1])) { - case 1: g_pInputManager->dragMode = MBIND_RESIZE_FORCE_RATIO; break; - case 2: g_pInputManager->dragMode = MBIND_RESIZE_BLOCK_RATIO; break; - default: g_pInputManager->dragMode = MBIND_RESIZE; - } - } catch (std::exception& e) { g_pInputManager->dragMode = MBIND_RESIZE; } - g_pLayoutManager->getCurrentLayout()->onBeginDragWindow(); - } else if (!PRESSED && - (g_pInputManager->dragMode == MBIND_RESIZE_FORCE_RATIO || g_pInputManager->dragMode == MBIND_RESIZE_BLOCK_RATIO || g_pInputManager->dragMode == MBIND_RESIZE)) { - g_pKeybindManager->m_bIsMouseBindActive = false; + const auto MOUSECOORDS = g_pInputManager->getMouseCoordsInternal(); + const PHLWINDOW PWINDOW = g_pCompositor->vectorToWindowUnified(MOUSECOORDS, RESERVED_EXTENTS | INPUT_EXTENTS | ALLOW_FLOATING); - if (!g_pInputManager->currentlyDraggedWindow.expired()) { - g_pLayoutManager->getCurrentLayout()->onEndDragWindow(); - g_pInputManager->currentlyDraggedWindow.reset(); - g_pInputManager->dragMode = MBIND_INVALID; - } - } + if (!PWINDOW) + return; + + if (!PWINDOW->m_bIsFullscreen && MODE == MBIND_MOVE) + PWINDOW->checkInputOnDecos(INPUT_TYPE_DRAG_START, MOUSECOORDS); + + if (g_pInputManager->currentlyDraggedWindow.expired()) + g_pInputManager->currentlyDraggedWindow = PWINDOW; + + g_pInputManager->dragMode = MODE; + + g_pLayoutManager->getCurrentLayout()->onBeginDragWindow(); + } else { + if (g_pInputManager->currentlyDraggedWindow.expired() || g_pInputManager->dragMode == MBIND_INVALID) + return; + + g_pLayoutManager->getCurrentLayout()->onEndDragWindow(); + g_pInputManager->dragMode = MODE; } } diff --git a/src/managers/KeybindManager.hpp b/src/managers/KeybindManager.hpp index 7201df04..26a6345b 100644 --- a/src/managers/KeybindManager.hpp +++ b/src/managers/KeybindManager.hpp @@ -105,6 +105,8 @@ class CKeybindManager { //we also store the keyboard pointer (in the string) to differentiate between different keyboard (layouts) std::unordered_map m_mKeyToCodeCache; + static void changeMouseBindMode(const eMouseBindMode mode); + private: std::deque m_dPressedKeys; @@ -116,7 +118,6 @@ class CKeybindManager { uint32_t m_uLastCode = 0; uint32_t m_uLastMouseCode = 0; - bool m_bIsMouseBindActive = false; std::vector m_vPressedSpecialBinds; int m_iPassPressed = -1; // used for pass diff --git a/src/managers/input/InputManager.cpp b/src/managers/input/InputManager.cpp index 7d2e7a0e..619bfab7 100644 --- a/src/managers/input/InputManager.cpp +++ b/src/managers/input/InputManager.cpp @@ -1677,7 +1677,7 @@ void CInputManager::releaseAllMouseButtons() { void CInputManager::setCursorIconOnBorder(PHLWINDOW w) { // do not override cursor icons set by mouse binds - if (g_pKeybindManager->m_bIsMouseBindActive) { + if (g_pInputManager->currentlyDraggedWindow.expired()) { m_eBorderIconDirection = BORDERICON_NONE; return; } From 10e8af00d61ee2d647af82712c4070eaec875cdb Mon Sep 17 00:00:00 2001 From: Mihai Fufezan Date: Sat, 27 Jul 2024 19:51:43 +0300 Subject: [PATCH 0180/2181] flake.lock: update hyprutils --- flake.lock | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/flake.lock b/flake.lock index 90d09c39..a42f8fe9 100644 --- a/flake.lock +++ b/flake.lock @@ -116,11 +116,11 @@ ] }, "locked": { - "lastModified": 1721324102, - "narHash": "sha256-WAZ0X6yJW1hFG6otkHBfyJDKRpNP5stsRqdEuHrFRpk=", + "lastModified": 1722098849, + "narHash": "sha256-D3wIZlBNh7LuZ0NaoCpY/Pvu+xHxIVtSN+KkWZYvvVs=", "owner": "hyprwm", "repo": "hyprutils", - "rev": "962582a090bc233c4de9d9897f46794280288989", + "rev": "5dcbbc1e3de40b2cecfd2007434d86e924468f1f", "type": "github" }, "original": { From 55ceca4cdd8f4b3980d2840b85f6b91778a24eab Mon Sep 17 00:00:00 2001 From: Mihai Fufezan Date: Sat, 27 Jul 2024 20:32:11 +0300 Subject: [PATCH 0181/2181] flake.lock: update aquamarine --- flake.lock | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/flake.lock b/flake.lock index a42f8fe9..422b0cf7 100644 --- a/flake.lock +++ b/flake.lock @@ -16,11 +16,11 @@ ] }, "locked": { - "lastModified": 1721992626, - "narHash": "sha256-GFDSPWxOqEkNrbuSfyoQHGIaRhJNapn2Rv0EEmBGR9A=", + "lastModified": 1722100913, + "narHash": "sha256-75Hcx5Zu0f+BeCkZxN1frkYacjbkwgCq+z3doVgr4Hw=", "owner": "hyprwm", "repo": "aquamarine", - "rev": "f95d1509370b7f40ef356ff69a332bd0356ab044", + "rev": "4918e57979bbdbd05aabb20f63e1cb5dc289bcbd", "type": "github" }, "original": { From 04b40ea2ec85dd1d74ff18edc046a233b65024ac Mon Sep 17 00:00:00 2001 From: Mihai Fufezan Date: Sat, 27 Jul 2024 22:17:05 +0300 Subject: [PATCH 0182/2181] CI: only run once for PRs with branches from original repo (#7075) --- .github/workflows/ci.yaml | 5 +++++ .github/workflows/nix-ci.yml | 2 +- .github/workflows/security-checks.yml | 1 + 3 files changed, 7 insertions(+), 1 deletion(-) diff --git a/.github/workflows/ci.yaml b/.github/workflows/ci.yaml index 6d25e027..7739d2b2 100644 --- a/.github/workflows/ci.yaml +++ b/.github/workflows/ci.yaml @@ -3,6 +3,7 @@ name: Build Hyprland on: [push, pull_request, workflow_dispatch] jobs: gcc: + if: github.event_name != 'pull_request' || github.event.pull_request.head.repo.fork name: "Build Hyprland (Arch)" runs-on: ubuntu-latest container: @@ -44,6 +45,7 @@ jobs: path: Hyprland.tar.xz meson: + if: github.event_name != 'pull_request' || github.event.pull_request.head.repo.fork name: "Build Hyprland with Meson (Arch)" runs-on: ubuntu-latest container: @@ -64,6 +66,7 @@ jobs: run: ninja -C build no-pch: + if: github.event_name != 'pull_request' || github.event.pull_request.head.repo.fork name: "Build Hyprland without precompiled headers (Arch)" runs-on: ubuntu-latest container: @@ -83,6 +86,7 @@ jobs: run: make nopch noxwayland: + if: github.event_name != 'pull_request' || github.event.pull_request.head.repo.fork name: "Build Hyprland in pure Wayland (Arch)" runs-on: ubuntu-latest container: @@ -103,6 +107,7 @@ jobs: run: make release clang-format: + if: github.event_name != 'pull_request' || github.event.pull_request.head.repo.fork name: "Code Style (Arch)" runs-on: ubuntu-latest container: diff --git a/.github/workflows/nix-ci.yml b/.github/workflows/nix-ci.yml index a66307c4..b25ed9aa 100644 --- a/.github/workflows/nix-ci.yml +++ b/.github/workflows/nix-ci.yml @@ -9,7 +9,7 @@ jobs: secrets: inherit build: - if: always() && !cancelled() && !contains(needs.*.result, 'failure') + if: (github.event_name != 'pull_request' || github.event.pull_request.head.repo.fork) && !contains(needs.*.result, 'failure') needs: update-inputs uses: ./.github/workflows/nix-build.yml secrets: inherit diff --git a/.github/workflows/security-checks.yml b/.github/workflows/security-checks.yml index 564013cf..4f539132 100644 --- a/.github/workflows/security-checks.yml +++ b/.github/workflows/security-checks.yml @@ -4,6 +4,7 @@ on: [push, pull_request] jobs: flawfinder: + if: github.event_name != 'pull_request' || github.event.pull_request.head.repo.fork name: Flawfinder Checks runs-on: ubuntu-latest permissions: From 6edfdd63a1fc87a6d874364c404c9b6f852c7096 Mon Sep 17 00:00:00 2001 From: vaxerski Date: Sat, 27 Jul 2024 22:07:57 +0200 Subject: [PATCH 0183/2181] surface: avoid crashes on fading out layers --- src/desktop/WLSurface.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/desktop/WLSurface.cpp b/src/desktop/WLSurface.cpp index e1348a90..3c91a142 100644 --- a/src/desktop/WLSurface.cpp +++ b/src/desktop/WLSurface.cpp @@ -227,7 +227,7 @@ SP CWLSurface::fromResource(SP pSurface) { bool CWLSurface::keyboardFocusable() const { if (m_pWindowOwner || m_pPopupOwner || m_pSubsurfaceOwner) return true; - if (m_pLayerOwner) + if (m_pLayerOwner && m_pLayerOwner->layerSurface) return m_pLayerOwner->layerSurface->current.interactivity != ZWLR_LAYER_SURFACE_V1_KEYBOARD_INTERACTIVITY_NONE; return false; } From bc86afea7e177a7ad4335737417fc0e468698dc4 Mon Sep 17 00:00:00 2001 From: outfoxxed Date: Sat, 27 Jul 2024 13:43:01 -0700 Subject: [PATCH 0184/2181] xdg-shell: completely rewrite xdg-positioner (#7067) This implementation actually works. --- CMakeLists.txt | 2 +- src/desktop/Popup.cpp | 10 +- src/desktop/Popup.hpp | 4 +- src/meson.build | 2 +- src/protocols/XDGShell.cpp | 199 +++++++++++++++++-------------------- src/protocols/XDGShell.hpp | 23 +++-- 6 files changed, 114 insertions(+), 126 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 8a27d81b..d9411075 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -115,7 +115,7 @@ pkg_check_modules( gbm hyprlang>=0.3.2 hyprcursor>=0.1.7 - hyprutils>=0.2.0) + hyprutils>=0.2.1) find_package(hyprwayland-scanner 0.3.10 REQUIRED) diff --git a/src/desktop/Popup.cpp b/src/desktop/Popup.cpp index 131a26b5..e48b7400 100644 --- a/src/desktop/Popup.cpp +++ b/src/desktop/Popup.cpp @@ -22,7 +22,7 @@ CPopup::CPopup(SP popup, CPopup* pOwner) : m_pParent(pOwner), m_pWindowOwner = pOwner->m_pWindowOwner; m_vLastSize = popup->surface->current.geometry.size(); - unconstrain(); + reposition(); initAllSignals(); } @@ -188,18 +188,18 @@ void CPopup::onReposition() { m_vLastPos = coordsRelativeToParent(); - unconstrain(); + reposition(); } -void CPopup::unconstrain() { +void CPopup::reposition() { const auto COORDS = t1ParentCoords(); const auto PMONITOR = g_pCompositor->getMonitorFromVector(COORDS); if (!PMONITOR) return; - CBox box = {PMONITOR->vecPosition.x - COORDS.x, PMONITOR->vecPosition.y - COORDS.y, PMONITOR->vecSize.x, PMONITOR->vecSize.y}; - m_pResource->applyPositioning(box, COORDS - PMONITOR->vecPosition); + CBox box = {PMONITOR->vecPosition.x, PMONITOR->vecPosition.y, PMONITOR->vecSize.x, PMONITOR->vecSize.y}; + m_pResource->applyPositioning(box, COORDS); } Vector2D CPopup::coordsRelativeToParent() { diff --git a/src/desktop/Popup.hpp b/src/desktop/Popup.hpp index d045cd41..eea3fb84 100644 --- a/src/desktop/Popup.hpp +++ b/src/desktop/Popup.hpp @@ -74,11 +74,11 @@ class CPopup { } listeners; void initAllSignals(); - void unconstrain(); + void reposition(); void recheckChildrenRecursive(); void sendScale(); Vector2D localToGlobal(const Vector2D& rel); Vector2D t1ParentCoords(); static void bfHelper(std::vector nodes, std::function fn, void* data); -}; \ No newline at end of file +}; diff --git a/src/meson.build b/src/meson.build index 71854fa4..098d8298 100644 --- a/src/meson.build +++ b/src/meson.build @@ -14,7 +14,7 @@ executable('Hyprland', src, dependency('cairo'), dependency('hyprcursor', version: '>=0.1.7'), dependency('hyprlang', version: '>= 0.3.2'), - dependency('hyprutils', version: '>= 0.2.0'), + dependency('hyprutils', version: '>= 0.2.1'), dependency('libdrm'), dependency('egl'), dependency('xkbcommon'), diff --git a/src/protocols/XDGShell.cpp b/src/protocols/XDGShell.cpp index 8276ed55..4b180617 100644 --- a/src/protocols/XDGShell.cpp +++ b/src/protocols/XDGShell.cpp @@ -8,6 +8,20 @@ #define LOGM PROTO::xdgShell->protoLog +void SXDGPositionerState::setAnchor(xdgPositionerAnchor edges) { + anchor.setTop(edges == XDG_POSITIONER_ANCHOR_TOP || edges == XDG_POSITIONER_ANCHOR_TOP_LEFT || edges == XDG_POSITIONER_ANCHOR_TOP_RIGHT); + anchor.setLeft(edges == XDG_POSITIONER_ANCHOR_LEFT || edges == XDG_POSITIONER_ANCHOR_TOP_LEFT || edges == XDG_POSITIONER_ANCHOR_BOTTOM_LEFT); + anchor.setBottom(edges == XDG_POSITIONER_ANCHOR_BOTTOM || edges == XDG_POSITIONER_ANCHOR_BOTTOM_LEFT || edges == XDG_POSITIONER_ANCHOR_BOTTOM_RIGHT); + anchor.setRight(edges == XDG_POSITIONER_ANCHOR_RIGHT || edges == XDG_POSITIONER_ANCHOR_TOP_RIGHT || edges == XDG_POSITIONER_ANCHOR_BOTTOM_RIGHT); +} + +void SXDGPositionerState::setGravity(xdgPositionerGravity edges) { + gravity.setTop(edges == XDG_POSITIONER_GRAVITY_TOP || edges == XDG_POSITIONER_GRAVITY_TOP_LEFT || edges == XDG_POSITIONER_GRAVITY_TOP_RIGHT); + gravity.setLeft(edges == XDG_POSITIONER_GRAVITY_LEFT || edges == XDG_POSITIONER_GRAVITY_TOP_LEFT || edges == XDG_POSITIONER_GRAVITY_BOTTOM_LEFT); + gravity.setBottom(edges == XDG_POSITIONER_GRAVITY_BOTTOM || edges == XDG_POSITIONER_GRAVITY_BOTTOM_LEFT || edges == XDG_POSITIONER_GRAVITY_BOTTOM_RIGHT); + gravity.setRight(edges == XDG_POSITIONER_GRAVITY_RIGHT || edges == XDG_POSITIONER_GRAVITY_TOP_RIGHT || edges == XDG_POSITIONER_GRAVITY_BOTTOM_RIGHT); +} + CXDGPopupResource::CXDGPopupResource(SP resource_, SP owner_, SP surface_, SP positioner) : surface(surface_), parent(owner_), resource(resource_), positionerRules(positioner) { if (!good()) @@ -490,9 +504,9 @@ CXDGPositionerResource::CXDGPositionerResource(SP resource_, SP< resource->setSetOffset([this](CXdgPositioner* r, int32_t x, int32_t y) { state.offset = {x, y}; }); - resource->setSetAnchor([this](CXdgPositioner* r, xdgPositionerAnchor a) { state.anchor = a; }); + resource->setSetAnchor([this](CXdgPositioner* r, xdgPositionerAnchor a) { state.setAnchor(a); }); - resource->setSetGravity([this](CXdgPositioner* r, xdgPositionerGravity g) { state.gravity = g; }); + resource->setSetGravity([this](CXdgPositioner* r, xdgPositionerGravity g) { state.setGravity(g); }); resource->setSetConstraintAdjustment([this](CXdgPositioner* r, xdgPositionerConstraintAdjustment a) { state.constraintAdjustment = (uint32_t)a; }); @@ -513,125 +527,96 @@ CXDGPositionerRules::CXDGPositionerRules(SP positioner) state = positioner->state; } -static Vector2D pointForAnchor(const CBox& box, const Vector2D& predictionSize, xdgPositionerAnchor anchor) { - switch (anchor) { - case XDG_POSITIONER_ANCHOR_TOP: return box.pos() + Vector2D{box.size().x / 2.0 - predictionSize.x / 2.0, 0.0}; - case XDG_POSITIONER_ANCHOR_BOTTOM: return box.pos() + Vector2D{box.size().x / 2.0 - predictionSize.x / 2.0, box.size().y}; - case XDG_POSITIONER_ANCHOR_LEFT: return box.pos() + Vector2D{0.0, box.size().y / 2.0 - predictionSize.y / 2.0}; - case XDG_POSITIONER_ANCHOR_RIGHT: return box.pos() + Vector2D{box.size().x, box.size().y / 2.F - predictionSize.y / 2.0}; - case XDG_POSITIONER_ANCHOR_TOP_LEFT: return box.pos(); - case XDG_POSITIONER_ANCHOR_BOTTOM_LEFT: return box.pos() + Vector2D{0.0, box.size().y}; - case XDG_POSITIONER_ANCHOR_TOP_RIGHT: return box.pos() + Vector2D{box.size().x, 0.0}; - case XDG_POSITIONER_ANCHOR_BOTTOM_RIGHT: return box.pos() + Vector2D{box.size().x, box.size().y}; - default: return box.pos(); - } - - return {}; -} - -CBox CXDGPositionerRules::getPosition(const CBox& constraint, const Vector2D& parentCoord) { - +CBox CXDGPositionerRules::getPosition(CBox constraint, const Vector2D& parentCoord) { Debug::log(LOG, "GetPosition with constraint {} {} and parent {}", constraint.pos(), constraint.size(), parentCoord); - CBox predictedBox = {parentCoord + constraint.pos() + pointForAnchor(state.anchorRect, state.requestedSize, state.anchor) + state.offset, state.requestedSize}; + // padding + constraint.expand(-4); - bool success = predictedBox.inside(constraint); + auto anchorRect = state.anchorRect.copy().translate(parentCoord); - if (success) - return predictedBox.translate(-parentCoord - constraint.pos()); + auto width = state.requestedSize.x; + auto height = state.requestedSize.y; - CBox test = predictedBox; + auto anchorX = state.anchor.left() ? anchorRect.x : state.anchor.right() ? anchorRect.extent().x : anchorRect.middle().x; + auto anchorY = state.anchor.top() ? anchorRect.y : state.anchor.bottom() ? anchorRect.extent().y : anchorRect.middle().y; - if (state.constraintAdjustment & (XDG_POSITIONER_CONSTRAINT_ADJUSTMENT_FLIP_X | XDG_POSITIONER_CONSTRAINT_ADJUSTMENT_FLIP_Y)) { - // attempt to flip - const bool flipX = state.constraintAdjustment & XDG_POSITIONER_CONSTRAINT_ADJUSTMENT_FLIP_X; - const bool flipY = state.constraintAdjustment & XDG_POSITIONER_CONSTRAINT_ADJUSTMENT_FLIP_Y; - auto countEdges = [constraint](const CBox& test) -> int { - int edgeCount = 0; - edgeCount += test.x < constraint.x ? 1 : 0; - edgeCount += test.x + test.w > constraint.x + constraint.w ? 1 : 0; - edgeCount += test.y < constraint.y ? 1 : 0; - edgeCount += test.y + test.h > constraint.y + constraint.h ? 1 : 0; - return edgeCount; - }; - int edgeCount = countEdges(test); + auto calcEffectiveX = [&]() { return state.gravity.left() ? anchorX - width : state.gravity.right() ? anchorX : anchorX - width / 2; }; + auto calcEffectiveY = [&]() { return state.gravity.top() ? anchorY - height : state.gravity.bottom() ? anchorY : anchorY - height / 2; }; - if (flipX && edgeCount > countEdges(test.copy().translate(Vector2D{-predictedBox.w - state.anchorRect.w, 0.0}))) - test.translate(Vector2D{-predictedBox.w - state.anchorRect.w, 0.0}); - if (flipY && edgeCount > countEdges(test.copy().translate(Vector2D{0.0, -predictedBox.h - state.anchorRect.h}))) - test.translate(Vector2D{0.0, -predictedBox.h - state.anchorRect.h}); + auto effectiveX = calcEffectiveX(); + auto effectiveY = calcEffectiveY(); - success = test.copy().expand(-1).inside(constraint); + // Note: the usage of offset is a guess which maintains compatibility with other compositors that were tested. + // It considers the offset when deciding whether or not to flip but does not actually flip the offset, instead + // applying it after the flip step. - if (success) - return test.translate(-parentCoord - constraint.pos()); - } + if (state.constraintAdjustment & XDG_POSITIONER_CONSTRAINT_ADJUSTMENT_FLIP_X) { + auto flip = (state.gravity.left() && effectiveX + state.offset.x < constraint.x) || (state.gravity.right() && effectiveX + state.offset.x + width > constraint.extent().x); - // for slide and resize, defines the padding around the edge for the positioned - // surface. - constexpr int EDGE_PADDING = 4; - - if (state.constraintAdjustment & (XDG_POSITIONER_CONSTRAINT_ADJUSTMENT_SLIDE_X | XDG_POSITIONER_CONSTRAINT_ADJUSTMENT_SLIDE_Y)) { - // attempt to slide - const bool slideX = state.constraintAdjustment & XDG_POSITIONER_CONSTRAINT_ADJUSTMENT_SLIDE_X; - const bool slideY = state.constraintAdjustment & XDG_POSITIONER_CONSTRAINT_ADJUSTMENT_SLIDE_Y; - - //const bool gravityLeft = state.gravity == XDG_POSITIONER_GRAVITY_NONE || state.gravity == XDG_POSITIONER_GRAVITY_LEFT || state.gravity == XDG_POSITIONER_GRAVITY_TOP_LEFT || state.gravity == XDG_POSITIONER_GRAVITY_BOTTOM_LEFT; - //const bool gravityTop = state.gravity == XDG_POSITIONER_GRAVITY_NONE || state.gravity == XDG_POSITIONER_GRAVITY_TOP || state.gravity == XDG_POSITIONER_GRAVITY_TOP_LEFT || state.gravity == XDG_POSITIONER_GRAVITY_TOP_RIGHT; - - const bool leftEdgeOut = test.x < constraint.x; - const bool topEdgeOut = test.y < constraint.y; - const bool rightEdgeOut = test.x + test.w > constraint.x + constraint.w; - const bool bottomEdgeOut = test.y + test.h > constraint.y + constraint.h; - - // TODO: this isn't truly conformant. - if (leftEdgeOut && slideX) - test.x = constraint.x + EDGE_PADDING; - if (rightEdgeOut && slideX) - test.x = std::clamp((double)(constraint.x + constraint.w - test.w), (double)(constraint.x + EDGE_PADDING), (double)INFINITY); - if (topEdgeOut && slideY) - test.y = constraint.y + EDGE_PADDING; - if (bottomEdgeOut && slideY) - test.y = std::clamp((double)(constraint.y + constraint.h - test.h), (double)(constraint.y + EDGE_PADDING), (double)INFINITY); - - success = test.copy().expand(-1).inside(constraint); - - if (success) - return test.translate(-parentCoord - constraint.pos()); - } - - if (state.constraintAdjustment & (XDG_POSITIONER_CONSTRAINT_ADJUSTMENT_RESIZE_X | XDG_POSITIONER_CONSTRAINT_ADJUSTMENT_RESIZE_Y)) { - const bool resizeX = state.constraintAdjustment & XDG_POSITIONER_CONSTRAINT_ADJUSTMENT_RESIZE_X; - const bool resizeY = state.constraintAdjustment & XDG_POSITIONER_CONSTRAINT_ADJUSTMENT_RESIZE_Y; - - const bool leftEdgeOut = test.x < constraint.x; - const bool topEdgeOut = test.y < constraint.y; - const bool rightEdgeOut = test.x + test.w > constraint.x + constraint.w; - const bool bottomEdgeOut = test.y + test.h > constraint.y + constraint.h; - - // TODO: this isn't truly conformant. - if (leftEdgeOut && resizeX) { - test.w = test.x + test.w - constraint.x - EDGE_PADDING; - test.x = constraint.x + EDGE_PADDING; + if (flip) { + state.gravity ^= CEdges::LEFT | CEdges::RIGHT; + anchorX = state.anchor.left() ? anchorRect.extent().x : state.anchor.right() ? anchorRect.x : anchorX; + effectiveX = calcEffectiveX(); } - if (rightEdgeOut && resizeX) - test.w = constraint.w - (test.x - constraint.w) - EDGE_PADDING; - if (topEdgeOut && resizeY) { - test.h = test.y + test.h - constraint.y - EDGE_PADDING; - test.y = constraint.y + EDGE_PADDING; - } - if (bottomEdgeOut && resizeY) - test.h = constraint.h - (test.y - constraint.y) - EDGE_PADDING; - - success = test.copy().expand(-1).inside(constraint); - - if (success) - return test.translate(-parentCoord - constraint.pos()); } - LOGM(WARN, "Compositor/client bug: xdg_positioner couldn't find a place"); + if (state.constraintAdjustment & XDG_POSITIONER_CONSTRAINT_ADJUSTMENT_FLIP_Y) { + auto flip = (state.gravity.top() && effectiveY + state.offset.y < constraint.y) || (state.gravity.bottom() && effectiveY + state.offset.y + height > constraint.extent().y); - return test.translate(-parentCoord - constraint.pos()); + if (flip) { + state.gravity ^= CEdges::TOP | CEdges::BOTTOM; + anchorY = state.anchor.top() ? anchorRect.extent().y : state.anchor.bottom() ? anchorRect.y : anchorY; + effectiveX = calcEffectiveX(); + } + } + + effectiveX += state.offset.x; + effectiveY += state.offset.y; + + // Slide order is important for the case where the window is too large to fit on screen. + + if (state.constraintAdjustment & XDG_POSITIONER_CONSTRAINT_ADJUSTMENT_SLIDE_X) { + if (effectiveX + width > constraint.extent().x) + effectiveX = constraint.extent().x - width; + + if (effectiveX < constraint.x) + effectiveX = constraint.x; + } + + if (state.constraintAdjustment & XDG_POSITIONER_CONSTRAINT_ADJUSTMENT_SLIDE_Y) { + if (effectiveY + height > constraint.extent().y) + effectiveY = constraint.extent().y - height; + + if (effectiveY < constraint.y) + effectiveY = constraint.y; + } + + if (state.constraintAdjustment & XDG_POSITIONER_CONSTRAINT_ADJUSTMENT_RESIZE_X) { + if (effectiveX < constraint.x) { + auto diff = constraint.x - effectiveX; + effectiveX = constraint.x; + width -= diff; + } + + auto effectiveX2 = effectiveX + width; + if (effectiveX2 > constraint.extent().x) + width -= effectiveX2 - constraint.extent().x; + } + + if (state.constraintAdjustment & XDG_POSITIONER_CONSTRAINT_ADJUSTMENT_RESIZE_Y) { + if (effectiveY < constraint.y) { + auto diff = constraint.y - effectiveY; + effectiveY = constraint.y; + height -= diff; + } + + auto effectiveY2 = effectiveY + height; + if (effectiveY2 > constraint.extent().y) + height -= effectiveY2 - constraint.extent().y; + } + + return {effectiveX - parentCoord.x, effectiveY - parentCoord.y, width, height}; } CXDGWMBase::CXDGWMBase(SP resource_) : resource(resource_) { diff --git a/src/protocols/XDGShell.hpp b/src/protocols/XDGShell.hpp index da551718..e6812c38 100644 --- a/src/protocols/XDGShell.hpp +++ b/src/protocols/XDGShell.hpp @@ -4,10 +4,10 @@ #include #include #include +#include #include "WaylandProtocol.hpp" #include "xdg-shell.hpp" #include "../helpers/math/Math.hpp" -#include "../helpers/math/Math.hpp" #include "../helpers/signal/Signal.hpp" #include "types/SurfaceRole.hpp" @@ -20,21 +20,24 @@ class CSeatGrab; class CWLSurfaceResource; struct SXDGPositionerState { - Vector2D requestedSize; - CBox anchorRect; - xdgPositionerAnchor anchor = XDG_POSITIONER_ANCHOR_NONE; - xdgPositionerGravity gravity = XDG_POSITIONER_GRAVITY_NONE; - uint32_t constraintAdjustment = 0; - Vector2D offset; - bool reactive = false; - Vector2D parentSize; + Vector2D requestedSize; + CBox anchorRect; + CEdges anchor; + CEdges gravity; + uint32_t constraintAdjustment = 0; + Vector2D offset; + bool reactive = false; + Vector2D parentSize; + + void setAnchor(xdgPositionerAnchor edges); + void setGravity(xdgPositionerGravity edges); }; class CXDGPositionerRules { public: CXDGPositionerRules(SP positioner); - CBox getPosition(const CBox& constraint, const Vector2D& parentPos); + CBox getPosition(CBox constraint, const Vector2D& parentPos); private: SXDGPositionerState state; From 9b6ae4f77b95fef271c2e21abba5e05b4cc47719 Mon Sep 17 00:00:00 2001 From: Sungyoon Cho Date: Sun, 28 Jul 2024 19:46:38 +0900 Subject: [PATCH 0185/2181] input: fix keyboard leds with multiple keyboards (#7079) --- src/devices/IKeyboard.cpp | 15 ++++++++++++--- src/devices/IKeyboard.hpp | 26 ++++++++++++++------------ src/managers/input/InputManager.cpp | 9 ++++++++- 3 files changed, 34 insertions(+), 16 deletions(-) diff --git a/src/devices/IKeyboard.cpp b/src/devices/IKeyboard.cpp index e3517bf1..e05cbd04 100644 --- a/src/devices/IKeyboard.cpp +++ b/src/devices/IKeyboard.cpp @@ -274,9 +274,9 @@ std::string IKeyboard::getActiveLayout() { return "none"; } -void IKeyboard::updateLEDs() { +std::optional IKeyboard::getLEDs() { if (xkbState == nullptr) - return; + return {}; uint32_t leds = 0; for (uint32_t i = 0; i < LED_COUNT; ++i) { @@ -284,7 +284,16 @@ void IKeyboard::updateLEDs() { leds |= (1 << i); } - updateLEDs(leds); + return leds; +} + +void IKeyboard::updateLEDs() { + std::optional leds = getLEDs(); + + if (!leds.has_value()) + return; + + updateLEDs(leds.value()); } void IKeyboard::updateLEDs(uint32_t leds) { diff --git a/src/devices/IKeyboard.hpp b/src/devices/IKeyboard.hpp index 2ff8a190..ad8eaf7e 100644 --- a/src/devices/IKeyboard.hpp +++ b/src/devices/IKeyboard.hpp @@ -5,6 +5,7 @@ #include "../macros.hpp" #include "../helpers/math/Math.hpp" +#include #include AQUAMARINE_FORWARD(IKeyboard); @@ -61,19 +62,20 @@ class IKeyboard : public IHID { std::string rules = ""; }; - void setKeymap(const SStringRuleNames& rules); - void updateXKBTranslationState(xkb_keymap* const keymap = nullptr); - std::string getActiveLayout(); - void updateLEDs(); - void updateLEDs(uint32_t leds); - uint32_t getModifiers(); - void updateModifiers(uint32_t depressed, uint32_t latched, uint32_t locked, uint32_t group); - bool updateModifiersState(); // rets whether changed - void updateXkbStateWithKey(uint32_t xkbKey, bool pressed); - void updateKeymapFD(); + void setKeymap(const SStringRuleNames& rules); + void updateXKBTranslationState(xkb_keymap* const keymap = nullptr); + std::string getActiveLayout(); + std::optional getLEDs(); + void updateLEDs(); + void updateLEDs(uint32_t leds); + uint32_t getModifiers(); + void updateModifiers(uint32_t depressed, uint32_t latched, uint32_t locked, uint32_t group); + bool updateModifiersState(); // rets whether changed + void updateXkbStateWithKey(uint32_t xkbKey, bool pressed); + void updateKeymapFD(); - bool active = false; - bool enabled = true; + bool active = false; + bool enabled = true; // if the keymap is overridden by the implementation, // don't try to set keyboard rules anymore, to avoid overwriting the requested one. diff --git a/src/managers/input/InputManager.cpp b/src/managers/input/InputManager.cpp index 619bfab7..014de40a 100644 --- a/src/managers/input/InputManager.cpp +++ b/src/managers/input/InputManager.cpp @@ -1265,7 +1265,14 @@ void CInputManager::updateKeyboardsLeds(SP pKeyboard) { if (!pKeyboard) return; - pKeyboard->updateLEDs(); + std::optional leds = pKeyboard->getLEDs(); + + if (!leds.has_value()) + return; + + for (auto& k : m_vKeyboards) { + k->updateLEDs(leds.value()); + } } void CInputManager::onKeyboardKey(std::any event, SP pKeyboard) { From 3cc2028def295735ce496a42c79d1b922d2de45d Mon Sep 17 00:00:00 2001 From: Mihai Fufezan Date: Sun, 28 Jul 2024 14:03:30 +0300 Subject: [PATCH 0186/2181] hyprpm: checkout commit instead of branch Fixes #6948 --- hyprpm/src/core/PluginManager.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/hyprpm/src/core/PluginManager.cpp b/hyprpm/src/core/PluginManager.cpp index 036609f3..edb98812 100644 --- a/hyprpm/src/core/PluginManager.cpp +++ b/hyprpm/src/core/PluginManager.cpp @@ -464,7 +464,7 @@ bool CPluginManager::updateHeaders(bool force) { progress.m_szCurrentMessage = "Checking out sources"; progress.print(); - ret = execAndGet("cd " + WORKINGDIR + " && git checkout " + HLVER.branch + " 2>&1"); + ret = execAndGet("cd " + WORKINGDIR + " && git checkout " + HLVER.hash + " 2>&1"); if (m_bVerbose) progress.printMessageAbove(std::string{Colors::BLUE} + "[v] " + Colors::RESET + "git returned (co): " + ret); From fcff2dcac24ca497a39c1cb271d449ade037b7ad Mon Sep 17 00:00:00 2001 From: Mihai Fufezan Date: Sun, 28 Jul 2024 18:42:05 +0300 Subject: [PATCH 0187/2181] flake.lock: update xdph --- flake.lock | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/flake.lock b/flake.lock index 422b0cf7..01b68384 100644 --- a/flake.lock +++ b/flake.lock @@ -67,11 +67,11 @@ ] }, "locked": { - "lastModified": 1718746314, - "narHash": "sha256-HUklK5u86w2Yh9dOkk4FdsL8eehcOZ95jPhLixGDRQY=", + "lastModified": 1721326555, + "narHash": "sha256-zCu4R0CSHEactW9JqYki26gy8h9f6rHmSwj4XJmlHgg=", "owner": "hyprwm", "repo": "hyprland-protocols", - "rev": "1b61f0093afff20ab44d88ad707aed8bf2215290", + "rev": "5a11232266bf1a1f5952d5b179c3f4b2facaaa84", "type": "github" }, "original": { @@ -209,11 +209,11 @@ ] }, "locked": { - "lastModified": 1721755049, - "narHash": "sha256-O17b38bQnmfxv7It3OnVYx7fp1seEdI7xxnw5vJFv30=", + "lastModified": 1722181019, + "narHash": "sha256-Lj/g1UzrsTZUixtveQix6eB3pon2j23qv5/5pzTx0LQ=", "owner": "hyprwm", "repo": "xdg-desktop-portal-hyprland", - "rev": "5555f467f68ce7cdf1060991c24263073b95e9da", + "rev": "0e2f3b9c85f7bab3983098a01366876d34daf383", "type": "github" }, "original": { From 73d09953e84ae4f320498fee8522295899972f25 Mon Sep 17 00:00:00 2001 From: vaxerski Date: Sun, 28 Jul 2024 23:41:15 +0200 Subject: [PATCH 0188/2181] core/surface: drop map/unmap events in member funcs causes loops --- src/protocols/core/Compositor.cpp | 4 ---- src/protocols/core/Subcompositor.cpp | 2 ++ 2 files changed, 2 insertions(+), 4 deletions(-) diff --git a/src/protocols/core/Compositor.cpp b/src/protocols/core/Compositor.cpp index 76907cc2..7275cbf8 100644 --- a/src/protocols/core/Compositor.cpp +++ b/src/protocols/core/Compositor.cpp @@ -319,8 +319,6 @@ void CWLSurfaceResource::map() { mapped = true; - events.map.emit(); - timespec now; clock_gettime(CLOCK_MONOTONIC, &now); frame(&now); @@ -335,8 +333,6 @@ void CWLSurfaceResource::unmap() { mapped = false; - events.unmap.emit(); - // release the buffers. // this is necessary for XWayland to function correctly, // as it does not unmap via the traditional commit(null buffer) method, but via the X11 protocol. diff --git a/src/protocols/core/Subcompositor.cpp b/src/protocols/core/Subcompositor.cpp index cbc4063a..01cc0798 100644 --- a/src/protocols/core/Subcompositor.cpp +++ b/src/protocols/core/Subcompositor.cpp @@ -82,11 +82,13 @@ CWLSubsurfaceResource::CWLSubsurfaceResource(SP resource_, SPevents.commit.registerListener([this](std::any d) { if (surface->current.buffer && !surface->mapped) { surface->map(); + surface->events.map.emit(); return; } if (!surface->current.buffer && surface->mapped) { surface->unmap(); + surface->events.unmap.emit(); return; } }); From 256db08aed3bf045a8268dddaf15a96558bbcf2a Mon Sep 17 00:00:00 2001 From: vaxerski Date: Sun, 28 Jul 2024 23:41:36 +0200 Subject: [PATCH 0189/2181] layersurface: null check for surface validity before unmap() --- src/desktop/LayerSurface.cpp | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/desktop/LayerSurface.cpp b/src/desktop/LayerSurface.cpp index f3db4b61..3a3edc6d 100644 --- a/src/desktop/LayerSurface.cpp +++ b/src/desktop/LayerSurface.cpp @@ -192,7 +192,8 @@ void CLayerSurface::onUnmap() { g_pCompositor->addToFadingOutSafe(self.lock()); mapped = false; - layerSurface->surface->unmap(); + if (layerSurface && layerSurface->surface) + layerSurface->surface->unmap(); startAnimation(false); return; @@ -204,7 +205,8 @@ void CLayerSurface::onUnmap() { startAnimation(false); mapped = false; - layerSurface->surface->unmap(); + if (layerSurface && layerSurface->surface) + layerSurface->surface->unmap(); g_pCompositor->addToFadingOutSafe(self.lock()); From 7df9b01d483155713c8d89666c7fc865b90c162e Mon Sep 17 00:00:00 2001 From: vaxerski Date: Sun, 28 Jul 2024 23:47:17 +0200 Subject: [PATCH 0190/2181] core: emit unmap event after unmap in surface destroy --- src/protocols/core/Compositor.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/protocols/core/Compositor.cpp b/src/protocols/core/Compositor.cpp index 7275cbf8..368b8ed4 100644 --- a/src/protocols/core/Compositor.cpp +++ b/src/protocols/core/Compositor.cpp @@ -151,8 +151,10 @@ CWLSurfaceResource::~CWLSurfaceResource() { } void CWLSurfaceResource::destroy() { - if (mapped) + if (mapped) { unmap(); + events.unmap.emit(); + } events.destroy.emit(); PROTO::compositor->destroyResource(this); } From a9d87bd6669568741704de08b6f0328a92e29396 Mon Sep 17 00:00:00 2001 From: vaxerski Date: Sun, 28 Jul 2024 23:56:35 +0200 Subject: [PATCH 0191/2181] surface: emit unmap before unmapping and releasing the buffers --- src/protocols/LayerShell.cpp | 2 +- src/protocols/XDGShell.cpp | 2 +- src/protocols/core/Compositor.cpp | 2 +- src/protocols/core/Subcompositor.cpp | 2 +- src/xwayland/XSurface.cpp | 3 +-- 5 files changed, 5 insertions(+), 6 deletions(-) diff --git a/src/protocols/LayerShell.cpp b/src/protocols/LayerShell.cpp index e018c3d0..5018828e 100644 --- a/src/protocols/LayerShell.cpp +++ b/src/protocols/LayerShell.cpp @@ -73,8 +73,8 @@ CLayerShellResource::CLayerShellResource(SP resource_, SPunmap(); events.unmap.emit(); + surface->unmap(); configured = false; return; } diff --git a/src/protocols/XDGShell.cpp b/src/protocols/XDGShell.cpp index 4b180617..e9921988 100644 --- a/src/protocols/XDGShell.cpp +++ b/src/protocols/XDGShell.cpp @@ -365,8 +365,8 @@ CXDGSurfaceResource::CXDGSurfaceResource(SP resource_, SPcurrent.buffer && mapped) { mapped = false; - surface->unmap(); events.unmap.emit(); + surface->unmap(); return; } diff --git a/src/protocols/core/Compositor.cpp b/src/protocols/core/Compositor.cpp index 368b8ed4..6352b7e6 100644 --- a/src/protocols/core/Compositor.cpp +++ b/src/protocols/core/Compositor.cpp @@ -152,8 +152,8 @@ CWLSurfaceResource::~CWLSurfaceResource() { void CWLSurfaceResource::destroy() { if (mapped) { - unmap(); events.unmap.emit(); + unmap(); } events.destroy.emit(); PROTO::compositor->destroyResource(this); diff --git a/src/protocols/core/Subcompositor.cpp b/src/protocols/core/Subcompositor.cpp index 01cc0798..c0c1f258 100644 --- a/src/protocols/core/Subcompositor.cpp +++ b/src/protocols/core/Subcompositor.cpp @@ -87,8 +87,8 @@ CWLSubsurfaceResource::CWLSubsurfaceResource(SP resource_, SPcurrent.buffer && surface->mapped) { - surface->unmap(); surface->events.unmap.emit(); + surface->unmap(); return; } }); diff --git a/src/xwayland/XSurface.cpp b/src/xwayland/XSurface.cpp index 5d25e0e8..107b22da 100644 --- a/src/xwayland/XSurface.cpp +++ b/src/xwayland/XSurface.cpp @@ -114,12 +114,11 @@ void CXWaylandSurface::unmap() { std::erase(g_pXWayland->pWM->mappedSurfacesStacking, self); mapped = false; + events.unmap.emit(); surface->unmap(); Debug::log(LOG, "XWayland surface {:x} unmapping", (uintptr_t)this); - events.unmap.emit(); - g_pXWayland->pWM->updateClientList(); } From 6e6c61b9e87942425b978efa2309dbcca57c3217 Mon Sep 17 00:00:00 2001 From: Virt <41426325+VirtCode@users.noreply.github.com> Date: Mon, 29 Jul 2024 10:47:25 +0200 Subject: [PATCH 0192/2181] layer-shell: avoid crashes on unmap (#7092) --- src/desktop/LayerSurface.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/desktop/LayerSurface.cpp b/src/desktop/LayerSurface.cpp index 3a3edc6d..4426491d 100644 --- a/src/desktop/LayerSurface.cpp +++ b/src/desktop/LayerSurface.cpp @@ -219,7 +219,7 @@ void CLayerSurface::onUnmap() { // refocus if needed // vvvvvvvvvvvvv if there is a last focus and the last focus is not keyboard focusable, fallback to window - if (WASLASTFOCUS || (g_pCompositor->m_pLastFocus && !g_pCompositor->m_pLastFocus->hlSurface->keyboardFocusable())) + if (WASLASTFOCUS || (g_pCompositor->m_pLastFocus && g_pCompositor->m_pLastFocus->hlSurface && !g_pCompositor->m_pLastFocus->hlSurface->keyboardFocusable())) g_pInputManager->refocusLastWindow(PMONITOR); else if (g_pCompositor->m_pLastFocus) g_pSeatManager->setKeyboardFocus(g_pCompositor->m_pLastFocus.lock()); From 33e513d489faf5998a3831d55aa7ddd796ef3368 Mon Sep 17 00:00:00 2001 From: outfoxxed Date: Mon, 29 Jul 2024 01:48:27 -0700 Subject: [PATCH 0193/2181] xdg-shell: fix xdg-positioner y-flip (#7094) --- src/protocols/XDGShell.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/protocols/XDGShell.cpp b/src/protocols/XDGShell.cpp index e9921988..cb8a5bc3 100644 --- a/src/protocols/XDGShell.cpp +++ b/src/protocols/XDGShell.cpp @@ -567,7 +567,7 @@ CBox CXDGPositionerRules::getPosition(CBox constraint, const Vector2D& parentCoo if (flip) { state.gravity ^= CEdges::TOP | CEdges::BOTTOM; anchorY = state.anchor.top() ? anchorRect.extent().y : state.anchor.bottom() ? anchorRect.y : anchorY; - effectiveX = calcEffectiveX(); + effectiveY = calcEffectiveY(); } } From 87699575e1663649270e9a271609b5bcd079ce70 Mon Sep 17 00:00:00 2001 From: Vaxry Date: Mon, 29 Jul 2024 14:23:19 +0200 Subject: [PATCH 0194/2181] egl: require gles 3.0 only No clue what could break, hopefully nothing ref #6973 --- src/render/OpenGL.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/render/OpenGL.cpp b/src/render/OpenGL.cpp index 39f6614e..b2346e0f 100644 --- a/src/render/OpenGL.cpp +++ b/src/render/OpenGL.cpp @@ -134,7 +134,7 @@ void CHyprOpenGLImpl::initEGL(bool gbm) { attrs.push_back(EGL_CONTEXT_MAJOR_VERSION); attrs.push_back(3); attrs.push_back(EGL_CONTEXT_MINOR_VERSION); - attrs.push_back(2); + attrs.push_back(0); #else attrs.push_back(EGL_CONTEXT_CLIENT_VERSION); attrs.push_back(2); From 70468857da2e64c35c7e79b7e63bff04e56e3be5 Mon Sep 17 00:00:00 2001 From: Vaxry Date: Mon, 29 Jul 2024 14:27:05 +0200 Subject: [PATCH 0195/2181] egl: attempt a 3.2 egl context first --- src/render/OpenGL.cpp | 24 +++++++++++++++++++++--- 1 file changed, 21 insertions(+), 3 deletions(-) diff --git a/src/render/OpenGL.cpp b/src/render/OpenGL.cpp index b2346e0f..43a2c3a7 100644 --- a/src/render/OpenGL.cpp +++ b/src/render/OpenGL.cpp @@ -130,11 +130,13 @@ void CHyprOpenGLImpl::initEGL(bool gbm) { attrs.push_back(EGL_LOSE_CONTEXT_ON_RESET_EXT); } + auto attrsNoVer = attrs; + #ifndef GLES2 attrs.push_back(EGL_CONTEXT_MAJOR_VERSION); attrs.push_back(3); attrs.push_back(EGL_CONTEXT_MINOR_VERSION); - attrs.push_back(0); + attrs.push_back(2); #else attrs.push_back(EGL_CONTEXT_CLIENT_VERSION); attrs.push_back(2); @@ -143,8 +145,24 @@ void CHyprOpenGLImpl::initEGL(bool gbm) { attrs.push_back(EGL_NONE); m_pEglContext = eglCreateContext(m_pEglDisplay, EGL_NO_CONFIG_KHR, EGL_NO_CONTEXT, attrs.data()); - if (m_pEglContext == EGL_NO_CONTEXT) - RASSERT(false, "EGL: failed to create a context"); + if (m_pEglContext == EGL_NO_CONTEXT) { +#ifdef GLES2 + RASSERT(false, "EGL: failed to create a context with GLES2.0"); +#endif + Debug::log(WARN, "EGL: Failed to create a context with GLES3.2, retrying 3.0"); + + attrs = attrsNoVer; + attrs.push_back(EGL_CONTEXT_MAJOR_VERSION); + attrs.push_back(3); + attrs.push_back(EGL_CONTEXT_MINOR_VERSION); + attrs.push_back(0); + attrs.push_back(EGL_NONE); + + m_pEglContext = eglCreateContext(m_pEglDisplay, EGL_NO_CONFIG_KHR, EGL_NO_CONTEXT, attrs.data()); + + if (m_pEglContext == EGL_NO_CONTEXT) + RASSERT(false, "EGL: failed to create a context with either GLES3.2 or 3.0"); + } if (m_sExts.IMG_context_priority) { EGLint priority = EGL_CONTEXT_PRIORITY_MEDIUM_IMG; From 23a8f06594fd75580ddb6115c78812d3e3d6c57f Mon Sep 17 00:00:00 2001 From: Vaxry Date: Mon, 29 Jul 2024 16:27:09 +0200 Subject: [PATCH 0196/2181] virtualptr: allow binding to output --- src/devices/IPointer.hpp | 3 ++- src/devices/VirtualPointer.cpp | 2 ++ src/managers/PointerManager.cpp | 10 ++++++++++ src/protocols/VirtualPointer.cpp | 21 +++++++++++++++------ src/protocols/VirtualPointer.hpp | 12 +++++++----- 5 files changed, 36 insertions(+), 12 deletions(-) diff --git a/src/devices/IPointer.hpp b/src/devices/IPointer.hpp index 5df47c04..760ec8dc 100644 --- a/src/devices/IPointer.hpp +++ b/src/devices/IPointer.hpp @@ -106,7 +106,8 @@ class IPointer : public IHID { } pointerEvents; std::string hlName; - bool connected = false; // means connected to the cursor + bool connected = false; // means connected to the cursor + std::string boundOutput = ""; WP self; }; diff --git a/src/devices/VirtualPointer.cpp b/src/devices/VirtualPointer.cpp index f9a1c409..9223ebe1 100644 --- a/src/devices/VirtualPointer.cpp +++ b/src/devices/VirtualPointer.cpp @@ -38,6 +38,8 @@ CVirtualPointer::CVirtualPointer(SP resource) : point listeners.holdBegin = pointer->events.holdBegin.registerListener([this](std::any d) { pointerEvents.holdBegin.emit(d); }); listeners.holdEnd = pointer->events.holdEnd.registerListener([this](std::any d) { pointerEvents.holdEnd.emit(d); }); + boundOutput = resource->boundOutput ? resource->boundOutput->szName : "auto"; + deviceName = pointer->name; } diff --git a/src/managers/PointerManager.cpp b/src/managers/PointerManager.cpp index 3b425688..59c54c78 100644 --- a/src/managers/PointerManager.cpp +++ b/src/managers/PointerManager.cpp @@ -674,6 +674,16 @@ void CPointerManager::warpAbsolute(Vector2D abs, SP dev) { } break; } + case HID_TYPE_POINTER: { + IPointer* POINTER = reinterpret_cast(dev.get()); + if (!POINTER->boundOutput.empty() && POINTER->boundOutput != "auto") { + if (const auto PMONITOR = g_pCompositor->getMonitorFromString(POINTER->boundOutput); PMONITOR) { + currentMonitor = PMONITOR->self.lock(); + mappedArea = currentMonitor->logicalBox(); + } + } + break; + } default: break; } diff --git a/src/protocols/VirtualPointer.cpp b/src/protocols/VirtualPointer.cpp index bdeec32d..8626241a 100644 --- a/src/protocols/VirtualPointer.cpp +++ b/src/protocols/VirtualPointer.cpp @@ -1,8 +1,9 @@ #include "VirtualPointer.hpp" +#include "core/Output.hpp" #define LOGM PROTO::virtualPointer->protoLog -CVirtualPointerV1Resource::CVirtualPointerV1Resource(SP resource_) : resource(resource_) { +CVirtualPointerV1Resource::CVirtualPointerV1Resource(SP resource_, WP boundOutput_) : boundOutput(boundOutput_), resource(resource_) { if (!good()) return; @@ -112,10 +113,18 @@ void CVirtualPointerProtocol::bindManager(wl_client* client, void* data, uint32_ RESOURCE->setOnDestroy([this](CZwlrVirtualPointerManagerV1* p) { this->onManagerResourceDestroy(p->resource()); }); RESOURCE->setDestroy([this](CZwlrVirtualPointerManagerV1* p) { this->onManagerResourceDestroy(p->resource()); }); - RESOURCE->setCreateVirtualPointer([this](CZwlrVirtualPointerManagerV1* pMgr, wl_resource* seat, uint32_t id) { this->onCreatePointer(pMgr, seat, id); }); + RESOURCE->setCreateVirtualPointer([this](CZwlrVirtualPointerManagerV1* pMgr, wl_resource* seat, uint32_t id) { this->onCreatePointer(pMgr, seat, id, {}); }); RESOURCE->setCreateVirtualPointerWithOutput([this](CZwlrVirtualPointerManagerV1* pMgr, wl_resource* seat, wl_resource* output, uint32_t id) { - LOGM(WARN, "TODO: CreateWithOutput is not supported yet. Ignoring for now."); - this->onCreatePointer(pMgr, seat, id); + if (output) { + auto RES = CWLOutputResource::fromResource(output); + if (!RES) { + this->onCreatePointer(pMgr, seat, id, {}); + return; + } + + this->onCreatePointer(pMgr, seat, id, RES->monitor); + } else + this->onCreatePointer(pMgr, seat, id, {}); }); } @@ -127,9 +136,9 @@ void CVirtualPointerProtocol::destroyResource(CVirtualPointerV1Resource* pointer std::erase_if(m_vPointers, [&](const auto& other) { return other.get() == pointer; }); } -void CVirtualPointerProtocol::onCreatePointer(CZwlrVirtualPointerManagerV1* pMgr, wl_resource* seat, uint32_t id) { +void CVirtualPointerProtocol::onCreatePointer(CZwlrVirtualPointerManagerV1* pMgr, wl_resource* seat, uint32_t id, WP output) { - const auto RESOURCE = m_vPointers.emplace_back(makeShared(makeShared(pMgr->client(), pMgr->version(), id))); + const auto RESOURCE = m_vPointers.emplace_back(makeShared(makeShared(pMgr->client(), pMgr->version(), id), output)); if (!RESOURCE->good()) { pMgr->noMemory(); diff --git a/src/protocols/VirtualPointer.hpp b/src/protocols/VirtualPointer.hpp index ee5ee7e2..1a51d977 100644 --- a/src/protocols/VirtualPointer.hpp +++ b/src/protocols/VirtualPointer.hpp @@ -11,7 +11,7 @@ class CVirtualPointerV1Resource { public: - CVirtualPointerV1Resource(SP resource_); + CVirtualPointerV1Resource(SP resource_, WP boundOutput_); ~CVirtualPointerV1Resource(); struct { @@ -34,10 +34,12 @@ class CVirtualPointerV1Resource { CSignal holdEnd; } events; - bool good(); - wl_client* client(); + bool good(); + wl_client* client(); - std::string name; + std::string name; + + WP boundOutput; private: SP resource; @@ -60,7 +62,7 @@ class CVirtualPointerProtocol : public IWaylandProtocol { private: void onManagerResourceDestroy(wl_resource* res); void destroyResource(CVirtualPointerV1Resource* pointer); - void onCreatePointer(CZwlrVirtualPointerManagerV1* pMgr, wl_resource* seat, uint32_t id); + void onCreatePointer(CZwlrVirtualPointerManagerV1* pMgr, wl_resource* seat, uint32_t id, WP output); // std::vector> m_vManagers; From 3a1afb53fdc75d6bfb434fb5ff29ab43ce6b040a Mon Sep 17 00:00:00 2001 From: atikiNBTW <74009330+atikiNBTW@users.noreply.github.com> Date: Mon, 29 Jul 2024 19:56:50 +0500 Subject: [PATCH 0197/2181] pluginapi: Add force reload of config at the end of plugin initialization (#7099) * Add force reload of config at the end of plugin load * Remove unnecessary include --- src/plugins/PluginSystem.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/plugins/PluginSystem.cpp b/src/plugins/PluginSystem.cpp index 46f50469..122faafd 100644 --- a/src/plugins/PluginSystem.cpp +++ b/src/plugins/PluginSystem.cpp @@ -80,6 +80,8 @@ CPlugin* CPluginSystem::loadPlugin(const std::string& path) { PLUGIN->version = PLUGINDATA.version; PLUGIN->name = PLUGINDATA.name; + g_pConfigManager->m_bForceReload = true; + Debug::log(LOG, " [PluginSystem] Plugin {} loaded. Handle: {:x}, path: \"{}\", author: \"{}\", description: \"{}\", version: \"{}\"", PLUGINDATA.name, (uintptr_t)MODULE, path, PLUGINDATA.author, PLUGINDATA.description, PLUGINDATA.version); From 01560c9d7ccd0beec1a9c190862ee325e6f3c45e Mon Sep 17 00:00:00 2001 From: Vaxry Date: Mon, 29 Jul 2024 18:13:17 +0200 Subject: [PATCH 0198/2181] virtualptr: map to entire screen if no output is provided fixes #6749 --- src/devices/VirtualPointer.cpp | 2 +- src/managers/PointerManager.cpp | 20 ++++++++++++++++++-- 2 files changed, 19 insertions(+), 3 deletions(-) diff --git a/src/devices/VirtualPointer.cpp b/src/devices/VirtualPointer.cpp index 9223ebe1..7ad18775 100644 --- a/src/devices/VirtualPointer.cpp +++ b/src/devices/VirtualPointer.cpp @@ -38,7 +38,7 @@ CVirtualPointer::CVirtualPointer(SP resource) : point listeners.holdBegin = pointer->events.holdBegin.registerListener([this](std::any d) { pointerEvents.holdBegin.emit(d); }); listeners.holdEnd = pointer->events.holdEnd.registerListener([this](std::any d) { pointerEvents.holdEnd.emit(d); }); - boundOutput = resource->boundOutput ? resource->boundOutput->szName : "auto"; + boundOutput = resource->boundOutput ? resource->boundOutput->szName : "entire"; deviceName = pointer->name; } diff --git a/src/managers/PointerManager.cpp b/src/managers/PointerManager.cpp index 59c54c78..a09992a2 100644 --- a/src/managers/PointerManager.cpp +++ b/src/managers/PointerManager.cpp @@ -676,8 +676,24 @@ void CPointerManager::warpAbsolute(Vector2D abs, SP dev) { } case HID_TYPE_POINTER: { IPointer* POINTER = reinterpret_cast(dev.get()); - if (!POINTER->boundOutput.empty() && POINTER->boundOutput != "auto") { - if (const auto PMONITOR = g_pCompositor->getMonitorFromString(POINTER->boundOutput); PMONITOR) { + if (!POINTER->boundOutput.empty()) { + if (POINTER->boundOutput == "entire") { + // find x and y size of the entire space + Vector2D bottomRight = {-9999999, -9999999}, topLeft = {9999999, 9999999}; + for (auto& m : g_pCompositor->m_vMonitors) { + const auto EXTENT = m->logicalBox().extent(); + const auto POS = m->logicalBox().pos(); + if (EXTENT.x > bottomRight.x) + bottomRight.x = EXTENT.x; + if (EXTENT.y > bottomRight.y) + bottomRight.y = EXTENT.y; + if (POS.x < topLeft.x) + topLeft.x = POS.x; + if (POS.y < topLeft.y) + topLeft.y = POS.y; + } + mappedArea = {topLeft, bottomRight - topLeft}; + } else if (const auto PMONITOR = g_pCompositor->getMonitorFromString(POINTER->boundOutput); PMONITOR) { currentMonitor = PMONITOR->self.lock(); mappedArea = currentMonitor->logicalBox(); } From 60b663e2765c4cdb7e14fff75c4f88bf7ae312e2 Mon Sep 17 00:00:00 2001 From: Ikalco <73481042+ikalco@users.noreply.github.com> Date: Mon, 29 Jul 2024 11:14:19 -0500 Subject: [PATCH 0199/2181] protocols: move text-input-v1 to hyprwayland-scanner (#7096) * move text-input-v1 to hyprwayland-scanner * vro --- CMakeLists.txt | 5 +- protocols/meson.build | 2 +- src/managers/ProtocolManager.cpp | 4 +- src/managers/ProtocolManager.hpp | 2 - src/managers/input/InputMethodRelay.cpp | 10 +- src/managers/input/InputMethodRelay.hpp | 7 +- src/managers/input/TextInput.cpp | 86 +++---- src/managers/input/TextInput.hpp | 14 +- src/protocols/TextInputV1.cpp | 295 ++++++++---------------- src/protocols/TextInputV1.hpp | 84 +++---- src/protocols/VirtualPointer.hpp | 1 + 11 files changed, 196 insertions(+), 314 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index d9411075..550f1dc5 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -292,10 +292,7 @@ protocol( "subprojects/hyprland-protocols/protocols/hyprland-global-shortcuts-v1.xml" "hyprland-global-shortcuts-v1" true) -protocol( - "unstable/text-input/text-input-unstable-v1.xml" - "text-input-unstable-v1" false) - +protocolnew("unstable/text-input" "text-input-unstable-v1" false) protocolnew("subprojects/hyprland-protocols/protocols" "hyprland-toplevel-export-v1" true) protocolnew("protocols" "wlr-screencopy-unstable-v1" true) protocolnew("protocols" "wlr-gamma-control-unstable-v1" true) diff --git a/protocols/meson.build b/protocols/meson.build index 35b2b29b..4fd40859 100644 --- a/protocols/meson.build +++ b/protocols/meson.build @@ -24,7 +24,6 @@ hyprwayland_scanner = find_program( ) protocols = [ - [wl_protocol_dir, 'unstable/text-input/text-input-unstable-v1.xml'], [hl_protocol_dir, 'protocols/hyprland-global-shortcuts-v1.xml'] ] @@ -55,6 +54,7 @@ new_protocols = [ [wl_protocol_dir, 'unstable/pointer-gestures/pointer-gestures-unstable-v1.xml'], [wl_protocol_dir, 'unstable/keyboard-shortcuts-inhibit/keyboard-shortcuts-inhibit-unstable-v1.xml'], [wl_protocol_dir, 'unstable/text-input/text-input-unstable-v3.xml'], + [wl_protocol_dir, 'unstable/text-input/text-input-unstable-v1.xml'], [wl_protocol_dir, 'unstable/pointer-constraints/pointer-constraints-unstable-v1.xml'], [wl_protocol_dir, 'staging/xdg-activation/xdg-activation-v1.xml'], [wl_protocol_dir, 'staging/ext-idle-notify/ext-idle-notify-v1.xml'], diff --git a/src/managers/ProtocolManager.cpp b/src/managers/ProtocolManager.cpp index 3704befb..d052e045 100644 --- a/src/managers/ProtocolManager.cpp +++ b/src/managers/ProtocolManager.cpp @@ -41,6 +41,7 @@ #include "../protocols/DRMSyncobj.hpp" #include "../protocols/Screencopy.hpp" #include "../protocols/ToplevelExport.hpp" +#include "../protocols/TextInputV1.hpp" #include "../protocols/core/Seat.hpp" #include "../protocols/core/DataDevice.hpp" @@ -125,6 +126,7 @@ CProtocolManager::CProtocolManager() { PROTO::pointerGestures = std::make_unique(&zwp_pointer_gestures_v1_interface, 3, "PointerGestures"); PROTO::foreignToplevelWlr = std::make_unique(&zwlr_foreign_toplevel_manager_v1_interface, 3, "ForeignToplevelWlr"); PROTO::shortcutsInhibit = std::make_unique(&zwp_keyboard_shortcuts_inhibit_manager_v1_interface, 1, "ShortcutsInhibit"); + PROTO::textInputV1 = std::make_unique(&zwp_text_input_manager_v1_interface, 1, "TextInputV1"); PROTO::textInputV3 = std::make_unique(&zwp_text_input_manager_v3_interface, 1, "TextInputV3"); PROTO::constraints = std::make_unique(&zwp_pointer_constraints_v1_interface, 1, "PointerConstraints"); PROTO::outputPower = std::make_unique(&zwlr_output_power_manager_v1_interface, 1, "OutputPower"); @@ -165,7 +167,6 @@ CProtocolManager::CProtocolManager() { // Old protocol implementations. // TODO: rewrite them to use hyprwayland-scanner. - m_pTextInputV1ProtocolManager = std::make_unique(); m_pGlobalShortcutsProtocolManager = std::make_unique(); } @@ -197,6 +198,7 @@ CProtocolManager::~CProtocolManager() { PROTO::pointerGestures.reset(); PROTO::foreignToplevelWlr.reset(); PROTO::shortcutsInhibit.reset(); + PROTO::textInputV1.reset(); PROTO::textInputV3.reset(); PROTO::constraints.reset(); PROTO::outputPower.reset(); diff --git a/src/managers/ProtocolManager.hpp b/src/managers/ProtocolManager.hpp index 62653e89..044a4d9b 100644 --- a/src/managers/ProtocolManager.hpp +++ b/src/managers/ProtocolManager.hpp @@ -1,7 +1,6 @@ #pragma once #include "../defines.hpp" -#include "../protocols/TextInputV1.hpp" #include "../protocols/GlobalShortcuts.hpp" #include "../helpers/Monitor.hpp" #include "../helpers/memory/Memory.hpp" @@ -14,7 +13,6 @@ class CProtocolManager { ~CProtocolManager(); // TODO: rewrite to use the new protocol framework - std::unique_ptr m_pTextInputV1ProtocolManager; std::unique_ptr m_pGlobalShortcutsProtocolManager; private: diff --git a/src/managers/input/InputMethodRelay.cpp b/src/managers/input/InputMethodRelay.cpp index f1fe6421..7cfd54b4 100644 --- a/src/managers/input/InputMethodRelay.cpp +++ b/src/managers/input/InputMethodRelay.cpp @@ -2,6 +2,7 @@ #include "InputManager.hpp" #include "../../Compositor.hpp" #include "../../protocols/TextInputV3.hpp" +#include "../../protocols/TextInputV1.hpp" #include "../../protocols/InputMethodV2.hpp" #include "../../protocols/core/Compositor.hpp" @@ -9,7 +10,8 @@ CInputMethodRelay::CInputMethodRelay() { static auto P = g_pHookSystem->hookDynamic("keyboardFocus", [&](void* self, SCallbackInfo& info, std::any param) { onKeyboardFocus(std::any_cast>(param)); }); - listeners.newTIV3 = PROTO::textInputV3->events.newTextInput.registerListener([this](std::any ti) { onNewTextInput(ti); }); + listeners.newTIV3 = PROTO::textInputV3->events.newTextInput.registerListener([this](std::any ti) { onNewTextInput(std::any_cast>(ti)); }); + listeners.newTIV1 = PROTO::textInputV1->events.newTextInput.registerListener([this](std::any ti) { onNewTextInput(std::any_cast>(ti)); }); listeners.newIME = PROTO::ime->events.newIME.registerListener([this](std::any ime) { onNewIME(std::any_cast>(ime)); }); } @@ -86,11 +88,11 @@ CTextInput* CInputMethodRelay::getFocusedTextInput() { return nullptr; } -void CInputMethodRelay::onNewTextInput(std::any tiv3) { - m_vTextInputs.emplace_back(std::make_unique(std::any_cast>(tiv3))); +void CInputMethodRelay::onNewTextInput(WP tiv3) { + m_vTextInputs.emplace_back(std::make_unique(tiv3)); } -void CInputMethodRelay::onNewTextInput(STextInputV1* pTIV1) { +void CInputMethodRelay::onNewTextInput(WP pTIV1) { m_vTextInputs.emplace_back(std::make_unique(pTIV1)); } diff --git a/src/managers/input/InputMethodRelay.hpp b/src/managers/input/InputMethodRelay.hpp index e13a1f1c..5ecc11a2 100644 --- a/src/managers/input/InputMethodRelay.hpp +++ b/src/managers/input/InputMethodRelay.hpp @@ -10,7 +10,7 @@ class CInputManager; class CHyprRenderer; -struct STextInputV1; +class CTextInputV1; class CInputMethodV2; class CInputMethodRelay { @@ -18,8 +18,8 @@ class CInputMethodRelay { CInputMethodRelay(); void onNewIME(SP); - void onNewTextInput(std::any tiv3); - void onNewTextInput(STextInputV1* pTIV1); + void onNewTextInput(WP tiv3); + void onNewTextInput(WP pTIV1); void activateIME(CTextInput* pInput); void deactivateIME(CTextInput* pInput); @@ -48,6 +48,7 @@ class CInputMethodRelay { struct { CHyprSignalListener newTIV3; + CHyprSignalListener newTIV1; CHyprSignalListener newIME; CHyprSignalListener commitIME; CHyprSignalListener destroyIME; diff --git a/src/managers/input/TextInput.cpp b/src/managers/input/TextInput.cpp index 635a8b01..5bff9fed 100644 --- a/src/managers/input/TextInput.cpp +++ b/src/managers/input/TextInput.cpp @@ -7,8 +7,7 @@ #include "../../protocols/InputMethodV2.hpp" #include "../../protocols/core/Compositor.hpp" -CTextInput::CTextInput(STextInputV1* ti) : pV1Input(ti) { - ti->pTextInput = this; +CTextInput::CTextInput(WP ti) : pV1Input(ti) { initCallbacks(); } @@ -16,17 +15,6 @@ CTextInput::CTextInput(WP ti) : pV3Input(ti) { initCallbacks(); } -CTextInput::~CTextInput() { - if (pV1Input) - pV1Input->pTextInput = nullptr; -} - -void CTextInput::tiV1Destroyed() { - pV1Input = nullptr; - - g_pInputManager->m_sIMERelay.removeTextInput(this); -} - void CTextInput::initCallbacks() { if (isV3()) { const auto INPUT = pV3Input.lock(); @@ -41,25 +29,19 @@ void CTextInput::initCallbacks() { g_pInputManager->m_sIMERelay.removeTextInput(this); }); } else { - hyprListener_textInputEnable.initCallback(&pV1Input->sEnable, [this](void* owner, void* data) { onEnabled(); }, this, "textInput"); + const auto INPUT = pV1Input.lock(); - hyprListener_textInputCommit.initCallback(&pV1Input->sCommit, [this](void* owner, void* data) { onCommit(); }, this, "textInput"); - - hyprListener_textInputDisable.initCallback(&pV1Input->sDisable, [this](void* owner, void* data) { onDisabled(); }, this, "textInput"); - - hyprListener_textInputDestroy.initCallback( - &pV1Input->sDestroy, - [this](void* owner, void* data) { - hyprListener_textInputCommit.removeCallback(); - hyprListener_textInputDestroy.removeCallback(); - hyprListener_textInputDisable.removeCallback(); - hyprListener_textInputEnable.removeCallback(); - listeners.surfaceUnmap.reset(); - listeners.surfaceDestroy.reset(); - - g_pInputManager->m_sIMERelay.removeTextInput(this); - }, - this, "textInput"); + listeners.enable = INPUT->events.enable.registerListener([this](std::any p) { + const auto SURFACE = std::any_cast>(p); + onEnabled(SURFACE); + }); + listeners.disable = INPUT->events.disable.registerListener([this](std::any p) { onDisabled(); }); + listeners.commit = INPUT->events.onCommit.registerListener([this](std::any p) { onCommit(); }); + listeners.destroy = INPUT->events.destroy.registerListener([this](std::any p) { + listeners.surfaceUnmap.reset(); + listeners.surfaceDestroy.reset(); + g_pInputManager->m_sIMERelay.removeTextInput(this); + }); } } @@ -149,7 +131,7 @@ void CTextInput::setFocusedSurface(SP pSurface) { } bool CTextInput::isV3() { - return !pV1Input; + return pV3Input && !pV1Input; } void CTextInput::enter(SP pSurface) { @@ -174,8 +156,7 @@ void CTextInput::enter(SP pSurface) { if (isV3()) pV3Input->enter(pSurface); else { - zwp_text_input_v1_send_enter(pV1Input->resourceImpl, pSurface->getResource()->resource()); - pV1Input->active = true; + pV1Input->enter(pSurface); } setFocusedSurface(pSurface); @@ -194,8 +175,7 @@ void CTextInput::leave() { if (isV3() && focusedSurface()) pV3Input->leave(focusedSurface()); else if (focusedSurface() && pV1Input) { - zwp_text_input_v1_send_leave(pV1Input->resourceImpl); - pV1Input->active = false; + pV1Input->leave(); } setFocusedSurface(nullptr); @@ -208,7 +188,7 @@ SP CTextInput::focusedSurface() { } wl_client* CTextInput::client() { - return isV3() ? pV3Input->client() : pV1Input->client; + return isV3() ? pV3Input->client() : pV1Input->client(); } void CTextInput::commitStateToIME(SP ime) { @@ -223,13 +203,15 @@ void CTextInput::commitStateToIME(SP ime) { if (INPUT->current.contentType.updated) ime->textContentType(INPUT->current.contentType.hint, INPUT->current.contentType.purpose); } else { - if (pV1Input->pendingSurrounding.isPending) - ime->surroundingText(pV1Input->pendingSurrounding.text, pV1Input->pendingSurrounding.cursor, pV1Input->pendingSurrounding.anchor); + const auto INPUT = pV1Input.lock(); + + if (INPUT->pendingSurrounding.isPending) + ime->surroundingText(INPUT->pendingSurrounding.text, INPUT->pendingSurrounding.cursor, INPUT->pendingSurrounding.anchor); ime->textChangeCause(ZWP_TEXT_INPUT_V3_CHANGE_CAUSE_INPUT_METHOD); if (pV1Input->pendingContentType.isPending) - ime->textContentType((zwpTextInputV3ContentHint)pV1Input->pendingContentType.hint, (zwpTextInputV3ContentPurpose)pV1Input->pendingContentType.purpose); + ime->textContentType((zwpTextInputV3ContentHint)INPUT->pendingContentType.hint, (zwpTextInputV3ContentPurpose)INPUT->pendingContentType.purpose); } g_pInputManager->m_sIMERelay.updateAllPopups(); @@ -252,25 +234,27 @@ void CTextInput::updateIMEState(SP ime) { INPUT->sendDone(); } else { + const auto INPUT = pV1Input.lock(); + if (ime->current.preeditString.committed) { - zwp_text_input_v1_send_preedit_cursor(pV1Input->resourceImpl, ime->current.preeditString.begin); - zwp_text_input_v1_send_preedit_styling(pV1Input->resourceImpl, 0, std::string(ime->current.preeditString.string).length(), ZWP_TEXT_INPUT_V1_PREEDIT_STYLE_HIGHLIGHT); - zwp_text_input_v1_send_preedit_string(pV1Input->resourceImpl, pV1Input->serial, ime->current.preeditString.string.c_str(), ""); + INPUT->preeditCursor(ime->current.preeditString.begin); + INPUT->preeditStyling(0, std::string(ime->current.preeditString.string).length(), ZWP_TEXT_INPUT_V1_PREEDIT_STYLE_HIGHLIGHT); + INPUT->preeditString(pV1Input->serial, ime->current.preeditString.string.c_str(), ""); } else { - zwp_text_input_v1_send_preedit_cursor(pV1Input->resourceImpl, ime->current.preeditString.begin); - zwp_text_input_v1_send_preedit_styling(pV1Input->resourceImpl, 0, 0, ZWP_TEXT_INPUT_V1_PREEDIT_STYLE_HIGHLIGHT); - zwp_text_input_v1_send_preedit_string(pV1Input->resourceImpl, pV1Input->serial, "", ""); + INPUT->preeditCursor(ime->current.preeditString.begin); + INPUT->preeditStyling(0, 0, ZWP_TEXT_INPUT_V1_PREEDIT_STYLE_HIGHLIGHT); + INPUT->preeditString(pV1Input->serial, "", ""); } if (ime->current.committedString.committed) - zwp_text_input_v1_send_commit_string(pV1Input->resourceImpl, pV1Input->serial, ime->current.committedString.string.c_str()); + INPUT->commitString(pV1Input->serial, ime->current.committedString.string.c_str()); if (ime->current.deleteSurrounding.committed) { - zwp_text_input_v1_send_delete_surrounding_text(pV1Input->resourceImpl, std::string(ime->current.preeditString.string).length() - ime->current.deleteSurrounding.before, - ime->current.deleteSurrounding.after + ime->current.deleteSurrounding.before); + INPUT->deleteSurroundingText(std::string(ime->current.preeditString.string).length() - ime->current.deleteSurrounding.before, + ime->current.deleteSurrounding.after + ime->current.deleteSurrounding.before); if (ime->current.preeditString.committed) - zwp_text_input_v1_send_commit_string(pV1Input->resourceImpl, pV1Input->serial, ime->current.preeditString.string.c_str()); + INPUT->commitString(pV1Input->serial, ime->current.preeditString.string.c_str()); } } } @@ -281,4 +265,4 @@ bool CTextInput::hasCursorRectangle() { CBox CTextInput::cursorBox() { return CBox{isV3() ? pV3Input->current.box.cursorBox : pV1Input->cursorRectangle}; -} \ No newline at end of file +} diff --git a/src/managers/input/TextInput.hpp b/src/managers/input/TextInput.hpp index 79e08af9..0f69866e 100644 --- a/src/managers/input/TextInput.hpp +++ b/src/managers/input/TextInput.hpp @@ -8,7 +8,7 @@ struct wl_client; -struct STextInputV1; +class CTextInputV1; class CTextInputV3; class CInputMethodV2; class CWLSurfaceResource; @@ -16,8 +16,7 @@ class CWLSurfaceResource; class CTextInput { public: CTextInput(WP ti); - CTextInput(STextInputV1* ti); - ~CTextInput(); + CTextInput(WP ti); bool isV3(); void enter(SP pSurface); @@ -43,12 +42,7 @@ class CTextInput { WP pFocusedSurface; int enterLocks = 0; WP pV3Input; - STextInputV1* pV1Input = nullptr; - - DYNLISTENER(textInputEnable); - DYNLISTENER(textInputDisable); - DYNLISTENER(textInputCommit); - DYNLISTENER(textInputDestroy); + WP pV1Input; struct { CHyprSignalListener enable; @@ -58,4 +52,4 @@ class CTextInput { CHyprSignalListener surfaceUnmap; CHyprSignalListener surfaceDestroy; } listeners; -}; \ No newline at end of file +}; diff --git a/src/protocols/TextInputV1.cpp b/src/protocols/TextInputV1.cpp index 12068671..78e910cb 100644 --- a/src/protocols/TextInputV1.cpp +++ b/src/protocols/TextInputV1.cpp @@ -3,228 +3,125 @@ #include "../Compositor.hpp" #include "core/Compositor.hpp" -#define TEXT_INPUT_VERSION 1 +#define LOGM PROTO::textInputV1->protoLog -static void bindManagerInt(wl_client* client, void* data, uint32_t version, uint32_t id) { - g_pProtocolManager->m_pTextInputV1ProtocolManager->bindManager(client, data, version, id); +CTextInputV1::~CTextInputV1() { + events.destroy.emit(); } -static void handleDisplayDestroy(struct wl_listener* listener, void* data) { - CTextInputV1ProtocolManager* proto = wl_container_of(listener, proto, m_liDisplayDestroy); - proto->displayDestroy(); -} - -void CTextInputV1ProtocolManager::displayDestroy() { - wl_list_remove(&m_liDisplayDestroy.link); - wl_list_init(&m_liDisplayDestroy.link); - wl_global_destroy(m_pGlobal); -} - -CTextInputV1ProtocolManager::~CTextInputV1ProtocolManager() { - displayDestroy(); -} - -CTextInputV1ProtocolManager::CTextInputV1ProtocolManager() { - m_pGlobal = wl_global_create(g_pCompositor->m_sWLDisplay, &zwp_text_input_manager_v1_interface, TEXT_INPUT_VERSION, this, bindManagerInt); - - if (!m_pGlobal) { - Debug::log(ERR, "TextInputV1Manager could not start!"); - return; - } - - m_liDisplayDestroy.notify = handleDisplayDestroy; - wl_display_add_destroy_listener(g_pCompositor->m_sWLDisplay, &m_liDisplayDestroy); - - Debug::log(LOG, "TextInputV1Manager started successfully!"); -} - -static void createTI(wl_client* client, wl_resource* resource, uint32_t id) { - g_pProtocolManager->m_pTextInputV1ProtocolManager->createTI(client, resource, id); -} - -static const struct zwp_text_input_manager_v1_interface textInputManagerImpl = { - .create_text_input = createTI, -}; - -void CTextInputV1ProtocolManager::bindManager(wl_client* client, void* data, uint32_t version, uint32_t id) { - const auto RESOURCE = wl_resource_create(client, &zwp_text_input_manager_v1_interface, version, id); - wl_resource_set_implementation(RESOURCE, &textInputManagerImpl, this, nullptr); - - Debug::log(LOG, "TextInputV1Manager bound successfully!"); -} - -// - -static void handleActivate(wl_client* client, wl_resource* resource, wl_resource* seat, wl_resource* surface) { - g_pProtocolManager->m_pTextInputV1ProtocolManager->handleActivate(client, resource, seat, surface); -} - -static void handleDeactivate(wl_client* client, wl_resource* resource, wl_resource* seat) { - g_pProtocolManager->m_pTextInputV1ProtocolManager->handleDeactivate(client, resource, seat); -} - -static void handleShowInputPanel(wl_client* client, wl_resource* resource) { - g_pProtocolManager->m_pTextInputV1ProtocolManager->handleShowInputPanel(client, resource); -} - -static void handleHideInputPanel(wl_client* client, wl_resource* resource) { - g_pProtocolManager->m_pTextInputV1ProtocolManager->handleHideInputPanel(client, resource); -} - -static void handleReset(wl_client* client, wl_resource* resource) { - g_pProtocolManager->m_pTextInputV1ProtocolManager->handleReset(client, resource); -} - -static void handleSetSurroundingText(wl_client* client, wl_resource* resource, const char* text, uint32_t cursor, uint32_t anchor) { - g_pProtocolManager->m_pTextInputV1ProtocolManager->handleSetSurroundingText(client, resource, text, cursor, anchor); -} - -static void handleSetContentType(wl_client* client, wl_resource* resource, uint32_t hint, uint32_t purpose) { - g_pProtocolManager->m_pTextInputV1ProtocolManager->handleSetContentType(client, resource, hint, purpose); -} - -static void handleSetCursorRectangle(wl_client* client, wl_resource* resource, int32_t x, int32_t y, int32_t width, int32_t height) { - g_pProtocolManager->m_pTextInputV1ProtocolManager->handleSetCursorRectangle(client, resource, x, y, width, height); -} - -static void handleSetPreferredLanguage(wl_client* client, wl_resource* resource, const char* language) { - g_pProtocolManager->m_pTextInputV1ProtocolManager->handleSetPreferredLanguage(client, resource, language); -} - -static void handleCommitState(wl_client* client, wl_resource* resource, uint32_t serial) { - g_pProtocolManager->m_pTextInputV1ProtocolManager->handleCommitState(client, resource, serial); -} - -static void handleInvokeAction(wl_client* client, wl_resource* resource, uint32_t button, uint32_t index) { - g_pProtocolManager->m_pTextInputV1ProtocolManager->handleInvokeAction(client, resource, button, index); -} - -static const struct zwp_text_input_v1_interface textInputImpl = { - .activate = handleActivate, - .deactivate = handleDeactivate, - .show_input_panel = handleShowInputPanel, - .hide_input_panel = handleHideInputPanel, - .reset = handleReset, - .set_surrounding_text = handleSetSurroundingText, - .set_content_type = handleSetContentType, - .set_cursor_rectangle = handleSetCursorRectangle, - .set_preferred_language = handleSetPreferredLanguage, - .commit_state = handleCommitState, - .invoke_action = handleInvokeAction, -}; - -void CTextInputV1ProtocolManager::removeTI(STextInputV1* pTI) { - const auto TI = std::find_if(m_pClients.begin(), m_pClients.end(), [&](const auto& other) { return other->resourceCaller == pTI->resourceCaller; }); - if (TI == m_pClients.end()) +CTextInputV1::CTextInputV1(SP resource_) : resource(resource_) { + if (!good()) return; - // if ((*TI)->resourceImpl) - // wl_resource_destroy((*TI)->resourceImpl); + resource->setOnDestroy([this](CZwpTextInputV1* pMgr) { PROTO::textInputV1->destroyResource(this); }); - std::erase_if(m_pClients, [&](const auto& other) { return other.get() == pTI; }); + resource->setActivate([this](CZwpTextInputV1* pMgr, wl_resource* seat, wl_resource* surface) { + if (!surface) { + LOGM(WARN, "Text-input-v1 PTI{:x}: No surface to activate text input on!", (uintptr_t)this); + return; + } + + active = true; + events.enable.emit(CWLSurfaceResource::fromResource(surface)); + }); + + resource->setDeactivate([this](CZwpTextInputV1* pMgr, wl_resource* seat) { + active = false; + events.disable.emit(); + }); + + resource->setReset([this](CZwpTextInputV1* pMgr) { + pendingSurrounding.isPending = false; + pendingContentType.isPending = false; + }); + + resource->setSetSurroundingText( + [this](CZwpTextInputV1* pMgr, const char* text, uint32_t cursor, uint32_t anchor) { pendingSurrounding = {true, std::string(text), cursor, anchor}; }); + + resource->setSetContentType([this](CZwpTextInputV1* pMgr, uint32_t hint, uint32_t purpose) { + pendingContentType = {true, hint == (uint32_t)ZWP_TEXT_INPUT_V1_CONTENT_HINT_DEFAULT ? (uint32_t)ZWP_TEXT_INPUT_V1_CONTENT_HINT_NONE : hint, + purpose > (uint32_t)ZWP_TEXT_INPUT_V1_CONTENT_PURPOSE_PASSWORD ? hint + 1 : hint}; + }); + + resource->setSetCursorRectangle([this](CZwpTextInputV1* pMgr, int32_t x, int32_t y, int32_t width, int32_t height) { cursorRectangle = CBox{x, y, width, height}; }); + + resource->setCommitState([this](CZwpTextInputV1* pMgr, uint32_t serial_) { + serial = serial_; + events.onCommit.emit(); + }); + + // nothing + resource->setShowInputPanel([this](CZwpTextInputV1* pMgr) {}); + resource->setHideInputPanel([this](CZwpTextInputV1* pMgr) {}); + resource->setSetPreferredLanguage([this](CZwpTextInputV1* pMgr, const char* language) {}); + resource->setInvokeAction([this](CZwpTextInputV1* pMgr, uint32_t button, uint32_t index) {}); } -STextInputV1* tiFromResource(wl_resource* resource) { - ASSERT(wl_resource_instance_of(resource, &zwp_text_input_v1_interface, &textInputImpl)); - return (STextInputV1*)wl_resource_get_user_data(resource); +bool CTextInputV1::good() { + return resource->resource(); } -static void destroyTI(wl_resource* resource) { - const auto TI = tiFromResource(resource); - - if (!TI) - return; - - if (TI->resourceImpl) { - wl_resource_set_user_data(resource, nullptr); - } - - TI->pTextInput->tiV1Destroyed(); - - g_pProtocolManager->m_pTextInputV1ProtocolManager->removeTI(TI); +wl_client* CTextInputV1::client() { + return resource->client(); } -void CTextInputV1ProtocolManager::createTI(wl_client* client, wl_resource* resource, uint32_t id) { - const auto PTI = m_pClients.emplace_back(std::make_unique()).get(); - Debug::log(LOG, "New TI V1 at {:x}", (uintptr_t)PTI); - - PTI->client = client; - PTI->resourceCaller = resource; - PTI->resourceImpl = wl_resource_create(client, &zwp_text_input_v1_interface, TEXT_INPUT_VERSION, id); - - if (!PTI->resourceImpl) { - Debug::log(ERR, "Could not alloc wl_resource for TIV1"); - removeTI(PTI); - return; - } - - wl_resource_set_implementation(PTI->resourceImpl, &textInputImpl, PTI, &destroyTI); - wl_resource_set_user_data(PTI->resourceImpl, PTI); - - wl_signal_init(&PTI->sEnable); - wl_signal_init(&PTI->sDisable); - wl_signal_init(&PTI->sDestroy); - wl_signal_init(&PTI->sCommit); - - g_pInputManager->m_sIMERelay.onNewTextInput(PTI); +void CTextInputV1::enter(SP surface) { + resource->sendEnter(surface->getResource()->resource()); + active = true; } -void CTextInputV1ProtocolManager::handleActivate(wl_client* client, wl_resource* resource, wl_resource* seat, wl_resource* surface) { - const auto PTI = tiFromResource(resource); - if (!surface) { - Debug::log(WARN, "Text-input-v1 PTI{:x}: No surface to activate text input on!", (uintptr_t)PTI); - return; - } - PTI->active = true; - PTI->pTextInput->onEnabled(CWLSurfaceResource::fromResource(surface)); +void CTextInputV1::leave() { + resource->sendLeave(); + active = false; } -void CTextInputV1ProtocolManager::handleDeactivate(wl_client* client, wl_resource* resource, wl_resource* seat) { - const auto PTI = tiFromResource(resource); - PTI->active = false; - PTI->pTextInput->onDisabled(); +void CTextInputV1::preeditCursor(int32_t index) { + resource->sendPreeditCursor(index); } -void CTextInputV1ProtocolManager::handleShowInputPanel(wl_client* client, wl_resource* resource) { +void CTextInputV1::preeditStyling(uint32_t index, uint32_t length, zwpTextInputV1PreeditStyle style) { + resource->sendPreeditStyling(index, length, style); +} + +void CTextInputV1::preeditString(uint32_t serial, const char* text, const char* commit) { + resource->sendPreeditString(serial, text, commit); +} + +void CTextInputV1::commitString(uint32_t serial, const char* text) { + resource->sendCommitString(serial, text); +} + +void CTextInputV1::deleteSurroundingText(int32_t index, uint32_t length) { + resource->sendDeleteSurroundingText(index, length); +} + +CTextInputV1Protocol::CTextInputV1Protocol(const wl_interface* iface, const int& ver, const std::string& name) : IWaylandProtocol(iface, ver, name) { ; } -void CTextInputV1ProtocolManager::handleHideInputPanel(wl_client* client, wl_resource* resource) { - ; +void CTextInputV1Protocol::bindManager(wl_client* client, void* data, uint32_t ver, uint32_t id) { + const auto RESOURCE = m_vManagers.emplace_back(makeShared(client, ver, id)); + + RESOURCE->setOnDestroy([this](CZwpTextInputManagerV1* pMgr) { PROTO::textInputV1->destroyResource(pMgr); }); + RESOURCE->setCreateTextInput([this](CZwpTextInputManagerV1* pMgr, uint32_t id) { + const auto PTI = m_vClients.emplace_back(makeShared(makeShared(pMgr->client(), pMgr->version(), id))); + LOGM(LOG, "New TI V1 at {:x}", (uintptr_t)PTI.get()); + + if (!PTI->good()) { + LOGM(ERR, "Could not alloc wl_resource for TIV1"); + pMgr->noMemory(); + PROTO::textInputV1->destroyResource(PTI.get()); + return; + } + + events.newTextInput.emit(WP(PTI)); + }); } -void CTextInputV1ProtocolManager::handleReset(wl_client* client, wl_resource* resource) { - const auto PTI = tiFromResource(resource); - PTI->pendingSurrounding.isPending = false; - PTI->pendingContentType.isPending = false; +void CTextInputV1Protocol::destroyResource(CTextInputV1* client) { + std::erase_if(m_vClients, [&](const auto& other) { return other.get() == client; }); } -void CTextInputV1ProtocolManager::handleSetSurroundingText(wl_client* client, wl_resource* resource, const char* text, uint32_t cursor, uint32_t anchor) { - const auto PTI = tiFromResource(resource); - PTI->pendingSurrounding = {true, std::string(text), cursor, anchor}; -} - -void CTextInputV1ProtocolManager::handleSetContentType(wl_client* client, wl_resource* resource, uint32_t hint, uint32_t purpose) { - const auto PTI = tiFromResource(resource); - PTI->pendingContentType = {true, hint == (uint32_t)ZWP_TEXT_INPUT_V1_CONTENT_HINT_DEFAULT ? (uint32_t)ZWP_TEXT_INPUT_V1_CONTENT_HINT_NONE : hint, - purpose > (uint32_t)ZWP_TEXT_INPUT_V1_CONTENT_PURPOSE_PASSWORD ? hint + 1 : hint}; -} - -void CTextInputV1ProtocolManager::handleSetCursorRectangle(wl_client* client, wl_resource* resource, int32_t x, int32_t y, int32_t width, int32_t height) { - const auto PTI = tiFromResource(resource); - PTI->cursorRectangle = CBox{x, y, width, height}; -} - -void CTextInputV1ProtocolManager::handleSetPreferredLanguage(wl_client* client, wl_resource* resource, const char* language) { - ; -} - -void CTextInputV1ProtocolManager::handleCommitState(wl_client* client, wl_resource* resource, uint32_t serial) { - const auto PTI = tiFromResource(resource); - PTI->serial = serial; - PTI->pTextInput->onCommit(); -} - -void CTextInputV1ProtocolManager::handleInvokeAction(wl_client* client, wl_resource* resource, uint32_t button, uint32_t index) { - ; +void CTextInputV1Protocol::destroyResource(CZwpTextInputManagerV1* client) { + std::erase_if(m_vManagers, [&](const auto& other) { return other.get() == client; }); } diff --git a/src/protocols/TextInputV1.hpp b/src/protocols/TextInputV1.hpp index e56a8990..c85a1f31 100644 --- a/src/protocols/TextInputV1.hpp +++ b/src/protocols/TextInputV1.hpp @@ -1,28 +1,44 @@ #pragma once #include "../defines.hpp" -#include "text-input-unstable-v1-protocol.h" +#include "../protocols/core/Compositor.hpp" +#include "text-input-unstable-v1.hpp" +#include "WaylandProtocol.hpp" #include class CTextInput; -struct STextInputV1 { - wl_client* client = nullptr; - wl_resource* resourceCaller = nullptr; +class CTextInputV1 { + public: + CTextInputV1(SP resource); + ~CTextInputV1(); - wl_resource* resourceImpl = nullptr; + void enter(SP surface); + void leave(); - CTextInput* pTextInput = nullptr; + void preeditCursor(int32_t index); + void preeditStyling(uint32_t index, uint32_t length, zwpTextInputV1PreeditStyle style); + void preeditString(uint32_t serial, const char* text, const char* commit); + void commitString(uint32_t serial, const char* text); + void deleteSurroundingText(int32_t index, uint32_t length); - wl_signal sEnable; - wl_signal sDisable; - wl_signal sCommit; - wl_signal sDestroy; + bool good(); + wl_client* client(); - uint32_t serial = 0; + private: + SP resource; + WP self; - bool active = false; + uint32_t serial = 0; + bool active = false; + + struct { + CSignal onCommit; + CSignal enable; + CSignal disable; + CSignal destroy; + } events; struct SPendingSurr { bool isPending = false; @@ -39,39 +55,29 @@ struct STextInputV1 { CBox cursorRectangle = {0, 0, 0, 0}; - bool operator==(const STextInputV1& other) { - return other.client == client && other.resourceCaller == resourceCaller && other.resourceImpl == resourceImpl; - } + friend class CTextInput; + friend class CTextInputV1Protocol; }; -class CTextInputV1ProtocolManager { +class CTextInputV1Protocol : IWaylandProtocol { public: - CTextInputV1ProtocolManager(); - ~CTextInputV1ProtocolManager(); + CTextInputV1Protocol(const wl_interface* iface, const int& ver, const std::string& name); - void bindManager(wl_client* client, void* data, uint32_t version, uint32_t id); - void createTI(wl_client* client, wl_resource* resource, uint32_t id); - void removeTI(STextInputV1* pTI); + virtual void bindManager(wl_client* client, void* data, uint32_t version, uint32_t id); + void destroyResource(CTextInputV1* resource); + void destroyResource(CZwpTextInputManagerV1* client); - void displayDestroy(); - - // handlers for tiv1 - void handleActivate(wl_client* client, wl_resource* resource, wl_resource* seat, wl_resource* surface); - void handleDeactivate(wl_client* client, wl_resource* resource, wl_resource* seat); - void handleShowInputPanel(wl_client* client, wl_resource* resource); - void handleHideInputPanel(wl_client* client, wl_resource* resource); - void handleReset(wl_client* client, wl_resource* resource); - void handleSetSurroundingText(wl_client* client, wl_resource* resource, const char* text, uint32_t cursor, uint32_t anchor); - void handleSetContentType(wl_client* client, wl_resource* resource, uint32_t hint, uint32_t purpose); - void handleSetCursorRectangle(wl_client* client, wl_resource* resource, int32_t x, int32_t y, int32_t width, int32_t height); - void handleSetPreferredLanguage(wl_client* client, wl_resource* resource, const char* language); - void handleCommitState(wl_client* client, wl_resource* resource, uint32_t serial); - void handleInvokeAction(wl_client* client, wl_resource* resource, uint32_t button, uint32_t index); - - wl_listener m_liDisplayDestroy; + struct { + CSignal newTextInput; // WP + } events; private: - wl_global* m_pGlobal = nullptr; + std::vector> m_vManagers; + std::vector> m_vClients; - std::vector> m_pClients; + friend class CTextInputV1; +}; + +namespace PROTO { + inline UP textInputV1; }; diff --git a/src/protocols/VirtualPointer.hpp b/src/protocols/VirtualPointer.hpp index 1a51d977..7ee450dc 100644 --- a/src/protocols/VirtualPointer.hpp +++ b/src/protocols/VirtualPointer.hpp @@ -8,6 +8,7 @@ #include "wlr-virtual-pointer-unstable-v1.hpp" #include "../helpers/signal/Signal.hpp" #include "../devices/IPointer.hpp" +#include "../helpers/Monitor.hpp" class CVirtualPointerV1Resource { public: From 9c38b0fdbe32dc2cb81d53c9be90113d114f1cd2 Mon Sep 17 00:00:00 2001 From: Tom Englund Date: Mon, 29 Jul 2024 19:19:47 +0200 Subject: [PATCH 0200/2181] core: add a destructor to CHyprOpenglImpl and avoid wl_container_of undefined behaviour (#7101) * protocols: avoid undefined behaviour in C macro to safely use wl_container_of with a class the class has to be no virtual functions, no inheritance, and uniform access control (e.g all public) work around this by putting this into a destroywrapper struct. * opengl: clean memory on destruction add a destructor and free the allocated memory and close the fd --- src/protocols/GlobalShortcuts.cpp | 13 ++++++++----- src/protocols/GlobalShortcuts.hpp | 8 +++++++- src/protocols/WaylandProtocol.cpp | 13 ++++++++----- src/protocols/WaylandProtocol.hpp | 8 +++++++- src/render/OpenGL.cpp | 16 ++++++++++++++++ src/render/OpenGL.hpp | 1 + 6 files changed, 47 insertions(+), 12 deletions(-) diff --git a/src/protocols/GlobalShortcuts.cpp b/src/protocols/GlobalShortcuts.cpp index 898f0e07..7eb84be6 100644 --- a/src/protocols/GlobalShortcuts.cpp +++ b/src/protocols/GlobalShortcuts.cpp @@ -8,13 +8,14 @@ static void bindManagerInt(wl_client* client, void* data, uint32_t version, uint } static void handleDisplayDestroy(struct wl_listener* listener, void* data) { - CGlobalShortcutsProtocolManager* proto = wl_container_of(listener, proto, m_liDisplayDestroy); + CGlobalShortcutsProtocolManagerDestroyWrapper* wrap = wl_container_of(listener, wrap, listener); + CGlobalShortcutsProtocolManager* proto = wrap->parent; proto->displayDestroy(); } void CGlobalShortcutsProtocolManager::displayDestroy() { - wl_list_remove(&m_liDisplayDestroy.link); - wl_list_init(&m_liDisplayDestroy.link); + wl_list_remove(&m_liDisplayDestroy.listener.link); + wl_list_init(&m_liDisplayDestroy.listener.link); wl_global_destroy(m_pGlobal); } @@ -30,8 +31,10 @@ CGlobalShortcutsProtocolManager::CGlobalShortcutsProtocolManager() { return; } - m_liDisplayDestroy.notify = handleDisplayDestroy; - wl_display_add_destroy_listener(g_pCompositor->m_sWLDisplay, &m_liDisplayDestroy); + wl_list_init(&m_liDisplayDestroy.listener.link); + m_liDisplayDestroy.listener.notify = handleDisplayDestroy; + m_liDisplayDestroy.parent = this; + wl_display_add_destroy_listener(g_pCompositor->m_sWLDisplay, &m_liDisplayDestroy.listener); Debug::log(LOG, "GlobalShortcutsManager started successfully!"); } diff --git a/src/protocols/GlobalShortcuts.hpp b/src/protocols/GlobalShortcuts.hpp index 5fd03465..7e512021 100644 --- a/src/protocols/GlobalShortcuts.hpp +++ b/src/protocols/GlobalShortcuts.hpp @@ -14,6 +14,12 @@ struct SShortcutClient { std::vector> shortcuts; }; +class CGlobalShortcutsProtocolManager; +struct CGlobalShortcutsProtocolManagerDestroyWrapper { + wl_listener listener; + CGlobalShortcutsProtocolManager* parent = nullptr; +}; + class CGlobalShortcutsProtocolManager { public: CGlobalShortcutsProtocolManager(); @@ -31,7 +37,7 @@ class CGlobalShortcutsProtocolManager { std::vector getAllShortcuts(); - wl_listener m_liDisplayDestroy; + CGlobalShortcutsProtocolManagerDestroyWrapper m_liDisplayDestroy; private: std::vector> m_vClients; diff --git a/src/protocols/WaylandProtocol.cpp b/src/protocols/WaylandProtocol.cpp index 71c43300..954f160d 100644 --- a/src/protocols/WaylandProtocol.cpp +++ b/src/protocols/WaylandProtocol.cpp @@ -6,13 +6,14 @@ static void bindManagerInternal(wl_client* client, void* data, uint32_t ver, uin } static void displayDestroyInternal(struct wl_listener* listener, void* data) { - IWaylandProtocol* proto = wl_container_of(listener, proto, m_liDisplayDestroy); + IWaylandProtocolDestroyWrapper* wrap = wl_container_of(listener, wrap, listener); + IWaylandProtocol* proto = wrap->parent; proto->onDisplayDestroy(); } void IWaylandProtocol::onDisplayDestroy() { - wl_list_remove(&m_liDisplayDestroy.link); - wl_list_init(&m_liDisplayDestroy.link); + wl_list_remove(&m_liDisplayDestroy.listener.link); + wl_list_init(&m_liDisplayDestroy.listener.link); wl_global_destroy(m_pGlobal); } @@ -24,8 +25,10 @@ IWaylandProtocol::IWaylandProtocol(const wl_interface* iface, const int& ver, co return; } - m_liDisplayDestroy.notify = displayDestroyInternal; - wl_display_add_destroy_listener(g_pCompositor->m_sWLDisplay, &m_liDisplayDestroy); + wl_list_init(&m_liDisplayDestroy.listener.link); + m_liDisplayDestroy.listener.notify = displayDestroyInternal; + m_liDisplayDestroy.parent = this; + wl_display_add_destroy_listener(g_pCompositor->m_sWLDisplay, &m_liDisplayDestroy.listener); protoLog(LOG, "Registered global"); } diff --git a/src/protocols/WaylandProtocol.hpp b/src/protocols/WaylandProtocol.hpp index 6154fa30..4d4e7925 100644 --- a/src/protocols/WaylandProtocol.hpp +++ b/src/protocols/WaylandProtocol.hpp @@ -11,6 +11,12 @@ #define PROTO NProtocols +class IWaylandProtocol; +struct IWaylandProtocolDestroyWrapper { + wl_listener listener; + IWaylandProtocol* parent = nullptr; +}; + class IWaylandProtocol { public: IWaylandProtocol(const wl_interface* iface, const int& ver, const std::string& name); @@ -26,7 +32,7 @@ class IWaylandProtocol { Debug::log(level, std::format("[{}] ", m_szName) + std::vformat(fmt.get(), std::make_format_args(args...))); }; - wl_listener m_liDisplayDestroy; + IWaylandProtocolDestroyWrapper m_liDisplayDestroy; private: std::string m_szName; diff --git a/src/render/OpenGL.cpp b/src/render/OpenGL.cpp index 43a2c3a7..b925fcc9 100644 --- a/src/render/OpenGL.cpp +++ b/src/render/OpenGL.cpp @@ -345,6 +345,22 @@ CHyprOpenGLImpl::CHyprOpenGLImpl() { m_tGlobalTimer.reset(); } +CHyprOpenGLImpl::~CHyprOpenGLImpl() { + if (m_pEglDisplay && m_pEglContext != EGL_NO_CONTEXT) + eglDestroyContext(m_pEglDisplay, m_pEglContext); + + if (m_pEglDisplay) + eglTerminate(m_pEglDisplay); + + eglReleaseThread(); + + if (m_pGbmDevice) + gbm_device_destroy(m_pGbmDevice); + + if (m_iGBMFD >= 0) + close(m_iGBMFD); +} + std::optional> CHyprOpenGLImpl::getModsForFormat(EGLint format) { // TODO: return std::expected when clang supports it diff --git a/src/render/OpenGL.hpp b/src/render/OpenGL.hpp index 41e80ee5..1e8325c1 100644 --- a/src/render/OpenGL.hpp +++ b/src/render/OpenGL.hpp @@ -145,6 +145,7 @@ class CGradientValueData; class CHyprOpenGLImpl { public: CHyprOpenGLImpl(); + ~CHyprOpenGLImpl(); void begin(CMonitor*, const CRegion& damage, CFramebuffer* fb = nullptr, std::optional finalDamage = {}); void beginSimple(CMonitor*, const CRegion& damage, SP rb = nullptr, CFramebuffer* fb = nullptr); From e67322034037fef22079c8e480be38c1d04b5a4a Mon Sep 17 00:00:00 2001 From: Vaxry Date: Mon, 29 Jul 2024 19:02:58 +0200 Subject: [PATCH 0201/2181] core/surface: fixup a few pointer handling edge cases --- src/managers/PointerManager.cpp | 4 ++++ src/protocols/core/Compositor.cpp | 10 ++++++++-- src/protocols/core/Compositor.hpp | 1 + 3 files changed, 13 insertions(+), 2 deletions(-) diff --git a/src/managers/PointerManager.cpp b/src/managers/PointerManager.cpp index a09992a2..a405e2eb 100644 --- a/src/managers/PointerManager.cpp +++ b/src/managers/PointerManager.cpp @@ -151,6 +151,8 @@ void CPointerManager::setCursorSurface(SP surf, const Vector2D& hots currentCursorImage.surface = surf; currentCursorImage.scale = surf->resource()->current.scale; + surf->resource()->map(); + currentCursorImage.destroySurface = surf->events.destroy.registerListener([this](std::any data) { resetCursorImage(); }); currentCursorImage.commitSurface = surf->resource()->events.commit.registerListener([this](std::any data) { damageIfSoftware(); @@ -222,6 +224,8 @@ void CPointerManager::resetCursorImage(bool apply) { currentCursorImage.surface->resource()->leave(m); } + currentCursorImage.surface->resource()->unmap(); + currentCursorImage.destroySurface.reset(); currentCursorImage.commitSurface.reset(); currentCursorImage.surface.reset(); diff --git a/src/protocols/core/Compositor.cpp b/src/protocols/core/Compositor.cpp index 6352b7e6..43d3059b 100644 --- a/src/protocols/core/Compositor.cpp +++ b/src/protocols/core/Compositor.cpp @@ -156,6 +156,7 @@ void CWLSurfaceResource::destroy() { unmap(); } events.destroy.emit(); + releaseBuffers(false); PROTO::compositor->destroyResource(this); } @@ -338,13 +339,18 @@ void CWLSurfaceResource::unmap() { // release the buffers. // this is necessary for XWayland to function correctly, // as it does not unmap via the traditional commit(null buffer) method, but via the X11 protocol. + releaseBuffers(); +} + +void CWLSurfaceResource::releaseBuffers(bool onlyCurrent) { if (current.buffer && !current.buffer->resource->released) current.buffer->sendRelease(); - if (pending.buffer && !pending.buffer->resource->released) + if (pending.buffer && !pending.buffer->resource->released && !onlyCurrent) pending.buffer->sendRelease(); pending.buffer.reset(); - current.buffer.reset(); + if (!onlyCurrent) + current.buffer.reset(); } void CWLSurfaceResource::error(int code, const std::string& str) { diff --git a/src/protocols/core/Compositor.hpp b/src/protocols/core/Compositor.hpp index 1fa6926a..79cd1de6 100644 --- a/src/protocols/core/Compositor.hpp +++ b/src/protocols/core/Compositor.hpp @@ -137,6 +137,7 @@ class CWLSurfaceResource { int stateLocks = 0; void destroy(); + void releaseBuffers(bool onlyCurrent = true); void commitPendingState(); void bfHelper(std::vector> nodes, std::function, const Vector2D&, void*)> fn, void* data); }; From 743e98f0c0c2de63a0715f7112dade3a819a8307 Mon Sep 17 00:00:00 2001 From: Vaxry Date: Tue, 30 Jul 2024 11:54:28 +0200 Subject: [PATCH 0202/2181] hyprpm: add short error code explanations --- hyprpm/src/core/PluginManager.cpp | 15 ++++++++++++++- hyprpm/src/core/PluginManager.hpp | 1 + 2 files changed, 15 insertions(+), 1 deletion(-) diff --git a/hyprpm/src/core/PluginManager.cpp b/hyprpm/src/core/PluginManager.cpp index edb98812..15ce87f7 100644 --- a/hyprpm/src/core/PluginManager.cpp +++ b/hyprpm/src/core/PluginManager.cpp @@ -529,7 +529,8 @@ bool CPluginManager::updateHeaders(bool force) { std::cout << "\n"; } else { - progress.printMessageAbove(std::string{Colors::RED} + "✖" + Colors::RESET + " failed to install headers with error code " + std::to_string((int)HEADERSVALID)); + progress.printMessageAbove(std::string{Colors::RED} + "✖" + Colors::RESET + " failed to install headers with error code " + std::to_string((int)HEADERSVALID) + " (" + + headerErrorShort(HEADERSVALID) + ")"); progress.m_iSteps = 5; progress.m_szCurrentMessage = "Failed"; progress.print(); @@ -880,6 +881,18 @@ std::string CPluginManager::headerError(const eHeadersErrors err) { return std::string{Colors::RED} + "✖" + Colors::RESET + " Unknown header error. Please run hyprpm update to fix those.\n"; } +std::string CPluginManager::headerErrorShort(const eHeadersErrors err) { + switch (err) { + case HEADERS_CORRUPTED: return "Headers corrupted"; + case HEADERS_MISMATCHED: return "Headers version mismatched"; + case HEADERS_NOT_HYPRLAND: return "Not running on Hyprland"; + case HEADERS_MISSING: return "Headers missing"; + case HEADERS_DUPLICATED: return "Headers duplicated"; + default: break; + } + return "?"; +} + bool CPluginManager::hasDeps() { std::vector deps = {"meson", "cpio", "cmake"}; for (auto& d : deps) { diff --git a/hyprpm/src/core/PluginManager.hpp b/hyprpm/src/core/PluginManager.hpp index 13ea5b12..c16a9d0f 100644 --- a/hyprpm/src/core/PluginManager.hpp +++ b/hyprpm/src/core/PluginManager.hpp @@ -66,6 +66,7 @@ class CPluginManager { private: std::string headerError(const eHeadersErrors err); + std::string headerErrorShort(const eHeadersErrors err); std::string m_szWorkingPluginDirectory = ""; }; From 68ee4dda5e4f4ce719bc814b873deca73f3d5eba Mon Sep 17 00:00:00 2001 From: Vaxry Date: Tue, 30 Jul 2024 12:05:23 +0200 Subject: [PATCH 0203/2181] hyprpm: warn about uncheckoutable commits --- hyprpm/src/core/PluginManager.cpp | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/hyprpm/src/core/PluginManager.cpp b/hyprpm/src/core/PluginManager.cpp index 15ce87f7..a29afad7 100644 --- a/hyprpm/src/core/PluginManager.cpp +++ b/hyprpm/src/core/PluginManager.cpp @@ -464,8 +464,18 @@ bool CPluginManager::updateHeaders(bool force) { progress.m_szCurrentMessage = "Checking out sources"; progress.print(); + if (m_bVerbose) + progress.printMessageAbove(std::string{Colors::BLUE} + "[v] " + Colors::RESET + "will run: " + "cd " + WORKINGDIR + " && git checkout " + HLVER.hash + " 2>&1"); + ret = execAndGet("cd " + WORKINGDIR + " && git checkout " + HLVER.hash + " 2>&1"); + if (ret.contains("fatal: unable to read tree")) { + std::cerr << "\n" + << Colors::RED << "✖" << Colors::RESET + << " Could not checkout the running Hyprland commit. If you are on -git, try updating.\nYou can also try re-running hyprpm update with --no-shallow.\n"; + return false; + } + if (m_bVerbose) progress.printMessageAbove(std::string{Colors::BLUE} + "[v] " + Colors::RESET + "git returned (co): " + ret); From 46c6efeab39cae0e709a2a29d299dd4dfab36a8c Mon Sep 17 00:00:00 2001 From: Vaxry Date: Tue, 30 Jul 2024 12:11:38 +0200 Subject: [PATCH 0204/2181] hyprpm: execute all git commands regardless of fails --- hyprpm/src/core/PluginManager.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/hyprpm/src/core/PluginManager.cpp b/hyprpm/src/core/PluginManager.cpp index a29afad7..6988547c 100644 --- a/hyprpm/src/core/PluginManager.cpp +++ b/hyprpm/src/core/PluginManager.cpp @@ -479,7 +479,7 @@ bool CPluginManager::updateHeaders(bool force) { if (m_bVerbose) progress.printMessageAbove(std::string{Colors::BLUE} + "[v] " + Colors::RESET + "git returned (co): " + ret); - ret = execAndGet("cd " + WORKINGDIR + " && git rm subprojects/tracy && git submodule update --init 2>&1 && git reset --hard --recurse-submodules " + HLVER.hash); + ret = execAndGet("cd " + WORKINGDIR + " ; git rm subprojects/tracy ; git submodule update --init 2>&1 ; git reset --hard --recurse-submodules " + HLVER.hash); if (m_bVerbose) progress.printMessageAbove(std::string{Colors::BLUE} + "[v] " + Colors::RESET + "git returned (rs): " + ret); From 10e631053aaccdf31fab195454deab1154e21219 Mon Sep 17 00:00:00 2001 From: jim3692 <31220180+jim3692@users.noreply.github.com> Date: Tue, 30 Jul 2024 14:50:13 +0300 Subject: [PATCH 0205/2181] compositor: fix log typos (#7111) --- src/Compositor.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Compositor.cpp b/src/Compositor.cpp index 36f483fd..f6e418de 100644 --- a/src/Compositor.cpp +++ b/src/Compositor.cpp @@ -247,7 +247,7 @@ void CCompositor::initServer(std::string socketName, int socketFd) { if (!m_pAqBackend) { Debug::log(CRIT, - "m_pAqBackend was null! This usually means aquamarine could not find a GPU or enountered some issues. Make sure you're running either on a tty or on a Wayland " + "m_pAqBackend was null! This usually means aquamarine could not find a GPU or encountered some issues. Make sure you're running either on a tty or on a Wayland " "session, NOT an X11 one."); throwError("CBackend::create() failed!"); } @@ -258,7 +258,7 @@ void CCompositor::initServer(std::string socketName, int socketFd) { if (!m_pAqBackend->start()) { Debug::log(CRIT, - "m_pAqBackend couldn't start! This usually means aquamarine could not find a GPU or enountered some issues. Make sure you're running either on a tty or on a " + "m_pAqBackend couldn't start! This usually means aquamarine could not find a GPU or encountered some issues. Make sure you're running either on a tty or on a " "Wayland session, NOT an X11 one."); throwError("CBackend::create() failed!"); } From f3a9f9ec4544225d6f340fa5f8a0dab9bf39157c Mon Sep 17 00:00:00 2001 From: Vaxry Date: Tue, 30 Jul 2024 15:32:38 +0200 Subject: [PATCH 0206/2181] pointer: use preMonitorCommit for resetting render state in DS preRender is not called --- src/helpers/Monitor.cpp | 2 ++ src/managers/PointerManager.cpp | 2 +- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/src/helpers/Monitor.cpp b/src/helpers/Monitor.cpp index 635427d1..9d282090 100644 --- a/src/helpers/Monitor.cpp +++ b/src/helpers/Monitor.cpp @@ -863,6 +863,8 @@ bool CMonitorState::commit() { if (!updateSwapchain()) return false; + EMIT_HOOK_EVENT("preMonitorCommit", m_pOwner); + ensureBufferPresent(); bool ret = m_pOwner->output->commit(); diff --git a/src/managers/PointerManager.cpp b/src/managers/PointerManager.cpp index a405e2eb..8314e79a 100644 --- a/src/managers/PointerManager.cpp +++ b/src/managers/PointerManager.cpp @@ -25,7 +25,7 @@ CPointerManager::CPointerManager() { nullptr); }); - hooks.monitorPreRender = g_pHookSystem->hookDynamic("preRender", [this](void* self, SCallbackInfo& info, std::any data) { + hooks.monitorPreRender = g_pHookSystem->hookDynamic("preMonitorCommit", [this](void* self, SCallbackInfo& info, std::any data) { auto state = stateFor(std::any_cast(data)->self.lock()); if (!state) return; From c1afc82a4ceb2e1989ec750b476a97f7f49051e3 Mon Sep 17 00:00:00 2001 From: vaxerski Date: Tue, 30 Jul 2024 13:34:22 +0000 Subject: [PATCH 0207/2181] [gha] Nix: update inputs --- flake.lock | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/flake.lock b/flake.lock index 01b68384..045e692e 100644 --- a/flake.lock +++ b/flake.lock @@ -16,11 +16,11 @@ ] }, "locked": { - "lastModified": 1722100913, - "narHash": "sha256-75Hcx5Zu0f+BeCkZxN1frkYacjbkwgCq+z3doVgr4Hw=", + "lastModified": 1722283490, + "narHash": "sha256-xqaO+h2ams6bpfNdUAtvWN6SKuNIeyr3lXYsAKYS/+0=", "owner": "hyprwm", "repo": "aquamarine", - "rev": "4918e57979bbdbd05aabb20f63e1cb5dc289bcbd", + "rev": "9ccb4411ee001715db0fbc74e7ff1cea02c6c24f", "type": "github" }, "original": { @@ -154,11 +154,11 @@ }, "nixpkgs": { "locked": { - "lastModified": 1721924956, - "narHash": "sha256-Sb1jlyRO+N8jBXEX9Pg9Z1Qb8Bw9QyOgLDNMEpmjZ2M=", + "lastModified": 1722185531, + "narHash": "sha256-veKR07psFoJjINLC8RK4DiLniGGMgF3QMlS4tb74S6k=", "owner": "NixOS", "repo": "nixpkgs", - "rev": "5ad6a14c6bf098e98800b091668718c336effc95", + "rev": "52ec9ac3b12395ad677e8b62106f0b98c1f8569d", "type": "github" }, "original": { From 1c221240d0c6c352cea203b51a918b906a8d340f Mon Sep 17 00:00:00 2001 From: Vaxry Date: Tue, 30 Jul 2024 15:46:35 +0200 Subject: [PATCH 0208/2181] output: submit damage to kms --- src/helpers/Monitor.cpp | 2 ++ src/render/Renderer.cpp | 2 ++ 2 files changed, 4 insertions(+) diff --git a/src/helpers/Monitor.cpp b/src/helpers/Monitor.cpp index 9d282090..787b790f 100644 --- a/src/helpers/Monitor.cpp +++ b/src/helpers/Monitor.cpp @@ -822,6 +822,8 @@ bool CMonitor::attemptDirectScanout() { Debug::log(TRACE, "presentFeedback for DS"); PSURFACE->presentFeedback(&now, this, true); + output->state->addDamage(CBox{{}, vecPixelSize}); + if (state.commit()) { if (lastScanout.expired()) { lastScanout = PCANDIDATE; diff --git a/src/render/Renderer.cpp b/src/render/Renderer.cpp index 0bf4c9f3..df0c6af5 100644 --- a/src/render/Renderer.cpp +++ b/src/render/Renderer.cpp @@ -1371,6 +1371,8 @@ void CHyprRenderer::renderMonitor(CMonitor* pMonitor) { frameDamage.add(damage); g_pHyprRenderer->damageMirrorsWith(pMonitor, frameDamage); + + pMonitor->output->state->addDamage(frameDamage); } pMonitor->renderingActive = false; From cc7c117fe76ff0a4da56b18026c725501de92c84 Mon Sep 17 00:00:00 2001 From: Vaxry Date: Tue, 30 Jul 2024 15:50:14 +0200 Subject: [PATCH 0209/2181] output: minor tearing fixes --- src/helpers/Monitor.cpp | 3 ++- src/render/Renderer.cpp | 7 ++----- 2 files changed, 4 insertions(+), 6 deletions(-) diff --git a/src/helpers/Monitor.cpp b/src/helpers/Monitor.cpp index 787b790f..33fe0c04 100644 --- a/src/helpers/Monitor.cpp +++ b/src/helpers/Monitor.cpp @@ -812,7 +812,8 @@ bool CMonitor::attemptDirectScanout() { // and comes from the appropriate device. This may implode on multi-gpu!! output->state->setBuffer(PSURFACE->current.buffer); - output->state->setPresentationMode(Aquamarine::eOutputPresentationMode::AQ_OUTPUT_PRESENTATION_VSYNC); + output->state->setPresentationMode(tearingState.activelyTearing ? Aquamarine::eOutputPresentationMode::AQ_OUTPUT_PRESENTATION_IMMEDIATE : + Aquamarine::eOutputPresentationMode::AQ_OUTPUT_PRESENTATION_VSYNC); if (!state.test()) return false; diff --git a/src/render/Renderer.cpp b/src/render/Renderer.cpp index df0c6af5..b5397598 100644 --- a/src/render/Renderer.cpp +++ b/src/render/Renderer.cpp @@ -1193,6 +1193,8 @@ void CHyprRenderer::renderMonitor(CMonitor* pMonitor) { shouldTear = true; } + pMonitor->tearingState.activelyTearing = shouldTear; + if (!*PNODIRECTSCANOUT && !shouldTear) { if (pMonitor->attemptDirectScanout()) { return; @@ -1202,11 +1204,6 @@ void CHyprRenderer::renderMonitor(CMonitor* pMonitor) { } } - if (pMonitor->tearingState.activelyTearing != shouldTear) { - // change of state - pMonitor->tearingState.activelyTearing = shouldTear; - } - EMIT_HOOK_EVENT("preRender", pMonitor); timespec now; From 8ec3dc4c09c30aab7669f99ba6359be320023fa8 Mon Sep 17 00:00:00 2001 From: Mihai Fufezan Date: Tue, 30 Jul 2024 22:13:47 +0300 Subject: [PATCH 0210/2181] CI: update actions flake.lock: update aquamarine and xdph --- .github/workflows/nix-build.yml | 6 +++--- flake.lock | 12 ++++++------ 2 files changed, 9 insertions(+), 9 deletions(-) diff --git a/.github/workflows/nix-build.yml b/.github/workflows/nix-build.yml index 33ee5cac..d0234498 100644 --- a/.github/workflows/nix-build.yml +++ b/.github/workflows/nix-build.yml @@ -15,14 +15,14 @@ jobs: runs-on: ubuntu-latest steps: - name: Clone repository - uses: actions/checkout@v3 + uses: actions/checkout@v4 with: ref: ${{ github.ref }} submodules: recursive - - uses: cachix/install-nix-action@v26 + - uses: cachix/install-nix-action@v27 - uses: DeterminateSystems/magic-nix-cache-action@main - - uses: cachix/cachix-action@v12 + - uses: cachix/cachix-action@v15 with: name: hyprland authToken: '${{ secrets.CACHIX_AUTH_TOKEN }}' diff --git a/flake.lock b/flake.lock index 045e692e..5c384d4d 100644 --- a/flake.lock +++ b/flake.lock @@ -16,11 +16,11 @@ ] }, "locked": { - "lastModified": 1722283490, - "narHash": "sha256-xqaO+h2ams6bpfNdUAtvWN6SKuNIeyr3lXYsAKYS/+0=", + "lastModified": 1722347739, + "narHash": "sha256-rAoh+K6KG+b1DwSWtqRVocdojnH6nGk6q07mNltoUSM=", "owner": "hyprwm", "repo": "aquamarine", - "rev": "9ccb4411ee001715db0fbc74e7ff1cea02c6c24f", + "rev": "7c3565f9bedc7cb601cc0baa14792247e4dc1d5a", "type": "github" }, "original": { @@ -209,11 +209,11 @@ ] }, "locked": { - "lastModified": 1722181019, - "narHash": "sha256-Lj/g1UzrsTZUixtveQix6eB3pon2j23qv5/5pzTx0LQ=", + "lastModified": 1722365976, + "narHash": "sha256-Khdm+mDzYA//XaU0M+hftod+rKr5q9SSHSEuiQ0/9ow=", "owner": "hyprwm", "repo": "xdg-desktop-portal-hyprland", - "rev": "0e2f3b9c85f7bab3983098a01366876d34daf383", + "rev": "7f2a77ddf60390248e2a3de2261d7102a13e5341", "type": "github" }, "original": { From 3b9b5346b830554aa7470ccf1202a7f3be72d1b4 Mon Sep 17 00:00:00 2001 From: Ikalco <73481042+ikalco@users.noreply.github.com> Date: Tue, 30 Jul 2024 16:33:56 -0500 Subject: [PATCH 0211/2181] protocols: Move globalshortcuts impl (#7102) * move global shortcuts to hyprwayland-scanner * remove wayland-scanner from deps * fix the thing --- CMakeLists.txt | 31 +----- protocols/meson.build | 28 +----- src/debug/HyprCtl.cpp | 3 +- src/managers/KeybindManager.cpp | 5 +- src/managers/ProtocolManager.cpp | 7 +- src/managers/ProtocolManager.hpp | 4 - src/protocols/GlobalShortcuts.cpp | 153 +++++++++--------------------- src/protocols/GlobalShortcuts.hpp | 65 ++++++------- 8 files changed, 84 insertions(+), 212 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 550f1dc5..3616da24 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -49,8 +49,6 @@ endif() find_package(PkgConfig REQUIRED) -pkg_get_variable(WaylandScanner wayland-scanner wayland_scanner) -message(STATUS "Found WaylandScanner at ${WaylandScanner}") pkg_get_variable(WAYLAND_PROTOCOLS_DIR wayland-protocols pkgdatadir) message(STATUS "Found wayland-protocols at ${WAYLAND_PROTOCOLS_DIR}") pkg_get_variable(WAYLAND_SERVER_DIR wayland-server pkgdatadir) @@ -232,30 +230,6 @@ target_link_libraries(Hyprland rt PkgConfig::deps) # used by `make installheaders`, to ensure the headers are generated add_custom_target(generate-protocol-headers) -function(protocol 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}-protocol.h - COMMAND ${WaylandScanner} server-header ${path} - protocols/${protoName}-protocol.h - WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}) - add_custom_command( - OUTPUT ${CMAKE_SOURCE_DIR}/protocols/${protoName}-protocol.c - COMMAND ${WaylandScanner} private-code ${path} - protocols/${protoName}-protocol.c - WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}) - target_sources( - Hyprland PRIVATE ${CMAKE_SOURCE_DIR}/protocols/${protoName}-protocol.h - ${CMAKE_SOURCE_DIR}/protocols/${protoName}-protocol.c) - target_sources(generate-protocol-headers - PRIVATE ${CMAKE_SOURCE_DIR}/protocols/${protoName}-protocol.h) -endfunction() - function(protocolnew protoPath protoName external) if(external) set(path ${CMAKE_SOURCE_DIR}/${protoPath}) @@ -288,10 +262,7 @@ endfunction() target_link_libraries(Hyprland OpenGL::EGL OpenGL::GL Threads::Threads libudis86 uuid) -protocol( - "subprojects/hyprland-protocols/protocols/hyprland-global-shortcuts-v1.xml" - "hyprland-global-shortcuts-v1" true) - +protocolnew("subprojects/hyprland-protocols/protocols" "hyprland-global-shortcuts-v1" true) protocolnew("unstable/text-input" "text-input-unstable-v1" false) protocolnew("subprojects/hyprland-protocols/protocols" "hyprland-toplevel-export-v1" true) protocolnew("protocols" "wlr-screencopy-unstable-v1" true) diff --git a/protocols/meson.build b/protocols/meson.build index 4fd40859..5b807914 100644 --- a/protocols/meson.build +++ b/protocols/meson.build @@ -12,21 +12,12 @@ hyprland_protos = dependency('hyprland-protocols', wl_protocol_dir = wayland_protos.get_variable('pkgdatadir') hl_protocol_dir = hyprland_protos.get_variable('pkgdatadir') -wayland_scanner_dep = dependency('wayland-scanner', native: true) -wayland_scanner = find_program( - wayland_scanner_dep.get_variable('wayland_scanner'), - native: true, -) hyprwayland_scanner_dep = dependency('hyprwayland-scanner', version: '>=0.3.8', native: true) hyprwayland_scanner = find_program( hyprwayland_scanner_dep.get_variable('hyprwayland_scanner'), native: true, ) -protocols = [ - [hl_protocol_dir, 'protocols/hyprland-global-shortcuts-v1.xml'] -] - new_protocols = [ ['wlr-gamma-control-unstable-v1.xml'], ['wlr-foreign-toplevel-management-unstable-v1.xml'], @@ -40,6 +31,7 @@ new_protocols = [ ['wayland-drm.xml'], ['wlr-data-control-unstable-v1.xml'], ['wlr-screencopy-unstable-v1.xml'], + [hl_protocol_dir, 'protocols/hyprland-global-shortcuts-v1.xml'], [hl_protocol_dir, 'protocols/hyprland-toplevel-export-v1.xml'], [hl_protocol_dir, 'protocols/hyprland-focus-grab-v1.xml'], [wl_protocol_dir, 'staging/tearing-control/tearing-control-v1.xml'], @@ -73,24 +65,6 @@ new_protocols = [ wl_protos_src = [] wl_protos_headers = [] -foreach p : protocols - xml = join_paths(p) - wl_protos_src += custom_target( - xml.underscorify() + '_server_c', - input: xml, - output: '@BASENAME@-protocol.c', - command: [wayland_scanner, 'private-code', '@INPUT@', '@OUTPUT@'], - ) - wl_protos_headers += custom_target( - xml.underscorify() + '_server_h', - input: xml, - install: true, - install_dir: join_paths(get_option('includedir'), 'hyprland/protocols'), - output: '@BASENAME@-protocol.h', - command: [wayland_scanner, 'server-header', '@INPUT@', '@OUTPUT@'], - ) -endforeach - new_wl_protos = [] foreach p : new_protocols xml = join_paths(p) diff --git a/src/debug/HyprCtl.cpp b/src/debug/HyprCtl.cpp index b81cfeff..d89d1772 100644 --- a/src/debug/HyprCtl.cpp +++ b/src/debug/HyprCtl.cpp @@ -32,6 +32,7 @@ using namespace Hyprutils::String; #include "../devices/IKeyboard.hpp" #include "../devices/ITouch.hpp" #include "../devices/Tablet.hpp" +#include "../protocols/GlobalShortcuts.hpp" #include "debug/RollingLogFollow.hpp" #include "config/ConfigManager.hpp" #include "helpers/MiscFunctions.hpp" @@ -776,7 +777,7 @@ std::string rollinglogRequest(eHyprCtlOutputFormat format, std::string request) std::string globalShortcutsRequest(eHyprCtlOutputFormat format, std::string request) { std::string ret = ""; - const auto SHORTCUTS = g_pProtocolManager->m_pGlobalShortcutsProtocolManager->getAllShortcuts(); + const auto SHORTCUTS = PROTO::globalShortcuts->getAllShortcuts(); if (format == eHyprCtlOutputFormat::FORMAT_NORMAL) { for (auto& sh : SHORTCUTS) ret += std::format("{}:{} -> {}\n", sh.appid, sh.id, sh.description); diff --git a/src/managers/KeybindManager.cpp b/src/managers/KeybindManager.cpp index 038f6401..2b99ce97 100644 --- a/src/managers/KeybindManager.cpp +++ b/src/managers/KeybindManager.cpp @@ -3,6 +3,7 @@ #include "../managers/SeatManager.hpp" #include "../protocols/LayerShell.hpp" #include "../protocols/ShortcutsInhibit.hpp" +#include "../protocols/GlobalShortcuts.hpp" #include "../render/decorations/CHyprGroupBarDecoration.hpp" #include "../devices/IKeyboard.hpp" #include "KeybindManager.hpp" @@ -2664,10 +2665,10 @@ void CKeybindManager::global(std::string args) { if (NAME.empty()) return; - if (!g_pProtocolManager->m_pGlobalShortcutsProtocolManager->globalShortcutExists(APPID, NAME)) + if (!PROTO::globalShortcuts->isTaken(APPID, NAME)) return; - g_pProtocolManager->m_pGlobalShortcutsProtocolManager->sendGlobalShortcutEvent(APPID, NAME, g_pKeybindManager->m_iPassPressed); + PROTO::globalShortcuts->sendGlobalShortcutEvent(APPID, NAME, g_pKeybindManager->m_iPassPressed); } void CKeybindManager::moveGroupWindow(std::string args) { diff --git a/src/managers/ProtocolManager.cpp b/src/managers/ProtocolManager.cpp index d052e045..635e6223 100644 --- a/src/managers/ProtocolManager.cpp +++ b/src/managers/ProtocolManager.cpp @@ -42,6 +42,7 @@ #include "../protocols/Screencopy.hpp" #include "../protocols/ToplevelExport.hpp" #include "../protocols/TextInputV1.hpp" +#include "../protocols/GlobalShortcuts.hpp" #include "../protocols/core/Seat.hpp" #include "../protocols/core/DataDevice.hpp" @@ -148,6 +149,7 @@ CProtocolManager::CProtocolManager() { PROTO::xwaylandShell = std::make_unique(&xwayland_shell_v1_interface, 1, "XWaylandShell"); PROTO::screencopy = std::make_unique(&zwlr_screencopy_manager_v1_interface, 3, "Screencopy"); PROTO::toplevelExport = std::make_unique(&hyprland_toplevel_export_manager_v1_interface, 2, "ToplevelExport"); + PROTO::globalShortcuts = std::make_unique(&hyprland_global_shortcuts_manager_v1_interface, 1, "GlobalShortcuts"); for (auto& b : g_pCompositor->m_pAqBackend->getImplementations()) { if (b->type() != Aquamarine::AQ_BACKEND_DRM) @@ -164,10 +166,6 @@ CProtocolManager::CProtocolManager() { PROTO::linuxDma = std::make_unique(&zwp_linux_dmabuf_v1_interface, 5, "LinuxDMABUF"); } else Debug::log(WARN, "ProtocolManager: Not binding linux-dmabuf and MesaDRM: DMABUF not available"); - - // Old protocol implementations. - // TODO: rewrite them to use hyprwayland-scanner. - m_pGlobalShortcutsProtocolManager = std::make_unique(); } CProtocolManager::~CProtocolManager() { @@ -220,6 +218,7 @@ CProtocolManager::~CProtocolManager() { PROTO::xwaylandShell.reset(); PROTO::screencopy.reset(); PROTO::toplevelExport.reset(); + PROTO::globalShortcuts.reset(); PROTO::lease.reset(); PROTO::sync.reset(); diff --git a/src/managers/ProtocolManager.hpp b/src/managers/ProtocolManager.hpp index 044a4d9b..1b6d31b6 100644 --- a/src/managers/ProtocolManager.hpp +++ b/src/managers/ProtocolManager.hpp @@ -1,7 +1,6 @@ #pragma once #include "../defines.hpp" -#include "../protocols/GlobalShortcuts.hpp" #include "../helpers/Monitor.hpp" #include "../helpers/memory/Memory.hpp" #include "../helpers/signal/Signal.hpp" @@ -12,9 +11,6 @@ class CProtocolManager { CProtocolManager(); ~CProtocolManager(); - // TODO: rewrite to use the new protocol framework - std::unique_ptr m_pGlobalShortcutsProtocolManager; - private: std::unordered_map m_mModeChangeListeners; diff --git a/src/protocols/GlobalShortcuts.cpp b/src/protocols/GlobalShortcuts.cpp index 7eb84be6..860004c9 100644 --- a/src/protocols/GlobalShortcuts.cpp +++ b/src/protocols/GlobalShortcuts.cpp @@ -1,120 +1,61 @@ #include "GlobalShortcuts.hpp" #include "../Compositor.hpp" -#define GLOBAL_SHORTCUTS_VERSION 1 +#define LOGM PROTO::globalShortcuts->protoLog -static void bindManagerInt(wl_client* client, void* data, uint32_t version, uint32_t id) { - g_pProtocolManager->m_pGlobalShortcutsProtocolManager->bindManager(client, data, version, id); -} - -static void handleDisplayDestroy(struct wl_listener* listener, void* data) { - CGlobalShortcutsProtocolManagerDestroyWrapper* wrap = wl_container_of(listener, wrap, listener); - CGlobalShortcutsProtocolManager* proto = wrap->parent; - proto->displayDestroy(); -} - -void CGlobalShortcutsProtocolManager::displayDestroy() { - wl_list_remove(&m_liDisplayDestroy.listener.link); - wl_list_init(&m_liDisplayDestroy.listener.link); - wl_global_destroy(m_pGlobal); -} - -CGlobalShortcutsProtocolManager::~CGlobalShortcutsProtocolManager() { - displayDestroy(); -} - -CGlobalShortcutsProtocolManager::CGlobalShortcutsProtocolManager() { - m_pGlobal = wl_global_create(g_pCompositor->m_sWLDisplay, &hyprland_global_shortcuts_manager_v1_interface, GLOBAL_SHORTCUTS_VERSION, this, bindManagerInt); - - if (!m_pGlobal) { - Debug::log(ERR, "GlobalShortcutsManager could not start!"); +CShortcutClient::CShortcutClient(SP resource_) : resource(resource_) { + if (!good()) return; - } - wl_list_init(&m_liDisplayDestroy.listener.link); - m_liDisplayDestroy.listener.notify = handleDisplayDestroy; - m_liDisplayDestroy.parent = this; - wl_display_add_destroy_listener(g_pCompositor->m_sWLDisplay, &m_liDisplayDestroy.listener); + resource->setOnDestroy([this](CHyprlandGlobalShortcutsManagerV1* pMgr) { PROTO::globalShortcuts->destroyResource(this); }); + resource->setDestroy([this](CHyprlandGlobalShortcutsManagerV1* pMgr) { PROTO::globalShortcuts->destroyResource(this); }); - Debug::log(LOG, "GlobalShortcutsManager started successfully!"); -} - -static void handleRegisterShortcut(wl_client* client, wl_resource* resource, uint32_t shortcut, const char* id, const char* app_id, const char* description, - const char* trigger_description) { - g_pProtocolManager->m_pGlobalShortcutsProtocolManager->registerShortcut(client, resource, shortcut, id, app_id, description, trigger_description); -} - -static void handleDestroy(wl_client* client, wl_resource* resource) { - wl_resource_destroy(resource); -} - -static const struct hyprland_global_shortcuts_manager_v1_interface globalShortcutsManagerImpl = { - .register_shortcut = handleRegisterShortcut, - .destroy = handleDestroy, -}; - -static const struct hyprland_global_shortcut_v1_interface shortcutImpl = { - .destroy = handleDestroy, -}; - -void CGlobalShortcutsProtocolManager::bindManager(wl_client* client, void* data, uint32_t version, uint32_t id) { - const auto RESOURCE = wl_resource_create(client, &hyprland_global_shortcuts_manager_v1_interface, version, id); - wl_resource_set_implementation(RESOURCE, &globalShortcutsManagerImpl, this, nullptr); - - Debug::log(LOG, "GlobalShortcutsManager bound successfully!"); - - m_vClients.emplace_back(std::make_unique(client)); -} - -SShortcutClient* CGlobalShortcutsProtocolManager::clientFromWlClient(wl_client* client) { - for (auto& c : m_vClients) { - if (c->client == client) { - return c.get(); + resource->setRegisterShortcut([this](CHyprlandGlobalShortcutsManagerV1* pMgr, uint32_t shortcut, const char* id, const char* app_id, const char* description, + const char* trigger_description) { + if (PROTO::globalShortcuts->isTaken(id, app_id)) { + resource->error(HYPRLAND_GLOBAL_SHORTCUTS_MANAGER_V1_ERROR_ALREADY_TAKEN, "Combination is taken"); + return; } - } - return nullptr; -} + const auto PSHORTCUT = shortcuts.emplace_back(makeShared(makeShared(resource->client(), resource->version(), shortcut))); + PSHORTCUT->id = id; + PSHORTCUT->description = description; + PSHORTCUT->appid = app_id; + PSHORTCUT->shortcut = shortcut; -static void onShortcutDestroy(wl_resource* pResource) { - g_pProtocolManager->m_pGlobalShortcutsProtocolManager->destroyShortcut(pResource); -} - -void CGlobalShortcutsProtocolManager::registerShortcut(wl_client* client, wl_resource* resource, uint32_t shortcut, const char* id, const char* app_id, const char* description, - const char* trigger_description) { - const auto PCLIENT = clientFromWlClient(client); - - if (!PCLIENT) { - Debug::log(ERR, "Error at global shortcuts: no client in register?"); - return; - } - - for (auto& c : m_vClients) { - for (auto& sh : c->shortcuts) { - if (sh->appid == app_id && sh->id == id) { - wl_resource_post_error(resource, HYPRLAND_GLOBAL_SHORTCUTS_MANAGER_V1_ERROR_ALREADY_TAKEN, "Combination is taken"); - return; - } + if (!PSHORTCUT->resource->resource()) { + PSHORTCUT->resource->noMemory(); + shortcuts.pop_back(); + return; } - } - const auto PSHORTCUT = PCLIENT->shortcuts.emplace_back(std::make_unique()).get(); - PSHORTCUT->id = id; - PSHORTCUT->description = description; - PSHORTCUT->appid = app_id; - PSHORTCUT->shortcut = shortcut; + PSHORTCUT->resource->setDestroy([this](CHyprlandGlobalShortcutV1* pMgr) { std::erase_if(shortcuts, [&](const auto& other) { return other->resource.get() == pMgr; }); }); + }); +} - PSHORTCUT->resource = wl_resource_create(client, &hyprland_global_shortcut_v1_interface, 1, shortcut); - if (!PSHORTCUT->resource) { +bool CShortcutClient::good() { + return resource->resource(); +} + +CGlobalShortcutsProtocol::CGlobalShortcutsProtocol(const wl_interface* iface, const int& ver, const std::string& name) : IWaylandProtocol(iface, ver, name) { + ; +} + +void CGlobalShortcutsProtocol::bindManager(wl_client* client, void* data, uint32_t ver, uint32_t id) { + const auto RESROUCE = m_vClients.emplace_back(makeShared(makeShared(client, ver, id))); + + if (!RESROUCE->good()) { wl_client_post_no_memory(client); - std::erase_if(PCLIENT->shortcuts, [&](const auto& other) { return other.get() == PSHORTCUT; }); + m_vClients.pop_back(); return; } - - wl_resource_set_implementation(PSHORTCUT->resource, &shortcutImpl, this, &onShortcutDestroy); } -bool CGlobalShortcutsProtocolManager::globalShortcutExists(std::string appid, std::string trigger) { +void CGlobalShortcutsProtocol::destroyResource(CShortcutClient* client) { + std::erase_if(m_vClients, [&](const auto& other) { return other.get() == client; }); +} + +bool CGlobalShortcutsProtocol::isTaken(std::string appid, std::string trigger) { for (auto& c : m_vClients) { for (auto& sh : c->shortcuts) { if (sh->appid == appid && sh->id == trigger) { @@ -126,7 +67,7 @@ bool CGlobalShortcutsProtocolManager::globalShortcutExists(std::string appid, st return false; } -void CGlobalShortcutsProtocolManager::sendGlobalShortcutEvent(std::string appid, std::string trigger, bool pressed) { +void CGlobalShortcutsProtocol::sendGlobalShortcutEvent(std::string appid, std::string trigger, bool pressed) { for (auto& c : m_vClients) { for (auto& sh : c->shortcuts) { if (sh->appid == appid && sh->id == trigger) { @@ -135,15 +76,15 @@ void CGlobalShortcutsProtocolManager::sendGlobalShortcutEvent(std::string appid, uint32_t tvSecHi = (sizeof(now.tv_sec) > 4) ? now.tv_sec >> 32 : 0; uint32_t tvSecLo = now.tv_sec & 0xFFFFFFFF; if (pressed) - hyprland_global_shortcut_v1_send_pressed(sh->resource, tvSecHi, tvSecLo, now.tv_nsec); + sh->resource->sendPressed(tvSecHi, tvSecLo, now.tv_nsec); else - hyprland_global_shortcut_v1_send_released(sh->resource, tvSecHi, tvSecLo, now.tv_nsec); + sh->resource->sendReleased(tvSecHi, tvSecLo, now.tv_nsec); } } } } -std::vector CGlobalShortcutsProtocolManager::getAllShortcuts() { +std::vector CGlobalShortcutsProtocol::getAllShortcuts() { std::vector copy; for (auto& c : m_vClients) { for (auto& sh : c->shortcuts) { @@ -153,9 +94,3 @@ std::vector CGlobalShortcutsProtocolManager::getAllShortcuts() { return copy; } - -void CGlobalShortcutsProtocolManager::destroyShortcut(wl_resource* resource) { - for (auto& c : m_vClients) { - std::erase_if(c->shortcuts, [&](const auto& other) { return other->resource == resource; }); - } -} diff --git a/src/protocols/GlobalShortcuts.hpp b/src/protocols/GlobalShortcuts.hpp index 7e512021..14f6ee0b 100644 --- a/src/protocols/GlobalShortcuts.hpp +++ b/src/protocols/GlobalShortcuts.hpp @@ -1,48 +1,43 @@ #pragma once #include "../defines.hpp" -#include "hyprland-global-shortcuts-v1-protocol.h" +#include "hyprland-global-shortcuts-v1.hpp" +#include "../protocols/WaylandProtocol.hpp" #include struct SShortcut { - wl_resource* resource; - std::string id, description, appid; - uint32_t shortcut = 0; + SP resource; + std::string id, description, appid; + uint32_t shortcut = 0; }; -struct SShortcutClient { - wl_client* client = nullptr; - std::vector> shortcuts; -}; - -class CGlobalShortcutsProtocolManager; -struct CGlobalShortcutsProtocolManagerDestroyWrapper { - wl_listener listener; - CGlobalShortcutsProtocolManager* parent = nullptr; -}; - -class CGlobalShortcutsProtocolManager { +class CShortcutClient { public: - CGlobalShortcutsProtocolManager(); - ~CGlobalShortcutsProtocolManager(); + CShortcutClient(SP resource); - void bindManager(wl_client* client, void* data, uint32_t version, uint32_t id); - void displayDestroy(); - - void registerShortcut(wl_client* client, wl_resource* resource, uint32_t shortcut, const char* id, const char* app_id, const char* description, - const char* trigger_description); - void destroyShortcut(wl_resource* resource); - - bool globalShortcutExists(std::string appid, std::string trigger); - void sendGlobalShortcutEvent(std::string appid, std::string trigger, bool pressed); - - std::vector getAllShortcuts(); - - CGlobalShortcutsProtocolManagerDestroyWrapper m_liDisplayDestroy; + bool good(); private: - std::vector> m_vClients; + SP resource; + std::vector> shortcuts; - SShortcutClient* clientFromWlClient(wl_client* client); - - wl_global* m_pGlobal = nullptr; + friend class CGlobalShortcutsProtocol; +}; + +class CGlobalShortcutsProtocol : IWaylandProtocol { + public: + CGlobalShortcutsProtocol(const wl_interface* iface, const int& ver, const std::string& name); + + void bindManager(wl_client* client, void* data, uint32_t version, uint32_t id); + void destroyResource(CShortcutClient* client); + + void sendGlobalShortcutEvent(std::string appid, std::string trigger, bool pressed); + bool isTaken(std::string id, std::string app_id); + std::vector getAllShortcuts(); + + private: + std::vector> m_vClients; +}; + +namespace PROTO { + inline UP globalShortcuts; }; From 8a5f9bbb394ddeb4be9a9df6248b41b07d84ea66 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andr=C3=A9=20Silva?= <123550+andresilva@users.noreply.github.com> Date: Wed, 31 Jul 2024 16:54:07 +0100 Subject: [PATCH 0212/2181] keybinds: handle null monitor in pinActive (#7122) --- src/managers/KeybindManager.cpp | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/src/managers/KeybindManager.cpp b/src/managers/KeybindManager.cpp index 2b99ce97..823e2d2e 100644 --- a/src/managers/KeybindManager.cpp +++ b/src/managers/KeybindManager.cpp @@ -2333,8 +2333,16 @@ void CKeybindManager::pinActive(std::string args) { if (!PWINDOW->m_bIsFloating || PWINDOW->m_bIsFullscreen) return; - PWINDOW->m_bPinned = !PWINDOW->m_bPinned; - PWINDOW->m_pWorkspace = g_pCompositor->getMonitorFromID(PWINDOW->m_iMonitorID)->activeWorkspace; + PWINDOW->m_bPinned = !PWINDOW->m_bPinned; + + const auto PMONITOR = g_pCompositor->getMonitorFromID(PWINDOW->m_iMonitorID); + + if (!PMONITOR) { + Debug::log(ERR, "pin: monitor not found"); + return; + } + + PWINDOW->m_pWorkspace = PMONITOR->activeWorkspace; PWINDOW->updateDynamicRules(); g_pCompositor->updateWindowAnimatedDecorationValues(PWINDOW); From e989a0bcffac81092ed2a7e371f5225c113f689d Mon Sep 17 00:00:00 2001 From: MightyPlaza <123664421+MightyPlaza@users.noreply.github.com> Date: Wed, 31 Jul 2024 17:55:52 +0000 Subject: [PATCH 0213/2181] internal: refactor fullscreen states (#7104) * refactor fullscreen modified: src/Compositor.cpp modified: src/Compositor.hpp modified: src/config/ConfigManager.cpp modified: src/config/ConfigManager.hpp modified: src/debug/HyprCtl.cpp modified: src/desktop/LayerSurface.cpp modified: src/desktop/Window.cpp modified: src/desktop/Window.hpp modified: src/desktop/Workspace.cpp modified: src/desktop/Workspace.hpp modified: src/events/Windows.cpp modified: src/helpers/Monitor.cpp modified: src/layout/DwindleLayout.cpp modified: src/layout/DwindleLayout.hpp modified: src/layout/IHyprLayout.cpp modified: src/layout/IHyprLayout.hpp modified: src/layout/MasterLayout.cpp modified: src/layout/MasterLayout.hpp modified: src/managers/KeybindManager.cpp modified: src/managers/KeybindManager.hpp modified: src/managers/input/IdleInhibitor.cpp modified: src/managers/input/InputManager.cpp modified: src/managers/input/Swipe.cpp modified: src/protocols/ForeignToplevelWlr.cpp modified: src/render/Renderer.cpp modified: src/render/decorations/CHyprGroupBarDecoration.cpp * clean up modified: src/config/ConfigManager.cpp modified: src/debug/HyprCtl.cpp modified: src/desktop/Window.hpp modified: src/desktop/Workspace.cpp modified: src/events/Windows.cpp modified: src/managers/KeybindManager.cpp modified: src/managers/input/Swipe.cpp * fix mapWindow fullscreen modified: src/events/Windows.cpp * fix typo modified: src/desktop/Workspace.cpp * add fullscreenstate modified: src/config/ConfigManager.cpp modified: src/events/Windows.cpp * change syncFullscreen to lower modified: src/config/ConfigManager.hpp * initialize fs state modified: src/desktop/Window.hpp --- src/Compositor.cpp | 116 +++++++++++------- src/Compositor.hpp | 6 +- src/config/ConfigManager.cpp | 10 +- src/config/ConfigManager.hpp | 1 + src/debug/HyprCtl.cpp | 13 +- src/desktop/LayerSurface.cpp | 2 +- src/desktop/Window.cpp | 40 +++--- src/desktop/Window.hpp | 43 ++++--- src/desktop/Workspace.cpp | 9 +- src/desktop/Workspace.hpp | 9 +- src/events/Windows.cpp | 99 ++++++++------- src/helpers/Monitor.cpp | 2 +- src/layout/DwindleLayout.cpp | 76 +++--------- src/layout/DwindleLayout.hpp | 2 +- src/layout/IHyprLayout.cpp | 14 +-- src/layout/IHyprLayout.hpp | 2 +- src/layout/MasterLayout.cpp | 76 ++++-------- src/layout/MasterLayout.hpp | 2 +- src/managers/KeybindManager.cpp | 81 +++++++----- src/managers/KeybindManager.hpp | 2 +- src/managers/input/IdleInhibitor.cpp | 2 +- src/managers/input/InputManager.cpp | 8 +- src/managers/input/Swipe.cpp | 2 +- src/protocols/ForeignToplevelWlr.cpp | 12 +- src/render/Renderer.cpp | 24 ++-- .../decorations/CHyprGroupBarDecoration.cpp | 2 +- 26 files changed, 325 insertions(+), 330 deletions(-) diff --git a/src/Compositor.cpp b/src/Compositor.cpp index f6e418de..97355d2c 100644 --- a/src/Compositor.cpp +++ b/src/Compositor.cpp @@ -1206,7 +1206,7 @@ PHLWINDOW CCompositor::getWindowFromHandle(uint32_t handle) { PHLWINDOW CCompositor::getFullscreenWindowOnWorkspace(const int& ID) { for (auto& w : m_vWindows) { - if (w->workspaceID() == ID && w->m_bIsFullscreen) + if (w->workspaceID() == ID && w->isFullscreen()) return w; } @@ -1494,7 +1494,7 @@ PHLWINDOW CCompositor::getWindowInDirection(PHLWINDOW pWindow, char dir) { if (!PMONITOR) return nullptr; // ?? - const auto WINDOWIDEALBB = pWindow->m_bIsFullscreen ? CBox{PMONITOR->vecPosition, PMONITOR->vecSize} : pWindow->getWindowIdealBoundingBoxIgnoreReserved(); + const auto WINDOWIDEALBB = pWindow->isFullscreen() ? CBox{PMONITOR->vecPosition, PMONITOR->vecSize} : pWindow->getWindowIdealBoundingBoxIgnoreReserved(); const auto POSA = Vector2D(WINDOWIDEALBB.x, WINDOWIDEALBB.y); const auto SIZEA = Vector2D(WINDOWIDEALBB.width, WINDOWIDEALBB.height); @@ -1507,13 +1507,13 @@ PHLWINDOW CCompositor::getWindowInDirection(PHLWINDOW pWindow, char dir) { // for tiled windows, we calc edges for (auto& w : m_vWindows) { - if (w == pWindow || !w->m_bIsMapped || w->isHidden() || (!w->m_bIsFullscreen && w->m_bIsFloating) || !isWorkspaceVisible(w->m_pWorkspace)) + if (w == pWindow || !w->m_bIsMapped || w->isHidden() || (!w->isFullscreen() && w->m_bIsFloating) || !isWorkspaceVisible(w->m_pWorkspace)) continue; if (pWindow->m_iMonitorID == w->m_iMonitorID && pWindow->m_pWorkspace != w->m_pWorkspace) continue; - if (PWORKSPACE->m_bHasFullscreenWindow && !w->m_bIsFullscreen && !w->m_bCreatedOverFullscreen) + if (PWORKSPACE->m_bHasFullscreenWindow && !w->isFullscreen() && !w->m_bCreatedOverFullscreen) continue; if (!*PMONITORFALLBACK && pWindow->m_iMonitorID != w->m_iMonitorID) @@ -1599,13 +1599,13 @@ PHLWINDOW CCompositor::getWindowInDirection(PHLWINDOW pWindow, char dir) { constexpr float THRESHOLD = 0.3 * M_PI; for (auto& w : m_vWindows) { - if (w == pWindow || !w->m_bIsMapped || w->isHidden() || (!w->m_bIsFullscreen && !w->m_bIsFloating) || !isWorkspaceVisible(w->m_pWorkspace)) + if (w == pWindow || !w->m_bIsMapped || w->isHidden() || (!w->isFullscreen() && !w->m_bIsFloating) || !isWorkspaceVisible(w->m_pWorkspace)) continue; if (pWindow->m_iMonitorID == w->m_iMonitorID && pWindow->m_pWorkspace != w->m_pWorkspace) continue; - if (PWORKSPACE->m_bHasFullscreenWindow && !w->m_bIsFullscreen && !w->m_bCreatedOverFullscreen) + if (PWORKSPACE->m_bHasFullscreenWindow && !w->isFullscreen() && !w->m_bCreatedOverFullscreen) continue; if (!*PMONITORFALLBACK && pWindow->m_iMonitorID != w->m_iMonitorID) @@ -1887,7 +1887,7 @@ void CCompositor::updateWindowAnimatedDecorationValues(PHLWINDOW pWindow) { // opacity const auto PWORKSPACE = pWindow->m_pWorkspace; - if (pWindow->m_bIsFullscreen && PWORKSPACE->m_efFullscreenMode == FULLSCREEN_FULL) { + if (pWindow->isEffectiveInternalFSMode(FSMODE_FULLSCREEN)) { pWindow->m_fActiveInactiveAlpha = pWindow->m_sWindowData.alphaFullscreen.valueOrDefault().applyAlpha(*PFULLSCREENALPHA); } else { if (pWindow == m_pLastWindow) @@ -1957,7 +1957,7 @@ void CCompositor::swapActiveWorkspaces(CMonitor* pMonitorA, CMonitor* pMonitorB) if (w->m_bIsFloating) w->m_vRealPosition = w->m_vRealPosition.goal() - pMonitorA->vecPosition + pMonitorB->vecPosition; - if (w->m_bIsFullscreen) { + if (w->isFullscreen()) { w->m_vRealPosition = pMonitorB->vecPosition; w->m_vRealSize = pMonitorB->vecSize; } @@ -1982,7 +1982,7 @@ void CCompositor::swapActiveWorkspaces(CMonitor* pMonitorA, CMonitor* pMonitorB) if (w->m_bIsFloating) w->m_vRealPosition = w->m_vRealPosition.goal() - pMonitorB->vecPosition + pMonitorA->vecPosition; - if (w->m_bIsFullscreen) { + if (w->isFullscreen()) { w->m_vRealPosition = pMonitorA->vecPosition; w->m_vRealSize = pMonitorA->vecSize; } @@ -2159,7 +2159,7 @@ void CCompositor::moveWorkspaceToMonitor(PHLWORKSPACE pWorkspace, CMonitor* pMon if (w->m_bIsFloating) w->m_vRealPosition = w->m_vRealPosition.goal() - POLDMON->vecPosition + pMonitor->vecPosition; - if (w->m_bIsFullscreen) { + if (w->isFullscreen()) { w->m_vRealPosition = pMonitor->vecPosition; w->m_vRealSize = pMonitor->vecSize; } @@ -2234,12 +2234,12 @@ void CCompositor::updateFullscreenFadeOnWorkspace(PHLWORKSPACE pWorkspace) { for (auto& w : g_pCompositor->m_vWindows) { if (w->m_pWorkspace == pWorkspace) { - if (w->m_bFadingOut || w->m_bPinned || w->m_bIsFullscreen) + if (w->m_bFadingOut || w->m_bPinned || w->isFullscreen()) continue; if (!FULLSCREEN) w->m_fAlpha = 1.f; - else if (!w->m_bIsFullscreen) + else if (!w->isFullscreen()) w->m_fAlpha = !w->m_bCreatedOverFullscreen ? 0.f : 1.f; } } @@ -2249,54 +2249,86 @@ void CCompositor::updateFullscreenFadeOnWorkspace(PHLWORKSPACE pWorkspace) { if (pWorkspace->m_iID == PMONITOR->activeWorkspaceID() || pWorkspace->m_iID == PMONITOR->activeSpecialWorkspaceID()) { for (auto& ls : PMONITOR->m_aLayerSurfaceLayers[ZWLR_LAYER_SHELL_V1_LAYER_TOP]) { if (!ls->fadingOut) - ls->alpha = FULLSCREEN && pWorkspace->m_efFullscreenMode == FULLSCREEN_FULL ? 0.f : 1.f; + ls->alpha = FULLSCREEN && pWorkspace->m_efFullscreenMode == FSMODE_FULLSCREEN ? 0.f : 1.f; } } } -void CCompositor::setWindowFullscreen(PHLWINDOW pWindow, bool on, eFullscreenMode mode) { +void CCompositor::changeWindowFullscreenModeInternal(const PHLWINDOW PWINDOW, const eFullscreenMode MODE, const bool ON) { + setWindowFullscreenInternal( + PWINDOW, (eFullscreenMode)(ON ? (uint8_t)PWINDOW->m_sFullscreenState.internal | (uint8_t)MODE : ((uint8_t)PWINDOW->m_sFullscreenState.internal & (uint8_t)~MODE))); +} + +void CCompositor::changeWindowFullscreenModeClient(const PHLWINDOW PWINDOW, const eFullscreenMode MODE, const bool ON) { + setWindowFullscreenClient(PWINDOW, + (eFullscreenMode)(ON ? (uint8_t)PWINDOW->m_sFullscreenState.client | (uint8_t)MODE : ((uint8_t)PWINDOW->m_sFullscreenState.client & (uint8_t)~MODE))); +} + +void CCompositor::setWindowFullscreenInternal(const PHLWINDOW PWINDOW, const eFullscreenMode MODE) { + if (PWINDOW->m_sWindowData.syncFullscreen.valueOrDefault()) + setWindowFullscreenState(PWINDOW, sFullscreenState{.internal = MODE, .client = MODE}); + else + setWindowFullscreenState(PWINDOW, sFullscreenState{.internal = MODE, .client = PWINDOW->m_sFullscreenState.client}); +} + +void CCompositor::setWindowFullscreenClient(const PHLWINDOW PWINDOW, const eFullscreenMode MODE) { + if (PWINDOW->m_sWindowData.syncFullscreen.valueOrDefault()) + setWindowFullscreenState(PWINDOW, sFullscreenState{.internal = MODE, .client = MODE}); + else + setWindowFullscreenState(PWINDOW, sFullscreenState{.internal = PWINDOW->m_sFullscreenState.internal, .client = MODE}); +} + +void CCompositor::setWindowFullscreenState(const PHLWINDOW PWINDOW, sFullscreenState state) { static auto PNODIRECTSCANOUT = CConfigValue("misc:no_direct_scanout"); - if (!validMapped(pWindow) || g_pCompositor->m_bUnsafeState) + if (!validMapped(PWINDOW) || g_pCompositor->m_bUnsafeState) return; - if (pWindow->m_bPinned) { - Debug::log(LOG, "Pinned windows cannot be fullscreen'd"); + state.internal = std::clamp(state.internal, (eFullscreenMode)0, FSMODE_MAX); + state.client = std::clamp(state.client, (eFullscreenMode)0, FSMODE_MAX); + + const auto PMONITOR = getMonitorFromID(PWINDOW->m_iMonitorID); + const auto PWORKSPACE = PWINDOW->m_pWorkspace; + + const eFullscreenMode CURRENT_EFFECTIVE_MODE = (eFullscreenMode)std::bit_floor((uint8_t)PWINDOW->m_sFullscreenState.internal); + const eFullscreenMode EFFECTIVE_MODE = (eFullscreenMode)std::bit_floor((uint8_t)state.internal); + + const bool CHANGEINTERNAL = !(PWINDOW->m_bPinned || CURRENT_EFFECTIVE_MODE == EFFECTIVE_MODE || (PWORKSPACE->m_bHasFullscreenWindow && !PWINDOW->isFullscreen())); + + // TODO: update the state on syncFullscreen changes + if (!CHANGEINTERNAL && PWINDOW->m_sWindowData.syncFullscreen.valueOrDefault()) return; - } - if (pWindow->m_bIsFullscreen == on) { - Debug::log(LOG, "Window is already in the required fullscreen state"); + PWINDOW->m_sFullscreenState.client = state.client; + g_pXWaylandManager->setWindowFullscreen(PWINDOW, state.client & FSMODE_FULLSCREEN); + + if (!CHANGEINTERNAL) return; - } - const auto PMONITOR = getMonitorFromID(pWindow->m_iMonitorID); + g_pLayoutManager->getCurrentLayout()->fullscreenRequestForWindow(PWINDOW, CURRENT_EFFECTIVE_MODE, EFFECTIVE_MODE); - const auto PWORKSPACE = pWindow->m_pWorkspace; + PWINDOW->m_sFullscreenState.internal = state.internal; + PWORKSPACE->m_efFullscreenMode = EFFECTIVE_MODE; + PWORKSPACE->m_bHasFullscreenWindow = EFFECTIVE_MODE != FSMODE_NONE; - const auto MODE = mode == FULLSCREEN_INVALID ? PWORKSPACE->m_efFullscreenMode : mode; + g_pEventManager->postEvent(SHyprIPCEvent{"fullscreen", std::to_string((int)EFFECTIVE_MODE != FSMODE_NONE)}); + EMIT_HOOK_EVENT("fullscreen", PWINDOW); - if (PWORKSPACE->m_bHasFullscreenWindow && on) { - Debug::log(LOG, "Rejecting fullscreen ON on a fullscreen workspace"); - return; - } - - g_pLayoutManager->getCurrentLayout()->fullscreenRequestForWindow(pWindow, MODE, on); - - g_pXWaylandManager->setWindowFullscreen(pWindow, pWindow->shouldSendFullscreenState()); - - updateWindowAnimatedDecorationValues(pWindow); + g_pLayoutManager->getCurrentLayout()->recalculateMonitor(PWINDOW->m_iMonitorID); + PWINDOW->updateWindowDecos(); + updateWindowAnimatedDecorationValues(PWINDOW); // make all windows on the same workspace under the fullscreen window for (auto& w : m_vWindows) { - if (w->m_pWorkspace == PWORKSPACE && !w->m_bIsFullscreen && !w->m_bFadingOut && !w->m_bPinned) + if (w->m_pWorkspace == PWORKSPACE && !w->isFullscreen() && !w->m_bFadingOut && !w->m_bPinned) w->m_bCreatedOverFullscreen = false; } + updateFullscreenFadeOnWorkspace(PWORKSPACE); - g_pXWaylandManager->setWindowSize(pWindow, pWindow->m_vRealSize.goal(), true); + g_pXWaylandManager->setWindowSize(PWINDOW, PWINDOW->m_vRealSize.goal(), true); - forceReportSizesToWindowsOnWorkspace(pWindow->workspaceID()); + forceReportSizesToWindowsOnWorkspace(PWINDOW->workspaceID()); g_pInputManager->recheckIdleInhibitorStatus(); @@ -2307,7 +2339,7 @@ void CCompositor::setWindowFullscreen(PHLWINDOW pWindow, bool on, eFullscreenMod // send a scanout tranche if we are entering fullscreen, and send a regular one if we aren't. // ignore if DS is disabled. if (!*PNODIRECTSCANOUT) - g_pHyprRenderer->setSurfaceScanoutMode(pWindow->m_pWLSurface->resource(), on ? PMONITOR->self.lock() : nullptr); + g_pHyprRenderer->setSurfaceScanoutMode(PWINDOW->m_pWLSurface->resource(), EFFECTIVE_MODE != FSMODE_NONE ? PMONITOR->self.lock() : nullptr); g_pConfigManager->ensureVRR(PMONITOR); } @@ -2639,11 +2671,11 @@ void CCompositor::moveWindowToWorkspaceSafe(PHLWINDOW pWindow, PHLWORKSPACE pWor if (pWindow->m_bPinned && pWorkspace->m_bIsSpecialWorkspace) return; - const bool FULLSCREEN = pWindow->m_bIsFullscreen; - const auto FULLSCREENMODE = pWindow->m_pWorkspace->m_efFullscreenMode; + const bool FULLSCREEN = pWindow->isFullscreen(); + const auto FULLSCREENMODE = pWindow->m_sFullscreenState.internal; if (FULLSCREEN) - setWindowFullscreen(pWindow, false, FULLSCREEN_FULL); + setWindowFullscreenInternal(pWindow, FSMODE_NONE); if (!pWindow->m_bIsFloating) { g_pLayoutManager->getCurrentLayout()->onWindowRemovedTiling(pWindow); @@ -2676,7 +2708,7 @@ void CCompositor::moveWindowToWorkspaceSafe(PHLWINDOW pWindow, PHLWORKSPACE pWor } if (FULLSCREEN) - setWindowFullscreen(pWindow, true, FULLSCREENMODE); + setWindowFullscreenInternal(pWindow, FULLSCREENMODE); g_pCompositor->updateWorkspaceWindows(pWorkspace->m_iID); g_pCompositor->updateWorkspaceWindows(pWindow->workspaceID()); diff --git a/src/Compositor.hpp b/src/Compositor.hpp index da390b44..295935c4 100644 --- a/src/Compositor.hpp +++ b/src/Compositor.hpp @@ -146,7 +146,11 @@ class CCompositor { void swapActiveWorkspaces(CMonitor*, CMonitor*); CMonitor* getMonitorFromString(const std::string&); bool workspaceIDOutOfBounds(const int64_t&); - void setWindowFullscreen(PHLWINDOW, bool, eFullscreenMode mode = FULLSCREEN_INVALID); + void setWindowFullscreenInternal(const PHLWINDOW PWINDOW, const eFullscreenMode MODE); + void setWindowFullscreenClient(const PHLWINDOW PWINDOW, const eFullscreenMode MODE); + void setWindowFullscreenState(const PHLWINDOW PWINDOW, const sFullscreenState state); + void changeWindowFullscreenModeInternal(const PHLWINDOW PWINDOW, const eFullscreenMode MODE, const bool ON); + void changeWindowFullscreenModeClient(const PHLWINDOW PWINDOW, const eFullscreenMode MODE, const bool ON); void updateFullscreenFadeOnWorkspace(PHLWORKSPACE); PHLWINDOW getX11Parent(PHLWINDOW); void scheduleFrameForMonitor(CMonitor*, Aquamarine::IOutput::scheduleFrameReason reason = Aquamarine::IOutput::AQ_SCHEDULE_CLIENT_UNKNOWN); diff --git a/src/config/ConfigManager.cpp b/src/config/ConfigManager.cpp index 65eab579..fe3af8c0 100644 --- a/src/config/ConfigManager.cpp +++ b/src/config/ConfigManager.cpp @@ -1100,7 +1100,7 @@ std::vector CConfigManager::getMatchingRules(PHLWINDOW pWindow, boo // since some rules will be applied later, we need to store some flags bool hasFloating = pWindow->m_bIsFloating; - bool hasFullscreen = pWindow->m_bIsFullscreen; + bool hasFullscreen = pWindow->isFullscreen(); // local tags for dynamic tag rule match auto tags = pWindow->m_tags; @@ -1448,7 +1448,7 @@ void CConfigManager::ensureVRR(CMonitor* pMonitor) { if (!PWORKSPACE) return; // ??? - const auto WORKSPACEFULL = PWORKSPACE->m_bHasFullscreenWindow && PWORKSPACE->m_efFullscreenMode == FULLSCREEN_FULL; + const auto WORKSPACEFULL = PWORKSPACE->m_bHasFullscreenWindow && (PWORKSPACE->m_efFullscreenMode & FSMODE_FULLSCREEN); if (WORKSPACEFULL) { m->output->state->setAdaptiveSync(true); @@ -2099,11 +2099,11 @@ std::optional CConfigManager::handleUnbind(const std::string& comma bool windowRuleValid(const std::string& RULE) { static const auto rules = std::unordered_set{ - "fakefullscreen", "float", "fullscreen", "maximize", "noinitialfocus", "pin", "stayfocused", "tile", + "float", "fullscreen", "maximize", "noinitialfocus", "pin", "stayfocused", "tile", }; static const auto rulesPrefix = std::vector{ - "animation", "bordercolor", "bordersize", "center", "group", "idleinhibit", "maxsize", "minsize", "monitor", "move", - "opacity", "plugin:", "pseudo", "rounding", "size", "suppressevent", "tag", "workspace", "xray", + "animation", "bordercolor", "bordersize", "center", "fullscreenstate", "group", "idleinhibit", "maxsize", "minsize", "monitor", + "move", "opacity", "plugin:", "pseudo", "rounding", "size", "suppressevent", "tag", "workspace", "xray", }; const auto VALS = CVarList(RULE, 2, ' '); diff --git a/src/config/ConfigManager.hpp b/src/config/ConfigManager.hpp index 454a12c0..75dea9ef 100644 --- a/src/config/ConfigManager.hpp +++ b/src/config/ConfigManager.hpp @@ -182,6 +182,7 @@ class CConfigManager { {"noshortcutsinhibit", [](PHLWINDOW pWindow) { return &pWindow->m_sWindowData.noShortcutsInhibit; }}, {"opaque", [](PHLWINDOW pWindow) { return &pWindow->m_sWindowData.opaque; }}, {"forcergbx", [](PHLWINDOW pWindow) { return &pWindow->m_sWindowData.RGBX; }}, + {"syncfullscreen", [](PHLWINDOW pWindow) { return &pWindow->m_sWindowData.syncFullscreen; }}, {"immediate", [](PHLWINDOW pWindow) { return &pWindow->m_sWindowData.tearing; }}, {"xray", [](PHLWINDOW pWindow) { return &pWindow->m_sWindowData.xray; }}, }; diff --git a/src/debug/HyprCtl.cpp b/src/debug/HyprCtl.cpp index d89d1772..cf873e6c 100644 --- a/src/debug/HyprCtl.cpp +++ b/src/debug/HyprCtl.cpp @@ -240,8 +240,7 @@ std::string CHyprCtl::getWindowData(PHLWINDOW w, eHyprCtlOutputFormat format) { "xwayland": {}, "pinned": {}, "fullscreen": {}, - "fullscreenMode": {}, - "fakeFullscreen": {}, + "fullscreenClient": {}, "grouped": [{}], "tags": [{}], "swallowing": "0x{:x}", @@ -252,19 +251,19 @@ std::string CHyprCtl::getWindowData(PHLWINDOW w, eHyprCtlOutputFormat format) { escapeJSONStrings(!w->m_pWorkspace ? "" : w->m_pWorkspace->m_szName), ((int)w->m_bIsFloating == 1 ? "true" : "false"), (w->m_bIsPseudotiled ? "true" : "false"), (int64_t)w->m_iMonitorID, escapeJSONStrings(w->m_szClass), escapeJSONStrings(w->m_szTitle), escapeJSONStrings(w->m_szInitialClass), escapeJSONStrings(w->m_szInitialTitle), w->getPID(), ((int)w->m_bIsX11 == 1 ? "true" : "false"), (w->m_bPinned ? "true" : "false"), - (w->m_bIsFullscreen ? "true" : "false"), (w->m_bIsFullscreen ? (w->m_pWorkspace ? (int)w->m_pWorkspace->m_efFullscreenMode : 0) : 0), - w->m_bFakeFullscreenState ? "true" : "false", getGroupedData(w, format), getTagsData(w, format), (uintptr_t)w->m_pSwallowed.lock().get(), getFocusHistoryID(w)); + (uint8_t)w->m_sFullscreenState.internal, (uint8_t)w->m_sFullscreenState.client, getGroupedData(w, format), getTagsData(w, format), + (uintptr_t)w->m_pSwallowed.lock().get(), getFocusHistoryID(w)); } else { return std::format( "Window {:x} -> {}:\n\tmapped: {}\n\thidden: {}\n\tat: {},{}\n\tsize: {},{}\n\tworkspace: {} ({})\n\tfloating: {}\n\tpseudo: {}\n\tmonitor: {}\n\tclass: {}\n\ttitle: " "{}\n\tinitialClass: {}\n\tinitialTitle: {}\n\tpid: " "{}\n\txwayland: {}\n\tpinned: " - "{}\n\tfullscreen: {}\n\tfullscreenmode: {}\n\tfakefullscreen: {}\n\tgrouped: {}\n\ttags: {}\n\tswallowing: {:x}\n\tfocusHistoryID: {}\n\n", + "{}\n\tfullscreen: {}\n\tfullscreenClient: {}\n\tgrouped: {}\n\ttags: {}\n\tswallowing: {:x}\n\tfocusHistoryID: {}\n\n", (uintptr_t)w.get(), w->m_szTitle, (int)w->m_bIsMapped, (int)w->isHidden(), (int)w->m_vRealPosition.goal().x, (int)w->m_vRealPosition.goal().y, (int)w->m_vRealSize.goal().x, (int)w->m_vRealSize.goal().y, w->m_pWorkspace ? w->workspaceID() : WORKSPACE_INVALID, (!w->m_pWorkspace ? "" : w->m_pWorkspace->m_szName), (int)w->m_bIsFloating, (int)w->m_bIsPseudotiled, (int64_t)w->m_iMonitorID, w->m_szClass, w->m_szTitle, w->m_szInitialClass, w->m_szInitialTitle, w->getPID(), - (int)w->m_bIsX11, (int)w->m_bPinned, (int)w->m_bIsFullscreen, (w->m_bIsFullscreen ? (w->m_pWorkspace ? w->m_pWorkspace->m_efFullscreenMode : 0) : 0), - (int)w->m_bFakeFullscreenState, getGroupedData(w, format), getTagsData(w, format), (uintptr_t)w->m_pSwallowed.lock().get(), getFocusHistoryID(w)); + (int)w->m_bIsX11, (int)w->m_bPinned, (uint8_t)w->m_sFullscreenState.internal, (uint8_t)w->m_sFullscreenState.client, getGroupedData(w, format), getTagsData(w, format), + (uintptr_t)w->m_pSwallowed.lock().get(), getFocusHistoryID(w)); } } diff --git a/src/desktop/LayerSurface.cpp b/src/desktop/LayerSurface.cpp index 4426491d..80138910 100644 --- a/src/desktop/LayerSurface.cpp +++ b/src/desktop/LayerSurface.cpp @@ -165,7 +165,7 @@ void CLayerSurface::onMap() { CBox geomFixed = {geometry.x + PMONITOR->vecPosition.x, geometry.y + PMONITOR->vecPosition.y, geometry.width, geometry.height}; g_pHyprRenderer->damageBox(&geomFixed); const auto WORKSPACE = PMONITOR->activeWorkspace; - const bool FULLSCREEN = WORKSPACE->m_bHasFullscreenWindow && WORKSPACE->m_efFullscreenMode == FULLSCREEN_FULL; + const bool FULLSCREEN = WORKSPACE->m_bHasFullscreenWindow && WORKSPACE->m_efFullscreenMode == FSMODE_FULLSCREEN; startAnimation(!(layer == ZWLR_LAYER_SHELL_V1_LAYER_TOP && FULLSCREEN && !GRABSFOCUS)); readyToDelete = false; diff --git a/src/desktop/Window.cpp b/src/desktop/Window.cpp index f635d367..9316959d 100644 --- a/src/desktop/Window.cpp +++ b/src/desktop/Window.cpp @@ -192,7 +192,7 @@ CBox CWindow::getWindowIdealBoundingBoxIgnoreReserved() { auto POS = m_vPosition; auto SIZE = m_vSize; - if (m_bIsFullscreen) { + if (isFullscreen()) { POS = PMONITOR->vecPosition; SIZE = PMONITOR->vecSize; @@ -970,8 +970,9 @@ void CWindow::setGroupCurrent(PHLWINDOW pWindow) { return; const auto PCURRENT = getGroupCurrent(); - const bool FULLSCREEN = PCURRENT->m_bIsFullscreen; + const bool FULLSCREEN = PCURRENT->isFullscreen(); const auto WORKSPACE = PCURRENT->m_pWorkspace; + const auto MODE = PCURRENT->m_sFullscreenState.client; const auto PWINDOWSIZE = PCURRENT->m_vRealSize.goal(); const auto PWINDOWPOS = PCURRENT->m_vRealPosition.goal(); @@ -979,7 +980,7 @@ void CWindow::setGroupCurrent(PHLWINDOW pWindow) { const auto CURRENTISFOCUS = PCURRENT == g_pCompositor->m_pLastWindow.lock(); if (FULLSCREEN) - g_pCompositor->setWindowFullscreen(PCURRENT, false, WORKSPACE->m_efFullscreenMode); + g_pCompositor->setWindowFullscreenInternal(PCURRENT, FSMODE_NONE); PCURRENT->setHidden(true); pWindow->setHidden(false); // can remove m_pLastWindow @@ -997,7 +998,7 @@ void CWindow::setGroupCurrent(PHLWINDOW pWindow) { g_pCompositor->focusWindow(pWindow); if (FULLSCREEN) - g_pCompositor->setWindowFullscreen(pWindow, true, WORKSPACE->m_efFullscreenMode); + g_pCompositor->setWindowFullscreenInternal(pWindow, MODE); g_pHyprRenderer->damageWindow(pWindow); @@ -1140,7 +1141,7 @@ void CWindow::updateWindowData(const SWorkspaceRule& workspaceRule) { } int CWindow::getRealBorderSize() { - if (m_sWindowData.noBorder.valueOrDefault() || (m_pWorkspace && m_bIsFullscreen && (m_pWorkspace->m_efFullscreenMode == FULLSCREEN_FULL))) + if (m_sWindowData.noBorder.valueOrDefault() || (m_pWorkspace && isEffectiveInternalFSMode(FSMODE_FULLSCREEN))) return 0; static auto PBORDERSIZE = CConfigValue("general:border_size"); @@ -1153,11 +1154,6 @@ bool CWindow::canBeTorn() { return m_sWindowData.tearing.valueOr(m_bTearingHint) && *PTEARING; } -bool CWindow::shouldSendFullscreenState() { - const auto MODE = m_pWorkspace->m_efFullscreenMode; - return m_bDontSendFullscreen ? false : (m_bFakeFullscreenState || (m_bIsFullscreen && (MODE == FULLSCREEN_FULL))); -} - void CWindow::setSuspended(bool suspend) { if (suspend == m_bSuspended) return; @@ -1184,7 +1180,7 @@ void CWindow::setAnimationsToMove() { void CWindow::onWorkspaceAnimUpdate() { // clip box for animated offsets - if (!m_bIsFloating || m_bPinned || m_bIsFullscreen) { + if (!m_bIsFloating || m_bPinned || isFullscreen()) { m_vFloatingOffset = Vector2D(0, 0); return; } @@ -1238,6 +1234,14 @@ int CWindow::surfacesCount() { return no; } +bool CWindow::isFullscreen() { + return m_sFullscreenState.internal != FSMODE_NONE; +} + +bool CWindow::isEffectiveInternalFSMode(const eFullscreenMode MODE) { + return (eFullscreenMode)std::bit_floor((uint8_t)m_sFullscreenState.internal) == MODE; +} + int CWindow::workspaceID() { return m_pWorkspace ? m_pWorkspace->m_iID : m_iLastWorkspace; } @@ -1315,19 +1319,17 @@ void CWindow::onUpdateState() { if (requestsFS.has_value() && !(m_eSuppressedEvents & SUPPRESS_FULLSCREEN)) { bool fs = requestsFS.value(); - - if (fs != m_bIsFullscreen && m_bIsMapped) - g_pCompositor->setWindowFullscreen(m_pSelf.lock(), fs, FULLSCREEN_FULL); + if (m_bIsMapped) { + g_pCompositor->changeWindowFullscreenModeClient(m_pSelf.lock(), FSMODE_FULLSCREEN, requestsFS.value()); + } if (!m_bIsMapped) m_bWantsInitialFullscreen = fs; } if (requestsMX.has_value() && !(m_eSuppressedEvents & SUPPRESS_MAXIMIZE)) { - bool fs = requestsMX.value(); - - if (fs != m_bIsFullscreen && m_bIsMapped) - g_pCompositor->setWindowFullscreen(m_pSelf.lock(), fs, FULLSCREEN_MAXIMIZED); + if (m_bIsMapped) + g_pCompositor->changeWindowFullscreenModeClient(m_pSelf.lock(), FSMODE_MAXIMIZED, requestsMX.value()); } } @@ -1432,7 +1434,7 @@ void CWindow::onX11Configure(CBox box) { g_pHyprRenderer->damageWindow(m_pSelf.lock()); - if (!m_bIsFloating || m_bIsFullscreen || g_pInputManager->currentlyDraggedWindow == m_pSelf) { + if (!m_bIsFloating || isFullscreen() || g_pInputManager->currentlyDraggedWindow == m_pSelf) { g_pXWaylandManager->setWindowSize(m_pSelf.lock(), m_vRealSize.goal(), true); g_pInputManager->refocus(); g_pHyprRenderer->damageWindow(m_pSelf.lock()); diff --git a/src/desktop/Window.hpp b/src/desktop/Window.hpp index 108b804c..11bf662a 100644 --- a/src/desktop/Window.hpp +++ b/src/desktop/Window.hpp @@ -16,6 +16,7 @@ #include "Popup.hpp" #include "Subsurface.hpp" #include "WLSurface.hpp" +#include "Workspace.hpp" class CXDGSurfaceResource; class CXWaylandSurface; @@ -170,6 +171,7 @@ struct SWindowData { CWindowOverridableVar noShortcutsInhibit = false; CWindowOverridableVar opaque = false; CWindowOverridableVar RGBX = false; + CWindowOverridableVar syncFullscreen = true; CWindowOverridableVar tearing = false; CWindowOverridableVar xray = false; @@ -208,6 +210,11 @@ struct SInitialWorkspaceToken { std::string workspace; }; +struct sFullscreenState { + eFullscreenMode internal = FSMODE_NONE; + eFullscreenMode client = FSMODE_NONE; +}; + class CWindow { public: static PHLWINDOW create(SP); @@ -256,24 +263,23 @@ class CWindow { Vector2D m_vPseudoSize = Vector2D(1280, 720); // for recovering relative cursor position - Vector2D m_vRelativeCursorCoordsOnLastWarp = Vector2D(-1, -1); + Vector2D m_vRelativeCursorCoordsOnLastWarp = Vector2D(-1, -1); - bool m_bFirstMap = false; // for layouts - bool m_bIsFloating = false; - bool m_bDraggingTiled = false; // for dragging around tiled windows - bool m_bIsFullscreen = false; - bool m_bDontSendFullscreen = false; - bool m_bWasMaximized = false; - uint64_t m_iMonitorID = -1; - std::string m_szTitle = ""; - std::string m_szClass = ""; - std::string m_szInitialTitle = ""; - std::string m_szInitialClass = ""; - PHLWORKSPACE m_pWorkspace; + bool m_bFirstMap = false; // for layouts + bool m_bIsFloating = false; + bool m_bDraggingTiled = false; // for dragging around tiled windows + bool m_bWasMaximized = false; + sFullscreenState m_sFullscreenState = {.internal = FSMODE_NONE, .client = FSMODE_NONE}; + uint64_t m_iMonitorID = -1; + std::string m_szTitle = ""; + std::string m_szClass = ""; + std::string m_szInitialTitle = ""; + std::string m_szInitialClass = ""; + PHLWORKSPACE m_pWorkspace; - bool m_bIsMapped = false; + bool m_bIsMapped = false; - bool m_bRequestsFloat = false; + bool m_bRequestsFloat = false; // This is for fullscreen apps bool m_bCreatedOverFullscreen = false; @@ -322,9 +328,6 @@ class CWindow { // urgency hint bool m_bIsUrgent = false; - // fakefullscreen - bool m_bFakeFullscreenState = false; - // for proper cycling. While cycling we can't just move the pointers, so we need to keep track of the last cycled window. PHLWINDOWREF m_pLastCycledWindow; @@ -416,7 +419,6 @@ class CWindow { bool opaque(); float rounding(); bool canBeTorn(); - bool shouldSendFullscreenState(); void setSuspended(bool suspend); bool visibleOnMonitor(CMonitor* pMonitor); int workspaceID(); @@ -424,6 +426,9 @@ class CWindow { void activate(bool force = false); int surfacesCount(); + bool isFullscreen(); + bool isEffectiveInternalFSMode(const eFullscreenMode); + int getRealBorderSize(); void updateWindowData(); void updateWindowData(const struct SWorkspaceRule&); diff --git a/src/desktop/Workspace.cpp b/src/desktop/Workspace.cpp index 34db914e..a08f1804 100644 --- a/src/desktop/Workspace.cpp +++ b/src/desktop/Workspace.cpp @@ -480,16 +480,11 @@ bool CWorkspace::matchesStaticSelector(const std::string& selector_) { return false; break; case 0: // fullscreen full - if (!m_bHasFullscreenWindow || m_efFullscreenMode != FULLSCREEN_FULL) + if (!m_bHasFullscreenWindow || m_efFullscreenMode != FSMODE_FULLSCREEN) return false; break; case 1: // maximized - if (!m_bHasFullscreenWindow || m_efFullscreenMode != FULLSCREEN_MAXIMIZED) - return false; - break; - case 2: // fullscreen without sending fullscreen state to window - if (!m_bHasFullscreenWindow || m_efFullscreenMode != FULLSCREEN_FULL || !g_pCompositor->getFullscreenWindowOnWorkspace(m_iID) || - !g_pCompositor->getFullscreenWindowOnWorkspace(m_iID)->m_bDontSendFullscreen) + if (!m_bHasFullscreenWindow || m_efFullscreenMode != FSMODE_MAXIMIZED) return false; break; default: break; diff --git a/src/desktop/Workspace.hpp b/src/desktop/Workspace.hpp index bb5cd441..3e9ac8a8 100644 --- a/src/desktop/Workspace.hpp +++ b/src/desktop/Workspace.hpp @@ -7,9 +7,10 @@ #include "../helpers/MiscFunctions.hpp" enum eFullscreenMode : int8_t { - FULLSCREEN_INVALID = -1, - FULLSCREEN_FULL = 0, - FULLSCREEN_MAXIMIZED + FSMODE_NONE = 0, + FSMODE_MAXIMIZED = 1 << 0, + FSMODE_FULLSCREEN = 1 << 1, + FSMODE_MAX = (1 << 2) - 1 }; class CWindow; @@ -31,7 +32,7 @@ class CWorkspace { SWorkspaceIDName m_sPrevWorkspace, m_sPrevWorkspacePerMonitor; bool m_bHasFullscreenWindow = false; - eFullscreenMode m_efFullscreenMode = FULLSCREEN_FULL; + eFullscreenMode m_efFullscreenMode = FSMODE_NONE; wl_array m_wlrCoordinateArr; diff --git a/src/events/Windows.cpp b/src/events/Windows.cpp index b2abb65c..71ad4ba1 100644 --- a/src/events/Windows.cpp +++ b/src/events/Windows.cpp @@ -133,12 +133,11 @@ void Events::listener_mapWindow(void* owner, void* data) { } // window rules - PWINDOW->m_vMatchedRules = g_pConfigManager->getMatchingRules(PWINDOW, false); - bool requestsFullscreen = PWINDOW->m_bWantsInitialFullscreen || (PWINDOW->m_bIsX11 && PWINDOW->m_pXWaylandSurface->fullscreen); - bool requestsFakeFullscreen = false; - bool requestsMaximize = false; - bool overridingNoFullscreen = false; - bool overridingNoMaximize = false; + PWINDOW->m_vMatchedRules = g_pConfigManager->getMatchingRules(PWINDOW, false); + std::optional requestedInternalFSMode, requestedClientFSMode; + std::optional requestedFSState; + if (PWINDOW->m_bWantsInitialFullscreen || (PWINDOW->m_bIsX11 && PWINDOW->m_pXWaylandSurface->fullscreen)) + requestedClientFSMode = FSMODE_FULLSCREEN; for (auto& r : PWINDOW->m_vMatchedRules) { if (r.szRule.starts_with("monitor")) { @@ -199,6 +198,16 @@ void Events::listener_mapWindow(void* owner, void* data) { PWINDOW->m_bIsPseudotiled = true; } else if (r.szRule.starts_with("noinitialfocus")) { PWINDOW->m_bNoInitialFocus = true; + } else if (r.szRule.starts_with("fullscreenstate")) { + const auto ARGS = CVarList(r.szRule.substr(r.szRule.find_first_of(' ') + 1), 2, ' '); + int internalMode, clientMode; + try { + internalMode = std::stoi(ARGS[0]); + } catch (std::exception& e) { internalMode = 0; } + try { + clientMode = std::stoi(ARGS[1]); + } catch (std::exception& e) { clientMode = 0; } + requestedFSState = sFullscreenState{.internal = (eFullscreenMode)internalMode, .client = (eFullscreenMode)clientMode}; } else if (r.szRule.starts_with("suppressevent")) { CVarList vars(r.szRule, 0, 's', true); for (size_t i = 1; i < vars.size(); ++i) { @@ -213,16 +222,12 @@ void Events::listener_mapWindow(void* owner, void* data) { else Debug::log(ERR, "Error while parsing suppressevent windowrule: unknown event type {}", vars[i]); } - } else if (r.szRule == "fullscreen") { - requestsFullscreen = true; - overridingNoFullscreen = true; - } else if (r.szRule == "fakefullscreen") { - requestsFakeFullscreen = true; } else if (r.szRule == "pin") { PWINDOW->m_bPinned = true; + } else if (r.szRule == "fullscreen") { + requestedInternalFSMode = FSMODE_FULLSCREEN; } else if (r.szRule == "maximize") { - requestsMaximize = true; - overridingNoMaximize = true; + requestedInternalFSMode = FSMODE_MAXIMIZED; } else if (r.szRule == "stayfocused") { PWINDOW->m_bStayFocused = true; } else if (r.szRule.starts_with("group")) { @@ -461,17 +466,14 @@ void Events::listener_mapWindow(void* owner, void* data) { const auto PLSFROMFOCUS = g_pCompositor->getLayerSurfaceFromSurface(g_pCompositor->m_pLastFocus.lock()); if (PLSFROMFOCUS && PLSFROMFOCUS->layerSurface->current.interactivity != ZWLR_LAYER_SURFACE_V1_KEYBOARD_INTERACTIVITY_NONE) PWINDOW->m_bNoInitialFocus = true; - if (PWINDOW->m_pWorkspace->m_bHasFullscreenWindow && !requestsFullscreen && !PWINDOW->m_bIsFloating) { + + if (PWINDOW->m_pWorkspace->m_bHasFullscreenWindow && !requestedInternalFSMode.has_value() && !requestedClientFSMode.has_value() && !PWINDOW->m_bIsFloating) { if (*PNEWTAKESOVERFS == 0) PWINDOW->m_bNoInitialFocus = true; + else if (*PNEWTAKESOVERFS == 1) + requestedInternalFSMode = PWINDOW->m_pWorkspace->m_efFullscreenMode; else if (*PNEWTAKESOVERFS == 2) - g_pCompositor->setWindowFullscreen(g_pCompositor->getFullscreenWindowOnWorkspace(PWINDOW->m_pWorkspace->m_iID), false, FULLSCREEN_INVALID); - else if (PWINDOW->m_pWorkspace->m_efFullscreenMode == FULLSCREEN_MAXIMIZED) { - requestsMaximize = true; - if (*PNEWTAKESOVERFS == 1) - overridingNoMaximize = true; - } else - requestsFullscreen = true; + g_pCompositor->setWindowFullscreenInternal(g_pCompositor->getFullscreenWindowOnWorkspace(PWINDOW->m_pWorkspace->m_iID), FSMODE_NONE); } if (!PWINDOW->m_sWindowData.noFocus.valueOrDefault() && !PWINDOW->m_bNoInitialFocus && @@ -485,24 +487,27 @@ void Events::listener_mapWindow(void* owner, void* data) { PWINDOW->m_fDimPercent.setValueAndWarp(0); } - if ((requestsFullscreen && (!(PWINDOW->m_eSuppressedEvents & SUPPRESS_FULLSCREEN) || overridingNoFullscreen)) || - (requestsMaximize && (!(PWINDOW->m_eSuppressedEvents & SUPPRESS_MAXIMIZE) || overridingNoMaximize)) || requestsFakeFullscreen) { - // fix fullscreen on requested (basically do a switcheroo) - if (PWINDOW->m_pWorkspace->m_bHasFullscreenWindow) { - const auto PFULLWINDOW = g_pCompositor->getFullscreenWindowOnWorkspace(PWINDOW->m_pWorkspace->m_iID); - g_pCompositor->setWindowFullscreen(PFULLWINDOW, false, FULLSCREEN_FULL); - } + if (requestedClientFSMode.has_value() && !(PWINDOW->m_eSuppressedEvents & SUPPRESS_FULLSCREEN)) + requestedClientFSMode = (eFullscreenMode)((uint8_t)requestedClientFSMode.value_or(FSMODE_NONE) & ~(uint8_t)FSMODE_FULLSCREEN); + if (requestedClientFSMode.has_value() && !(PWINDOW->m_eSuppressedEvents & SUPPRESS_MAXIMIZE)) + requestedClientFSMode = (eFullscreenMode)((uint8_t)requestedClientFSMode.value_or(FSMODE_NONE) & ~(uint8_t)FSMODE_MAXIMIZED); - if (requestsFakeFullscreen && !PWINDOW->m_bFakeFullscreenState) { - PWINDOW->m_bFakeFullscreenState = !PWINDOW->m_bFakeFullscreenState; - g_pXWaylandManager->setWindowFullscreen(PWINDOW, true); - } else { - overridingNoFullscreen = false; - overridingNoMaximize = false; - PWINDOW->m_vRealPosition.warp(); - PWINDOW->m_vRealSize.warp(); - g_pCompositor->setWindowFullscreen(PWINDOW, true, requestsFullscreen ? FULLSCREEN_FULL : FULLSCREEN_MAXIMIZED); - } + if (!PWINDOW->m_bNoInitialFocus && (requestedInternalFSMode.has_value() || requestedClientFSMode.has_value() || requestedFSState.has_value())) { + // fix fullscreen on requested (basically do a switcheroo) + if (PWINDOW->m_pWorkspace->m_bHasFullscreenWindow) + g_pCompositor->setWindowFullscreenInternal(g_pCompositor->getFullscreenWindowOnWorkspace(PWINDOW->m_pWorkspace->m_iID), FSMODE_NONE); + + PWINDOW->m_vRealPosition.warp(); + PWINDOW->m_vRealSize.warp(); + if (requestedFSState.has_value()) { + PWINDOW->m_sWindowData.syncFullscreen = CWindowOverridableVar(false, PRIORITY_WINDOW_RULE); + g_pCompositor->setWindowFullscreenState(PWINDOW, requestedFSState.value()); + } else if (requestedInternalFSMode.has_value() && requestedClientFSMode.has_value() && !PWINDOW->m_sWindowData.syncFullscreen.valueOrDefault()) + g_pCompositor->setWindowFullscreenState(PWINDOW, sFullscreenState{.internal = requestedInternalFSMode.value(), .client = requestedClientFSMode.value()}); + else if (requestedInternalFSMode.has_value()) + g_pCompositor->setWindowFullscreenInternal(PWINDOW, requestedInternalFSMode.value()); + else if (requestedClientFSMode.has_value()) + g_pCompositor->setWindowFullscreenClient(PWINDOW, requestedClientFSMode.value()); } // recheck idle inhibitors @@ -558,7 +563,7 @@ void Events::listener_mapWindow(void* owner, void* data) { // recalc the values for this window g_pCompositor->updateWindowAnimatedDecorationValues(PWINDOW); // avoid this window being visible - if (PWORKSPACE->m_bHasFullscreenWindow && !PWINDOW->m_bIsFullscreen && !PWINDOW->m_bIsFloating) + if (PWORKSPACE->m_bHasFullscreenWindow && !PWINDOW->isFullscreen() && !PWINDOW->m_bIsFloating) PWINDOW->m_fAlpha.setValueAndWarp(0.f); g_pCompositor->setPreferredScaleForSurface(PWINDOW->m_pWLSurface->resource(), PMONITOR->scale); @@ -583,8 +588,8 @@ void Events::listener_unmapWindow(void* owner, void* data) { static auto PEXITRETAINSFS = CConfigValue("misc:exit_window_retains_fullscreen"); - const auto CURRENTWINDOWFSSTATE = PWINDOW->m_bIsFullscreen; - const auto CURRENTWINDOWFSMODE = PWINDOW->m_pWorkspace->m_efFullscreenMode; + const auto CURRENTWINDOWFSSTATE = PWINDOW->isFullscreen(); + const auto CURRENTFSMODE = PWINDOW->m_sFullscreenState.internal; if (!PWINDOW->m_pWLSurface->exists() || !PWINDOW->m_bIsMapped) { Debug::log(WARN, "{} unmapped without being mapped??", PWINDOW); @@ -604,8 +609,8 @@ void Events::listener_unmapWindow(void* owner, void* data) { PROTO::toplevelExport->onWindowUnmap(PWINDOW); - if (PWINDOW->m_bIsFullscreen) - g_pCompositor->setWindowFullscreen(PWINDOW, false, FULLSCREEN_FULL); + if (PWINDOW->isFullscreen()) + g_pCompositor->setWindowFullscreenInternal(PWINDOW, FSMODE_NONE); // Allow the renderer to catch the last frame. g_pHyprOpenGL->makeWindowSnapshot(PWINDOW); @@ -633,7 +638,7 @@ void Events::listener_unmapWindow(void* owner, void* data) { // remove the fullscreen window status from workspace if we closed it const auto PWORKSPACE = PWINDOW->m_pWorkspace; - if (PWORKSPACE->m_bHasFullscreenWindow && PWINDOW->m_bIsFullscreen) + if (PWORKSPACE->m_bHasFullscreenWindow && PWINDOW->isFullscreen()) PWORKSPACE->m_bHasFullscreenWindow = false; g_pLayoutManager->getCurrentLayout()->onWindowRemoved(PWINDOW); @@ -650,7 +655,7 @@ void Events::listener_unmapWindow(void* owner, void* data) { if (PWINDOWCANDIDATE != g_pCompositor->m_pLastWindow.lock() && PWINDOWCANDIDATE) { g_pCompositor->focusWindow(PWINDOWCANDIDATE); if (*PEXITRETAINSFS && CURRENTWINDOWFSSTATE) - g_pCompositor->setWindowFullscreen(PWINDOWCANDIDATE, true, CURRENTWINDOWFSMODE); + g_pCompositor->setWindowFullscreenInternal(PWINDOWCANDIDATE, CURRENTFSMODE); } if (!PWINDOWCANDIDATE && g_pCompositor->getWindowsOnWorkspace(PWINDOW->workspaceID()) == 0) @@ -708,7 +713,7 @@ void Events::listener_commitWindow(void* owner, void* data) { PWINDOW->m_vReportedSize = PWINDOW->m_vPendingReportedSize; // apply pending size. We pinged, the window ponged. - if (!PWINDOW->m_bIsX11 && !PWINDOW->m_bIsFullscreen && PWINDOW->m_bIsFloating) { + if (!PWINDOW->m_bIsX11 && !PWINDOW->isFullscreen() && PWINDOW->m_bIsFloating) { const auto MINSIZE = PWINDOW->m_pXDGSurface->toplevel->current.minSize; const auto MAXSIZE = PWINDOW->m_pXDGSurface->toplevel->current.maxSize; @@ -835,7 +840,7 @@ void Events::listener_unmanagedSetGeometry(void* owner, void* data) { else PWINDOW->setHidden(true); - if (PWINDOW->m_bIsFullscreen || !PWINDOW->m_bIsFloating) { + if (PWINDOW->isFullscreen() || !PWINDOW->m_bIsFloating) { g_pXWaylandManager->setWindowSize(PWINDOW, PWINDOW->m_vRealSize.goal(), true); g_pHyprRenderer->damageWindow(PWINDOW); return; diff --git a/src/helpers/Monitor.cpp b/src/helpers/Monitor.cpp index 33fe0c04..377825fb 100644 --- a/src/helpers/Monitor.cpp +++ b/src/helpers/Monitor.cpp @@ -354,7 +354,7 @@ bool CMonitor::shouldSkipScheduleFrameOnMouseEvent() { // skip scheduling extra frames for fullsreen apps with vrr bool shouldSkip = - *PNOBREAK && output->state->state().adaptiveSync && activeWorkspace && activeWorkspace->m_bHasFullscreenWindow && activeWorkspace->m_efFullscreenMode == FULLSCREEN_FULL; + *PNOBREAK && output->state->state().adaptiveSync && activeWorkspace && activeWorkspace->m_bHasFullscreenWindow && activeWorkspace->m_efFullscreenMode == FSMODE_FULLSCREEN; // keep requested minimum refresh rate if (shouldSkip && *PMINRR && lastPresentationTimer.getMillis() > 1000 / *PMINRR) { diff --git a/src/layout/DwindleLayout.cpp b/src/layout/DwindleLayout.cpp index 7fa6fdbc..336c8c68 100644 --- a/src/layout/DwindleLayout.cpp +++ b/src/layout/DwindleLayout.cpp @@ -136,11 +136,12 @@ void CHyprDwindleLayout::applyNodeDataToWindow(SDwindleNodeData* pNode, bool for return; } - if (PWINDOW->m_bIsFullscreen && !pNode->ignoreFullscreenChecks) + if (PWINDOW->isFullscreen() && !pNode->ignoreFullscreenChecks) return; PWINDOW->unsetWindowData(PRIORITY_LAYOUT); PWINDOW->updateWindowData(); + PWINDOW->updateWindowDecos(); static auto PNOGAPSWHENONLY = CConfigValue("dwindle:no_gaps_when_only"); static auto PGAPSINDATA = CConfigValue("general:gaps_in"); @@ -158,8 +159,7 @@ void CHyprDwindleLayout::applyNodeDataToWindow(SDwindleNodeData* pNode, bool for const auto NODESONWORKSPACE = getNodesOnWorkspace(PWINDOW->workspaceID()); - if (*PNOGAPSWHENONLY && !PWINDOW->onSpecialWorkspace() && - (NODESONWORKSPACE == 1 || (PWINDOW->m_bIsFullscreen && PWINDOW->m_pWorkspace->m_efFullscreenMode == FULLSCREEN_MAXIMIZED))) { + if (*PNOGAPSWHENONLY && !PWINDOW->onSpecialWorkspace() && (NODESONWORKSPACE == 1 || PWINDOW->isEffectiveInternalFSMode(FSMODE_MAXIMIZED))) { PWINDOW->m_sWindowData.decorate = CWindowOverridableVar(true, PRIORITY_LAYOUT); PWINDOW->m_sWindowData.noBorder = CWindowOverridableVar(*PNOGAPSWHENONLY != 2, PRIORITY_LAYOUT); @@ -216,7 +216,7 @@ void CHyprDwindleLayout::applyNodeDataToWindow(SDwindleNodeData* pNode, bool for calcPos = calcPos + RESERVED.topLeft; calcSize = calcSize - (RESERVED.topLeft + RESERVED.bottomRight); - if (PWINDOW->onSpecialWorkspace() && !PWINDOW->m_bIsFullscreen) { + if (PWINDOW->onSpecialWorkspace() && !PWINDOW->isFullscreen()) { // if special, we adjust the coords a bit static auto PSCALEFACTOR = CConfigValue("dwindle:special_scale_factor"); @@ -500,8 +500,8 @@ void CHyprDwindleLayout::onWindowRemovedTiling(PHLWINDOW pWindow) { pWindow->unsetWindowData(PRIORITY_LAYOUT); pWindow->updateWindowData(); - if (pWindow->m_bIsFullscreen) - g_pCompositor->setWindowFullscreen(pWindow, false, FULLSCREEN_FULL); + if (pWindow->isFullscreen()) + g_pCompositor->setWindowFullscreenInternal(pWindow, FSMODE_NONE); const auto PPARENT = PNODE->pParent; @@ -560,10 +560,10 @@ void CHyprDwindleLayout::calculateWorkspace(const PHLWORKSPACE& pWorkspace) { // massive hack from the fullscreen func const auto PFULLWINDOW = g_pCompositor->getFullscreenWindowOnWorkspace(pWorkspace->m_iID); - if (pWorkspace->m_efFullscreenMode == FULLSCREEN_FULL) { + if (pWorkspace->m_efFullscreenMode == FSMODE_FULLSCREEN) { PFULLWINDOW->m_vRealPosition = PMONITOR->vecPosition; PFULLWINDOW->m_vRealSize = PMONITOR->vecSize; - } else if (pWorkspace->m_efFullscreenMode == FULLSCREEN_MAXIMIZED) { + } else if (pWorkspace->m_efFullscreenMode == FSMODE_MAXIMIZED) { SDwindleNodeData fakeNode; fakeNode.pWindow = PFULLWINDOW; fakeNode.box = {PMONITOR->vecPosition + PMONITOR->vecReservedTopLeft, PMONITOR->vecSize - PMONITOR->vecReservedTopLeft - PMONITOR->vecReservedBottomRight}; @@ -788,41 +788,19 @@ void CHyprDwindleLayout::resizeActiveWindow(const Vector2D& pixResize, eRectCorn } } -void CHyprDwindleLayout::fullscreenRequestForWindow(PHLWINDOW pWindow, eFullscreenMode fullscreenMode, bool on) { - if (!validMapped(pWindow)) - return; - - if (on == pWindow->m_bIsFullscreen) - return; // ignore - +void CHyprDwindleLayout::fullscreenRequestForWindow(PHLWINDOW pWindow, const eFullscreenMode CURRENT_EFFECTIVE_MODE, const eFullscreenMode EFFECTIVE_MODE) { const auto PMONITOR = g_pCompositor->getMonitorFromID(pWindow->m_iMonitorID); const auto PWORKSPACE = pWindow->m_pWorkspace; - if (PWORKSPACE->m_bHasFullscreenWindow && on) { - // if the window wants to be fullscreen but there already is one, - // ignore the request. - return; - } - // save position and size if floating - if (pWindow->m_bIsFloating && on) { + if (pWindow->m_bIsFloating && CURRENT_EFFECTIVE_MODE == FSMODE_NONE) { pWindow->m_vLastFloatingSize = pWindow->m_vRealSize.goal(); pWindow->m_vLastFloatingPosition = pWindow->m_vRealPosition.goal(); pWindow->m_vPosition = pWindow->m_vRealPosition.goal(); pWindow->m_vSize = pWindow->m_vRealSize.goal(); } - // otherwise, accept it. - pWindow->m_bIsFullscreen = on; - PWORKSPACE->m_bHasFullscreenWindow = !PWORKSPACE->m_bHasFullscreenWindow; - - pWindow->updateDynamicRules(); - pWindow->updateWindowDecos(); - - g_pEventManager->postEvent(SHyprIPCEvent{"fullscreen", std::to_string((int)on)}); - EMIT_HOOK_EVENT("fullscreen", pWindow); - - if (!pWindow->m_bIsFullscreen) { + if (EFFECTIVE_MODE == FSMODE_NONE) { // if it got its fullscreen disabled, set back its node if it had one const auto PNODE = getNodeFromWindow(pWindow); if (PNODE) @@ -836,12 +814,8 @@ void CHyprDwindleLayout::fullscreenRequestForWindow(PHLWINDOW pWindow, eFullscre pWindow->updateWindowData(); } } else { - // if it now got fullscreen, make it fullscreen - - PWORKSPACE->m_efFullscreenMode = fullscreenMode; - // apply new pos and size being monitors' box - if (fullscreenMode == FULLSCREEN_FULL) { + if (EFFECTIVE_MODE == FSMODE_FULLSCREEN) { pWindow->m_vRealPosition = PMONITOR->vecPosition; pWindow->m_vRealSize = PMONITOR->vecSize; } else { @@ -861,13 +835,7 @@ void CHyprDwindleLayout::fullscreenRequestForWindow(PHLWINDOW pWindow, eFullscre } } - g_pCompositor->updateWindowAnimatedDecorationValues(pWindow); - - g_pXWaylandManager->setWindowSize(pWindow, pWindow->m_vRealSize.goal()); - g_pCompositor->changeWindowZOrder(pWindow, true); - - recalculateMonitor(PMONITOR->ID); } void CHyprDwindleLayout::recalculateWindow(PHLWINDOW pWindow) { @@ -957,13 +925,11 @@ void CHyprDwindleLayout::switchWindows(PHLWINDOW pWindow, PHLWINDOW pWindow2) { if (!PNODE2 || !PNODE) return; - const bool FS1 = pWindow->m_bIsFullscreen; - const bool FS2 = pWindow2->m_bIsFullscreen; + const eFullscreenMode MODE1 = pWindow->m_sFullscreenState.internal; + const eFullscreenMode MODE2 = pWindow->m_sFullscreenState.internal; - if (FS1) - g_pCompositor->setWindowFullscreen(pWindow, false); - if (FS2) - g_pCompositor->setWindowFullscreen(pWindow2, false); + g_pCompositor->setWindowFullscreenInternal(pWindow, FSMODE_NONE); + g_pCompositor->setWindowFullscreenInternal(pWindow2, FSMODE_NONE); SDwindleNodeData* ACTIVE1 = nullptr; SDwindleNodeData* ACTIVE2 = nullptr; @@ -1001,10 +967,8 @@ void CHyprDwindleLayout::switchWindows(PHLWINDOW pWindow, PHLWINDOW pWindow2) { g_pHyprRenderer->damageWindow(pWindow); g_pHyprRenderer->damageWindow(pWindow2); - if (FS1) - g_pCompositor->setWindowFullscreen(pWindow2, true); - if (FS2) - g_pCompositor->setWindowFullscreen(pWindow, true); + g_pCompositor->setWindowFullscreenInternal(pWindow2, MODE1); + g_pCompositor->setWindowFullscreenInternal(pWindow, MODE2); } void CHyprDwindleLayout::alterSplitRatio(PHLWINDOW pWindow, float ratio, bool exact) { @@ -1072,7 +1036,7 @@ void CHyprDwindleLayout::toggleSplit(PHLWINDOW pWindow) { if (!PNODE || !PNODE->pParent) return; - if (pWindow->m_bIsFullscreen) + if (pWindow->isFullscreen()) return; PNODE->pParent->splitTop = !PNODE->pParent->splitTop; @@ -1086,7 +1050,7 @@ void CHyprDwindleLayout::swapSplit(PHLWINDOW pWindow) { if (!PNODE || !PNODE->pParent) return; - if (pWindow->m_bIsFullscreen) + if (pWindow->isFullscreen()) return; std::swap(PNODE->pParent->children[0], PNODE->pParent->children[1]); diff --git a/src/layout/DwindleLayout.hpp b/src/layout/DwindleLayout.hpp index 13834bc7..f638f6a2 100644 --- a/src/layout/DwindleLayout.hpp +++ b/src/layout/DwindleLayout.hpp @@ -52,7 +52,7 @@ class CHyprDwindleLayout : public IHyprLayout { virtual void recalculateWindow(PHLWINDOW); virtual void onBeginDragWindow(); virtual void resizeActiveWindow(const Vector2D&, eRectCorner corner = CORNER_NONE, PHLWINDOW pWindow = nullptr); - virtual void fullscreenRequestForWindow(PHLWINDOW, eFullscreenMode, bool); + virtual void fullscreenRequestForWindow(PHLWINDOW pWindow, const eFullscreenMode CURRENT_EFFECTIVE_MODE, const eFullscreenMode EFFECTIVE_MODE); virtual std::any layoutMessage(SLayoutMessageHeader, std::string); virtual SWindowRenderLayoutHints requestRenderHints(PHLWINDOW); virtual void switchWindows(PHLWINDOW, PHLWINDOW); diff --git a/src/layout/IHyprLayout.cpp b/src/layout/IHyprLayout.cpp index 0738b71c..233933d4 100644 --- a/src/layout/IHyprLayout.cpp +++ b/src/layout/IHyprLayout.cpp @@ -29,8 +29,8 @@ void IHyprLayout::onWindowCreated(PHLWINDOW pWindow, eDirection direction) { } void IHyprLayout::onWindowRemoved(PHLWINDOW pWindow) { - if (pWindow->m_bIsFullscreen) - g_pCompositor->setWindowFullscreen(pWindow, false, FULLSCREEN_FULL); + if (pWindow->isFullscreen()) + g_pCompositor->setWindowFullscreenInternal(pWindow, FSMODE_NONE); if (!pWindow->m_sGroupData.pNextWindow.expired()) { if (pWindow->m_sGroupData.pNextWindow.lock() == pWindow) @@ -191,9 +191,9 @@ void IHyprLayout::onBeginDragWindow() { return; } - if (DRAGGINGWINDOW->m_bIsFullscreen) { + if (DRAGGINGWINDOW->isFullscreen()) { Debug::log(LOG, "Dragging a fullscreen window"); - g_pCompositor->setWindowFullscreen(DRAGGINGWINDOW, false, FULLSCREEN_FULL); + g_pCompositor->setWindowFullscreenInternal(DRAGGINGWINDOW, FSMODE_NONE); } const auto PWORKSPACE = DRAGGINGWINDOW->m_pWorkspace; @@ -475,9 +475,9 @@ void IHyprLayout::onMouseMove(const Vector2D& mousePos) { void IHyprLayout::changeWindowFloatingMode(PHLWINDOW pWindow) { - if (pWindow->m_bIsFullscreen) { + if (pWindow->isFullscreen()) { Debug::log(LOG, "changeWindowFloatingMode: fullscreen"); - g_pCompositor->setWindowFullscreen(pWindow, false, FULLSCREEN_FULL); + g_pCompositor->setWindowFullscreenInternal(pWindow, FSMODE_NONE); } pWindow->m_bPinned = false; @@ -497,7 +497,7 @@ void IHyprLayout::changeWindowFloatingMode(PHLWINDOW pWindow) { const auto PWORKSPACE = PNEWMON->activeSpecialWorkspace ? PNEWMON->activeSpecialWorkspace : PNEWMON->activeWorkspace; if (PWORKSPACE->m_bHasFullscreenWindow) - g_pCompositor->setWindowFullscreen(g_pCompositor->getFullscreenWindowOnWorkspace(PWORKSPACE->m_iID), false); + g_pCompositor->setWindowFullscreenInternal(g_pCompositor->getFullscreenWindowOnWorkspace(PWORKSPACE->m_iID), FSMODE_NONE); // save real pos cuz the func applies the default 5,5 mid const auto PSAVEDPOS = pWindow->m_vRealPosition.goal(); diff --git a/src/layout/IHyprLayout.hpp b/src/layout/IHyprLayout.hpp index 74a00d19..4b1b59e3 100644 --- a/src/layout/IHyprLayout.hpp +++ b/src/layout/IHyprLayout.hpp @@ -110,7 +110,7 @@ class IHyprLayout { The layout sets all the fullscreen flags. It can either accept or ignore. */ - virtual void fullscreenRequestForWindow(PHLWINDOW, eFullscreenMode, bool) = 0; + virtual void fullscreenRequestForWindow(PHLWINDOW pWindow, const eFullscreenMode CURRENT_EFFECTIVE_MODE, const eFullscreenMode EFFECTIVE_MODE) = 0; /* Called when a dispatcher requests a custom message diff --git a/src/layout/MasterLayout.cpp b/src/layout/MasterLayout.cpp index d7f264e7..e3aaa767 100644 --- a/src/layout/MasterLayout.cpp +++ b/src/layout/MasterLayout.cpp @@ -267,7 +267,8 @@ void CHyprMasterLayout::onWindowRemovedTiling(PHLWINDOW pWindow) { pWindow->unsetWindowData(PRIORITY_LAYOUT); pWindow->updateWindowData(); - g_pCompositor->setWindowFullscreen(pWindow, false, FULLSCREEN_FULL); + if (pWindow->isFullscreen()) + g_pCompositor->setWindowFullscreenInternal(pWindow, FSMODE_NONE); if (PNODE->isMaster && (MASTERSLEFT <= 1 || *SMALLSPLIT == 1)) { // find a new master from top of the list @@ -327,10 +328,10 @@ void CHyprMasterLayout::calculateWorkspace(PHLWORKSPACE pWorkspace) { // massive hack from the fullscreen func const auto PFULLWINDOW = g_pCompositor->getFullscreenWindowOnWorkspace(pWorkspace->m_iID); - if (pWorkspace->m_efFullscreenMode == FULLSCREEN_FULL) { + if (pWorkspace->m_efFullscreenMode == FSMODE_FULLSCREEN) { PFULLWINDOW->m_vRealPosition = PMONITOR->vecPosition; PFULLWINDOW->m_vRealSize = PMONITOR->vecSize; - } else if (pWorkspace->m_efFullscreenMode == FULLSCREEN_MAXIMIZED) { + } else if (pWorkspace->m_efFullscreenMode == FSMODE_MAXIMIZED) { SMasterNodeData fakeNode; fakeNode.pWindow = PFULLWINDOW; fakeNode.position = PMONITOR->vecPosition + PMONITOR->vecReservedTopLeft; @@ -644,11 +645,12 @@ void CHyprMasterLayout::applyNodeDataToWindow(SMasterNodeData* pNode) { // if user specified them in config const auto WORKSPACERULE = g_pConfigManager->getWorkspaceRuleFor(PWINDOW->m_pWorkspace); - if (PWINDOW->m_bIsFullscreen && !pNode->ignoreFullscreenChecks) + if (PWINDOW->isFullscreen() && !pNode->ignoreFullscreenChecks) return; PWINDOW->unsetWindowData(PRIORITY_LAYOUT); PWINDOW->updateWindowData(); + PWINDOW->updateWindowDecos(); static auto PNOGAPSWHENONLY = CConfigValue("master:no_gaps_when_only"); static auto PANIMATE = CConfigValue("misc:animate_manual_resizes"); @@ -668,8 +670,7 @@ void CHyprMasterLayout::applyNodeDataToWindow(SMasterNodeData* pNode) { PWINDOW->m_vSize = pNode->size; PWINDOW->m_vPosition = pNode->position; - if (*PNOGAPSWHENONLY && !PWINDOW->onSpecialWorkspace() && - (getNodesOnWorkspace(PWINDOW->workspaceID()) == 1 || (PWINDOW->m_bIsFullscreen && PWINDOW->m_pWorkspace->m_efFullscreenMode == FULLSCREEN_MAXIMIZED))) { + if (*PNOGAPSWHENONLY && !PWINDOW->onSpecialWorkspace() && (getNodesOnWorkspace(PWINDOW->workspaceID()) == 1 || PWINDOW->isEffectiveInternalFSMode(FSMODE_MAXIMIZED))) { PWINDOW->m_sWindowData.decorate = CWindowOverridableVar(true, PRIORITY_LAYOUT); PWINDOW->m_sWindowData.noBorder = CWindowOverridableVar(*PNOGAPSWHENONLY != 2, PRIORITY_LAYOUT); @@ -702,7 +703,7 @@ void CHyprMasterLayout::applyNodeDataToWindow(SMasterNodeData* pNode) { calcPos = calcPos + RESERVED.topLeft; calcSize = calcSize - (RESERVED.topLeft + RESERVED.bottomRight); - if (PWINDOW->onSpecialWorkspace() && !PWINDOW->m_bIsFullscreen) { + if (PWINDOW->onSpecialWorkspace() && !PWINDOW->isFullscreen()) { static auto PSCALEFACTOR = CConfigValue("master:special_scale_factor"); CBox wb = {calcPos + (calcSize - calcSize * *PSCALEFACTOR) / 2.f, calcSize * *PSCALEFACTOR}; @@ -880,41 +881,19 @@ void CHyprMasterLayout::resizeActiveWindow(const Vector2D& pixResize, eRectCorne m_bForceWarps = false; } -void CHyprMasterLayout::fullscreenRequestForWindow(PHLWINDOW pWindow, eFullscreenMode fullscreenMode, bool on) { - if (!validMapped(pWindow)) - return; - - if (on == pWindow->m_bIsFullscreen) - return; // ignore - +void CHyprMasterLayout::fullscreenRequestForWindow(PHLWINDOW pWindow, const eFullscreenMode CURRENT_EFFECTIVE_MODE, const eFullscreenMode EFFECTIVE_MODE) { const auto PMONITOR = g_pCompositor->getMonitorFromID(pWindow->m_iMonitorID); const auto PWORKSPACE = pWindow->m_pWorkspace; - if (PWORKSPACE->m_bHasFullscreenWindow && on) { - // if the window wants to be fullscreen but there already is one, - // ignore the request. - return; - } - // save position and size if floating - if (pWindow->m_bIsFloating && on) { + if (pWindow->m_bIsFloating && CURRENT_EFFECTIVE_MODE == FSMODE_NONE) { pWindow->m_vLastFloatingSize = pWindow->m_vRealSize.goal(); pWindow->m_vLastFloatingPosition = pWindow->m_vRealPosition.goal(); pWindow->m_vPosition = pWindow->m_vRealPosition.goal(); pWindow->m_vSize = pWindow->m_vRealSize.goal(); } - // otherwise, accept it. - pWindow->m_bIsFullscreen = on; - PWORKSPACE->m_bHasFullscreenWindow = !PWORKSPACE->m_bHasFullscreenWindow; - - pWindow->updateDynamicRules(); - pWindow->updateWindowDecos(); - - g_pEventManager->postEvent(SHyprIPCEvent{"fullscreen", std::to_string((int)on)}); - EMIT_HOOK_EVENT("fullscreen", pWindow); - - if (!pWindow->m_bIsFullscreen) { + if (EFFECTIVE_MODE == FSMODE_NONE) { // if it got its fullscreen disabled, set back its node if it had one const auto PNODE = getNodeFromWindow(pWindow); if (PNODE) @@ -928,12 +907,8 @@ void CHyprMasterLayout::fullscreenRequestForWindow(PHLWINDOW pWindow, eFullscree pWindow->updateWindowData(); } } else { - // if it now got fullscreen, make it fullscreen - - PWORKSPACE->m_efFullscreenMode = fullscreenMode; - // apply new pos and size being monitors' box - if (fullscreenMode == FULLSCREEN_FULL) { + if (EFFECTIVE_MODE == FSMODE_FULLSCREEN) { pWindow->m_vRealPosition = PMONITOR->vecPosition; pWindow->m_vRealSize = PMONITOR->vecSize; } else { @@ -954,13 +929,7 @@ void CHyprMasterLayout::fullscreenRequestForWindow(PHLWINDOW pWindow, eFullscree } } - g_pCompositor->updateWindowAnimatedDecorationValues(pWindow); - - g_pXWaylandManager->setWindowSize(pWindow, pWindow->m_vRealSize.goal()); - g_pCompositor->changeWindowZOrder(pWindow, true); - - recalculateMonitor(PMONITOR->ID); } void CHyprMasterLayout::recalculateWindow(PHLWINDOW pWindow) { @@ -1081,14 +1050,14 @@ std::any CHyprMasterLayout::layoutMessage(SLayoutMessageHeader header, std::stri if (!validMapped(PWINDOWTOCHANGETO)) return; - if (header.pWindow->m_bIsFullscreen) { + if (header.pWindow->isFullscreen()) { const auto PWORKSPACE = header.pWindow->m_pWorkspace; - const auto FSMODE = PWORKSPACE->m_efFullscreenMode; + const auto FSMODE = header.pWindow->m_sFullscreenState.internal; static auto INHERITFULLSCREEN = CConfigValue("master:inherit_fullscreen"); - g_pCompositor->setWindowFullscreen(header.pWindow, false, FULLSCREEN_FULL); + g_pCompositor->setWindowFullscreenInternal(header.pWindow, FSMODE_NONE); g_pCompositor->focusWindow(PWINDOWTOCHANGETO); if (*INHERITFULLSCREEN) - g_pCompositor->setWindowFullscreen(PWINDOWTOCHANGETO, true, FSMODE); + g_pCompositor->setWindowFullscreenInternal(PWINDOWTOCHANGETO, FSMODE); } else { g_pCompositor->focusWindow(PWINDOWTOCHANGETO); g_pCompositor->warpCursorTo(PWINDOWTOCHANGETO->middle()); @@ -1208,7 +1177,7 @@ std::any CHyprMasterLayout::layoutMessage(SLayoutMessageHeader header, std::stri const auto PWINDOWTOSWAPWITH = getNextWindow(header.pWindow, true); if (PWINDOWTOSWAPWITH) { - g_pCompositor->setWindowFullscreen(header.pWindow, false, FULLSCREEN_FULL); + g_pCompositor->setWindowFullscreenInternal(header.pWindow, FSMODE_NONE); switchWindows(header.pWindow, PWINDOWTOSWAPWITH); switchToWindow(header.pWindow); } @@ -1224,7 +1193,7 @@ std::any CHyprMasterLayout::layoutMessage(SLayoutMessageHeader header, std::stri const auto PWINDOWTOSWAPWITH = getNextWindow(header.pWindow, false); if (PWINDOWTOSWAPWITH) { - g_pCompositor->setWindowFullscreen(header.pWindow, false, FULLSCREEN_FULL); + g_pCompositor->setWindowFullscreenClient(header.pWindow, FSMODE_NONE); switchWindows(header.pWindow, PWINDOWTOSWAPWITH); switchToWindow(header.pWindow); } @@ -1243,7 +1212,8 @@ std::any CHyprMasterLayout::layoutMessage(SLayoutMessageHeader header, std::stri if (MASTERS + 2 > WINDOWS && *SMALLSPLIT == 0) return 0; - g_pCompositor->setWindowFullscreen(header.pWindow, false, FULLSCREEN_FULL); + + g_pCompositor->setWindowFullscreenInternal(header.pWindow, FSMODE_NONE); if (!PNODE || PNODE->isMaster) { // first non-master node @@ -1275,7 +1245,7 @@ std::any CHyprMasterLayout::layoutMessage(SLayoutMessageHeader header, std::stri if (WINDOWS < 2 || MASTERS < 2) return 0; - g_pCompositor->setWindowFullscreen(header.pWindow, false, FULLSCREEN_FULL); + g_pCompositor->setWindowFullscreenInternal(header.pWindow, FSMODE_NONE); if (!PNODE || !PNODE->isMaster) { // first non-master node @@ -1296,7 +1266,7 @@ std::any CHyprMasterLayout::layoutMessage(SLayoutMessageHeader header, std::stri if (!PWINDOW) return 0; - g_pCompositor->setWindowFullscreen(PWINDOW, false, FULLSCREEN_FULL); + g_pCompositor->setWindowFullscreenInternal(PWINDOW, FSMODE_NONE); const auto PWORKSPACEDATA = getMasterWorkspaceData(PWINDOW->workspaceID()); @@ -1392,7 +1362,7 @@ void CHyprMasterLayout::runOrientationCycle(SLayoutMessageHeader& header, CVarLi if (!PWINDOW) return; - g_pCompositor->setWindowFullscreen(PWINDOW, false, FULLSCREEN_FULL); + g_pCompositor->setWindowFullscreenInternal(PWINDOW, FSMODE_NONE); const auto PWORKSPACEDATA = getMasterWorkspaceData(PWINDOW->workspaceID()); diff --git a/src/layout/MasterLayout.hpp b/src/layout/MasterLayout.hpp index 30d5b3cf..fdb916e5 100644 --- a/src/layout/MasterLayout.hpp +++ b/src/layout/MasterLayout.hpp @@ -58,7 +58,7 @@ class CHyprMasterLayout : public IHyprLayout { virtual void recalculateMonitor(const int&); virtual void recalculateWindow(PHLWINDOW); virtual void resizeActiveWindow(const Vector2D&, eRectCorner corner = CORNER_NONE, PHLWINDOW pWindow = nullptr); - virtual void fullscreenRequestForWindow(PHLWINDOW, eFullscreenMode, bool); + virtual void fullscreenRequestForWindow(PHLWINDOW pWindow, const eFullscreenMode CURRENT_EFFECTIVE_MODE, const eFullscreenMode EFFECTIVE_MODE); virtual std::any layoutMessage(SLayoutMessageHeader, std::string); virtual SWindowRenderLayoutHints requestRenderHints(PHLWINDOW); virtual void switchWindows(PHLWINDOW, PHLWINDOW); diff --git a/src/managers/KeybindManager.cpp b/src/managers/KeybindManager.cpp index 823e2d2e..33b07351 100644 --- a/src/managers/KeybindManager.cpp +++ b/src/managers/KeybindManager.cpp @@ -68,7 +68,7 @@ CKeybindManager::CKeybindManager() { m_mDispatchers["workspace"] = changeworkspace; m_mDispatchers["renameworkspace"] = renameWorkspace; m_mDispatchers["fullscreen"] = fullscreenActive; - m_mDispatchers["fakefullscreen"] = fakeFullscreenActive; + m_mDispatchers["fullscreenstate"] = fullscreenStateActive; m_mDispatchers["movetoworkspace"] = moveActiveToWorkspace; m_mDispatchers["movetoworkspacesilent"] = moveActiveToWorkspaceSilent; m_mDispatchers["pseudo"] = toggleActivePseudo; @@ -319,17 +319,17 @@ void CKeybindManager::switchToWindow(PHLWINDOW PWINDOWTOCHANGETO) { // remove constraints g_pInputManager->unconstrainMouse(); - if (PLASTWINDOW && PLASTWINDOW->m_pWorkspace == PWINDOWTOCHANGETO->m_pWorkspace && PLASTWINDOW->m_bIsFullscreen) { + if (PLASTWINDOW && PLASTWINDOW->m_pWorkspace == PWINDOWTOCHANGETO->m_pWorkspace && PLASTWINDOW->isFullscreen()) { const auto PWORKSPACE = PLASTWINDOW->m_pWorkspace; - const auto FSMODE = PWORKSPACE->m_efFullscreenMode; + const auto MODE = PWORKSPACE->m_efFullscreenMode; if (!PWINDOWTOCHANGETO->m_bPinned) - g_pCompositor->setWindowFullscreen(PLASTWINDOW, false, FULLSCREEN_FULL); + g_pCompositor->setWindowFullscreenInternal(PLASTWINDOW, FSMODE_NONE); g_pCompositor->focusWindow(PWINDOWTOCHANGETO); if (!PWINDOWTOCHANGETO->m_bPinned) - g_pCompositor->setWindowFullscreen(PWINDOWTOCHANGETO, true, FSMODE); + g_pCompositor->setWindowFullscreenInternal(PWINDOWTOCHANGETO, MODE); } else { updateRelativeCursorCoords(); g_pCompositor->focusWindow(PWINDOWTOCHANGETO); @@ -996,7 +996,7 @@ void CKeybindManager::setActiveTiled(std::string args) { void CKeybindManager::centerWindow(std::string args) { const auto PWINDOW = g_pCompositor->m_pLastWindow.lock(); - if (!PWINDOW || !PWINDOW->m_bIsFloating || PWINDOW->m_bIsFullscreen) + if (!PWINDOW || !PWINDOW->m_bIsFloating || PWINDOW->isFullscreen()) return; const auto PMONITOR = g_pCompositor->getMonitorFromID(PWINDOW->m_iMonitorID); @@ -1022,7 +1022,7 @@ void CKeybindManager::toggleActivePseudo(std::string args) { PWINDOW->m_bIsPseudotiled = !PWINDOW->m_bIsPseudotiled; - if (!PWINDOW->m_bIsFullscreen) + if (!PWINDOW->isFullscreen()) g_pLayoutManager->getCurrentLayout()->recalculateWindow(PWINDOW); } @@ -1149,10 +1149,34 @@ void CKeybindManager::fullscreenActive(std::string args) { if (!PWINDOW) return; - PWINDOW->m_bDontSendFullscreen = false; - if (args == "2") - PWINDOW->m_bDontSendFullscreen = true; - g_pCompositor->setWindowFullscreen(PWINDOW, !PWINDOW->m_bIsFullscreen, args == "1" ? FULLSCREEN_MAXIMIZED : FULLSCREEN_FULL); + const eFullscreenMode MODE = args == "1" ? FSMODE_MAXIMIZED : FSMODE_FULLSCREEN; + + if (PWINDOW->isEffectiveInternalFSMode(MODE)) + g_pCompositor->setWindowFullscreenInternal(PWINDOW, FSMODE_NONE); + else + g_pCompositor->setWindowFullscreenInternal(PWINDOW, MODE); +} + +void CKeybindManager::fullscreenStateActive(std::string args) { + const auto PWINDOW = g_pCompositor->m_pLastWindow.lock(); + const auto ARGS = CVarList(args, 2, ' '); + + if (!PWINDOW) + return; + + PWINDOW->m_sWindowData.syncFullscreen = CWindowOverridableVar(false, PRIORITY_SET_PROP); + + int internalMode, clientMode; + try { + internalMode = std::stoi(ARGS[0]); + } catch (std::exception& e) { internalMode = -1; } + try { + clientMode = std::stoi(ARGS[1]); + } catch (std::exception& e) { clientMode = -1; } + + g_pCompositor->setWindowFullscreenState(PWINDOW, + sFullscreenState{.internal = (internalMode != -1 ? (eFullscreenMode)internalMode : PWINDOW->m_sFullscreenState.internal), + .client = (clientMode != -1 ? (eFullscreenMode)clientMode : PWINDOW->m_sFullscreenState.client)}); } void CKeybindManager::moveActiveToWorkspace(std::string args) { @@ -1277,7 +1301,7 @@ void CKeybindManager::moveFocusTo(std::string args) { return; } - const auto PWINDOWTOCHANGETO = *PFULLCYCLE && PLASTWINDOW->m_bIsFullscreen ? + const auto PWINDOWTOCHANGETO = *PFULLCYCLE && PLASTWINDOW->isFullscreen() ? (arg == 'd' || arg == 'b' || arg == 'r' ? g_pCompositor->getNextWindowOnWorkspace(PLASTWINDOW, true) : g_pCompositor->getPrevWindowOnWorkspace(PLASTWINDOW, true)) : g_pCompositor->getWindowInDirection(PLASTWINDOW, arg); @@ -1334,7 +1358,7 @@ void CKeybindManager::swapActive(std::string args) { Debug::log(LOG, "Swapping active window in direction {}", arg); const auto PLASTWINDOW = g_pCompositor->m_pLastWindow.lock(); - if (!PLASTWINDOW || PLASTWINDOW->m_bIsFullscreen) + if (!PLASTWINDOW || PLASTWINDOW->isFullscreen()) return; const auto PWINDOWTOCHANGETO = g_pCompositor->getWindowInDirection(PLASTWINDOW, arg); @@ -1372,7 +1396,7 @@ void CKeybindManager::moveActiveTo(std::string args) { const auto PLASTWINDOW = g_pCompositor->m_pLastWindow.lock(); - if (!PLASTWINDOW || PLASTWINDOW->m_bIsFullscreen) + if (!PLASTWINDOW || PLASTWINDOW->isFullscreen()) return; if (PLASTWINDOW->m_bIsFloating) { @@ -1427,7 +1451,8 @@ void CKeybindManager::toggleGroup(std::string args) { if (!PWINDOW) return; - g_pCompositor->setWindowFullscreen(PWINDOW, false, FULLSCREEN_FULL); + if (PWINDOW->isFullscreen()) + g_pCompositor->setWindowFullscreenInternal(PWINDOW, FSMODE_NONE); if (PWINDOW->m_sGroupData.pNextWindow.expired()) PWINDOW->createGroup(); @@ -1819,7 +1844,7 @@ void CKeybindManager::forceRendererReload(std::string args) { void CKeybindManager::resizeActive(std::string args) { const auto PLASTWINDOW = g_pCompositor->m_pLastWindow.lock(); - if (!PLASTWINDOW || PLASTWINDOW->m_bIsFullscreen) + if (!PLASTWINDOW || PLASTWINDOW->isFullscreen()) return; const auto SIZ = g_pCompositor->parseWindowVectorArgsRelative(args, PLASTWINDOW->m_vRealSize.goal()); @@ -1836,7 +1861,7 @@ void CKeybindManager::resizeActive(std::string args) { void CKeybindManager::moveActive(std::string args) { const auto PLASTWINDOW = g_pCompositor->m_pLastWindow.lock(); - if (!PLASTWINDOW || PLASTWINDOW->m_bIsFullscreen) + if (!PLASTWINDOW || PLASTWINDOW->isFullscreen()) return; const auto POS = g_pCompositor->parseWindowVectorArgsRelative(args, PLASTWINDOW->m_vRealPosition.goal()); @@ -1856,7 +1881,7 @@ void CKeybindManager::moveWindow(std::string args) { return; } - if (PWINDOW->m_bIsFullscreen) + if (PWINDOW->isFullscreen()) return; const auto POS = g_pCompositor->parseWindowVectorArgsRelative(MOVECMD, PWINDOW->m_vRealPosition.goal()); @@ -1876,7 +1901,7 @@ void CKeybindManager::resizeWindow(std::string args) { return; } - if (PWINDOW->m_bIsFullscreen) + if (PWINDOW->isFullscreen()) return; const auto SIZ = g_pCompositor->parseWindowVectorArgsRelative(MOVECMD, PWINDOW->m_vRealSize.goal()); @@ -1953,12 +1978,12 @@ void CKeybindManager::focusWindow(std::string regexp) { g_pCompositor->focusWindow(PWINDOW); } else { if (FSWINDOW != PWINDOW && !PWINDOW->m_bPinned) - g_pCompositor->setWindowFullscreen(FSWINDOW, false, FULLSCREEN_FULL); + g_pCompositor->setWindowFullscreenClient(FSWINDOW, FSMODE_NONE); g_pCompositor->focusWindow(PWINDOW); if (FSWINDOW != PWINDOW && !PWINDOW->m_bPinned) - g_pCompositor->setWindowFullscreen(PWINDOW, true, FSMODE); + g_pCompositor->setWindowFullscreenClient(PWINDOW, FSMODE); } } else g_pCompositor->focusWindow(PWINDOW); @@ -2330,7 +2355,7 @@ void CKeybindManager::pinActive(std::string args) { return; } - if (!PWINDOW->m_bIsFloating || PWINDOW->m_bIsFullscreen) + if (!PWINDOW->m_bIsFloating || PWINDOW->isFullscreen()) return; PWINDOW->m_bPinned = !PWINDOW->m_bPinned; @@ -2388,7 +2413,7 @@ void CKeybindManager::changeMouseBindMode(const eMouseBindMode MODE) { if (!PWINDOW) return; - if (!PWINDOW->m_bIsFullscreen && MODE == MBIND_MOVE) + if (!PWINDOW->isFullscreen() && MODE == MBIND_MOVE) PWINDOW->checkInputOnDecos(INPUT_TYPE_DRAG_START, MOUSECOORDS); if (g_pInputManager->currentlyDraggedWindow.expired()) @@ -2436,14 +2461,6 @@ void CKeybindManager::alterZOrder(std::string args) { g_pInputManager->simulateMouseMovement(); } -void CKeybindManager::fakeFullscreenActive(std::string args) { - if (!g_pCompositor->m_pLastWindow.expired()) { - // will also set the flag - g_pCompositor->m_pLastWindow->m_bFakeFullscreenState = !g_pCompositor->m_pLastWindow->m_bFakeFullscreenState; - g_pXWaylandManager->setWindowFullscreen(g_pCompositor->m_pLastWindow.lock(), g_pCompositor->m_pLastWindow->shouldSendFullscreenState()); - } -} - void CKeybindManager::lockGroups(std::string args) { if (args == "lock" || args.empty() || args == "lockgroups") g_pKeybindManager->m_bGroupsLocked = true; @@ -2603,7 +2620,7 @@ void CKeybindManager::moveWindowOrGroup(std::string args) { } const auto PWINDOW = g_pCompositor->m_pLastWindow.lock(); - if (!PWINDOW || PWINDOW->m_bIsFullscreen) + if (!PWINDOW || PWINDOW->isFullscreen()) return; if (!*PIGNOREGROUPLOCK && g_pKeybindManager->m_bGroupsLocked) { diff --git a/src/managers/KeybindManager.hpp b/src/managers/KeybindManager.hpp index 26a6345b..26b42b00 100644 --- a/src/managers/KeybindManager.hpp +++ b/src/managers/KeybindManager.hpp @@ -155,7 +155,7 @@ class CKeybindManager { static void setActiveTiled(std::string); static void changeworkspace(std::string); static void fullscreenActive(std::string); - static void fakeFullscreenActive(std::string); + static void fullscreenStateActive(std::string args); static void moveActiveToWorkspace(std::string); static void moveActiveToWorkspaceSilent(std::string); static void moveFocusTo(std::string); diff --git a/src/managers/input/IdleInhibitor.cpp b/src/managers/input/IdleInhibitor.cpp index da2429bc..2c335a7e 100644 --- a/src/managers/input/IdleInhibitor.cpp +++ b/src/managers/input/IdleInhibitor.cpp @@ -63,7 +63,7 @@ void CInputManager::recheckIdleInhibitorStatus() { return; } - if (w->m_eIdleInhibitMode == IDLEINHIBIT_FULLSCREEN && w->m_bIsFullscreen && g_pCompositor->isWorkspaceVisible(w->m_pWorkspace)) { + if (w->m_eIdleInhibitMode == IDLEINHIBIT_FULLSCREEN && w->isFullscreen() && g_pCompositor->isWorkspaceVisible(w->m_pWorkspace)) { PROTO::idle->setInhibit(true); return; } diff --git a/src/managers/input/InputManager.cpp b/src/managers/input/InputManager.cpp index 014de40a..8c38893f 100644 --- a/src/managers/input/InputManager.cpp +++ b/src/managers/input/InputManager.cpp @@ -298,7 +298,7 @@ void CInputManager::mouseMoveUnified(uint32_t time, bool refocus) { // then, we check if the workspace doesnt have a fullscreen window const auto PWORKSPACE = PMONITOR->activeWorkspace; - if (PWORKSPACE->m_bHasFullscreenWindow && !foundSurface && PWORKSPACE->m_efFullscreenMode == FULLSCREEN_FULL) { + if (PWORKSPACE->m_bHasFullscreenWindow && !foundSurface && PWORKSPACE->m_efFullscreenMode == FSMODE_FULLSCREEN) { pFoundWindow = g_pCompositor->getFullscreenWindowOnWorkspace(PWORKSPACE->m_iID); if (!pFoundWindow) { @@ -325,7 +325,7 @@ void CInputManager::mouseMoveUnified(uint32_t time, bool refocus) { // then windows if (!foundSurface) { - if (PWORKSPACE->m_bHasFullscreenWindow && PWORKSPACE->m_efFullscreenMode == FULLSCREEN_MAXIMIZED) { + if (PWORKSPACE->m_bHasFullscreenWindow && PWORKSPACE->m_efFullscreenMode == FSMODE_MAXIMIZED) { if (!foundSurface) { if (PMONITOR->activeSpecialWorkspace) { pFoundWindow = g_pCompositor->vectorToWindowUnified(mouseCoords, RESERVED_EXTENTS | INPUT_EXTENTS | ALLOW_FLOATING); @@ -470,7 +470,7 @@ void CInputManager::mouseMoveUnified(uint32_t time, bool refocus) { else if (pFoundWindow) { // change cursor icon if hovering over border if (*PRESIZEONBORDER && *PRESIZECURSORICON) { - if (!pFoundWindow->m_bIsFullscreen && !pFoundWindow->hasPopupAt(mouseCoords)) { + if (!pFoundWindow->isFullscreen() && !pFoundWindow->hasPopupAt(mouseCoords)) { setCursorIconOnBorder(pFoundWindow); } else if (m_eBorderIconDirection != BORDERICON_NONE) { unsetCursorImage(); @@ -681,7 +681,7 @@ void CInputManager::processMouseDownNormal(const IPointer::SButtonEvent& e) { // clicking on border triggers resize // TODO detect click on LS properly if (*PRESIZEONBORDER && !m_bLastFocusOnLS && e.state == WL_POINTER_BUTTON_STATE_PRESSED && (!w || w->m_iX11Type != 2)) { - if (w && !w->m_bIsFullscreen) { + if (w && !w->isFullscreen()) { const CBox real = {w->m_vRealPosition.value().x, w->m_vRealPosition.value().y, w->m_vRealSize.value().x, w->m_vRealSize.value().y}; const CBox grab = {real.x - BORDER_GRAB_AREA, real.y - BORDER_GRAB_AREA, real.width + 2 * BORDER_GRAB_AREA, real.height + 2 * BORDER_GRAB_AREA}; diff --git a/src/managers/input/Swipe.cpp b/src/managers/input/Swipe.cpp index 775881cd..c0e6c4f0 100644 --- a/src/managers/input/Swipe.cpp +++ b/src/managers/input/Swipe.cpp @@ -194,7 +194,7 @@ void CInputManager::endWorkspaceSwipe() { // apply alpha for (auto& ls : g_pCompositor->m_pLastMonitor->m_aLayerSurfaceLayers[2]) { - ls->alpha = pSwitchedTo->m_bHasFullscreenWindow && pSwitchedTo->m_efFullscreenMode == FULLSCREEN_FULL ? 0.f : 1.f; + ls->alpha = pSwitchedTo->m_bHasFullscreenWindow && pSwitchedTo->m_efFullscreenMode == FSMODE_FULLSCREEN ? 0.f : 1.f; } } diff --git a/src/protocols/ForeignToplevelWlr.cpp b/src/protocols/ForeignToplevelWlr.cpp index 2b378386..295834ea 100644 --- a/src/protocols/ForeignToplevelWlr.cpp +++ b/src/protocols/ForeignToplevelWlr.cpp @@ -51,7 +51,7 @@ CForeignToplevelHandleWlr::CForeignToplevelHandleWlr(SPsetWindowFullscreen(PWINDOW, true, FULLSCREEN_FULL); + g_pCompositor->changeWindowFullscreenModeClient(PWINDOW, FSMODE_FULLSCREEN, true); g_pHyprRenderer->damageWindow(PWINDOW); }); @@ -64,7 +64,7 @@ CForeignToplevelHandleWlr::CForeignToplevelHandleWlr(SPm_eSuppressedEvents & SUPPRESS_FULLSCREEN) return; - g_pCompositor->setWindowFullscreen(PWINDOW, false); + g_pCompositor->changeWindowFullscreenModeClient(PWINDOW, FSMODE_FULLSCREEN, false); }); resource->setSetMaximized([this](CZwlrForeignToplevelHandleV1* p) { @@ -81,7 +81,7 @@ CForeignToplevelHandleWlr::CForeignToplevelHandleWlr(SPsetWindowFullscreen(PWINDOW, true, FULLSCREEN_MAXIMIZED); + g_pCompositor->changeWindowFullscreenModeClient(PWINDOW, FSMODE_MAXIMIZED, true); }); resource->setUnsetMaximized([this](CZwlrForeignToplevelHandleV1* p) { @@ -93,7 +93,7 @@ CForeignToplevelHandleWlr::CForeignToplevelHandleWlr(SPm_eSuppressedEvents & SUPPRESS_MAXIMIZE) return; - g_pCompositor->setWindowFullscreen(PWINDOW, false); + g_pCompositor->changeWindowFullscreenModeClient(PWINDOW, FSMODE_MAXIMIZED, false); }); resource->setClose([this](CZwlrForeignToplevelHandleV1* p) { @@ -155,9 +155,9 @@ void CForeignToplevelHandleWlr::sendState() { *p = ZWLR_FOREIGN_TOPLEVEL_HANDLE_V1_STATE_ACTIVATED; } - if (PWINDOW->m_bIsFullscreen) { + if (PWINDOW->isFullscreen()) { auto p = (uint32_t*)wl_array_add(&state, sizeof(uint32_t)); - if (PWINDOW->m_pWorkspace->m_efFullscreenMode == FULLSCREEN_FULL) + if (PWINDOW->isEffectiveInternalFSMode(FSMODE_FULLSCREEN)) *p = ZWLR_FOREIGN_TOPLEVEL_HANDLE_V1_STATE_FULLSCREEN; else *p = ZWLR_FOREIGN_TOPLEVEL_HANDLE_V1_STATE_MAXIMIZED; diff --git a/src/render/Renderer.cpp b/src/render/Renderer.cpp index b5397598..e4f97895 100644 --- a/src/render/Renderer.cpp +++ b/src/render/Renderer.cpp @@ -269,7 +269,7 @@ bool CHyprRenderer::shouldRenderWindow(PHLWINDOW pWindow, CMonitor* pMonitor) { return true; // if hidden behind fullscreen - if (PWINDOWWORKSPACE->m_bHasFullscreenWindow && !pWindow->m_bIsFullscreen && (!pWindow->m_bIsFloating || !pWindow->m_bCreatedOverFullscreen) && + if (PWINDOWWORKSPACE->m_bHasFullscreenWindow && !pWindow->isFullscreen() && (!pWindow->m_bIsFloating || !pWindow->m_bCreatedOverFullscreen) && pWindow->m_fAlpha.value() == 0) return false; @@ -285,7 +285,7 @@ bool CHyprRenderer::shouldRenderWindow(PHLWINDOW pWindow, CMonitor* pMonitor) { // if not, check if it maybe is active on a different monitor. if (g_pCompositor->isWorkspaceVisible(pWindow->m_pWorkspace) && pWindow->m_bIsFloating /* tiled windows can't be multi-ws */) - return !pWindow->m_bIsFullscreen; // Do not draw fullscreen windows on other monitors + return !pWindow->isFullscreen(); // Do not draw fullscreen windows on other monitors if (pMonitor->activeSpecialWorkspace == pWindow->m_pWorkspace) return true; @@ -352,7 +352,7 @@ void CHyprRenderer::renderWorkspaceWindowsFullscreen(CMonitor* pMonitor, PHLWORK if (w->m_fAlpha.value() == 0.f) continue; - if (w->m_bIsFullscreen || w->m_bIsFloating) + if (w->isFullscreen() || w->m_bIsFloating) continue; if (pWorkspace->m_bIsSpecialWorkspace != w->onSpecialWorkspace()) @@ -369,7 +369,7 @@ void CHyprRenderer::renderWorkspaceWindowsFullscreen(CMonitor* pMonitor, PHLWORK if (w->m_fAlpha.value() == 0.f) continue; - if (w->m_bIsFullscreen || !w->m_bIsFloating) + if (w->isFullscreen() || !w->m_bIsFloating) continue; if (w->m_iMonitorID == pWorkspace->m_iMonitorID && pWorkspace->m_bIsSpecialWorkspace != w->onSpecialWorkspace()) @@ -385,7 +385,7 @@ void CHyprRenderer::renderWorkspaceWindowsFullscreen(CMonitor* pMonitor, PHLWORK for (auto& w : g_pCompositor->m_vWindows) { const auto PWORKSPACE = w->m_pWorkspace; - if (w->m_pWorkspace != pWorkspace || !w->m_bIsFullscreen) { + if (w->m_pWorkspace != pWorkspace || !w->isFullscreen()) { if (!(PWORKSPACE && (PWORKSPACE->m_vRenderOffset.isBeingAnimated() || PWORKSPACE->m_fAlpha.isBeingAnimated() || PWORKSPACE->m_bForceRendering))) continue; @@ -393,14 +393,14 @@ void CHyprRenderer::renderWorkspaceWindowsFullscreen(CMonitor* pMonitor, PHLWORK continue; } - if (!w->m_bIsFullscreen) + if (!w->isFullscreen()) continue; if (w->m_iMonitorID == pWorkspace->m_iMonitorID && pWorkspace->m_bIsSpecialWorkspace != w->onSpecialWorkspace()) continue; if (shouldRenderWindow(w, pMonitor)) - renderWindow(w, pMonitor, time, pWorkspace->m_efFullscreenMode != FULLSCREEN_FULL, RENDER_PASS_ALL); + renderWindow(w, pMonitor, time, pWorkspace->m_efFullscreenMode != FSMODE_FULLSCREEN, RENDER_PASS_ALL); if (w->m_pWorkspace != pWorkspace) continue; @@ -416,7 +416,7 @@ void CHyprRenderer::renderWorkspaceWindowsFullscreen(CMonitor* pMonitor, PHLWORK // then render windows over fullscreen. for (auto& w : g_pCompositor->m_vWindows) { - if (w->m_pWorkspace != pWorkspaceWindow->m_pWorkspace || (!w->m_bCreatedOverFullscreen && !w->m_bPinned) || (!w->m_bIsMapped && !w->m_bFadingOut) || w->m_bIsFullscreen) + if (w->m_pWorkspace != pWorkspaceWindow->m_pWorkspace || (!w->m_bCreatedOverFullscreen && !w->m_bPinned) || (!w->m_bIsMapped && !w->m_bFadingOut) || w->isFullscreen()) continue; if (w->m_iMonitorID == pWorkspace->m_iMonitorID && pWorkspace->m_bIsSpecialWorkspace != w->onSpecialWorkspace()) @@ -538,10 +538,10 @@ void CHyprRenderer::renderWindow(PHLWINDOW pWindow, CMonitor* pMonitor, timespec decorate = false; renderdata.surface = pWindow->m_pWLSurface->resource(); - renderdata.dontRound = (pWindow->m_bIsFullscreen && PWORKSPACE->m_efFullscreenMode == FULLSCREEN_FULL) || pWindow->m_sWindowData.noRounding.valueOrDefault(); + renderdata.dontRound = pWindow->isEffectiveInternalFSMode(FSMODE_FULLSCREEN) || pWindow->m_sWindowData.noRounding.valueOrDefault(); renderdata.fadeAlpha = pWindow->m_fAlpha.value() * (pWindow->m_bPinned ? 1.f : PWORKSPACE->m_fAlpha.value()); renderdata.alpha = pWindow->m_fActiveInactiveAlpha.value(); - renderdata.decorate = decorate && !pWindow->m_bX11DoesntWantBorders && (!pWindow->m_bIsFullscreen || PWORKSPACE->m_efFullscreenMode != FULLSCREEN_FULL); + renderdata.decorate = decorate && !pWindow->m_bX11DoesntWantBorders && !pWindow->isEffectiveInternalFSMode(FSMODE_FULLSCREEN); renderdata.rounding = ignoreAllGeometry || renderdata.dontRound ? 0 : pWindow->rounding() * pMonitor->scale; renderdata.blur = !ignoreAllGeometry; // if it shouldn't, it will be ignored later renderdata.pWindow = pWindow; @@ -568,7 +568,7 @@ void CHyprRenderer::renderWindow(PHLWINDOW pWindow, CMonitor* pMonitor, timespec renderdata.y += pWindow->m_vFloatingOffset.y; // if window is floating and we have a slide animation, clip it to its full bb - if (!ignorePosition && pWindow->m_bIsFloating && !pWindow->m_bIsFullscreen && PWORKSPACE->m_vRenderOffset.isBeingAnimated() && !pWindow->m_bPinned) { + if (!ignorePosition && pWindow->m_bIsFloating && !pWindow->isFullscreen() && PWORKSPACE->m_vRenderOffset.isBeingAnimated() && !pWindow->m_bPinned) { CRegion rg = pWindow->getFullWindowBoundingBox().translate(-pMonitor->vecPosition + PWORKSPACE->m_vRenderOffset.value() + pWindow->m_vFloatingOffset).scale(pMonitor->scale); g_pHyprOpenGL->m_RenderData.clipBox = rg.getExtents(); @@ -871,7 +871,7 @@ void CHyprRenderer::renderAllClientsForWorkspace(CMonitor* pMonitor, PHLWORKSPAC // if we have a fullscreen, opaque window that convers the screen, we can skip this. // TODO: check better with solitary after MR for tearing. const auto PFULLWINDOW = pWorkspace ? g_pCompositor->getFullscreenWindowOnWorkspace(pWorkspace->m_iID) : nullptr; - if (!pWorkspace->m_bHasFullscreenWindow || pWorkspace->m_efFullscreenMode != FULLSCREEN_FULL || !PFULLWINDOW || PFULLWINDOW->m_vRealSize.isBeingAnimated() || + if (!pWorkspace->m_bHasFullscreenWindow || pWorkspace->m_efFullscreenMode != FSMODE_FULLSCREEN || !PFULLWINDOW || PFULLWINDOW->m_vRealSize.isBeingAnimated() || !PFULLWINDOW->opaque() || pWorkspace->m_vRenderOffset.value() != Vector2D{} || g_pHyprOpenGL->preBlurQueued()) { if (!g_pHyprOpenGL->m_RenderData.pCurrentMonData->blurFBShouldRender) diff --git a/src/render/decorations/CHyprGroupBarDecoration.cpp b/src/render/decorations/CHyprGroupBarDecoration.cpp index a13750d0..8163a8c1 100644 --- a/src/render/decorations/CHyprGroupBarDecoration.cpp +++ b/src/render/decorations/CHyprGroupBarDecoration.cpp @@ -464,7 +464,7 @@ bool CHyprGroupBarDecoration::onEndWindowDragOnDeco(const Vector2D& pos, PHLWIND bool CHyprGroupBarDecoration::onMouseButtonOnDeco(const Vector2D& pos, const IPointer::SButtonEvent& e) { static auto PSTACKED = CConfigValue("group:groupbar:stacked"); - if (m_pWindow->m_bIsFullscreen && m_pWindow->m_pWorkspace->m_efFullscreenMode == FULLSCREEN_FULL) + if (m_pWindow->isEffectiveInternalFSMode(FSMODE_FULLSCREEN)) return true; const float BARRELATIVEX = pos.x - assignedBoxGlobal().x; From 548968279926a73d7ff19a9a185c977c50d56756 Mon Sep 17 00:00:00 2001 From: Tom Englund Date: Wed, 31 Jul 2024 21:00:14 +0200 Subject: [PATCH 0214/2181] internal: some minor fd/socket cleanups and make logging thread safe (#7123) * bezier: dont loop on float values Using a floating-point loop variable with a fixed increment can cause precision errors over time due to the nature of floating-point arithmetic. and cause undesired effects. ex iteration 1 = 0.10000000149011611938 iteration 2 = 0.20000000298023223877 eventually.. iteration 8 = 0.80000001192092895508 iteration 9 = 0.89999997615814208984 * hyprctl: close sockets on destruction store socketpath and close the fd and unlink the socket path on exit. * eventloopmgr: close the timerfd close the timerfd on exit. * debug: make logging thread safe instead of opening and closing the logfile on each write open it on init and close it on compositor exit. also add a mutex so accidently using logging from a thread like the watchdog or similiar doesnt cause issues. * xwl: clean up fd logic check if the fd is actually opened before closing, and close the pipesource FD on exit. --- src/Compositor.cpp | 2 ++ src/debug/HyprCtl.cpp | 10 +++++++--- src/debug/HyprCtl.hpp | 1 + src/debug/Log.cpp | 12 +++++++----- src/debug/Log.hpp | 7 +++++++ src/helpers/BezierCurve.cpp | 4 +++- src/managers/eventLoop/EventLoopManager.cpp | 2 ++ src/xwayland/Server.cpp | 12 ++++++++---- src/xwayland/Server.hpp | 1 + 9 files changed, 38 insertions(+), 13 deletions(-) diff --git a/src/Compositor.cpp b/src/Compositor.cpp index 97355d2c..7221d3a7 100644 --- a/src/Compositor.cpp +++ b/src/Compositor.cpp @@ -518,6 +518,8 @@ void CCompositor::cleanup() { // this frees all wayland resources, including sockets wl_display_destroy(m_sWLDisplay); + + Debug::close(); } void CCompositor::initManagers(eManagersInitStage stage) { diff --git a/src/debug/HyprCtl.cpp b/src/debug/HyprCtl.cpp index cf873e6c..d91a1cec 100644 --- a/src/debug/HyprCtl.cpp +++ b/src/debug/HyprCtl.cpp @@ -1604,6 +1604,10 @@ CHyprCtl::CHyprCtl() { CHyprCtl::~CHyprCtl() { if (m_eventSource) wl_event_source_remove(m_eventSource); + if (m_iSocketFD >= 0) + close(m_iSocketFD); + if (!m_socketPath.empty()) + unlink(m_socketPath.c_str()); } SP CHyprCtl::registerCommand(SHyprCtlCommand cmd) { @@ -1821,9 +1825,9 @@ void CHyprCtl::startHyprCtlSocket() { sockaddr_un SERVERADDRESS = {.sun_family = AF_UNIX}; - std::string socketPath = g_pCompositor->m_szInstancePath + "/.socket.sock"; + m_socketPath = g_pCompositor->m_szInstancePath + "/.socket.sock"; - strcpy(SERVERADDRESS.sun_path, socketPath.c_str()); + strcpy(SERVERADDRESS.sun_path, m_socketPath.c_str()); if (bind(m_iSocketFD, (sockaddr*)&SERVERADDRESS, SUN_LEN(&SERVERADDRESS)) < 0) { Debug::log(ERR, "Couldn't start the Hyprland Socket. (2) IPC will not work."); @@ -1833,7 +1837,7 @@ void CHyprCtl::startHyprCtlSocket() { // 10 max queued. listen(m_iSocketFD, 10); - Debug::log(LOG, "Hypr socket started at {}", socketPath); + Debug::log(LOG, "Hypr socket started at {}", m_socketPath); m_eventSource = wl_event_loop_add_fd(g_pCompositor->m_sWLEventLoop, m_iSocketFD, WL_EVENT_READABLE, hyprCtlFDTick, nullptr); } diff --git a/src/debug/HyprCtl.hpp b/src/debug/HyprCtl.hpp index ccbd40cd..cbacd7cb 100644 --- a/src/debug/HyprCtl.hpp +++ b/src/debug/HyprCtl.hpp @@ -31,6 +31,7 @@ class CHyprCtl { std::vector> m_vCommands; wl_event_source* m_eventSource = nullptr; + std::string m_socketPath; }; inline std::unique_ptr g_pHyprCtl; diff --git a/src/debug/Log.cpp b/src/debug/Log.cpp index c2939831..0def77c0 100644 --- a/src/debug/Log.cpp +++ b/src/debug/Log.cpp @@ -8,6 +8,11 @@ void Debug::init(const std::string& IS) { logFile = IS + (ISDEBUG ? "/hyprlandd.log" : "/hyprland.log"); + logOfs.open(logFile, std::ios::out | std::ios::app); +} + +void Debug::close() { + logOfs.close(); } void Debug::log(LogLevel level, std::string str) { @@ -55,11 +60,8 @@ void Debug::log(LogLevel level, std::string str) { if (!disableLogs || !**disableLogs) { // log to a file - std::ofstream ofs; - ofs.open(logFile, std::ios::out | std::ios::app); - ofs << str << "\n"; - - ofs.close(); + logOfs << str << "\n"; + logOfs.flush(); } // log it to the stdout too. diff --git a/src/debug/Log.hpp b/src/debug/Log.hpp index 33f3c9c1..617f451a 100644 --- a/src/debug/Log.hpp +++ b/src/debug/Log.hpp @@ -4,6 +4,7 @@ #include #include #include +#include #include "../includes.hpp" #include "../helpers/MiscFunctions.hpp" @@ -22,6 +23,7 @@ enum LogLevel { namespace Debug { inline std::string logFile; + inline std::ofstream logOfs; inline int64_t* const* disableLogs = nullptr; inline int64_t* const* disableTime = nullptr; inline bool disableStdout = false; @@ -30,14 +32,18 @@ namespace Debug { inline int64_t* const* coloredLogs = nullptr; inline std::string rollingLog = ""; // rolling log contains the ROLLING_LOG_SIZE tail of the log + inline std::mutex logMutex; void init(const std::string& IS); + void close(); // void log(LogLevel level, std::string str); template void log(LogLevel level, std::format_string fmt, Args&&... args) { + std::lock_guard guard(logMutex); + if (level == TRACE && !trace) return; @@ -66,5 +72,6 @@ namespace Debug { logMsg += std::vformat(fmt.get(), std::make_format_args(args...)); log(level, logMsg); + logMutex.unlock(); } }; diff --git a/src/helpers/BezierCurve.cpp b/src/helpers/BezierCurve.cpp index e79863a3..dd0ff2b0 100644 --- a/src/helpers/BezierCurve.cpp +++ b/src/helpers/BezierCurve.cpp @@ -30,8 +30,10 @@ void CBezierCurve::setup(std::vector* pVec) { const auto POINTSSIZE = m_aPointsBaked.size() * sizeof(m_aPointsBaked[0]) / 1000.f; const auto BEGINCALC = std::chrono::high_resolution_clock::now(); - for (float i = 0.1f; i < 1.f; i += 0.1f) + for (int j = 1; j < 10; ++j) { + float i = j / 10.0f; getYForPoint(i); + } const auto ELAPSEDCALCAVG = std::chrono::duration_cast(std::chrono::high_resolution_clock::now() - BEGINCALC).count() / 1000.f / 10.f; Debug::log(LOG, "Created a bezier curve, baked {} points, mem usage: {:.2f}kB, time to bake: {:.2f}µs. Estimated average calc time: {:.2f}µs.", BAKEDPOINTS, POINTSSIZE, diff --git a/src/managers/eventLoop/EventLoopManager.cpp b/src/managers/eventLoop/EventLoopManager.cpp index 3131531a..c2c088f8 100644 --- a/src/managers/eventLoop/EventLoopManager.cpp +++ b/src/managers/eventLoop/EventLoopManager.cpp @@ -27,6 +27,8 @@ CEventLoopManager::~CEventLoopManager() { wl_event_source_remove(m_sWayland.eventSource); if (m_sIdle.eventSource) wl_event_source_remove(m_sIdle.eventSource); + if (m_sTimers.timerfd >= 0) + close(m_sTimers.timerfd); } static int timerWrite(int fd, uint32_t mask, void* data) { diff --git a/src/xwayland/Server.cpp b/src/xwayland/Server.cpp index 3f4e7b43..cec582f6 100644 --- a/src/xwayland/Server.cpp +++ b/src/xwayland/Server.cpp @@ -262,13 +262,16 @@ void CXWaylandServer::die() { if (pipeSource) wl_event_source_remove(pipeSource); - if (waylandFDs[0]) + if (pipeFd >= 0) + close(pipeFd); + + if (waylandFDs[0] >= 0) close(waylandFDs[0]); - if (waylandFDs[1]) + if (waylandFDs[1] >= 0) close(waylandFDs[1]); - if (xwmFDs[0]) + if (xwmFDs[0] >= 0) close(xwmFDs[0]); - if (xwmFDs[1]) + if (xwmFDs[1] >= 0) close(xwmFDs[1]); // possible crash. Better to leak a bit. @@ -364,6 +367,7 @@ bool CXWaylandServer::start() { } pipeSource = wl_event_loop_add_fd(g_pCompositor->m_sWLEventLoop, notify[0], WL_EVENT_READABLE, ::xwaylandReady, nullptr); + pipeFd = notify[0]; serverPID = fork(); if (serverPID < 0) { diff --git a/src/xwayland/Server.hpp b/src/xwayland/Server.hpp index 0c06a56c..7a36a965 100644 --- a/src/xwayland/Server.hpp +++ b/src/xwayland/Server.hpp @@ -41,6 +41,7 @@ class CXWaylandServer { std::array xFDReadEvents = {nullptr, nullptr}; wl_event_source* idleSource = nullptr; wl_event_source* pipeSource = nullptr; + int pipeFd = -1; std::array xwmFDs = {-1, -1}; std::array waylandFDs = {-1, -1}; From 37e1411e8d94fe8f3fb678588a7df9b8f931910f Mon Sep 17 00:00:00 2001 From: Vaxry <43317083+vaxerski@users.noreply.github.com> Date: Wed, 31 Jul 2024 20:47:26 +0100 Subject: [PATCH 0215/2181] core/surface/buffer: Buffer lock/release fixes (#7110) --- src/desktop/LayerSurface.cpp | 2 +- src/desktop/WLSurface.cpp | 23 +++-- src/desktop/Window.cpp | 10 +-- src/events/Windows.cpp | 2 +- src/helpers/Monitor.cpp | 7 +- src/managers/PointerManager.cpp | 50 ++++++++--- src/protocols/DRMSyncobj.cpp | 2 +- src/protocols/InputMethodV2.cpp | 4 +- src/protocols/LayerShell.cpp | 2 +- src/protocols/SessionLock.cpp | 2 +- src/protocols/Viewporter.cpp | 4 +- src/protocols/XDGShell.cpp | 6 +- src/protocols/core/Compositor.cpp | 124 +++++++++++++++++---------- src/protocols/core/Compositor.hpp | 35 +++++--- src/protocols/core/DataDevice.cpp | 8 +- src/protocols/core/Seat.cpp | 21 ++++- src/protocols/core/Seat.hpp | 15 ++++ src/protocols/core/Subcompositor.cpp | 4 +- src/protocols/types/Buffer.cpp | 56 ++++++++++++ src/protocols/types/Buffer.hpp | 28 +++++- src/protocols/types/SurfaceRole.hpp | 1 + src/protocols/types/WLBuffer.cpp | 1 - src/protocols/types/WLBuffer.hpp | 2 - src/render/Renderer.cpp | 14 +-- src/render/Texture.cpp | 3 + src/render/Texture.hpp | 1 + src/xwayland/XSurface.cpp | 6 +- 27 files changed, 304 insertions(+), 129 deletions(-) diff --git a/src/desktop/LayerSurface.cpp b/src/desktop/LayerSurface.cpp index 80138910..ba1b1776 100644 --- a/src/desktop/LayerSurface.cpp +++ b/src/desktop/LayerSurface.cpp @@ -242,7 +242,7 @@ void CLayerSurface::onCommit() { if (!mapped) { // we're re-mapping if this is the case - if (layerSurface->surface && !layerSurface->surface->current.buffer) { + if (layerSurface->surface && !layerSurface->surface->current.texture) { fadingOut = false; geometry = {}; g_pHyprRenderer->arrangeLayersForMonitor(monitorID); diff --git a/src/desktop/WLSurface.cpp b/src/desktop/WLSurface.cpp index 3c91a142..45050e35 100644 --- a/src/desktop/WLSurface.cpp +++ b/src/desktop/WLSurface.cpp @@ -57,12 +57,12 @@ bool CWLSurface::small() const { if (!validMapped(m_pWindowOwner) || !exists()) return false; - if (!m_pResource->current.buffer) + if (!m_pResource->current.texture) return false; const auto O = m_pWindowOwner.lock(); - return O->m_vReportedSize.x > m_pResource->current.buffer->size.x + 1 || O->m_vReportedSize.y > m_pResource->current.buffer->size.y + 1; + return O->m_vReportedSize.x > m_pResource->current.bufferSize.x + 1 || O->m_vReportedSize.y > m_pResource->current.bufferSize.y + 1; } Vector2D CWLSurface::correctSmallVec() const { @@ -76,37 +76,36 @@ Vector2D CWLSurface::correctSmallVec() const { } Vector2D CWLSurface::correctSmallVecBuf() const { - if (!exists() || !small() || m_bFillIgnoreSmall || !m_pResource->current.buffer) + if (!exists() || !small() || m_bFillIgnoreSmall || !m_pResource->current.texture) return {}; const auto SIZE = getViewporterCorrectedSize(); - const auto BS = m_pResource->current.buffer->size; + const auto BS = m_pResource->current.bufferSize; return Vector2D{(BS.x - SIZE.x) / 2, (BS.y - SIZE.y) / 2}.clamp({}, {INFINITY, INFINITY}); } Vector2D CWLSurface::getViewporterCorrectedSize() const { - if (!exists() || !m_pResource->current.buffer) + if (!exists() || !m_pResource->current.texture) return {}; - return m_pResource->current.viewport.hasDestination ? m_pResource->current.viewport.destination : m_pResource->current.buffer->size; + return m_pResource->current.viewport.hasDestination ? m_pResource->current.viewport.destination : m_pResource->current.bufferSize; } CRegion CWLSurface::computeDamage() const { - if (!m_pResource->current.buffer) + if (!m_pResource->current.texture) return {}; CRegion damage = m_pResource->accumulateCurrentBufferDamage(); - damage.transform(wlTransformToHyprutils(m_pResource->current.transform), m_pResource->current.buffer->size.x, m_pResource->current.buffer->size.y); + damage.transform(wlTransformToHyprutils(m_pResource->current.transform), m_pResource->current.bufferSize.x, m_pResource->current.bufferSize.y); - const auto BUFSIZE = m_pResource->current.buffer->size; + const auto BUFSIZE = m_pResource->current.bufferSize; const auto CORRECTVEC = correctSmallVecBuf(); if (m_pResource->current.viewport.hasSource) damage.intersect(m_pResource->current.viewport.source); - const auto SCALEDSRCSIZE = - m_pResource->current.viewport.hasSource ? m_pResource->current.viewport.source.size() * m_pResource->current.scale : m_pResource->current.buffer->size; + const auto SCALEDSRCSIZE = m_pResource->current.viewport.hasSource ? m_pResource->current.viewport.source.size() * m_pResource->current.scale : m_pResource->current.bufferSize; damage.scale({BUFSIZE.x / SCALEDSRCSIZE.x, BUFSIZE.y / SCALEDSRCSIZE.y}); damage.translate(CORRECTVEC); @@ -114,7 +113,7 @@ CRegion CWLSurface::computeDamage() const { // go from buffer coords in the damage to hl logical const auto BOX = getSurfaceBoxGlobal(); - const Vector2D SCALE = BOX.has_value() ? BOX->size() / m_pResource->current.buffer->size : + const Vector2D SCALE = BOX.has_value() ? BOX->size() / m_pResource->current.bufferSize : Vector2D{1.0 / m_pResource->current.scale, 1.0 / m_pResource->current.scale /* Wrong... but we can't really do better */}; damage.scale(SCALE); diff --git a/src/desktop/Window.cpp b/src/desktop/Window.cpp index 9316959d..27010454 100644 --- a/src/desktop/Window.cpp +++ b/src/desktop/Window.cpp @@ -1097,18 +1097,18 @@ bool CWindow::opaque() { if (PWORKSPACE->m_fAlpha.value() != 1.f) return false; - if (m_bIsX11 && m_pXWaylandSurface && m_pXWaylandSurface->surface && m_pXWaylandSurface->surface->current.buffer) - return m_pXWaylandSurface->surface->current.buffer->opaque; + if (m_bIsX11 && m_pXWaylandSurface && m_pXWaylandSurface->surface && m_pXWaylandSurface->surface->current.texture) + return m_pXWaylandSurface->surface->current.texture->m_bOpaque; - if (!m_pWLSurface->resource() || !m_pWLSurface->resource()->current.buffer) + if (!m_pWLSurface->resource() || !m_pWLSurface->resource()->current.texture) return false; // TODO: this is wrong const auto EXTENTS = m_pXDGSurface->surface->current.opaque.getExtents(); - if (EXTENTS.w >= m_pXDGSurface->surface->current.buffer->size.x && EXTENTS.h >= m_pXDGSurface->surface->current.buffer->size.y) + if (EXTENTS.w >= m_pXDGSurface->surface->current.bufferSize.x && EXTENTS.h >= m_pXDGSurface->surface->current.bufferSize.y) return true; - return m_pWLSurface->resource()->current.buffer->opaque; + return m_pWLSurface->resource()->current.texture->m_bOpaque; } float CWindow::rounding() { diff --git a/src/events/Windows.cpp b/src/events/Windows.cpp index 71ad4ba1..0389f57e 100644 --- a/src/events/Windows.cpp +++ b/src/events/Windows.cpp @@ -752,7 +752,7 @@ void Events::listener_commitWindow(void* owner, void* data) { // tearing: if solitary, redraw it. This still might be a single surface window const auto PMONITOR = g_pCompositor->getMonitorFromID(PWINDOW->m_iMonitorID); - if (PMONITOR && PMONITOR->solitaryClient.lock() == PWINDOW && PWINDOW->canBeTorn() && PMONITOR->tearingState.canTear && PWINDOW->m_pWLSurface->resource()->current.buffer) { + if (PMONITOR && PMONITOR->solitaryClient.lock() == PWINDOW && PWINDOW->canBeTorn() && PMONITOR->tearingState.canTear && PWINDOW->m_pWLSurface->resource()->current.texture) { CRegion damageBox{PWINDOW->m_pWLSurface->resource()->accumulateCurrentBufferDamage()}; if (!damageBox.empty()) { diff --git a/src/helpers/Monitor.cpp b/src/helpers/Monitor.cpp index 377825fb..1cf1b069 100644 --- a/src/helpers/Monitor.cpp +++ b/src/helpers/Monitor.cpp @@ -801,17 +801,16 @@ bool CMonitor::attemptDirectScanout() { const auto PSURFACE = g_pXWaylandManager->getWindowSurface(PCANDIDATE); - if (!PSURFACE || !PSURFACE->current.buffer || PSURFACE->current.buffer->size != vecPixelSize || PSURFACE->current.transform != transform) + if (!PSURFACE || !PSURFACE->current.buffer || PSURFACE->current.bufferSize != vecPixelSize || PSURFACE->current.transform != transform) return false; // we can't scanout shm buffers. - if (!PSURFACE->current.buffer->dmabuf().success) + if (!PSURFACE->current.buffer || !PSURFACE->current.texture || !PSURFACE->current.texture->m_pEglImage /* dmabuf */) return false; // FIXME: make sure the buffer actually follows the available scanout dmabuf formats // and comes from the appropriate device. This may implode on multi-gpu!! - - output->state->setBuffer(PSURFACE->current.buffer); + output->state->setBuffer(PSURFACE->current.buffer->buffer.lock()); output->state->setPresentationMode(tearingState.activelyTearing ? Aquamarine::eOutputPresentationMode::AQ_OUTPUT_PRESENTATION_IMMEDIATE : Aquamarine::eOutputPresentationMode::AQ_OUTPUT_PRESENTATION_VSYNC); diff --git a/src/managers/PointerManager.cpp b/src/managers/PointerManager.cpp index 8314e79a..3ba34c11 100644 --- a/src/managers/PointerManager.cpp +++ b/src/managers/PointerManager.cpp @@ -4,6 +4,7 @@ #include "../protocols/PointerGestures.hpp" #include "../protocols/FractionalScale.hpp" #include "../protocols/core/Compositor.hpp" +#include "../protocols/core/Seat.hpp" #include "eventLoop/EventLoopManager.hpp" #include "SeatManager.hpp" #include @@ -156,15 +157,15 @@ void CPointerManager::setCursorSurface(SP surf, const Vector2D& hots currentCursorImage.destroySurface = surf->events.destroy.registerListener([this](std::any data) { resetCursorImage(); }); currentCursorImage.commitSurface = surf->resource()->events.commit.registerListener([this](std::any data) { damageIfSoftware(); - currentCursorImage.size = currentCursorImage.surface->resource()->current.buffer ? currentCursorImage.surface->resource()->current.buffer->size : Vector2D{}; + currentCursorImage.size = currentCursorImage.surface->resource()->current.texture ? currentCursorImage.surface->resource()->current.bufferSize : Vector2D{}; currentCursorImage.scale = currentCursorImage.surface ? currentCursorImage.surface->resource()->current.scale : 1.F; recheckEnteredOutputs(); updateCursorBackend(); damageIfSoftware(); }); - if (surf->resource()->current.buffer) { - currentCursorImage.size = surf->resource()->current.buffer->size; + if (surf->resource()->current.texture) { + currentCursorImage.size = surf->resource()->current.bufferSize; timespec now; clock_gettime(CLOCK_MONOTONIC, &now); surf->resource()->frame(&now); @@ -430,16 +431,39 @@ SP CPointerManager::renderHWCursorBuffer(SP(bufData)); - auto texBuffer = currentCursorImage.pBuffer ? currentCursorImage.pBuffer : currentCursorImage.surface->resource()->current.buffer; + if (currentCursorImage.pBuffer) { + auto texAttrs = currentCursorImage.pBuffer->shm(); - if (texBuffer) { - auto textAttrs = texBuffer->shm(); - auto texData = texBuffer->beginDataPtr(GBM_BO_TRANSFER_WRITE); - auto texPtr = std::get<0>(texData); - Debug::log(TRACE, "cursor texture {}x{} {} {} {}", textAttrs.size.x, textAttrs.size.y, (void*)texPtr, textAttrs.format, textAttrs.stride); + if (!texAttrs.success) { + Debug::log(TRACE, "Cannot use dumb copy on dmabuf cursor buffers"); + return nullptr; + } + + auto texData = currentCursorImage.pBuffer->beginDataPtr(GBM_BO_TRANSFER_WRITE); + auto texPtr = std::get<0>(texData); + Debug::log(TRACE, "cursor texture {}x{} {} {} {}", texAttrs.size.x, texAttrs.size.y, (void*)texPtr, texAttrs.format, texAttrs.stride); // copy cursor texture - for (int i = 0; i < texBuffer->shm().size.y; i++) - memcpy(bufPtr + i * buf->dmabuf().strides[0], texPtr + i * textAttrs.stride, textAttrs.stride); + for (int i = 0; i < texAttrs.size.y; i++) + memcpy(bufPtr + i * buf->dmabuf().strides[0], texPtr + i * texAttrs.stride, texAttrs.stride); + } else if (currentCursorImage.surface && currentCursorImage.surface->resource()->role->role() == SURFACE_ROLE_CURSOR) { + const auto SURFACE = currentCursorImage.surface->resource(); + auto& shmBuffer = CCursorSurfaceRole::cursorPixelData(SURFACE); + Debug::log(TRACE, "cursor texture pixel data length: {}B", shmBuffer.size()); + + if (shmBuffer.data()) { + // copy cursor texture + // assume format is 32bpp + size_t STRIDE = 4 * SURFACE->current.bufferSize.x; + for (int i = 0; i < SURFACE->current.bufferSize.y; i++) + memcpy(bufPtr + i * buf->dmabuf().strides[0], shmBuffer.data() + i * STRIDE, STRIDE); + } else { + // if there is no data, hide the cursor + memset(bufPtr, '\0', buf->size.x * buf->size.y * 4 /* assume 32bpp */); + } + + } else { + Debug::log(TRACE, "Unsupported cursor buffer/surface, falling back to sw (can't dumb copy)"); + return nullptr; } buf->endDataPtr(); @@ -740,7 +764,7 @@ void CPointerManager::onMonitorLayoutChange() { } SP CPointerManager::getCurrentCursorTexture() { - if (!currentCursorImage.pBuffer && (!currentCursorImage.surface || !currentCursorImage.surface->resource()->current.buffer)) + if (!currentCursorImage.pBuffer && (!currentCursorImage.surface || !currentCursorImage.surface->resource()->current.texture)) return nullptr; if (currentCursorImage.pBuffer) { @@ -749,7 +773,7 @@ SP CPointerManager::getCurrentCursorTexture() { return currentCursorImage.bufferTex; } - return currentCursorImage.surface->resource()->current.buffer->texture; + return currentCursorImage.surface->resource()->current.texture; } void CPointerManager::attachPointer(SP pointer) { diff --git a/src/protocols/DRMSyncobj.cpp b/src/protocols/DRMSyncobj.cpp index 41178109..33339554 100644 --- a/src/protocols/DRMSyncobj.cpp +++ b/src/protocols/DRMSyncobj.cpp @@ -47,7 +47,7 @@ CDRMSyncobjSurfaceResource::CDRMSyncobjSurfaceResource(SPpending.buffer) { + if ((acquireTimeline || releaseTimeline) && !surface->pending.texture) { resource->error(WP_LINUX_DRM_SYNCOBJ_SURFACE_V1_ERROR_NO_BUFFER, "Missing buffer"); surface->pending.rejected = true; return; diff --git a/src/protocols/InputMethodV2.cpp b/src/protocols/InputMethodV2.cpp index def4d837..fd306f09 100644 --- a/src/protocols/InputMethodV2.cpp +++ b/src/protocols/InputMethodV2.cpp @@ -107,14 +107,14 @@ CInputMethodPopupV2::CInputMethodPopupV2(SP resource_, }); listeners.commitSurface = surface->events.commit.registerListener([this](std::any d) { - if (pSurface->current.buffer && !mapped) { + if (pSurface->current.texture && !mapped) { mapped = true; pSurface->map(); events.map.emit(); return; } - if (!pSurface->current.buffer && mapped) { + if (!pSurface->current.texture && mapped) { mapped = false; pSurface->unmap(); events.unmap.emit(); diff --git a/src/protocols/LayerShell.cpp b/src/protocols/LayerShell.cpp index 5018828e..0ed1b219 100644 --- a/src/protocols/LayerShell.cpp +++ b/src/protocols/LayerShell.cpp @@ -44,7 +44,7 @@ CLayerShellResource::CLayerShellResource(SP resource_, SPcurrent.buffer; + bool attachedBuffer = surface->current.texture; if (attachedBuffer && !configured) { surface->error(-1, "layerSurface was not configured, but a buffer was attached"); diff --git a/src/protocols/SessionLock.cpp b/src/protocols/SessionLock.cpp index 42df5fd6..df97413c 100644 --- a/src/protocols/SessionLock.cpp +++ b/src/protocols/SessionLock.cpp @@ -24,7 +24,7 @@ CSessionLockSurface::CSessionLockSurface(SP resource_, resource->setAckConfigure([this](CExtSessionLockSurfaceV1* r, uint32_t serial) { ackdConfigure = true; }); listeners.surfaceCommit = pSurface->events.commit.registerListener([this](std::any d) { - if (!pSurface->current.buffer) { + if (!pSurface->current.texture) { LOGM(ERR, "SessionLock attached a null buffer"); resource->error(EXT_SESSION_LOCK_SURFACE_V1_ERROR_NULL_BUFFER, "Null buffer attached"); return; diff --git a/src/protocols/Viewporter.cpp b/src/protocols/Viewporter.cpp index 03c5775e..78f3039f 100644 --- a/src/protocols/Viewporter.cpp +++ b/src/protocols/Viewporter.cpp @@ -54,13 +54,13 @@ CViewportResource::CViewportResource(SP resource_, SPevents.precommit.registerListener([this](std::any d) { - if (!surface || !surface->pending.buffer) + if (!surface || !surface->pending.texture) return; if (surface->pending.viewport.hasSource) { auto& src = surface->pending.viewport.source; - if (src.w + src.x > surface->pending.buffer->size.x || src.h + src.y > surface->pending.buffer->size.y) { + if (src.w + src.x > surface->pending.bufferSize.x || src.h + src.y > surface->pending.bufferSize.y) { resource->error(WP_VIEWPORT_ERROR_BAD_VALUE, "Box doesn't fit"); surface->pending.rejected = true; return; diff --git a/src/protocols/XDGShell.cpp b/src/protocols/XDGShell.cpp index cb8a5bc3..71873374 100644 --- a/src/protocols/XDGShell.cpp +++ b/src/protocols/XDGShell.cpp @@ -347,12 +347,12 @@ CXDGSurfaceResource::CXDGSurfaceResource(SP resource_, SPcurrent = toplevel->pending; - if (initialCommit && surface->pending.buffer) { + if (initialCommit && surface->pending.texture) { resource->error(-1, "Buffer attached before initial commit"); return; } - if (surface->current.buffer && !mapped) { + if (surface->current.texture && !mapped) { // this forces apps to not draw CSD. if (toplevel) toplevel->setMaximized(true); @@ -363,7 +363,7 @@ CXDGSurfaceResource::CXDGSurfaceResource(SP resource_, SPcurrent.buffer && mapped) { + if (!surface->current.texture && mapped) { mapped = false; events.unmap.emit(); surface->unmap(); diff --git a/src/protocols/core/Compositor.cpp b/src/protocols/core/Compositor.cpp index 43d3059b..81be8e46 100644 --- a/src/protocols/core/Compositor.cpp +++ b/src/protocols/core/Compositor.cpp @@ -1,5 +1,6 @@ #include "Compositor.hpp" #include "Output.hpp" +#include "Seat.hpp" #include "../types/WLBuffer.hpp" #include #include @@ -9,6 +10,7 @@ #include "../PresentationTime.hpp" #include "../DRMSyncobj.hpp" #include "../../render/Renderer.hpp" +#include #define LOGM PROTO::compositor->protoLog @@ -19,8 +21,6 @@ class CDefaultSurfaceRole : public ISurfaceRole { } }; -SP defaultRole = makeShared(); - CWLCallbackResource::CWLCallbackResource(SP resource_) : resource(resource_) { ; } @@ -63,7 +63,7 @@ CWLSurfaceResource::CWLSurfaceResource(SP resource_) : resource(reso resource->setData(this); - role = defaultRole; + role = makeShared(); resource->setDestroy([this](CWlSurface* r) { destroy(); }); resource->setOnDestroy([this](CWlSurface* r) { destroy(); }); @@ -75,41 +75,42 @@ CWLSurfaceResource::CWLSurfaceResource(SP resource_) : resource(reso pending.buffer.reset(); pending.texture.reset(); } else { - auto res = CWLBufferResource::fromResource(buffer); - pending.buffer = res && res->buffer ? res->buffer.lock() : nullptr; - pending.size = res && res->buffer ? res->buffer->size : Vector2D{}; - pending.texture = res && res->buffer ? res->buffer->texture : nullptr; - if (res) - res->released = false; + auto res = CWLBufferResource::fromResource(buffer); + pending.buffer = res && res->buffer ? makeShared(res->buffer.lock(), self.lock()) : nullptr; + pending.size = res && res->buffer ? res->buffer->size : Vector2D{}; + pending.texture = res && res->buffer ? res->buffer->texture : nullptr; + pending.bufferSize = res && res->buffer ? res->buffer->size : Vector2D{}; } - Vector2D oldBufSize = current.buffer ? current.buffer->size : Vector2D{}; - Vector2D newBufSize = pending.buffer ? pending.buffer->size : Vector2D{}; + Vector2D oldBufSize = current.buffer ? current.bufferSize : Vector2D{}; + Vector2D newBufSize = pending.buffer ? pending.bufferSize : Vector2D{}; if (oldBufSize != newBufSize || current.buffer != pending.buffer) pending.bufferDamage = CBox{{}, {INT32_MAX, INT32_MAX}}; }); resource->setCommit([this](CWlSurface* r) { - if (pending.buffer) - pending.bufferDamage.intersect(CBox{{}, pending.buffer->size}); + if (pending.texture) + pending.bufferDamage.intersect(CBox{{}, pending.bufferSize}); - if (!pending.buffer) + if (!pending.texture) pending.size = {}; else if (pending.viewport.hasDestination) pending.size = pending.viewport.destination; else if (pending.viewport.hasSource) pending.size = pending.viewport.source.size(); else { - Vector2D tfs = pending.transform % 2 == 1 ? Vector2D{pending.buffer->size.y, pending.buffer->size.x} : pending.buffer->size; + Vector2D tfs = pending.transform % 2 == 1 ? Vector2D{pending.bufferSize.y, pending.bufferSize.x} : pending.bufferSize; pending.size = tfs / pending.scale; } pending.damage.intersect(CBox{{}, pending.size}); events.precommit.emit(); - if (pending.rejected) + if (pending.rejected) { + dropPendingBuffer(); return; + } if (stateLocks <= 0) commitPendingState(); @@ -160,6 +161,14 @@ void CWLSurfaceResource::destroy() { PROTO::compositor->destroyResource(this); } +void CWLSurfaceResource::dropPendingBuffer() { + pending.buffer.reset(); +} + +void CWLSurfaceResource::dropCurrentBuffer() { + current.buffer.reset(); +} + SP CWLSurfaceResource::fromResource(wl_resource* res) { auto data = (CWLSurfaceResource*)(((CWlSurface*)wl_resource_get_user_data(res))->data()); return data ? data->self.lock() : nullptr; @@ -240,7 +249,7 @@ void CWLSurfaceResource::frame(timespec* now) { } void CWLSurfaceResource::resetRole() { - role = defaultRole; + role = makeShared(); } void CWLSurfaceResource::bfHelper(std::vector> nodes, std::function, const Vector2D&, void*)> fn, void* data) { @@ -254,6 +263,8 @@ void CWLSurfaceResource::bfHelper(std::vector> nodes, std for (auto& c : n->subsurfaces) { if (c->zIndex >= 0) break; + if (c->surface.expired()) + continue; nodes2.push_back(c->surface.lock()); } } @@ -277,6 +288,8 @@ void CWLSurfaceResource::bfHelper(std::vector> nodes, std for (auto& c : n->subsurfaces) { if (c->zIndex < 0) continue; + if (c->surface.expired()) + continue; nodes2.push_back(c->surface.lock()); } } @@ -343,14 +356,9 @@ void CWLSurfaceResource::unmap() { } void CWLSurfaceResource::releaseBuffers(bool onlyCurrent) { - if (current.buffer && !current.buffer->resource->released) - current.buffer->sendRelease(); - if (pending.buffer && !pending.buffer->resource->released && !onlyCurrent) - pending.buffer->sendRelease(); - - pending.buffer.reset(); if (!onlyCurrent) - current.buffer.reset(); + dropPendingBuffer(); + dropCurrentBuffer(); } void CWLSurfaceResource::error(int code, const std::string& str) { @@ -375,18 +383,18 @@ CBox CWLSurfaceResource::extends() { } Vector2D CWLSurfaceResource::sourceSize() { - if (!current.buffer) + if (!current.texture) return {}; if (current.viewport.hasSource) return current.viewport.source.size(); - Vector2D trc = current.transform % 2 == 1 ? Vector2D{current.buffer->size.y, current.buffer->size.x} : current.buffer->size; + Vector2D trc = current.transform % 2 == 1 ? Vector2D{current.bufferSize.y, current.bufferSize.x} : current.bufferSize; return trc / current.scale; } CRegion CWLSurfaceResource::accumulateCurrentBufferDamage() { - if (!current.buffer) + if (!current.texture) return {}; CRegion surfaceDamage = current.damage; @@ -398,7 +406,7 @@ CRegion CWLSurfaceResource::accumulateCurrentBufferDamage() { if (current.viewport.hasSource) surfaceDamage.translate(current.viewport.source.pos()); - Vector2D trc = current.transform % 2 == 1 ? Vector2D{current.buffer->size.y, current.buffer->size.x} : current.buffer->size; + Vector2D trc = current.transform % 2 == 1 ? Vector2D{current.bufferSize.y, current.bufferSize.x} : current.bufferSize; return surfaceDamage.scale(current.scale).transform(wlTransformToHyprutils(invertTransform(current.transform)), trc.x, trc.y).add(current.bufferDamage); } @@ -421,16 +429,21 @@ void CWLSurfaceResource::commitPendingState() { pending.damage.clear(); pending.bufferDamage.clear(); - if (current.buffer && current.buffer->texture) - current.buffer->texture->m_eTransform = wlTransformToHyprutils(current.transform); + if (current.texture) + current.texture->m_eTransform = wlTransformToHyprutils(current.transform); - if (current.buffer && !current.buffer->resource->released) { - current.buffer->update(accumulateCurrentBufferDamage()); + if (current.buffer && current.buffer->buffer) { + current.buffer->buffer->update(accumulateCurrentBufferDamage()); + + // if the surface is a cursor, update the shm buffer + // TODO: don't update the entire texture + if (role->role() == SURFACE_ROLE_CURSOR) + updateCursorShm(); // release the buffer if it's synchronous as update() has done everything thats needed // so we can let the app know we're done. - if (current.buffer->isSynchronous()) - current.buffer->sendReleaseWithSurface(self.lock()); + if (current.buffer->buffer->isSynchronous()) + dropCurrentBuffer(); } // TODO: we should _accumulate_ and not replace above if sync @@ -455,20 +468,37 @@ void CWLSurfaceResource::commitPendingState() { } // for async buffers, we can only release the buffer once we are unrefing it from current. - if (previousBuffer && !previousBuffer->isSynchronous() && !previousBuffer->resource->released) { - if (previousBuffer->lockedByBackend) { - previousBuffer->hlEvents.backendRelease = previousBuffer->events.backendRelease.registerListener([this, previousBuffer](std::any data) { - if (!self.expired()) // could be dead in the dtor - previousBuffer->sendReleaseWithSurface(self.lock()); - else - previousBuffer->sendRelease(); - previousBuffer->hlEvents.backendRelease.reset(); - }); - } else - previousBuffer->sendReleaseWithSurface(self.lock()); - - previousBuffer->resource->released = true; // set it here regardless so we dont set more listeners for backendRelease + // if the backend took it, ref it with the lambda. Otherwise, the end of this scope will release it. + if (previousBuffer && previousBuffer->buffer && !previousBuffer->buffer->isSynchronous()) { + if (previousBuffer->buffer->lockedByBackend && !previousBuffer->buffer->hlEvents.backendRelease) { + previousBuffer->buffer->lock(); + previousBuffer->buffer->unlockOnBufferRelease(self); + } } + + lastBuffer = current.buffer ? current.buffer->buffer : WP{}; +} + +void CWLSurfaceResource::updateCursorShm() { + auto buf = current.buffer ? current.buffer : lastBuffer; + + if (!buf) + return; + + // TODO: actually use damage + auto& shmData = CCursorSurfaceRole::cursorPixelData(self.lock()); + auto shmAttrs = current.buffer->buffer->shm(); + + if (!shmAttrs.success) { + LOGM(TRACE, "updateCursorShm: ignoring, not a shm buffer"); + return; + } + + // no need to end, shm. + auto [pixelData, fmt, bufLen] = current.buffer->buffer->beginDataPtr(0); + + shmData.resize(bufLen); + memcpy(shmData.data(), pixelData, bufLen); } void CWLSurfaceResource::presentFeedback(timespec* when, CMonitor* pMonitor, bool needsExplicitSync) { diff --git a/src/protocols/core/Compositor.hpp b/src/protocols/core/Compositor.hpp index 79cd1de6..460ec755 100644 --- a/src/protocols/core/Compositor.hpp +++ b/src/protocols/core/Compositor.hpp @@ -84,13 +84,13 @@ class CWLSurfaceResource { } events; struct SState { - CRegion opaque, input = CBox{{}, {INT32_MAX, INT32_MAX}}, damage, bufferDamage = CBox{{}, {INT32_MAX, INT32_MAX}} /* initial damage */; - wl_output_transform transform = WL_OUTPUT_TRANSFORM_NORMAL; - int scale = 1; - SP buffer; - SP texture; - Vector2D offset; - Vector2D size; + CRegion opaque, input = CBox{{}, {INT32_MAX, INT32_MAX}}, damage, bufferDamage = CBox{{}, {INT32_MAX, INT32_MAX}} /* initial damage */; + wl_output_transform transform = WL_OUTPUT_TRANSFORM_NORMAL; + int scale = 1; + SP buffer; // buffer ref will be released once the buffer is no longer locked. For checking if a buffer is attached to this state, check texture. + SP texture; + Vector2D offset; + Vector2D size, bufferSize; struct { bool hasDestination = false; bool hasSource = false; @@ -116,7 +116,7 @@ class CWLSurfaceResource { std::vector> enteredOutputs; bool mapped = false; std::vector> subsurfaces; - WP role; + SP role; WP viewportResource; WP syncobj; // may not be present @@ -134,12 +134,21 @@ class CWLSurfaceResource { SP resource; wl_client* pClient = nullptr; - int stateLocks = 0; + // this is for cursor dumb copy. Due to our (and wayland's...) architecture, + // this stupid-ass hack is used + WP lastBuffer; - void destroy(); - void releaseBuffers(bool onlyCurrent = true); - void commitPendingState(); - void bfHelper(std::vector> nodes, std::function, const Vector2D&, void*)> fn, void* data); + int stateLocks = 0; + + void destroy(); + void releaseBuffers(bool onlyCurrent = true); + void dropPendingBuffer(); + void dropCurrentBuffer(); + void commitPendingState(); + void bfHelper(std::vector> nodes, std::function, const Vector2D&, void*)> fn, void* data); + void updateCursorShm(); + + friend class CWLPointerResource; }; class CWLCompositorResource { diff --git a/src/protocols/core/DataDevice.cpp b/src/protocols/core/DataDevice.cpp index 9634d569..fe3905d0 100644 --- a/src/protocols/core/DataDevice.cpp +++ b/src/protocols/core/DataDevice.cpp @@ -469,12 +469,12 @@ void CWLDataDeviceProtocol::initiateDrag(WP currentSource if (dragSurface) { dnd.dndSurfaceDestroy = dragSurface->events.destroy.registerListener([this](std::any d) { abortDrag(); }); dnd.dndSurfaceCommit = dragSurface->events.commit.registerListener([this](std::any d) { - if (dnd.dndSurface->current.buffer && !dnd.dndSurface->mapped) { + if (dnd.dndSurface->current.texture && !dnd.dndSurface->mapped) { dnd.dndSurface->map(); return; } - if (dnd.dndSurface->current.buffer <= 0 && dnd.dndSurface->mapped) { + if (dnd.dndSurface->current.texture <= 0 && dnd.dndSurface->mapped) { dnd.dndSurface->unmap(); return; } @@ -660,13 +660,13 @@ void CWLDataDeviceProtocol::abortDrag() { } void CWLDataDeviceProtocol::renderDND(CMonitor* pMonitor, timespec* when) { - if (!dnd.dndSurface || !dnd.dndSurface->current.buffer || !dnd.dndSurface->current.buffer->texture) + if (!dnd.dndSurface || !dnd.dndSurface->current.texture) return; const auto POS = g_pInputManager->getMouseCoordsInternal(); CBox box = CBox{POS, dnd.dndSurface->current.size}.translate(-pMonitor->vecPosition + g_pPointerManager->cursorSizeLogical() / 2.F).scale(pMonitor->scale); - g_pHyprOpenGL->renderTexture(dnd.dndSurface->current.buffer->texture, &box, 1.F); + g_pHyprOpenGL->renderTexture(dnd.dndSurface->current.texture, &box, 1.F); box = CBox{POS, dnd.dndSurface->current.size}.translate(g_pPointerManager->cursorSizeLogical() / 2.F); g_pHyprRenderer->damageBox(&box); diff --git a/src/protocols/core/Seat.cpp b/src/protocols/core/Seat.cpp index 7a295372..bb6a9d4d 100644 --- a/src/protocols/core/Seat.cpp +++ b/src/protocols/core/Seat.cpp @@ -119,7 +119,19 @@ CWLPointerResource::CWLPointerResource(SP resource_, SPonSetCursor(owner.lock(), serial, surf ? CWLSurfaceResource::fromResource(surf) : nullptr, {hotX, hotY}); + auto surfResource = surf ? CWLSurfaceResource::fromResource(surf) : nullptr; + + if (surfResource && surfResource->role->role() != SURFACE_ROLE_CURSOR && surfResource->role->role() != SURFACE_ROLE_UNASSIGNED) { + r->error(-1, "Cursor surface already has a different role"); + return; + } + + if (surfResource) { + surfResource->role = makeShared(); + surfResource->updateCursorShm(); + } + + g_pSeatManager->onSetCursor(owner.lock(), serial, surfResource, {hotX, hotY}); }); if (g_pSeatManager->state.pointerFocus && g_pSeatManager->state.pointerFocus->client() == resource->client()) @@ -546,3 +558,10 @@ SP CWLSeatProtocol::seatResourceForClient(wl_client* client) { return nullptr; } + +std::vector& CCursorSurfaceRole::cursorPixelData(SP surface) { + RASSERT(surface->role->role() == SURFACE_ROLE_CURSOR, "cursorPixelData called on a non-cursor surface"); + + auto role = (CCursorSurfaceRole*)surface->role.get(); + return role->cursorShmPixelData; +} diff --git a/src/protocols/core/Seat.hpp b/src/protocols/core/Seat.hpp index 09b36056..755a9c2f 100644 --- a/src/protocols/core/Seat.hpp +++ b/src/protocols/core/Seat.hpp @@ -16,6 +16,7 @@ #include "wayland.hpp" #include "../../helpers/signal/Signal.hpp" #include "../../helpers/math/Math.hpp" +#include "../types/SurfaceRole.hpp" constexpr const char* HL_SEAT_NAME = "Hyprland"; @@ -27,6 +28,20 @@ class CWLKeyboardResource; class CWLTouchResource; class CWLSeatResource; +class CCursorSurfaceRole : public ISurfaceRole { + public: + virtual eSurfaceRole role() { + return SURFACE_ROLE_CURSOR; + } + + // gets the current pixel data from a shm surface + // will assert if the surface is not a cursor + static std::vector& cursorPixelData(SP surface); + + private: + std::vector cursorShmPixelData; +}; + class CWLTouchResource { public: CWLTouchResource(SP resource_, SP owner_); diff --git a/src/protocols/core/Subcompositor.cpp b/src/protocols/core/Subcompositor.cpp index c0c1f258..90f89d91 100644 --- a/src/protocols/core/Subcompositor.cpp +++ b/src/protocols/core/Subcompositor.cpp @@ -80,13 +80,13 @@ CWLSubsurfaceResource::CWLSubsurfaceResource(SP resource_, SPevents.commit.registerListener([this](std::any d) { - if (surface->current.buffer && !surface->mapped) { + if (surface->current.texture && !surface->mapped) { surface->map(); surface->events.map.emit(); return; } - if (!surface->current.buffer && surface->mapped) { + if (!surface->current.texture && surface->mapped) { surface->events.unmap.emit(); surface->unmap(); return; diff --git a/src/protocols/types/Buffer.cpp b/src/protocols/types/Buffer.cpp index 0217f7e2..40f2eaf8 100644 --- a/src/protocols/types/Buffer.cpp +++ b/src/protocols/types/Buffer.cpp @@ -1,5 +1,10 @@ #include "Buffer.hpp" +IHLBuffer::~IHLBuffer() { + if (locked() && resource) + sendRelease(); +} + void IHLBuffer::sendRelease() { resource->sendRelease(); } @@ -8,3 +13,54 @@ void IHLBuffer::sendReleaseWithSurface(SP surf) { if (resource && resource->good()) resource->sendReleaseWithSurface(surf); } + +void IHLBuffer::lock() { + nLocks++; +} + +void IHLBuffer::unlock() { + nLocks--; + + ASSERT(nLocks >= 0); + + if (nLocks == 0) + sendRelease(); +} + +void IHLBuffer::unlockWithSurface(SP surf) { + nLocks--; + + ASSERT(nLocks >= 0); + + if (nLocks == 0) + sendReleaseWithSurface(surf); +} + +bool IHLBuffer::locked() { + return nLocks > 0; +} + +void IHLBuffer::unlockOnBufferRelease(WP surf) { + unlockSurface = surf; + hlEvents.backendRelease = events.backendRelease.registerListener([this](std::any data) { + if (unlockSurface.expired()) + unlock(); + else + unlockWithSurface(unlockSurface.lock()); + hlEvents.backendRelease.reset(); + }); +} + +CHLBufferReference::CHLBufferReference(SP buffer_, SP surface_) : buffer(buffer_), surface(surface_) { + buffer->lock(); +} + +CHLBufferReference::~CHLBufferReference() { + if (buffer.expired()) + return; + + if (surface) + buffer->unlockWithSurface(surface.lock()); + else + buffer->unlock(); +} diff --git a/src/protocols/types/Buffer.hpp b/src/protocols/types/Buffer.hpp index ba8278f3..d2157181 100644 --- a/src/protocols/types/Buffer.hpp +++ b/src/protocols/types/Buffer.hpp @@ -8,9 +8,7 @@ class IHLBuffer : public Aquamarine::IBuffer { public: - virtual ~IHLBuffer() { - ; - } + virtual ~IHLBuffer(); virtual Aquamarine::eBufferCapability caps() = 0; virtual Aquamarine::eBufferType type() = 0; virtual void update(const CRegion& damage) = 0; @@ -18,6 +16,12 @@ class IHLBuffer : public Aquamarine::IBuffer { virtual bool good() = 0; virtual void sendRelease(); virtual void sendReleaseWithSurface(SP); + virtual void lock(); + virtual void unlock(); + virtual void unlockWithSurface(SP surf); + virtual bool locked(); + + void unlockOnBufferRelease(WP surf /* optional */); SP texture; bool opaque = false; @@ -26,4 +30,22 @@ class IHLBuffer : public Aquamarine::IBuffer { struct { CHyprSignalListener backendRelease; } hlEvents; + + private: + int nLocks = 0; + + WP unlockSurface; +}; + +// for ref-counting. Releases in ~dtor +// surface optional +class CHLBufferReference { + public: + CHLBufferReference(SP buffer, SP surface); + ~CHLBufferReference(); + + WP buffer; + + private: + WP surface; }; diff --git a/src/protocols/types/SurfaceRole.hpp b/src/protocols/types/SurfaceRole.hpp index faaf70ee..64586f01 100644 --- a/src/protocols/types/SurfaceRole.hpp +++ b/src/protocols/types/SurfaceRole.hpp @@ -6,6 +6,7 @@ enum eSurfaceRole { SURFACE_ROLE_LAYER_SHELL, SURFACE_ROLE_EASTER_EGG, SURFACE_ROLE_SUBSURFACE, + SURFACE_ROLE_CURSOR, }; class ISurfaceRole { diff --git a/src/protocols/types/WLBuffer.cpp b/src/protocols/types/WLBuffer.cpp index e42094b1..d34a867d 100644 --- a/src/protocols/types/WLBuffer.cpp +++ b/src/protocols/types/WLBuffer.cpp @@ -29,7 +29,6 @@ bool CWLBufferResource::good() { } void CWLBufferResource::sendRelease() { - released = true; resource->sendRelease(); } diff --git a/src/protocols/types/WLBuffer.hpp b/src/protocols/types/WLBuffer.hpp index f4424abc..59512128 100644 --- a/src/protocols/types/WLBuffer.hpp +++ b/src/protocols/types/WLBuffer.hpp @@ -24,8 +24,6 @@ class CWLBufferResource { WP self; - bool released = false; - private: CWLBufferResource(SP resource_); diff --git a/src/render/Renderer.cpp b/src/render/Renderer.cpp index e4f97895..127ae187 100644 --- a/src/render/Renderer.cpp +++ b/src/render/Renderer.cpp @@ -102,10 +102,10 @@ CHyprRenderer::~CHyprRenderer() { } static void renderSurface(SP surface, int x, int y, void* data) { - if (!surface->current.buffer || !surface->current.buffer->texture) + if (!surface->current.texture) return; - const auto& TEXTURE = surface->current.buffer->texture; + const auto& TEXTURE = surface->current.texture; const auto RDATA = (SRenderData*)data; const auto INTERACTIVERESIZEINPROGRESS = RDATA->pWindow && g_pInputManager->currentlyDraggedWindow.lock() == RDATA->pWindow && g_pInputManager->dragMode == MBIND_RESIZE; @@ -192,8 +192,8 @@ static void renderSurface(SP surface, int x, int y, void* da windowBox.round(); const bool MISALIGNEDFSV1 = std::floor(RDATA->pMonitor->scale) != RDATA->pMonitor->scale /* Fractional */ && surface->current.scale == 1 /* fs protocol */ && - windowBox.size() != surface->current.buffer->size /* misaligned */ && DELTALESSTHAN(windowBox.width, surface->current.buffer->size.x, 3) && - DELTALESSTHAN(windowBox.height, surface->current.buffer->size.y, 3) /* off by one-or-two */ && + windowBox.size() != surface->current.bufferSize /* misaligned */ && DELTALESSTHAN(windowBox.width, surface->current.bufferSize.x, 3) && + DELTALESSTHAN(windowBox.height, surface->current.bufferSize.y, 3) /* off by one-or-two */ && (!RDATA->pWindow || (!RDATA->pWindow->m_vRealSize.isBeingAnimated() && !INTERACTIVERESIZEINPROGRESS)) /* not window or not animated/resizing */; g_pHyprRenderer->calculateUVForSurface(RDATA->pWindow, surface, RDATA->surface == surface, windowBox.size(), MISALIGNEDFSV1); @@ -1014,7 +1014,7 @@ void CHyprRenderer::calculateUVForSurface(PHLWINDOW pWindow, SPcurrent.viewport.hasSource) { // we stretch it to dest. if no dest, to 1,1 - Vector2D bufferSize = pSurface->current.buffer->size; + Vector2D bufferSize = pSurface->current.bufferSize; auto bufferSource = pSurface->current.viewport.source; // calculate UV for the basic src_box. Assume dest == size. Scale to dest later @@ -1030,8 +1030,8 @@ void CHyprRenderer::calculateUVForSurface(PHLWINDOW pWindow, SPcurrent.buffer->size; - const Vector2D MISALIGNMENT = pSurface->current.buffer->size - projSize; + const Vector2D PIXELASUV = Vector2D{1, 1} / pSurface->current.bufferSize; + const Vector2D MISALIGNMENT = pSurface->current.bufferSize - projSize; if (MISALIGNMENT != Vector2D{}) uvBR -= MISALIGNMENT * PIXELASUV; } diff --git a/src/render/Texture.cpp b/src/render/Texture.cpp index 0f5b4c4c..94d00184 100644 --- a/src/render/Texture.cpp +++ b/src/render/Texture.cpp @@ -28,6 +28,8 @@ CTexture::CTexture(const SP buffer) { if (!buffer) return; + m_bOpaque = buffer->opaque; + auto attrs = buffer->dmabuf(); if (!attrs.success) { @@ -86,6 +88,7 @@ void CTexture::createFromDma(const Aquamarine::SDMABUFAttrs& attrs, void* image) return; } + m_bOpaque = FormatUtils::isFormatOpaque(attrs.format); m_iTarget = GL_TEXTURE_2D; m_iType = TEXTURE_RGBA; m_vSize = attrs.size; diff --git a/src/render/Texture.hpp b/src/render/Texture.hpp index a54be8c5..e0ef5503 100644 --- a/src/render/Texture.hpp +++ b/src/render/Texture.hpp @@ -41,6 +41,7 @@ class CTexture { Vector2D m_vSize = {}; void* m_pEglImage = nullptr; eTransform m_eTransform = HYPRUTILS_TRANSFORM_NORMAL; + bool m_bOpaque = false; private: void createFromShm(uint32_t drmFormat, uint8_t* pixels, uint32_t stride, const Vector2D& size); diff --git a/src/xwayland/XSurface.cpp b/src/xwayland/XSurface.cpp index 107b22da..30ffbc68 100644 --- a/src/xwayland/XSurface.cpp +++ b/src/xwayland/XSurface.cpp @@ -62,12 +62,12 @@ void CXWaylandSurface::ensureListeners() { }); listeners.commitSurface = surface->events.commit.registerListener([this](std::any d) { - if (surface->pending.buffer && !mapped) { + if (surface->pending.texture && !mapped) { map(); return; } - if (!surface->pending.buffer && mapped) { + if (!surface->pending.texture && mapped) { unmap(); return; } @@ -131,7 +131,7 @@ void CXWaylandSurface::considerMap() { return; } - if (surface->pending.buffer) { + if (surface->pending.texture) { Debug::log(LOG, "XWayland surface: considerMap, sure, we have a buffer"); map(); return; From 5b7057c4790e0dafea53c2343a792c17e2dbf4a7 Mon Sep 17 00:00:00 2001 From: Tom Englund Date: Thu, 1 Aug 2024 11:42:22 +0200 Subject: [PATCH 0216/2181] pointer: fix buffer crash (#7131) current buffer->buffer can turn out to be null actually check for its existence or use the lastbuffer when calling updateCursorShm() --- src/protocols/core/Compositor.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/protocols/core/Compositor.cpp b/src/protocols/core/Compositor.cpp index 81be8e46..bff52133 100644 --- a/src/protocols/core/Compositor.cpp +++ b/src/protocols/core/Compositor.cpp @@ -480,14 +480,14 @@ void CWLSurfaceResource::commitPendingState() { } void CWLSurfaceResource::updateCursorShm() { - auto buf = current.buffer ? current.buffer : lastBuffer; + auto buf = current.buffer ? current.buffer->buffer : lastBuffer; if (!buf) return; // TODO: actually use damage auto& shmData = CCursorSurfaceRole::cursorPixelData(self.lock()); - auto shmAttrs = current.buffer->buffer->shm(); + auto shmAttrs = buf->shm(); if (!shmAttrs.success) { LOGM(TRACE, "updateCursorShm: ignoring, not a shm buffer"); @@ -495,7 +495,7 @@ void CWLSurfaceResource::updateCursorShm() { } // no need to end, shm. - auto [pixelData, fmt, bufLen] = current.buffer->buffer->beginDataPtr(0); + auto [pixelData, fmt, bufLen] = buf->beginDataPtr(0); shmData.resize(bufLen); memcpy(shmData.data(), pixelData, bufLen); From 8c02b3c267198541dd03601e4c7ff7d870197728 Mon Sep 17 00:00:00 2001 From: Sungyoon Cho Date: Thu, 1 Aug 2024 18:43:02 +0900 Subject: [PATCH 0217/2181] layout: fix dynamic rules not updating after setting fullscreen (#7129) --- src/Compositor.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/Compositor.cpp b/src/Compositor.cpp index 7221d3a7..2a1e4f8c 100644 --- a/src/Compositor.cpp +++ b/src/Compositor.cpp @@ -2316,9 +2316,10 @@ void CCompositor::setWindowFullscreenState(const PHLWINDOW PWINDOW, sFullscreenS g_pEventManager->postEvent(SHyprIPCEvent{"fullscreen", std::to_string((int)EFFECTIVE_MODE != FSMODE_NONE)}); EMIT_HOOK_EVENT("fullscreen", PWINDOW); - g_pLayoutManager->getCurrentLayout()->recalculateMonitor(PWINDOW->m_iMonitorID); + PWINDOW->updateDynamicRules(); PWINDOW->updateWindowDecos(); updateWindowAnimatedDecorationValues(PWINDOW); + g_pLayoutManager->getCurrentLayout()->recalculateMonitor(PWINDOW->m_iMonitorID); // make all windows on the same workspace under the fullscreen window for (auto& w : m_vWindows) { From 95959789b7667172b2b2f37f78fe96ac196e9cd3 Mon Sep 17 00:00:00 2001 From: MightyPlaza <123664421+MightyPlaza@users.noreply.github.com> Date: Thu, 1 Aug 2024 09:43:32 +0000 Subject: [PATCH 0218/2181] keybinds: allow toggling fullscreenstate (#7128) modified: src/managers/KeybindManager.cpp --- src/managers/KeybindManager.cpp | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/src/managers/KeybindManager.cpp b/src/managers/KeybindManager.cpp index 33b07351..9984fe40 100644 --- a/src/managers/KeybindManager.cpp +++ b/src/managers/KeybindManager.cpp @@ -1174,9 +1174,13 @@ void CKeybindManager::fullscreenStateActive(std::string args) { clientMode = std::stoi(ARGS[1]); } catch (std::exception& e) { clientMode = -1; } - g_pCompositor->setWindowFullscreenState(PWINDOW, - sFullscreenState{.internal = (internalMode != -1 ? (eFullscreenMode)internalMode : PWINDOW->m_sFullscreenState.internal), - .client = (clientMode != -1 ? (eFullscreenMode)clientMode : PWINDOW->m_sFullscreenState.client)}); + const sFullscreenState STATE = sFullscreenState{.internal = (internalMode != -1 ? (eFullscreenMode)internalMode : PWINDOW->m_sFullscreenState.internal), + .client = (clientMode != -1 ? (eFullscreenMode)clientMode : PWINDOW->m_sFullscreenState.client)}; + + if (PWINDOW->m_sFullscreenState.internal == STATE.internal && PWINDOW->m_sFullscreenState.client == STATE.client) + g_pCompositor->setWindowFullscreenState(PWINDOW, sFullscreenState{.internal = FSMODE_NONE, .client = FSMODE_NONE}); + else + g_pCompositor->setWindowFullscreenState(PWINDOW, STATE); } void CKeybindManager::moveActiveToWorkspace(std::string args) { From 5edfa627b4efc5d2125f4f0f97dad6bac6c3a407 Mon Sep 17 00:00:00 2001 From: Vaxry Date: Thu, 1 Aug 2024 11:45:55 +0200 Subject: [PATCH 0219/2181] layershell: don't throw misaligned error on exclusive edge 0 ref #7108 --- src/protocols/LayerShell.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/protocols/LayerShell.cpp b/src/protocols/LayerShell.cpp index 0ed1b219..295ef4a9 100644 --- a/src/protocols/LayerShell.cpp +++ b/src/protocols/LayerShell.cpp @@ -159,7 +159,7 @@ CLayerShellResource::CLayerShellResource(SP resource_, SPerror(ZWLR_LAYER_SURFACE_V1_ERROR_INVALID_EXCLUSIVE_EDGE, "Exclusive edge doesn't align with anchor"); return; } From 60571cd5ccc76f91209ef2faac93ecea542de221 Mon Sep 17 00:00:00 2001 From: Vaxry Date: Thu, 1 Aug 2024 12:36:09 +0200 Subject: [PATCH 0220/2181] border: fixup infinite recursion ref #7127 --- src/render/decorations/CHyprBorderDecoration.cpp | 14 ++++++++++++-- src/render/decorations/CHyprBorderDecoration.hpp | 2 ++ 2 files changed, 14 insertions(+), 2 deletions(-) diff --git a/src/render/decorations/CHyprBorderDecoration.cpp b/src/render/decorations/CHyprBorderDecoration.cpp index 708215b6..ddb38c6e 100644 --- a/src/render/decorations/CHyprBorderDecoration.cpp +++ b/src/render/decorations/CHyprBorderDecoration.cpp @@ -1,6 +1,7 @@ #include "CHyprBorderDecoration.hpp" #include "../../Compositor.hpp" #include "../../config/ConfigValue.hpp" +#include "../../managers/eventLoop/EventLoopManager.hpp" CHyprBorderDecoration::CHyprBorderDecoration(PHLWINDOW pWindow) : IHyprWindowDecoration(pWindow) { m_pWindow = pWindow; @@ -82,8 +83,17 @@ eDecorationType CHyprBorderDecoration::getDecorationType() { } void CHyprBorderDecoration::updateWindow(PHLWINDOW) { - if (m_pWindow->getRealBorderSize() != m_seExtents.topLeft.x) - g_pDecorationPositioner->repositionDeco(this); + auto borderSize = m_pWindow->getRealBorderSize(); + + if (borderSize == m_iLastBorderSize) + return; + + if (borderSize <= 0 && m_iLastBorderSize <= 0) + return; + + m_iLastBorderSize = borderSize; + + g_pEventLoopManager->doLater([this]() { g_pDecorationPositioner->repositionDeco(this); }); } void CHyprBorderDecoration::damageEntire() { diff --git a/src/render/decorations/CHyprBorderDecoration.hpp b/src/render/decorations/CHyprBorderDecoration.hpp index 8ad3263e..0e196565 100644 --- a/src/render/decorations/CHyprBorderDecoration.hpp +++ b/src/render/decorations/CHyprBorderDecoration.hpp @@ -36,6 +36,8 @@ class CHyprBorderDecoration : public IHyprWindowDecoration { CBox m_bAssignedGeometry = {0}; + int m_iLastBorderSize = -1; + CBox assignedBoxGlobal(); bool doesntWantBorders(); }; From c8873b958dd9330c364339ac4ab58e32b27d82b4 Mon Sep 17 00:00:00 2001 From: MightyPlaza <123664421+MightyPlaza@users.noreply.github.com> Date: Thu, 1 Aug 2024 12:59:52 +0000 Subject: [PATCH 0221/2181] internal: fix fullscreen typos (#7134) modified: src/events/Windows.cpp modified: src/layout/DwindleLayout.cpp --- src/events/Windows.cpp | 4 ++-- src/layout/DwindleLayout.cpp | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/events/Windows.cpp b/src/events/Windows.cpp index 0389f57e..f5ae6759 100644 --- a/src/events/Windows.cpp +++ b/src/events/Windows.cpp @@ -487,9 +487,9 @@ void Events::listener_mapWindow(void* owner, void* data) { PWINDOW->m_fDimPercent.setValueAndWarp(0); } - if (requestedClientFSMode.has_value() && !(PWINDOW->m_eSuppressedEvents & SUPPRESS_FULLSCREEN)) + if (requestedClientFSMode.has_value() && (PWINDOW->m_eSuppressedEvents & SUPPRESS_FULLSCREEN)) requestedClientFSMode = (eFullscreenMode)((uint8_t)requestedClientFSMode.value_or(FSMODE_NONE) & ~(uint8_t)FSMODE_FULLSCREEN); - if (requestedClientFSMode.has_value() && !(PWINDOW->m_eSuppressedEvents & SUPPRESS_MAXIMIZE)) + if (requestedClientFSMode.has_value() && (PWINDOW->m_eSuppressedEvents & SUPPRESS_MAXIMIZE)) requestedClientFSMode = (eFullscreenMode)((uint8_t)requestedClientFSMode.value_or(FSMODE_NONE) & ~(uint8_t)FSMODE_MAXIMIZED); if (!PWINDOW->m_bNoInitialFocus && (requestedInternalFSMode.has_value() || requestedClientFSMode.has_value() || requestedFSState.has_value())) { diff --git a/src/layout/DwindleLayout.cpp b/src/layout/DwindleLayout.cpp index 336c8c68..7253275d 100644 --- a/src/layout/DwindleLayout.cpp +++ b/src/layout/DwindleLayout.cpp @@ -926,7 +926,7 @@ void CHyprDwindleLayout::switchWindows(PHLWINDOW pWindow, PHLWINDOW pWindow2) { return; const eFullscreenMode MODE1 = pWindow->m_sFullscreenState.internal; - const eFullscreenMode MODE2 = pWindow->m_sFullscreenState.internal; + const eFullscreenMode MODE2 = pWindow2->m_sFullscreenState.internal; g_pCompositor->setWindowFullscreenInternal(pWindow, FSMODE_NONE); g_pCompositor->setWindowFullscreenInternal(pWindow2, FSMODE_NONE); From ab0a3268e04f2295ec4455be90ce8d0c2b107b8d Mon Sep 17 00:00:00 2001 From: Vaxry Date: Thu, 1 Aug 2024 15:43:13 +0200 Subject: [PATCH 0222/2181] xdg-shell: fixup unassigned wl surfaces to xdg surfaces fixes #7133 --- src/protocols/XDGShell.cpp | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/protocols/XDGShell.cpp b/src/protocols/XDGShell.cpp index 71873374..5e82b530 100644 --- a/src/protocols/XDGShell.cpp +++ b/src/protocols/XDGShell.cpp @@ -666,8 +666,9 @@ CXDGWMBase::CXDGWMBase(SP resource_) : resource(resource_) { return; } - RESOURCE->self = RESOURCE; - SURF->role = RESOURCE; + RESOURCE->self = RESOURCE; + RESOURCE->surface = SURF; + SURF->role = RESOURCE; surfaces.emplace_back(RESOURCE); From 09bb5658b7fa6c0dc4e2744797e51ad4dd25af42 Mon Sep 17 00:00:00 2001 From: Vaxry Date: Fri, 2 Aug 2024 00:31:44 +0200 Subject: [PATCH 0223/2181] window/ls: reset core signals after destroy fixes #7137 --- src/desktop/LayerSurface.cpp | 5 +++++ src/events/Windows.cpp | 5 +++++ 2 files changed, 10 insertions(+) diff --git a/src/desktop/LayerSurface.cpp b/src/desktop/LayerSurface.cpp index ba1b1776..8fd448ef 100644 --- a/src/desktop/LayerSurface.cpp +++ b/src/desktop/LayerSurface.cpp @@ -111,6 +111,11 @@ void CLayerSurface::onDestroy() { layerSurface.reset(); if (surface) surface->unassign(); + + listeners.unmap.reset(); + listeners.destroy.reset(); + listeners.map.reset(); + listeners.commit.reset(); } void CLayerSurface::onMap() { diff --git a/src/events/Windows.cpp b/src/events/Windows.cpp index f5ae6759..5d29a3b7 100644 --- a/src/events/Windows.cpp +++ b/src/events/Windows.cpp @@ -790,6 +790,11 @@ void Events::listener_destroyWindow(void* owner, void* data) { Debug::log(LOG, "Unmapped {} removed instantly", PWINDOW); g_pCompositor->removeWindowFromVectorSafe(PWINDOW); // most likely X11 unmanaged or sumn } + + PWINDOW->listeners.unmap.reset(); + PWINDOW->listeners.destroy.reset(); + PWINDOW->listeners.map.reset(); + PWINDOW->listeners.commit.reset(); } void Events::listener_setTitleWindow(void* owner, void* data) { From 592b4a709c8093273c6051fb7e76ce3c3d82cedf Mon Sep 17 00:00:00 2001 From: Maximilian Seidler <78690852+PaideiaDilemma@users.noreply.github.com> Date: Fri, 2 Aug 2024 15:25:51 +0200 Subject: [PATCH 0224/2181] sessionLock: don't sendLocked when session lock has already been destoyed (#7150) * sessionLock: reset m_pSessionLock on destroy * sessionLock: only send locked when resource is good --- src/managers/SessionLockManager.cpp | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/src/managers/SessionLockManager.cpp b/src/managers/SessionLockManager.cpp index 83ff3ee7..a82432a8 100644 --- a/src/managers/SessionLockManager.cpp +++ b/src/managers/SessionLockManager.cpp @@ -71,7 +71,8 @@ void CSessionLockManager::onNewSessionLock(SP pLock) { g_pHyprRenderer->damageMonitor(m.get()); }); - m_pSessionLock->listeners.destroy = pLock->events.destroyed.registerListener([](std::any data) { + m_pSessionLock->listeners.destroy = pLock->events.destroyed.registerListener([this](std::any data) { + m_pSessionLock.reset(); g_pCompositor->focusSurface(nullptr); for (auto& m : g_pCompositor->m_vMonitors) @@ -104,7 +105,7 @@ SSessionLockSurface* CSessionLockManager::getSessionLockSurfaceForMonitor(uint64 // We don't want the red screen to flash. float CSessionLockManager::getRedScreenAlphaForMonitor(uint64_t id) { if (!m_pSessionLock) - return 0.F; + return 1.F; const auto& NOMAPPEDSURFACETIMER = m_pSessionLock->mMonitorsWithoutMappedSurfaceTimers.find(id); @@ -123,7 +124,7 @@ void CSessionLockManager::onLockscreenRenderedOnMonitor(uint64_t id) { m_pSessionLock->m_lockedMonitors.emplace(id); const auto MONITORS = g_pCompositor->m_vMonitors; const bool LOCKED = std::all_of(MONITORS.begin(), MONITORS.end(), [this](auto m) { return m_pSessionLock->m_lockedMonitors.contains(m->ID); }); - if (LOCKED) { + if (LOCKED && m_pSessionLock->lock->good()) { m_pSessionLock->lock->sendLocked(); m_pSessionLock->m_hasSentLocked = true; } From 1fa4b7d79baaad47fde8e72221cd77f569fbfe35 Mon Sep 17 00:00:00 2001 From: Vaxry Date: Fri, 2 Aug 2024 18:42:05 +0200 Subject: [PATCH 0225/2181] hyprerror: minor stylistic changes --- src/hyprerror/HyprError.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/hyprerror/HyprError.cpp b/src/hyprerror/HyprError.cpp index a325d858..bbc3a006 100644 --- a/src/hyprerror/HyprError.cpp +++ b/src/hyprerror/HyprError.cpp @@ -88,14 +88,14 @@ void CHyprError::createQueued() { cairo_arc(CAIRO, X + RADIUS, Y + RADIUS, RADIUS, 180 * DEGREES, 270 * DEGREES); cairo_close_path(CAIRO); - cairo_set_source_rgba(CAIRO, m_cQueued.r, m_cQueued.g, m_cQueued.b, m_cQueued.a); + cairo_set_source_rgba(CAIRO, 0.06, 0.06, 0.06, 1.0); cairo_fill_preserve(CAIRO); - cairo_set_source_rgba(CAIRO, 0, 0, 0, 1); + cairo_set_source_rgba(CAIRO, m_cQueued.r, m_cQueued.g, m_cQueued.b, m_cQueued.a); cairo_set_line_width(CAIRO, 2); cairo_stroke(CAIRO); // draw the text with a common font - const CColor textColor = m_cQueued.r + m_cQueued.g + m_cQueued.b < 0.2f ? CColor(1.0, 1.0, 1.0, 1.0) : CColor(0, 0, 0, 1.0); + const CColor textColor = CColor(0.9, 0.9, 0.9, 1.0); cairo_set_source_rgba(CAIRO, textColor.r, textColor.g, textColor.b, textColor.a); static auto fontFamily = CConfigValue("misc:font_family"); From be2dfa36ef635add2d55c96f7616ec61b96e7bb1 Mon Sep 17 00:00:00 2001 From: Tuur Vanhoutte <4633209+zjeffer@users.noreply.github.com> Date: Fri, 2 Aug 2024 21:49:47 +0200 Subject: [PATCH 0226/2181] hyprctl: increase hyprctl timeout to 5s to fix #6801 (#7152) --- hyprctl/main.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/hyprctl/main.cpp b/hyprctl/main.cpp index 45fe9142..336d479e 100644 --- a/hyprctl/main.cpp +++ b/hyprctl/main.cpp @@ -141,7 +141,7 @@ int rollingRead(const int socket) { int request(std::string arg, int minArgs = 0, bool needRoll = false) { const auto SERVERSOCKET = socket(AF_UNIX, SOCK_STREAM, 0); - auto t = timeval{.tv_sec = 1, .tv_usec = 0}; + auto t = timeval{.tv_sec = 5, .tv_usec = 0}; setsockopt(SERVERSOCKET, SOL_SOCKET, SO_RCVTIMEO, &t, sizeof(struct timeval)); const auto ARGS = std::count(arg.begin(), arg.end(), ' '); From 4141e6755022edc19cd37cd7ad077a93b3bae5bd Mon Sep 17 00:00:00 2001 From: Tom Englund Date: Fri, 2 Aug 2024 23:16:20 +0200 Subject: [PATCH 0227/2181] xcursor: rework bootleg xcursor (#7140) there were a bunch of missing cursors, rework the shape loading add a function to get legacyname from new wayland names. also bootleg add a cursor if no theme can be found and no shape. to atleast show something. --- src/managers/CursorManager.cpp | 371 ++++++++++++++++++++++++--------- src/managers/CursorManager.hpp | 15 +- 2 files changed, 284 insertions(+), 102 deletions(-) diff --git a/src/managers/CursorManager.cpp b/src/managers/CursorManager.cpp index 3a13d10b..e0d3a62c 100644 --- a/src/managers/CursorManager.cpp +++ b/src/managers/CursorManager.cpp @@ -46,7 +46,7 @@ CCursorManager::CCursorManager() { if (m_iSize == 0) m_iSize = 24; - xcursor.loadTheme(getenv("XCURSOR_THEME") ? getenv("XCURSOR_THEME") : "", m_iSize * std::ceil(m_fCursorScale)); + xcursor.loadTheme(getenv("XCURSOR_THEME") ? getenv("XCURSOR_THEME") : "default", m_iSize * std::ceil(m_fCursorScale)); m_pAnimationTimer = wl_event_loop_add_timer(g_pCompositor->m_sWLEventLoop, ::cursorAnimTimer, nullptr); @@ -135,14 +135,20 @@ void CCursorManager::setXCursor(const std::string& name) { if (!xcursor.themeLoaded) { Debug::log(ERR, "XCursor failed to find theme in setXCursor"); - g_pPointerManager->resetCursorImage(); - return; + if (!xcursor.defaultCursor) { + g_pPointerManager->resetCursorImage(); + return; + } } auto& icon = xcursor.defaultCursor; // try to get an icon we know if we have one - if (xcursor.cursors.contains(name)) - icon = xcursor.cursors.at(name); + for (auto const& c : xcursor.cursors) { + if (c.first != name) + continue; + + icon = c.second; + } m_vCursorBuffers.emplace_back(makeShared((uint8_t*)icon->pixels.data(), icon->size, icon->hotspot)); @@ -305,87 +311,86 @@ bool CCursorManager::changeTheme(const std::string& name, const int size) { } // Taken from https://gitlab.freedesktop.org/xorg/lib/libxcursor/-/blob/master/src/library.c -// however modified to fit wayland cursor shape names better. // _ -> - // clang-format off static std::array XCURSOR_STANDARD_NAMES = { "X_cursor", - "default", // arrow - "ns-resize", // based-arrow-down - "ns-resize", // based-arrow-up + "arrow", + "based_arrow_down", + "based_arrow_up", "boat", "bogosity", - "sw-resize", // bottom-left-corner - "se-resize", // bottom-right-corner - "s-resize", // bottom-side - "bottom-tee", - "box-spiral", - "center-ptr", + "bottom_left_corner", + "bottom_right_corner", + "bottom_side", + "bottom_tee", + "box_spiral", + "center_ptr", "circle", "clock", - "coffee-mug", + "coffee_mug", "cross", - "cross-reverse", + "cross_reverse", "crosshair", - "diamond-cross", + "diamond_cross", "dot", "dotbox", - "double-arrow", - "draft-large", - "draft-small", - "draped-box", + "double_arrow", + "draft_large", + "draft_small", + "draped_box", "exchange", - "move", // fleur + "fleur", "gobbler", "gumby", - "pointer", // hand1 - "grabbing", // hand2 + "hand1", + "hand2", "heart", "icon", - "iron-cross", - "default", // left-ptr - "w-resize", // left-side - "left-tee", + "iron_cross", + "left_ptr", + "left_side", + "left_tee", "leftbutton", - "ll-angle", - "lr-angle", + "ll_angle", + "lr_angle", "man", "middlebutton", "mouse", "pencil", "pirate", "plus", - "help", // question-arrow - "right-ptr", - "e-resize", // right-side - "right-tee", + "question_arrow", + "right_ptr", + "right_side", + "right_tee", "rightbutton", - "rtl-logo", + "rtl_logo", "sailboat", - "ns-resize", // sb-down-arrow - "ew-resize", // sb-h-double-arrow - "ew-resize", // sb-left-arrow - "ew-resize", // sb-right-arrow - "n-resize", // sb-up-arrow - "s-resize", // sb-v-double-arrow + "sb_down_arrow", + "sb_h_double_arrow", + "sb_left_arrow", + "sb_right_arrow", + "sb_up_arrow", + "sb_v_double_arrow", "shuttle", "sizing", "spider", "spraycan", "star", "target", - "cell", // tcross - "nw-resize", // top-left-arrow - "nw-resize", // top-left-corner - "ne-resize", // top-right-corner - "n-resize", // top-side - "top-tee", + "tcross", + "top_left_arrow", + "top_left_corner", + "top_right_corner", + "top_side", + "top_tee", "trek", - "ul-angle", + "ul_angle", "umbrella", - "ur-angle", - "wait", // watch - "text", // xterm + "ur_angle", + "watch", + "xterm", }; // clang-format on @@ -397,51 +402,21 @@ void CCursorManager::SXCursorManager::loadTheme(const std::string& name, int siz themeLoaded = false; themeName = name.empty() ? "default" : name; - auto img = XcursorShapeLoadImage(2, themeName.c_str(), size); + std::vector>> newCursors; - if (!img) { - Debug::log(ERR, "XCursor failed finding theme \"{}\". Trying size 24.", themeName); - size = 24; - img = XcursorShapeLoadImage(2, themeName.c_str(), size); - if (!img) { - Debug::log(ERR, "XCursor failed finding theme \"{}\".", themeName); - return; - } - } - - defaultCursor = makeShared(); - defaultCursor->size = {(int)img->width, (int)img->height}; - defaultCursor->hotspot = {(int)img->xhot, (int)img->yhot}; - - defaultCursor->pixels.resize(img->width * img->height); - std::memcpy(defaultCursor->pixels.data(), img->pixels, img->width * img->height * sizeof(uint32_t)); - - themeLoaded = true; - - XcursorImageDestroy(img); - - // gather as many shapes as we can find. - cursors.clear(); - - for (auto& shape : CURSOR_SHAPE_NAMES) { - int id = -1; - for (size_t i = 0; i < XCURSOR_STANDARD_NAMES.size(); ++i) { - if (XCURSOR_STANDARD_NAMES.at(i) == std::string{shape}) { - id = i; - break; - } - } - - if (id < 0) { - Debug::log(LOG, "XCursor has no shape {}, skipping", shape); - continue; - } - - auto xImage = XcursorShapeLoadImage(id << 1 /* wtf xcursor? */, themeName.c_str(), size); + // load the default xcursor shapes that exist in the theme + for (size_t i = 0; i < XCURSOR_STANDARD_NAMES.size(); ++i) { + auto shape = XCURSOR_STANDARD_NAMES.at(i); + auto xImage = XcursorShapeLoadImage(i << 1 /* wtf xcursor? */, themeName.c_str(), size); if (!xImage) { - Debug::log(LOG, "XCursor failed to find a shape with name {}, skipping", shape); - continue; + Debug::log(LOG, "XCursor failed to find a shape with name {}, trying size 24.", shape); + xImage = XcursorShapeLoadImage(i << 1 /* wtf xcursor? */, themeName.c_str(), 24); + + if (!xImage) { + Debug::log(LOG, "XCursor failed to find a shape with name {}, skipping", shape); + continue; + } } auto xcursor = makeShared(); @@ -451,8 +426,214 @@ void CCursorManager::SXCursorManager::loadTheme(const std::string& name, int siz xcursor->pixels.resize(xImage->width * xImage->height); std::memcpy(xcursor->pixels.data(), xImage->pixels, xImage->width * xImage->height * sizeof(uint32_t)); - cursors.emplace(std::string{shape}, xcursor); + newCursors.emplace_back(std::string{shape}, xcursor); XcursorImageDestroy(xImage); } + + if (newCursors.empty()) { + Debug::log(ERR, "XCursor failed finding any shapes in theme \"{}\".", themeName); + if (!defaultCursor) { + defaultCursor = createDefaultCursor(); + } + return; + } + + cursors.clear(); + cursors = std::move(newCursors); + defaultCursor.reset(); + themeLoaded = true; + + for (auto const& shape : CURSOR_SHAPE_NAMES) { + auto legacyName = getLegacyShapeName(shape); + if (legacyName.empty()) + continue; + + auto it = std::find_if(cursors.begin(), cursors.end(), [&legacyName](auto const& c) { return c.first == legacyName; }); + + if (it == cursors.end()) { + Debug::log(LOG, "XCursor failed to find a legacy shape with name {}, skipping", legacyName); + continue; + } + + cursors.emplace_back(shape, it->second); + } + + // set default cursor + for (auto const& c : cursors) { + if (c.first == "left_ptr" || c.first == "arrow") { + defaultCursor = c.second; + break; + } + } + + // just assign the first one then. + if (!defaultCursor) + defaultCursor = cursors.at(0).second; +} + +std::string CCursorManager::SXCursorManager::getLegacyShapeName(std::string const& shape) { + if (shape == "invalid") + return std::string(); + else if (shape == "default") + return "left_ptr"; + else if (shape == "context-menu") + return "left_ptr"; + else if (shape == "help") + return "left_ptr"; + else if (shape == "pointer") + return "hand2"; + else if (shape == "progress") + return "watch"; + else if (shape == "wait") + return "watch"; + else if (shape == "cell") + return "plus"; + else if (shape == "crosshair") + return "cross"; + else if (shape == "text") + return "xterm"; + else if (shape == "vertical-text") + return "xterm"; + else if (shape == "alias") + return "dnd-link"; + else if (shape == "copy") + return "dnd-copy"; + else if (shape == "move") + return "dnd-move"; + else if (shape == "no-drop") + return "dnd-none"; + else if (shape == "not-allowed") + return "crossed_circle"; + else if (shape == "grab") + return "hand1"; + else if (shape == "grabbing") + return "hand1"; + else if (shape == "e-resize") + return "right_side"; + else if (shape == "n-resize") + return "top_side"; + else if (shape == "ne-resize") + return "top_right_corner"; + else if (shape == "nw-resize") + return "top_left_corner"; + else if (shape == "s-resize") + return "bottom_side"; + else if (shape == "se-resize") + return "bottom_right_corner"; + else if (shape == "sw-resize") + return "bottom_left_corner"; + else if (shape == "w-resize") + return "left_side"; + else if (shape == "ew-resize") + return "sb_h_double_arrow"; + else if (shape == "ns-resize") + return "sb_v_double_arrow"; + else if (shape == "nesw-resize") + return "fd_double_arrow"; + else if (shape == "nwse-resize") + return "bd_double_arrow"; + else if (shape == "col-resize") + return "sb_h_double_arrow"; + else if (shape == "row-resize") + return "sb_v_double_arrow"; + else if (shape == "all-scroll") + return "fleur"; + else if (shape == "zoom-in") + return "left_ptr"; + else if (shape == "zoom-out") + return "left_ptr"; + + return std::string(); +} + +SP CCursorManager::SXCursorManager::createDefaultCursor() { + int cursorWidth = 32; + int cursorHeight = 32; + int cursorHotspotX = 3; + int cursorHotspotY = 2; + + static const uint32_t pixels[] = { + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x1b001816, 0x01000101, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x8e008173, 0x5f00564d, 0x16001412, 0x09000807, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x2b002624, 0x05000404, 0x00000000, 0x35002f2b, 0xd400bead, + 0xc300b09e, 0x90008275, 0x44003e37, 0x04000403, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x67005a56, + 0x6f00615c, 0x00000000, 0x00000000, 0x8b007c72, 0xf200d7c6, 0xfa00e0cc, 0xe800d0bd, 0xa0009181, 0x44003e37, 0x1a001815, 0x06000505, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x8d007976, 0xd600b8b3, 0x2500201f, 0x00000000, 0x17001413, 0xbd00a79c, 0xf600dacb, 0xff00e3d1, 0xfc00e1ce, 0xe800d0bc, 0xbf00ac9b, + 0x95008778, 0x51004a41, 0x0f000e0c, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x92007b7b, 0xf500d0cf, 0x9e008685, 0x00000000, 0x00000000, 0x23001f1d, 0x64005853, + 0x9b008980, 0xd900bfb3, 0xfb00dfce, 0xff00e4d0, 0xfb00e1cd, 0xec00d5c0, 0xa7009788, 0x47004139, 0x1e001b18, 0x05000504, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0xa200878a, 0xff00d6d9, 0xd600b4b5, + 0x0e000c0c, 0x00000000, 0x00000000, 0x02000202, 0x0c000b0a, 0x30002a28, 0x8e007d75, 0xd600bdb0, 0xef00d4c4, 0xfb00e0ce, 0xff00e4d0, 0xe600cfbb, 0xb800a695, 0x5f00564d, + 0x06000505, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x02000202, 0xc600a3aa, 0xff00d3da, 0xea00c3c8, 0x08000707, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x01000101, 0x2a002523, 0x61005550, 0x9500837b, + 0xd800bfb1, 0xfd00e1cf, 0xff00e5d0, 0xf500dcc7, 0x7c007065, 0x2a002622, 0x01000101, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x06000505, 0xd600aeb9, 0xff00d0dc, 0xcc00a7af, 0x04000303, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x01000101, 0x01000101, 0x2c002724, 0xa1008e85, 0xe600ccbd, 0xf800ddcb, 0xef00d6c3, 0xc300af9f, 0x2c002824, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x09000708, 0xd800adbc, 0xff00cdde, 0xb90095a0, 0x02000202, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x10000e0d, 0x4b00423e, 0xa4009088, 0xfd00dfd0, 0xff00e3d1, + 0xae009c8f, 0x42003b36, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x14001012, 0xf400c0d6, + 0xff00cadf, 0xb2008e9c, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x02000202, 0x1200100f, 0xa2008e86, 0xec00cfc3, 0xfc00ded0, 0xc300ada0, 0x15001311, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x2e002429, 0xfd00c4e0, 0xff00c7e2, 0x8f00707e, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x1e001a19, 0x75006662, 0xfb00dbd1, 0xf700d9cc, 0x9600847c, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x3e002f37, 0xfc00c1e1, 0xff00c5e3, 0x60004b55, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x15001212, 0xa6008f8b, 0xff00ddd5, + 0xf800d8ce, 0x36002f2d, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x51003d49, 0xfe00bfe5, 0xfe00c1e4, 0x4c003a44, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x01000101, 0x1d001918, 0xf400d1cd, 0xfe00dad5, 0xb3009a96, 0x03000303, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x66004b5d, 0xff00bee7, 0xfd00bee5, 0x4500343f, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x02000202, 0x82006e6e, 0xff00d8d7, 0xd800b9b6, 0x33002c2b, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x70005267, 0xff00bbe9, 0xfa00b8e3, 0x29001e25, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x3f003536, 0xea00c3c7, 0xf800d1d3, + 0x4a003e3f, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x5f004458, 0xff00b8eb, 0xf400b1e0, 0x29001e26, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x1b001617, 0xe100bac0, 0xff00d4da, 0x82006c6f, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x5a004054, 0xfe00b4eb, + 0xfb00b3e8, 0x3b002a36, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x0a000809, 0xc900a4ad, 0xff00d1dc, 0x88007075, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x44002f3f, 0xf300aae3, 0xfc00b1ea, 0x48003343, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x05000404, 0xdf00b3c2, 0xff00cedd, 0x8f00747c, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x25001a23, 0xf200a6e4, 0xff00b1ef, 0x84005c7c, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x09000708, + 0xe400b5c8, 0xff00cbdf, 0x78006068, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x12000c11, 0xc00082b6, 0xff00aef1, 0xaa0075a0, + 0x11000c10, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x1e00171b, 0xf700c1db, 0xff00c8e1, 0x4b003b42, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x05000305, 0x8d005f86, 0xfc00aaef, 0xed00a0e1, 0x26001a24, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x6f005463, 0xff00c4e3, 0xf500beda, 0x0c00090b, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x3e00293b, 0xed009de2, 0xff00aaf3, 0x8b005d84, 0x04000304, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x07000506, 0xeb00b1d4, 0xff00c1e6, 0xba008ea7, + 0x02000202, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0xb20075ab, 0xff00a7f4, 0xf300a1e9, 0x35002333, + 0x06000406, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x8900647d, 0xff00bde8, 0xfb00bce2, 0x26001d22, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x2b001c29, 0xf1009ce8, 0xfe00a5f4, 0xc60082be, 0x3b002738, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x01000101, 0x54003c4d, 0xfd00b8e8, 0xff00baea, 0x96006f89, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x78004d74, 0xe20091da, 0xff00a5f6, 0xb60077af, 0x42002b3f, 0x0c00080c, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x9400688a, 0xff00b5ed, 0xff00b6ec, 0xcc0093bc, 0x02000102, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x04000304, 0x8100527d, 0xeb0096e4, 0xf900a0f1, 0xdc008dd4, + 0x9b006595, 0x32002130, 0x0a00070a, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x2100161f, 0x5300394e, 0xe2009cd4, 0xff00b1ef, 0xff00b2ee, 0xc8008cba, 0x17001015, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x19001018, 0x5e003b5b, 0xcb0081c5, 0xff00a2f8, 0xfc00a1f4, 0xde0090d6, 0xa9006da3, 0x8300567e, 0x6f00496a, 0x76004e71, 0xbb007db2, 0xeb009edf, 0xfb00a9ee, 0xff00adf1, + 0xfd00adee, 0x9e006d95, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x04000304, 0x34002133, 0xa60069a1, 0xd70089d1, 0xf2009bea, 0xff00a3f7, 0xfb00a1f2, 0xfb00a2f2, 0xff00a6f5, + 0xff00a8f4, 0xfd00a7f2, 0xed009ee2, 0xcf008bc5, 0x14000e13, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x11000b11, 0x35002134, 0x5b003959, + 0x8b005887, 0xb30072ae, 0xc90080c3, 0xd10086ca, 0xa6006ba0, 0x65004261, 0x3c002839, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x01000101, 0x06000406, 0x0d00080d, 0x0f000a0f, 0x0a00060a, 0x01000101, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000}; + + auto hackcursor = makeShared(); + hackcursor->size = {cursorWidth, cursorHeight}; + hackcursor->hotspot = {cursorHotspotX, cursorHotspotY}; + hackcursor->pixels.resize(cursorWidth * cursorHeight); + std::memcpy(hackcursor->pixels.data(), pixels, cursorWidth * cursorHeight * sizeof(uint32_t)); + + return hackcursor; } diff --git a/src/managers/CursorManager.hpp b/src/managers/CursorManager.hpp index 4324dfb4..44ab2e7b 100644 --- a/src/managers/CursorManager.hpp +++ b/src/managers/CursorManager.hpp @@ -83,14 +83,15 @@ class CCursorManager { }; struct SXCursorManager { - void loadTheme(const std::string& name, int size); + void loadTheme(const std::string& name, int size); + std::string getLegacyShapeName(std::string const& shape); + SP createDefaultCursor(); - int lastLoadSize = 0; - - bool themeLoaded = false; - std::string themeName = ""; - SP defaultCursor; - std::unordered_map> cursors; + int lastLoadSize = 0; + bool themeLoaded = false; + std::string themeName = ""; + SP defaultCursor; + std::vector>> cursors; } xcursor; }; From 9f5a57ff4569db57372bd86bd48add85a3a1a5e4 Mon Sep 17 00:00:00 2001 From: Jan Beich Date: Sat, 3 Aug 2024 12:02:10 +0000 Subject: [PATCH 0228/2181] core: Add missing header for libc++ after e989a0bcffac (#7158) src/Compositor.cpp:2295:74: error: no member named 'bit_floor' in namespace 'std' 2295 | const eFullscreenMode CURRENT_EFFECTIVE_MODE = (eFullscreenMode)std::bit_floor((uint8_t)PWINDOW->m_sFullscreenState.internal); | ~~~~~^ src/Compositor.cpp:2296:74: error: no member named 'bit_floor' in namespace 'std' 2296 | const eFullscreenMode EFFECTIVE_MODE = (eFullscreenMode)std::bit_floor((uint8_t)state.internal); | ~~~~~^ src/desktop/Window.cpp:1242:34: error: no member named 'bit_floor' in namespace 'std' 1242 | return (eFullscreenMode)std::bit_floor((uint8_t)m_sFullscreenState.internal) == MODE; | ~~~~~^ --- src/Compositor.cpp | 1 + src/desktop/Window.cpp | 1 + 2 files changed, 2 insertions(+) diff --git a/src/Compositor.cpp b/src/Compositor.cpp index 2a1e4f8c..a139742c 100644 --- a/src/Compositor.cpp +++ b/src/Compositor.cpp @@ -7,6 +7,7 @@ #include "managers/SeatManager.hpp" #include "managers/eventLoop/EventLoopManager.hpp" #include +#include #include #include #include diff --git a/src/desktop/Window.cpp b/src/desktop/Window.cpp index 27010454..93c208cf 100644 --- a/src/desktop/Window.cpp +++ b/src/desktop/Window.cpp @@ -1,4 +1,5 @@ #include +#include #include #include #include "Window.hpp" From ae50f8614d92132d918663ea7551bd68eb13953a Mon Sep 17 00:00:00 2001 From: Vaxry Date: Sat, 3 Aug 2024 17:58:06 +0200 Subject: [PATCH 0229/2181] wayland/surface: fixup self-owning surface roles fixes #7133 --- src/protocols/LayerShell.cpp | 10 +++++----- src/protocols/LayerShell.hpp | 20 +++++++++++++++----- src/protocols/XDGShell.cpp | 10 +++++----- src/protocols/XDGShell.hpp | 15 ++++++++++++--- src/protocols/core/Compositor.cpp | 6 +++--- src/protocols/core/Subcompositor.cpp | 16 ++++++++-------- src/protocols/core/Subcompositor.hpp | 15 +++++++++++++-- 7 files changed, 61 insertions(+), 31 deletions(-) diff --git a/src/protocols/LayerShell.cpp b/src/protocols/LayerShell.cpp index 295ef4a9..17d3b22a 100644 --- a/src/protocols/LayerShell.cpp +++ b/src/protocols/LayerShell.cpp @@ -175,10 +175,6 @@ CLayerShellResource::~CLayerShellResource() { surface->resetRole(); } -eSurfaceRole CLayerShellResource::role() { - return SURFACE_ROLE_LAYER_SHELL; -} - bool CLayerShellResource::good() { return resource->resource(); } @@ -245,8 +241,12 @@ void CLayerShellProtocol::onGetLayerSurface(CZwlrLayerShellV1* pMgr, uint32_t id return; } - SURF->role = RESOURCE; + SURF->role = makeShared(RESOURCE); g_pCompositor->m_vLayers.emplace_back(CLayerSurface::create(RESOURCE)); LOGM(LOG, "New wlr_layer_surface {:x}", (uintptr_t)RESOURCE.get()); } + +CLayerShellRole::CLayerShellRole(SP ls) : layerSurface(ls) { + ; +} diff --git a/src/protocols/LayerShell.hpp b/src/protocols/LayerShell.hpp index ee0b7859..801bdfd6 100644 --- a/src/protocols/LayerShell.hpp +++ b/src/protocols/LayerShell.hpp @@ -12,16 +12,26 @@ class CMonitor; class CWLSurfaceResource; +class CLayerShellResource; -class CLayerShellResource : public ISurfaceRole { +class CLayerShellRole : public ISurfaceRole { + public: + CLayerShellRole(SP ls); + + virtual eSurfaceRole role() { + return SURFACE_ROLE_LAYER_SHELL; + } + + WP layerSurface; +}; +class CLayerShellResource { public: CLayerShellResource(SP resource_, SP surf_, std::string namespace_, CMonitor* pMonitor, zwlrLayerShellV1Layer layer); ~CLayerShellResource(); - bool good(); - void configure(const Vector2D& size); - void sendClosed(); - virtual eSurfaceRole role(); + bool good(); + void configure(const Vector2D& size); + void sendClosed(); enum eCommittedState { STATE_SIZE = (1 << 0), diff --git a/src/protocols/XDGShell.cpp b/src/protocols/XDGShell.cpp index 5e82b530..4aa5d373 100644 --- a/src/protocols/XDGShell.cpp +++ b/src/protocols/XDGShell.cpp @@ -443,10 +443,6 @@ CXDGSurfaceResource::~CXDGSurfaceResource() { surface->resetRole(); } -eSurfaceRole CXDGSurfaceResource::role() { - return SURFACE_ROLE_XDG_SHELL; -} - bool CXDGSurfaceResource::good() { return resource->resource(); } @@ -668,7 +664,7 @@ CXDGWMBase::CXDGWMBase(SP resource_) : resource(resource_) { RESOURCE->self = RESOURCE; RESOURCE->surface = SURF; - SURF->role = RESOURCE; + SURF->role = makeShared(RESOURCE); surfaces.emplace_back(RESOURCE); @@ -765,3 +761,7 @@ void CXDGShellProtocol::onPopupDestroy(WP popup) { if (popup->surface) grab->remove(popup->surface->surface.lock()); } + +CXDGSurfaceRole::CXDGSurfaceRole(SP xdg) : xdgSurface(xdg) { + ; +} diff --git a/src/protocols/XDGShell.hpp b/src/protocols/XDGShell.hpp index e6812c38..81d10613 100644 --- a/src/protocols/XDGShell.hpp +++ b/src/protocols/XDGShell.hpp @@ -141,15 +141,24 @@ class CXDGToplevelResource { void applyState(); }; -class CXDGSurfaceResource : public ISurfaceRole { +class CXDGSurfaceRole : public ISurfaceRole { + public: + CXDGSurfaceRole(SP xdg); + + virtual eSurfaceRole role() { + return SURFACE_ROLE_XDG_SHELL; + } + + WP xdgSurface; +}; + +class CXDGSurfaceResource { public: CXDGSurfaceResource(SP resource_, SP owner_, SP surface_); ~CXDGSurfaceResource(); static SP fromResource(wl_resource*); - virtual eSurfaceRole role(); - bool good(); WP owner; diff --git a/src/protocols/core/Compositor.cpp b/src/protocols/core/Compositor.cpp index bff52133..4a6fa40f 100644 --- a/src/protocols/core/Compositor.cpp +++ b/src/protocols/core/Compositor.cpp @@ -277,7 +277,7 @@ void CWLSurfaceResource::bfHelper(std::vector> nodes, std for (auto& n : nodes) { Vector2D offset = {}; if (n->role->role() == SURFACE_ROLE_SUBSURFACE) { - auto subsurface = (CWLSubsurfaceResource*)n->role.get(); + auto subsurface = ((CSubsurfaceRole*)n->role.get())->subsurface.lock(); offset = subsurface->posRelativeToParent(); } @@ -448,7 +448,7 @@ void CWLSurfaceResource::commitPendingState() { // TODO: we should _accumulate_ and not replace above if sync if (role->role() == SURFACE_ROLE_SUBSURFACE) { - auto subsurface = (CWLSubsurfaceResource*)role.get(); + auto subsurface = ((CSubsurfaceRole*)role.get())->subsurface.lock(); if (subsurface->sync) return; @@ -458,7 +458,7 @@ void CWLSurfaceResource::commitPendingState() { breadthfirst( [](SP surf, const Vector2D& offset, void* data) { if (surf->role->role() == SURFACE_ROLE_SUBSURFACE) { - auto subsurface = (CWLSubsurfaceResource*)surf->role.get(); + auto subsurface = ((CSubsurfaceRole*)surf->role.get())->subsurface.lock(); if (!subsurface->sync) return; } diff --git a/src/protocols/core/Subcompositor.cpp b/src/protocols/core/Subcompositor.cpp index 90f89d91..2a7c06dc 100644 --- a/src/protocols/core/Subcompositor.cpp +++ b/src/protocols/core/Subcompositor.cpp @@ -119,7 +119,7 @@ Vector2D CWLSubsurfaceResource::posRelativeToParent() { while (surf->role->role() == SURFACE_ROLE_SUBSURFACE && std::find_if(surfacesVisited.begin(), surfacesVisited.end(), [surf](const auto& other) { return surf == other; }) == surfacesVisited.end()) { surfacesVisited.emplace_back(surf); - auto subsurface = (CWLSubsurfaceResource*)parent->role.get(); + auto subsurface = ((CSubsurfaceRole*)parent->role.get())->subsurface.lock(); pos += subsurface->position; surf = subsurface->parent.lock(); } @@ -130,10 +130,6 @@ bool CWLSubsurfaceResource::good() { return resource->resource(); } -eSurfaceRole CWLSubsurfaceResource::role() { - return SURFACE_ROLE_SUBSURFACE; -} - SP CWLSubsurfaceResource::t1Parent() { SP surf = parent.lock(); std::vector> surfacesVisited; @@ -141,7 +137,7 @@ SP CWLSubsurfaceResource::t1Parent() { while (surf->role->role() == SURFACE_ROLE_SUBSURFACE && std::find_if(surfacesVisited.begin(), surfacesVisited.end(), [surf](const auto& other) { return surf == other; }) == surfacesVisited.end()) { surfacesVisited.emplace_back(surf); - auto subsurface = (CWLSubsurfaceResource*)parent->role.get(); + auto subsurface = ((CSubsurfaceRole*)parent->role.get())->subsurface.lock(); surf = subsurface->parent.lock(); } return surf; @@ -171,7 +167,7 @@ CWLSubcompositorResource::CWLSubcompositorResource(SP resource SP t1Parent = nullptr; if (PARENT->role->role() == SURFACE_ROLE_SUBSURFACE) { - auto subsurface = (CWLSubsurfaceResource*)PARENT->role.get(); + auto subsurface = ((CSubsurfaceRole*)PARENT->role.get())->subsurface.lock(); t1Parent = subsurface->t1Parent(); } else t1Parent = PARENT; @@ -191,7 +187,7 @@ CWLSubcompositorResource::CWLSubcompositorResource(SP resource } RESOURCE->self = RESOURCE; - SURF->role = RESOURCE; + SURF->role = makeShared(RESOURCE); PARENT->subsurfaces.emplace_back(RESOURCE); LOGM(LOG, "New wl_subsurface with id {} at {:x}", id, (uintptr_t)RESOURCE.get()); @@ -225,3 +221,7 @@ void CWLSubcompositorProtocol::destroyResource(CWLSubcompositorResource* resourc void CWLSubcompositorProtocol::destroyResource(CWLSubsurfaceResource* resource) { std::erase_if(m_vSurfaces, [&](const auto& other) { return other.get() == resource; }); } + +CSubsurfaceRole::CSubsurfaceRole(SP sub) : subsurface(sub) { + ; +} diff --git a/src/protocols/core/Subcompositor.hpp b/src/protocols/core/Subcompositor.hpp index 824f0ffc..2e6b10bb 100644 --- a/src/protocols/core/Subcompositor.hpp +++ b/src/protocols/core/Subcompositor.hpp @@ -16,15 +16,26 @@ #include "../types/SurfaceRole.hpp" class CWLSurfaceResource; +class CWLSubsurfaceResource; -class CWLSubsurfaceResource : public ISurfaceRole { +class CSubsurfaceRole : public ISurfaceRole { + public: + CSubsurfaceRole(SP sub); + + virtual eSurfaceRole role() { + return SURFACE_ROLE_SUBSURFACE; + } + + WP subsurface; +}; + +class CWLSubsurfaceResource { public: CWLSubsurfaceResource(SP resource_, SP surface_, SP parent_); ~CWLSubsurfaceResource(); Vector2D posRelativeToParent(); bool good(); - virtual eSurfaceRole role(); SP t1Parent(); bool sync = false; From 51ffd7fa6f186419276e5d3d5fe141a3fdb3c55c Mon Sep 17 00:00:00 2001 From: MightyPlaza <123664421+MightyPlaza@users.noreply.github.com> Date: Sat, 3 Aug 2024 17:50:08 +0000 Subject: [PATCH 0230/2181] decorations: fix infinite recursion on no_gaps when only (#7169) modified: src/layout/DwindleLayout.cpp modified: src/layout/MasterLayout.cpp modified: src/render/decorations/CHyprBorderDecoration.cpp --- src/layout/DwindleLayout.cpp | 5 ++--- src/layout/MasterLayout.cpp | 5 ++--- src/render/decorations/CHyprBorderDecoration.cpp | 2 +- 3 files changed, 5 insertions(+), 7 deletions(-) diff --git a/src/layout/DwindleLayout.cpp b/src/layout/DwindleLayout.cpp index 7253275d..f287056f 100644 --- a/src/layout/DwindleLayout.cpp +++ b/src/layout/DwindleLayout.cpp @@ -141,7 +141,6 @@ void CHyprDwindleLayout::applyNodeDataToWindow(SDwindleNodeData* pNode, bool for PWINDOW->unsetWindowData(PRIORITY_LAYOUT); PWINDOW->updateWindowData(); - PWINDOW->updateWindowDecos(); static auto PNOGAPSWHENONLY = CConfigValue("dwindle:no_gaps_when_only"); static auto PGAPSINDATA = CConfigValue("general:gaps_in"); @@ -178,6 +177,8 @@ void CHyprDwindleLayout::applyNodeDataToWindow(SDwindleNodeData* pNode, bool for return; } + PWINDOW->updateWindowDecos(); + auto calcPos = PWINDOW->m_vPosition; auto calcSize = PWINDOW->m_vSize; @@ -245,8 +246,6 @@ void CHyprDwindleLayout::applyNodeDataToWindow(SDwindleNodeData* pNode, bool for g_pHyprRenderer->damageWindow(PWINDOW); } - - PWINDOW->updateWindowDecos(); } void CHyprDwindleLayout::onWindowCreatedTiling(PHLWINDOW pWindow, eDirection direction) { diff --git a/src/layout/MasterLayout.cpp b/src/layout/MasterLayout.cpp index e3aaa767..be00168f 100644 --- a/src/layout/MasterLayout.cpp +++ b/src/layout/MasterLayout.cpp @@ -650,7 +650,6 @@ void CHyprMasterLayout::applyNodeDataToWindow(SMasterNodeData* pNode) { PWINDOW->unsetWindowData(PRIORITY_LAYOUT); PWINDOW->updateWindowData(); - PWINDOW->updateWindowDecos(); static auto PNOGAPSWHENONLY = CConfigValue("master:no_gaps_when_only"); static auto PANIMATE = CConfigValue("misc:animate_manual_resizes"); @@ -689,6 +688,8 @@ void CHyprMasterLayout::applyNodeDataToWindow(SMasterNodeData* pNode) { return; } + PWINDOW->updateWindowDecos(); + auto calcPos = PWINDOW->m_vPosition; auto calcSize = PWINDOW->m_vSize; @@ -731,8 +732,6 @@ void CHyprMasterLayout::applyNodeDataToWindow(SMasterNodeData* pNode) { g_pHyprRenderer->damageWindow(PWINDOW); } - - PWINDOW->updateWindowDecos(); } bool CHyprMasterLayout::isWindowTiled(PHLWINDOW pWindow) { diff --git a/src/render/decorations/CHyprBorderDecoration.cpp b/src/render/decorations/CHyprBorderDecoration.cpp index ddb38c6e..f5e6e945 100644 --- a/src/render/decorations/CHyprBorderDecoration.cpp +++ b/src/render/decorations/CHyprBorderDecoration.cpp @@ -93,7 +93,7 @@ void CHyprBorderDecoration::updateWindow(PHLWINDOW) { m_iLastBorderSize = borderSize; - g_pEventLoopManager->doLater([this]() { g_pDecorationPositioner->repositionDeco(this); }); + g_pDecorationPositioner->repositionDeco(this); } void CHyprBorderDecoration::damageEntire() { From 4ae89e1f227d8b19afe8c692033ab894e053c7ec Mon Sep 17 00:00:00 2001 From: MaroonSkull <33577562+MaroonSkull@users.noreply.github.com> Date: Sat, 3 Aug 2024 14:10:48 +0300 Subject: [PATCH 0231/2181] CMake: Suppress CMake warning about GNUInstallDirs --- CMakeLists.txt | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 3616da24..e284cb68 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,8 +1,5 @@ cmake_minimum_required(VERSION 3.27) -include(CheckIncludeFile) -include(GNUInstallDirs) - # Get version file(READ "${CMAKE_SOURCE_DIR}/VERSION" VER_RAW) string(STRIP ${VER_RAW} VER) @@ -12,6 +9,9 @@ project( DESCRIPTION "A Modern C++ Wayland Compositor" VERSION ${VER}) +include(CheckIncludeFile) +include(GNUInstallDirs) + set(HYPRLAND_VERSION ${VER}) set(PREFIX ${CMAKE_INSTALL_PREFIX}) set(INCLUDEDIR ${CMAKE_INSTALL_INCLUDEDIR}) From 5dd2c27b631f16e49a2c6e6cbbefba9fa50bf543 Mon Sep 17 00:00:00 2001 From: Mihai Fufezan Date: Sun, 4 Aug 2024 15:19:37 +0300 Subject: [PATCH 0232/2181] CMake, Meson: install config and wallpapers to DATADIR/hypr OpenGL: get wallpapers dir from DATAROOTDIR --- CMakeLists.txt | 17 +++++++++++------ assets/meson.build | 2 +- example/meson.build | 2 +- meson.build | 2 ++ src/render/OpenGL.cpp | 8 +++++--- 5 files changed, 20 insertions(+), 11 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index e284cb68..fa58b63d 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -262,9 +262,11 @@ endfunction() target_link_libraries(Hyprland OpenGL::EGL OpenGL::GL Threads::Threads libudis86 uuid) -protocolnew("subprojects/hyprland-protocols/protocols" "hyprland-global-shortcuts-v1" true) +protocolnew("subprojects/hyprland-protocols/protocols" + "hyprland-global-shortcuts-v1" true) protocolnew("unstable/text-input" "text-input-unstable-v1" false) -protocolnew("subprojects/hyprland-protocols/protocols" "hyprland-toplevel-export-v1" true) +protocolnew("subprojects/hyprland-protocols/protocols" + "hyprland-toplevel-export-v1" true) protocolnew("protocols" "wlr-screencopy-unstable-v1" true) protocolnew("protocols" "wlr-gamma-control-unstable-v1" true) protocolnew("protocols" "wlr-foreign-toplevel-management-unstable-v1" true) @@ -326,19 +328,22 @@ install( # session file install(FILES ${CMAKE_SOURCE_DIR}/example/hyprland.desktop - DESTINATION ${CMAKE_INSTALL_DATADIR}/wayland-sessions) + DESTINATION ${CMAKE_INSTALL_DATAROOTDIR}/wayland-sessions) + +# allow Hyprland to find wallpapers +add_compile_definitions(DATAROOTDIR="${CMAKE_INSTALL_FULL_DATAROOTDIR}") # wallpapers file(GLOB_RECURSE WALLPAPERS "assets/wall*") -install(FILES ${WALLPAPERS} DESTINATION ${CMAKE_INSTALL_DATADIR}/hyprland) +install(FILES ${WALLPAPERS} DESTINATION ${CMAKE_INSTALL_DATAROOTDIR}/hypr) # default config install(FILES ${CMAKE_SOURCE_DIR}/example/hyprland.conf - DESTINATION ${CMAKE_INSTALL_DATADIR}/hyprland) + DESTINATION ${CMAKE_INSTALL_DATAROOTDIR}/hypr) # portal config install(FILES ${CMAKE_SOURCE_DIR}/assets/hyprland-portals.conf - DESTINATION ${CMAKE_INSTALL_DATADIR}/xdg-desktop-portal) + DESTINATION ${CMAKE_INSTALL_DATAROOTDIR}/xdg-desktop-portal) # man pages file(GLOB_RECURSE MANPAGES "docs/*.1") diff --git a/assets/meson.build b/assets/meson.build index 8c4a60ec..47de3d02 100644 --- a/assets/meson.build +++ b/assets/meson.build @@ -1,7 +1,7 @@ wallpapers = ['0', '1', '2'] foreach type : wallpapers - install_data(f'wall@type@.png', install_dir: join_paths(get_option('datadir'), 'hyprland'), install_tag: 'runtime') + install_data(f'wall@type@.png', install_dir: join_paths(get_option('datadir'), 'hypr'), install_tag: 'runtime') endforeach install_data('hyprland-portals.conf', install_dir: join_paths(get_option('datadir'), 'xdg-desktop-portal'), install_tag: 'runtime') diff --git a/example/meson.build b/example/meson.build index ccfc4e00..2fb3a35e 100644 --- a/example/meson.build +++ b/example/meson.build @@ -1,2 +1,2 @@ -install_data('hyprland.conf', install_dir: join_paths(get_option('datadir'), 'hyprland'), install_tag: 'runtime') +install_data('hyprland.conf', install_dir: join_paths(get_option('datadir'), 'hypr'), install_tag: 'runtime') install_data('hyprland.desktop', install_dir: join_paths(get_option('datadir'), 'wayland-sessions'), install_tag: 'runtime') diff --git a/meson.build b/meson.build index 4446ea0f..886f4f9c 100644 --- a/meson.build +++ b/meson.build @@ -9,6 +9,7 @@ project('Hyprland', 'cpp', 'c', 'cpp_std=c++23', ]) +datarootdir = '-DDATAROOTDIR="' + get_option('prefix') / get_option('datadir') + '"' add_project_arguments( [ '-Wno-unused-parameter', @@ -16,6 +17,7 @@ add_project_arguments( '-Wno-missing-field-initializers', '-Wno-narrowing', '-Wno-pointer-arith', + datarootdir, ], language: 'cpp') diff --git a/src/render/OpenGL.cpp b/src/render/OpenGL.cpp index b925fcc9..ea388df0 100644 --- a/src/render/OpenGL.cpp +++ b/src/render/OpenGL.cpp @@ -2669,10 +2669,12 @@ void CHyprOpenGLImpl::createBGTextureForMonitor(CMonitor* pMonitor) { PFB->alloc(pMonitor->vecPixelSize.x, pMonitor->vecPixelSize.y, pMonitor->output->state->state().drmFormat); if (!m_pBackgroundTexture) { - // TODO: use relative paths to the installation - // or configure the paths at build time std::string texPath = ""; - texPath = "/usr/share/hyprland/wall"; +#ifndef DATAROOTDIR + texPath = "/usr/share/hypr/wall"; +#else + texPath = std::format("{}{}", DATAROOTDIR, "/hypr/wall"); +#endif // get the adequate tex if (FORCEWALLPAPER == -1) { From 2b520571e897be2a0e88c8692da607b062000038 Mon Sep 17 00:00:00 2001 From: MightyPlaza <123664421+MightyPlaza@users.noreply.github.com> Date: Sun, 4 Aug 2024 19:40:34 +0000 Subject: [PATCH 0233/2181] keybinds: improve fullscreenstate toggling (#7174) modified: src/managers/KeybindManager.cpp --- src/managers/KeybindManager.cpp | 24 +++++++++++++++++++----- 1 file changed, 19 insertions(+), 5 deletions(-) diff --git a/src/managers/KeybindManager.cpp b/src/managers/KeybindManager.cpp index 9984fe40..09ba7d50 100644 --- a/src/managers/KeybindManager.cpp +++ b/src/managers/KeybindManager.cpp @@ -1164,8 +1164,6 @@ void CKeybindManager::fullscreenStateActive(std::string args) { if (!PWINDOW) return; - PWINDOW->m_sWindowData.syncFullscreen = CWindowOverridableVar(false, PRIORITY_SET_PROP); - int internalMode, clientMode; try { internalMode = std::stoi(ARGS[0]); @@ -1177,10 +1175,26 @@ void CKeybindManager::fullscreenStateActive(std::string args) { const sFullscreenState STATE = sFullscreenState{.internal = (internalMode != -1 ? (eFullscreenMode)internalMode : PWINDOW->m_sFullscreenState.internal), .client = (clientMode != -1 ? (eFullscreenMode)clientMode : PWINDOW->m_sFullscreenState.client)}; - if (PWINDOW->m_sFullscreenState.internal == STATE.internal && PWINDOW->m_sFullscreenState.client == STATE.client) + if (internalMode != -1 && clientMode != -1 && PWINDOW->m_sFullscreenState.internal == STATE.internal && PWINDOW->m_sFullscreenState.client == STATE.client) { g_pCompositor->setWindowFullscreenState(PWINDOW, sFullscreenState{.internal = FSMODE_NONE, .client = FSMODE_NONE}); - else - g_pCompositor->setWindowFullscreenState(PWINDOW, STATE); + PWINDOW->m_sWindowData.syncFullscreen = CWindowOverridableVar(true, PRIORITY_SET_PROP); + return; + } + + if (internalMode != -1 && clientMode == -1 && PWINDOW->m_sFullscreenState.internal == STATE.internal) { + g_pCompositor->setWindowFullscreenState(PWINDOW, sFullscreenState{.internal = PWINDOW->m_sFullscreenState.client, .client = PWINDOW->m_sFullscreenState.client}); + PWINDOW->m_sWindowData.syncFullscreen = CWindowOverridableVar(true, PRIORITY_SET_PROP); + return; + } + + if (internalMode == -1 && clientMode != -1 && PWINDOW->m_sFullscreenState.client == STATE.client) { + g_pCompositor->setWindowFullscreenState(PWINDOW, sFullscreenState{.internal = PWINDOW->m_sFullscreenState.internal, .client = PWINDOW->m_sFullscreenState.internal}); + PWINDOW->m_sWindowData.syncFullscreen = CWindowOverridableVar(true, PRIORITY_SET_PROP); + return; + } + + PWINDOW->m_sWindowData.syncFullscreen = CWindowOverridableVar(false, PRIORITY_SET_PROP); + g_pCompositor->setWindowFullscreenState(PWINDOW, STATE); } void CKeybindManager::moveActiveToWorkspace(std::string args) { From 0e86808e5912823f1c6bea1b6d5fcae297fc9f57 Mon Sep 17 00:00:00 2001 From: Tom Englund Date: Mon, 5 Aug 2024 19:58:21 +0200 Subject: [PATCH 0234/2181] cursor: Better xcursor implementation (#7178) * xcursor: bootleg xcursors into its own manager implent XCursorManager and load themes based on librarypath and its dir, now we catch all supplied theme files. and also implent animated cursors. also refactor a bit of spaghetti regarding xcursors in CursorManager. * hyprcursor: fix buffer leak animated cursors are creating a new buffer for each image, ensure we drop the buffers so it continously doesnt build up in infinity. * cursormgr: use eventloopmgr for animation use EvenloopManager for timers instead of adding it directly to m_sWLEventLoop and using its related wl_* functions. --- src/managers/CursorManager.cpp | 474 ++++++-------------------------- src/managers/CursorManager.hpp | 26 +- src/managers/XCursorManager.cpp | 447 ++++++++++++++++++++++++++++++ src/managers/XCursorManager.hpp | 46 ++++ 4 files changed, 585 insertions(+), 408 deletions(-) create mode 100644 src/managers/XCursorManager.cpp create mode 100644 src/managers/XCursorManager.hpp diff --git a/src/managers/CursorManager.cpp b/src/managers/CursorManager.cpp index e0d3a62c..9b574901 100644 --- a/src/managers/CursorManager.cpp +++ b/src/managers/CursorManager.cpp @@ -3,15 +3,10 @@ #include "../config/ConfigValue.hpp" #include "PointerManager.hpp" #include "../xwayland/XWayland.hpp" -#include -#include "../helpers/CursorShapes.hpp" -extern "C" { -#include -} - -static int cursorAnimTimer(void* data) { - g_pCursorManager->tickAnimatedCursor(); +static int cursorAnimTimer(SP self, void* data) { + const auto cursorMgr = reinterpret_cast(data); + cursorMgr->tickAnimatedCursor(); return 1; } @@ -24,31 +19,41 @@ static void hcLogger(enum eHyprcursorLogLevel level, char* message) { CCursorManager::CCursorManager() { m_pHyprcursor = std::make_unique(m_szTheme.empty() ? nullptr : m_szTheme.c_str(), hcLogger); + m_pXcursor = std::make_unique(); - if (!m_pHyprcursor->valid()) - Debug::log(ERR, "Hyprcursor failed loading theme \"{}\", falling back to X.", m_szTheme); + if (m_pHyprcursor->valid()) { + // find default size. First, HYPRCURSOR_SIZE then default to 24 + auto const* SIZE = getenv("HYPRCURSOR_SIZE"); + if (SIZE) { + try { + m_iSize = std::stoi(SIZE); + } catch (...) { ; } + } - // find default size. First, HYPRCURSOR_SIZE, then XCURSOR_SIZE, then 24 - auto SIZE = getenv("HYPRCURSOR_SIZE"); - if (SIZE) { - try { - m_iSize = std::stoi(SIZE); - } catch (...) { ; } + if (m_iSize <= 0) { + Debug::log(WARN, "HYPRCURSOR_SIZE size not set, defaulting to size 24"); + m_iSize = 24; + } + } else { + Debug::log(ERR, "Hyprcursor failed loading theme \"{}\", falling back to Xcursor.", m_szTheme); + + auto const* SIZE = getenv("XCURSOR_SIZE"); + if (SIZE) { + try { + m_iSize = std::stoi(SIZE); + } catch (...) { ; } + } + + if (m_iSize <= 0) { + Debug::log(WARN, "XCURSOR_SIZE size not set, defaulting to size 24"); + m_iSize = 24; + } + + m_pXcursor->loadTheme(getenv("XCURSOR_THEME") ? getenv("XCURSOR_THEME") : "default", m_iSize * std::ceil(m_fCursorScale)); } - SIZE = getenv("XCURSOR_SIZE"); - if (SIZE && m_iSize == 0) { - try { - m_iSize = std::stoi(SIZE); - } catch (...) { ; } - } - - if (m_iSize == 0) - m_iSize = 24; - - xcursor.loadTheme(getenv("XCURSOR_THEME") ? getenv("XCURSOR_THEME") : "default", m_iSize * std::ceil(m_fCursorScale)); - - m_pAnimationTimer = wl_event_loop_add_timer(g_pCompositor->m_sWLEventLoop, ::cursorAnimTimer, nullptr); + m_pAnimationTimer = makeShared(std::nullopt, cursorAnimTimer, this); + g_pEventLoopManager->addTimer(m_pAnimationTimer); updateTheme(); @@ -56,8 +61,10 @@ CCursorManager::CCursorManager() { } CCursorManager::~CCursorManager() { - if (m_pAnimationTimer) - wl_event_source_remove(m_pAnimationTimer); + if (m_pAnimationTimer && g_pEventLoopManager) { + g_pEventLoopManager->removeTimer(m_pAnimationTimer); + m_pAnimationTimer.reset(); + } } void CCursorManager::dropBufferRef(CCursorManager::CCursorBuffer* ref) { @@ -133,30 +140,26 @@ void CCursorManager::setCursorSurface(SP surf, const Vector2D& hotsp void CCursorManager::setXCursor(const std::string& name) { float scale = std::ceil(m_fCursorScale); - if (!xcursor.themeLoaded) { - Debug::log(ERR, "XCursor failed to find theme in setXCursor"); - if (!xcursor.defaultCursor) { - g_pPointerManager->resetCursorImage(); - return; - } - } + auto xcursor = m_pXcursor->getShape(name, m_iSize * scale); + auto& icon = xcursor->images.front(); - auto& icon = xcursor.defaultCursor; - // try to get an icon we know if we have one - for (auto const& c : xcursor.cursors) { - if (c.first != name) - continue; + m_vCursorBuffers.emplace_back(makeShared((uint8_t*)icon.pixels.data(), icon.size, icon.hotspot)); - icon = c.second; - } - - m_vCursorBuffers.emplace_back(makeShared((uint8_t*)icon->pixels.data(), icon->size, icon->hotspot)); - - g_pPointerManager->setCursorBuffer(getCursorBuffer(), icon->hotspot / scale, scale); + g_pPointerManager->setCursorBuffer(getCursorBuffer(), icon.hotspot / scale, scale); if (m_vCursorBuffers.size() > 1) dropBufferRef(m_vCursorBuffers.at(0).get()); + m_currentXcursor = xcursor; m_bOurBufferConnected = true; + + if (m_currentXcursor->images.size() > 1) { + // animated + m_pAnimationTimer->updateTimeout(std::chrono::milliseconds(m_currentXcursor->images[0].delay)); + m_iCurrentAnimationFrame = 0; + } else { + // disarm + m_pAnimationTimer->updateTimeout(std::nullopt); + } } void CCursorManager::setCursorFromName(const std::string& name) { @@ -209,15 +212,35 @@ void CCursorManager::setCursorFromName(const std::string& name) { if (m_sCurrentCursorShapeData.images.size() > 1) { // animated - wl_event_source_timer_update(m_pAnimationTimer, m_sCurrentCursorShapeData.images[0].delay); + m_pAnimationTimer->updateTimeout(std::chrono::milliseconds(m_sCurrentCursorShapeData.images[0].delay)); m_iCurrentAnimationFrame = 0; } else { // disarm - wl_event_source_timer_update(m_pAnimationTimer, 0); + m_pAnimationTimer->updateTimeout(std::nullopt); } } void CCursorManager::tickAnimatedCursor() { + if (!m_pHyprcursor->valid() && m_currentXcursor->images.size() > 1 && m_bOurBufferConnected) { + m_iCurrentAnimationFrame++; + + if ((size_t)m_iCurrentAnimationFrame >= m_currentXcursor->images.size()) + m_iCurrentAnimationFrame = 0; + + float scale = std::ceil(m_fCursorScale); + auto& icon = m_currentXcursor->images.at(m_iCurrentAnimationFrame); + m_vCursorBuffers.emplace_back(makeShared((uint8_t*)icon.pixels.data(), icon.size, icon.hotspot)); + + g_pPointerManager->setCursorBuffer(getCursorBuffer(), icon.hotspot / scale, scale); + + if (m_vCursorBuffers.size() > 1) + dropBufferRef(m_vCursorBuffers.at(0).get()); + + m_pAnimationTimer->updateTimeout(std::chrono::milliseconds(m_currentXcursor->images[m_iCurrentAnimationFrame].delay)); + + return; + } + if (m_sCurrentCursorShapeData.images.size() < 2 || !m_bOurBufferConnected) return; @@ -235,7 +258,10 @@ void CCursorManager::tickAnimatedCursor() { Vector2D{m_sCurrentCursorShapeData.images[m_iCurrentAnimationFrame].hotspotX, m_sCurrentCursorShapeData.images[m_iCurrentAnimationFrame].hotspotY} / m_fCursorScale, m_fCursorScale); - wl_event_source_timer_update(m_pAnimationTimer, m_sCurrentCursorShapeData.images[m_iCurrentAnimationFrame].delay); + if (m_vCursorBuffers.size() > 1) + dropBufferRef(m_vCursorBuffers.at(0).get()); + + m_pAnimationTimer->updateTimeout(std::chrono::milliseconds(m_sCurrentCursorShapeData.images[m_iCurrentAnimationFrame].delay)); } SCursorImageData CCursorManager::dataFor(const std::string& name) { @@ -256,10 +282,12 @@ void CCursorManager::setXWaylandCursor() { if (CURSOR.surface) { g_pXWayland->setCursor(cairo_image_surface_get_data(CURSOR.surface), cairo_image_surface_get_stride(CURSOR.surface), {CURSOR.size, CURSOR.size}, {CURSOR.hotspotX, CURSOR.hotspotY}); - } else if (xcursor.themeLoaded) - g_pXWayland->setCursor((uint8_t*)xcursor.defaultCursor->pixels.data(), xcursor.defaultCursor->size.x * 4, xcursor.defaultCursor->size, xcursor.defaultCursor->hotspot); - else - Debug::log(ERR, "CursorManager: no valid cursor for xwayland"); + } else { + auto xcursor = m_pXcursor->getShape("left_ptr", m_iSize * std::ceil(m_fCursorScale)); + auto& icon = xcursor->images.front(); + + g_pXWayland->setCursor((uint8_t*)icon.pixels.data(), icon.size.x * 4, icon.size, icon.hotspot); + } } void CCursorManager::updateTheme() { @@ -300,340 +328,12 @@ bool CCursorManager::changeTheme(const std::string& name, const int size) { return true; } - Debug::log(ERR, "Hyprcursor failed loading theme \"{}\", falling back to X.", name); + Debug::log(ERR, "Hyprcursor failed loading theme \"{}\", falling back to XCursor.", name); - xcursor.loadTheme(name, size); + m_pXcursor->loadTheme(name, size); m_szTheme = name; m_iSize = size; updateTheme(); return true; -} - -// Taken from https://gitlab.freedesktop.org/xorg/lib/libxcursor/-/blob/master/src/library.c -// _ -> - -// clang-format off -static std::array XCURSOR_STANDARD_NAMES = { - "X_cursor", - "arrow", - "based_arrow_down", - "based_arrow_up", - "boat", - "bogosity", - "bottom_left_corner", - "bottom_right_corner", - "bottom_side", - "bottom_tee", - "box_spiral", - "center_ptr", - "circle", - "clock", - "coffee_mug", - "cross", - "cross_reverse", - "crosshair", - "diamond_cross", - "dot", - "dotbox", - "double_arrow", - "draft_large", - "draft_small", - "draped_box", - "exchange", - "fleur", - "gobbler", - "gumby", - "hand1", - "hand2", - "heart", - "icon", - "iron_cross", - "left_ptr", - "left_side", - "left_tee", - "leftbutton", - "ll_angle", - "lr_angle", - "man", - "middlebutton", - "mouse", - "pencil", - "pirate", - "plus", - "question_arrow", - "right_ptr", - "right_side", - "right_tee", - "rightbutton", - "rtl_logo", - "sailboat", - "sb_down_arrow", - "sb_h_double_arrow", - "sb_left_arrow", - "sb_right_arrow", - "sb_up_arrow", - "sb_v_double_arrow", - "shuttle", - "sizing", - "spider", - "spraycan", - "star", - "target", - "tcross", - "top_left_arrow", - "top_left_corner", - "top_right_corner", - "top_side", - "top_tee", - "trek", - "ul_angle", - "umbrella", - "ur_angle", - "watch", - "xterm", -}; -// clang-format on - -void CCursorManager::SXCursorManager::loadTheme(const std::string& name, int size) { - if (lastLoadSize == size && themeName == name) - return; - - lastLoadSize = size; - themeLoaded = false; - themeName = name.empty() ? "default" : name; - - std::vector>> newCursors; - - // load the default xcursor shapes that exist in the theme - for (size_t i = 0; i < XCURSOR_STANDARD_NAMES.size(); ++i) { - auto shape = XCURSOR_STANDARD_NAMES.at(i); - auto xImage = XcursorShapeLoadImage(i << 1 /* wtf xcursor? */, themeName.c_str(), size); - - if (!xImage) { - Debug::log(LOG, "XCursor failed to find a shape with name {}, trying size 24.", shape); - xImage = XcursorShapeLoadImage(i << 1 /* wtf xcursor? */, themeName.c_str(), 24); - - if (!xImage) { - Debug::log(LOG, "XCursor failed to find a shape with name {}, skipping", shape); - continue; - } - } - - auto xcursor = makeShared(); - xcursor->size = {(int)xImage->width, (int)xImage->height}; - xcursor->hotspot = {(int)xImage->xhot, (int)xImage->yhot}; - - xcursor->pixels.resize(xImage->width * xImage->height); - std::memcpy(xcursor->pixels.data(), xImage->pixels, xImage->width * xImage->height * sizeof(uint32_t)); - - newCursors.emplace_back(std::string{shape}, xcursor); - - XcursorImageDestroy(xImage); - } - - if (newCursors.empty()) { - Debug::log(ERR, "XCursor failed finding any shapes in theme \"{}\".", themeName); - if (!defaultCursor) { - defaultCursor = createDefaultCursor(); - } - return; - } - - cursors.clear(); - cursors = std::move(newCursors); - defaultCursor.reset(); - themeLoaded = true; - - for (auto const& shape : CURSOR_SHAPE_NAMES) { - auto legacyName = getLegacyShapeName(shape); - if (legacyName.empty()) - continue; - - auto it = std::find_if(cursors.begin(), cursors.end(), [&legacyName](auto const& c) { return c.first == legacyName; }); - - if (it == cursors.end()) { - Debug::log(LOG, "XCursor failed to find a legacy shape with name {}, skipping", legacyName); - continue; - } - - cursors.emplace_back(shape, it->second); - } - - // set default cursor - for (auto const& c : cursors) { - if (c.first == "left_ptr" || c.first == "arrow") { - defaultCursor = c.second; - break; - } - } - - // just assign the first one then. - if (!defaultCursor) - defaultCursor = cursors.at(0).second; -} - -std::string CCursorManager::SXCursorManager::getLegacyShapeName(std::string const& shape) { - if (shape == "invalid") - return std::string(); - else if (shape == "default") - return "left_ptr"; - else if (shape == "context-menu") - return "left_ptr"; - else if (shape == "help") - return "left_ptr"; - else if (shape == "pointer") - return "hand2"; - else if (shape == "progress") - return "watch"; - else if (shape == "wait") - return "watch"; - else if (shape == "cell") - return "plus"; - else if (shape == "crosshair") - return "cross"; - else if (shape == "text") - return "xterm"; - else if (shape == "vertical-text") - return "xterm"; - else if (shape == "alias") - return "dnd-link"; - else if (shape == "copy") - return "dnd-copy"; - else if (shape == "move") - return "dnd-move"; - else if (shape == "no-drop") - return "dnd-none"; - else if (shape == "not-allowed") - return "crossed_circle"; - else if (shape == "grab") - return "hand1"; - else if (shape == "grabbing") - return "hand1"; - else if (shape == "e-resize") - return "right_side"; - else if (shape == "n-resize") - return "top_side"; - else if (shape == "ne-resize") - return "top_right_corner"; - else if (shape == "nw-resize") - return "top_left_corner"; - else if (shape == "s-resize") - return "bottom_side"; - else if (shape == "se-resize") - return "bottom_right_corner"; - else if (shape == "sw-resize") - return "bottom_left_corner"; - else if (shape == "w-resize") - return "left_side"; - else if (shape == "ew-resize") - return "sb_h_double_arrow"; - else if (shape == "ns-resize") - return "sb_v_double_arrow"; - else if (shape == "nesw-resize") - return "fd_double_arrow"; - else if (shape == "nwse-resize") - return "bd_double_arrow"; - else if (shape == "col-resize") - return "sb_h_double_arrow"; - else if (shape == "row-resize") - return "sb_v_double_arrow"; - else if (shape == "all-scroll") - return "fleur"; - else if (shape == "zoom-in") - return "left_ptr"; - else if (shape == "zoom-out") - return "left_ptr"; - - return std::string(); -} - -SP CCursorManager::SXCursorManager::createDefaultCursor() { - int cursorWidth = 32; - int cursorHeight = 32; - int cursorHotspotX = 3; - int cursorHotspotY = 2; - - static const uint32_t pixels[] = { - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x1b001816, 0x01000101, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x8e008173, 0x5f00564d, 0x16001412, 0x09000807, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x2b002624, 0x05000404, 0x00000000, 0x35002f2b, 0xd400bead, - 0xc300b09e, 0x90008275, 0x44003e37, 0x04000403, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x67005a56, - 0x6f00615c, 0x00000000, 0x00000000, 0x8b007c72, 0xf200d7c6, 0xfa00e0cc, 0xe800d0bd, 0xa0009181, 0x44003e37, 0x1a001815, 0x06000505, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x8d007976, 0xd600b8b3, 0x2500201f, 0x00000000, 0x17001413, 0xbd00a79c, 0xf600dacb, 0xff00e3d1, 0xfc00e1ce, 0xe800d0bc, 0xbf00ac9b, - 0x95008778, 0x51004a41, 0x0f000e0c, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x92007b7b, 0xf500d0cf, 0x9e008685, 0x00000000, 0x00000000, 0x23001f1d, 0x64005853, - 0x9b008980, 0xd900bfb3, 0xfb00dfce, 0xff00e4d0, 0xfb00e1cd, 0xec00d5c0, 0xa7009788, 0x47004139, 0x1e001b18, 0x05000504, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0xa200878a, 0xff00d6d9, 0xd600b4b5, - 0x0e000c0c, 0x00000000, 0x00000000, 0x02000202, 0x0c000b0a, 0x30002a28, 0x8e007d75, 0xd600bdb0, 0xef00d4c4, 0xfb00e0ce, 0xff00e4d0, 0xe600cfbb, 0xb800a695, 0x5f00564d, - 0x06000505, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x02000202, 0xc600a3aa, 0xff00d3da, 0xea00c3c8, 0x08000707, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x01000101, 0x2a002523, 0x61005550, 0x9500837b, - 0xd800bfb1, 0xfd00e1cf, 0xff00e5d0, 0xf500dcc7, 0x7c007065, 0x2a002622, 0x01000101, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x06000505, 0xd600aeb9, 0xff00d0dc, 0xcc00a7af, 0x04000303, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x01000101, 0x01000101, 0x2c002724, 0xa1008e85, 0xe600ccbd, 0xf800ddcb, 0xef00d6c3, 0xc300af9f, 0x2c002824, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x09000708, 0xd800adbc, 0xff00cdde, 0xb90095a0, 0x02000202, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x10000e0d, 0x4b00423e, 0xa4009088, 0xfd00dfd0, 0xff00e3d1, - 0xae009c8f, 0x42003b36, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x14001012, 0xf400c0d6, - 0xff00cadf, 0xb2008e9c, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x02000202, 0x1200100f, 0xa2008e86, 0xec00cfc3, 0xfc00ded0, 0xc300ada0, 0x15001311, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x2e002429, 0xfd00c4e0, 0xff00c7e2, 0x8f00707e, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x1e001a19, 0x75006662, 0xfb00dbd1, 0xf700d9cc, 0x9600847c, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x3e002f37, 0xfc00c1e1, 0xff00c5e3, 0x60004b55, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x15001212, 0xa6008f8b, 0xff00ddd5, - 0xf800d8ce, 0x36002f2d, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x51003d49, 0xfe00bfe5, 0xfe00c1e4, 0x4c003a44, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x01000101, 0x1d001918, 0xf400d1cd, 0xfe00dad5, 0xb3009a96, 0x03000303, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x66004b5d, 0xff00bee7, 0xfd00bee5, 0x4500343f, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x02000202, 0x82006e6e, 0xff00d8d7, 0xd800b9b6, 0x33002c2b, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x70005267, 0xff00bbe9, 0xfa00b8e3, 0x29001e25, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x3f003536, 0xea00c3c7, 0xf800d1d3, - 0x4a003e3f, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x5f004458, 0xff00b8eb, 0xf400b1e0, 0x29001e26, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x1b001617, 0xe100bac0, 0xff00d4da, 0x82006c6f, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x5a004054, 0xfe00b4eb, - 0xfb00b3e8, 0x3b002a36, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x0a000809, 0xc900a4ad, 0xff00d1dc, 0x88007075, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x44002f3f, 0xf300aae3, 0xfc00b1ea, 0x48003343, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x05000404, 0xdf00b3c2, 0xff00cedd, 0x8f00747c, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x25001a23, 0xf200a6e4, 0xff00b1ef, 0x84005c7c, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x09000708, - 0xe400b5c8, 0xff00cbdf, 0x78006068, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x12000c11, 0xc00082b6, 0xff00aef1, 0xaa0075a0, - 0x11000c10, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x1e00171b, 0xf700c1db, 0xff00c8e1, 0x4b003b42, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x05000305, 0x8d005f86, 0xfc00aaef, 0xed00a0e1, 0x26001a24, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x6f005463, 0xff00c4e3, 0xf500beda, 0x0c00090b, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x3e00293b, 0xed009de2, 0xff00aaf3, 0x8b005d84, 0x04000304, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x07000506, 0xeb00b1d4, 0xff00c1e6, 0xba008ea7, - 0x02000202, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0xb20075ab, 0xff00a7f4, 0xf300a1e9, 0x35002333, - 0x06000406, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x8900647d, 0xff00bde8, 0xfb00bce2, 0x26001d22, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x2b001c29, 0xf1009ce8, 0xfe00a5f4, 0xc60082be, 0x3b002738, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x01000101, 0x54003c4d, 0xfd00b8e8, 0xff00baea, 0x96006f89, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x78004d74, 0xe20091da, 0xff00a5f6, 0xb60077af, 0x42002b3f, 0x0c00080c, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x9400688a, 0xff00b5ed, 0xff00b6ec, 0xcc0093bc, 0x02000102, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x04000304, 0x8100527d, 0xeb0096e4, 0xf900a0f1, 0xdc008dd4, - 0x9b006595, 0x32002130, 0x0a00070a, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x2100161f, 0x5300394e, 0xe2009cd4, 0xff00b1ef, 0xff00b2ee, 0xc8008cba, 0x17001015, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x19001018, 0x5e003b5b, 0xcb0081c5, 0xff00a2f8, 0xfc00a1f4, 0xde0090d6, 0xa9006da3, 0x8300567e, 0x6f00496a, 0x76004e71, 0xbb007db2, 0xeb009edf, 0xfb00a9ee, 0xff00adf1, - 0xfd00adee, 0x9e006d95, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x04000304, 0x34002133, 0xa60069a1, 0xd70089d1, 0xf2009bea, 0xff00a3f7, 0xfb00a1f2, 0xfb00a2f2, 0xff00a6f5, - 0xff00a8f4, 0xfd00a7f2, 0xed009ee2, 0xcf008bc5, 0x14000e13, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x11000b11, 0x35002134, 0x5b003959, - 0x8b005887, 0xb30072ae, 0xc90080c3, 0xd10086ca, 0xa6006ba0, 0x65004261, 0x3c002839, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x01000101, 0x06000406, 0x0d00080d, 0x0f000a0f, 0x0a00060a, 0x01000101, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000}; - - auto hackcursor = makeShared(); - hackcursor->size = {cursorWidth, cursorHeight}; - hackcursor->hotspot = {cursorHotspotX, cursorHotspotY}; - hackcursor->pixels.resize(cursorWidth * cursorHeight); - std::memcpy(hackcursor->pixels.data(), pixels, cursorWidth * cursorHeight * sizeof(uint32_t)); - - return hackcursor; -} +} \ No newline at end of file diff --git a/src/managers/CursorManager.hpp b/src/managers/CursorManager.hpp index 44ab2e7b..a114b6c2 100644 --- a/src/managers/CursorManager.hpp +++ b/src/managers/CursorManager.hpp @@ -7,6 +7,8 @@ #include "../helpers/math/Math.hpp" #include "../helpers/memory/Memory.hpp" #include "../macros.hpp" +#include "managers/eventLoop/EventLoopManager.hpp" +#include "managers/XCursorManager.hpp" #include class CWLSurface; @@ -63,6 +65,8 @@ class CCursorManager { std::vector> m_vCursorBuffers; std::unique_ptr m_pHyprcursor; + std::unique_ptr m_pXcursor; + SP m_currentXcursor; std::string m_szTheme = ""; int m_iSize = 0; @@ -70,29 +74,9 @@ class CCursorManager { Hyprcursor::SCursorStyleInfo m_sCurrentStyleInfo; - wl_event_source* m_pAnimationTimer = nullptr; + SP m_pAnimationTimer; int m_iCurrentAnimationFrame = 0; Hyprcursor::SCursorShapeData m_sCurrentCursorShapeData; - - // gangsta bootleg XCursor impl. Whenever Hyprland has to use - // an xcursor, just use the pointer. - struct SXCursor { - Vector2D size; - Vector2D hotspot; - std::vector pixels; // XPixel is a u32 - }; - - struct SXCursorManager { - void loadTheme(const std::string& name, int size); - std::string getLegacyShapeName(std::string const& shape); - SP createDefaultCursor(); - - int lastLoadSize = 0; - bool themeLoaded = false; - std::string themeName = ""; - SP defaultCursor; - std::vector>> cursors; - } xcursor; }; inline std::unique_ptr g_pCursorManager; \ No newline at end of file diff --git a/src/managers/XCursorManager.cpp b/src/managers/XCursorManager.cpp new file mode 100644 index 00000000..b3f33086 --- /dev/null +++ b/src/managers/XCursorManager.cpp @@ -0,0 +1,447 @@ +#include +#include +#include +#include "helpers/CursorShapes.hpp" +#include "debug/Log.hpp" +#include "XCursorManager.hpp" + +// clang-format off +static std::vector HYPR_XCURSOR_PIXELS = { + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x1b001816, 0x01000101, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x8e008173, 0x5f00564d, 0x16001412, 0x09000807, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x2b002624, 0x05000404, 0x00000000, 0x35002f2b, 0xd400bead, + 0xc300b09e, 0x90008275, 0x44003e37, 0x04000403, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x67005a56, + 0x6f00615c, 0x00000000, 0x00000000, 0x8b007c72, 0xf200d7c6, 0xfa00e0cc, 0xe800d0bd, 0xa0009181, 0x44003e37, 0x1a001815, 0x06000505, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x8d007976, 0xd600b8b3, 0x2500201f, 0x00000000, 0x17001413, 0xbd00a79c, 0xf600dacb, 0xff00e3d1, 0xfc00e1ce, 0xe800d0bc, 0xbf00ac9b, + 0x95008778, 0x51004a41, 0x0f000e0c, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x92007b7b, 0xf500d0cf, 0x9e008685, 0x00000000, 0x00000000, 0x23001f1d, 0x64005853, + 0x9b008980, 0xd900bfb3, 0xfb00dfce, 0xff00e4d0, 0xfb00e1cd, 0xec00d5c0, 0xa7009788, 0x47004139, 0x1e001b18, 0x05000504, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0xa200878a, 0xff00d6d9, 0xd600b4b5, + 0x0e000c0c, 0x00000000, 0x00000000, 0x02000202, 0x0c000b0a, 0x30002a28, 0x8e007d75, 0xd600bdb0, 0xef00d4c4, 0xfb00e0ce, 0xff00e4d0, 0xe600cfbb, 0xb800a695, 0x5f00564d, + 0x06000505, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x02000202, 0xc600a3aa, 0xff00d3da, 0xea00c3c8, 0x08000707, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x01000101, 0x2a002523, 0x61005550, 0x9500837b, + 0xd800bfb1, 0xfd00e1cf, 0xff00e5d0, 0xf500dcc7, 0x7c007065, 0x2a002622, 0x01000101, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x06000505, 0xd600aeb9, 0xff00d0dc, 0xcc00a7af, 0x04000303, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x01000101, 0x01000101, 0x2c002724, 0xa1008e85, 0xe600ccbd, 0xf800ddcb, 0xef00d6c3, 0xc300af9f, 0x2c002824, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x09000708, 0xd800adbc, 0xff00cdde, 0xb90095a0, 0x02000202, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x10000e0d, 0x4b00423e, 0xa4009088, 0xfd00dfd0, 0xff00e3d1, + 0xae009c8f, 0x42003b36, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x14001012, 0xf400c0d6, + 0xff00cadf, 0xb2008e9c, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x02000202, 0x1200100f, 0xa2008e86, 0xec00cfc3, 0xfc00ded0, 0xc300ada0, 0x15001311, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x2e002429, 0xfd00c4e0, 0xff00c7e2, 0x8f00707e, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x1e001a19, 0x75006662, 0xfb00dbd1, 0xf700d9cc, 0x9600847c, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x3e002f37, 0xfc00c1e1, 0xff00c5e3, 0x60004b55, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x15001212, 0xa6008f8b, 0xff00ddd5, + 0xf800d8ce, 0x36002f2d, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x51003d49, 0xfe00bfe5, 0xfe00c1e4, 0x4c003a44, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x01000101, 0x1d001918, 0xf400d1cd, 0xfe00dad5, 0xb3009a96, 0x03000303, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x66004b5d, 0xff00bee7, 0xfd00bee5, 0x4500343f, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x02000202, 0x82006e6e, 0xff00d8d7, 0xd800b9b6, 0x33002c2b, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x70005267, 0xff00bbe9, 0xfa00b8e3, 0x29001e25, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x3f003536, 0xea00c3c7, 0xf800d1d3, + 0x4a003e3f, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x5f004458, 0xff00b8eb, 0xf400b1e0, 0x29001e26, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x1b001617, 0xe100bac0, 0xff00d4da, 0x82006c6f, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x5a004054, 0xfe00b4eb, + 0xfb00b3e8, 0x3b002a36, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x0a000809, 0xc900a4ad, 0xff00d1dc, 0x88007075, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x44002f3f, 0xf300aae3, 0xfc00b1ea, 0x48003343, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x05000404, 0xdf00b3c2, 0xff00cedd, 0x8f00747c, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x25001a23, 0xf200a6e4, 0xff00b1ef, 0x84005c7c, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x09000708, + 0xe400b5c8, 0xff00cbdf, 0x78006068, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x12000c11, 0xc00082b6, 0xff00aef1, 0xaa0075a0, + 0x11000c10, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x1e00171b, 0xf700c1db, 0xff00c8e1, 0x4b003b42, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x05000305, 0x8d005f86, 0xfc00aaef, 0xed00a0e1, 0x26001a24, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x6f005463, 0xff00c4e3, 0xf500beda, 0x0c00090b, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x3e00293b, 0xed009de2, 0xff00aaf3, 0x8b005d84, 0x04000304, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x07000506, 0xeb00b1d4, 0xff00c1e6, 0xba008ea7, + 0x02000202, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0xb20075ab, 0xff00a7f4, 0xf300a1e9, 0x35002333, + 0x06000406, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x8900647d, 0xff00bde8, 0xfb00bce2, 0x26001d22, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x2b001c29, 0xf1009ce8, 0xfe00a5f4, 0xc60082be, 0x3b002738, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x01000101, 0x54003c4d, 0xfd00b8e8, 0xff00baea, 0x96006f89, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x78004d74, 0xe20091da, 0xff00a5f6, 0xb60077af, 0x42002b3f, 0x0c00080c, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x9400688a, 0xff00b5ed, 0xff00b6ec, 0xcc0093bc, 0x02000102, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x04000304, 0x8100527d, 0xeb0096e4, 0xf900a0f1, 0xdc008dd4, + 0x9b006595, 0x32002130, 0x0a00070a, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x2100161f, 0x5300394e, 0xe2009cd4, 0xff00b1ef, 0xff00b2ee, 0xc8008cba, 0x17001015, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x19001018, 0x5e003b5b, 0xcb0081c5, 0xff00a2f8, 0xfc00a1f4, 0xde0090d6, 0xa9006da3, 0x8300567e, 0x6f00496a, 0x76004e71, 0xbb007db2, 0xeb009edf, 0xfb00a9ee, 0xff00adf1, + 0xfd00adee, 0x9e006d95, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x04000304, 0x34002133, 0xa60069a1, 0xd70089d1, 0xf2009bea, 0xff00a3f7, 0xfb00a1f2, 0xfb00a2f2, 0xff00a6f5, + 0xff00a8f4, 0xfd00a7f2, 0xed009ee2, 0xcf008bc5, 0x14000e13, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x11000b11, 0x35002134, 0x5b003959, + 0x8b005887, 0xb30072ae, 0xc90080c3, 0xd10086ca, 0xa6006ba0, 0x65004261, 0x3c002839, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x01000101, 0x06000406, 0x0d00080d, 0x0f000a0f, 0x0a00060a, 0x01000101, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000}; +// clang-format on + +CXCursorManager::CXCursorManager() { + hyprCursor = makeShared(); + SXCursorImage image; + image.size = {32, 32}; + image.hotspot = {3, 2}; + image.pixels = HYPR_XCURSOR_PIXELS; + image.delay = 0; + + hyprCursor->images.push_back(image); + hyprCursor->shape = "left_ptr"; + defaultCursor = hyprCursor; +} + +void CXCursorManager::loadTheme(std::string const& name, int size) { + if (lastLoadSize == size && themeName == name) + return; + + lastLoadSize = size; + themeName = name.empty() ? "default" : name; + defaultCursor.reset(); + cursors.clear(); + + auto paths = themePaths(themeName); + if (paths.empty()) { + Debug::log(ERR, "XCursor librarypath is empty loading standard XCursors"); + cursors = loadStandardCursors(themeName, lastLoadSize); + } else { + for (auto const& p : paths) { + auto dirCursors = loadAllFromDir(p, lastLoadSize); + std::copy_if(dirCursors.begin(), dirCursors.end(), std::back_inserter(cursors), + [this](auto const& p) { return std::none_of(cursors.begin(), cursors.end(), [&p](auto const& dp) { return dp->shape == p->shape; }); }); + } + } + + if (cursors.empty()) { + Debug::log(ERR, "XCursor failed finding any shapes in theme \"{}\".", themeName); + defaultCursor = hyprCursor; + return; + } + + for (auto const& shape : CURSOR_SHAPE_NAMES) { + auto legacyName = getLegacyShapeName(shape); + if (legacyName.empty()) + continue; + + auto it = std::find_if(cursors.begin(), cursors.end(), [&legacyName](auto const& c) { return c->shape == legacyName; }); + + if (it == cursors.end()) { + Debug::log(LOG, "XCursor failed to find a legacy shape with name {}, skipping", legacyName); + continue; + } + + auto cursor = makeShared(); + cursor->images = it->get()->images; + cursor->shape = shape; + + cursors.emplace_back(cursor); + } +} + +SP CXCursorManager::getShape(std::string const& shape, int size) { + // monitor scaling changed etc, so reload theme with new size. + if (size != lastLoadSize) + loadTheme(themeName, size); + + // try to get an icon we know if we have one + for (auto const& c : cursors) { + if (c->shape != shape) + continue; + + return c; + } + + Debug::log(WARN, "XCursor couldn't find shape {} , using default cursor instead", shape); + return defaultCursor; +} + +SP CXCursorManager::createCursor(std::string const& shape, XcursorImages* xImages) { + auto xcursor = makeShared(); + + for (int i = 0; i < xImages->nimage; i++) { + auto xImage = xImages->images[i]; + SXCursorImage image; + image.size = {(int)xImage->width, (int)xImage->height}; + image.hotspot = {(int)xImage->xhot, (int)xImage->yhot}; + image.pixels.resize(xImage->width * xImage->height); + std::memcpy(image.pixels.data(), xImage->pixels, xImage->width * xImage->height * sizeof(uint32_t)); + image.delay = xImage->delay; + + xcursor->images.emplace_back(image); + } + + xcursor->shape = shape; + + return xcursor; +} + +std::vector CXCursorManager::themePaths(std::string const& theme) { + auto const* path = XcursorLibraryPath(); + std::vector paths; + + auto expandTilde = [](std::string const& path) { + if (!path.empty() && path[0] == '~') { + const char* home = std::getenv("HOME"); + if (home) + return std::string(home) + path.substr(1); + } + return path; + }; + + if (path) { + std::stringstream ss(path); + std::string item; + + while (std::getline(ss, item, ':')) { + auto p = expandTilde(item + "/" + theme + "/cursors"); + + if (std::filesystem::exists(p) && std::filesystem::is_directory(p)) + paths.push_back(p); + } + } + + return paths; +} + +std::string CXCursorManager::getLegacyShapeName(std::string const& shape) { + if (shape == "invalid") + return std::string(); + else if (shape == "default") + return "left_ptr"; + else if (shape == "context-menu") + return "left_ptr"; + else if (shape == "help") + return "left_ptr"; + else if (shape == "pointer") + return "hand2"; + else if (shape == "progress") + return "watch"; + else if (shape == "wait") + return "watch"; + else if (shape == "cell") + return "plus"; + else if (shape == "crosshair") + return "cross"; + else if (shape == "text") + return "xterm"; + else if (shape == "vertical-text") + return "xterm"; + else if (shape == "alias") + return "dnd-link"; + else if (shape == "copy") + return "dnd-copy"; + else if (shape == "move") + return "dnd-move"; + else if (shape == "no-drop") + return "dnd-none"; + else if (shape == "not-allowed") + return "crossed_circle"; + else if (shape == "grab") + return "hand1"; + else if (shape == "grabbing") + return "hand1"; + else if (shape == "e-resize") + return "right_side"; + else if (shape == "n-resize") + return "top_side"; + else if (shape == "ne-resize") + return "top_right_corner"; + else if (shape == "nw-resize") + return "top_left_corner"; + else if (shape == "s-resize") + return "bottom_side"; + else if (shape == "se-resize") + return "bottom_right_corner"; + else if (shape == "sw-resize") + return "bottom_left_corner"; + else if (shape == "w-resize") + return "left_side"; + else if (shape == "ew-resize") + return "sb_h_double_arrow"; + else if (shape == "ns-resize") + return "sb_v_double_arrow"; + else if (shape == "nesw-resize") + return "fd_double_arrow"; + else if (shape == "nwse-resize") + return "bd_double_arrow"; + else if (shape == "col-resize") + return "sb_h_double_arrow"; + else if (shape == "row-resize") + return "sb_v_double_arrow"; + else if (shape == "all-scroll") + return "fleur"; + else if (shape == "zoom-in") + return "left_ptr"; + else if (shape == "zoom-out") + return "left_ptr"; + + return std::string(); +}; + +// Taken from https://gitlab.freedesktop.org/xorg/lib/libxcursor/-/blob/master/src/library.c +// clang-format off +static std::array XCURSOR_STANDARD_NAMES = { + "X_cursor", + "arrow", + "based_arrow_down", + "based_arrow_up", + "boat", + "bogosity", + "bottom_left_corner", + "bottom_right_corner", + "bottom_side", + "bottom_tee", + "box_spiral", + "center_ptr", + "circle", + "clock", + "coffee_mug", + "cross", + "cross_reverse", + "crosshair", + "diamond_cross", + "dot", + "dotbox", + "double_arrow", + "draft_large", + "draft_small", + "draped_box", + "exchange", + "fleur", + "gobbler", + "gumby", + "hand1", + "hand2", + "heart", + "icon", + "iron_cross", + "left_ptr", + "left_side", + "left_tee", + "leftbutton", + "ll_angle", + "lr_angle", + "man", + "middlebutton", + "mouse", + "pencil", + "pirate", + "plus", + "question_arrow", + "right_ptr", + "right_side", + "right_tee", + "rightbutton", + "rtl_logo", + "sailboat", + "sb_down_arrow", + "sb_h_double_arrow", + "sb_left_arrow", + "sb_right_arrow", + "sb_up_arrow", + "sb_v_double_arrow", + "shuttle", + "sizing", + "spider", + "spraycan", + "star", + "target", + "tcross", + "top_left_arrow", + "top_left_corner", + "top_right_corner", + "top_side", + "top_tee", + "trek", + "ul_angle", + "umbrella", + "ur_angle", + "watch", + "xterm", +}; +// clang-format on + +std::vector> CXCursorManager::loadStandardCursors(std::string const& name, int size) { + std::vector> newCursors; + + // load the default xcursor shapes that exist in the theme + for (size_t i = 0; i < XCURSOR_STANDARD_NAMES.size(); ++i) { + std::string shape{XCURSOR_STANDARD_NAMES.at(i)}; + auto xImages = XcursorShapeLoadImages(i << 1 /* wtf xcursor? */, name.c_str(), size); + + if (!xImages) { + Debug::log(WARN, "XCursor failed to find a shape with name {}, trying size 24.", shape); + xImages = XcursorShapeLoadImages(i << 1 /* wtf xcursor? */, name.c_str(), 24); + + if (!xImages) { + Debug::log(WARN, "XCursor failed to find a shape with name {}, skipping", shape); + continue; + } + } + + auto cursor = createCursor(shape, xImages); + newCursors.emplace_back(cursor); + + if (!defaultCursor && (shape == "left_ptr" || shape == "arrow")) + defaultCursor = cursor; + + XcursorImagesDestroy(xImages); + } + + // broken theme.. just set it. + if (!newCursors.empty() && !defaultCursor) + defaultCursor = newCursors.front(); + + return newCursors; +} + +std::vector> CXCursorManager::loadAllFromDir(std::string const& path, int size) { + std::vector> newCursors; + std::string full; + + if (std::filesystem::exists(path) && std::filesystem::is_directory(path)) { + for (const auto& entry : std::filesystem::directory_iterator(path)) { + if (!entry.is_regular_file() && !entry.is_symlink()) + continue; + + std::string full = entry.path().string(); + using PcloseType = int (*)(FILE*); + const std::unique_ptr f(fopen(full.c_str(), "r"), static_cast(fclose)); + + if (!f) + continue; + + auto xImages = XcursorFileLoadImages(f.get(), size); + + if (!xImages) { + Debug::log(WARN, "XCursor failed to load image {}, trying size 24.", full); + xImages = XcursorFileLoadImages(f.get(), 24); + + if (!xImages) { + Debug::log(WARN, "XCursor failed to load image {}, skipping", full); + continue; + } + } + + std::string shape = entry.path().filename().string(); + auto cursor = createCursor(shape, xImages); + newCursors.emplace_back(cursor); + + if (!defaultCursor && (shape == "left_ptr" || shape == "arrow")) + defaultCursor = cursor; + + XcursorImagesDestroy(xImages); + } + } + + // broken theme.. just set it. + if (!newCursors.empty() && !defaultCursor) + defaultCursor = newCursors.front(); + + return newCursors; +} diff --git a/src/managers/XCursorManager.hpp b/src/managers/XCursorManager.hpp new file mode 100644 index 00000000..9ced076f --- /dev/null +++ b/src/managers/XCursorManager.hpp @@ -0,0 +1,46 @@ +#pragma once +#include +#include +#include +#include +#include +#include "helpers/memory/Memory.hpp" + +extern "C" { +#include +} + +// gangsta bootleg XCursor impl. adidas balkanized +struct SXCursorImage { + Vector2D size; + Vector2D hotspot; + std::vector pixels; // XPixel is a u32 + uint32_t delay; // animation delay to next frame (ms) +}; + +struct SXCursors { + std::vector images; + std::string shape; +}; + +class CXCursorManager { + public: + CXCursorManager(); + ~CXCursorManager() = default; + + void loadTheme(const std::string& name, int size); + SP getShape(std::string const& shape, int size); + + private: + SP createCursor(std::string const& shape, XcursorImages* xImages); + std::vector themePaths(std::string const& theme); + std::string getLegacyShapeName(std::string const& shape); + std::vector> loadStandardCursors(std::string const& name, int size); + std::vector> loadAllFromDir(std::string const& path, int size); + + int lastLoadSize = 0; + std::string themeName = ""; + SP defaultCursor; + SP hyprCursor; + std::vector> cursors; +}; \ No newline at end of file From 640d1618519d42dd592f7af5e9984ad52eb8b820 Mon Sep 17 00:00:00 2001 From: Vaxry <43317083+vaxerski@users.noreply.github.com> Date: Tue, 6 Aug 2024 14:52:19 +0100 Subject: [PATCH 0235/2181] renderer: Explicit sync fixes (#7151) Enables explicit sync by default for most platforms `misc:no_direct_scanout` -> `render:direct_scanout` --- src/Compositor.cpp | 4 +- src/config/ConfigManager.cpp | 17 ++- src/helpers/Monitor.cpp | 64 +++++++++- src/helpers/Monitor.hpp | 3 +- src/helpers/ScopeGuard.cpp | 10 ++ src/helpers/ScopeGuard.hpp | 13 ++ src/helpers/sync/SyncReleaser.cpp | 25 ++++ src/helpers/sync/SyncReleaser.hpp | 31 +++++ src/helpers/sync/SyncTimeline.cpp | 5 + src/helpers/sync/SyncTimeline.hpp | 1 + src/managers/KeybindManager.cpp | 1 + src/managers/ProtocolManager.cpp | 2 +- src/protocols/DRMSyncobj.cpp | 53 ++++++--- src/protocols/DRMSyncobj.hpp | 11 +- src/protocols/core/Compositor.cpp | 17 +-- src/protocols/core/Compositor.hpp | 5 +- src/protocols/types/Buffer.cpp | 25 +--- src/protocols/types/Buffer.hpp | 12 +- src/protocols/types/WLBuffer.cpp | 10 -- src/protocols/types/WLBuffer.hpp | 1 - src/render/OpenGL.cpp | 32 ++--- src/render/OpenGL.hpp | 4 +- src/render/Renderer.cpp | 191 +++++++++++++++++++----------- src/render/Renderer.hpp | 6 + 24 files changed, 378 insertions(+), 165 deletions(-) create mode 100644 src/helpers/ScopeGuard.cpp create mode 100644 src/helpers/ScopeGuard.hpp create mode 100644 src/helpers/sync/SyncReleaser.cpp create mode 100644 src/helpers/sync/SyncReleaser.hpp diff --git a/src/Compositor.cpp b/src/Compositor.cpp index a139742c..299a16c6 100644 --- a/src/Compositor.cpp +++ b/src/Compositor.cpp @@ -2282,7 +2282,7 @@ void CCompositor::setWindowFullscreenClient(const PHLWINDOW PWINDOW, const eFull } void CCompositor::setWindowFullscreenState(const PHLWINDOW PWINDOW, sFullscreenState state) { - static auto PNODIRECTSCANOUT = CConfigValue("misc:no_direct_scanout"); + static auto PDIRECTSCANOUT = CConfigValue("render:direct_scanout"); if (!validMapped(PWINDOW) || g_pCompositor->m_bUnsafeState) return; @@ -2342,7 +2342,7 @@ void CCompositor::setWindowFullscreenState(const PHLWINDOW PWINDOW, sFullscreenS // send a scanout tranche if we are entering fullscreen, and send a regular one if we aren't. // ignore if DS is disabled. - if (!*PNODIRECTSCANOUT) + if (*PDIRECTSCANOUT) g_pHyprRenderer->setSurfaceScanoutMode(PWINDOW->m_pWLSurface->resource(), EFFECTIVE_MODE != FSMODE_NONE ? PMONITOR->self.lock() : nullptr); g_pConfigManager->ensureVRR(PMONITOR); diff --git a/src/config/ConfigManager.cpp b/src/config/ConfigManager.cpp index fe3af8c0..be6433fa 100644 --- a/src/config/ConfigManager.cpp +++ b/src/config/ConfigManager.cpp @@ -3,6 +3,7 @@ #include "../render/decorations/CHyprGroupBarDecoration.hpp" #include "config/ConfigDataValues.hpp" +#include "config/ConfigValue.hpp" #include "helpers/varlist/VarList.hpp" #include "../protocols/LayerShell.hpp" @@ -346,7 +347,6 @@ CConfigManager::CConfigManager() { m_pConfig->addConfigValue("misc:swallow_regex", {STRVAL_EMPTY}); m_pConfig->addConfigValue("misc:swallow_exception_regex", {STRVAL_EMPTY}); m_pConfig->addConfigValue("misc:focus_on_activate", Hyprlang::INT{0}); - m_pConfig->addConfigValue("misc:no_direct_scanout", Hyprlang::INT{1}); m_pConfig->addConfigValue("misc:mouse_move_focuses_monitor", Hyprlang::INT{1}); m_pConfig->addConfigValue("misc:render_ahead_of_time", Hyprlang::INT{0}); m_pConfig->addConfigValue("misc:render_ahead_safezone", Hyprlang::INT{1}); @@ -560,7 +560,9 @@ CConfigManager::CConfigManager() { m_pConfig->addConfigValue("group:groupbar:col.locked_active", Hyprlang::CConfigCustomValueType{&configHandleGradientSet, configHandleGradientDestroy, "0x66ff5500"}); m_pConfig->addConfigValue("group:groupbar:col.locked_inactive", Hyprlang::CConfigCustomValueType{&configHandleGradientSet, configHandleGradientDestroy, "0x66775500"}); - m_pConfig->addConfigValue("experimental:explicit_sync", Hyprlang::INT{0}); + m_pConfig->addConfigValue("render:explicit_sync", Hyprlang::INT{2}); + m_pConfig->addConfigValue("render:explicit_sync_kms", Hyprlang::INT{2}); + m_pConfig->addConfigValue("render:direct_scanout", Hyprlang::INT{0}); // devices m_pConfig->addSpecialCategory("device", {"name"}); @@ -798,6 +800,9 @@ std::optional CConfigManager::resetHLConfig() { } void CConfigManager::postConfigReload(const Hyprlang::CParseResult& result) { + static const auto PENABLEEXPLICIT = CConfigValue("render:explicit_sync"); + static int prevEnabledExplicit = *PENABLEEXPLICIT; + for (auto& w : g_pCompositor->m_vWindows) { w->uncacheWindowDecos(); } @@ -816,6 +821,9 @@ void CConfigManager::postConfigReload(const Hyprlang::CParseResult& result) { if (!isFirstLaunch) g_pHyprOpenGL->m_bReloadScreenShader = true; + if (!isFirstLaunch && *PENABLEEXPLICIT != prevEnabledExplicit) + g_pHyprError->queueCreate("Warning: You changed the render:explicit_sync option, this requires you to restart Hyprland.", CColor(0.9, 0.76, 0.221, 1.0)); + // parseError will be displayed next frame if (result.error) @@ -1417,7 +1425,7 @@ void CConfigManager::ensureVRR(CMonitor* pMonitor) { if (USEVRR == 0) { if (m->vrrActive) { - + m->output->state->resetExplicitFences(); m->output->state->setAdaptiveSync(false); if (!m->state.commit()) @@ -1427,6 +1435,7 @@ void CConfigManager::ensureVRR(CMonitor* pMonitor) { return; } else if (USEVRR == 1) { if (!m->vrrActive) { + m->output->state->resetExplicitFences(); m->output->state->setAdaptiveSync(true); if (!m->state.test()) { @@ -1451,6 +1460,7 @@ void CConfigManager::ensureVRR(CMonitor* pMonitor) { const auto WORKSPACEFULL = PWORKSPACE->m_bHasFullscreenWindow && (PWORKSPACE->m_efFullscreenMode & FSMODE_FULLSCREEN); if (WORKSPACEFULL) { + m->output->state->resetExplicitFences(); m->output->state->setAdaptiveSync(true); if (!m->state.test()) { @@ -1462,6 +1472,7 @@ void CConfigManager::ensureVRR(CMonitor* pMonitor) { Debug::log(ERR, "Couldn't commit output {} in ensureVRR -> true", m->output->name); } else if (!WORKSPACEFULL) { + m->output->state->resetExplicitFences(); m->output->state->setAdaptiveSync(false); if (!m->state.commit()) diff --git a/src/helpers/Monitor.cpp b/src/helpers/Monitor.cpp index 1cf1b069..8f23c462 100644 --- a/src/helpers/Monitor.cpp +++ b/src/helpers/Monitor.cpp @@ -1,6 +1,8 @@ #include "Monitor.hpp" #include "MiscFunctions.hpp" #include "math/Math.hpp" +#include "sync/SyncReleaser.hpp" +#include "ScopeGuard.hpp" #include "../Compositor.hpp" #include "../config/ConfigValue.hpp" #include "../protocols/GammaControl.hpp" @@ -8,6 +10,7 @@ #include "../protocols/LayerShell.hpp" #include "../protocols/PresentationTime.hpp" #include "../protocols/DRMLease.hpp" +#include "../protocols/DRMSyncobj.hpp" #include "../protocols/core/Output.hpp" #include "../managers/PointerManager.hpp" #include "../protocols/core/Compositor.hpp" @@ -77,6 +80,7 @@ void CMonitor::onConnect(bool noRule) { tearingState.canTear = output->getBackend()->type() == Aquamarine::AQ_BACKEND_DRM; if (m_bEnabled) { + output->state->resetExplicitFences(); output->state->setEnabled(true); state.commit(); return; @@ -101,6 +105,7 @@ void CMonitor::onConnect(bool noRule) { // if it's disabled, disable and ignore if (monitorRule.disabled) { + output->state->resetExplicitFences(); output->state->setEnabled(false); if (!state.commit()) @@ -137,6 +142,7 @@ void CMonitor::onConnect(bool noRule) { m_bEnabled = true; + output->state->resetExplicitFences(); output->state->setEnabled(true); // set mode, also applies @@ -300,6 +306,7 @@ void CMonitor::onDisconnect(bool destroy) { activeWorkspace->m_bVisible = false; activeWorkspace.reset(); + output->state->resetExplicitFences(); output->state->setEnabled(false); if (!state.commit()) @@ -808,28 +815,77 @@ bool CMonitor::attemptDirectScanout() { if (!PSURFACE->current.buffer || !PSURFACE->current.texture || !PSURFACE->current.texture->m_pEglImage /* dmabuf */) return false; + Debug::log(TRACE, "attemptDirectScanout: surface {:x} passed, will attempt", (uintptr_t)PSURFACE.get()); + // FIXME: make sure the buffer actually follows the available scanout dmabuf formats // and comes from the appropriate device. This may implode on multi-gpu!! output->state->setBuffer(PSURFACE->current.buffer->buffer.lock()); output->state->setPresentationMode(tearingState.activelyTearing ? Aquamarine::eOutputPresentationMode::AQ_OUTPUT_PRESENTATION_IMMEDIATE : Aquamarine::eOutputPresentationMode::AQ_OUTPUT_PRESENTATION_VSYNC); - if (!state.test()) + if (!state.test()) { + Debug::log(TRACE, "attemptDirectScanout: failed basic test"); return false; + } + + auto explicitOptions = g_pHyprRenderer->getExplicitSyncSettings(); + + // wait for the explicit fence if present, and if kms explicit is allowed + bool DOEXPLICIT = PSURFACE->syncobj && PSURFACE->syncobj->current.acquireTimeline && PSURFACE->syncobj->current.acquireTimeline->timeline && explicitOptions.explicitKMSEnabled; + int explicitWaitFD = -1; + if (DOEXPLICIT) { + explicitWaitFD = PSURFACE->syncobj->current.acquireTimeline->timeline->exportAsSyncFileFD(PSURFACE->syncobj->current.acquirePoint); + if (explicitWaitFD < 0) + Debug::log(TRACE, "attemptDirectScanout: failed to acquire an explicit wait fd"); + } + DOEXPLICIT = DOEXPLICIT && explicitWaitFD >= 0; + + auto cleanup = CScopeGuard([explicitWaitFD, this]() { + output->state->resetExplicitFences(); + if (explicitWaitFD >= 0) + close(explicitWaitFD); + }); timespec now; clock_gettime(CLOCK_MONOTONIC, &now); - Debug::log(TRACE, "presentFeedback for DS"); - PSURFACE->presentFeedback(&now, this, true); + PSURFACE->presentFeedback(&now, this); output->state->addDamage(CBox{{}, vecPixelSize}); + output->state->resetExplicitFences(); - if (state.commit()) { + if (DOEXPLICIT) { + Debug::log(TRACE, "attemptDirectScanout: setting IN_FENCE for aq to {}", explicitWaitFD); + output->state->setExplicitInFence(explicitWaitFD); + } + + bool ok = output->commit(); + + if (!ok && DOEXPLICIT) { + Debug::log(TRACE, "attemptDirectScanout: EXPLICIT SYNC FAILED: commit() returned false. Resetting fences and retrying, might result in glitches."); + output->state->resetExplicitFences(); + + ok = output->commit(); + } + + if (ok) { if (lastScanout.expired()) { lastScanout = PCANDIDATE; Debug::log(LOG, "Entered a direct scanout to {:x}: \"{}\"", (uintptr_t)PCANDIDATE.get(), PCANDIDATE->m_szTitle); } + + // delay explicit sync feedback until kms release of the buffer + if (DOEXPLICIT) { + Debug::log(TRACE, "attemptDirectScanout: Delaying explicit sync release feedback until kms release"); + PSURFACE->current.buffer->releaser->drop(); + + PSURFACE->current.buffer->buffer->hlEvents.backendRelease2 = PSURFACE->current.buffer->buffer->events.backendRelease.registerListener([PSURFACE](std::any d) { + const bool DOEXPLICIT = PSURFACE->syncobj && PSURFACE->syncobj->current.releaseTimeline && PSURFACE->syncobj->current.releaseTimeline->timeline; + if (DOEXPLICIT) + PSURFACE->syncobj->current.releaseTimeline->timeline->signal(PSURFACE->syncobj->current.releasePoint); + }); + } } else { + Debug::log(TRACE, "attemptDirectScanout: failed to scanout surface"); lastScanout.reset(); return false; } diff --git a/src/helpers/Monitor.hpp b/src/helpers/Monitor.hpp index 32fc768a..fbe26f67 100644 --- a/src/helpers/Monitor.hpp +++ b/src/helpers/Monitor.hpp @@ -121,8 +121,7 @@ class CMonitor { // explicit sync SP inTimeline; SP outTimeline; - uint64_t lastWaitPoint = 0; - uint64_t commitSeq = 0; + uint64_t commitSeq = 0; WP self; diff --git a/src/helpers/ScopeGuard.cpp b/src/helpers/ScopeGuard.cpp new file mode 100644 index 00000000..319255cd --- /dev/null +++ b/src/helpers/ScopeGuard.cpp @@ -0,0 +1,10 @@ +#include "ScopeGuard.hpp" + +CScopeGuard::CScopeGuard(const std::function& fn_) : fn(fn_) { + ; +} + +CScopeGuard::~CScopeGuard() { + if (fn) + fn(); +} diff --git a/src/helpers/ScopeGuard.hpp b/src/helpers/ScopeGuard.hpp new file mode 100644 index 00000000..8a1468eb --- /dev/null +++ b/src/helpers/ScopeGuard.hpp @@ -0,0 +1,13 @@ +#pragma once + +#include + +// calls a function when it goes out of scope +class CScopeGuard { + public: + CScopeGuard(const std::function& fn_); + ~CScopeGuard(); + + private: + std::function fn; +}; diff --git a/src/helpers/sync/SyncReleaser.cpp b/src/helpers/sync/SyncReleaser.cpp new file mode 100644 index 00000000..198495ab --- /dev/null +++ b/src/helpers/sync/SyncReleaser.cpp @@ -0,0 +1,25 @@ +#include "SyncReleaser.hpp" +#include "SyncTimeline.hpp" +#include "../../render/OpenGL.hpp" + +CSyncReleaser::CSyncReleaser(WP timeline_, uint64_t point_) : timeline(timeline_), point(point_) { + ; +} + +CSyncReleaser::~CSyncReleaser() { + if (timeline.expired()) + return; + + if (sync) + timeline->importFromSyncFileFD(point, sync->fd()); + else + timeline->signal(point); +} + +void CSyncReleaser::addReleaseSync(SP sync_) { + sync = sync_; +} + +void CSyncReleaser::drop() { + timeline.reset(); +} \ No newline at end of file diff --git a/src/helpers/sync/SyncReleaser.hpp b/src/helpers/sync/SyncReleaser.hpp new file mode 100644 index 00000000..e21d2e34 --- /dev/null +++ b/src/helpers/sync/SyncReleaser.hpp @@ -0,0 +1,31 @@ +#pragma once + +#include +#include +#include +#include +#include "../memory/Memory.hpp" + +/* + A helper (inspired by KDE's KWin) that will release the timeline point in the dtor +*/ + +class CSyncTimeline; +class CEGLSync; + +class CSyncReleaser { + public: + CSyncReleaser(WP timeline_, uint64_t point_); + ~CSyncReleaser(); + + // drops the releaser, will never signal anymore + void drop(); + + // wait for this gpu job to finish before releasing + void addReleaseSync(SP sync); + + private: + WP timeline; + uint64_t point = 0; + SP sync; +}; diff --git a/src/helpers/sync/SyncTimeline.cpp b/src/helpers/sync/SyncTimeline.cpp index 352120ea..16b5bd92 100644 --- a/src/helpers/sync/SyncTimeline.cpp +++ b/src/helpers/sync/SyncTimeline.cpp @@ -188,3 +188,8 @@ bool CSyncTimeline::transfer(SP from, uint64_t fromPoint, uint64_ return true; } + +void CSyncTimeline::signal(uint64_t point) { + if (drmSyncobjTimelineSignal(drmFD, &handle, &point, 1)) + Debug::log(ERR, "CSyncTimeline::signal: drmSyncobjTimelineSignal failed"); +} diff --git a/src/helpers/sync/SyncTimeline.hpp b/src/helpers/sync/SyncTimeline.hpp index 3d868a95..88ad4921 100644 --- a/src/helpers/sync/SyncTimeline.hpp +++ b/src/helpers/sync/SyncTimeline.hpp @@ -35,6 +35,7 @@ class CSyncTimeline { int exportAsSyncFileFD(uint64_t src); bool importFromSyncFileFD(uint64_t dst, int fd); bool transfer(SP from, uint64_t fromPoint, uint64_t toPoint); + void signal(uint64_t point); int drmFD = -1; uint32_t handle = 0; diff --git a/src/managers/KeybindManager.cpp b/src/managers/KeybindManager.cpp index 09ba7d50..08c6998d 100644 --- a/src/managers/KeybindManager.cpp +++ b/src/managers/KeybindManager.cpp @@ -2293,6 +2293,7 @@ void CKeybindManager::dpms(std::string arg) { if (!port.empty() && m->szName != port) continue; + m->output->state->resetExplicitFences(); m->output->state->setEnabled(enable); m->dpmsStatus = enable; diff --git a/src/managers/ProtocolManager.cpp b/src/managers/ProtocolManager.cpp index 635e6223..6e5cd16f 100644 --- a/src/managers/ProtocolManager.cpp +++ b/src/managers/ProtocolManager.cpp @@ -76,7 +76,7 @@ void CProtocolManager::onMonitorModeChange(CMonitor* pMonitor) { CProtocolManager::CProtocolManager() { - static const auto PENABLEEXPLICIT = CConfigValue("experimental:explicit_sync"); + static const auto PENABLEEXPLICIT = CConfigValue("render:explicit_sync"); // Outputs are a bit dumb, we have to agree. static auto P = g_pHookSystem->hookDynamic("monitorAdded", [this](void* self, SCallbackInfo& info, std::any param) { diff --git a/src/protocols/DRMSyncobj.cpp b/src/protocols/DRMSyncobj.cpp index 33339554..8b0330de 100644 --- a/src/protocols/DRMSyncobj.cpp +++ b/src/protocols/DRMSyncobj.cpp @@ -24,9 +24,9 @@ CDRMSyncobjSurfaceResource::CDRMSyncobjSurfaceResource(SPsetSetReleasePoint([this](CWpLinuxDrmSyncobjSurfaceV1* r, wl_resource* timeline_, uint32_t hi, uint32_t lo) { @@ -35,29 +35,33 @@ CDRMSyncobjSurfaceResource::CDRMSyncobjSurfaceResource(SPevents.precommit.registerListener([this](std::any d) { - if (!!acquireTimeline != !!releaseTimeline) { - resource->error(acquireTimeline ? WP_LINUX_DRM_SYNCOBJ_SURFACE_V1_ERROR_NO_RELEASE_POINT : WP_LINUX_DRM_SYNCOBJ_SURFACE_V1_ERROR_NO_ACQUIRE_POINT, "Missing timeline"); - surface->pending.rejected = true; - return; - } - - if ((acquireTimeline || releaseTimeline) && !surface->pending.texture) { + if ((pending.acquireTimeline || pending.releaseTimeline) && !surface->pending.texture) { resource->error(WP_LINUX_DRM_SYNCOBJ_SURFACE_V1_ERROR_NO_BUFFER, "Missing buffer"); surface->pending.rejected = true; return; } - if (!acquireTimeline) + if (!surface->pending.newBuffer) + return; // this commit does not change the state here + + if (!!pending.acquireTimeline != !!pending.releaseTimeline) { + resource->error(pending.acquireTimeline ? WP_LINUX_DRM_SYNCOBJ_SURFACE_V1_ERROR_NO_RELEASE_POINT : WP_LINUX_DRM_SYNCOBJ_SURFACE_V1_ERROR_NO_ACQUIRE_POINT, + "Missing timeline"); + surface->pending.rejected = true; + return; + } + + if (!pending.acquireTimeline) return; // wait for the acquire timeline to materialize - auto materialized = acquireTimeline->timeline->check(acquirePoint, DRM_SYNCOBJ_WAIT_FLAGS_WAIT_AVAILABLE); + auto materialized = pending.acquireTimeline->timeline->check(pending.acquirePoint, DRM_SYNCOBJ_WAIT_FLAGS_WAIT_AVAILABLE); if (!materialized.has_value()) { LOGM(ERR, "Failed to check the acquire timeline"); resource->noMemory(); @@ -68,7 +72,24 @@ CDRMSyncobjSurfaceResource::CDRMSyncobjSurfaceResource(SPlockPendingState(); - acquireTimeline->timeline->addWaiter([this]() { surface->unlockPendingState(); }, acquirePoint, DRM_SYNCOBJ_WAIT_FLAGS_WAIT_AVAILABLE); + pending.acquireTimeline->timeline->addWaiter([this]() { surface->unlockPendingState(); }, pending.acquirePoint, DRM_SYNCOBJ_WAIT_FLAGS_WAIT_AVAILABLE); + }); + + listeners.surfaceCommit = surface->events.commit.registerListener([this](std::any d) { + // apply timelines if new ones have been attached, otherwise don't touch + // the current ones + if (pending.releaseTimeline) { + current.releaseTimeline = pending.releaseTimeline; + current.releasePoint = pending.releasePoint; + } + + if (pending.acquireTimeline) { + current.acquireTimeline = pending.acquireTimeline; + current.acquirePoint = pending.acquirePoint; + } + + pending.releaseTimeline.reset(); + pending.acquireTimeline.reset(); }); } diff --git a/src/protocols/DRMSyncobj.hpp b/src/protocols/DRMSyncobj.hpp index c1c884ff..25dc10c1 100644 --- a/src/protocols/DRMSyncobj.hpp +++ b/src/protocols/DRMSyncobj.hpp @@ -14,17 +14,20 @@ class CDRMSyncobjSurfaceResource { public: CDRMSyncobjSurfaceResource(SP resource_, SP surface_); - bool good(); + bool good(); - WP surface; - WP acquireTimeline, releaseTimeline; - uint64_t acquirePoint = 0, releasePoint = 0; + WP surface; + struct { + WP acquireTimeline, releaseTimeline; + uint64_t acquirePoint = 0, releasePoint = 0; + } current, pending; private: SP resource; struct { CHyprSignalListener surfacePrecommit; + CHyprSignalListener surfaceCommit; } listeners; }; diff --git a/src/protocols/core/Compositor.cpp b/src/protocols/core/Compositor.cpp index 4a6fa40f..b0111032 100644 --- a/src/protocols/core/Compositor.cpp +++ b/src/protocols/core/Compositor.cpp @@ -7,6 +7,7 @@ #include "Subcompositor.hpp" #include "../Viewporter.hpp" #include "../../helpers/Monitor.hpp" +#include "../../helpers/sync/SyncReleaser.hpp" #include "../PresentationTime.hpp" #include "../DRMSyncobj.hpp" #include "../../render/Renderer.hpp" @@ -69,7 +70,8 @@ CWLSurfaceResource::CWLSurfaceResource(SP resource_) : resource(reso resource->setOnDestroy([this](CWlSurface* r) { destroy(); }); resource->setAttach([this](CWlSurface* r, wl_resource* buffer, int32_t x, int32_t y) { - pending.offset = {x, y}; + pending.offset = {x, y}; + pending.newBuffer = true; if (!buffer) { pending.buffer.reset(); @@ -428,6 +430,10 @@ void CWLSurfaceResource::commitPendingState() { current = pending; pending.damage.clear(); pending.bufferDamage.clear(); + pending.newBuffer = false; + + if (syncobj && syncobj->current.releaseTimeline && syncobj->current.releaseTimeline->timeline && current.buffer && current.buffer->buffer) + current.buffer->releaser = makeShared(syncobj->current.releaseTimeline->timeline, syncobj->current.releasePoint); if (current.texture) current.texture->m_eTransform = wlTransformToHyprutils(current.transform); @@ -501,23 +507,18 @@ void CWLSurfaceResource::updateCursorShm() { memcpy(shmData.data(), pixelData, bufLen); } -void CWLSurfaceResource::presentFeedback(timespec* when, CMonitor* pMonitor, bool needsExplicitSync) { +void CWLSurfaceResource::presentFeedback(timespec* when, CMonitor* pMonitor) { frame(when); auto FEEDBACK = makeShared(self.lock()); FEEDBACK->attachMonitor(pMonitor); FEEDBACK->presented(); PROTO::presentation->queueData(FEEDBACK); - if (!pMonitor || !pMonitor->outTimeline || !syncobj || !needsExplicitSync) + if (!pMonitor || !pMonitor->outTimeline || !syncobj) return; // attach explicit sync g_pHyprRenderer->explicitPresented.emplace_back(self.lock()); - - if (syncobj->acquirePoint > pMonitor->lastWaitPoint) { - Debug::log(TRACE, "presentFeedback lastWaitPoint {} -> {}", pMonitor->lastWaitPoint, syncobj->acquirePoint); - pMonitor->lastWaitPoint = syncobj->acquirePoint; - } } CWLCompositorResource::CWLCompositorResource(SP resource_) : resource(resource_) { diff --git a/src/protocols/core/Compositor.hpp b/src/protocols/core/Compositor.hpp index 460ec755..af0dfa58 100644 --- a/src/protocols/core/Compositor.hpp +++ b/src/protocols/core/Compositor.hpp @@ -97,7 +97,8 @@ class CWLSurfaceResource { Vector2D destination; CBox source; } viewport; - bool rejected = false; + bool rejected = false; + bool newBuffer = false; // void reset() { @@ -122,7 +123,7 @@ class CWLSurfaceResource { void breadthfirst(std::function, const Vector2D&, void*)> fn, void* data); CRegion accumulateCurrentBufferDamage(); - void presentFeedback(timespec* when, CMonitor* pMonitor, bool needsExplicitSync = false); + void presentFeedback(timespec* when, CMonitor* pMonitor); void lockPendingState(); void unlockPendingState(); diff --git a/src/protocols/types/Buffer.cpp b/src/protocols/types/Buffer.cpp index 40f2eaf8..ea12f017 100644 --- a/src/protocols/types/Buffer.cpp +++ b/src/protocols/types/Buffer.cpp @@ -9,11 +9,6 @@ void IHLBuffer::sendRelease() { resource->sendRelease(); } -void IHLBuffer::sendReleaseWithSurface(SP surf) { - if (resource && resource->good()) - resource->sendReleaseWithSurface(surf); -} - void IHLBuffer::lock() { nLocks++; } @@ -27,26 +22,13 @@ void IHLBuffer::unlock() { sendRelease(); } -void IHLBuffer::unlockWithSurface(SP surf) { - nLocks--; - - ASSERT(nLocks >= 0); - - if (nLocks == 0) - sendReleaseWithSurface(surf); -} - bool IHLBuffer::locked() { return nLocks > 0; } void IHLBuffer::unlockOnBufferRelease(WP surf) { - unlockSurface = surf; hlEvents.backendRelease = events.backendRelease.registerListener([this](std::any data) { - if (unlockSurface.expired()) - unlock(); - else - unlockWithSurface(unlockSurface.lock()); + unlock(); hlEvents.backendRelease.reset(); }); } @@ -59,8 +41,5 @@ CHLBufferReference::~CHLBufferReference() { if (buffer.expired()) return; - if (surface) - buffer->unlockWithSurface(surface.lock()); - else - buffer->unlock(); + buffer->unlock(); } diff --git a/src/protocols/types/Buffer.hpp b/src/protocols/types/Buffer.hpp index d2157181..7d84dce7 100644 --- a/src/protocols/types/Buffer.hpp +++ b/src/protocols/types/Buffer.hpp @@ -6,6 +6,8 @@ #include +class CSyncReleaser; + class IHLBuffer : public Aquamarine::IBuffer { public: virtual ~IHLBuffer(); @@ -15,10 +17,8 @@ class IHLBuffer : public Aquamarine::IBuffer { virtual bool isSynchronous() = 0; // whether the updates to this buffer are synchronous, aka happen over cpu virtual bool good() = 0; virtual void sendRelease(); - virtual void sendReleaseWithSurface(SP); virtual void lock(); virtual void unlock(); - virtual void unlockWithSurface(SP surf); virtual bool locked(); void unlockOnBufferRelease(WP surf /* optional */); @@ -29,12 +29,11 @@ class IHLBuffer : public Aquamarine::IBuffer { struct { CHyprSignalListener backendRelease; + CHyprSignalListener backendRelease2; // for explicit ds } hlEvents; private: - int nLocks = 0; - - WP unlockSurface; + int nLocks = 0; }; // for ref-counting. Releases in ~dtor @@ -44,7 +43,8 @@ class CHLBufferReference { CHLBufferReference(SP buffer, SP surface); ~CHLBufferReference(); - WP buffer; + WP buffer; + SP releaser; private: WP surface; diff --git a/src/protocols/types/WLBuffer.cpp b/src/protocols/types/WLBuffer.cpp index d34a867d..eb7d1fde 100644 --- a/src/protocols/types/WLBuffer.cpp +++ b/src/protocols/types/WLBuffer.cpp @@ -32,16 +32,6 @@ void CWLBufferResource::sendRelease() { resource->sendRelease(); } -void CWLBufferResource::sendReleaseWithSurface(SP surf) { - sendRelease(); - - if (!surf || !surf->syncobj) - return; - - if (drmSyncobjTimelineSignal(g_pCompositor->m_iDRMFD, &surf->syncobj->releaseTimeline->timeline->handle, &surf->syncobj->releasePoint, 1)) - Debug::log(ERR, "sendReleaseWithSurface: drmSyncobjTimelineSignal failed"); -} - wl_resource* CWLBufferResource::getResource() { return resource->resource(); } diff --git a/src/protocols/types/WLBuffer.hpp b/src/protocols/types/WLBuffer.hpp index 59512128..787abe1f 100644 --- a/src/protocols/types/WLBuffer.hpp +++ b/src/protocols/types/WLBuffer.hpp @@ -17,7 +17,6 @@ class CWLBufferResource { bool good(); void sendRelease(); - void sendReleaseWithSurface(SP); wl_resource* getResource(); WP buffer; diff --git a/src/render/OpenGL.cpp b/src/render/OpenGL.cpp index ea388df0..8875d8f4 100644 --- a/src/render/OpenGL.cpp +++ b/src/render/OpenGL.cpp @@ -2870,7 +2870,7 @@ SP CHyprOpenGLImpl::createEGLSync(int fenceFD) { std::vector attribs; int dupFd = -1; if (fenceFD > 0) { - int dupFd = fcntl(fenceFD, F_DUPFD_CLOEXEC, 0); + dupFd = fcntl(fenceFD, F_DUPFD_CLOEXEC, 0); if (dupFd < 0) { Debug::log(ERR, "createEGLSync: dup failed"); return nullptr; @@ -2889,8 +2889,18 @@ SP CHyprOpenGLImpl::createEGLSync(int fenceFD) { return nullptr; } - auto eglsync = SP(new CEGLSync); - eglsync->sync = sync; + // we need to flush otherwise we might not get a valid fd + glFlush(); + + int fd = g_pHyprOpenGL->m_sProc.eglDupNativeFenceFDANDROID(g_pHyprOpenGL->m_pEglDisplay, sync); + if (fd == EGL_NO_NATIVE_FENCE_FD_ANDROID) { + Debug::log(ERR, "eglDupNativeFenceFDANDROID failed"); + return nullptr; + } + + auto eglsync = SP(new CEGLSync); + eglsync->sync = sync; + eglsync->m_iFd = fd; return eglsync; } @@ -2983,19 +2993,13 @@ CEGLSync::~CEGLSync() { if (g_pHyprOpenGL->m_sProc.eglDestroySyncKHR(g_pHyprOpenGL->m_pEglDisplay, sync) != EGL_TRUE) Debug::log(ERR, "eglDestroySyncKHR failed"); + + if (m_iFd >= 0) + close(m_iFd); } -int CEGLSync::dupFenceFD() { - if (sync == EGL_NO_SYNC_KHR) - return -1; - - int fd = g_pHyprOpenGL->m_sProc.eglDupNativeFenceFDANDROID(g_pHyprOpenGL->m_pEglDisplay, sync); - if (fd == EGL_NO_NATIVE_FENCE_FD_ANDROID) { - Debug::log(ERR, "eglDupNativeFenceFDANDROID failed"); - return -1; - } - - return fd; +int CEGLSync::fd() { + return m_iFd; } bool CEGLSync::wait() { diff --git a/src/render/OpenGL.hpp b/src/render/OpenGL.hpp index 1e8325c1..f405cb7c 100644 --- a/src/render/OpenGL.hpp +++ b/src/render/OpenGL.hpp @@ -131,12 +131,14 @@ class CEGLSync { EGLSyncKHR sync = nullptr; - int dupFenceFD(); + int fd(); bool wait(); private: CEGLSync() = default; + int m_iFd = -1; + friend class CHyprOpenGLImpl; }; diff --git a/src/render/Renderer.cpp b/src/render/Renderer.cpp index 127ae187..7794d476 100644 --- a/src/render/Renderer.cpp +++ b/src/render/Renderer.cpp @@ -1,9 +1,12 @@ #include "Renderer.hpp" #include "../Compositor.hpp" #include "../helpers/math/Math.hpp" +#include "../helpers/ScopeGuard.hpp" +#include "../helpers/sync/SyncReleaser.hpp" #include #include #include +#include #include "../config/ConfigValue.hpp" #include "../managers/CursorManager.hpp" #include "../managers/PointerManager.hpp" @@ -115,8 +118,8 @@ static void renderSurface(SP surface, int x, int y, void* da return; // explicit sync: wait for the timeline, if any - if (surface->syncobj && surface->syncobj->acquireTimeline) { - if (!g_pHyprOpenGL->waitForTimelinePoint(surface->syncobj->acquireTimeline->timeline, surface->syncobj->acquirePoint)) { + if (surface->syncobj && surface->syncobj->current.acquireTimeline) { + if (!g_pHyprOpenGL->waitForTimelinePoint(surface->syncobj->current.acquireTimeline->timeline, surface->syncobj->current.acquirePoint)) { Debug::log(ERR, "Renderer: failed to wait for explicit timeline"); return; } @@ -1095,7 +1098,7 @@ void CHyprRenderer::renderMonitor(CMonitor* pMonitor) { static auto PDEBUGOVERLAY = CConfigValue("debug:overlay"); static auto PDAMAGETRACKINGMODE = CConfigValue("debug:damage_tracking"); static auto PDAMAGEBLINK = CConfigValue("debug:damage_blink"); - static auto PNODIRECTSCANOUT = CConfigValue("misc:no_direct_scanout"); + static auto PDIRECTSCANOUT = CConfigValue("render:direct_scanout"); static auto PVFR = CConfigValue("misc:vfr"); static auto PZOOMFACTOR = CConfigValue("cursor:zoom_factor"); static auto PANIMENABLED = CConfigValue("animations:enabled"); @@ -1195,7 +1198,7 @@ void CHyprRenderer::renderMonitor(CMonitor* pMonitor) { pMonitor->tearingState.activelyTearing = shouldTear; - if (!*PNODIRECTSCANOUT && !shouldTear) { + if (*PDIRECTSCANOUT && !shouldTear) { if (pMonitor->attemptDirectScanout()) { return; } else if (!pMonitor->lastScanout.expired()) { @@ -1403,59 +1406,62 @@ void CHyprRenderer::renderMonitor(CMonitor* pMonitor) { } bool CHyprRenderer::commitPendingAndDoExplicitSync(CMonitor* pMonitor) { - static auto PENABLEEXPLICIT = CConfigValue("experimental:explicit_sync"); - // apply timelines for explicit sync + // save inFD otherwise reset will reset it + auto inFD = pMonitor->output->state->state().explicitInFence; pMonitor->output->state->resetExplicitFences(); - - bool anyExplicit = !explicitPresented.empty(); - if (anyExplicit) { - Debug::log(TRACE, "Explicit sync presented begin"); - auto inFence = pMonitor->inTimeline->exportAsSyncFileFD(pMonitor->lastWaitPoint); - if (inFence < 0) - Debug::log(ERR, "Export lastWaitPoint {} as sync explicitInFence failed", pMonitor->lastWaitPoint); - - pMonitor->output->state->setExplicitInFence(inFence); - - for (auto& e : explicitPresented) { - Debug::log(TRACE, "Explicit sync presented releasePoint {}", e->syncobj && e->syncobj->releaseTimeline ? e->syncobj->releasePoint : -1); - if (!e->syncobj || !e->syncobj->releaseTimeline) - continue; - e->syncobj->releaseTimeline->timeline->transfer(pMonitor->outTimeline, pMonitor->commitSeq, e->syncobj->releasePoint); - } - - explicitPresented.clear(); - auto outFence = pMonitor->outTimeline->exportAsSyncFileFD(pMonitor->commitSeq); - if (outFence < 0) - Debug::log(ERR, "Export commitSeq {} as sync explicitOutFence failed", pMonitor->commitSeq); - - pMonitor->output->state->setExplicitOutFence(outFence); - Debug::log(TRACE, "Explicit sync presented end"); - } - - pMonitor->lastWaitPoint = 0; + if (inFD >= 0) + pMonitor->output->state->setExplicitInFence(inFD); bool ok = pMonitor->state.commit(); if (!ok) { - Debug::log(TRACE, "Monitor state commit failed"); - // rollback the buffer to avoid writing to the front buffer that is being - // displayed - pMonitor->output->swapchain->rollback(); - pMonitor->damage.damageEntire(); + if (inFD >= 0) { + Debug::log(TRACE, "Monitor state commit failed, retrying without a fence"); + pMonitor->output->state->resetExplicitFences(); + ok = pMonitor->state.commit(); + } + + if (!ok) { + Debug::log(TRACE, "Monitor state commit failed"); + // rollback the buffer to avoid writing to the front buffer that is being + // displayed + pMonitor->output->swapchain->rollback(); + pMonitor->damage.damageEntire(); + } } - if (!*PENABLEEXPLICIT) + auto explicitOptions = getExplicitSyncSettings(); + + if (!explicitOptions.explicitEnabled) return ok; - if (pMonitor->output->state->state().explicitInFence >= 0) - close(pMonitor->output->state->state().explicitInFence); + if (inFD >= 0) + close(inFD); if (pMonitor->output->state->state().explicitOutFence >= 0) { - if (ok) - pMonitor->outTimeline->importFromSyncFileFD(pMonitor->commitSeq, pMonitor->output->state->state().explicitOutFence); + Debug::log(TRACE, "Aquamarine returned an explicit out fence at {}", pMonitor->output->state->state().explicitOutFence); close(pMonitor->output->state->state().explicitOutFence); + } else + Debug::log(TRACE, "Aquamarine did not return an explicit out fence"); + + Debug::log(TRACE, "Explicit: {} presented", explicitPresented.size()); + auto sync = g_pHyprOpenGL->createEGLSync(-1); + + if (!sync) + Debug::log(TRACE, "Explicit: can't add sync, EGLSync failed"); + else { + for (auto& e : explicitPresented) { + if (!e->current.buffer || !e->current.buffer->releaser) + continue; + + e->current.buffer->releaser->addReleaseSync(sync); + } } + explicitPresented.clear(); + + pMonitor->output->state->resetExplicitFences(); + return ok; } @@ -1898,6 +1904,7 @@ bool CHyprRenderer::applyMonitorRule(CMonitor* pMonitor, SMonitorRule* pMonitorR pMonitor->currentMode = nullptr; pMonitor->output->state->setFormat(DRM_FORMAT_XRGB8888); + pMonitor->output->state->resetExplicitFences(); bool autoScale = false; @@ -2643,10 +2650,16 @@ bool CHyprRenderer::beginRender(CMonitor* pMonitor, CRegion& damage, eRenderMode void CHyprRenderer::endRender() { const auto PMONITOR = g_pHyprOpenGL->m_RenderData.pMonitor; static auto PNVIDIAANTIFLICKER = CConfigValue("opengl:nvidia_anti_flicker"); - static auto PENABLEEXPLICIT = CConfigValue("experimental:explicit_sync"); PMONITOR->commitSeq++; + auto cleanup = CScopeGuard([this]() { + if (m_pCurrentRenderbuffer) + m_pCurrentRenderbuffer->unbind(); + m_pCurrentRenderbuffer = nullptr; + m_pCurrentBuffer = nullptr; + }); + if (m_eRenderMode != RENDER_MODE_TO_BUFFER_READ_ONLY) g_pHyprOpenGL->end(); else { @@ -2661,35 +2674,28 @@ void CHyprRenderer::endRender() { if (m_eRenderMode == RENDER_MODE_NORMAL) { PMONITOR->output->state->setBuffer(m_pCurrentBuffer); - if (PMONITOR->inTimeline && *PENABLEEXPLICIT) { + auto explicitOptions = getExplicitSyncSettings(); + + if (PMONITOR->inTimeline && explicitOptions.explicitEnabled && explicitOptions.explicitKMSEnabled) { auto sync = g_pHyprOpenGL->createEGLSync(-1); if (!sync) { - m_pCurrentRenderbuffer->unbind(); - m_pCurrentRenderbuffer = nullptr; - m_pCurrentBuffer = nullptr; Debug::log(ERR, "renderer: couldn't create an EGLSync for out in endRender"); return; } - auto dupedfd = sync->dupFenceFD(); - sync.reset(); - if (dupedfd < 0) { - m_pCurrentRenderbuffer->unbind(); - m_pCurrentRenderbuffer = nullptr; - m_pCurrentBuffer = nullptr; - Debug::log(ERR, "renderer: couldn't dup an EGLSync fence for out in endRender"); - return; - } - - bool ok = PMONITOR->inTimeline->importFromSyncFileFD(PMONITOR->commitSeq, dupedfd); - close(dupedfd); + bool ok = PMONITOR->inTimeline->importFromSyncFileFD(PMONITOR->commitSeq, sync->fd()); if (!ok) { - m_pCurrentRenderbuffer->unbind(); - m_pCurrentRenderbuffer = nullptr; - m_pCurrentBuffer = nullptr; Debug::log(ERR, "renderer: couldn't import from sync file fd in endRender"); return; } + + auto fd = PMONITOR->inTimeline->exportAsSyncFileFD(PMONITOR->commitSeq); + if (fd <= 0) { + Debug::log(ERR, "renderer: couldn't export from sync timeline in endRender"); + return; + } + + PMONITOR->output->state->setExplicitInFence(fd); } else { if (isNvidia() && *PNVIDIAANTIFLICKER) glFinish(); @@ -2697,11 +2703,6 @@ void CHyprRenderer::endRender() { glFlush(); } } - - m_pCurrentRenderbuffer->unbind(); - - m_pCurrentRenderbuffer = nullptr; - m_pCurrentBuffer = nullptr; } void CHyprRenderer::onRenderbufferDestroy(CRenderbuffer* rb) { @@ -2715,3 +2716,57 @@ SP CHyprRenderer::getCurrentRBO() { bool CHyprRenderer::isNvidia() { return m_bNvidia; } + +SExplicitSyncSettings CHyprRenderer::getExplicitSyncSettings() { + static auto PENABLEEXPLICIT = CConfigValue("render:explicit_sync"); + static auto PENABLEEXPLICITKMS = CConfigValue("render:explicit_sync_kms"); + + SExplicitSyncSettings settings; + settings.explicitEnabled = *PENABLEEXPLICIT; + settings.explicitKMSEnabled = *PENABLEEXPLICITKMS; + + if (*PENABLEEXPLICIT == 2 /* auto */) + settings.explicitEnabled = true; + if (*PENABLEEXPLICITKMS == 2 /* auto */) { + if (!m_bNvidia) + settings.explicitKMSEnabled = true; + else { + + // check nvidia version. Explicit KMS is supported in >=560 + // in the case of an error, driverMajor will stay 0 and explicit KMS will be disabled + int driverMajor = 0; + + static bool once = true; + if (once) { + once = false; + + Debug::log(LOG, "Renderer: checking for explicit KMS support for nvidia"); + + if (std::filesystem::exists("/sys/module/nvidia_drm/version")) { + Debug::log(LOG, "Renderer: Nvidia version file exists"); + + std::ifstream ifs("/sys/module/nvidia_drm/version"); + if (ifs.good()) { + try { + std::string driverInfo((std::istreambuf_iterator(ifs)), (std::istreambuf_iterator())); + + Debug::log(LOG, "Renderer: Read nvidia version {}", driverInfo); + + CVarList ver(driverInfo, 0, '.', true); + driverMajor = std::stoi(ver[0]); + + Debug::log(LOG, "Renderer: Parsed nvidia major version: {}", driverMajor); + + } catch (std::exception& e) { settings.explicitKMSEnabled = false; } + + ifs.close(); + } + } + } + + settings.explicitKMSEnabled = driverMajor >= 560; + } + } + + return settings; +} diff --git a/src/render/Renderer.hpp b/src/render/Renderer.hpp index a9397cac..84501821 100644 --- a/src/render/Renderer.hpp +++ b/src/render/Renderer.hpp @@ -39,6 +39,10 @@ class CToplevelExportProtocolManager; class CInputManager; struct SSessionLockSurface; +struct SExplicitSyncSettings { + bool explicitEnabled = false, explicitKMSEnabled = false; +}; + class CHyprRenderer { public: CHyprRenderer(); @@ -73,6 +77,7 @@ class CHyprRenderer { bool isNvidia(); void makeEGLCurrent(); void unsetEGL(); + SExplicitSyncSettings getExplicitSyncSettings(); // if RENDER_MODE_NORMAL, provided damage will be written to. // otherwise, it will be the one used. @@ -142,6 +147,7 @@ class CHyprRenderer { friend class CToplevelExportFrame; friend class CInputManager; friend class CPointerManager; + friend class CMonitor; }; inline std::unique_ptr g_pHyprRenderer; From d597ae41b9ce7d995a4ad28bda9ef54d4d01a020 Mon Sep 17 00:00:00 2001 From: Vaxry Date: Tue, 6 Aug 2024 16:57:15 +0200 Subject: [PATCH 0236/2181] renderer: fixup crashes on inaccessible files for bg --- src/render/OpenGL.cpp | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/src/render/OpenGL.cpp b/src/render/OpenGL.cpp index 8875d8f4..c355f4f9 100644 --- a/src/render/OpenGL.cpp +++ b/src/render/OpenGL.cpp @@ -2688,12 +2688,10 @@ void CHyprOpenGLImpl::createBGTextureForMonitor(CMonitor* pMonitor) { texPath += ".png"; // check if wallpapers exist - if (!std::filesystem::exists(texPath)) { - // try local - texPath = texPath.substr(0, 5) + "local/" + texPath.substr(5); - - if (!std::filesystem::exists(texPath)) - return; // the texture will be empty, oh well. We'll clear with a solid color anyways. + std::error_code err; + if (!std::filesystem::exists(texPath, err)) { + Debug::log(ERR, "createBGTextureForMonitor: failed, file doesn't exist or access denied, ec: {}", err.message()); + return; // the texture will be empty, oh well. We'll clear with a solid color anyways. } createBackgroundTexture(texPath); From b0a70f63e3865eaa77f0b78a04b230aa583bc95c Mon Sep 17 00:00:00 2001 From: Vaxry Date: Tue, 6 Aug 2024 17:08:22 +0200 Subject: [PATCH 0237/2181] wayland/compositor: drop pending buffer ref if synchronous fixes https://github.com/hyprwm/hyprpicker/issues/85 --- src/protocols/core/Compositor.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/protocols/core/Compositor.cpp b/src/protocols/core/Compositor.cpp index b0111032..656433d3 100644 --- a/src/protocols/core/Compositor.cpp +++ b/src/protocols/core/Compositor.cpp @@ -448,8 +448,10 @@ void CWLSurfaceResource::commitPendingState() { // release the buffer if it's synchronous as update() has done everything thats needed // so we can let the app know we're done. - if (current.buffer->buffer->isSynchronous()) + if (current.buffer->buffer->isSynchronous()) { dropCurrentBuffer(); + dropPendingBuffer(); // pending atm is just a copied ref of the current, drop it too to send a release + } } // TODO: we should _accumulate_ and not replace above if sync From fa6ee513678e6e1cfdc575a421c1e0ddf4608994 Mon Sep 17 00:00:00 2001 From: Ikalco <73481042+ikalco@users.noreply.github.com> Date: Wed, 7 Aug 2024 02:44:20 -0500 Subject: [PATCH 0238/2181] input: fix leds on kb creation (#7206) --- src/managers/input/InputManager.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/managers/input/InputManager.cpp b/src/managers/input/InputManager.cpp index 8c38893f..c502cb0d 100644 --- a/src/managers/input/InputManager.cpp +++ b/src/managers/input/InputManager.cpp @@ -919,6 +919,8 @@ void CInputManager::setupKeyboard(SP keeb) { applyConfigToKeyboard(keeb); g_pSeatManager->setKeyboard(keeb); + + keeb->updateLEDs(); } void CInputManager::setKeyboardLayout() { From 5b736a4a661220ab07abc3afda6cdb8774095bfb Mon Sep 17 00:00:00 2001 From: Tom Englund Date: Wed, 7 Aug 2024 13:22:01 +0200 Subject: [PATCH 0239/2181] debug: dont manually unlock the lock_guard (#7210) when lock_guard goes out of scope it RAII itself and calls unlock. causes crashes on freebsd/libc++ and double unlocking a mutex is UB. --- src/debug/Log.hpp | 1 - 1 file changed, 1 deletion(-) diff --git a/src/debug/Log.hpp b/src/debug/Log.hpp index 617f451a..4fc8ed5b 100644 --- a/src/debug/Log.hpp +++ b/src/debug/Log.hpp @@ -72,6 +72,5 @@ namespace Debug { logMsg += std::vformat(fmt.get(), std::make_format_args(args...)); log(level, logMsg); - logMutex.unlock(); } }; From a05da63d853fc750bae29228d924b346243afaec Mon Sep 17 00:00:00 2001 From: Ikalco <73481042+ikalco@users.noreply.github.com> Date: Wed, 7 Aug 2024 06:22:19 -0500 Subject: [PATCH 0240/2181] keybinds: fix NoSymbol keybinds (#7199) --- src/managers/KeybindManager.cpp | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/src/managers/KeybindManager.cpp b/src/managers/KeybindManager.cpp index 08c6998d..c7b93730 100644 --- a/src/managers/KeybindManager.cpp +++ b/src/managers/KeybindManager.cpp @@ -639,18 +639,17 @@ bool CKeybindManager::handleKeybinds(const uint32_t modmask, const SPressedKeyWi if (found || key.submapAtPress != m_szCurrentSelectedSubmap) continue; } else { - // in this case, we only have the keysym to go off. - // if the keysym failed resolving, we can't do anything. It's likely missing - // from the keymap. - if (key.keysym == 0) - return false; + // in this case, we only have the keysym to go off of for this keybind, and it's invalid + // since there might be something like keycode to match with other keybinds, try the next + if (key.keysym == XKB_KEY_NoSymbol) + continue; // oMg such performance hit!!11! // this little maneouver is gonna cost us 4µs const auto KBKEY = xkb_keysym_from_name(k.key.c_str(), XKB_KEYSYM_NO_FLAGS); const auto KBKEYLOWER = xkb_keysym_from_name(k.key.c_str(), XKB_KEYSYM_CASE_INSENSITIVE); - if (KBKEY == 0 && KBKEYLOWER == 0) { + if (KBKEY == XKB_KEY_NoSymbol && KBKEYLOWER == XKB_KEY_NoSymbol) { // Keysym failed to resolve from the key name of the currently iterated bind. // This happens for names such as `switch:off:Lid Switch` as well as some keys // (such as yen and ro). From 3d82d199f0ec6d8bf6252ed0795b4d883ade84ff Mon Sep 17 00:00:00 2001 From: Tom Englund Date: Wed, 7 Aug 2024 13:23:00 +0200 Subject: [PATCH 0241/2181] cursormgr: implement inheriting themes for xcursor (#7197) * cursormgr: reduce duplicated code add a few functions such as setCursorBuffer and setAnimationTimer to reduce duplicated code and also avoid future mishaps of forgetting to clear buffer or disarm timer. and generally reduce spaghetti even tho pasta can be delicious. * xcursormgr: implent inherited themes implent index.theme parsing and inherited themes. * cursormgr: ensure a fallback xcursor exist ensure a xcursor fallback exist otherwise it wont load the proper theme if we at launch have hyprcursor enabled and then set it to false in config and reload. also use the env var when using hyprctl setcursor incase its empty. --- src/managers/CursorManager.cpp | 343 ++++++++++++++++---------------- src/managers/CursorManager.hpp | 54 +++-- src/managers/XCursorManager.cpp | 90 +++++++-- src/managers/XCursorManager.hpp | 21 +- 4 files changed, 285 insertions(+), 223 deletions(-) diff --git a/src/managers/CursorManager.cpp b/src/managers/CursorManager.cpp index 9b574901..3f3a25f6 100644 --- a/src/managers/CursorManager.cpp +++ b/src/managers/CursorManager.cpp @@ -17,11 +17,61 @@ static void hcLogger(enum eHyprcursorLogLevel level, char* message) { Debug::log(NONE, "[hc] {}", message); } -CCursorManager::CCursorManager() { - m_pHyprcursor = std::make_unique(m_szTheme.empty() ? nullptr : m_szTheme.c_str(), hcLogger); - m_pXcursor = std::make_unique(); +CCursorBuffer::CCursorBuffer(cairo_surface_t* surf, const Vector2D& size_, const Vector2D& hot_) : hotspot(hot_) { + surface = surf; + size = size_; + stride = cairo_image_surface_get_stride(surf); +} - if (m_pHyprcursor->valid()) { +CCursorBuffer::CCursorBuffer(uint8_t* pixelData_, const Vector2D& size_, const Vector2D& hot_) : hotspot(hot_) { + pixelData = pixelData_; + size = size_; + stride = 4 * size_.x; +} + +Aquamarine::eBufferCapability CCursorBuffer::caps() { + return Aquamarine::eBufferCapability::BUFFER_CAPABILITY_DATAPTR; +} + +Aquamarine::eBufferType CCursorBuffer::type() { + return Aquamarine::eBufferType::BUFFER_TYPE_SHM; +} + +void CCursorBuffer::update(const Hyprutils::Math::CRegion& damage) { + ; +} + +bool CCursorBuffer::isSynchronous() { + return true; +} + +bool CCursorBuffer::good() { + return true; +} + +Aquamarine::SSHMAttrs CCursorBuffer::shm() { + Aquamarine::SSHMAttrs attrs; + attrs.success = true; + attrs.format = DRM_FORMAT_ARGB8888; + attrs.size = size; + attrs.stride = stride; + return attrs; +} + +std::tuple CCursorBuffer::beginDataPtr(uint32_t flags) { + return {pixelData ? pixelData : cairo_image_surface_get_data(surface), DRM_FORMAT_ARGB8888, stride}; +} + +void CCursorBuffer::endDataPtr() { + ; +} + +CCursorManager::CCursorManager() { + m_pHyprcursor = std::make_unique(m_szTheme.empty() ? nullptr : m_szTheme.c_str(), hcLogger); + m_pXcursor = std::make_unique(); + static auto PUSEHYPRCURSOR = CConfigValue("cursor:enable_hyprcursor"); + + if (m_pHyprcursor->valid() && *PUSEHYPRCURSOR) { // find default size. First, HYPRCURSOR_SIZE then default to 24 auto const* SIZE = getenv("HYPRCURSOR_SIZE"); if (SIZE) { @@ -48,10 +98,12 @@ CCursorManager::CCursorManager() { Debug::log(WARN, "XCURSOR_SIZE size not set, defaulting to size 24"); m_iSize = 24; } - - m_pXcursor->loadTheme(getenv("XCURSOR_THEME") ? getenv("XCURSOR_THEME") : "default", m_iSize * std::ceil(m_fCursorScale)); } + // since we fallback to xcursor always load it on startup. otherwise we end up with a empty theme if hyprcursor is enabled in the config + // and then later is disabled. + m_pXcursor->loadTheme(getenv("XCURSOR_THEME") ? getenv("XCURSOR_THEME") : "default", m_iSize * std::ceil(m_fCursorScale)); + m_pAnimationTimer = makeShared(std::nullopt, cursorAnimTimer, this); g_pEventLoopManager->addTimer(m_pAnimationTimer); @@ -65,63 +117,9 @@ CCursorManager::~CCursorManager() { g_pEventLoopManager->removeTimer(m_pAnimationTimer); m_pAnimationTimer.reset(); } -} -void CCursorManager::dropBufferRef(CCursorManager::CCursorBuffer* ref) { - std::erase_if(m_vCursorBuffers, [ref](const auto& buf) { return buf.get() == ref; }); -} - -CCursorManager::CCursorBuffer::CCursorBuffer(cairo_surface_t* surf, const Vector2D& size_, const Vector2D& hot_) : hotspot(hot_) { - surface = surf; - size = size_; - stride = cairo_image_surface_get_stride(surf); -} - -CCursorManager::CCursorBuffer::CCursorBuffer(uint8_t* pixelData_, const Vector2D& size_, const Vector2D& hot_) : hotspot(hot_) { - pixelData = pixelData_; - size = size_; - stride = 4 * size_.x; -} - -CCursorManager::CCursorBuffer::~CCursorBuffer() { - ; -} - -Aquamarine::eBufferCapability CCursorManager::CCursorBuffer::caps() { - return Aquamarine::eBufferCapability::BUFFER_CAPABILITY_DATAPTR; -} - -Aquamarine::eBufferType CCursorManager::CCursorBuffer::type() { - return Aquamarine::eBufferType::BUFFER_TYPE_SHM; -} - -void CCursorManager::CCursorBuffer::update(const Hyprutils::Math::CRegion& damage) { - ; -} - -bool CCursorManager::CCursorBuffer::isSynchronous() { - return true; -} - -bool CCursorManager::CCursorBuffer::good() { - return true; -} - -Aquamarine::SSHMAttrs CCursorManager::CCursorBuffer::shm() { - Aquamarine::SSHMAttrs attrs; - attrs.success = true; - attrs.format = DRM_FORMAT_ARGB8888; - attrs.size = size; - attrs.stride = stride; - return attrs; -} - -std::tuple CCursorManager::CCursorBuffer::beginDataPtr(uint32_t flags) { - return {pixelData ? pixelData : cairo_image_surface_get_data(surface), DRM_FORMAT_ARGB8888, stride}; -} - -void CCursorManager::CCursorBuffer::endDataPtr() { - ; + if (m_pHyprcursor->valid() && m_sCurrentStyleInfo.size > 0) + m_pHyprcursor->cursorSurfaceStyleDone(m_sCurrentStyleInfo); } SP CCursorManager::getCursorBuffer() { @@ -137,91 +135,101 @@ void CCursorManager::setCursorSurface(SP surf, const Vector2D& hotsp m_bOurBufferConnected = false; } -void CCursorManager::setXCursor(const std::string& name) { - float scale = std::ceil(m_fCursorScale); - - auto xcursor = m_pXcursor->getShape(name, m_iSize * scale); - auto& icon = xcursor->images.front(); - - m_vCursorBuffers.emplace_back(makeShared((uint8_t*)icon.pixels.data(), icon.size, icon.hotspot)); - - g_pPointerManager->setCursorBuffer(getCursorBuffer(), icon.hotspot / scale, scale); +void CCursorManager::setCursorBuffer(SP buf, const Vector2D& hotspot, const float& scale) { + m_vCursorBuffers.emplace_back(buf); + g_pPointerManager->setCursorBuffer(getCursorBuffer(), hotspot, scale); if (m_vCursorBuffers.size() > 1) - dropBufferRef(m_vCursorBuffers.at(0).get()); + std::erase_if(m_vCursorBuffers, [this](const auto& buf) { return buf.get() == m_vCursorBuffers.front().get(); }); - m_currentXcursor = xcursor; m_bOurBufferConnected = true; +} - if (m_currentXcursor->images.size() > 1) { - // animated - m_pAnimationTimer->updateTimeout(std::chrono::milliseconds(m_currentXcursor->images[0].delay)); - m_iCurrentAnimationFrame = 0; +void CCursorManager::setAnimationTimer(const int& frame, const int& delay) { + if (delay > 0) { + // arm + m_pAnimationTimer->updateTimeout(std::chrono::milliseconds(delay)); } else { // disarm m_pAnimationTimer->updateTimeout(std::nullopt); } + + m_iCurrentAnimationFrame = frame; } void CCursorManager::setCursorFromName(const std::string& name) { static auto PUSEHYPRCURSOR = CConfigValue("cursor:enable_hyprcursor"); - if (!m_pHyprcursor->valid() || !*PUSEHYPRCURSOR) { - setXCursor(name); - return; - } + auto setXCursor = [this](auto const& name) { + float scale = std::ceil(m_fCursorScale); - m_sCurrentCursorShapeData = m_pHyprcursor->getShape(name.c_str(), m_sCurrentStyleInfo); + auto xcursor = m_pXcursor->getShape(name, m_iSize * scale); + auto& icon = xcursor->images.front(); + auto buf = makeShared((uint8_t*)icon.pixels.data(), icon.size, icon.hotspot); + setCursorBuffer(buf, icon.hotspot / scale, scale); - if (m_sCurrentCursorShapeData.images.size() < 1) { - // try with '_' first (old hc, etc) - std::string newName = name; - std::replace(newName.begin(), newName.end(), '-', '_'); + m_currentXcursor = xcursor; - m_sCurrentCursorShapeData = m_pHyprcursor->getShape(newName.c_str(), m_sCurrentStyleInfo); - } + int delay = 0; + int frame = 0; + if (m_currentXcursor->images.size() > 1) + delay = m_currentXcursor->images[frame].delay; - if (m_sCurrentCursorShapeData.images.size() < 1) { - // fallback to a default if available - constexpr const std::array fallbackShapes = {"default", "left_ptr", "left-ptr"}; + setAnimationTimer(frame, delay); + }; - for (auto& s : fallbackShapes) { - m_sCurrentCursorShapeData = m_pHyprcursor->getShape(s, m_sCurrentStyleInfo); + auto setHyprCursor = [this](auto const& name) { + m_sCurrentCursorShapeData = m_pHyprcursor->getShape(name.c_str(), m_sCurrentStyleInfo); - if (m_sCurrentCursorShapeData.images.size() > 0) - break; + if (m_sCurrentCursorShapeData.images.size() < 1) { + // try with '_' first (old hc, etc) + std::string newName = name; + std::replace(newName.begin(), newName.end(), '-', '_'); + + m_sCurrentCursorShapeData = m_pHyprcursor->getShape(newName.c_str(), m_sCurrentStyleInfo); } if (m_sCurrentCursorShapeData.images.size() < 1) { - Debug::log(ERR, "BUG THIS: No fallback found for a cursor in setCursorFromName"); - setXCursor(name); - return; + // fallback to a default if available + constexpr const std::array fallbackShapes = {"default", "left_ptr", "left-ptr"}; + + for (auto& s : fallbackShapes) { + m_sCurrentCursorShapeData = m_pHyprcursor->getShape(s, m_sCurrentStyleInfo); + + if (m_sCurrentCursorShapeData.images.size() > 0) + break; + } + + if (m_sCurrentCursorShapeData.images.size() < 1) { + Debug::log(ERR, "BUG THIS: No fallback found for a cursor in setCursorFromName"); + return false; + } } - } - m_vCursorBuffers.emplace_back(makeShared(m_sCurrentCursorShapeData.images[0].surface, - Vector2D{m_sCurrentCursorShapeData.images[0].size, m_sCurrentCursorShapeData.images[0].size}, - Vector2D{m_sCurrentCursorShapeData.images[0].hotspotX, m_sCurrentCursorShapeData.images[0].hotspotY})); + auto buf = + makeShared(m_sCurrentCursorShapeData.images[0].surface, Vector2D{m_sCurrentCursorShapeData.images[0].size, m_sCurrentCursorShapeData.images[0].size}, + Vector2D{m_sCurrentCursorShapeData.images[0].hotspotX, m_sCurrentCursorShapeData.images[0].hotspotY}); + auto hotspot = Vector2D{m_sCurrentCursorShapeData.images[0].hotspotX, m_sCurrentCursorShapeData.images[0].hotspotY} / m_fCursorScale; + setCursorBuffer(buf, hotspot, m_fCursorScale); - g_pPointerManager->setCursorBuffer(getCursorBuffer(), Vector2D{m_sCurrentCursorShapeData.images[0].hotspotX, m_sCurrentCursorShapeData.images[0].hotspotY} / m_fCursorScale, - m_fCursorScale); - if (m_vCursorBuffers.size() > 1) - dropBufferRef(m_vCursorBuffers.at(0).get()); + int delay = 0; + int frame = 0; + if (m_sCurrentCursorShapeData.images.size() > 1) + delay = m_sCurrentCursorShapeData.images[frame].delay; - m_bOurBufferConnected = true; + setAnimationTimer(frame, delay); + return true; + }; - if (m_sCurrentCursorShapeData.images.size() > 1) { - // animated - m_pAnimationTimer->updateTimeout(std::chrono::milliseconds(m_sCurrentCursorShapeData.images[0].delay)); - m_iCurrentAnimationFrame = 0; - } else { - // disarm - m_pAnimationTimer->updateTimeout(std::nullopt); - } + if (!m_pHyprcursor->valid() || !*PUSEHYPRCURSOR || !setHyprCursor(name)) + setXCursor(name); } void CCursorManager::tickAnimatedCursor() { - if (!m_pHyprcursor->valid() && m_currentXcursor->images.size() > 1 && m_bOurBufferConnected) { + if (!m_bOurBufferConnected) + return; + + if (!m_pHyprcursor->valid() && m_currentXcursor->images.size() > 1) { m_iCurrentAnimationFrame++; if ((size_t)m_iCurrentAnimationFrame >= m_currentXcursor->images.size()) @@ -229,39 +237,24 @@ void CCursorManager::tickAnimatedCursor() { float scale = std::ceil(m_fCursorScale); auto& icon = m_currentXcursor->images.at(m_iCurrentAnimationFrame); - m_vCursorBuffers.emplace_back(makeShared((uint8_t*)icon.pixels.data(), icon.size, icon.hotspot)); + auto buf = makeShared((uint8_t*)icon.pixels.data(), icon.size, icon.hotspot); + setCursorBuffer(buf, icon.hotspot / scale, scale); + setAnimationTimer(m_iCurrentAnimationFrame, m_currentXcursor->images[m_iCurrentAnimationFrame].delay); + } else if (m_sCurrentCursorShapeData.images.size() > 1) { + m_iCurrentAnimationFrame++; - g_pPointerManager->setCursorBuffer(getCursorBuffer(), icon.hotspot / scale, scale); + if ((size_t)m_iCurrentAnimationFrame >= m_sCurrentCursorShapeData.images.size()) + m_iCurrentAnimationFrame = 0; - if (m_vCursorBuffers.size() > 1) - dropBufferRef(m_vCursorBuffers.at(0).get()); - - m_pAnimationTimer->updateTimeout(std::chrono::milliseconds(m_currentXcursor->images[m_iCurrentAnimationFrame].delay)); - - return; + auto hotspot = + Vector2D{m_sCurrentCursorShapeData.images[m_iCurrentAnimationFrame].hotspotX, m_sCurrentCursorShapeData.images[m_iCurrentAnimationFrame].hotspotY} / m_fCursorScale; + auto buf = makeShared( + m_sCurrentCursorShapeData.images[m_iCurrentAnimationFrame].surface, + Vector2D{m_sCurrentCursorShapeData.images[m_iCurrentAnimationFrame].size, m_sCurrentCursorShapeData.images[m_iCurrentAnimationFrame].size}, + Vector2D{m_sCurrentCursorShapeData.images[m_iCurrentAnimationFrame].hotspotX, m_sCurrentCursorShapeData.images[m_iCurrentAnimationFrame].hotspotY}); + setCursorBuffer(buf, hotspot, m_fCursorScale); + setAnimationTimer(m_iCurrentAnimationFrame, m_sCurrentCursorShapeData.images[m_iCurrentAnimationFrame].delay); } - - if (m_sCurrentCursorShapeData.images.size() < 2 || !m_bOurBufferConnected) - return; - - m_iCurrentAnimationFrame++; - if ((size_t)m_iCurrentAnimationFrame >= m_sCurrentCursorShapeData.images.size()) - m_iCurrentAnimationFrame = 0; - - m_vCursorBuffers.emplace_back(makeShared( - m_sCurrentCursorShapeData.images[m_iCurrentAnimationFrame].surface, - Vector2D{m_sCurrentCursorShapeData.images[m_iCurrentAnimationFrame].size, m_sCurrentCursorShapeData.images[m_iCurrentAnimationFrame].size}, - Vector2D{m_sCurrentCursorShapeData.images[m_iCurrentAnimationFrame].hotspotX, m_sCurrentCursorShapeData.images[m_iCurrentAnimationFrame].hotspotY})); - - g_pPointerManager->setCursorBuffer( - getCursorBuffer(), - Vector2D{m_sCurrentCursorShapeData.images[m_iCurrentAnimationFrame].hotspotX, m_sCurrentCursorShapeData.images[m_iCurrentAnimationFrame].hotspotY} / m_fCursorScale, - m_fCursorScale); - - if (m_vCursorBuffers.size() > 1) - dropBufferRef(m_vCursorBuffers.at(0).get()); - - m_pAnimationTimer->updateTimeout(std::chrono::milliseconds(m_sCurrentCursorShapeData.images[m_iCurrentAnimationFrame].delay)); } SCursorImageData CCursorManager::dataFor(const std::string& name) { @@ -278,11 +271,12 @@ SCursorImageData CCursorManager::dataFor(const std::string& name) { } void CCursorManager::setXWaylandCursor() { - const auto CURSOR = dataFor("left_ptr"); - if (CURSOR.surface) { + static auto PUSEHYPRCURSOR = CConfigValue("cursor:enable_hyprcursor"); + const auto CURSOR = dataFor("left_ptr"); + if (CURSOR.surface && *PUSEHYPRCURSOR) g_pXWayland->setCursor(cairo_image_surface_get_data(CURSOR.surface), cairo_image_surface_get_stride(CURSOR.surface), {CURSOR.size, CURSOR.size}, {CURSOR.hotspotX, CURSOR.hotspotY}); - } else { + else { auto xcursor = m_pXcursor->getShape("left_ptr", m_iSize * std::ceil(m_fCursorScale)); auto& icon = xcursor->images.front(); @@ -291,21 +285,25 @@ void CCursorManager::setXWaylandCursor() { } void CCursorManager::updateTheme() { - float highestScale = 1.0; + static auto PUSEHYPRCURSOR = CConfigValue("cursor:enable_hyprcursor"); + float highestScale = 1.0; for (auto& m : g_pCompositor->m_vMonitors) { if (m->scale > highestScale) highestScale = m->scale; } - if (m_sCurrentStyleInfo.size && m_pHyprcursor->valid()) - m_pHyprcursor->cursorSurfaceStyleDone(m_sCurrentStyleInfo); + m_fCursorScale = highestScale; - m_sCurrentStyleInfo.size = std::round(m_iSize * highestScale); - m_fCursorScale = highestScale; + if (*PUSEHYPRCURSOR) { + if (m_sCurrentStyleInfo.size > 0 && m_pHyprcursor->valid()) + m_pHyprcursor->cursorSurfaceStyleDone(m_sCurrentStyleInfo); - if (m_pHyprcursor->valid()) - m_pHyprcursor->loadThemeStyle(m_sCurrentStyleInfo); + m_sCurrentStyleInfo.size = std::round(m_iSize * highestScale); + + if (m_pHyprcursor->valid()) + m_pHyprcursor->loadThemeStyle(m_sCurrentStyleInfo); + } setCursorFromName("left_ptr"); @@ -316,24 +314,27 @@ void CCursorManager::updateTheme() { } bool CCursorManager::changeTheme(const std::string& name, const int size) { - auto options = Hyprcursor::SManagerOptions(); - options.logFn = hcLogger; - options.allowDefaultFallback = false; + static auto PUSEHYPRCURSOR = CConfigValue("cursor:enable_hyprcursor"); + m_szTheme = name.empty() ? "" : name; + m_iSize = size <= 0 ? 24 : size; + auto xcursor_theme = getenv("XCURSOR_THEME") ? getenv("XCURSOR_THEME") : "default"; - m_pHyprcursor = std::make_unique(name.empty() ? "" : name.c_str(), options); - if (m_pHyprcursor->valid()) { - m_szTheme = name; - m_iSize = size; - updateTheme(); - return true; - } + if (*PUSEHYPRCURSOR) { + auto options = Hyprcursor::SManagerOptions(); + options.logFn = hcLogger; + options.allowDefaultFallback = false; + m_szTheme = name.empty() ? "" : name; + m_iSize = size; - Debug::log(ERR, "Hyprcursor failed loading theme \"{}\", falling back to XCursor.", name); + m_pHyprcursor = std::make_unique(m_szTheme.empty() ? nullptr : m_szTheme.c_str(), options); + if (!m_pHyprcursor->valid()) { + Debug::log(ERR, "Hyprcursor failed loading theme \"{}\", falling back to XCursor.", m_szTheme); + m_pXcursor->loadTheme(m_szTheme.empty() ? xcursor_theme : m_szTheme, m_iSize); + } + } else + m_pXcursor->loadTheme(m_szTheme.empty() ? xcursor_theme : m_szTheme, m_iSize); - m_pXcursor->loadTheme(name, size); - - m_szTheme = name; - m_iSize = size; updateTheme(); + return true; } \ No newline at end of file diff --git a/src/managers/CursorManager.hpp b/src/managers/CursorManager.hpp index a114b6c2..ceb4816b 100644 --- a/src/managers/CursorManager.hpp +++ b/src/managers/CursorManager.hpp @@ -15,6 +15,28 @@ class CWLSurface; AQUAMARINE_FORWARD(IBuffer); +class CCursorBuffer : public Aquamarine::IBuffer { + public: + CCursorBuffer(cairo_surface_t* surf, const Vector2D& size, const Vector2D& hotspot); + CCursorBuffer(uint8_t* pixelData, const Vector2D& size, const Vector2D& hotspot); + ~CCursorBuffer() = default; + + virtual Aquamarine::eBufferCapability caps(); + virtual Aquamarine::eBufferType type(); + virtual void update(const Hyprutils::Math::CRegion& damage); + virtual bool isSynchronous(); // whether the updates to this buffer are synchronous, aka happen over cpu + virtual bool good(); + virtual Aquamarine::SSHMAttrs shm(); + virtual std::tuple beginDataPtr(uint32_t flags); + virtual void endDataPtr(); + + private: + Vector2D hotspot; + cairo_surface_t* surface = nullptr; + uint8_t* pixelData = nullptr; + size_t stride = 0; +}; + class CCursorManager { public: CCursorManager(); @@ -24,7 +46,8 @@ class CCursorManager { void setCursorFromName(const std::string& name); void setCursorSurface(SP surf, const Vector2D& hotspot); - void setXCursor(const std::string& name); + void setCursorBuffer(SP buf, const Vector2D& hotspot, const float& scale); + void setAnimationTimer(const int& frame, const int& delay); bool changeTheme(const std::string& name, const int size); void updateTheme(); @@ -33,35 +56,8 @@ class CCursorManager { void tickAnimatedCursor(); - class CCursorBuffer : public Aquamarine::IBuffer { - public: - CCursorBuffer(cairo_surface_t* surf, const Vector2D& size, const Vector2D& hotspot); - CCursorBuffer(uint8_t* pixelData, const Vector2D& size, const Vector2D& hotspot); - ~CCursorBuffer(); - - virtual Aquamarine::eBufferCapability caps(); - virtual Aquamarine::eBufferType type(); - virtual void update(const Hyprutils::Math::CRegion& damage); - virtual bool isSynchronous(); // whether the updates to this buffer are synchronous, aka happen over cpu - virtual bool good(); - virtual Aquamarine::SSHMAttrs shm(); - virtual std::tuple beginDataPtr(uint32_t flags); - virtual void endDataPtr(); - - private: - Vector2D hotspot; - cairo_surface_t* surface = nullptr; - uint8_t* pixelData = nullptr; - size_t stride = 0; - - friend class CCursorManager; - }; - - void dropBufferRef(CCursorBuffer* ref); - - bool m_bOurBufferConnected = false; - private: + bool m_bOurBufferConnected = false; std::vector> m_vCursorBuffers; std::unique_ptr m_pHyprcursor; diff --git a/src/managers/XCursorManager.cpp b/src/managers/XCursorManager.cpp index b3f33086..76c908db 100644 --- a/src/managers/XCursorManager.cpp +++ b/src/managers/XCursorManager.cpp @@ -135,6 +135,11 @@ void CXCursorManager::loadTheme(std::string const& name, int size) { continue; } + if (std::any_of(cursors.begin(), cursors.end(), [&shape](auto const& dp) { return dp->shape == shape; })) { + Debug::log(LOG, "XCursor already has a shape {} loaded, skipping", shape); + continue; + } + auto cursor = makeShared(); cursor->images = it->get()->images; cursor->shape = shape; @@ -180,11 +185,10 @@ SP CXCursorManager::createCursor(std::string const& shape, XcursorIma return xcursor; } -std::vector CXCursorManager::themePaths(std::string const& theme) { - auto const* path = XcursorLibraryPath(); - std::vector paths; +std::unordered_set CXCursorManager::themePaths(std::string const& theme) { + auto const* path = XcursorLibraryPath(); - auto expandTilde = [](std::string const& path) { + auto expandTilde = [](std::string const& path) { if (!path.empty() && path[0] == '~') { const char* home = std::getenv("HOME"); if (home) @@ -193,15 +197,76 @@ std::vector CXCursorManager::themePaths(std::string const& theme) { return path; }; - if (path) { + auto getInheritThemes = [](std::string const& indexTheme) { + std::ifstream infile(indexTheme); + std::string line; + std::vector themes; + + Debug::log(LOG, "XCursor parsing index.theme {}", indexTheme); + + while (std::getline(infile, line)) { + // Trim leading and trailing whitespace + line.erase(0, line.find_first_not_of(" \t\n\r")); + line.erase(line.find_last_not_of(" \t\n\r") + 1); + + if (line.rfind("Inherits", 0) == 0) { // Check if line starts with "Inherits" + std::string inheritThemes = line.substr(8); // Extract the part after "Inherits" + // Remove leading whitespace from inheritThemes and = + inheritThemes.erase(0, inheritThemes.find_first_not_of(" \t\n\r")); + inheritThemes.erase(0, 1); + inheritThemes.erase(0, inheritThemes.find_first_not_of(" \t\n\r")); + + std::stringstream inheritStream(inheritThemes); + std::string inheritTheme; + while (std::getline(inheritStream, inheritTheme, ',')) { + // Trim leading and trailing whitespace from each theme + inheritTheme.erase(0, inheritTheme.find_first_not_of(" \t\n\r")); + inheritTheme.erase(inheritTheme.find_last_not_of(" \t\n\r") + 1); + themes.push_back(inheritTheme); + } + } + } + infile.close(); + + return themes; + }; + + std::unordered_set paths; + std::unordered_set inherits; + + auto scanTheme = [&path, &paths, &expandTilde, &inherits, &getInheritThemes](auto const& t) { std::stringstream ss(path); - std::string item; + std::string line; - while (std::getline(ss, item, ':')) { - auto p = expandTilde(item + "/" + theme + "/cursors"); + Debug::log(LOG, "XCursor scanning theme {}", t); - if (std::filesystem::exists(p) && std::filesystem::is_directory(p)) - paths.push_back(p); + while (std::getline(ss, line, ':')) { + auto p = expandTilde(line + "/" + t + "/cursors"); + if (std::filesystem::exists(p) && std::filesystem::is_directory(p)) { + Debug::log(LOG, "XCursor using theme path {}", p); + paths.insert(p); + } + + auto inherit = expandTilde(line + "/" + t + "/index.theme"); + if (std::filesystem::exists(inherit) && std::filesystem::is_regular_file(inherit)) { + auto inheritThemes = getInheritThemes(inherit); + for (auto const& i : inheritThemes) { + Debug::log(LOG, "XCursor theme {} inherits {}", t, i); + inherits.insert(i); + } + } + } + }; + + if (path) { + scanTheme(theme); + while (!inherits.empty()) { + auto oldInherits = inherits; + for (auto& i : oldInherits) + scanTheme(i); + + if (oldInherits.size() == inherits.size()) + break; } } @@ -402,14 +467,13 @@ std::vector> CXCursorManager::loadStandardCursors(std::string cons std::vector> CXCursorManager::loadAllFromDir(std::string const& path, int size) { std::vector> newCursors; - std::string full; if (std::filesystem::exists(path) && std::filesystem::is_directory(path)) { for (const auto& entry : std::filesystem::directory_iterator(path)) { if (!entry.is_regular_file() && !entry.is_symlink()) continue; - std::string full = entry.path().string(); + auto const& full = entry.path().string(); using PcloseType = int (*)(FILE*); const std::unique_ptr f(fopen(full.c_str(), "r"), static_cast(fclose)); @@ -428,7 +492,7 @@ std::vector> CXCursorManager::loadAllFromDir(std::string const& pa } } - std::string shape = entry.path().filename().string(); + auto const& shape = entry.path().filename().string(); auto cursor = createCursor(shape, xImages); newCursors.emplace_back(cursor); diff --git a/src/managers/XCursorManager.hpp b/src/managers/XCursorManager.hpp index 9ced076f..20637055 100644 --- a/src/managers/XCursorManager.hpp +++ b/src/managers/XCursorManager.hpp @@ -1,6 +1,7 @@ #pragma once #include #include +#include #include #include #include @@ -32,15 +33,15 @@ class CXCursorManager { SP getShape(std::string const& shape, int size); private: - SP createCursor(std::string const& shape, XcursorImages* xImages); - std::vector themePaths(std::string const& theme); - std::string getLegacyShapeName(std::string const& shape); - std::vector> loadStandardCursors(std::string const& name, int size); - std::vector> loadAllFromDir(std::string const& path, int size); + SP createCursor(std::string const& shape, XcursorImages* xImages); + std::unordered_set themePaths(std::string const& theme); + std::string getLegacyShapeName(std::string const& shape); + std::vector> loadStandardCursors(std::string const& name, int size); + std::vector> loadAllFromDir(std::string const& path, int size); - int lastLoadSize = 0; - std::string themeName = ""; - SP defaultCursor; - SP hyprCursor; - std::vector> cursors; + int lastLoadSize = 0; + std::string themeName = ""; + SP defaultCursor; + SP hyprCursor; + std::vector> cursors; }; \ No newline at end of file From b2717cf7fd86774b450b58f6263291e277553e63 Mon Sep 17 00:00:00 2001 From: outfoxxed Date: Wed, 7 Aug 2024 04:26:09 -0700 Subject: [PATCH 0242/2181] xdg-shell: make xdg-positioner flip target greatest available space (#7209) When both flip directions use more space than is available, pick the direction that has more space available instead of just the opposite of what was initially requested. --- src/protocols/XDGShell.cpp | 93 +++++++++++++++++++++++++------------- 1 file changed, 62 insertions(+), 31 deletions(-) diff --git a/src/protocols/XDGShell.cpp b/src/protocols/XDGShell.cpp index 4aa5d373..aea23329 100644 --- a/src/protocols/XDGShell.cpp +++ b/src/protocols/XDGShell.cpp @@ -531,29 +531,66 @@ CBox CXDGPositionerRules::getPosition(CBox constraint, const Vector2D& parentCoo auto anchorRect = state.anchorRect.copy().translate(parentCoord); - auto width = state.requestedSize.x; - auto height = state.requestedSize.y; + auto width = state.requestedSize.x; + auto height = state.requestedSize.y; + auto gravity = state.gravity; auto anchorX = state.anchor.left() ? anchorRect.x : state.anchor.right() ? anchorRect.extent().x : anchorRect.middle().x; auto anchorY = state.anchor.top() ? anchorRect.y : state.anchor.bottom() ? anchorRect.extent().y : anchorRect.middle().y; - auto calcEffectiveX = [&]() { return state.gravity.left() ? anchorX - width : state.gravity.right() ? anchorX : anchorX - width / 2; }; - auto calcEffectiveY = [&]() { return state.gravity.top() ? anchorY - height : state.gravity.bottom() ? anchorY : anchorY - height / 2; }; + auto calcEffectiveX = [&](CEdges anchorGravity, double anchorX) { return anchorGravity.left() ? anchorX - width : anchorGravity.right() ? anchorX : anchorX - width / 2; }; + auto calcEffectiveY = [&](CEdges anchorGravity, double anchorY) { return anchorGravity.top() ? anchorY - height : anchorGravity.bottom() ? anchorY : anchorY - height / 2; }; - auto effectiveX = calcEffectiveX(); - auto effectiveY = calcEffectiveY(); + auto calcRemainingWidth = [&](double effectiveX) { + auto width = state.requestedSize.x; + if (effectiveX < constraint.x) { + auto diff = constraint.x - effectiveX; + effectiveX = constraint.x; + width -= diff; + } + + auto effectiveX2 = effectiveX + width; + if (effectiveX2 > constraint.extent().x) + width -= effectiveX2 - constraint.extent().x; + + return std::make_pair(effectiveX, width); + }; + + auto calcRemainingHeight = [&](double effectiveY) { + auto height = state.requestedSize.y; + if (effectiveY < constraint.y) { + auto diff = constraint.y - effectiveY; + effectiveY = constraint.y; + height -= diff; + } + + auto effectiveY2 = effectiveY + height; + if (effectiveY2 > constraint.extent().y) + height -= effectiveY2 - constraint.extent().y; + + return std::make_pair(effectiveY, height); + }; + + auto effectiveX = calcEffectiveX(gravity, anchorX); + auto effectiveY = calcEffectiveY(gravity, anchorY); // Note: the usage of offset is a guess which maintains compatibility with other compositors that were tested. // It considers the offset when deciding whether or not to flip but does not actually flip the offset, instead // applying it after the flip step. if (state.constraintAdjustment & XDG_POSITIONER_CONSTRAINT_ADJUSTMENT_FLIP_X) { - auto flip = (state.gravity.left() && effectiveX + state.offset.x < constraint.x) || (state.gravity.right() && effectiveX + state.offset.x + width > constraint.extent().x); + auto flip = (gravity.left() && effectiveX + state.offset.x < constraint.x) || (gravity.right() && effectiveX + state.offset.x + width > constraint.extent().x); if (flip) { - state.gravity ^= CEdges::LEFT | CEdges::RIGHT; - anchorX = state.anchor.left() ? anchorRect.extent().x : state.anchor.right() ? anchorRect.x : anchorX; - effectiveX = calcEffectiveX(); + auto newGravity = gravity ^ (CEdges::LEFT | CEdges::RIGHT); + auto newAnchorX = state.anchor.left() ? anchorRect.extent().x : state.anchor.right() ? anchorRect.x : anchorX; + auto newEffectiveX = calcEffectiveX(newGravity, newAnchorX); + + if (calcRemainingWidth(newEffectiveX).second > calcRemainingWidth(effectiveX).second) { + gravity = newGravity; + anchorX = newAnchorX; + effectiveX = newEffectiveX; + } } } @@ -561,9 +598,15 @@ CBox CXDGPositionerRules::getPosition(CBox constraint, const Vector2D& parentCoo auto flip = (state.gravity.top() && effectiveY + state.offset.y < constraint.y) || (state.gravity.bottom() && effectiveY + state.offset.y + height > constraint.extent().y); if (flip) { - state.gravity ^= CEdges::TOP | CEdges::BOTTOM; - anchorY = state.anchor.top() ? anchorRect.extent().y : state.anchor.bottom() ? anchorRect.y : anchorY; - effectiveY = calcEffectiveY(); + auto newGravity = gravity ^ (CEdges::TOP | CEdges::BOTTOM); + auto newAnchorY = state.anchor.top() ? anchorRect.extent().y : state.anchor.bottom() ? anchorRect.y : anchorY; + auto newEffectiveY = calcEffectiveY(newGravity, newAnchorY); + + if (calcRemainingHeight(newEffectiveY).second > calcRemainingHeight(effectiveY).second) { + gravity = newGravity; + anchorY = newAnchorY; + effectiveY = newEffectiveY; + } } } @@ -589,27 +632,15 @@ CBox CXDGPositionerRules::getPosition(CBox constraint, const Vector2D& parentCoo } if (state.constraintAdjustment & XDG_POSITIONER_CONSTRAINT_ADJUSTMENT_RESIZE_X) { - if (effectiveX < constraint.x) { - auto diff = constraint.x - effectiveX; - effectiveX = constraint.x; - width -= diff; - } - - auto effectiveX2 = effectiveX + width; - if (effectiveX2 > constraint.extent().x) - width -= effectiveX2 - constraint.extent().x; + auto [newX, newWidth] = calcRemainingWidth(effectiveX); + effectiveX = newX; + width = newWidth; } if (state.constraintAdjustment & XDG_POSITIONER_CONSTRAINT_ADJUSTMENT_RESIZE_Y) { - if (effectiveY < constraint.y) { - auto diff = constraint.y - effectiveY; - effectiveY = constraint.y; - height -= diff; - } - - auto effectiveY2 = effectiveY + height; - if (effectiveY2 > constraint.extent().y) - height -= effectiveY2 - constraint.extent().y; + auto [newY, newHeight] = calcRemainingHeight(effectiveY); + effectiveY = newY; + height = newHeight; } return {effectiveX - parentCoord.x, effectiveY - parentCoord.y, width, height}; From 2e3dc17a7e56c609659514af13ce911481334be3 Mon Sep 17 00:00:00 2001 From: Vaxry Date: Wed, 7 Aug 2024 13:31:27 +0200 Subject: [PATCH 0243/2181] renderer: guard layer in renderLayer ref #7181 --- src/render/Renderer.cpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/render/Renderer.cpp b/src/render/Renderer.cpp index 7794d476..8c29bef4 100644 --- a/src/render/Renderer.cpp +++ b/src/render/Renderer.cpp @@ -716,6 +716,9 @@ void CHyprRenderer::renderWindow(PHLWINDOW pWindow, CMonitor* pMonitor, timespec } void CHyprRenderer::renderLayer(PHLLS pLayer, CMonitor* pMonitor, timespec* time, bool popups) { + if (!pLayer) + return; + static auto PDIMAROUND = CConfigValue("decoration:dim_around"); if (*PDIMAROUND && pLayer->dimAround && !m_bRenderingSnapshot && !popups) { From f36c625e37f8913d8da38365a4783948f2217f02 Mon Sep 17 00:00:00 2001 From: Vaxry Date: Wed, 7 Aug 2024 13:35:02 +0200 Subject: [PATCH 0244/2181] compositor: minor cleanups for fading out layers --- src/Compositor.cpp | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/src/Compositor.cpp b/src/Compositor.cpp index 299a16c6..9b8fd3d7 100644 --- a/src/Compositor.cpp +++ b/src/Compositor.cpp @@ -1425,12 +1425,16 @@ void CCompositor::cleanupFadingOut(const int& monid) { } } + bool layersDirty = false; + for (auto& lsr : m_vSurfacesFadingOut) { auto ls = lsr.lock(); - if (!ls) + if (!ls) { + layersDirty = true; continue; + } if (ls->monitorID != monid) continue; @@ -1443,7 +1447,7 @@ void CCompositor::cleanupFadingOut(const int& monid) { for (auto& m : m_vMonitors) { for (auto& lsl : m->m_aLayerSurfaceLayers) { if (!lsl.empty() && std::find_if(lsl.begin(), lsl.end(), [&](auto& other) { return other == ls; }) != lsl.end()) { - std::erase_if(lsl, [&](auto& other) { return other == ls; }); + std::erase_if(lsl, [&](auto& other) { return other == ls || !other; }); } } } @@ -1459,6 +1463,9 @@ void CCompositor::cleanupFadingOut(const int& monid) { return; } } + + if (layersDirty) + std::erase_if(m_vSurfacesFadingOut, [](const auto& el) { return el.expired(); }); } void CCompositor::addToFadingOutSafe(PHLLS pLS) { From 99e9cb510777c62f56c94137b302186d4d9506d8 Mon Sep 17 00:00:00 2001 From: Vaxry Date: Wed, 7 Aug 2024 16:08:50 +0200 Subject: [PATCH 0245/2181] drm-syncobj: fixup fd leak with timelines --- src/protocols/DRMSyncobj.cpp | 5 +++++ src/protocols/DRMSyncobj.hpp | 1 + 2 files changed, 6 insertions(+) diff --git a/src/protocols/DRMSyncobj.cpp b/src/protocols/DRMSyncobj.cpp index 8b0330de..37e6d0f1 100644 --- a/src/protocols/DRMSyncobj.cpp +++ b/src/protocols/DRMSyncobj.cpp @@ -114,6 +114,11 @@ CDRMSyncobjTimelineResource::CDRMSyncobjTimelineResource(SP= 0) + close(fd); +} + SP CDRMSyncobjTimelineResource::fromResource(wl_resource* res) { auto data = (CDRMSyncobjTimelineResource*)(((CWpLinuxDrmSyncobjTimelineV1*)wl_resource_get_user_data(res))->data()); return data ? data->self.lock() : nullptr; diff --git a/src/protocols/DRMSyncobj.hpp b/src/protocols/DRMSyncobj.hpp index 25dc10c1..bc89a3d3 100644 --- a/src/protocols/DRMSyncobj.hpp +++ b/src/protocols/DRMSyncobj.hpp @@ -34,6 +34,7 @@ class CDRMSyncobjSurfaceResource { class CDRMSyncobjTimelineResource { public: CDRMSyncobjTimelineResource(SP resource_, int fd_); + ~CDRMSyncobjTimelineResource(); static SP fromResource(wl_resource*); bool good(); From d5bc3eb1fa0e11e9e77ffef8c8449a9c022a13a5 Mon Sep 17 00:00:00 2001 From: Sami Liedes Date: Wed, 7 Aug 2024 16:28:02 +0200 Subject: [PATCH 0246/2181] hyprctl: link to much less libraries (#7212) This makes hyprctl start significantly faster. $ time for ((i=0; i<1000; i++)); do hyprctl/hyprctl -j activewindow >/dev/null; done Before: 12.269 s (about 12.3 ms/execution) After: 2.142 s (about 2.1 ms/execution) --- CMakeLists.txt | 6 ++++++ hyprctl/CMakeLists.txt | 2 +- 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index fa58b63d..fc8eafd5 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -87,6 +87,12 @@ else() endif() find_package(OpenGL REQUIRED COMPONENTS ${GLES_VERSION}) +pkg_check_modules( + hyprctl_deps + REQUIRED + IMPORTED_TARGET + hyprutils>=0.2.1) + pkg_check_modules( deps REQUIRED diff --git a/hyprctl/CMakeLists.txt b/hyprctl/CMakeLists.txt index 64b983e6..aaffe411 100644 --- a/hyprctl/CMakeLists.txt +++ b/hyprctl/CMakeLists.txt @@ -9,7 +9,7 @@ pkg_check_modules(deps REQUIRED IMPORTED_TARGET hyprutils>=0.1.1) add_executable(hyprctl "main.cpp") -target_link_libraries(hyprctl PUBLIC PkgConfig::deps) +target_link_libraries(hyprctl PUBLIC PkgConfig::hyprctl_deps) # binary install(TARGETS hyprctl) From 3e00d7dde774a44b5738d339ce58a4903897942b Mon Sep 17 00:00:00 2001 From: Agent00Ming <107314235+Agent00Ming@users.noreply.github.com> Date: Wed, 7 Aug 2024 10:36:20 -0400 Subject: [PATCH 0247/2181] compositor: fix general:extend_border_grab_area (#7214) Co-authored-by: Agent_00Ming --- src/Compositor.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Compositor.cpp b/src/Compositor.cpp index 9b8fd3d7..49408597 100644 --- a/src/Compositor.cpp +++ b/src/Compositor.cpp @@ -777,7 +777,7 @@ PHLWINDOW CCompositor::vectorToWindowUnified(const Vector2D& pos, uint8_t proper if (properties & ALLOW_FLOATING) { for (auto& w : m_vWindows | std::views::reverse) { const auto BB = w->getWindowBoxUnified(properties); - CBox box = BB.copy().expand(w->m_iX11Type == 2 ? BORDER_GRAB_AREA : 0); + CBox box = BB.copy().expand(w->m_iX11Type != 2 ? BORDER_GRAB_AREA : 0); if (w->m_bIsFloating && w->m_bIsMapped && !w->isHidden() && !w->m_bX11ShouldntFocus && w->m_bPinned && !w->m_sWindowData.noFocus.valueOrDefault() && w != pIgnoreWindow) { if (box.containsPoint(g_pPointerManager->position())) @@ -807,7 +807,7 @@ PHLWINDOW CCompositor::vectorToWindowUnified(const Vector2D& pos, uint8_t proper BB.x + BB.width <= PWINDOWMONITOR->vecPosition.x + PWINDOWMONITOR->vecSize.x && BB.y + BB.height <= PWINDOWMONITOR->vecPosition.y + PWINDOWMONITOR->vecSize.y) continue; - CBox box = BB.copy().expand(w->m_iX11Type == 2 ? BORDER_GRAB_AREA : 0); + CBox box = BB.copy().expand(w->m_iX11Type != 2 ? BORDER_GRAB_AREA : 0); if (w->m_bIsFloating && w->m_bIsMapped && isWorkspaceVisible(w->m_pWorkspace) && !w->isHidden() && !w->m_bPinned && !w->m_sWindowData.noFocus.valueOrDefault() && w != pIgnoreWindow && (!aboveFullscreen || w->m_bCreatedOverFullscreen)) { // OR windows should add focus to parent From a399f98c68d017152883fbf81d67624ac3254073 Mon Sep 17 00:00:00 2001 From: Tom Englund Date: Wed, 7 Aug 2024 16:37:09 +0200 Subject: [PATCH 0248/2181] cursormgr: avoid scanning ill formed inherit (#7211) avoid adding ill formed Inherit lines to inherit vector and later scanning them, it wont change anything in practice but makes the inherit theme parsing more in line with what its supposed todo. also check for return values of the various string functions so we dont end up erasing the wrong thing. --- src/managers/XCursorManager.cpp | 53 ++++++++++++++++++++++++++------- 1 file changed, 43 insertions(+), 10 deletions(-) diff --git a/src/managers/XCursorManager.cpp b/src/managers/XCursorManager.cpp index 76c908db..f2a7ab53 100644 --- a/src/managers/XCursorManager.cpp +++ b/src/managers/XCursorManager.cpp @@ -205,23 +205,56 @@ std::unordered_set CXCursorManager::themePaths(std::string const& t Debug::log(LOG, "XCursor parsing index.theme {}", indexTheme); while (std::getline(infile, line)) { - // Trim leading and trailing whitespace - line.erase(0, line.find_first_not_of(" \t\n\r")); - line.erase(line.find_last_not_of(" \t\n\r") + 1); + if (line.empty()) + continue; + + // Trim leading and trailing whitespace + auto pos = line.find_first_not_of(" \t\n\r"); + if (pos != std::string::npos) + line.erase(0, pos); + + pos = line.find_last_not_of(" \t\n\r"); + if (pos != std::string::npos && pos < line.length()) { + line.erase(pos + 1); + } + + if (line.rfind("Inherits", 8) != std::string::npos) { // Check if line starts with "Inherits" + std::string inheritThemes = line.substr(8); // Extract the part after "Inherits" + if (inheritThemes.empty()) + continue; - if (line.rfind("Inherits", 0) == 0) { // Check if line starts with "Inherits" - std::string inheritThemes = line.substr(8); // Extract the part after "Inherits" // Remove leading whitespace from inheritThemes and = - inheritThemes.erase(0, inheritThemes.find_first_not_of(" \t\n\r")); - inheritThemes.erase(0, 1); - inheritThemes.erase(0, inheritThemes.find_first_not_of(" \t\n\r")); + pos = inheritThemes.find_first_not_of(" \t\n\r"); + if (pos != std::string::npos) + inheritThemes.erase(0, pos); + + if (inheritThemes.empty()) + continue; + + if (inheritThemes.at(0) == '=') + inheritThemes.erase(0, 1); + else + continue; // not correct formatted index.theme + + pos = inheritThemes.find_first_not_of(" \t\n\r"); + if (pos != std::string::npos) + inheritThemes.erase(0, pos); std::stringstream inheritStream(inheritThemes); std::string inheritTheme; while (std::getline(inheritStream, inheritTheme, ',')) { + if (inheritTheme.empty()) + continue; + // Trim leading and trailing whitespace from each theme - inheritTheme.erase(0, inheritTheme.find_first_not_of(" \t\n\r")); - inheritTheme.erase(inheritTheme.find_last_not_of(" \t\n\r") + 1); + pos = inheritTheme.find_first_not_of(" \t\n\r"); + if (pos != std::string::npos) + inheritTheme.erase(0, pos); + + pos = inheritTheme.find_last_not_of(" \t\n\r"); + if (pos != std::string::npos && pos < inheritTheme.length()) + inheritTheme.erase(inheritTheme.find_last_not_of(" \t\n\r") + 1); + themes.push_back(inheritTheme); } } From ea728315410e220d73a993f17c83ae9dc9be9015 Mon Sep 17 00:00:00 2001 From: Vaxry Date: Wed, 7 Aug 2024 17:04:43 +0200 Subject: [PATCH 0249/2181] wayland/compositor: introduce client commit events --- src/protocols/DRMSyncobj.cpp | 2 +- src/protocols/core/Compositor.cpp | 2 ++ src/protocols/core/Compositor.hpp | 5 +++-- 3 files changed, 6 insertions(+), 3 deletions(-) diff --git a/src/protocols/DRMSyncobj.cpp b/src/protocols/DRMSyncobj.cpp index 37e6d0f1..9a48b99a 100644 --- a/src/protocols/DRMSyncobj.cpp +++ b/src/protocols/DRMSyncobj.cpp @@ -75,7 +75,7 @@ CDRMSyncobjSurfaceResource::CDRMSyncobjSurfaceResource(SPtimeline->addWaiter([this]() { surface->unlockPendingState(); }, pending.acquirePoint, DRM_SYNCOBJ_WAIT_FLAGS_WAIT_AVAILABLE); }); - listeners.surfaceCommit = surface->events.commit.registerListener([this](std::any d) { + listeners.surfaceCommit = surface->events.roleCommit.registerListener([this](std::any d) { // apply timelines if new ones have been attached, otherwise don't touch // the current ones if (pending.releaseTimeline) { diff --git a/src/protocols/core/Compositor.cpp b/src/protocols/core/Compositor.cpp index 656433d3..a767dd52 100644 --- a/src/protocols/core/Compositor.cpp +++ b/src/protocols/core/Compositor.cpp @@ -432,6 +432,8 @@ void CWLSurfaceResource::commitPendingState() { pending.bufferDamage.clear(); pending.newBuffer = false; + events.roleCommit.emit(); + if (syncobj && syncobj->current.releaseTimeline && syncobj->current.releaseTimeline->timeline && current.buffer && current.buffer->buffer) current.buffer->releaser = makeShared(syncobj->current.releaseTimeline->timeline, syncobj->current.releasePoint); diff --git a/src/protocols/core/Compositor.hpp b/src/protocols/core/Compositor.hpp index af0dfa58..a3245399 100644 --- a/src/protocols/core/Compositor.hpp +++ b/src/protocols/core/Compositor.hpp @@ -75,8 +75,9 @@ class CWLSurfaceResource { Vector2D sourceSize(); struct { - CSignal precommit; - CSignal commit; + CSignal precommit; // before commit + CSignal roleCommit; // commit for role objects, before regular commit + CSignal commit; // after commit CSignal map; CSignal unmap; CSignal newSubsurface; From 2d552fbaa25f1457c3819521a2750dd30820271b Mon Sep 17 00:00:00 2001 From: Vaxry Date: Wed, 7 Aug 2024 18:54:45 +0200 Subject: [PATCH 0250/2181] renderer: fixup nvidia driver version checks --- src/render/Renderer.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/render/Renderer.cpp b/src/render/Renderer.cpp index 8c29bef4..7b29eb77 100644 --- a/src/render/Renderer.cpp +++ b/src/render/Renderer.cpp @@ -2737,7 +2737,7 @@ SExplicitSyncSettings CHyprRenderer::getExplicitSyncSettings() { // check nvidia version. Explicit KMS is supported in >=560 // in the case of an error, driverMajor will stay 0 and explicit KMS will be disabled - int driverMajor = 0; + static int driverMajor = 0; static bool once = true; if (once) { From 9a09eac79b85c846e3a865a9078a3f8ff65a9259 Mon Sep 17 00:00:00 2001 From: Vaxry Date: Wed, 7 Aug 2024 21:17:10 +0200 Subject: [PATCH 0251/2181] props: bump version to 0.42.0 --- VERSION | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/VERSION b/VERSION index 6599454d..787ffc30 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -0.41.2 +0.42.0 From 83a334f97df4389ca30cb63e50317a66a82562b9 Mon Sep 17 00:00:00 2001 From: Vaxry <43317083+vaxerski@users.noreply.github.com> Date: Thu, 8 Aug 2024 10:54:41 +0100 Subject: [PATCH 0252/2181] core: Move to C++26 and use native_handle to CLOEXEC the debug fd (#7219) Requires GCC >= 14 / Clang >= 18 --------- Co-authored-by: Mihai Fufezan --- CMakeLists.txt | 2 +- flake.nix | 2 +- meson.build | 2 +- nix/default.nix | 5 +++++ nix/overlays.nix | 2 +- nix/stdcxx.patch | 12 ++++++++++++ src/debug/Log.cpp | 3 +++ 7 files changed, 24 insertions(+), 4 deletions(-) create mode 100644 nix/stdcxx.patch diff --git a/CMakeLists.txt b/CMakeLists.txt index fc8eafd5..cfbd431f 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -62,7 +62,7 @@ else() endif() include_directories(. "src/" "subprojects/udis86/" "protocols/") -set(CMAKE_CXX_STANDARD 23) +set(CMAKE_CXX_STANDARD 26) add_compile_options( -Wall -Wextra diff --git a/flake.nix b/flake.nix index 9c20b3f5..9e1e3ab4 100644 --- a/flake.nix +++ b/flake.nix @@ -95,7 +95,7 @@ devShells = eachSystem (system: { default = pkgsFor.${system}.mkShell.override { - stdenv = pkgsFor.${system}.gcc13Stdenv; + stdenv = pkgsFor.${system}.gcc14Stdenv; } { name = "hyprland-shell"; nativeBuildInputs = with pkgsFor.${system}; [ diff --git a/meson.build b/meson.build index 886f4f9c..e8cd25b4 100644 --- a/meson.build +++ b/meson.build @@ -6,7 +6,7 @@ project('Hyprland', 'cpp', 'c', 'optimization=3', 'buildtype=release', 'debug=false', - 'cpp_std=c++23', + 'cpp_std=c++26', ]) datarootdir = '-DDATAROOTDIR="' + get_option('prefix') / get_option('datadir') + '"' diff --git a/nix/default.nix b/nix/default.nix index e4e12f43..9bae9d83 100644 --- a/nix/default.nix +++ b/nix/default.nix @@ -71,6 +71,11 @@ assert lib.assertMsg (!hidpiXWayland) "The option `hidpiXWayland` has been remov src = lib.cleanSource ../.; }; + patches = [ + # forces GCC to use -std=c++26 + ./stdcxx.patch + ]; + postPatch = '' # Fix hardcoded paths to /usr installation sed -i "s#/usr#$out#" src/render/OpenGL.cpp diff --git a/nix/overlays.nix b/nix/overlays.nix index d8979b45..36206f46 100644 --- a/nix/overlays.nix +++ b/nix/overlays.nix @@ -31,7 +31,7 @@ in { date = mkDate (self.lastModifiedDate or "19700101"); in { hyprland = final.callPackage ./default.nix { - stdenv = final.gcc13Stdenv; + stdenv = final.gcc14Stdenv; version = "${version}+date=${date}_${self.shortRev or "dirty"}"; commit = self.rev or ""; inherit date; diff --git a/nix/stdcxx.patch b/nix/stdcxx.patch new file mode 100644 index 00000000..032e494d --- /dev/null +++ b/nix/stdcxx.patch @@ -0,0 +1,12 @@ +diff --git a/CMakeLists.txt b/CMakeLists.txt +index cfbd431f..73e8e0c2 100644 +--- a/CMakeLists.txt ++++ b/CMakeLists.txt +@@ -64,6 +64,7 @@ endif() + include_directories(. "src/" "subprojects/udis86/" "protocols/") + set(CMAKE_CXX_STANDARD 26) + add_compile_options( ++ -std=c++26 + -Wall + -Wextra + -Wno-unused-parameter diff --git a/src/debug/Log.cpp b/src/debug/Log.cpp index 0def77c0..a4c5b08e 100644 --- a/src/debug/Log.cpp +++ b/src/debug/Log.cpp @@ -5,10 +5,13 @@ #include #include +#include void Debug::init(const std::string& IS) { logFile = IS + (ISDEBUG ? "/hyprlandd.log" : "/hyprland.log"); logOfs.open(logFile, std::ios::out | std::ios::app); + auto handle = logOfs.native_handle(); + fcntl(handle, F_SETFD, FD_CLOEXEC); } void Debug::close() { From 4b4971c06fb02df00a2bd20b6b47b5d0e7d799a7 Mon Sep 17 00:00:00 2001 From: Tom Englund Date: Thu, 8 Aug 2024 21:01:50 +0200 Subject: [PATCH 0253/2181] internal: introduce new types to avoid unsigned int rollover and signed int overflow (#7216) * framebuffer: avoid gluint overflow GLuint was being initialized to -1 and rolling over to unsigned int max, its defined behaviour but very unnecessery. add a bool and use it for checking if allocated or not. * opengl: avoid gluint rollover -1 rolls over to unsigned int max, use 0xFF instead. * core: big uint64_t to int type conversion there were a few uint64_t to int implicit conversions overflowing int and causing UB, make all monitor/workspaces/windows use the new typedefs. also fix the various related 64 to 32 implicit conversions going around found with -Wshorten-64-to-32 --- hyprctl/main.cpp | 2 +- src/Compositor.cpp | 74 ++++++------- src/Compositor.hpp | 115 ++++++++++---------- src/SharedDefs.hpp | 4 + src/config/ConfigManager.cpp | 2 +- src/config/ConfigManager.hpp | 2 +- src/debug/HyprCtl.cpp | 4 +- src/desktop/LayerSurface.cpp | 4 +- src/desktop/LayerSurface.hpp | 4 +- src/desktop/Window.cpp | 2 +- src/desktop/Window.hpp | 14 +-- src/desktop/Workspace.cpp | 14 +-- src/desktop/Workspace.hpp | 10 +- src/events/Windows.cpp | 2 +- src/helpers/MiscFunctions.cpp | 78 ++++++------- src/helpers/MiscFunctions.hpp | 4 +- src/helpers/Monitor.cpp | 14 +-- src/helpers/Monitor.hpp | 52 ++++----- src/helpers/Timer.cpp | 2 +- src/helpers/Timer.hpp | 2 +- src/layout/DwindleLayout.cpp | 12 +- src/layout/DwindleLayout.hpp | 12 +- src/layout/IHyprLayout.hpp | 2 +- src/layout/MasterLayout.cpp | 10 +- src/layout/MasterLayout.hpp | 14 +-- src/macros.hpp | 2 + src/managers/KeybindManager.cpp | 6 +- src/managers/eventLoop/EventLoopManager.cpp | 4 +- src/managers/input/InputMethodPopup.hpp | 2 +- src/managers/input/Swipe.cpp | 2 +- src/protocols/ForeignToplevelWlr.cpp | 2 +- src/protocols/ForeignToplevelWlr.hpp | 2 +- src/render/Framebuffer.cpp | 11 +- src/render/Framebuffer.hpp | 3 +- src/render/OpenGL.cpp | 16 +-- src/render/Renderer.cpp | 2 +- src/render/Renderer.hpp | 2 +- src/signal-safe.cpp | 2 +- src/signal-safe.hpp | 4 +- 39 files changed, 263 insertions(+), 252 deletions(-) diff --git a/hyprctl/main.cpp b/hyprctl/main.cpp index 336d479e..c86406fc 100644 --- a/hyprctl/main.cpp +++ b/hyprctl/main.cpp @@ -113,7 +113,7 @@ int rollingRead(const int socket) { constexpr size_t BUFFER_SIZE = 8192; std::array buffer = {0}; - int sizeWritten = 0; + long sizeWritten = 0; std::cout << "[hyprctl] reading from socket following up log:" << std::endl; while (!sigintReceived) { sizeWritten = read(socket, buffer.data(), BUFFER_SIZE); diff --git a/src/Compositor.cpp b/src/Compositor.cpp index 49408597..e3a347fd 100644 --- a/src/Compositor.cpp +++ b/src/Compositor.cpp @@ -683,9 +683,9 @@ void CCompositor::startCompositor() { g_pEventLoopManager->enterLoop(); } -CMonitor* CCompositor::getMonitorFromID(const int& id) { +CMonitor* CCompositor::getMonitorFromID(const MONITORID& id) { for (auto& m : m_vMonitors) { - if (m->ID == (uint64_t)id) { + if (m->ID == id) { return m.get(); } } @@ -845,8 +845,8 @@ PHLWINDOW CCompositor::vectorToWindowUnified(const Vector2D& pos, uint8_t proper if (properties & FLOATING_ONLY) return floating(false); - const int64_t WORKSPACEID = special ? PMONITOR->activeSpecialWorkspaceID() : PMONITOR->activeWorkspaceID(); - const auto PWORKSPACE = getWorkspaceByID(WORKSPACEID); + const WORKSPACEID WSPID = special ? PMONITOR->activeSpecialWorkspaceID() : PMONITOR->activeWorkspaceID(); + const auto PWORKSPACE = getWorkspaceByID(WSPID); if (PWORKSPACE->m_bHasFullscreenWindow) return getFullscreenWindowOnWorkspace(PWORKSPACE->m_iID); @@ -860,7 +860,7 @@ PHLWINDOW CCompositor::vectorToWindowUnified(const Vector2D& pos, uint8_t proper if (special != w->onSpecialWorkspace()) continue; - if (!w->m_bIsX11 && !w->m_bIsFloating && w->m_bIsMapped && w->workspaceID() == WORKSPACEID && !w->isHidden() && !w->m_bX11ShouldntFocus && + if (!w->m_bIsX11 && !w->m_bIsFloating && w->m_bIsMapped && w->workspaceID() == WSPID && !w->isHidden() && !w->m_bX11ShouldntFocus && !w->m_sWindowData.noFocus.valueOrDefault() && w != pIgnoreWindow) { if (w->hasPopupAt(pos)) return w; @@ -872,7 +872,7 @@ PHLWINDOW CCompositor::vectorToWindowUnified(const Vector2D& pos, uint8_t proper continue; CBox box = (properties & USE_PROP_TILED) ? w->getWindowBoxUnified(properties) : CBox{w->m_vPosition, w->m_vSize}; - if (!w->m_bIsFloating && w->m_bIsMapped && box.containsPoint(pos) && w->workspaceID() == WORKSPACEID && !w->isHidden() && !w->m_bX11ShouldntFocus && + if (!w->m_bIsFloating && w->m_bIsMapped && box.containsPoint(pos) && w->workspaceID() == WSPID && !w->isHidden() && !w->m_bX11ShouldntFocus && !w->m_sWindowData.noFocus.valueOrDefault() && w != pIgnoreWindow) return w; } @@ -1207,7 +1207,7 @@ PHLWINDOW CCompositor::getWindowFromHandle(uint32_t handle) { return nullptr; } -PHLWINDOW CCompositor::getFullscreenWindowOnWorkspace(const int& ID) { +PHLWINDOW CCompositor::getFullscreenWindowOnWorkspace(const WORKSPACEID& ID) { for (auto& w : m_vWindows) { if (w->workspaceID() == ID && w->isFullscreen()) return w; @@ -1231,7 +1231,7 @@ bool CCompositor::isWorkspaceVisibleNotCovered(PHLWORKSPACE w) { return PMONITOR->activeWorkspace->m_iID == w->m_iID; } -PHLWORKSPACE CCompositor::getWorkspaceByID(const int& id) { +PHLWORKSPACE CCompositor::getWorkspaceByID(const WORKSPACEID& id) { for (auto& w : m_vWorkspaces) { if (w->m_iID == id && !w->inert()) return w; @@ -1255,7 +1255,7 @@ void CCompositor::sanityCheckWorkspaces() { } } -int CCompositor::getWindowsOnWorkspace(const int& id, std::optional onlyTiled, std::optional onlyVisible) { +int CCompositor::getWindowsOnWorkspace(const WORKSPACEID& id, std::optional onlyTiled, std::optional onlyVisible) { int no = 0; for (auto& w : m_vWindows) { if (w->workspaceID() != id || !w->m_bIsMapped) @@ -1270,7 +1270,7 @@ int CCompositor::getWindowsOnWorkspace(const int& id, std::optional onlyTi return no; } -int CCompositor::getGroupsOnWorkspace(const int& id, std::optional onlyTiled, std::optional onlyVisible) { +int CCompositor::getGroupsOnWorkspace(const WORKSPACEID& id, std::optional onlyTiled, std::optional onlyVisible) { int no = 0; for (auto& w : m_vWindows) { if (w->workspaceID() != id || !w->m_bIsMapped) @@ -1295,7 +1295,7 @@ PHLWINDOW CCompositor::getUrgentWindow() { return nullptr; } -bool CCompositor::hasUrgentWindowOnWorkspace(const int& id) { +bool CCompositor::hasUrgentWindowOnWorkspace(const WORKSPACEID& id) { for (auto& w : m_vWindows) { if (w->workspaceID() == id && w->m_bIsMapped && w->m_bIsUrgent) return true; @@ -1304,7 +1304,7 @@ bool CCompositor::hasUrgentWindowOnWorkspace(const int& id) { return false; } -PHLWINDOW CCompositor::getFirstWindowOnWorkspace(const int& id) { +PHLWINDOW CCompositor::getFirstWindowOnWorkspace(const WORKSPACEID& id) { for (auto& w : m_vWindows) { if (w->workspaceID() == id && w->m_bIsMapped && !w->isHidden()) return w; @@ -1313,7 +1313,7 @@ PHLWINDOW CCompositor::getFirstWindowOnWorkspace(const int& id) { return nullptr; } -PHLWINDOW CCompositor::getTopLeftWindowOnWorkspace(const int& id) { +PHLWINDOW CCompositor::getTopLeftWindowOnWorkspace(const WORKSPACEID& id) { const auto PWORKSPACE = getWorkspaceByID(id); if (!PWORKSPACE) @@ -1401,12 +1401,12 @@ void CCompositor::changeWindowZOrder(PHLWINDOW pWindow, bool top) { } } -void CCompositor::cleanupFadingOut(const int& monid) { +void CCompositor::cleanupFadingOut(const MONITORID& monid) { for (auto& ww : m_vWindowsFadingOut) { auto w = ww.lock(); - if (w->m_iMonitorID != (long unsigned int)monid) + if (w->m_iMonitorID != monid) continue; if (!w->m_bFadingOut || w->m_fAlpha.value() == 0.f) { @@ -1702,8 +1702,8 @@ PHLWINDOW CCompositor::getPrevWindowOnWorkspace(PHLWINDOW pWindow, bool focusabl return nullptr; } -int CCompositor::getNextAvailableNamedWorkspace() { - int lowest = -1337 + 1; +WORKSPACEID CCompositor::getNextAvailableNamedWorkspace() { + WORKSPACEID lowest = -1337 + 1; for (auto& w : m_vWorkspaces) { if (w->m_iID < -1 && w->m_iID < lowest) lowest = w->m_iID; @@ -1927,18 +1927,18 @@ void CCompositor::updateWindowAnimatedDecorationValues(PHLWINDOW pWindow) { pWindow->updateWindowDecos(); } -int CCompositor::getNextAvailableMonitorID(std::string const& name) { +MONITORID CCompositor::getNextAvailableMonitorID(std::string const& name) { // reuse ID if it's already in the map, and the monitor with that ID is not being used by another monitor if (m_mMonitorIDMap.contains(name) && !std::any_of(m_vRealMonitors.begin(), m_vRealMonitors.end(), [&](auto m) { return m->ID == m_mMonitorIDMap[name]; })) return m_mMonitorIDMap[name]; // otherwise, find minimum available ID that is not in the map - std::unordered_set usedIDs; + std::unordered_set usedIDs; for (auto const& monitor : m_vRealMonitors) { usedIDs.insert(monitor->ID); } - uint64_t nextID = 0; + MONITORID nextID = 0; while (usedIDs.count(nextID) > 0) { nextID++; } @@ -2078,7 +2078,7 @@ CMonitor* CCompositor::getMonitorFromString(const std::string& name) { return m_vMonitors[currentPlace].get(); } else if (isNumber(name)) { // change by ID - int monID = -1; + MONITORID monID = MONITOR_INVALID; try { monID = std::stoi(name); } catch (std::exception& e) { @@ -2087,7 +2087,7 @@ CMonitor* CCompositor::getMonitorFromString(const std::string& name) { return nullptr; } - if (monID > -1 && monID < (int)m_vMonitors.size()) { + if (monID > -1 && monID < (MONITORID)m_vMonitors.size()) { return getMonitorFromID(monID); } else { Debug::log(ERR, "Error in getMonitorFromString: invalid arg 1"); @@ -2121,7 +2121,7 @@ void CCompositor::moveWorkspaceToMonitor(PHLWORKSPACE pWorkspace, CMonitor* pMon const bool SWITCHINGISACTIVE = POLDMON ? POLDMON->activeWorkspace == pWorkspace : false; // fix old mon - int nextWorkspaceOnMonitorID = -1; + WORKSPACEID nextWorkspaceOnMonitorID = WORKSPACE_INVALID; if (!SWITCHINGISACTIVE) nextWorkspaceOnMonitorID = pWorkspace->m_iID; else { @@ -2132,7 +2132,7 @@ void CCompositor::moveWorkspaceToMonitor(PHLWORKSPACE pWorkspace, CMonitor* pMon } } - if (nextWorkspaceOnMonitorID == -1) { + if (nextWorkspaceOnMonitorID == WORKSPACE_INVALID) { nextWorkspaceOnMonitorID = 1; while (getWorkspaceByID(nextWorkspaceOnMonitorID) || [&]() -> bool { @@ -2219,9 +2219,9 @@ void CCompositor::moveWorkspaceToMonitor(PHLWORKSPACE pWorkspace, CMonitor* pMon EMIT_HOOK_EVENT("moveWorkspace", (std::vector{pWorkspace, pMonitor})); } -bool CCompositor::workspaceIDOutOfBounds(const int64_t& id) { - int64_t lowestID = INT64_MAX; - int64_t highestID = INT64_MIN; +bool CCompositor::workspaceIDOutOfBounds(const WORKSPACEID& id) { + WORKSPACEID lowestID = INT64_MAX; + WORKSPACEID highestID = INT64_MIN; for (auto& w : m_vWorkspaces) { if (w->m_bIsSpecialWorkspace) @@ -2370,7 +2370,7 @@ PHLWINDOW CCompositor::getX11Parent(PHLWINDOW pWindow) { return nullptr; } -void CCompositor::updateWorkspaceWindowDecos(const int& id) { +void CCompositor::updateWorkspaceWindowDecos(const WORKSPACEID& id) { for (auto& w : m_vWindows) { if (w->workspaceID() != id) continue; @@ -2379,7 +2379,7 @@ void CCompositor::updateWorkspaceWindowDecos(const int& id) { } } -void CCompositor::updateWorkspaceWindowData(const int& id) { +void CCompositor::updateWorkspaceWindowData(const WORKSPACEID& id) { const auto PWORKSPACE = getWorkspaceByID(id); const auto WORKSPACERULE = PWORKSPACE ? g_pConfigManager->getWorkspaceRuleFor(PWORKSPACE) : SWorkspaceRule{}; @@ -2599,7 +2599,7 @@ Vector2D CCompositor::parseWindowVectorArgsRelative(const std::string& args, con return Vector2D(X, Y); } -void CCompositor::forceReportSizesToWindowsOnWorkspace(const int& wid) { +void CCompositor::forceReportSizesToWindowsOnWorkspace(const WORKSPACEID& wid) { for (auto& w : m_vWindows) { if (w->workspaceID() == wid && w->m_bIsMapped && !w->isHidden()) { g_pXWaylandManager->setWindowSize(w, w->m_vRealSize.value(), true); @@ -2607,7 +2607,7 @@ void CCompositor::forceReportSizesToWindowsOnWorkspace(const int& wid) { } } -PHLWORKSPACE CCompositor::createNewWorkspace(const int& id, const int& monid, const std::string& name, bool isEmtpy) { +PHLWORKSPACE CCompositor::createNewWorkspace(const WORKSPACEID& id, const MONITORID& monid, const std::string& name, bool isEmtpy) { const auto NAME = name == "" ? std::to_string(id) : name; auto monID = monid; @@ -2625,7 +2625,7 @@ PHLWORKSPACE CCompositor::createNewWorkspace(const int& id, const int& monid, co return PWORKSPACE; } -void CCompositor::renameWorkspace(const int& id, const std::string& name) { +void CCompositor::renameWorkspace(const WORKSPACEID& id, const std::string& name) { const auto PWORKSPACE = getWorkspaceByID(id); if (!PWORKSPACE) @@ -2656,12 +2656,12 @@ void CCompositor::setActiveMonitor(CMonitor* pMonitor) { m_pLastMonitor = pMonitor->self; } -bool CCompositor::isWorkspaceSpecial(const int& id) { +bool CCompositor::isWorkspaceSpecial(const WORKSPACEID& id) { return id >= SPECIAL_WORKSPACE_START && id <= -2; } -int CCompositor::getNewSpecialID() { - int highest = SPECIAL_WORKSPACE_START; +WORKSPACEID CCompositor::getNewSpecialID() { + WORKSPACEID highest = SPECIAL_WORKSPACE_START; for (auto& ws : m_vWorkspaces) { if (ws->m_bIsSpecialWorkspace && ws->m_iID > highest) { highest = ws->m_iID; @@ -2965,7 +2965,7 @@ void CCompositor::onNewMonitor(SP output) { PNEWMONITOR->output = output; PNEWMONITOR->self = PNEWMONITOR; const bool FALLBACK = g_pCompositor->m_pUnsafeOutput ? output == g_pCompositor->m_pUnsafeOutput->output : false; - PNEWMONITOR->ID = FALLBACK ? -1 : g_pCompositor->getNextAvailableMonitorID(output->name); + PNEWMONITOR->ID = FALLBACK ? MONITOR_INVALID : g_pCompositor->getNextAvailableMonitorID(output->name); PNEWMONITOR->isUnsafeFallback = FALLBACK; EMIT_HOOK_EVENT("newMonitor", PNEWMONITOR); @@ -2990,7 +2990,7 @@ void CCompositor::onNewMonitor(SP output) { for (auto& w : g_pCompositor->m_vWindows) { if (w->m_iMonitorID == PNEWMONITOR->ID) { - w->m_iLastSurfaceMonitorID = -1; + w->m_iLastSurfaceMonitorID = MONITOR_INVALID; w->updateSurfaceScaleTransformDetails(); } } diff --git a/src/Compositor.hpp b/src/Compositor.hpp index 295935c4..5e9e3266 100644 --- a/src/Compositor.hpp +++ b/src/Compositor.hpp @@ -46,55 +46,55 @@ class CCompositor { CCompositor(); ~CCompositor(); - wl_display* m_sWLDisplay; - wl_event_loop* m_sWLEventLoop; - int m_iDRMFD = -1; - bool m_bInitialized = false; - SP m_pAqBackend; + wl_display* m_sWLDisplay; + wl_event_loop* m_sWLEventLoop; + int m_iDRMFD = -1; + bool m_bInitialized = false; + SP m_pAqBackend; - std::string m_szHyprTempDataRoot = ""; + std::string m_szHyprTempDataRoot = ""; - std::string m_szWLDisplaySocket = ""; - std::string m_szInstanceSignature = ""; - std::string m_szInstancePath = ""; - std::string m_szCurrentSplash = "error"; + std::string m_szWLDisplaySocket = ""; + std::string m_szInstanceSignature = ""; + std::string m_szInstancePath = ""; + std::string m_szCurrentSplash = "error"; - std::vector> m_vMonitors; - std::vector> m_vRealMonitors; // for all monitors, even those turned off - std::vector m_vWindows; - std::vector m_vLayers; - std::vector m_vWorkspaces; - std::vector m_vWindowsFadingOut; - std::vector m_vSurfacesFadingOut; + std::vector> m_vMonitors; + std::vector> m_vRealMonitors; // for all monitors, even those turned off + std::vector m_vWindows; + std::vector m_vLayers; + std::vector m_vWorkspaces; + std::vector m_vWindowsFadingOut; + std::vector m_vSurfacesFadingOut; - std::unordered_map m_mMonitorIDMap; + std::unordered_map m_mMonitorIDMap; - void initServer(std::string socketName, int socketFd); - void startCompositor(); - void stopCompositor(); - void cleanup(); - void createLockFile(); - void removeLockFile(); - void bumpNofile(); - void restoreNofile(); + void initServer(std::string socketName, int socketFd); + void startCompositor(); + void stopCompositor(); + void cleanup(); + void createLockFile(); + void removeLockFile(); + void bumpNofile(); + void restoreNofile(); - WP m_pLastFocus; - PHLWINDOWREF m_pLastWindow; - WP m_pLastMonitor; + WP m_pLastFocus; + PHLWINDOWREF m_pLastWindow; + WP m_pLastMonitor; - std::vector m_vWindowFocusHistory; // first element is the most recently focused. + std::vector m_vWindowFocusHistory; // first element is the most recently focused. - bool m_bReadyToProcess = false; - bool m_bSessionActive = true; - bool m_bDPMSStateON = true; - bool m_bUnsafeState = false; // unsafe state is when there is no monitors. - bool m_bNextIsUnsafe = false; - CMonitor* m_pUnsafeOutput = nullptr; // fallback output for the unsafe state - bool m_bIsShuttingDown = false; + bool m_bReadyToProcess = false; + bool m_bSessionActive = true; + bool m_bDPMSStateON = true; + bool m_bUnsafeState = false; // unsafe state is when there is no monitors. + bool m_bNextIsUnsafe = false; + CMonitor* m_pUnsafeOutput = nullptr; // fallback output for the unsafe state + bool m_bIsShuttingDown = false; // ------------------------------------------------- // - CMonitor* getMonitorFromID(const int&); + CMonitor* getMonitorFromID(const MONITORID&); CMonitor* getMonitorFromName(const std::string&); CMonitor* getMonitorFromDesc(const std::string&); CMonitor* getMonitorFromCursor(); @@ -114,38 +114,38 @@ class CCompositor { PHLWINDOW getWindowFromHandle(uint32_t); bool isWorkspaceVisible(PHLWORKSPACE); bool isWorkspaceVisibleNotCovered(PHLWORKSPACE); - PHLWORKSPACE getWorkspaceByID(const int&); + PHLWORKSPACE getWorkspaceByID(const WORKSPACEID&); PHLWORKSPACE getWorkspaceByName(const std::string&); PHLWORKSPACE getWorkspaceByString(const std::string&); void sanityCheckWorkspaces(); - void updateWorkspaceWindowDecos(const int&); - void updateWorkspaceWindowData(const int&); - int getWindowsOnWorkspace(const int& id, std::optional onlyTiled = {}, std::optional onlyVisible = {}); - int getGroupsOnWorkspace(const int& id, std::optional onlyTiled = {}, std::optional onlyVisible = {}); + void updateWorkspaceWindowDecos(const WORKSPACEID&); + void updateWorkspaceWindowData(const WORKSPACEID&); + int getWindowsOnWorkspace(const WORKSPACEID& id, std::optional onlyTiled = {}, std::optional onlyVisible = {}); + int getGroupsOnWorkspace(const WORKSPACEID& id, std::optional onlyTiled = {}, std::optional onlyVisible = {}); PHLWINDOW getUrgentWindow(); - bool hasUrgentWindowOnWorkspace(const int&); - PHLWINDOW getFirstWindowOnWorkspace(const int&); - PHLWINDOW getTopLeftWindowOnWorkspace(const int&); - PHLWINDOW getFullscreenWindowOnWorkspace(const int&); + bool hasUrgentWindowOnWorkspace(const WORKSPACEID&); + PHLWINDOW getFirstWindowOnWorkspace(const WORKSPACEID&); + PHLWINDOW getTopLeftWindowOnWorkspace(const WORKSPACEID&); + PHLWINDOW getFullscreenWindowOnWorkspace(const WORKSPACEID&); bool isWindowActive(PHLWINDOW); void changeWindowZOrder(PHLWINDOW, bool); - void cleanupFadingOut(const int& monid); + void cleanupFadingOut(const MONITORID& monid); PHLWINDOW getWindowInDirection(PHLWINDOW, char); PHLWINDOW getNextWindowOnWorkspace(PHLWINDOW, bool focusableOnly = false, std::optional floating = {}); PHLWINDOW getPrevWindowOnWorkspace(PHLWINDOW, bool focusableOnly = false, std::optional floating = {}); - int getNextAvailableNamedWorkspace(); + WORKSPACEID getNextAvailableNamedWorkspace(); bool isPointOnAnyMonitor(const Vector2D&); bool isPointOnReservedArea(const Vector2D& point, const CMonitor* monitor = nullptr); CMonitor* getMonitorInDirection(const char&); CMonitor* getMonitorInDirection(CMonitor*, const char&); void updateAllWindowsAnimatedDecorationValues(); - void updateWorkspaceWindows(const int64_t& id); + void updateWorkspaceWindows(const WORKSPACEID& id); void updateWindowAnimatedDecorationValues(PHLWINDOW); - int getNextAvailableMonitorID(std::string const& name); + MONITORID getNextAvailableMonitorID(std::string const& name); void moveWorkspaceToMonitor(PHLWORKSPACE, CMonitor*, bool noWarpCursor = false); void swapActiveWorkspaces(CMonitor*, CMonitor*); CMonitor* getMonitorFromString(const std::string&); - bool workspaceIDOutOfBounds(const int64_t&); + bool workspaceIDOutOfBounds(const WORKSPACEID&); void setWindowFullscreenInternal(const PHLWINDOW PWINDOW, const eFullscreenMode MODE); void setWindowFullscreenClient(const PHLWINDOW PWINDOW, const eFullscreenMode MODE); void setWindowFullscreenState(const PHLWINDOW PWINDOW, const sFullscreenState state); @@ -162,12 +162,13 @@ class CCompositor { PHLLS getLayerSurfaceFromSurface(SP); void closeWindow(PHLWINDOW); Vector2D parseWindowVectorArgsRelative(const std::string&, const Vector2D&); - void forceReportSizesToWindowsOnWorkspace(const int&); - PHLWORKSPACE createNewWorkspace(const int&, const int&, const std::string& name = "", bool isEmtpy = true); // will be deleted next frame if left empty and unfocused! - void renameWorkspace(const int&, const std::string& name = ""); + void forceReportSizesToWindowsOnWorkspace(const WORKSPACEID&); + PHLWORKSPACE createNewWorkspace(const WORKSPACEID&, const MONITORID&, const std::string& name = "", + bool isEmtpy = true); // will be deleted next frame if left empty and unfocused! + void renameWorkspace(const WORKSPACEID&, const std::string& name = ""); void setActiveMonitor(CMonitor*); - bool isWorkspaceSpecial(const int&); - int getNewSpecialID(); + bool isWorkspaceSpecial(const WORKSPACEID&); + WORKSPACEID getNewSpecialID(); void performUserChecks(); void moveWindowToWorkspaceSafe(PHLWINDOW pWindow, PHLWORKSPACE pWorkspace); PHLWINDOW getForceFocus(); diff --git a/src/SharedDefs.hpp b/src/SharedDefs.hpp index 2a1546c6..9bee7150 100644 --- a/src/SharedDefs.hpp +++ b/src/SharedDefs.hpp @@ -52,4 +52,8 @@ struct SHyprCtlCommand { std::function fn; }; +typedef int64_t WINDOWID; +typedef int64_t MONITORID; +typedef int64_t WORKSPACEID; + typedef std::function HOOK_CALLBACK_FN; diff --git a/src/config/ConfigManager.cpp b/src/config/ConfigManager.cpp index be6433fa..1a823f3e 100644 --- a/src/config/ConfigManager.cpp +++ b/src/config/ConfigManager.cpp @@ -2425,7 +2425,7 @@ std::optional CConfigManager::handleWorkspaceRules(const std::strin // } const static std::string ruleOnCreatedEmpty = "on-created-empty:"; - const static int ruleOnCreatedEmptyLen = ruleOnCreatedEmpty.length(); + const static auto ruleOnCreatedEmptyLen = ruleOnCreatedEmpty.length(); auto assignRule = [&](std::string rule) -> std::optional { size_t delim = std::string::npos; diff --git a/src/config/ConfigManager.hpp b/src/config/ConfigManager.hpp index 75dea9ef..38dd0872 100644 --- a/src/config/ConfigManager.hpp +++ b/src/config/ConfigManager.hpp @@ -33,7 +33,7 @@ struct SWorkspaceRule { std::string monitor = ""; std::string workspaceString = ""; std::string workspaceName = ""; - int workspaceId = -1; + WORKSPACEID workspaceId = -1; bool isDefault = false; bool isPersistent = false; std::optional gapsIn; diff --git a/src/debug/HyprCtl.cpp b/src/debug/HyprCtl.cpp index d91a1cec..3ab0fa7a 100644 --- a/src/debug/HyprCtl.cpp +++ b/src/debug/HyprCtl.cpp @@ -71,7 +71,7 @@ static std::string availableModesForOutput(CMonitor* pMonitor, eHyprCtlOutputFor std::string CHyprCtl::getMonitorData(Hyprutils::Memory::CSharedPointer m, eHyprCtlOutputFormat format) { std::string result; - if (!m->output || m->ID == -1ull) + if (!m->output || m->ID == -1) return ""; if (format == eHyprCtlOutputFormat::FORMAT_JSON) { @@ -155,7 +155,7 @@ std::string monitorsRequest(eHyprCtlOutputFormat format, std::string request) { result += "]"; } else { for (auto& m : allMonitors ? g_pCompositor->m_vRealMonitors : g_pCompositor->m_vMonitors) { - if (!m->output || m->ID == -1ull) + if (!m->output || m->ID == -1) continue; result += diff --git a/src/desktop/LayerSurface.cpp b/src/desktop/LayerSurface.cpp index 8fd448ef..c352fa74 100644 --- a/src/desktop/LayerSurface.cpp +++ b/src/desktop/LayerSurface.cpp @@ -432,8 +432,8 @@ void CLayerSurface::startAnimation(bool in, bool instant) { PMONITOR->vecPosition + Vector2D{PMONITOR->vecSize.x, PMONITOR->vecSize.y / 2}, }; - float closest = std::numeric_limits::max(); - int leader = force; + float closest = std::numeric_limits::max(); + size_t leader = force; if (leader == -1) { for (size_t i = 0; i < 4; ++i) { float dist = MIDDLE.distance(edgePoints[i]); diff --git a/src/desktop/LayerSurface.hpp b/src/desktop/LayerSurface.hpp index 056f66a8..84935b34 100644 --- a/src/desktop/LayerSurface.hpp +++ b/src/desktop/LayerSurface.hpp @@ -42,7 +42,7 @@ class CLayerSurface { bool mapped = false; uint32_t layer = 0; - int monitorID = -1; + MONITORID monitorID = -1; bool fadingOut = false; bool readyToDelete = false; @@ -51,7 +51,7 @@ class CLayerSurface { bool forceBlur = false; bool forceBlurPopups = false; - int xray = -1; + int64_t xray = -1; bool ignoreAlpha = false; float ignoreAlphaValue = 0.f; bool dimAround = false; diff --git a/src/desktop/Window.cpp b/src/desktop/Window.cpp index 93c208cf..dcdcb573 100644 --- a/src/desktop/Window.cpp +++ b/src/desktop/Window.cpp @@ -1243,7 +1243,7 @@ bool CWindow::isEffectiveInternalFSMode(const eFullscreenMode MODE) { return (eFullscreenMode)std::bit_floor((uint8_t)m_sFullscreenState.internal) == MODE; } -int CWindow::workspaceID() { +WORKSPACEID CWindow::workspaceID() { return m_pWorkspace ? m_pWorkspace->m_iID : m_iLastWorkspace; } diff --git a/src/desktop/Window.hpp b/src/desktop/Window.hpp index 11bf662a..2e5b54b1 100644 --- a/src/desktop/Window.hpp +++ b/src/desktop/Window.hpp @@ -270,7 +270,7 @@ class CWindow { bool m_bDraggingTiled = false; // for dragging around tiled windows bool m_bWasMaximized = false; sFullscreenState m_sFullscreenState = {.internal = FSMODE_NONE, .client = FSMODE_NONE}; - uint64_t m_iMonitorID = -1; + MONITORID m_iMonitorID = -1; std::string m_szTitle = ""; std::string m_szClass = ""; std::string m_szInitialTitle = ""; @@ -358,8 +358,8 @@ class CWindow { bool m_bStayFocused = false; // for toplevel monitor events - uint64_t m_iLastToplevelMonitorID = -1; - uint64_t m_iLastSurfaceMonitorID = -1; + MONITORID m_iLastToplevelMonitorID = -1; + MONITORID m_iLastSurfaceMonitorID = -1; // for idle inhibiting windows eIdleInhibitMode m_eIdleInhibitMode = IDLEINHIBIT_NONE; @@ -421,7 +421,7 @@ class CWindow { bool canBeTorn(); void setSuspended(bool suspend); bool visibleOnMonitor(CMonitor* pMonitor); - int workspaceID(); + WORKSPACEID workspaceID(); bool onSpecialWorkspace(); void activate(bool force = false); int surfacesCount(); @@ -490,9 +490,9 @@ class CWindow { private: // For hidden windows and stuff - bool m_bHidden = false; - bool m_bSuspended = false; - int m_iLastWorkspace = WORKSPACE_INVALID; + bool m_bHidden = false; + bool m_bSuspended = false; + WORKSPACEID m_iLastWorkspace = WORKSPACE_INVALID; }; inline bool valid(PHLWINDOW w) { diff --git a/src/desktop/Workspace.cpp b/src/desktop/Workspace.cpp index a08f1804..d9ac7927 100644 --- a/src/desktop/Workspace.cpp +++ b/src/desktop/Workspace.cpp @@ -5,13 +5,13 @@ #include using namespace Hyprutils::String; -PHLWORKSPACE CWorkspace::create(int id, int monitorID, std::string name, bool special, bool isEmtpy) { +PHLWORKSPACE CWorkspace::create(WORKSPACEID id, MONITORID monitorID, std::string name, bool special, bool isEmtpy) { PHLWORKSPACE workspace = makeShared(id, monitorID, name, special, isEmtpy); workspace->init(workspace); return workspace; } -CWorkspace::CWorkspace(int id, int monitorID, std::string name, bool special, bool isEmtpy) { +CWorkspace::CWorkspace(WORKSPACEID id, MONITORID monitorID, std::string name, bool special, bool isEmtpy) { m_iMonitorID = monitorID; m_iID = id; m_szName = name; @@ -190,7 +190,7 @@ void CWorkspace::setActive(bool on) { ; // empty until https://gitlab.freedesktop.org/wayland/wayland-protocols/-/merge_requests/40 } -void CWorkspace::moveToMonitor(const int& id) { +void CWorkspace::moveToMonitor(const MONITORID& id) { ; // empty until https://gitlab.freedesktop.org/wayland/wayland-protocols/-/merge_requests/40 } @@ -275,7 +275,7 @@ bool CWorkspace::matchesStaticSelector(const std::string& selector_) { i = std::min(NEXTSPACE, std::string::npos - 1); if (cur == 'r') { - int from = 0, to = 0; + WORKSPACEID from = 0, to = 0; if (!prop.starts_with("r[") || !prop.ends_with("]")) { Debug::log(LOG, "Invalid selector {}", selector); return false; @@ -365,7 +365,7 @@ bool CWorkspace::matchesStaticSelector(const std::string& selector_) { } if (cur == 'w') { - int from = 0, to = 0; + WORKSPACEID from = 0, to = 0; if (!prop.starts_with("w[") || !prop.ends_with("]")) { Debug::log(LOG, "Invalid selector {}", selector); return false; @@ -446,7 +446,7 @@ bool CWorkspace::matchesStaticSelector(const std::string& selector_) { return false; } - int count; + WORKSPACEID count; if (wantsCountGroup) count = g_pCompositor->getGroupsOnWorkspace(m_iID, wantsOnlyTiled == -1 ? std::nullopt : std::optional((bool)wantsOnlyTiled), wantsCountVisible ? std::optional(wantsCountVisible) : std::nullopt); @@ -506,7 +506,7 @@ bool CWorkspace::matchesStaticSelector(const std::string& selector_) { void CWorkspace::markInert() { m_bInert = true; m_iID = WORKSPACE_INVALID; - m_iMonitorID = -1; + m_iMonitorID = MONITOR_INVALID; m_bVisible = false; } diff --git a/src/desktop/Workspace.hpp b/src/desktop/Workspace.hpp index 3e9ac8a8..9cacb0cc 100644 --- a/src/desktop/Workspace.hpp +++ b/src/desktop/Workspace.hpp @@ -17,16 +17,16 @@ class CWindow; class CWorkspace { public: - static PHLWORKSPACE create(int id, int monitorID, std::string name, bool special = false, bool isEmtpy = true); + static PHLWORKSPACE create(WORKSPACEID id, MONITORID monitorID, std::string name, bool special = false, bool isEmtpy = true); // use create() don't use this - CWorkspace(int id, int monitorID, std::string name, bool special = false, bool isEmpty = true); + CWorkspace(WORKSPACEID id, MONITORID monitorID, std::string name, bool special = false, bool isEmpty = true); ~CWorkspace(); // Workspaces ID-based have IDs > 0 // and workspaces name-based have IDs starting with -1337 - int m_iID = -1; + WORKSPACEID m_iID = WORKSPACE_INVALID; std::string m_szName = ""; - uint64_t m_iMonitorID = -1; + MONITORID m_iMonitorID = MONITOR_INVALID; // Previous workspace ID and name is stored during a workspace change, allowing travel // to the previous workspace. SWorkspaceIDName m_sPrevWorkspace, m_sPrevWorkspacePerMonitor; @@ -67,7 +67,7 @@ class CWorkspace { void startAnim(bool in, bool left, bool instant = false); void setActive(bool on); - void moveToMonitor(const int&); + void moveToMonitor(const MONITORID&); PHLWINDOW getLastFocusedWindow(); void rememberPrevWorkspace(const PHLWORKSPACE& prevWorkspace); diff --git a/src/events/Windows.cpp b/src/events/Windows.cpp index 5d29a3b7..2eb7038f 100644 --- a/src/events/Windows.cpp +++ b/src/events/Windows.cpp @@ -148,7 +148,7 @@ void Events::listener_mapWindow(void* owner, void* data) { PWINDOW->m_iMonitorID = PMONITOR->ID; } else { if (isNumber(MONITORSTR)) { - const long int MONITOR = std::stoi(MONITORSTR); + const MONITORID MONITOR = std::stoi(MONITORSTR); if (!g_pCompositor->getMonitorFromID(MONITOR)) PWINDOW->m_iMonitorID = 0; else diff --git a/src/helpers/MiscFunctions.cpp b/src/helpers/MiscFunctions.cpp index 53c0dc13..a81aa7d1 100644 --- a/src/helpers/MiscFunctions.cpp +++ b/src/helpers/MiscFunctions.cpp @@ -249,7 +249,7 @@ SWorkspaceIDName getWorkspaceIDNameFromString(const std::string& in) { return {WORKSPACE_INVALID}; } - std::set invalidWSes; + std::set invalidWSes; if (same_mon) { for (auto& rule : g_pConfigManager->getAllWorkspaceRules()) { const auto PMONITOR = g_pCompositor->getMonitorFromName(rule.monitor); @@ -258,8 +258,8 @@ SWorkspaceIDName getWorkspaceIDNameFromString(const std::string& in) { } } - int id = next ? g_pCompositor->m_pLastMonitor->activeWorkspaceID() : 0; - while (++id < INT_MAX) { + WORKSPACEID id = next ? g_pCompositor->m_pLastMonitor->activeWorkspaceID() : 0; + while (++id < LONG_MAX) { const auto PWORKSPACE = g_pCompositor->getWorkspaceByID(id); if (!invalidWSes.contains(id) && (!PWORKSPACE || g_pCompositor->getWindowsOnWorkspace(id) == 0)) { result.id = id; @@ -296,9 +296,9 @@ SWorkspaceIDName getWorkspaceIDNameFromString(const std::string& in) { result.id = (int)PLUSMINUSRESULT.value(); - int remains = (int)result.id; + WORKSPACEID remains = result.id; - std::set invalidWSes; + std::set invalidWSes; // Collect all the workspaces we can't jump to. for (auto& ws : g_pCompositor->m_vWorkspaces) { @@ -318,7 +318,7 @@ SWorkspaceIDName getWorkspaceIDNameFromString(const std::string& in) { } // Prepare all named workspaces in case when we need them - std::vector namedWSes; + std::vector namedWSes; for (auto& ws : g_pCompositor->m_vWorkspaces) { if (ws->m_bIsSpecialWorkspace || (ws->m_iMonitorID != g_pCompositor->m_pLastMonitor->ID) || ws->m_iID >= 0) continue; @@ -347,18 +347,18 @@ SWorkspaceIDName getWorkspaceIDNameFromString(const std::string& in) { } else { // Just take a blind guess at where we'll probably end up - int activeWSID = g_pCompositor->m_pLastMonitor->activeWorkspace ? g_pCompositor->m_pLastMonitor->activeWorkspace->m_iID : 1; - int predictedWSID = activeWSID + remains; - int remainingWSes = 0; - char walkDir = in[1]; + WORKSPACEID activeWSID = g_pCompositor->m_pLastMonitor->activeWorkspace ? g_pCompositor->m_pLastMonitor->activeWorkspace->m_iID : 1; + WORKSPACEID predictedWSID = activeWSID + remains; + int remainingWSes = 0; + char walkDir = in[1]; // sanitize. 0 means invalid oob in - - predictedWSID = std::max(predictedWSID, 0); + predictedWSID = std::max(predictedWSID, 0L); // Count how many invalidWSes are in between (how bad the prediction was) - int beginID = in[1] == '+' ? activeWSID + 1 : predictedWSID; - int endID = in[1] == '+' ? predictedWSID : activeWSID; - auto begin = invalidWSes.upper_bound(beginID - 1); // upper_bound is >, we want >= + WORKSPACEID beginID = in[1] == '+' ? activeWSID + 1 : predictedWSID; + WORKSPACEID endID = in[1] == '+' ? predictedWSID : activeWSID; + auto begin = invalidWSes.upper_bound(beginID - 1); // upper_bound is >, we want >= for (auto it = begin; *it <= endID && it != invalidWSes.end(); it++) { remainingWSes++; } @@ -367,7 +367,7 @@ SWorkspaceIDName getWorkspaceIDNameFromString(const std::string& in) { if (activeWSID < 0) { // Behaviour similar to 'm' // Find current - int currentItem = -1; + size_t currentItem = -1; for (size_t i = 0; i < namedWSes.size(); i++) { if (namedWSes[i] == activeWSID) { currentItem = i; @@ -376,14 +376,14 @@ SWorkspaceIDName getWorkspaceIDNameFromString(const std::string& in) { } currentItem += remains; - currentItem = std::max(currentItem, 0); - if (currentItem >= (int)namedWSes.size()) { + currentItem = std::max(currentItem, 0UL); + if (currentItem >= namedWSes.size()) { // At the seam between namedWSes and normal WSes. Behave like r+[diff] at imaginary ws 0 - int diff = currentItem - (namedWSes.size() - 1); - predictedWSID = diff; - int beginID = 1; - int endID = predictedWSID; - auto begin = invalidWSes.upper_bound(beginID - 1); // upper_bound is >, we want >= + size_t diff = currentItem - (namedWSes.size() - 1); + predictedWSID = diff; + WORKSPACEID beginID = 1; + WORKSPACEID endID = predictedWSID; + auto begin = invalidWSes.upper_bound(beginID - 1); // upper_bound is >, we want >= for (auto it = begin; *it <= endID && it != invalidWSes.end(); it++) { remainingWSes++; } @@ -397,10 +397,10 @@ SWorkspaceIDName getWorkspaceIDNameFromString(const std::string& in) { // Go in the search direction for remainingWSes // The performance impact is directly proportional to the number of open and bound workspaces - int finalWSID = predictedWSID; + WORKSPACEID finalWSID = predictedWSID; if (walkDir == '-') { - int beginID = finalWSID; - int curID = finalWSID; + WORKSPACEID beginID = finalWSID; + WORKSPACEID curID = finalWSID; while (--curID > 0 && remainingWSes > 0) { if (!invalidWSes.contains(curID)) { remainingWSes--; @@ -411,9 +411,9 @@ SWorkspaceIDName getWorkspaceIDNameFromString(const std::string& in) { if (namedWSes.size()) { // Go to the named workspaces // Need remainingWSes more - int namedWSIdx = namedWSes.size() - remainingWSes; + auto namedWSIdx = namedWSes.size() - remainingWSes; // Sanitze - namedWSIdx = std::clamp(namedWSIdx, 0, (int)namedWSes.size() - 1); + namedWSIdx = std::clamp(namedWSIdx, 0UL, namedWSes.size() - 1); finalWSID = namedWSes[namedWSIdx]; } else { // Couldn't find valid workspace in negative direction, search last first one back up positive direction @@ -425,7 +425,7 @@ SWorkspaceIDName getWorkspaceIDNameFromString(const std::string& in) { } } if (walkDir == '+') { - int curID = finalWSID; + WORKSPACEID curID = finalWSID; while (++curID < INT32_MAX && remainingWSes > 0) { if (!invalidWSes.contains(curID)) { remainingWSes--; @@ -460,9 +460,9 @@ SWorkspaceIDName getWorkspaceIDNameFromString(const std::string& in) { result.id = (int)PLUSMINUSRESULT.value(); // result now has +/- what we should move on mon - int remains = (int)result.id; + int remains = (int)result.id; - std::vector validWSes; + std::vector validWSes; for (auto& ws : g_pCompositor->m_vWorkspaces) { if (ws->m_bIsSpecialWorkspace || (ws->m_iMonitorID != g_pCompositor->m_pLastMonitor->ID && !onAllMonitors)) continue; @@ -472,7 +472,7 @@ SWorkspaceIDName getWorkspaceIDNameFromString(const std::string& in) { std::sort(validWSes.begin(), validWSes.end()); - int currentItem = -1; + size_t currentItem = -1; if (absolute) { // 1-index @@ -481,7 +481,7 @@ SWorkspaceIDName getWorkspaceIDNameFromString(const std::string& in) { // clamp if (currentItem < 0) { currentItem = 0; - } else if (currentItem >= (int)validWSes.size()) { + } else if (currentItem >= validWSes.size()) { currentItem = validWSes.size() - 1; } } else { @@ -489,7 +489,7 @@ SWorkspaceIDName getWorkspaceIDNameFromString(const std::string& in) { remains = remains < 0 ? -((-remains) % validWSes.size()) : remains % validWSes.size(); // get the current item - int activeWSID = g_pCompositor->m_pLastMonitor->activeWorkspace ? g_pCompositor->m_pLastMonitor->activeWorkspace->m_iID : 1; + WORKSPACEID activeWSID = g_pCompositor->m_pLastMonitor->activeWorkspace ? g_pCompositor->m_pLastMonitor->activeWorkspace->m_iID : 1; for (size_t i = 0; i < validWSes.size(); i++) { if (validWSes[i] == activeWSID) { currentItem = i; @@ -501,7 +501,7 @@ SWorkspaceIDName getWorkspaceIDNameFromString(const std::string& in) { currentItem += remains; // sanitize - if (currentItem >= (int)validWSes.size()) { + if (currentItem >= validWSes.size()) { currentItem = currentItem % validWSes.size(); } else if (currentItem < 0) { currentItem = validWSes.size() + currentItem; @@ -547,9 +547,9 @@ std::optional cleanCmdForWorkspace(const std::string& inWorkspaceNa const std::string workspaceRule = "workspace " + inWorkspaceName; if (cmd[0] == '[') { - const int closingBracketIdx = cmd.find_last_of(']'); - auto tmpRules = cmd.substr(1, closingBracketIdx - 1); - cmd = cmd.substr(closingBracketIdx + 1); + const auto closingBracketIdx = cmd.find_last_of(']'); + auto tmpRules = cmd.substr(1, closingBracketIdx - 1); + cmd = cmd.substr(closingBracketIdx + 1); auto rulesList = CVarList(tmpRules, 0, ';'); @@ -785,13 +785,13 @@ std::vector getBacktrace() { #ifdef HAS_EXECINFO void* bt[1024]; - size_t btSize; + int btSize; char** btSymbols; btSize = backtrace(bt, 1024); btSymbols = backtrace_symbols(bt, btSize); - for (size_t i = 0; i < btSize; ++i) { + for (auto i = 0; i < btSize; ++i) { callstack.emplace_back(SCallstackFrameInfo{bt[i], std::string{btSymbols[i]}}); } #else diff --git a/src/helpers/MiscFunctions.hpp b/src/helpers/MiscFunctions.hpp index 49e3bced..7eb2a1ed 100644 --- a/src/helpers/MiscFunctions.hpp +++ b/src/helpers/MiscFunctions.hpp @@ -6,6 +6,8 @@ #include "math/Math.hpp" #include #include +#include "SharedDefs.hpp" +#include "macros.hpp" struct SCallstackFrameInfo { void* adr = nullptr; @@ -13,7 +15,7 @@ struct SCallstackFrameInfo { }; struct SWorkspaceIDName { - int id = -1; + WORKSPACEID id = WORKSPACE_INVALID; std::string name; }; diff --git a/src/helpers/Monitor.cpp b/src/helpers/Monitor.cpp index 8f23c462..f6b61d57 100644 --- a/src/helpers/Monitor.cpp +++ b/src/helpers/Monitor.cpp @@ -389,8 +389,8 @@ bool CMonitor::matchesStaticSelector(const std::string& selector) const { } } -int CMonitor::findAvailableDefaultWS() { - for (size_t i = 1; i < INT32_MAX; ++i) { +WORKSPACEID CMonitor::findAvailableDefaultWS() { + for (WORKSPACEID i = 1; i < LONG_MAX; ++i) { if (g_pCompositor->getWorkspaceByID(i)) continue; @@ -400,7 +400,7 @@ int CMonitor::findAvailableDefaultWS() { return i; } - return INT32_MAX; // shouldn't be reachable + return LONG_MAX; // shouldn't be reachable } void CMonitor::setupDefaultWS(const SMonitorRule& monitorRule) { @@ -638,7 +638,7 @@ void CMonitor::changeWorkspace(const PHLWORKSPACE& pWorkspace, bool internal, bo g_pCompositor->updateFullscreenFadeOnWorkspace(activeSpecialWorkspace); } -void CMonitor::changeWorkspace(const int& id, bool internal, bool noMouseMove, bool noFocus) { +void CMonitor::changeWorkspace(const WORKSPACEID& id, bool internal, bool noMouseMove, bool noFocus) { changeWorkspace(g_pCompositor->getWorkspaceByID(id), internal, noMouseMove, noFocus); } @@ -745,7 +745,7 @@ void CMonitor::setSpecialWorkspace(const PHLWORKSPACE& pWorkspace) { g_pCompositor->updateSuspendedStates(); } -void CMonitor::setSpecialWorkspace(const int& id) { +void CMonitor::setSpecialWorkspace(const WORKSPACEID& id) { setSpecialWorkspace(g_pCompositor->getWorkspaceByID(id)); } @@ -766,11 +766,11 @@ void CMonitor::updateMatrix() { } } -int64_t CMonitor::activeWorkspaceID() { +WORKSPACEID CMonitor::activeWorkspaceID() { return activeWorkspace ? activeWorkspace->m_iID : 0; } -int64_t CMonitor::activeSpecialWorkspaceID() { +WORKSPACEID CMonitor::activeSpecialWorkspaceID() { return activeSpecialWorkspace ? activeSpecialWorkspace->m_iID : 0; } diff --git a/src/helpers/Monitor.hpp b/src/helpers/Monitor.hpp index fbe26f67..7429ecf1 100644 --- a/src/helpers/Monitor.hpp +++ b/src/helpers/Monitor.hpp @@ -70,7 +70,7 @@ class CMonitor { bool primary = false; - uint64_t ID = -1; + MONITORID ID = MONITOR_INVALID; PHLWORKSPACE activeWorkspace = nullptr; PHLWORKSPACE activeSpecialWorkspace = nullptr; float setScale = 1; // scale set by cfg @@ -155,31 +155,31 @@ class CMonitor { std::array, 4> m_aLayerSurfaceLayers; // methods - void onConnect(bool noRule); - void onDisconnect(bool destroy = false); - void addDamage(const pixman_region32_t* rg); - void addDamage(const CRegion* rg); - void addDamage(const CBox* box); - bool shouldSkipScheduleFrameOnMouseEvent(); - void setMirror(const std::string&); - bool isMirror(); - bool matchesStaticSelector(const std::string& selector) const; - float getDefaultScale(); - void changeWorkspace(const PHLWORKSPACE& pWorkspace, bool internal = false, bool noMouseMove = false, bool noFocus = false); - void changeWorkspace(const int& id, bool internal = false, bool noMouseMove = false, bool noFocus = false); - void setSpecialWorkspace(const PHLWORKSPACE& pWorkspace); - void setSpecialWorkspace(const int& id); - void moveTo(const Vector2D& pos); - Vector2D middle(); - void updateMatrix(); - int64_t activeWorkspaceID(); - int64_t activeSpecialWorkspaceID(); - CBox logicalBox(); - void scheduleDone(); - bool attemptDirectScanout(); + void onConnect(bool noRule); + void onDisconnect(bool destroy = false); + void addDamage(const pixman_region32_t* rg); + void addDamage(const CRegion* rg); + void addDamage(const CBox* box); + bool shouldSkipScheduleFrameOnMouseEvent(); + void setMirror(const std::string&); + bool isMirror(); + bool matchesStaticSelector(const std::string& selector) const; + float getDefaultScale(); + void changeWorkspace(const PHLWORKSPACE& pWorkspace, bool internal = false, bool noMouseMove = false, bool noFocus = false); + void changeWorkspace(const WORKSPACEID& id, bool internal = false, bool noMouseMove = false, bool noFocus = false); + void setSpecialWorkspace(const PHLWORKSPACE& pWorkspace); + void setSpecialWorkspace(const WORKSPACEID& id); + void moveTo(const Vector2D& pos); + Vector2D middle(); + void updateMatrix(); + WORKSPACEID activeWorkspaceID(); + WORKSPACEID activeSpecialWorkspaceID(); + CBox logicalBox(); + void scheduleDone(); + bool attemptDirectScanout(); - bool m_bEnabled = false; - bool m_bRenderingInitPassed = false; + bool m_bEnabled = false; + bool m_bRenderingInitPassed = false; // For the list lookup @@ -189,7 +189,7 @@ class CMonitor { private: void setupDefaultWS(const SMonitorRule&); - int findAvailableDefaultWS(); + WORKSPACEID findAvailableDefaultWS(); wl_event_source* doneSource = nullptr; diff --git a/src/helpers/Timer.cpp b/src/helpers/Timer.cpp index ec530df4..7b1726df 100644 --- a/src/helpers/Timer.cpp +++ b/src/helpers/Timer.cpp @@ -8,7 +8,7 @@ std::chrono::steady_clock::duration CTimer::getDuration() { return std::chrono::steady_clock::now() - m_tpLastReset; } -int CTimer::getMillis() { +long CTimer::getMillis() { return std::chrono::duration_cast(getDuration()).count(); } diff --git a/src/helpers/Timer.hpp b/src/helpers/Timer.hpp index a6d1aeed..827e7625 100644 --- a/src/helpers/Timer.hpp +++ b/src/helpers/Timer.hpp @@ -6,7 +6,7 @@ class CTimer { public: void reset(); float getSeconds(); - int getMillis(); + long getMillis(); const std::chrono::steady_clock::time_point& chrono() const; private: diff --git a/src/layout/DwindleLayout.cpp b/src/layout/DwindleLayout.cpp index f287056f..acdc3de2 100644 --- a/src/layout/DwindleLayout.cpp +++ b/src/layout/DwindleLayout.cpp @@ -47,7 +47,7 @@ void SDwindleNodeData::getAllChildrenRecursive(std::deque* pD } } -int CHyprDwindleLayout::getNodesOnWorkspace(const int& id) { +int CHyprDwindleLayout::getNodesOnWorkspace(const WORKSPACEID& id) { int no = 0; for (auto& n : m_lDwindleNodesData) { if (n.workspaceID == id && n.valid) @@ -56,7 +56,7 @@ int CHyprDwindleLayout::getNodesOnWorkspace(const int& id) { return no; } -SDwindleNodeData* CHyprDwindleLayout::getFirstNodeOnWorkspace(const int& id) { +SDwindleNodeData* CHyprDwindleLayout::getFirstNodeOnWorkspace(const WORKSPACEID& id) { for (auto& n : m_lDwindleNodesData) { if (n.workspaceID == id && validMapped(n.pWindow)) return &n; @@ -64,7 +64,7 @@ SDwindleNodeData* CHyprDwindleLayout::getFirstNodeOnWorkspace(const int& id) { return nullptr; } -SDwindleNodeData* CHyprDwindleLayout::getClosestNodeOnWorkspace(const int& id, const Vector2D& point) { +SDwindleNodeData* CHyprDwindleLayout::getClosestNodeOnWorkspace(const WORKSPACEID& id, const Vector2D& point) { SDwindleNodeData* res = nullptr; double distClosest = -1; for (auto& n : m_lDwindleNodesData) { @@ -88,7 +88,7 @@ SDwindleNodeData* CHyprDwindleLayout::getNodeFromWindow(PHLWINDOW pWindow) { return nullptr; } -SDwindleNodeData* CHyprDwindleLayout::getMasterNodeOnWorkspace(const int& id) { +SDwindleNodeData* CHyprDwindleLayout::getMasterNodeOnWorkspace(const WORKSPACEID& id) { for (auto& n : m_lDwindleNodesData) { if (!n.pParent && n.workspaceID == id) return &n; @@ -535,7 +535,7 @@ void CHyprDwindleLayout::onWindowRemovedTiling(PHLWINDOW pWindow) { m_lDwindleNodesData.remove(*PNODE); } -void CHyprDwindleLayout::recalculateMonitor(const int& monid) { +void CHyprDwindleLayout::recalculateMonitor(const MONITORID& monid) { const auto PMONITOR = g_pCompositor->getMonitorFromID(monid); if (!PMONITOR || !PMONITOR->activeWorkspace) @@ -872,7 +872,7 @@ void CHyprDwindleLayout::moveWindowTo(PHLWINDOW pWindow, const std::string& dir, return; const auto PNODE = getNodeFromWindow(pWindow); - const int originalWorkspaceID = pWindow->workspaceID(); + const auto originalWorkspaceID = pWindow->workspaceID(); const Vector2D originalPos = pWindow->middle(); if (!PNODE) diff --git a/src/layout/DwindleLayout.hpp b/src/layout/DwindleLayout.hpp index f638f6a2..bbd511c2 100644 --- a/src/layout/DwindleLayout.hpp +++ b/src/layout/DwindleLayout.hpp @@ -24,7 +24,7 @@ struct SDwindleNodeData { CBox box = {0}; - int workspaceID = -1; + WORKSPACEID workspaceID = WORKSPACE_INVALID; float splitRatio = 1.f; @@ -48,7 +48,7 @@ class CHyprDwindleLayout : public IHyprLayout { virtual void onWindowCreatedTiling(PHLWINDOW, eDirection direction = DIRECTION_DEFAULT); virtual void onWindowRemovedTiling(PHLWINDOW); virtual bool isWindowTiled(PHLWINDOW); - virtual void recalculateMonitor(const int&); + virtual void recalculateMonitor(const MONITORID&); virtual void recalculateWindow(PHLWINDOW); virtual void onBeginDragWindow(); virtual void resizeActiveWindow(const Vector2D&, eRectCorner corner = CORNER_NONE, PHLWINDOW pWindow = nullptr); @@ -77,13 +77,13 @@ class CHyprDwindleLayout : public IHyprLayout { std::optional m_vOverrideFocalPoint; // for onWindowCreatedTiling. - int getNodesOnWorkspace(const int&); + int getNodesOnWorkspace(const WORKSPACEID&); void applyNodeDataToWindow(SDwindleNodeData*, bool force = false); void calculateWorkspace(const PHLWORKSPACE& pWorkspace); SDwindleNodeData* getNodeFromWindow(PHLWINDOW); - SDwindleNodeData* getFirstNodeOnWorkspace(const int&); - SDwindleNodeData* getClosestNodeOnWorkspace(const int&, const Vector2D&); - SDwindleNodeData* getMasterNodeOnWorkspace(const int&); + SDwindleNodeData* getFirstNodeOnWorkspace(const WORKSPACEID&); + SDwindleNodeData* getClosestNodeOnWorkspace(const WORKSPACEID&, const Vector2D&); + SDwindleNodeData* getMasterNodeOnWorkspace(const WORKSPACEID&); void toggleSplit(PHLWINDOW); void swapSplit(PHLWINDOW); diff --git a/src/layout/IHyprLayout.hpp b/src/layout/IHyprLayout.hpp index 4b1b59e3..7e0d5704 100644 --- a/src/layout/IHyprLayout.hpp +++ b/src/layout/IHyprLayout.hpp @@ -63,7 +63,7 @@ class IHyprLayout { Called when the monitor requires a layout recalculation this usually means reserved area changes */ - virtual void recalculateMonitor(const int&) = 0; + virtual void recalculateMonitor(const MONITORID&) = 0; /* Called when the compositor requests a window diff --git a/src/layout/MasterLayout.cpp b/src/layout/MasterLayout.cpp index be00168f..aa1c0adf 100644 --- a/src/layout/MasterLayout.cpp +++ b/src/layout/MasterLayout.cpp @@ -14,7 +14,7 @@ SMasterNodeData* CHyprMasterLayout::getNodeFromWindow(PHLWINDOW pWindow) { return nullptr; } -int CHyprMasterLayout::getNodesOnWorkspace(const int& ws) { +int CHyprMasterLayout::getNodesOnWorkspace(const WORKSPACEID& ws) { int no = 0; for (auto& n : m_lMasterNodesData) { if (n.workspaceID == ws) @@ -24,7 +24,7 @@ int CHyprMasterLayout::getNodesOnWorkspace(const int& ws) { return no; } -int CHyprMasterLayout::getMastersOnWorkspace(const int& ws) { +int CHyprMasterLayout::getMastersOnWorkspace(const WORKSPACEID& ws) { int no = 0; for (auto& n : m_lMasterNodesData) { if (n.workspaceID == ws && n.isMaster) @@ -34,7 +34,7 @@ int CHyprMasterLayout::getMastersOnWorkspace(const int& ws) { return no; } -SMasterWorkspaceData* CHyprMasterLayout::getMasterWorkspaceData(const int& ws) { +SMasterWorkspaceData* CHyprMasterLayout::getMasterWorkspaceData(const WORKSPACEID& ws) { for (auto& n : m_lMasterWorkspacesData) { if (n.workspaceID == ws) return &n; @@ -63,7 +63,7 @@ std::string CHyprMasterLayout::getLayoutName() { return "Master"; } -SMasterNodeData* CHyprMasterLayout::getMasterNodeOnWorkspace(const int& ws) { +SMasterNodeData* CHyprMasterLayout::getMasterNodeOnWorkspace(const WORKSPACEID& ws) { for (auto& n : m_lMasterNodesData) { if (n.isMaster && n.workspaceID == ws) return &n; @@ -304,7 +304,7 @@ void CHyprMasterLayout::onWindowRemovedTiling(PHLWINDOW pWindow) { recalculateMonitor(pWindow->m_iMonitorID); } -void CHyprMasterLayout::recalculateMonitor(const int& monid) { +void CHyprMasterLayout::recalculateMonitor(const MONITORID& monid) { const auto PMONITOR = g_pCompositor->getMonitorFromID(monid); if (!PMONITOR || !PMONITOR->activeWorkspace) diff --git a/src/layout/MasterLayout.hpp b/src/layout/MasterLayout.hpp index fdb916e5..b72be74f 100644 --- a/src/layout/MasterLayout.hpp +++ b/src/layout/MasterLayout.hpp @@ -30,7 +30,7 @@ struct SMasterNodeData { float percSize = 1.f; // size multiplier for resizing children - int workspaceID = -1; + WORKSPACEID workspaceID = WORKSPACE_INVALID; bool ignoreFullscreenChecks = false; @@ -41,7 +41,7 @@ struct SMasterNodeData { }; struct SMasterWorkspaceData { - int workspaceID = -1; + WORKSPACEID workspaceID = WORKSPACE_INVALID; eOrientation orientation = ORIENTATION_LEFT; // @@ -55,7 +55,7 @@ class CHyprMasterLayout : public IHyprLayout { virtual void onWindowCreatedTiling(PHLWINDOW, eDirection direction = DIRECTION_DEFAULT); virtual void onWindowRemovedTiling(PHLWINDOW); virtual bool isWindowTiled(PHLWINDOW); - virtual void recalculateMonitor(const int&); + virtual void recalculateMonitor(const MONITORID&); virtual void recalculateWindow(PHLWINDOW); virtual void resizeActiveWindow(const Vector2D&, eRectCorner corner = CORNER_NONE, PHLWINDOW pWindow = nullptr); virtual void fullscreenRequestForWindow(PHLWINDOW pWindow, const eFullscreenMode CURRENT_EFFECTIVE_MODE, const eFullscreenMode EFFECTIVE_MODE); @@ -81,14 +81,14 @@ class CHyprMasterLayout : public IHyprLayout { void buildOrientationCycleVectorFromEOperation(std::vector& cycle); void runOrientationCycle(SLayoutMessageHeader& header, CVarList* vars, int next); eOrientation getDynamicOrientation(PHLWORKSPACE); - int getNodesOnWorkspace(const int&); + int getNodesOnWorkspace(const WORKSPACEID&); void applyNodeDataToWindow(SMasterNodeData*); SMasterNodeData* getNodeFromWindow(PHLWINDOW); - SMasterNodeData* getMasterNodeOnWorkspace(const int&); - SMasterWorkspaceData* getMasterWorkspaceData(const int&); + SMasterNodeData* getMasterNodeOnWorkspace(const WORKSPACEID&); + SMasterWorkspaceData* getMasterWorkspaceData(const WORKSPACEID&); void calculateWorkspace(PHLWORKSPACE); PHLWINDOW getNextWindow(PHLWINDOW, bool); - int getMastersOnWorkspace(const int&); + int getMastersOnWorkspace(const WORKSPACEID&); friend struct SMasterNodeData; friend struct SMasterWorkspaceData; diff --git a/src/macros.hpp b/src/macros.hpp index b2adb036..44014085 100644 --- a/src/macros.hpp +++ b/src/macros.hpp @@ -27,6 +27,8 @@ #define WORKSPACE_INVALID -1L #define WORKSPACE_NOT_CHANGED -101 +#define MONITOR_INVALID -1L + #define LISTENER(name) \ void listener_##name(wl_listener*, void*); \ inline wl_listener listen_##name = {.notify = listener_##name} diff --git a/src/managers/KeybindManager.cpp b/src/managers/KeybindManager.cpp index c7b93730..d4bac507 100644 --- a/src/managers/KeybindManager.cpp +++ b/src/managers/KeybindManager.cpp @@ -1738,7 +1738,7 @@ void CKeybindManager::moveWorkspaceToMonitor(std::string args) { return; } - const int WORKSPACEID = getWorkspaceIDNameFromString(workspace).id; + const auto WORKSPACEID = getWorkspaceIDNameFromString(workspace).id; if (WORKSPACEID == WORKSPACE_INVALID) { Debug::log(ERR, "moveWorkspaceToMonitor invalid workspace!"); @@ -1756,7 +1756,7 @@ void CKeybindManager::moveWorkspaceToMonitor(std::string args) { } void CKeybindManager::focusWorkspaceOnCurrentMonitor(std::string args) { - int workspaceID = getWorkspaceIDNameFromString(args).id; + auto workspaceID = getWorkspaceIDNameFromString(args).id; if (workspaceID == WORKSPACE_INVALID) { Debug::log(ERR, "focusWorkspaceOnCurrentMonitor invalid workspace!"); return; @@ -1816,7 +1816,7 @@ void CKeybindManager::toggleSpecialWorkspace(std::string args) { bool requestedWorkspaceIsAlreadyOpen = false; const auto PMONITOR = g_pCompositor->m_pLastMonitor; - int specialOpenOnMonitor = PMONITOR->activeSpecialWorkspaceID(); + auto specialOpenOnMonitor = PMONITOR->activeSpecialWorkspaceID(); for (auto& m : g_pCompositor->m_vMonitors) { if (m->activeSpecialWorkspaceID() == workspaceID) { diff --git a/src/managers/eventLoop/EventLoopManager.cpp b/src/managers/eventLoop/EventLoopManager.cpp index c2c088f8..041e7101 100644 --- a/src/managers/eventLoop/EventLoopManager.cpp +++ b/src/managers/eventLoop/EventLoopManager.cpp @@ -76,8 +76,8 @@ void CEventLoopManager::removeTimer(SP timer) { } static void timespecAddNs(timespec* pTimespec, int64_t delta) { - int delta_ns_low = delta % TIMESPEC_NSEC_PER_SEC; - int delta_s_high = delta / TIMESPEC_NSEC_PER_SEC; + auto delta_ns_low = delta % TIMESPEC_NSEC_PER_SEC; + auto delta_s_high = delta / TIMESPEC_NSEC_PER_SEC; pTimespec->tv_sec += delta_s_high; diff --git a/src/managers/input/InputMethodPopup.hpp b/src/managers/input/InputMethodPopup.hpp index f6e5c8be..f8e4b962 100644 --- a/src/managers/input/InputMethodPopup.hpp +++ b/src/managers/input/InputMethodPopup.hpp @@ -33,7 +33,7 @@ class CInputPopup { WP popup; SP surface; CBox lastBoxLocal; - uint64_t lastMonitor = -1; + MONITORID lastMonitor = MONITOR_INVALID; struct { CHyprSignalListener map; diff --git a/src/managers/input/Swipe.cpp b/src/managers/input/Swipe.cpp index c0e6c4f0..6ee690cd 100644 --- a/src/managers/input/Swipe.cpp +++ b/src/managers/input/Swipe.cpp @@ -77,7 +77,7 @@ void CInputManager::endWorkspaceSwipe() { // left of where we started. Instead, it's one more than the greatest // workspace ID that currently exists. if (workspaceIDRight <= m_sActiveSwipe.pWorkspaceBegin->m_iID && *PSWIPENEW) { - int maxWorkspace = 0; + WORKSPACEID maxWorkspace = 0; for (const auto& ws : g_pCompositor->m_vWorkspaces) { maxWorkspace = std::max(maxWorkspace, ws->m_iID); } diff --git a/src/protocols/ForeignToplevelWlr.cpp b/src/protocols/ForeignToplevelWlr.cpp index 295834ea..b31a4083 100644 --- a/src/protocols/ForeignToplevelWlr.cpp +++ b/src/protocols/ForeignToplevelWlr.cpp @@ -119,7 +119,7 @@ wl_resource* CForeignToplevelHandleWlr::res() { } void CForeignToplevelHandleWlr::sendMonitor(CMonitor* pMonitor) { - if (lastMonitorID == (int64_t)pMonitor->ID) + if (lastMonitorID == pMonitor->ID) return; const auto CLIENT = resource->client(); diff --git a/src/protocols/ForeignToplevelWlr.hpp b/src/protocols/ForeignToplevelWlr.hpp index e3b6f3f3..99f63b47 100644 --- a/src/protocols/ForeignToplevelWlr.hpp +++ b/src/protocols/ForeignToplevelWlr.hpp @@ -20,7 +20,7 @@ class CForeignToplevelHandleWlr { SP resource; PHLWINDOWREF pWindow; bool closed = false; - int64_t lastMonitorID = -1; + MONITORID lastMonitorID = MONITOR_INVALID; void sendMonitor(CMonitor* pMonitor); void sendState(); diff --git a/src/render/Framebuffer.cpp b/src/render/Framebuffer.cpp index 67629e23..c48ff6f3 100644 --- a/src/render/Framebuffer.cpp +++ b/src/render/Framebuffer.cpp @@ -12,9 +12,10 @@ bool CFramebuffer::alloc(int w, int h, uint32_t drmFormat) { uint32_t glFormat = FormatUtils::drmFormatToGL(drmFormat); uint32_t glType = FormatUtils::glFormatToType(glFormat); - if (m_iFb == (uint32_t)-1) { + if (!m_iFbAllocated) { firstAlloc = true; glGenFramebuffers(1, &m_iFb); + m_iFbAllocated = true; } if (m_cTex->m_iTexID == 0) { @@ -88,12 +89,12 @@ void CFramebuffer::bind() { } void CFramebuffer::release() { - if (m_iFb != (uint32_t)-1 && m_iFb) + if (m_iFbAllocated) glDeleteFramebuffers(1, &m_iFb); m_cTex->destroyTexture(); - m_iFb = -1; - m_vSize = Vector2D(); + m_iFbAllocated = false; + m_vSize = Vector2D(); } CFramebuffer::~CFramebuffer() { @@ -101,5 +102,5 @@ CFramebuffer::~CFramebuffer() { } bool CFramebuffer::isAllocated() { - return m_iFb != (GLuint)-1; + return m_iFbAllocated; } \ No newline at end of file diff --git a/src/render/Framebuffer.hpp b/src/render/Framebuffer.hpp index a46a4859..ca7f9e8a 100644 --- a/src/render/Framebuffer.hpp +++ b/src/render/Framebuffer.hpp @@ -18,7 +18,8 @@ class CFramebuffer { Vector2D m_vSize; SP m_cTex; - GLuint m_iFb = -1; + GLuint m_iFb; + bool m_iFbAllocated{false}; SP m_pStencilTex; }; \ No newline at end of file diff --git a/src/render/OpenGL.cpp b/src/render/OpenGL.cpp index c355f4f9..0461662c 100644 --- a/src/render/OpenGL.cpp +++ b/src/render/OpenGL.cpp @@ -1247,14 +1247,14 @@ void CHyprOpenGLImpl::renderRectWithBlur(CBox* box, const CColor& col, int round glEnable(GL_STENCIL_TEST); - glStencilFunc(GL_ALWAYS, 1, -1); + glStencilFunc(GL_ALWAYS, 1, 0xFF); glStencilOp(GL_KEEP, GL_KEEP, GL_REPLACE); glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE); renderRect(box, CColor(0, 0, 0, 0), round); glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE); - glStencilFunc(GL_EQUAL, 1, -1); + glStencilFunc(GL_EQUAL, 1, 0xFF); glStencilOp(GL_KEEP, GL_KEEP, GL_REPLACE); scissor(box); @@ -1269,7 +1269,7 @@ void CHyprOpenGLImpl::renderRectWithBlur(CBox* box, const CColor& col, int round glClearStencil(0); glClear(GL_STENCIL_BUFFER_BIT); glDisable(GL_STENCIL_TEST); - glStencilMask(-1); + glStencilMask(0xFF); glStencilFunc(GL_ALWAYS, 1, 0xFF); scissor((CBox*)nullptr); @@ -1802,12 +1802,12 @@ CFramebuffer* CHyprOpenGLImpl::blurMainFramebufferWithDamage(float a, CRegion* o CRegion tempDamage{damage}; // and draw - for (int i = 1; i <= *PBLURPASSES; ++i) { + for (auto i = 1; i <= *PBLURPASSES; ++i) { tempDamage = damage.copy().scale(1.f / (1 << i)); drawPass(&m_RenderData.pCurrentMonData->m_shBLUR1, &tempDamage); // down } - for (int i = *PBLURPASSES - 1; i >= 0; --i) { + for (auto i = *PBLURPASSES - 1; i >= 0; --i) { tempDamage = damage.copy().scale(1.f / (1 << i)); // when upsampling we make the region twice as big drawPass(&m_RenderData.pCurrentMonData->m_shBLUR2, &tempDamage); // up } @@ -2091,7 +2091,7 @@ void CHyprOpenGLImpl::renderTextureWithBlur(SP tex, CBox* pBox, float glEnable(GL_STENCIL_TEST); - glStencilFunc(GL_ALWAYS, 1, -1); + glStencilFunc(GL_ALWAYS, 1, 0xFF); glStencilOp(GL_KEEP, GL_KEEP, GL_REPLACE); glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE); @@ -2101,7 +2101,7 @@ void CHyprOpenGLImpl::renderTextureWithBlur(SP tex, CBox* pBox, float renderTexture(tex, pBox, a, round, true, true); // discard opaque glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE); - glStencilFunc(GL_EQUAL, 1, -1); + glStencilFunc(GL_EQUAL, 1, 0xFF); glStencilOp(GL_KEEP, GL_KEEP, GL_REPLACE); // stencil done. Render everything. @@ -2124,7 +2124,7 @@ void CHyprOpenGLImpl::renderTextureWithBlur(SP tex, CBox* pBox, float glDisable(GL_STENCIL_TEST); renderTextureInternalWithDamage(tex, pBox, a, &texDamage, round, false, false, true, true); - glStencilMask(-1); + glStencilMask(0xFF); glStencilFunc(GL_ALWAYS, 1, 0xFF); scissor((CBox*)nullptr); } diff --git a/src/render/Renderer.cpp b/src/render/Renderer.cpp index 7b29eb77..17aed940 100644 --- a/src/render/Renderer.cpp +++ b/src/render/Renderer.cpp @@ -1658,7 +1658,7 @@ void CHyprRenderer::arrangeLayerArray(CMonitor* pMonitor, const std::vectorgetMonitorFromID(monitor); if (!PMONITOR) diff --git a/src/render/Renderer.hpp b/src/render/Renderer.hpp index 84501821..0b16efea 100644 --- a/src/render/Renderer.hpp +++ b/src/render/Renderer.hpp @@ -49,7 +49,7 @@ class CHyprRenderer { ~CHyprRenderer(); void renderMonitor(CMonitor* pMonitor); - void arrangeLayersForMonitor(const int&); + void arrangeLayersForMonitor(const MONITORID&); void damageSurface(SP, double, double, double scale = 1.0); void damageWindow(PHLWINDOW, bool forceFull = false); void damageBox(CBox*, bool skipFrameSchedule = false); diff --git a/src/signal-safe.cpp b/src/signal-safe.cpp index 05ca9c65..44d23f9b 100644 --- a/src/signal-safe.cpp +++ b/src/signal-safe.cpp @@ -10,7 +10,7 @@ extern char** environ; char const* sig_getenv(char const* name) { - int len = strlen(name); + size_t len = strlen(name); for (char** var = environ; *var != NULL; var++) { if (strncmp(*var, name, len) == 0 && (*var)[len] == '=') { return (*var) + len + 1; diff --git a/src/signal-safe.hpp b/src/signal-safe.hpp index 3a38f043..ef643097 100644 --- a/src/signal-safe.hpp +++ b/src/signal-safe.hpp @@ -139,7 +139,7 @@ class BufFileWriter { abort(); } else { close(pipefd[1]); - int len; + long len; char readbuf[256]; while ((len = read(pipefd[0], readbuf, 256)) > 0) { write(readbuf, len); @@ -155,7 +155,7 @@ class BufFileWriter { void flush() { size_t i = 0; while (i < m_writeBufPos) { - int written = ::write(m_fd, m_writeBuf + i, m_writeBufPos - i); + auto written = ::write(m_fd, m_writeBuf + i, m_writeBufPos - i); if (written <= 0) { return; } From fd1d4e288edd586a3d5273cda053a51f5b14cad7 Mon Sep 17 00:00:00 2001 From: "Mathis H." Date: Fri, 9 Aug 2024 14:51:21 +0000 Subject: [PATCH 0254/2181] headers: set correct paths to header files (#7245) --- src/helpers/MiscFunctions.hpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/helpers/MiscFunctions.hpp b/src/helpers/MiscFunctions.hpp index 7eb2a1ed..8b2ea0d1 100644 --- a/src/helpers/MiscFunctions.hpp +++ b/src/helpers/MiscFunctions.hpp @@ -6,8 +6,8 @@ #include "math/Math.hpp" #include #include -#include "SharedDefs.hpp" -#include "macros.hpp" +#include "../SharedDefs.hpp" +#include "../macros.hpp" struct SCallstackFrameInfo { void* adr = nullptr; From 8b37e81374928856d8fd859b95a62c8bf4211901 Mon Sep 17 00:00:00 2001 From: Tom Englund Date: Fri, 9 Aug 2024 19:33:20 +0200 Subject: [PATCH 0255/2181] cursormgr: add a new setting to sync gsettings (#7253) cursor:sync_gsettings_theme is set to default true and if enabled it will now sync xcursor theme loading with gsettings if it can, meaning CSD clients will now also change to the appropiate theme upon start and hyprctl setcursor THEME SIZE . --- CMakeLists.txt | 1 + meson.build | 2 ++ src/config/ConfigManager.cpp | 1 + src/managers/XCursorManager.cpp | 59 +++++++++++++++++++++++++++++++++ src/managers/XCursorManager.hpp | 1 + src/meson.build | 1 + 6 files changed, 65 insertions(+) diff --git a/CMakeLists.txt b/CMakeLists.txt index cfbd431f..d8c45bbe 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -117,6 +117,7 @@ pkg_check_modules( libliftoff libudev gbm + gio-2.0 hyprlang>=0.3.2 hyprcursor>=0.1.7 hyprutils>=0.2.1) diff --git a/meson.build b/meson.build index e8cd25b4..6a9b7ac5 100644 --- a/meson.build +++ b/meson.build @@ -34,6 +34,8 @@ xcb_render_dep = dependency('xcb-render', required: get_option('xwayland')) xcb_res_dep = dependency('xcb-res', required: get_option('xwayland')) xcb_xfixes_dep = dependency('xcb-xfixes', required: get_option('xwayland')) +gio_dep = dependency('gio-2.0', required:true) + cmake = import('cmake') udis = cmake.subproject('udis86') udis86 = udis.dependency('libudis86') diff --git a/src/config/ConfigManager.cpp b/src/config/ConfigManager.cpp index 1a823f3e..fb93032a 100644 --- a/src/config/ConfigManager.cpp +++ b/src/config/ConfigManager.cpp @@ -539,6 +539,7 @@ CConfigManager::CConfigManager() { m_pConfig->addConfigValue("cursor:zoom_factor", {1.f}); m_pConfig->addConfigValue("cursor:zoom_rigid", Hyprlang::INT{0}); m_pConfig->addConfigValue("cursor:enable_hyprcursor", Hyprlang::INT{1}); + m_pConfig->addConfigValue("cursor:sync_gsettings_theme", Hyprlang::INT{1}); m_pConfig->addConfigValue("cursor:hide_on_key_press", Hyprlang::INT{0}); m_pConfig->addConfigValue("cursor:hide_on_touch", Hyprlang::INT{1}); m_pConfig->addConfigValue("cursor:allow_dumb_copy", Hyprlang::INT{0}); diff --git a/src/managers/XCursorManager.cpp b/src/managers/XCursorManager.cpp index f2a7ab53..1108bbb2 100644 --- a/src/managers/XCursorManager.cpp +++ b/src/managers/XCursorManager.cpp @@ -1,6 +1,9 @@ #include #include #include +#include +#include +#include "config/ConfigValue.hpp" #include "helpers/CursorShapes.hpp" #include "debug/Log.hpp" #include "XCursorManager.hpp" @@ -146,6 +149,10 @@ void CXCursorManager::loadTheme(std::string const& name, int size) { cursors.emplace_back(cursor); } + + static auto SYNCGSETTINGS = CConfigValue("cursor:sync_gsettings_theme"); + if (*SYNCGSETTINGS) + syncGsettings(); } SP CXCursorManager::getShape(std::string const& shape, int size) { @@ -542,3 +549,55 @@ std::vector> CXCursorManager::loadAllFromDir(std::string const& pa return newCursors; } + +void CXCursorManager::syncGsettings() { + auto checkParamExists = [](std::string const& paramName, std::string const& category) { + auto* gSettingsSchemaSource = g_settings_schema_source_get_default(); + + if (!gSettingsSchemaSource) { + Debug::log(WARN, "GSettings default schema source does not exist, cant sync GSettings"); + return false; + } + + auto* gSettingsSchema = g_settings_schema_source_lookup(gSettingsSchemaSource, category.c_str(), true); + bool hasParam = false; + + if (gSettingsSchema != NULL) { + hasParam = gSettingsSchema && g_settings_schema_has_key(gSettingsSchema, paramName.c_str()); + g_settings_schema_unref(gSettingsSchema); + } + + return hasParam; + }; + + using SettingValue = std::variant; + auto setValue = [&checkParamExists](std::string const& paramName, const SettingValue& paramValue, std::string const& category) { + if (!checkParamExists(paramName, category)) { + Debug::log(WARN, "GSettings parameter doesnt exist {} in {}", paramName, category); + return; + } + + auto* gsettings = g_settings_new(category.c_str()); + + if (!gsettings) { + Debug::log(WARN, "GSettings failed to allocate new settings with category {}", category); + return; + } + + std::visit( + [&](auto&& value) { + using T = std::decay_t; + if constexpr (std::is_same_v) + g_settings_set_string(gsettings, paramName.c_str(), value.c_str()); + else if constexpr (std::is_same_v) + g_settings_set_int(gsettings, paramName.c_str(), value); + }, + paramValue); + + g_settings_sync(); + g_object_unref(gsettings); + }; + + setValue("cursor-theme", themeName, "org.gnome.desktop.interface"); + setValue("cursor-size", lastLoadSize, "org.gnome.desktop.interface"); +} diff --git a/src/managers/XCursorManager.hpp b/src/managers/XCursorManager.hpp index 20637055..464c1ec3 100644 --- a/src/managers/XCursorManager.hpp +++ b/src/managers/XCursorManager.hpp @@ -38,6 +38,7 @@ class CXCursorManager { std::string getLegacyShapeName(std::string const& shape); std::vector> loadStandardCursors(std::string const& name, int size); std::vector> loadAllFromDir(std::string const& path, int size); + void syncGsettings(); int lastLoadSize = 0; std::string themeName = ""; diff --git a/src/meson.build b/src/meson.build index 098d8298..475ecc24 100644 --- a/src/meson.build +++ b/src/meson.build @@ -28,6 +28,7 @@ executable('Hyprland', src, xcb_xfixes_dep, backtrace_dep, epoll_dep, + gio_dep, udis86, dependency('pixman-1'), From 4fdc0d55e4b44bb5300679025d2378fb6de0cae4 Mon Sep 17 00:00:00 2001 From: Vaxry Date: Sat, 10 Aug 2024 00:04:26 +0200 Subject: [PATCH 0256/2181] eventloop: don't dispatch in enterLoop ref #6842, BSD blocks in udev on no event apparently --- src/managers/eventLoop/EventLoopManager.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/src/managers/eventLoop/EventLoopManager.cpp b/src/managers/eventLoop/EventLoopManager.cpp index 041e7101..d1b85cf2 100644 --- a/src/managers/eventLoop/EventLoopManager.cpp +++ b/src/managers/eventLoop/EventLoopManager.cpp @@ -48,7 +48,6 @@ void CEventLoopManager::enterLoop() { aqPollFDs = g_pCompositor->m_pAqBackend->getPollFDs(); for (auto& fd : aqPollFDs) { m_sWayland.aqEventSources.emplace_back(wl_event_loop_add_fd(m_sWayland.loop, fd->fd, WL_EVENT_READABLE, aquamarineFDWrite, fd.get())); - fd->onSignal(); // dispatch outstanding } wl_display_run(m_sWayland.display); From 0bf9ceb53b338c79ab65e631877efcf96f53b49a Mon Sep 17 00:00:00 2001 From: Zach DeCook Date: Sat, 10 Aug 2024 16:09:12 -0400 Subject: [PATCH 0257/2181] core: Include cstring whenever strncpy is used (#7267) Fixes ppc64le build in alpine --- hyprctl/main.cpp | 1 + src/helpers/SdDaemon.cpp | 1 + src/managers/EventManager.cpp | 1 + src/xwayland/Server.cpp | 1 + 4 files changed, 4 insertions(+) diff --git a/hyprctl/main.cpp b/hyprctl/main.cpp index c86406fc..5d5113b8 100644 --- a/hyprctl/main.cpp +++ b/hyprctl/main.cpp @@ -26,6 +26,7 @@ #include #include #include +#include using namespace Hyprutils::String; #include "Strings.hpp" diff --git a/src/helpers/SdDaemon.cpp b/src/helpers/SdDaemon.cpp index 25e0ca3b..48c23e6b 100644 --- a/src/helpers/SdDaemon.cpp +++ b/src/helpers/SdDaemon.cpp @@ -8,6 +8,7 @@ #include #include #include +#include namespace Systemd { int SdBooted(void) { diff --git a/src/managers/EventManager.cpp b/src/managers/EventManager.cpp index 75c98e2a..079a6b68 100644 --- a/src/managers/EventManager.cpp +++ b/src/managers/EventManager.cpp @@ -8,6 +8,7 @@ #include #include #include +#include CEventManager::CEventManager() { m_iSocketFD = socket(AF_UNIX, SOCK_STREAM | SOCK_CLOEXEC | SOCK_NONBLOCK, 0); diff --git a/src/xwayland/Server.cpp b/src/xwayland/Server.cpp index cec582f6..200bec70 100644 --- a/src/xwayland/Server.cpp +++ b/src/xwayland/Server.cpp @@ -19,6 +19,7 @@ #include #include #include +#include // TODO: cleanup static bool set_cloexec(int fd, bool cloexec) { From 01ff5fdf6a00a9231bd3b56400d8bcab378c4257 Mon Sep 17 00:00:00 2001 From: Walt Bringenberg <44916811+wwaltb@users.noreply.github.com> Date: Sat, 10 Aug 2024 13:42:45 -0700 Subject: [PATCH 0258/2181] cursor: make inactive_timeout setting a float (#7268) --- src/config/ConfigManager.cpp | 2 +- src/render/Renderer.cpp | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/config/ConfigManager.cpp b/src/config/ConfigManager.cpp index fb93032a..edc1723d 100644 --- a/src/config/ConfigManager.cpp +++ b/src/config/ConfigManager.cpp @@ -531,7 +531,7 @@ CConfigManager::CConfigManager() { m_pConfig->addConfigValue("cursor:no_break_fs_vrr", Hyprlang::INT{0}); m_pConfig->addConfigValue("cursor:min_refresh_rate", Hyprlang::INT{24}); m_pConfig->addConfigValue("cursor:hotspot_padding", Hyprlang::INT{0}); - m_pConfig->addConfigValue("cursor:inactive_timeout", Hyprlang::INT{0}); + m_pConfig->addConfigValue("cursor:inactive_timeout", {0.f}); m_pConfig->addConfigValue("cursor:no_warps", Hyprlang::INT{0}); m_pConfig->addConfigValue("cursor:persistent_warps", Hyprlang::INT{0}); m_pConfig->addConfigValue("cursor:warp_on_change_workspace", Hyprlang::INT{0}); diff --git a/src/render/Renderer.cpp b/src/render/Renderer.cpp index 17aed940..a2d5a95e 100644 --- a/src/render/Renderer.cpp +++ b/src/render/Renderer.cpp @@ -2299,7 +2299,7 @@ void CHyprRenderer::setCursorFromName(const std::string& name, bool force) { } void CHyprRenderer::ensureCursorRenderingMode() { - static auto PCURSORTIMEOUT = CConfigValue("cursor:inactive_timeout"); + static auto PCURSORTIMEOUT = CConfigValue("cursor:inactive_timeout"); static auto PHIDEONTOUCH = CConfigValue("cursor:hide_on_touch"); static auto PHIDEONKEY = CConfigValue("cursor:hide_on_key_press"); From 511eea71c60e10f3d3d757a376f1ca98b9034ae0 Mon Sep 17 00:00:00 2001 From: Tom Englund Date: Sun, 11 Aug 2024 20:42:18 +0200 Subject: [PATCH 0259/2181] pointermgr: fix initial cursorwarp (#7286) change the hook to monitorAdded instead of newMonitor so its finalized in the compositor and added to vMonitors, move the checkDefaultCursorWarp to PointerManager and check for it upon mode change. and also ensure it doesnt go out of bounds by replacing it in the middle again on resolution changes. --- src/Compositor.cpp | 35 ------------------------ src/managers/PointerManager.cpp | 48 ++++++++++++++++++++++++++++++--- src/managers/PointerManager.hpp | 1 + 3 files changed, 45 insertions(+), 39 deletions(-) diff --git a/src/Compositor.cpp b/src/Compositor.cpp index e3a347fd..c3f95961 100644 --- a/src/Compositor.cpp +++ b/src/Compositor.cpp @@ -2918,39 +2918,6 @@ PHLWINDOW CCompositor::windowForCPointer(CWindow* pWindow) { return {}; } -static void checkDefaultCursorWarp(SP PNEWMONITOR, std::string monitorName) { - static auto PCURSORMONITOR = CConfigValue("cursor:default_monitor"); - static auto firstMonitorAdded = std::chrono::system_clock::now(); - static bool cursorDefaultDone = false; - static bool firstLaunch = true; - - const auto POS = PNEWMONITOR->middle(); - - // by default, cursor should be set to first monitor detected - // this is needed as a default if the monitor given in config above doesn't exist - if (firstLaunch) { - firstLaunch = false; - g_pCompositor->warpCursorTo(POS, true); - g_pInputManager->refocus(); - } - - if (cursorDefaultDone || *PCURSORMONITOR == STRVAL_EMPTY) - return; - - // after 10s, don't set cursor to default monitor - auto timePassedSec = std::chrono::duration_cast(std::chrono::system_clock::now() - firstMonitorAdded); - if (timePassedSec.count() > 10) { - cursorDefaultDone = true; - return; - } - - if (*PCURSORMONITOR == monitorName) { - cursorDefaultDone = true; - g_pCompositor->warpCursorTo(POS, true); - g_pInputManager->refocus(); - } -} - void CCompositor::onNewMonitor(SP output) { // add it to real auto PNEWMONITOR = g_pCompositor->m_vRealMonitors.emplace_back(makeShared()); @@ -2986,8 +2953,6 @@ void CCompositor::onNewMonitor(SP output) { g_pConfigManager->m_bWantsMonitorReload = true; g_pCompositor->scheduleFrameForMonitor(PNEWMONITOR.get(), IOutput::AQ_SCHEDULE_NEW_MONITOR); - checkDefaultCursorWarp(PNEWMONITOR, output->name); - for (auto& w : g_pCompositor->m_vWindows) { if (w->m_iMonitorID == PNEWMONITOR->ID) { w->m_iLastSurfaceMonitorID = MONITOR_INVALID; diff --git a/src/managers/PointerManager.cpp b/src/managers/PointerManager.cpp index 3ba34c11..72ff5ae7 100644 --- a/src/managers/PointerManager.cpp +++ b/src/managers/PointerManager.cpp @@ -11,13 +11,21 @@ #include CPointerManager::CPointerManager() { - hooks.monitorAdded = g_pHookSystem->hookDynamic("newMonitor", [this](void* self, SCallbackInfo& info, std::any data) { - auto PMONITOR = std::any_cast>(data); + hooks.monitorAdded = g_pHookSystem->hookDynamic("monitorAdded", [this](void* self, SCallbackInfo& info, std::any data) { + auto PMONITOR = std::any_cast(data)->self.lock(); onMonitorLayoutChange(); - PMONITOR->events.modeChanged.registerStaticListener([this](void* owner, std::any data) { g_pEventLoopManager->doLater([this]() { onMonitorLayoutChange(); }); }, nullptr); - PMONITOR->events.disconnect.registerStaticListener([this](void* owner, std::any data) { g_pEventLoopManager->doLater([this]() { onMonitorLayoutChange(); }); }, nullptr); + PMONITOR->events.modeChanged.registerStaticListener( + [this, PMONITOR](void* owner, std::any data) { + g_pEventLoopManager->doLater([this, PMONITOR]() { + onMonitorLayoutChange(); + checkDefaultCursorWarp(PMONITOR, PMONITOR->output->name); + }); + }, + nullptr); + PMONITOR->events.disconnect.registerStaticListener( + [this, PMONITOR](void* owner, std::any data) { g_pEventLoopManager->doLater([this, PMONITOR]() { onMonitorLayoutChange(); }); }, nullptr); PMONITOR->events.destroy.registerStaticListener( [this](void* owner, std::any data) { if (g_pCompositor && !g_pCompositor->m_bIsShuttingDown) @@ -35,6 +43,38 @@ CPointerManager::CPointerManager() { }); } +void CPointerManager::checkDefaultCursorWarp(SP monitor, std::string monitorName) { + static auto PCURSORMONITOR = CConfigValue("cursor:default_monitor"); + static bool cursorDefaultDone = false; + static bool firstLaunch = true; + + const auto POS = monitor->middle(); + + // by default, cursor should be set to first monitor detected + // this is needed as a default if the monitor given in config above doesn't exist + if (firstLaunch) { + firstLaunch = false; + g_pCompositor->warpCursorTo(POS, true); + g_pInputManager->refocus(); + return; + } + + if (!cursorDefaultDone && *PCURSORMONITOR != STRVAL_EMPTY) { + if (*PCURSORMONITOR == monitorName) { + cursorDefaultDone = true; + g_pCompositor->warpCursorTo(POS, true); + g_pInputManager->refocus(); + return; + } + } + + // modechange happend check if cursor is on that monitor and warp it to middle to not place it out of bounds if resolution changed. + if (g_pCompositor->getMonitorFromCursor() == monitor.get()) { + g_pCompositor->warpCursorTo(POS, true); + g_pInputManager->refocus(); + } +} + void CPointerManager::lockSoftwareAll() { for (auto& state : monitorStates) state->softwareLocks++; diff --git a/src/managers/PointerManager.hpp b/src/managers/PointerManager.hpp index 4a4c4f61..082855b5 100644 --- a/src/managers/PointerManager.hpp +++ b/src/managers/PointerManager.hpp @@ -26,6 +26,7 @@ class CPointerManager { public: CPointerManager(); + void checkDefaultCursorWarp(SP monitor, std::string monitorName); void attachPointer(SP pointer); void attachTouch(SP touch); void attachTablet(SP tablet); From 118d4e1001d5847aa42d1e5d5fa9623954ae751d Mon Sep 17 00:00:00 2001 From: "Yang, Ying-chao" Date: Mon, 12 Aug 2024 03:38:16 +0800 Subject: [PATCH 0260/2181] install: Prepend ${DESTDIR} when creating hyprland symbolic link (fixes #7280). (#7281) --- CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index d8c45bbe..f26a5c3c 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -330,7 +330,7 @@ install( CODE "execute_process( \ COMMAND ${CMAKE_COMMAND} -E create_symlink \ ${CMAKE_INSTALL_FULL_BINDIR}/Hyprland \ - ${CMAKE_INSTALL_FULL_BINDIR}/hyprland + \"\$ENV{DESTDIR}${CMAKE_INSTALL_FULL_BINDIR}/hyprland\" \ )") # session file From df9d830117cbbf8a1b2a144a28261c28753cb022 Mon Sep 17 00:00:00 2001 From: Mihai Fufezan Date: Mon, 12 Aug 2024 18:18:03 +0300 Subject: [PATCH 0261/2181] flake.lock: update --- flake.lock | 24 ++-- hyprpm/Makefile | 363 ++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 375 insertions(+), 12 deletions(-) create mode 100644 hyprpm/Makefile diff --git a/flake.lock b/flake.lock index 5c384d4d..8930d2e3 100644 --- a/flake.lock +++ b/flake.lock @@ -16,11 +16,11 @@ ] }, "locked": { - "lastModified": 1722347739, - "narHash": "sha256-rAoh+K6KG+b1DwSWtqRVocdojnH6nGk6q07mNltoUSM=", + "lastModified": 1723405438, + "narHash": "sha256-bpmC2m7OhlDvqgQZdZ2jBLyeIkq/Jld3X4bqRAxBSp8=", "owner": "hyprwm", "repo": "aquamarine", - "rev": "7c3565f9bedc7cb601cc0baa14792247e4dc1d5a", + "rev": "9312aa28271c91e5d67ecb9def527b2bbcff0e66", "type": "github" }, "original": { @@ -42,11 +42,11 @@ ] }, "locked": { - "lastModified": 1721330371, - "narHash": "sha256-aYlHTWylczLt6ERJyg6E66Y/XSCbVL7leVcRuJmVbpI=", + "lastModified": 1722623071, + "narHash": "sha256-sLADpVgebpCBFXkA1FlCXtvEPu1tdEsTfqK1hfeHySE=", "owner": "hyprwm", "repo": "hyprcursor", - "rev": "4493a972b48f9c3014befbbf381ed5fff91a65dc", + "rev": "912d56025f03d41b1ad29510c423757b4379eb1c", "type": "github" }, "original": { @@ -116,11 +116,11 @@ ] }, "locked": { - "lastModified": 1722098849, - "narHash": "sha256-D3wIZlBNh7LuZ0NaoCpY/Pvu+xHxIVtSN+KkWZYvvVs=", + "lastModified": 1722869141, + "narHash": "sha256-0KU4qhyMp441qfwbirNg3+wbm489KnEjXOz2I/RbeFs=", "owner": "hyprwm", "repo": "hyprutils", - "rev": "5dcbbc1e3de40b2cecfd2007434d86e924468f1f", + "rev": "0252fd13e78e60fb0da512a212e56007515a49f7", "type": "github" }, "original": { @@ -154,11 +154,11 @@ }, "nixpkgs": { "locked": { - "lastModified": 1722185531, - "narHash": "sha256-veKR07psFoJjINLC8RK4DiLniGGMgF3QMlS4tb74S6k=", + "lastModified": 1723175592, + "narHash": "sha256-M0xJ3FbDUc4fRZ84dPGx5VvgFsOzds77KiBMW/mMTnI=", "owner": "NixOS", "repo": "nixpkgs", - "rev": "52ec9ac3b12395ad677e8b62106f0b98c1f8569d", + "rev": "5e0ca22929f3342b19569b21b2f3462f053e497b", "type": "github" }, "original": { diff --git a/hyprpm/Makefile b/hyprpm/Makefile new file mode 100644 index 00000000..5249a14b --- /dev/null +++ b/hyprpm/Makefile @@ -0,0 +1,363 @@ +# CMAKE generated file: DO NOT EDIT! +# Generated by "Unix Makefiles" Generator, CMake Version 3.29 + +# Default target executed when no arguments are given to make. +default_target: all +.PHONY : default_target + +# Allow only one "make -f Makefile2" at a time, but pass parallelism. +.NOTPARALLEL: + +#============================================================================= +# Special targets provided by cmake. + +# Disable implicit rules so canonical targets will work. +.SUFFIXES: + +# Disable VCS-based implicit rules. +% : %,v + +# Disable VCS-based implicit rules. +% : RCS/% + +# Disable VCS-based implicit rules. +% : RCS/%,v + +# Disable VCS-based implicit rules. +% : SCCS/s.% + +# Disable VCS-based implicit rules. +% : s.% + +.SUFFIXES: .hpux_make_needs_suffix_list + +# Command-line flag to silence nested $(MAKE). +$(VERBOSE)MAKESILENT = -s + +#Suppress display of executed commands. +$(VERBOSE).SILENT: + +# A target that is always out of date. +cmake_force: +.PHONY : cmake_force + +#============================================================================= +# Set environment variables for the build. + +# The shell in which to execute make rules. +SHELL = /bin/sh + +# The CMake executable. +CMAKE_COMMAND = /nix/store/aqckch626lg0vxh41dabyzrq0jx7gdk5-cmake-3.29.6/bin/cmake + +# The command to remove a file. +RM = /nix/store/aqckch626lg0vxh41dabyzrq0jx7gdk5-cmake-3.29.6/bin/cmake -E rm -f + +# Escaping for special characters. +EQUALS = = + +# The top-level source directory on which CMake was run. +CMAKE_SOURCE_DIR = /home/mihai/Documents/code/git/Hyprland + +# The top-level build directory on which CMake was run. +CMAKE_BINARY_DIR = /home/mihai/Documents/code/git/Hyprland + +#============================================================================= +# Targets provided globally by CMake. + +# Special rule for the target package +package: preinstall + @$(CMAKE_COMMAND) -E cmake_echo_color "--switch=$(COLOR)" --cyan "Run CPack packaging tool..." + cd /home/mihai/Documents/code/git/Hyprland && /nix/store/aqckch626lg0vxh41dabyzrq0jx7gdk5-cmake-3.29.6/bin/cpack --config ./CPackConfig.cmake +.PHONY : package + +# Special rule for the target package +package/fast: package +.PHONY : package/fast + +# Special rule for the target package_source +package_source: + @$(CMAKE_COMMAND) -E cmake_echo_color "--switch=$(COLOR)" --cyan "Run CPack packaging tool for source..." + cd /home/mihai/Documents/code/git/Hyprland && /nix/store/aqckch626lg0vxh41dabyzrq0jx7gdk5-cmake-3.29.6/bin/cpack --config ./CPackSourceConfig.cmake /home/mihai/Documents/code/git/Hyprland/CPackSourceConfig.cmake +.PHONY : package_source + +# Special rule for the target package_source +package_source/fast: package_source +.PHONY : package_source/fast + +# Special rule for the target edit_cache +edit_cache: + @$(CMAKE_COMMAND) -E cmake_echo_color "--switch=$(COLOR)" --cyan "No interactive CMake dialog available..." + /nix/store/aqckch626lg0vxh41dabyzrq0jx7gdk5-cmake-3.29.6/bin/cmake -E echo No\ interactive\ CMake\ dialog\ available. +.PHONY : edit_cache + +# Special rule for the target edit_cache +edit_cache/fast: edit_cache +.PHONY : edit_cache/fast + +# Special rule for the target rebuild_cache +rebuild_cache: + @$(CMAKE_COMMAND) -E cmake_echo_color "--switch=$(COLOR)" --cyan "Running CMake to regenerate build system..." + /nix/store/aqckch626lg0vxh41dabyzrq0jx7gdk5-cmake-3.29.6/bin/cmake --regenerate-during-build -S$(CMAKE_SOURCE_DIR) -B$(CMAKE_BINARY_DIR) +.PHONY : rebuild_cache + +# Special rule for the target rebuild_cache +rebuild_cache/fast: rebuild_cache +.PHONY : rebuild_cache/fast + +# Special rule for the target list_install_components +list_install_components: + @$(CMAKE_COMMAND) -E cmake_echo_color "--switch=$(COLOR)" --cyan "Available install components are: \"Unspecified\"" +.PHONY : list_install_components + +# Special rule for the target list_install_components +list_install_components/fast: list_install_components +.PHONY : list_install_components/fast + +# Special rule for the target install +install: preinstall + @$(CMAKE_COMMAND) -E cmake_echo_color "--switch=$(COLOR)" --cyan "Install the project..." + /nix/store/aqckch626lg0vxh41dabyzrq0jx7gdk5-cmake-3.29.6/bin/cmake -P cmake_install.cmake +.PHONY : install + +# Special rule for the target install +install/fast: preinstall/fast + @$(CMAKE_COMMAND) -E cmake_echo_color "--switch=$(COLOR)" --cyan "Install the project..." + /nix/store/aqckch626lg0vxh41dabyzrq0jx7gdk5-cmake-3.29.6/bin/cmake -P cmake_install.cmake +.PHONY : install/fast + +# Special rule for the target install/local +install/local: preinstall + @$(CMAKE_COMMAND) -E cmake_echo_color "--switch=$(COLOR)" --cyan "Installing only the local directory..." + /nix/store/aqckch626lg0vxh41dabyzrq0jx7gdk5-cmake-3.29.6/bin/cmake -DCMAKE_INSTALL_LOCAL_ONLY=1 -P cmake_install.cmake +.PHONY : install/local + +# Special rule for the target install/local +install/local/fast: preinstall/fast + @$(CMAKE_COMMAND) -E cmake_echo_color "--switch=$(COLOR)" --cyan "Installing only the local directory..." + /nix/store/aqckch626lg0vxh41dabyzrq0jx7gdk5-cmake-3.29.6/bin/cmake -DCMAKE_INSTALL_LOCAL_ONLY=1 -P cmake_install.cmake +.PHONY : install/local/fast + +# Special rule for the target install/strip +install/strip: preinstall + @$(CMAKE_COMMAND) -E cmake_echo_color "--switch=$(COLOR)" --cyan "Installing the project stripped..." + /nix/store/aqckch626lg0vxh41dabyzrq0jx7gdk5-cmake-3.29.6/bin/cmake -DCMAKE_INSTALL_DO_STRIP=1 -P cmake_install.cmake +.PHONY : install/strip + +# Special rule for the target install/strip +install/strip/fast: preinstall/fast + @$(CMAKE_COMMAND) -E cmake_echo_color "--switch=$(COLOR)" --cyan "Installing the project stripped..." + /nix/store/aqckch626lg0vxh41dabyzrq0jx7gdk5-cmake-3.29.6/bin/cmake -DCMAKE_INSTALL_DO_STRIP=1 -P cmake_install.cmake +.PHONY : install/strip/fast + +# The main all target +all: cmake_check_build_system + cd /home/mihai/Documents/code/git/Hyprland && $(CMAKE_COMMAND) -E cmake_progress_start /home/mihai/Documents/code/git/Hyprland/CMakeFiles /home/mihai/Documents/code/git/Hyprland/hyprpm//CMakeFiles/progress.marks + cd /home/mihai/Documents/code/git/Hyprland && $(MAKE) $(MAKESILENT) -f CMakeFiles/Makefile2 hyprpm/all + $(CMAKE_COMMAND) -E cmake_progress_start /home/mihai/Documents/code/git/Hyprland/CMakeFiles 0 +.PHONY : all + +# The main clean target +clean: + cd /home/mihai/Documents/code/git/Hyprland && $(MAKE) $(MAKESILENT) -f CMakeFiles/Makefile2 hyprpm/clean +.PHONY : clean + +# The main clean target +clean/fast: clean +.PHONY : clean/fast + +# Prepare targets for installation. +preinstall: all + cd /home/mihai/Documents/code/git/Hyprland && $(MAKE) $(MAKESILENT) -f CMakeFiles/Makefile2 hyprpm/preinstall +.PHONY : preinstall + +# Prepare targets for installation. +preinstall/fast: + cd /home/mihai/Documents/code/git/Hyprland && $(MAKE) $(MAKESILENT) -f CMakeFiles/Makefile2 hyprpm/preinstall +.PHONY : preinstall/fast + +# clear depends +depend: + cd /home/mihai/Documents/code/git/Hyprland && $(CMAKE_COMMAND) -P /home/mihai/Documents/code/git/Hyprland/CMakeFiles/VerifyGlobs.cmake + cd /home/mihai/Documents/code/git/Hyprland && $(CMAKE_COMMAND) -S$(CMAKE_SOURCE_DIR) -B$(CMAKE_BINARY_DIR) --check-build-system CMakeFiles/Makefile.cmake 1 +.PHONY : depend + +# Convenience name for target. +hyprpm/CMakeFiles/hyprpm.dir/rule: + cd /home/mihai/Documents/code/git/Hyprland && $(MAKE) $(MAKESILENT) -f CMakeFiles/Makefile2 hyprpm/CMakeFiles/hyprpm.dir/rule +.PHONY : hyprpm/CMakeFiles/hyprpm.dir/rule + +# Convenience name for target. +hyprpm: hyprpm/CMakeFiles/hyprpm.dir/rule +.PHONY : hyprpm + +# fast build rule for target. +hyprpm/fast: + cd /home/mihai/Documents/code/git/Hyprland && $(MAKE) $(MAKESILENT) -f hyprpm/CMakeFiles/hyprpm.dir/build.make hyprpm/CMakeFiles/hyprpm.dir/build +.PHONY : hyprpm/fast + +src/core/DataState.o: src/core/DataState.cpp.o +.PHONY : src/core/DataState.o + +# target to build an object file +src/core/DataState.cpp.o: + cd /home/mihai/Documents/code/git/Hyprland && $(MAKE) $(MAKESILENT) -f hyprpm/CMakeFiles/hyprpm.dir/build.make hyprpm/CMakeFiles/hyprpm.dir/src/core/DataState.cpp.o +.PHONY : src/core/DataState.cpp.o + +src/core/DataState.i: src/core/DataState.cpp.i +.PHONY : src/core/DataState.i + +# target to preprocess a source file +src/core/DataState.cpp.i: + cd /home/mihai/Documents/code/git/Hyprland && $(MAKE) $(MAKESILENT) -f hyprpm/CMakeFiles/hyprpm.dir/build.make hyprpm/CMakeFiles/hyprpm.dir/src/core/DataState.cpp.i +.PHONY : src/core/DataState.cpp.i + +src/core/DataState.s: src/core/DataState.cpp.s +.PHONY : src/core/DataState.s + +# target to generate assembly for a file +src/core/DataState.cpp.s: + cd /home/mihai/Documents/code/git/Hyprland && $(MAKE) $(MAKESILENT) -f hyprpm/CMakeFiles/hyprpm.dir/build.make hyprpm/CMakeFiles/hyprpm.dir/src/core/DataState.cpp.s +.PHONY : src/core/DataState.cpp.s + +src/core/Manifest.o: src/core/Manifest.cpp.o +.PHONY : src/core/Manifest.o + +# target to build an object file +src/core/Manifest.cpp.o: + cd /home/mihai/Documents/code/git/Hyprland && $(MAKE) $(MAKESILENT) -f hyprpm/CMakeFiles/hyprpm.dir/build.make hyprpm/CMakeFiles/hyprpm.dir/src/core/Manifest.cpp.o +.PHONY : src/core/Manifest.cpp.o + +src/core/Manifest.i: src/core/Manifest.cpp.i +.PHONY : src/core/Manifest.i + +# target to preprocess a source file +src/core/Manifest.cpp.i: + cd /home/mihai/Documents/code/git/Hyprland && $(MAKE) $(MAKESILENT) -f hyprpm/CMakeFiles/hyprpm.dir/build.make hyprpm/CMakeFiles/hyprpm.dir/src/core/Manifest.cpp.i +.PHONY : src/core/Manifest.cpp.i + +src/core/Manifest.s: src/core/Manifest.cpp.s +.PHONY : src/core/Manifest.s + +# target to generate assembly for a file +src/core/Manifest.cpp.s: + cd /home/mihai/Documents/code/git/Hyprland && $(MAKE) $(MAKESILENT) -f hyprpm/CMakeFiles/hyprpm.dir/build.make hyprpm/CMakeFiles/hyprpm.dir/src/core/Manifest.cpp.s +.PHONY : src/core/Manifest.cpp.s + +src/core/PluginManager.o: src/core/PluginManager.cpp.o +.PHONY : src/core/PluginManager.o + +# target to build an object file +src/core/PluginManager.cpp.o: + cd /home/mihai/Documents/code/git/Hyprland && $(MAKE) $(MAKESILENT) -f hyprpm/CMakeFiles/hyprpm.dir/build.make hyprpm/CMakeFiles/hyprpm.dir/src/core/PluginManager.cpp.o +.PHONY : src/core/PluginManager.cpp.o + +src/core/PluginManager.i: src/core/PluginManager.cpp.i +.PHONY : src/core/PluginManager.i + +# target to preprocess a source file +src/core/PluginManager.cpp.i: + cd /home/mihai/Documents/code/git/Hyprland && $(MAKE) $(MAKESILENT) -f hyprpm/CMakeFiles/hyprpm.dir/build.make hyprpm/CMakeFiles/hyprpm.dir/src/core/PluginManager.cpp.i +.PHONY : src/core/PluginManager.cpp.i + +src/core/PluginManager.s: src/core/PluginManager.cpp.s +.PHONY : src/core/PluginManager.s + +# target to generate assembly for a file +src/core/PluginManager.cpp.s: + cd /home/mihai/Documents/code/git/Hyprland && $(MAKE) $(MAKESILENT) -f hyprpm/CMakeFiles/hyprpm.dir/build.make hyprpm/CMakeFiles/hyprpm.dir/src/core/PluginManager.cpp.s +.PHONY : src/core/PluginManager.cpp.s + +src/main.o: src/main.cpp.o +.PHONY : src/main.o + +# target to build an object file +src/main.cpp.o: + cd /home/mihai/Documents/code/git/Hyprland && $(MAKE) $(MAKESILENT) -f hyprpm/CMakeFiles/hyprpm.dir/build.make hyprpm/CMakeFiles/hyprpm.dir/src/main.cpp.o +.PHONY : src/main.cpp.o + +src/main.i: src/main.cpp.i +.PHONY : src/main.i + +# target to preprocess a source file +src/main.cpp.i: + cd /home/mihai/Documents/code/git/Hyprland && $(MAKE) $(MAKESILENT) -f hyprpm/CMakeFiles/hyprpm.dir/build.make hyprpm/CMakeFiles/hyprpm.dir/src/main.cpp.i +.PHONY : src/main.cpp.i + +src/main.s: src/main.cpp.s +.PHONY : src/main.s + +# target to generate assembly for a file +src/main.cpp.s: + cd /home/mihai/Documents/code/git/Hyprland && $(MAKE) $(MAKESILENT) -f hyprpm/CMakeFiles/hyprpm.dir/build.make hyprpm/CMakeFiles/hyprpm.dir/src/main.cpp.s +.PHONY : src/main.cpp.s + +src/progress/CProgressBar.o: src/progress/CProgressBar.cpp.o +.PHONY : src/progress/CProgressBar.o + +# target to build an object file +src/progress/CProgressBar.cpp.o: + cd /home/mihai/Documents/code/git/Hyprland && $(MAKE) $(MAKESILENT) -f hyprpm/CMakeFiles/hyprpm.dir/build.make hyprpm/CMakeFiles/hyprpm.dir/src/progress/CProgressBar.cpp.o +.PHONY : src/progress/CProgressBar.cpp.o + +src/progress/CProgressBar.i: src/progress/CProgressBar.cpp.i +.PHONY : src/progress/CProgressBar.i + +# target to preprocess a source file +src/progress/CProgressBar.cpp.i: + cd /home/mihai/Documents/code/git/Hyprland && $(MAKE) $(MAKESILENT) -f hyprpm/CMakeFiles/hyprpm.dir/build.make hyprpm/CMakeFiles/hyprpm.dir/src/progress/CProgressBar.cpp.i +.PHONY : src/progress/CProgressBar.cpp.i + +src/progress/CProgressBar.s: src/progress/CProgressBar.cpp.s +.PHONY : src/progress/CProgressBar.s + +# target to generate assembly for a file +src/progress/CProgressBar.cpp.s: + cd /home/mihai/Documents/code/git/Hyprland && $(MAKE) $(MAKESILENT) -f hyprpm/CMakeFiles/hyprpm.dir/build.make hyprpm/CMakeFiles/hyprpm.dir/src/progress/CProgressBar.cpp.s +.PHONY : src/progress/CProgressBar.cpp.s + +# Help Target +help: + @echo "The following are some of the valid targets for this Makefile:" + @echo "... all (the default if no target is provided)" + @echo "... clean" + @echo "... depend" + @echo "... edit_cache" + @echo "... install" + @echo "... install/local" + @echo "... install/strip" + @echo "... list_install_components" + @echo "... package" + @echo "... package_source" + @echo "... rebuild_cache" + @echo "... hyprpm" + @echo "... src/core/DataState.o" + @echo "... src/core/DataState.i" + @echo "... src/core/DataState.s" + @echo "... src/core/Manifest.o" + @echo "... src/core/Manifest.i" + @echo "... src/core/Manifest.s" + @echo "... src/core/PluginManager.o" + @echo "... src/core/PluginManager.i" + @echo "... src/core/PluginManager.s" + @echo "... src/main.o" + @echo "... src/main.i" + @echo "... src/main.s" + @echo "... src/progress/CProgressBar.o" + @echo "... src/progress/CProgressBar.i" + @echo "... src/progress/CProgressBar.s" +.PHONY : help + + + +#============================================================================= +# Special targets to cleanup operation of make. + +# Special rule to run CMake to check the build system integrity. +# No rule that depends on this can have commands that come from listfiles +# because they might be regenerated. +cmake_check_build_system: + cd /home/mihai/Documents/code/git/Hyprland && $(CMAKE_COMMAND) -P /home/mihai/Documents/code/git/Hyprland/CMakeFiles/VerifyGlobs.cmake + cd /home/mihai/Documents/code/git/Hyprland && $(CMAKE_COMMAND) -S$(CMAKE_SOURCE_DIR) -B$(CMAKE_BINARY_DIR) --check-build-system CMakeFiles/Makefile.cmake 0 +.PHONY : cmake_check_build_system + From d361fcbd85a92f0494c6d8ef0c63aad798df20a7 Mon Sep 17 00:00:00 2001 From: Ikalco <73481042+ikalco@users.noreply.github.com> Date: Mon, 12 Aug 2024 11:16:00 -0500 Subject: [PATCH 0262/2181] config: fix explicit sync option warning (#7293) --- src/config/ConfigManager.cpp | 17 +++++++++++++---- 1 file changed, 13 insertions(+), 4 deletions(-) diff --git a/src/config/ConfigManager.cpp b/src/config/ConfigManager.cpp index edc1723d..41d3871c 100644 --- a/src/config/ConfigManager.cpp +++ b/src/config/ConfigManager.cpp @@ -822,9 +822,6 @@ void CConfigManager::postConfigReload(const Hyprlang::CParseResult& result) { if (!isFirstLaunch) g_pHyprOpenGL->m_bReloadScreenShader = true; - if (!isFirstLaunch && *PENABLEEXPLICIT != prevEnabledExplicit) - g_pHyprError->queueCreate("Warning: You changed the render:explicit_sync option, this requires you to restart Hyprland.", CColor(0.9, 0.76, 0.221, 1.0)); - // parseError will be displayed next frame if (result.error) @@ -837,6 +834,8 @@ void CConfigManager::postConfigReload(const Hyprlang::CParseResult& result) { else if (std::any_cast(m_pConfig->getConfigValue("autogenerated")) == 1) g_pHyprError->queueCreate("Warning: You're using an autogenerated config! (config file: " + getMainConfigPath() + " )\nSUPER+Q -> kitty\nSUPER+M -> exit Hyprland", CColor(1.0, 1.0, 70.0 / 255.0, 1.0)); + else if (*PENABLEEXPLICIT != prevEnabledExplicit) + g_pHyprError->queueCreate("Warning: You changed the render:explicit_sync option, this requires you to restart Hyprland.", CColor(0.9, 0.76, 0.221, 1.0)); else g_pHyprError->destroy(); @@ -925,7 +924,10 @@ void CConfigManager::init() { } std::string CConfigManager::parseKeyword(const std::string& COMMAND, const std::string& VALUE) { - const auto RET = m_pConfig->parseDynamic(COMMAND.c_str(), VALUE.c_str()); + static const auto PENABLEEXPLICIT = CConfigValue("render:explicit_sync"); + static int prevEnabledExplicit = *PENABLEEXPLICIT; + + const auto RET = m_pConfig->parseDynamic(COMMAND.c_str(), VALUE.c_str()); // invalidate layouts if they changed if (COMMAND == "monitor" || COMMAND.contains("gaps_") || COMMAND.starts_with("dwindle:") || COMMAND.starts_with("master:")) { @@ -933,6 +935,13 @@ std::string CConfigManager::parseKeyword(const std::string& COMMAND, const std:: g_pLayoutManager->getCurrentLayout()->recalculateMonitor(m->ID); } + if (COMMAND.contains("explicit")) { + if (*PENABLEEXPLICIT != prevEnabledExplicit) + g_pHyprError->queueCreate("Warning: You changed the render:explicit_sync option, this requires you to restart Hyprland.", CColor(0.9, 0.76, 0.221, 1.0)); + else + g_pHyprError->destroy(); + } + // Update window border colors g_pCompositor->updateAllWindowsAnimatedDecorationValues(); From 3fa6db1e7a7f5596f449ae12d0b45ff364d7f6f1 Mon Sep 17 00:00:00 2001 From: Tom Englund Date: Mon, 12 Aug 2024 19:19:03 +0200 Subject: [PATCH 0263/2181] core: fix data race and a unsigned int rollover (#7278) * keybindmgr: avoid uint rollover on mouse keycode mouse keycode is 0, and the switch case checks for 0 - 8 and rolls over, just return early if keycode is 0. * watchdog: avoid data races in watchdog asan thread sanitizer reported data races in the watchdog from reading and setting the bool variables make them std::atomic bools. also add a atomic bool for the main thread to wait for to avoid data race when reading the config values. * hyprdebug: change non unicode character to name asan created false positives and didnt like this bit, so for the sake of easier debugging rename it to something unicode. --- src/Compositor.cpp | 4 ++++ src/debug/HyprDebugOverlay.cpp | 16 ++++++++-------- src/debug/HyprDebugOverlay.hpp | 8 ++++---- src/helpers/Watchdog.cpp | 13 ++++++------- src/helpers/Watchdog.hpp | 14 ++++++++------ src/managers/KeybindManager.cpp | 3 +++ src/render/Renderer.cpp | 10 +++++----- 7 files changed, 38 insertions(+), 30 deletions(-) diff --git a/src/Compositor.cpp b/src/Compositor.cpp index c3f95961..a2f7c52a 100644 --- a/src/Compositor.cpp +++ b/src/Compositor.cpp @@ -552,6 +552,10 @@ void CCompositor::initManagers(eManagersInitStage stage) { g_pConfigManager->init(); g_pWatchdog = std::make_unique(); // requires config + // wait for watchdog to initialize to not hit data races in reading config values. + while (!g_pWatchdog->m_bWatchdogInitialized) { + std::this_thread::yield(); + } Debug::log(LOG, "Creating the PointerManager!"); g_pPointerManager = std::make_unique(); diff --git a/src/debug/HyprDebugOverlay.cpp b/src/debug/HyprDebugOverlay.cpp index 889be8ea..fbd8cd71 100644 --- a/src/debug/HyprDebugOverlay.cpp +++ b/src/debug/HyprDebugOverlay.cpp @@ -7,8 +7,8 @@ CHyprDebugOverlay::CHyprDebugOverlay() { m_pTexture = makeShared(); } -void CHyprMonitorDebugOverlay::renderData(CMonitor* pMonitor, float µs) { - m_dLastRenderTimes.push_back(µs / 1000.f); +void CHyprMonitorDebugOverlay::renderData(CMonitor* pMonitor, float durationUs) { + m_dLastRenderTimes.push_back(durationUs / 1000.f); if (m_dLastRenderTimes.size() > (long unsigned int)pMonitor->refreshRate) m_dLastRenderTimes.pop_front(); @@ -17,8 +17,8 @@ void CHyprMonitorDebugOverlay::renderData(CMonitor* pMonitor, float µs) { m_pMonitor = pMonitor; } -void CHyprMonitorDebugOverlay::renderDataNoOverlay(CMonitor* pMonitor, float µs) { - m_dLastRenderTimesNoOverlay.push_back(µs / 1000.f); +void CHyprMonitorDebugOverlay::renderDataNoOverlay(CMonitor* pMonitor, float durationUs) { + m_dLastRenderTimesNoOverlay.push_back(durationUs / 1000.f); if (m_dLastRenderTimesNoOverlay.size() > (long unsigned int)pMonitor->refreshRate) m_dLastRenderTimesNoOverlay.pop_front(); @@ -188,12 +188,12 @@ int CHyprMonitorDebugOverlay::draw(int offset) { return posY - offset; } -void CHyprDebugOverlay::renderData(CMonitor* pMonitor, float µs) { - m_mMonitorOverlays[pMonitor].renderData(pMonitor, µs); +void CHyprDebugOverlay::renderData(CMonitor* pMonitor, float durationUs) { + m_mMonitorOverlays[pMonitor].renderData(pMonitor, durationUs); } -void CHyprDebugOverlay::renderDataNoOverlay(CMonitor* pMonitor, float µs) { - m_mMonitorOverlays[pMonitor].renderDataNoOverlay(pMonitor, µs); +void CHyprDebugOverlay::renderDataNoOverlay(CMonitor* pMonitor, float durationUs) { + m_mMonitorOverlays[pMonitor].renderDataNoOverlay(pMonitor, durationUs); } void CHyprDebugOverlay::frameData(CMonitor* pMonitor) { diff --git a/src/debug/HyprDebugOverlay.hpp b/src/debug/HyprDebugOverlay.hpp index a6063ee9..e7742b35 100644 --- a/src/debug/HyprDebugOverlay.hpp +++ b/src/debug/HyprDebugOverlay.hpp @@ -13,8 +13,8 @@ class CHyprMonitorDebugOverlay { public: int draw(int offset); - void renderData(CMonitor* pMonitor, float µs); - void renderDataNoOverlay(CMonitor* pMonitor, float µs); + void renderData(CMonitor* pMonitor, float durationUs); + void renderDataNoOverlay(CMonitor* pMonitor, float durationUs); void frameData(CMonitor* pMonitor); private: @@ -33,8 +33,8 @@ class CHyprDebugOverlay { public: CHyprDebugOverlay(); void draw(); - void renderData(CMonitor*, float µs); - void renderDataNoOverlay(CMonitor*, float µs); + void renderData(CMonitor*, float durationUs); + void renderDataNoOverlay(CMonitor*, float durationUs); void frameData(CMonitor*); private: diff --git a/src/helpers/Watchdog.cpp b/src/helpers/Watchdog.cpp index b9f654da..c7ff648b 100644 --- a/src/helpers/Watchdog.cpp +++ b/src/helpers/Watchdog.cpp @@ -18,15 +18,14 @@ CWatchdog::CWatchdog() { m_pWatchdog = std::make_unique([this] { static auto PTIMEOUT = CConfigValue("debug:watchdog_timeout"); - while (1337) { - std::unique_lock lk(m_mWatchdogMutex); + m_bWatchdogInitialized = true; + while (!m_bExitThread) { + std::unique_lock lk(m_mWatchdogMutex); if (!m_bWillWatch) - m_cvWatchdogCondition.wait(lk, [this] { return m_bNotified; }); - else { - if (m_cvWatchdogCondition.wait_for(lk, std::chrono::milliseconds((int)(*PTIMEOUT * 1000.0)), [this] { return m_bNotified; }) == false) - pthread_kill(m_iMainThreadPID, SIGUSR1); - } + m_cvWatchdogCondition.wait(lk, [this] { return m_bNotified || m_bExitThread; }); + else if (m_cvWatchdogCondition.wait_for(lk, std::chrono::milliseconds((int)(*PTIMEOUT * 1000.0)), [this] { return m_bNotified || m_bExitThread; }) == false) + pthread_kill(m_iMainThreadPID, SIGUSR1); if (m_bExitThread) break; diff --git a/src/helpers/Watchdog.hpp b/src/helpers/Watchdog.hpp index 7bb499d6..b16cb518 100644 --- a/src/helpers/Watchdog.hpp +++ b/src/helpers/Watchdog.hpp @@ -11,21 +11,23 @@ class CWatchdog { CWatchdog(); ~CWatchdog(); - void startWatching(); - void endWatching(); + void startWatching(); + void endWatching(); + + std::atomic m_bWatchdogInitialized{false}; private: std::chrono::high_resolution_clock::time_point m_tTriggered; pthread_t m_iMainThreadPID = 0; - bool m_bWatching = false; - bool m_bWillWatch = false; + std::atomic m_bWatching = false; + std::atomic m_bWillWatch = false; std::unique_ptr m_pWatchdog; std::mutex m_mWatchdogMutex; - bool m_bNotified = false; - bool m_bExitThread = false; + std::atomic m_bNotified = false; + std::atomic m_bExitThread = false; std::condition_variable m_cvWatchdogCondition; }; diff --git a/src/managers/KeybindManager.cpp b/src/managers/KeybindManager.cpp index d4bac507..dba34d70 100644 --- a/src/managers/KeybindManager.cpp +++ b/src/managers/KeybindManager.cpp @@ -180,6 +180,9 @@ uint32_t CKeybindManager::stringToModMask(std::string mods) { } uint32_t CKeybindManager::keycodeToModifier(xkb_keycode_t keycode) { + if (keycode == 0) + return 0; + switch (keycode - 8) { case KEY_LEFTMETA: return HL_MODIFIER_META; case KEY_RIGHTMETA: return HL_MODIFIER_META; diff --git a/src/render/Renderer.cpp b/src/render/Renderer.cpp index a2d5a95e..6bf6a761 100644 --- a/src/render/Renderer.cpp +++ b/src/render/Renderer.cpp @@ -1395,15 +1395,15 @@ void CHyprRenderer::renderMonitor(CMonitor* pMonitor) { pMonitor->pendingFrame = false; - const float µs = std::chrono::duration_cast(std::chrono::high_resolution_clock::now() - renderStart).count() / 1000.f; - g_pDebugOverlay->renderData(pMonitor, µs); + const float durationUs = std::chrono::duration_cast(std::chrono::high_resolution_clock::now() - renderStart).count() / 1000.f; + g_pDebugOverlay->renderData(pMonitor, durationUs); if (*PDEBUGOVERLAY == 1) { if (pMonitor == g_pCompositor->m_vMonitors.front().get()) { - const float µsNoOverlay = µs - std::chrono::duration_cast(endRenderOverlay - renderStartOverlay).count() / 1000.f; - g_pDebugOverlay->renderDataNoOverlay(pMonitor, µsNoOverlay); + const float noOverlayUs = durationUs - std::chrono::duration_cast(endRenderOverlay - renderStartOverlay).count() / 1000.f; + g_pDebugOverlay->renderDataNoOverlay(pMonitor, noOverlayUs); } else { - g_pDebugOverlay->renderDataNoOverlay(pMonitor, µs); + g_pDebugOverlay->renderDataNoOverlay(pMonitor, durationUs); } } } From c7b72790bd63172f04ee86784d4cb2a400532927 Mon Sep 17 00:00:00 2001 From: Kyle <56144092+txkyel@users.noreply.github.com> Date: Mon, 12 Aug 2024 13:41:26 -0400 Subject: [PATCH 0264/2181] keybinds: Fix fullscreenState toggling behaviour (#7288) * Update fullscreen state dispatcher behaviour * Change syncFullscreen default to false * Revert all changes * Modify fullscreenstate dispatcher toggle behaviour * Update syncFullscreen according to state * Update syncFullscreen before setting fullscreen state --- src/managers/KeybindManager.cpp | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/src/managers/KeybindManager.cpp b/src/managers/KeybindManager.cpp index dba34d70..8fc025ec 100644 --- a/src/managers/KeybindManager.cpp +++ b/src/managers/KeybindManager.cpp @@ -1166,6 +1166,8 @@ void CKeybindManager::fullscreenStateActive(std::string args) { if (!PWINDOW) return; + PWINDOW->m_sWindowData.syncFullscreen = CWindowOverridableVar(false, PRIORITY_SET_PROP); + int internalMode, clientMode; try { internalMode = std::stoi(ARGS[0]); @@ -1184,18 +1186,15 @@ void CKeybindManager::fullscreenStateActive(std::string args) { } if (internalMode != -1 && clientMode == -1 && PWINDOW->m_sFullscreenState.internal == STATE.internal) { - g_pCompositor->setWindowFullscreenState(PWINDOW, sFullscreenState{.internal = PWINDOW->m_sFullscreenState.client, .client = PWINDOW->m_sFullscreenState.client}); - PWINDOW->m_sWindowData.syncFullscreen = CWindowOverridableVar(true, PRIORITY_SET_PROP); + g_pCompositor->setWindowFullscreenState(PWINDOW, sFullscreenState{.internal = FSMODE_NONE, .client = PWINDOW->m_sFullscreenState.client}); return; } if (internalMode == -1 && clientMode != -1 && PWINDOW->m_sFullscreenState.client == STATE.client) { - g_pCompositor->setWindowFullscreenState(PWINDOW, sFullscreenState{.internal = PWINDOW->m_sFullscreenState.internal, .client = PWINDOW->m_sFullscreenState.internal}); - PWINDOW->m_sWindowData.syncFullscreen = CWindowOverridableVar(true, PRIORITY_SET_PROP); + g_pCompositor->setWindowFullscreenState(PWINDOW, sFullscreenState{.internal = PWINDOW->m_sFullscreenState.internal, .client = FSMODE_NONE}); return; } - PWINDOW->m_sWindowData.syncFullscreen = CWindowOverridableVar(false, PRIORITY_SET_PROP); g_pCompositor->setWindowFullscreenState(PWINDOW, STATE); } From 77cf651825c2afac69e3a827ff910a62c73e1218 Mon Sep 17 00:00:00 2001 From: Tom Englund Date: Mon, 12 Aug 2024 20:49:52 +0200 Subject: [PATCH 0265/2181] protocols: avoid crashing in drmlease (#7290) instead of potentially causing wonky behaviour from destructing in the constructor add the unique_ptr reset to doLater and dont use the not done constructed protolog in the constructor, call Debug::log directly. see issue #7240 --- src/protocols/DRMLease.cpp | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/src/protocols/DRMLease.cpp b/src/protocols/DRMLease.cpp index 9f5b6312..3ab38ea1 100644 --- a/src/protocols/DRMLease.cpp +++ b/src/protocols/DRMLease.cpp @@ -1,5 +1,6 @@ #include "DRMLease.hpp" #include "../Compositor.hpp" +#include "managers/eventLoop/EventLoopManager.hpp" #include #include @@ -225,7 +226,7 @@ CDRMLeaseDevice::CDRMLeaseDevice(SP drmBackend) : backe auto fd = drm->getNonMasterFD(); if (fd < 0) { - LOGM(ERR, "Failed to dup fd for drm node {}", drm->gpuName); + Debug::log(ERR, "[DRMLease] Failed to dup fd for drm node {}", drm->gpuName); return; } @@ -247,10 +248,8 @@ CDRMLeaseProtocol::CDRMLeaseProtocol(const wl_interface* iface, const int& ver, break; } - if (!primaryDevice || primaryDevice->success) { - PROTO::lease.reset(); - return; - } + if (!primaryDevice || !primaryDevice->success) + g_pEventLoopManager->doLater([]() { PROTO::lease.reset(); }); } void CDRMLeaseProtocol::bindManager(wl_client* client, void* data, uint32_t ver, uint32_t id) { From 39df1f4dbfedf97a7f30f9de359f3b3415844380 Mon Sep 17 00:00:00 2001 From: Ikalco <73481042+ikalco@users.noreply.github.com> Date: Tue, 13 Aug 2024 12:27:00 -0500 Subject: [PATCH 0266/2181] cursormgr: fix cursor gsettings on session change (#7295) --- src/Compositor.cpp | 1 + src/managers/CursorManager.cpp | 6 +++++- src/managers/CursorManager.hpp | 3 ++- src/managers/XCursorManager.cpp | 1 + src/managers/XCursorManager.hpp | 4 ++-- 5 files changed, 11 insertions(+), 4 deletions(-) diff --git a/src/Compositor.cpp b/src/Compositor.cpp index a2f7c52a..26a985ef 100644 --- a/src/Compositor.cpp +++ b/src/Compositor.cpp @@ -393,6 +393,7 @@ void CCompositor::initAllSignals() { } g_pConfigManager->m_bWantsMonitorReload = true; + g_pCursorManager->syncGsettings(); } else { Debug::log(LOG, "Session got deactivated!"); diff --git a/src/managers/CursorManager.cpp b/src/managers/CursorManager.cpp index 3f3a25f6..e2dd5bb3 100644 --- a/src/managers/CursorManager.cpp +++ b/src/managers/CursorManager.cpp @@ -337,4 +337,8 @@ bool CCursorManager::changeTheme(const std::string& name, const int size) { updateTheme(); return true; -} \ No newline at end of file +} + +void CCursorManager::syncGsettings() { + m_pXcursor->syncGsettings(); +} diff --git a/src/managers/CursorManager.hpp b/src/managers/CursorManager.hpp index ceb4816b..796ab10e 100644 --- a/src/managers/CursorManager.hpp +++ b/src/managers/CursorManager.hpp @@ -53,6 +53,7 @@ class CCursorManager { void updateTheme(); SCursorImageData dataFor(const std::string& name); // for xwayland void setXWaylandCursor(); + void syncGsettings(); void tickAnimatedCursor(); @@ -75,4 +76,4 @@ class CCursorManager { Hyprcursor::SCursorShapeData m_sCurrentCursorShapeData; }; -inline std::unique_ptr g_pCursorManager; \ No newline at end of file +inline std::unique_ptr g_pCursorManager; diff --git a/src/managers/XCursorManager.cpp b/src/managers/XCursorManager.cpp index 1108bbb2..3d36add5 100644 --- a/src/managers/XCursorManager.cpp +++ b/src/managers/XCursorManager.cpp @@ -5,6 +5,7 @@ #include #include "config/ConfigValue.hpp" #include "helpers/CursorShapes.hpp" +#include "../managers/CursorManager.hpp" #include "debug/Log.hpp" #include "XCursorManager.hpp" diff --git a/src/managers/XCursorManager.hpp b/src/managers/XCursorManager.hpp index 464c1ec3..48fda5dd 100644 --- a/src/managers/XCursorManager.hpp +++ b/src/managers/XCursorManager.hpp @@ -31,6 +31,7 @@ class CXCursorManager { void loadTheme(const std::string& name, int size); SP getShape(std::string const& shape, int size); + void syncGsettings(); private: SP createCursor(std::string const& shape, XcursorImages* xImages); @@ -38,11 +39,10 @@ class CXCursorManager { std::string getLegacyShapeName(std::string const& shape); std::vector> loadStandardCursors(std::string const& name, int size); std::vector> loadAllFromDir(std::string const& path, int size); - void syncGsettings(); int lastLoadSize = 0; std::string themeName = ""; SP defaultCursor; SP hyprCursor; std::vector> cursors; -}; \ No newline at end of file +}; From 4aec237ec0bfcb86be9c26926f5a87e036b7f668 Mon Sep 17 00:00:00 2001 From: Patrick Ulbricht <70023807+PaddeCraft@users.noreply.github.com> Date: Tue, 13 Aug 2024 20:14:52 +0200 Subject: [PATCH 0267/2181] README: Change image sources from vaxerski/Hyprland to hyprwm/Hyprland (#7315) * readme: Change image sources from vaxerski/Hyprland to hyprwm/Hyprland * readme: Remove unused image --- README.md | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/README.md b/README.md index fc2bd206..f271c29c 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,6 @@
-banner +banner
@@ -125,7 +125,6 @@ easy IPC, much more QoL stuff than other compositors and more... -[Stars Preview]: https://starchart.cc/vaxerski/Hyprland.svg [Preview A]: https://i.ibb.co/C1yTb0r/falf.png [Preview B]: https://linfindel.github.io/cdn/hyprland-preview-b.png [Preview C]: https://i.ibb.co/B3GJg28/20221126-20h53m26s-grim.png From c5ec079c6fa92fe89bd2b689dd49197675edbe58 Mon Sep 17 00:00:00 2001 From: Mihai Fufezan Date: Tue, 13 Aug 2024 22:14:58 +0300 Subject: [PATCH 0268/2181] hyprpm, hyprctl: remove Makefiles --- .gitignore | 2 + hyprctl/Makefile | 4 - hyprpm/Makefile | 363 ----------------------------------------------- 3 files changed, 2 insertions(+), 367 deletions(-) delete mode 100644 hyprctl/Makefile delete mode 100644 hyprpm/Makefile diff --git a/.gitignore b/.gitignore index 78f794fc..2e158a4e 100644 --- a/.gitignore +++ b/.gitignore @@ -37,3 +37,5 @@ gmon.out PKGBUILD src/version.h +hyprpm/Makefile +hyprctl/Makefile diff --git a/hyprctl/Makefile b/hyprctl/Makefile deleted file mode 100644 index 9798320c..00000000 --- a/hyprctl/Makefile +++ /dev/null @@ -1,4 +0,0 @@ -all: - $(CXX) $(CXXFLAGS) -std=c++2b ./main.cpp -o ./hyprctl -clean: - rm ./hyprctl diff --git a/hyprpm/Makefile b/hyprpm/Makefile deleted file mode 100644 index 5249a14b..00000000 --- a/hyprpm/Makefile +++ /dev/null @@ -1,363 +0,0 @@ -# CMAKE generated file: DO NOT EDIT! -# Generated by "Unix Makefiles" Generator, CMake Version 3.29 - -# Default target executed when no arguments are given to make. -default_target: all -.PHONY : default_target - -# Allow only one "make -f Makefile2" at a time, but pass parallelism. -.NOTPARALLEL: - -#============================================================================= -# Special targets provided by cmake. - -# Disable implicit rules so canonical targets will work. -.SUFFIXES: - -# Disable VCS-based implicit rules. -% : %,v - -# Disable VCS-based implicit rules. -% : RCS/% - -# Disable VCS-based implicit rules. -% : RCS/%,v - -# Disable VCS-based implicit rules. -% : SCCS/s.% - -# Disable VCS-based implicit rules. -% : s.% - -.SUFFIXES: .hpux_make_needs_suffix_list - -# Command-line flag to silence nested $(MAKE). -$(VERBOSE)MAKESILENT = -s - -#Suppress display of executed commands. -$(VERBOSE).SILENT: - -# A target that is always out of date. -cmake_force: -.PHONY : cmake_force - -#============================================================================= -# Set environment variables for the build. - -# The shell in which to execute make rules. -SHELL = /bin/sh - -# The CMake executable. -CMAKE_COMMAND = /nix/store/aqckch626lg0vxh41dabyzrq0jx7gdk5-cmake-3.29.6/bin/cmake - -# The command to remove a file. -RM = /nix/store/aqckch626lg0vxh41dabyzrq0jx7gdk5-cmake-3.29.6/bin/cmake -E rm -f - -# Escaping for special characters. -EQUALS = = - -# The top-level source directory on which CMake was run. -CMAKE_SOURCE_DIR = /home/mihai/Documents/code/git/Hyprland - -# The top-level build directory on which CMake was run. -CMAKE_BINARY_DIR = /home/mihai/Documents/code/git/Hyprland - -#============================================================================= -# Targets provided globally by CMake. - -# Special rule for the target package -package: preinstall - @$(CMAKE_COMMAND) -E cmake_echo_color "--switch=$(COLOR)" --cyan "Run CPack packaging tool..." - cd /home/mihai/Documents/code/git/Hyprland && /nix/store/aqckch626lg0vxh41dabyzrq0jx7gdk5-cmake-3.29.6/bin/cpack --config ./CPackConfig.cmake -.PHONY : package - -# Special rule for the target package -package/fast: package -.PHONY : package/fast - -# Special rule for the target package_source -package_source: - @$(CMAKE_COMMAND) -E cmake_echo_color "--switch=$(COLOR)" --cyan "Run CPack packaging tool for source..." - cd /home/mihai/Documents/code/git/Hyprland && /nix/store/aqckch626lg0vxh41dabyzrq0jx7gdk5-cmake-3.29.6/bin/cpack --config ./CPackSourceConfig.cmake /home/mihai/Documents/code/git/Hyprland/CPackSourceConfig.cmake -.PHONY : package_source - -# Special rule for the target package_source -package_source/fast: package_source -.PHONY : package_source/fast - -# Special rule for the target edit_cache -edit_cache: - @$(CMAKE_COMMAND) -E cmake_echo_color "--switch=$(COLOR)" --cyan "No interactive CMake dialog available..." - /nix/store/aqckch626lg0vxh41dabyzrq0jx7gdk5-cmake-3.29.6/bin/cmake -E echo No\ interactive\ CMake\ dialog\ available. -.PHONY : edit_cache - -# Special rule for the target edit_cache -edit_cache/fast: edit_cache -.PHONY : edit_cache/fast - -# Special rule for the target rebuild_cache -rebuild_cache: - @$(CMAKE_COMMAND) -E cmake_echo_color "--switch=$(COLOR)" --cyan "Running CMake to regenerate build system..." - /nix/store/aqckch626lg0vxh41dabyzrq0jx7gdk5-cmake-3.29.6/bin/cmake --regenerate-during-build -S$(CMAKE_SOURCE_DIR) -B$(CMAKE_BINARY_DIR) -.PHONY : rebuild_cache - -# Special rule for the target rebuild_cache -rebuild_cache/fast: rebuild_cache -.PHONY : rebuild_cache/fast - -# Special rule for the target list_install_components -list_install_components: - @$(CMAKE_COMMAND) -E cmake_echo_color "--switch=$(COLOR)" --cyan "Available install components are: \"Unspecified\"" -.PHONY : list_install_components - -# Special rule for the target list_install_components -list_install_components/fast: list_install_components -.PHONY : list_install_components/fast - -# Special rule for the target install -install: preinstall - @$(CMAKE_COMMAND) -E cmake_echo_color "--switch=$(COLOR)" --cyan "Install the project..." - /nix/store/aqckch626lg0vxh41dabyzrq0jx7gdk5-cmake-3.29.6/bin/cmake -P cmake_install.cmake -.PHONY : install - -# Special rule for the target install -install/fast: preinstall/fast - @$(CMAKE_COMMAND) -E cmake_echo_color "--switch=$(COLOR)" --cyan "Install the project..." - /nix/store/aqckch626lg0vxh41dabyzrq0jx7gdk5-cmake-3.29.6/bin/cmake -P cmake_install.cmake -.PHONY : install/fast - -# Special rule for the target install/local -install/local: preinstall - @$(CMAKE_COMMAND) -E cmake_echo_color "--switch=$(COLOR)" --cyan "Installing only the local directory..." - /nix/store/aqckch626lg0vxh41dabyzrq0jx7gdk5-cmake-3.29.6/bin/cmake -DCMAKE_INSTALL_LOCAL_ONLY=1 -P cmake_install.cmake -.PHONY : install/local - -# Special rule for the target install/local -install/local/fast: preinstall/fast - @$(CMAKE_COMMAND) -E cmake_echo_color "--switch=$(COLOR)" --cyan "Installing only the local directory..." - /nix/store/aqckch626lg0vxh41dabyzrq0jx7gdk5-cmake-3.29.6/bin/cmake -DCMAKE_INSTALL_LOCAL_ONLY=1 -P cmake_install.cmake -.PHONY : install/local/fast - -# Special rule for the target install/strip -install/strip: preinstall - @$(CMAKE_COMMAND) -E cmake_echo_color "--switch=$(COLOR)" --cyan "Installing the project stripped..." - /nix/store/aqckch626lg0vxh41dabyzrq0jx7gdk5-cmake-3.29.6/bin/cmake -DCMAKE_INSTALL_DO_STRIP=1 -P cmake_install.cmake -.PHONY : install/strip - -# Special rule for the target install/strip -install/strip/fast: preinstall/fast - @$(CMAKE_COMMAND) -E cmake_echo_color "--switch=$(COLOR)" --cyan "Installing the project stripped..." - /nix/store/aqckch626lg0vxh41dabyzrq0jx7gdk5-cmake-3.29.6/bin/cmake -DCMAKE_INSTALL_DO_STRIP=1 -P cmake_install.cmake -.PHONY : install/strip/fast - -# The main all target -all: cmake_check_build_system - cd /home/mihai/Documents/code/git/Hyprland && $(CMAKE_COMMAND) -E cmake_progress_start /home/mihai/Documents/code/git/Hyprland/CMakeFiles /home/mihai/Documents/code/git/Hyprland/hyprpm//CMakeFiles/progress.marks - cd /home/mihai/Documents/code/git/Hyprland && $(MAKE) $(MAKESILENT) -f CMakeFiles/Makefile2 hyprpm/all - $(CMAKE_COMMAND) -E cmake_progress_start /home/mihai/Documents/code/git/Hyprland/CMakeFiles 0 -.PHONY : all - -# The main clean target -clean: - cd /home/mihai/Documents/code/git/Hyprland && $(MAKE) $(MAKESILENT) -f CMakeFiles/Makefile2 hyprpm/clean -.PHONY : clean - -# The main clean target -clean/fast: clean -.PHONY : clean/fast - -# Prepare targets for installation. -preinstall: all - cd /home/mihai/Documents/code/git/Hyprland && $(MAKE) $(MAKESILENT) -f CMakeFiles/Makefile2 hyprpm/preinstall -.PHONY : preinstall - -# Prepare targets for installation. -preinstall/fast: - cd /home/mihai/Documents/code/git/Hyprland && $(MAKE) $(MAKESILENT) -f CMakeFiles/Makefile2 hyprpm/preinstall -.PHONY : preinstall/fast - -# clear depends -depend: - cd /home/mihai/Documents/code/git/Hyprland && $(CMAKE_COMMAND) -P /home/mihai/Documents/code/git/Hyprland/CMakeFiles/VerifyGlobs.cmake - cd /home/mihai/Documents/code/git/Hyprland && $(CMAKE_COMMAND) -S$(CMAKE_SOURCE_DIR) -B$(CMAKE_BINARY_DIR) --check-build-system CMakeFiles/Makefile.cmake 1 -.PHONY : depend - -# Convenience name for target. -hyprpm/CMakeFiles/hyprpm.dir/rule: - cd /home/mihai/Documents/code/git/Hyprland && $(MAKE) $(MAKESILENT) -f CMakeFiles/Makefile2 hyprpm/CMakeFiles/hyprpm.dir/rule -.PHONY : hyprpm/CMakeFiles/hyprpm.dir/rule - -# Convenience name for target. -hyprpm: hyprpm/CMakeFiles/hyprpm.dir/rule -.PHONY : hyprpm - -# fast build rule for target. -hyprpm/fast: - cd /home/mihai/Documents/code/git/Hyprland && $(MAKE) $(MAKESILENT) -f hyprpm/CMakeFiles/hyprpm.dir/build.make hyprpm/CMakeFiles/hyprpm.dir/build -.PHONY : hyprpm/fast - -src/core/DataState.o: src/core/DataState.cpp.o -.PHONY : src/core/DataState.o - -# target to build an object file -src/core/DataState.cpp.o: - cd /home/mihai/Documents/code/git/Hyprland && $(MAKE) $(MAKESILENT) -f hyprpm/CMakeFiles/hyprpm.dir/build.make hyprpm/CMakeFiles/hyprpm.dir/src/core/DataState.cpp.o -.PHONY : src/core/DataState.cpp.o - -src/core/DataState.i: src/core/DataState.cpp.i -.PHONY : src/core/DataState.i - -# target to preprocess a source file -src/core/DataState.cpp.i: - cd /home/mihai/Documents/code/git/Hyprland && $(MAKE) $(MAKESILENT) -f hyprpm/CMakeFiles/hyprpm.dir/build.make hyprpm/CMakeFiles/hyprpm.dir/src/core/DataState.cpp.i -.PHONY : src/core/DataState.cpp.i - -src/core/DataState.s: src/core/DataState.cpp.s -.PHONY : src/core/DataState.s - -# target to generate assembly for a file -src/core/DataState.cpp.s: - cd /home/mihai/Documents/code/git/Hyprland && $(MAKE) $(MAKESILENT) -f hyprpm/CMakeFiles/hyprpm.dir/build.make hyprpm/CMakeFiles/hyprpm.dir/src/core/DataState.cpp.s -.PHONY : src/core/DataState.cpp.s - -src/core/Manifest.o: src/core/Manifest.cpp.o -.PHONY : src/core/Manifest.o - -# target to build an object file -src/core/Manifest.cpp.o: - cd /home/mihai/Documents/code/git/Hyprland && $(MAKE) $(MAKESILENT) -f hyprpm/CMakeFiles/hyprpm.dir/build.make hyprpm/CMakeFiles/hyprpm.dir/src/core/Manifest.cpp.o -.PHONY : src/core/Manifest.cpp.o - -src/core/Manifest.i: src/core/Manifest.cpp.i -.PHONY : src/core/Manifest.i - -# target to preprocess a source file -src/core/Manifest.cpp.i: - cd /home/mihai/Documents/code/git/Hyprland && $(MAKE) $(MAKESILENT) -f hyprpm/CMakeFiles/hyprpm.dir/build.make hyprpm/CMakeFiles/hyprpm.dir/src/core/Manifest.cpp.i -.PHONY : src/core/Manifest.cpp.i - -src/core/Manifest.s: src/core/Manifest.cpp.s -.PHONY : src/core/Manifest.s - -# target to generate assembly for a file -src/core/Manifest.cpp.s: - cd /home/mihai/Documents/code/git/Hyprland && $(MAKE) $(MAKESILENT) -f hyprpm/CMakeFiles/hyprpm.dir/build.make hyprpm/CMakeFiles/hyprpm.dir/src/core/Manifest.cpp.s -.PHONY : src/core/Manifest.cpp.s - -src/core/PluginManager.o: src/core/PluginManager.cpp.o -.PHONY : src/core/PluginManager.o - -# target to build an object file -src/core/PluginManager.cpp.o: - cd /home/mihai/Documents/code/git/Hyprland && $(MAKE) $(MAKESILENT) -f hyprpm/CMakeFiles/hyprpm.dir/build.make hyprpm/CMakeFiles/hyprpm.dir/src/core/PluginManager.cpp.o -.PHONY : src/core/PluginManager.cpp.o - -src/core/PluginManager.i: src/core/PluginManager.cpp.i -.PHONY : src/core/PluginManager.i - -# target to preprocess a source file -src/core/PluginManager.cpp.i: - cd /home/mihai/Documents/code/git/Hyprland && $(MAKE) $(MAKESILENT) -f hyprpm/CMakeFiles/hyprpm.dir/build.make hyprpm/CMakeFiles/hyprpm.dir/src/core/PluginManager.cpp.i -.PHONY : src/core/PluginManager.cpp.i - -src/core/PluginManager.s: src/core/PluginManager.cpp.s -.PHONY : src/core/PluginManager.s - -# target to generate assembly for a file -src/core/PluginManager.cpp.s: - cd /home/mihai/Documents/code/git/Hyprland && $(MAKE) $(MAKESILENT) -f hyprpm/CMakeFiles/hyprpm.dir/build.make hyprpm/CMakeFiles/hyprpm.dir/src/core/PluginManager.cpp.s -.PHONY : src/core/PluginManager.cpp.s - -src/main.o: src/main.cpp.o -.PHONY : src/main.o - -# target to build an object file -src/main.cpp.o: - cd /home/mihai/Documents/code/git/Hyprland && $(MAKE) $(MAKESILENT) -f hyprpm/CMakeFiles/hyprpm.dir/build.make hyprpm/CMakeFiles/hyprpm.dir/src/main.cpp.o -.PHONY : src/main.cpp.o - -src/main.i: src/main.cpp.i -.PHONY : src/main.i - -# target to preprocess a source file -src/main.cpp.i: - cd /home/mihai/Documents/code/git/Hyprland && $(MAKE) $(MAKESILENT) -f hyprpm/CMakeFiles/hyprpm.dir/build.make hyprpm/CMakeFiles/hyprpm.dir/src/main.cpp.i -.PHONY : src/main.cpp.i - -src/main.s: src/main.cpp.s -.PHONY : src/main.s - -# target to generate assembly for a file -src/main.cpp.s: - cd /home/mihai/Documents/code/git/Hyprland && $(MAKE) $(MAKESILENT) -f hyprpm/CMakeFiles/hyprpm.dir/build.make hyprpm/CMakeFiles/hyprpm.dir/src/main.cpp.s -.PHONY : src/main.cpp.s - -src/progress/CProgressBar.o: src/progress/CProgressBar.cpp.o -.PHONY : src/progress/CProgressBar.o - -# target to build an object file -src/progress/CProgressBar.cpp.o: - cd /home/mihai/Documents/code/git/Hyprland && $(MAKE) $(MAKESILENT) -f hyprpm/CMakeFiles/hyprpm.dir/build.make hyprpm/CMakeFiles/hyprpm.dir/src/progress/CProgressBar.cpp.o -.PHONY : src/progress/CProgressBar.cpp.o - -src/progress/CProgressBar.i: src/progress/CProgressBar.cpp.i -.PHONY : src/progress/CProgressBar.i - -# target to preprocess a source file -src/progress/CProgressBar.cpp.i: - cd /home/mihai/Documents/code/git/Hyprland && $(MAKE) $(MAKESILENT) -f hyprpm/CMakeFiles/hyprpm.dir/build.make hyprpm/CMakeFiles/hyprpm.dir/src/progress/CProgressBar.cpp.i -.PHONY : src/progress/CProgressBar.cpp.i - -src/progress/CProgressBar.s: src/progress/CProgressBar.cpp.s -.PHONY : src/progress/CProgressBar.s - -# target to generate assembly for a file -src/progress/CProgressBar.cpp.s: - cd /home/mihai/Documents/code/git/Hyprland && $(MAKE) $(MAKESILENT) -f hyprpm/CMakeFiles/hyprpm.dir/build.make hyprpm/CMakeFiles/hyprpm.dir/src/progress/CProgressBar.cpp.s -.PHONY : src/progress/CProgressBar.cpp.s - -# Help Target -help: - @echo "The following are some of the valid targets for this Makefile:" - @echo "... all (the default if no target is provided)" - @echo "... clean" - @echo "... depend" - @echo "... edit_cache" - @echo "... install" - @echo "... install/local" - @echo "... install/strip" - @echo "... list_install_components" - @echo "... package" - @echo "... package_source" - @echo "... rebuild_cache" - @echo "... hyprpm" - @echo "... src/core/DataState.o" - @echo "... src/core/DataState.i" - @echo "... src/core/DataState.s" - @echo "... src/core/Manifest.o" - @echo "... src/core/Manifest.i" - @echo "... src/core/Manifest.s" - @echo "... src/core/PluginManager.o" - @echo "... src/core/PluginManager.i" - @echo "... src/core/PluginManager.s" - @echo "... src/main.o" - @echo "... src/main.i" - @echo "... src/main.s" - @echo "... src/progress/CProgressBar.o" - @echo "... src/progress/CProgressBar.i" - @echo "... src/progress/CProgressBar.s" -.PHONY : help - - - -#============================================================================= -# Special targets to cleanup operation of make. - -# Special rule to run CMake to check the build system integrity. -# No rule that depends on this can have commands that come from listfiles -# because they might be regenerated. -cmake_check_build_system: - cd /home/mihai/Documents/code/git/Hyprland && $(CMAKE_COMMAND) -P /home/mihai/Documents/code/git/Hyprland/CMakeFiles/VerifyGlobs.cmake - cd /home/mihai/Documents/code/git/Hyprland && $(CMAKE_COMMAND) -S$(CMAKE_SOURCE_DIR) -B$(CMAKE_BINARY_DIR) --check-build-system CMakeFiles/Makefile.cmake 0 -.PHONY : cmake_check_build_system - From 3b4aabe04c7756fb0a70d78b6f0e701228f46345 Mon Sep 17 00:00:00 2001 From: MightyPlaza <123664421+MightyPlaza@users.noreply.github.com> Date: Tue, 13 Aug 2024 20:00:31 +0000 Subject: [PATCH 0269/2181] decorations: fix manual resize not recalculating decos (#7323) modified: src/layout/DwindleLayout.cpp modified: src/layout/MasterLayout.cpp --- src/layout/DwindleLayout.cpp | 2 ++ src/layout/MasterLayout.cpp | 2 ++ 2 files changed, 4 insertions(+) diff --git a/src/layout/DwindleLayout.cpp b/src/layout/DwindleLayout.cpp index acdc3de2..20085ff7 100644 --- a/src/layout/DwindleLayout.cpp +++ b/src/layout/DwindleLayout.cpp @@ -246,6 +246,8 @@ void CHyprDwindleLayout::applyNodeDataToWindow(SDwindleNodeData* pNode, bool for g_pHyprRenderer->damageWindow(PWINDOW); } + + PWINDOW->updateWindowDecos(); } void CHyprDwindleLayout::onWindowCreatedTiling(PHLWINDOW pWindow, eDirection direction) { diff --git a/src/layout/MasterLayout.cpp b/src/layout/MasterLayout.cpp index aa1c0adf..e0b48e98 100644 --- a/src/layout/MasterLayout.cpp +++ b/src/layout/MasterLayout.cpp @@ -732,6 +732,8 @@ void CHyprMasterLayout::applyNodeDataToWindow(SMasterNodeData* pNode) { g_pHyprRenderer->damageWindow(PWINDOW); } + + PWINDOW->updateWindowDecos(); } bool CHyprMasterLayout::isWindowTiled(PHLWINDOW pWindow) { From 197f8807900afc81c1c92ad17e621d1998ee268b Mon Sep 17 00:00:00 2001 From: davc0n Date: Wed, 14 Aug 2024 19:35:07 +0200 Subject: [PATCH 0270/2181] logs: Add file path to asset ERR log (#7336) --- src/render/OpenGL.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/render/OpenGL.cpp b/src/render/OpenGL.cpp index 0461662c..63cc2203 100644 --- a/src/render/OpenGL.cpp +++ b/src/render/OpenGL.cpp @@ -2690,7 +2690,7 @@ void CHyprOpenGLImpl::createBGTextureForMonitor(CMonitor* pMonitor) { // check if wallpapers exist std::error_code err; if (!std::filesystem::exists(texPath, err)) { - Debug::log(ERR, "createBGTextureForMonitor: failed, file doesn't exist or access denied, ec: {}", err.message()); + Debug::log(ERR, "createBGTextureForMonitor: failed, file \"{}\" doesn't exist or access denied, ec: {}", texPath, err.message()); return; // the texture will be empty, oh well. We'll clear with a solid color anyways. } From d85ae306c5746c6ebeac74c2a7a520bb3f05a119 Mon Sep 17 00:00:00 2001 From: Ikalco <73481042+ikalco@users.noreply.github.com> Date: Thu, 15 Aug 2024 06:37:56 -0500 Subject: [PATCH 0271/2181] xcursor: handle file errors when loading xcursor themes (#7326) --- src/managers/XCursorManager.cpp | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/managers/XCursorManager.cpp b/src/managers/XCursorManager.cpp index 3d36add5..0921bcd4 100644 --- a/src/managers/XCursorManager.cpp +++ b/src/managers/XCursorManager.cpp @@ -511,8 +511,11 @@ std::vector> CXCursorManager::loadAllFromDir(std::string const& pa if (std::filesystem::exists(path) && std::filesystem::is_directory(path)) { for (const auto& entry : std::filesystem::directory_iterator(path)) { - if (!entry.is_regular_file() && !entry.is_symlink()) + std::error_code e1, e2; + if ((!entry.is_regular_file(e1) && !entry.is_symlink(e2)) || e1 || e2) { + Debug::log(WARN, "XCursor failed to load shape {}: {}", entry.path().stem().string(), e1 ? e1.message() : e2.message()); continue; + } auto const& full = entry.path().string(); using PcloseType = int (*)(FILE*); From c30dfe92eee017bc70e131fa30d3c87b56d0a143 Mon Sep 17 00:00:00 2001 From: vaxerski Date: Thu, 15 Aug 2024 11:39:29 +0000 Subject: [PATCH 0272/2181] [gha] Nix: update inputs --- flake.lock | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/flake.lock b/flake.lock index 8930d2e3..b4868793 100644 --- a/flake.lock +++ b/flake.lock @@ -154,11 +154,11 @@ }, "nixpkgs": { "locked": { - "lastModified": 1723175592, - "narHash": "sha256-M0xJ3FbDUc4fRZ84dPGx5VvgFsOzds77KiBMW/mMTnI=", + "lastModified": 1723637854, + "narHash": "sha256-med8+5DSWa2UnOqtdICndjDAEjxr5D7zaIiK4pn0Q7c=", "owner": "NixOS", "repo": "nixpkgs", - "rev": "5e0ca22929f3342b19569b21b2f3462f053e497b", + "rev": "c3aa7b8938b17aebd2deecf7be0636000d62a2b9", "type": "github" }, "original": { From 069faa4027d016549ee72afcd7df3b2c1e7ee578 Mon Sep 17 00:00:00 2001 From: Mirkwood Date: Thu, 15 Aug 2024 14:03:23 +0200 Subject: [PATCH 0273/2181] helpers: fix: revert to signed arithmetic for cycling through workspaces (#7339) The code clearly expects signed types there. Fixes #7329 --- src/helpers/MiscFunctions.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/helpers/MiscFunctions.cpp b/src/helpers/MiscFunctions.cpp index a81aa7d1..86f24e3a 100644 --- a/src/helpers/MiscFunctions.cpp +++ b/src/helpers/MiscFunctions.cpp @@ -472,7 +472,7 @@ SWorkspaceIDName getWorkspaceIDNameFromString(const std::string& in) { std::sort(validWSes.begin(), validWSes.end()); - size_t currentItem = -1; + ssize_t currentItem = -1; if (absolute) { // 1-index @@ -481,7 +481,7 @@ SWorkspaceIDName getWorkspaceIDNameFromString(const std::string& in) { // clamp if (currentItem < 0) { currentItem = 0; - } else if (currentItem >= validWSes.size()) { + } else if (currentItem >= (ssize_t)validWSes.size()) { currentItem = validWSes.size() - 1; } } else { @@ -490,7 +490,7 @@ SWorkspaceIDName getWorkspaceIDNameFromString(const std::string& in) { // get the current item WORKSPACEID activeWSID = g_pCompositor->m_pLastMonitor->activeWorkspace ? g_pCompositor->m_pLastMonitor->activeWorkspace->m_iID : 1; - for (size_t i = 0; i < validWSes.size(); i++) { + for (ssize_t i = 0; i < (ssize_t)validWSes.size(); i++) { if (validWSes[i] == activeWSID) { currentItem = i; break; @@ -501,7 +501,7 @@ SWorkspaceIDName getWorkspaceIDNameFromString(const std::string& in) { currentItem += remains; // sanitize - if (currentItem >= validWSes.size()) { + if (currentItem >= (ssize_t)validWSes.size()) { currentItem = currentItem % validWSes.size(); } else if (currentItem < 0) { currentItem = validWSes.size() + currentItem; From 0c56be74a310e137f577a2b71fc2c72a8100eada Mon Sep 17 00:00:00 2001 From: Kyle <56144092+txkyel@users.noreply.github.com> Date: Thu, 15 Aug 2024 12:04:24 -0400 Subject: [PATCH 0274/2181] keybinds: Fix syncFullscreen inconsistent with state when set by fullscreenState (#7343) * Set syncFullscreen to true on synced non -1 states * Fix syncFullscreen value in fullscreenState --- src/managers/KeybindManager.cpp | 19 ++++++------------- 1 file changed, 6 insertions(+), 13 deletions(-) diff --git a/src/managers/KeybindManager.cpp b/src/managers/KeybindManager.cpp index 8fc025ec..38593497 100644 --- a/src/managers/KeybindManager.cpp +++ b/src/managers/KeybindManager.cpp @@ -1179,23 +1179,16 @@ void CKeybindManager::fullscreenStateActive(std::string args) { const sFullscreenState STATE = sFullscreenState{.internal = (internalMode != -1 ? (eFullscreenMode)internalMode : PWINDOW->m_sFullscreenState.internal), .client = (clientMode != -1 ? (eFullscreenMode)clientMode : PWINDOW->m_sFullscreenState.client)}; - if (internalMode != -1 && clientMode != -1 && PWINDOW->m_sFullscreenState.internal == STATE.internal && PWINDOW->m_sFullscreenState.client == STATE.client) { + if (internalMode != -1 && clientMode != -1 && PWINDOW->m_sFullscreenState.internal == STATE.internal && PWINDOW->m_sFullscreenState.client == STATE.client) g_pCompositor->setWindowFullscreenState(PWINDOW, sFullscreenState{.internal = FSMODE_NONE, .client = FSMODE_NONE}); - PWINDOW->m_sWindowData.syncFullscreen = CWindowOverridableVar(true, PRIORITY_SET_PROP); - return; - } - - if (internalMode != -1 && clientMode == -1 && PWINDOW->m_sFullscreenState.internal == STATE.internal) { + else if (internalMode != -1 && clientMode == -1 && PWINDOW->m_sFullscreenState.internal == STATE.internal) g_pCompositor->setWindowFullscreenState(PWINDOW, sFullscreenState{.internal = FSMODE_NONE, .client = PWINDOW->m_sFullscreenState.client}); - return; - } - - if (internalMode == -1 && clientMode != -1 && PWINDOW->m_sFullscreenState.client == STATE.client) { + else if (internalMode == -1 && clientMode != -1 && PWINDOW->m_sFullscreenState.client == STATE.client) g_pCompositor->setWindowFullscreenState(PWINDOW, sFullscreenState{.internal = PWINDOW->m_sFullscreenState.internal, .client = FSMODE_NONE}); - return; - } + else + g_pCompositor->setWindowFullscreenState(PWINDOW, STATE); - g_pCompositor->setWindowFullscreenState(PWINDOW, STATE); + PWINDOW->m_sWindowData.syncFullscreen = CWindowOverridableVar(PWINDOW->m_sFullscreenState.internal == PWINDOW->m_sFullscreenState.client, PRIORITY_SET_PROP); } void CKeybindManager::moveActiveToWorkspace(std::string args) { From 520e91238f0e6e6990e6a0845d73d85012485525 Mon Sep 17 00:00:00 2001 From: Maximilian Seidler <78690852+PaideiaDilemma@users.noreply.github.com> Date: Thu, 15 Aug 2024 16:08:54 +0000 Subject: [PATCH 0275/2181] gamma-control: fix crash on monitor disconnect (#7353) --- src/protocols/GammaControl.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/protocols/GammaControl.cpp b/src/protocols/GammaControl.cpp index 494d9862..4febffbb 100644 --- a/src/protocols/GammaControl.cpp +++ b/src/protocols/GammaControl.cpp @@ -109,7 +109,7 @@ CGammaControl::CGammaControl(SP resource_, wl_resource* out } CGammaControl::~CGammaControl() { - if (!gammaTableSet || !pMonitor) + if (!gammaTableSet || !pMonitor || !pMonitor->output) return; // reset the LUT if the client dies for whatever reason and doesn't unset the gamma From 15f942000ef53776852d6d9dfd303e691aed73e3 Mon Sep 17 00:00:00 2001 From: Vladimir-csp <4061903+Vladimir-csp@users.noreply.github.com> Date: Thu, 15 Aug 2024 19:14:48 +0300 Subject: [PATCH 0276/2181] core: Preserve existing XDG_CURRENT_DESKTOP (#7347) * Preserve existing XDG_CURRENT_DESKTOP * fix --------- Co-authored-by: vaxerski --- src/Compositor.cpp | 7 ++++++- src/Compositor.hpp | 1 + src/main.cpp | 1 - 3 files changed, 7 insertions(+), 2 deletions(-) diff --git a/src/Compositor.cpp b/src/Compositor.cpp index 26a985ef..4024fadf 100644 --- a/src/Compositor.cpp +++ b/src/Compositor.cpp @@ -305,6 +305,10 @@ void CCompositor::initServer(std::string socketName, int socketFd) { setenv("WAYLAND_DISPLAY", m_szWLDisplaySocket.c_str(), 1); setenv("XDG_SESSION_TYPE", "wayland", 1); + if (!getenv("XDG_CURRENT_DESKTOP")) { + setenv("XDG_CURRENT_DESKTOP", "Hyprland", 1); + m_bDesktopEnvSet = true; + } initManagers(STAGE_BASICINIT); @@ -422,7 +426,8 @@ void CCompositor::cleanEnvironment() { // in main unsetenv("HYPRLAND_CMD"); unsetenv("XDG_BACKEND"); - unsetenv("XDG_CURRENT_DESKTOP"); + if (m_bDesktopEnvSet) + unsetenv("XDG_CURRENT_DESKTOP"); if (m_pAqBackend->hasSession()) { const auto CMD = diff --git a/src/Compositor.hpp b/src/Compositor.hpp index 5e9e3266..a570a06e 100644 --- a/src/Compositor.hpp +++ b/src/Compositor.hpp @@ -91,6 +91,7 @@ class CCompositor { bool m_bNextIsUnsafe = false; CMonitor* m_pUnsafeOutput = nullptr; // fallback output for the unsafe state bool m_bIsShuttingDown = false; + bool m_bDesktopEnvSet = false; // ------------------------------------------------- // diff --git a/src/main.cpp b/src/main.cpp index e85b0a22..820a248c 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -36,7 +36,6 @@ int main(int argc, char** argv) { setenv("XDG_BACKEND", "wayland", 1); setenv("_JAVA_AWT_WM_NONREPARENTING", "1", 1); setenv("MOZ_ENABLE_WAYLAND", "1", 1); - setenv("XDG_CURRENT_DESKTOP", "Hyprland", 1); // parse some args std::string configPath; From 12d9901472c6f9128fa8b16c25b3a879d1859e60 Mon Sep 17 00:00:00 2001 From: Tom Englund Date: Thu, 15 Aug 2024 18:16:18 +0200 Subject: [PATCH 0277/2181] protocols: refactor protocol logging to a macro (#7324) this avoids the usage of the unique_ptr PROTO::protocol before it has been constructed incase one wants to log something inside the constructor itself, move the logging to macros and print file:linenumber on ERR,CRIT,WARN and classname on the rest of the levels. --- src/protocols/AlphaModifier.cpp | 2 -- src/protocols/CursorShape.cpp | 2 -- src/protocols/DRMLease.cpp | 4 +-- src/protocols/DRMSyncobj.cpp | 2 -- src/protocols/DataDeviceWlr.cpp | 2 -- src/protocols/FocusGrab.cpp | 2 -- src/protocols/ForeignToplevel.cpp | 2 -- src/protocols/ForeignToplevelWlr.cpp | 2 -- src/protocols/FractionalScale.cpp | 2 -- src/protocols/GammaControl.cpp | 2 -- src/protocols/GlobalShortcuts.cpp | 2 -- src/protocols/IdleNotify.cpp | 2 -- src/protocols/InputMethodV2.cpp | 2 -- src/protocols/LayerShell.cpp | 2 -- src/protocols/LinuxDMABUF.cpp | 10 +++---- src/protocols/MesaDRM.cpp | 8 ++---- src/protocols/OutputManagement.cpp | 2 -- src/protocols/OutputPower.cpp | 2 -- src/protocols/PointerConstraints.cpp | 2 -- src/protocols/PointerGestures.cpp | 2 -- src/protocols/PresentationTime.cpp | 2 -- src/protocols/PrimarySelection.cpp | 2 -- src/protocols/Screencopy.cpp | 2 -- src/protocols/ServerDecorationKDE.cpp | 2 -- src/protocols/SessionLock.cpp | 2 -- src/protocols/ShortcutsInhibit.cpp | 2 -- src/protocols/Tablet.cpp | 2 -- src/protocols/TextInputV1.cpp | 2 -- src/protocols/TextInputV3.cpp | 2 -- src/protocols/ToplevelExport.cpp | 2 -- src/protocols/Viewporter.cpp | 2 -- src/protocols/VirtualKeyboard.cpp | 2 -- src/protocols/VirtualPointer.cpp | 2 -- src/protocols/WaylandProtocol.cpp | 4 +-- src/protocols/WaylandProtocol.hpp | 40 +++++++++++++++++++++------ src/protocols/XDGActivation.cpp | 2 -- src/protocols/XDGDecoration.cpp | 2 -- src/protocols/XDGOutput.cpp | 2 -- src/protocols/XDGShell.cpp | 2 -- src/protocols/XWaylandShell.cpp | 2 -- src/protocols/core/Compositor.cpp | 2 -- src/protocols/core/DataDevice.cpp | 2 -- src/protocols/core/Seat.cpp | 2 -- src/protocols/core/Shm.cpp | 2 -- src/protocols/core/Subcompositor.cpp | 2 -- 45 files changed, 42 insertions(+), 104 deletions(-) diff --git a/src/protocols/AlphaModifier.cpp b/src/protocols/AlphaModifier.cpp index 38b8c800..13597fa9 100644 --- a/src/protocols/AlphaModifier.cpp +++ b/src/protocols/AlphaModifier.cpp @@ -4,8 +4,6 @@ #include "../render/Renderer.hpp" #include "core/Compositor.hpp" -#define LOGM PROTO::alphaModifier->protoLog - CAlphaModifier::CAlphaModifier(SP resource_, SP surface_) : resource(resource_), pSurface(surface_) { if (!resource->resource()) return; diff --git a/src/protocols/CursorShape.cpp b/src/protocols/CursorShape.cpp index 812afe53..233a5df9 100644 --- a/src/protocols/CursorShape.cpp +++ b/src/protocols/CursorShape.cpp @@ -2,8 +2,6 @@ #include #include "../helpers/CursorShapes.hpp" -#define LOGM PROTO::cursorShape->protoLog - CCursorShapeProtocol::CCursorShapeProtocol(const wl_interface* iface, const int& ver, const std::string& name) : IWaylandProtocol(iface, ver, name) { ; } diff --git a/src/protocols/DRMLease.cpp b/src/protocols/DRMLease.cpp index 3ab38ea1..bc0945f1 100644 --- a/src/protocols/DRMLease.cpp +++ b/src/protocols/DRMLease.cpp @@ -4,8 +4,6 @@ #include #include -#define LOGM PROTO::lease->protoLog - CDRMLeaseResource::CDRMLeaseResource(SP resource_, SP request) : resource(resource_) { if (!good()) return; @@ -226,7 +224,7 @@ CDRMLeaseDevice::CDRMLeaseDevice(SP drmBackend) : backe auto fd = drm->getNonMasterFD(); if (fd < 0) { - Debug::log(ERR, "[DRMLease] Failed to dup fd for drm node {}", drm->gpuName); + LOGM(ERR, "Failed to dup fd for drm node {}", drm->gpuName); return; } diff --git a/src/protocols/DRMSyncobj.cpp b/src/protocols/DRMSyncobj.cpp index 9a48b99a..4993f1a4 100644 --- a/src/protocols/DRMSyncobj.cpp +++ b/src/protocols/DRMSyncobj.cpp @@ -7,8 +7,6 @@ #include -#define LOGM PROTO::sync->protoLog - CDRMSyncobjSurfaceResource::CDRMSyncobjSurfaceResource(SP resource_, SP surface_) : surface(surface_), resource(resource_) { if (!good()) return; diff --git a/src/protocols/DataDeviceWlr.cpp b/src/protocols/DataDeviceWlr.cpp index c039d3b4..ad6ee89a 100644 --- a/src/protocols/DataDeviceWlr.cpp +++ b/src/protocols/DataDeviceWlr.cpp @@ -3,8 +3,6 @@ #include "../managers/SeatManager.hpp" #include "core/Seat.hpp" -#define LOGM PROTO::dataWlr->protoLog - CWLRDataOffer::CWLRDataOffer(SP resource_, SP source_) : source(source_), resource(resource_) { if (!good()) return; diff --git a/src/protocols/FocusGrab.cpp b/src/protocols/FocusGrab.cpp index 40f9af44..2d6b2ee2 100644 --- a/src/protocols/FocusGrab.cpp +++ b/src/protocols/FocusGrab.cpp @@ -8,8 +8,6 @@ #include #include -#define LOGM PROTO::focusGrab->protoLog - CFocusGrabSurfaceState::CFocusGrabSurfaceState(CFocusGrab* grab, SP surface) { listeners.destroy = surface->events.destroy.registerListener([=](std::any d) { grab->eraseSurface(surface); }); } diff --git a/src/protocols/ForeignToplevel.cpp b/src/protocols/ForeignToplevel.cpp index f7b3886f..59888ce2 100644 --- a/src/protocols/ForeignToplevel.cpp +++ b/src/protocols/ForeignToplevel.cpp @@ -1,8 +1,6 @@ #include "ForeignToplevel.hpp" #include "../Compositor.hpp" -#define LOGM PROTO::foreignToplevel->protoLog - CForeignToplevelHandle::CForeignToplevelHandle(SP resource_, PHLWINDOW pWindow_) : resource(resource_), pWindow(pWindow_) { if (!resource_->resource()) return; diff --git a/src/protocols/ForeignToplevelWlr.cpp b/src/protocols/ForeignToplevelWlr.cpp index b31a4083..bd597a91 100644 --- a/src/protocols/ForeignToplevelWlr.cpp +++ b/src/protocols/ForeignToplevelWlr.cpp @@ -4,8 +4,6 @@ #include "protocols/core/Output.hpp" #include "render/Renderer.hpp" -#define LOGM PROTO::foreignToplevelWlr->protoLog - CForeignToplevelHandleWlr::CForeignToplevelHandleWlr(SP resource_, PHLWINDOW pWindow_) : resource(resource_), pWindow(pWindow_) { if (!resource_->resource()) return; diff --git a/src/protocols/FractionalScale.cpp b/src/protocols/FractionalScale.cpp index 5bf56c5a..d39fa67c 100644 --- a/src/protocols/FractionalScale.cpp +++ b/src/protocols/FractionalScale.cpp @@ -2,8 +2,6 @@ #include #include "core/Compositor.hpp" -#define LOGM PROTO::fractional->protoLog - CFractionalScaleProtocol::CFractionalScaleProtocol(const wl_interface* iface, const int& ver, const std::string& name) : IWaylandProtocol(iface, ver, name) { ; } diff --git a/src/protocols/GammaControl.cpp b/src/protocols/GammaControl.cpp index 4febffbb..c902d00e 100644 --- a/src/protocols/GammaControl.cpp +++ b/src/protocols/GammaControl.cpp @@ -5,8 +5,6 @@ #include "../Compositor.hpp" #include "../protocols/core/Output.hpp" -#define LOGM PROTO::gamma->protoLog - CGammaControl::CGammaControl(SP resource_, wl_resource* output) : resource(resource_) { if (!resource_->resource()) return; diff --git a/src/protocols/GlobalShortcuts.cpp b/src/protocols/GlobalShortcuts.cpp index 860004c9..92bfbae4 100644 --- a/src/protocols/GlobalShortcuts.cpp +++ b/src/protocols/GlobalShortcuts.cpp @@ -1,8 +1,6 @@ #include "GlobalShortcuts.hpp" #include "../Compositor.hpp" -#define LOGM PROTO::globalShortcuts->protoLog - CShortcutClient::CShortcutClient(SP resource_) : resource(resource_) { if (!good()) return; diff --git a/src/protocols/IdleNotify.cpp b/src/protocols/IdleNotify.cpp index 2ec7d2a1..8d915ac6 100644 --- a/src/protocols/IdleNotify.cpp +++ b/src/protocols/IdleNotify.cpp @@ -1,8 +1,6 @@ #include "IdleNotify.hpp" #include "../managers/eventLoop/EventLoopManager.hpp" -#define LOGM PROTO::idle->protoLog - static int onTimer(SP self, void* data) { const auto NOTIF = (CExtIdleNotification*)data; diff --git a/src/protocols/InputMethodV2.cpp b/src/protocols/InputMethodV2.cpp index fd306f09..a0820e0b 100644 --- a/src/protocols/InputMethodV2.cpp +++ b/src/protocols/InputMethodV2.cpp @@ -6,8 +6,6 @@ #include "core/Compositor.hpp" #include -#define LOGM PROTO::ime->protoLog - CInputMethodKeyboardGrabV2::CInputMethodKeyboardGrabV2(SP resource_, SP owner_) : resource(resource_), owner(owner_) { if (!resource->resource()) return; diff --git a/src/protocols/LayerShell.cpp b/src/protocols/LayerShell.cpp index 17d3b22a..c02d23f3 100644 --- a/src/protocols/LayerShell.cpp +++ b/src/protocols/LayerShell.cpp @@ -4,8 +4,6 @@ #include "core/Compositor.hpp" #include "core/Output.hpp" -#define LOGM PROTO::layerShell->protoLog - void CLayerShellResource::SState::reset() { anchor = 0; exclusive = 0; diff --git a/src/protocols/LinuxDMABUF.cpp b/src/protocols/LinuxDMABUF.cpp index 0fbf832e..3cdb5b34 100644 --- a/src/protocols/LinuxDMABUF.cpp +++ b/src/protocols/LinuxDMABUF.cpp @@ -14,8 +14,6 @@ #include "../render/OpenGL.hpp" #include "../Compositor.hpp" -#define LOGM PROTO::linuxDma->protoLog - static std::optional devIDFromFD(int fd) { struct stat stat; if (fstat(fd, &stat) != 0) @@ -425,7 +423,7 @@ CLinuxDMABufV1Protocol::CLinuxDMABufV1Protocol(const wl_interface* iface, const auto dev = devIDFromFD(rendererFD); if (!dev.has_value()) { - protoLog(ERR, "failed to get drm dev, disabling linux dmabuf"); + LOGM(ERR, "failed to get drm dev, disabling linux dmabuf"); removeGlobal(); return; } @@ -477,7 +475,7 @@ CLinuxDMABufV1Protocol::CLinuxDMABufV1Protocol(const wl_interface* iface, const drmDevice* device = nullptr; if (drmGetDeviceFromDevId(mainDevice, 0, &device) != 0) { - protoLog(ERR, "failed to get drm dev, disabling linux dmabuf"); + LOGM(ERR, "failed to get drm dev, disabling linux dmabuf"); removeGlobal(); return; } @@ -487,12 +485,12 @@ CLinuxDMABufV1Protocol::CLinuxDMABufV1Protocol(const wl_interface* iface, const mainDeviceFD = open(name, O_RDWR | O_CLOEXEC); drmFreeDevice(&device); if (mainDeviceFD < 0) { - protoLog(ERR, "failed to open drm dev, disabling linux dmabuf"); + LOGM(ERR, "failed to open drm dev, disabling linux dmabuf"); removeGlobal(); return; } } else { - protoLog(ERR, "DRM device {} has no render node, disabling linux dmabuf", device->nodes[DRM_NODE_PRIMARY] ? device->nodes[DRM_NODE_PRIMARY] : "null"); + LOGM(ERR, "DRM device {} has no render node, disabling linux dmabuf", device->nodes[DRM_NODE_PRIMARY] ? device->nodes[DRM_NODE_PRIMARY] : "null"); drmFreeDevice(&device); removeGlobal(); } diff --git a/src/protocols/MesaDRM.cpp b/src/protocols/MesaDRM.cpp index ed412555..9fcd5f9b 100644 --- a/src/protocols/MesaDRM.cpp +++ b/src/protocols/MesaDRM.cpp @@ -4,8 +4,6 @@ #include "../Compositor.hpp" #include "types/WLBuffer.hpp" -#define LOGM PROTO::mesaDRM->protoLog - CMesaDRMBufferResource::CMesaDRMBufferResource(uint32_t id, wl_client* client, Aquamarine::SDMABUFAttrs attrs_) { LOGM(LOG, "Creating a Mesa dmabuf, with id {}: size {}, fmt {}, planes {}", id, attrs_.size, attrs_.format, attrs_.planes); for (int i = 0; i < attrs_.planes; ++i) { @@ -115,7 +113,7 @@ CMesaDRMProtocol::CMesaDRMProtocol(const wl_interface* iface, const int& ver, co drmDevice* dev = nullptr; int drmFD = g_pCompositor->m_iDRMFD; if (drmGetDevice2(drmFD, 0, &dev) != 0) { - protoLog(ERR, "Failed to get device, disabling MesaDRM"); + LOGM(ERR, "Failed to get device, disabling MesaDRM"); removeGlobal(); return; } @@ -126,13 +124,13 @@ CMesaDRMProtocol::CMesaDRMProtocol(const wl_interface* iface, const int& ver, co ASSERT(dev->available_nodes & (1 << DRM_NODE_PRIMARY)); if (!dev->nodes[DRM_NODE_PRIMARY]) { - protoLog(ERR, "No DRM render node available, both render and primary are null, disabling MesaDRM"); + LOGM(ERR, "No DRM render node available, both render and primary are null, disabling MesaDRM"); drmFreeDevice(&dev); removeGlobal(); return; } - protoLog(WARN, "No DRM render node, falling back to primary {}", dev->nodes[DRM_NODE_PRIMARY]); + LOGM(WARN, "No DRM render node, falling back to primary {}", dev->nodes[DRM_NODE_PRIMARY]); nodeName = dev->nodes[DRM_NODE_PRIMARY]; } drmFreeDevice(&dev); diff --git a/src/protocols/OutputManagement.cpp b/src/protocols/OutputManagement.cpp index 66f4c5f0..cfe388fa 100644 --- a/src/protocols/OutputManagement.cpp +++ b/src/protocols/OutputManagement.cpp @@ -4,8 +4,6 @@ using namespace Aquamarine; -#define LOGM PROTO::outputManagement->protoLog - COutputManager::COutputManager(SP resource_) : resource(resource_) { if (!good()) return; diff --git a/src/protocols/OutputPower.cpp b/src/protocols/OutputPower.cpp index 597b9871..0c324bf0 100644 --- a/src/protocols/OutputPower.cpp +++ b/src/protocols/OutputPower.cpp @@ -2,8 +2,6 @@ #include "../Compositor.hpp" #include "core/Output.hpp" -#define LOGM PROTO::outputPower->protoLog - COutputPower::COutputPower(SP resource_, CMonitor* pMonitor_) : resource(resource_), pMonitor(pMonitor_) { if (!resource->resource()) return; diff --git a/src/protocols/PointerConstraints.cpp b/src/protocols/PointerConstraints.cpp index fd15242d..0f2dd991 100644 --- a/src/protocols/PointerConstraints.cpp +++ b/src/protocols/PointerConstraints.cpp @@ -5,8 +5,6 @@ #include "../managers/SeatManager.hpp" #include "core/Compositor.hpp" -#define LOGM PROTO::constraints->protoLog - CPointerConstraint::CPointerConstraint(SP resource_, SP surf, wl_resource* region_, zwpPointerConstraintsV1Lifetime lifetime_) : resourceL(resource_), locked(true), lifetime(lifetime_) { if (!resource_->resource()) diff --git a/src/protocols/PointerGestures.cpp b/src/protocols/PointerGestures.cpp index 86510779..c83e3887 100644 --- a/src/protocols/PointerGestures.cpp +++ b/src/protocols/PointerGestures.cpp @@ -4,8 +4,6 @@ #include "core/Seat.hpp" #include "core/Compositor.hpp" -#define LOGM PROTO::pointerGestures->protoLog - CPointerGestureSwipe::CPointerGestureSwipe(SP resource_) : resource(resource_) { if (!resource->resource()) return; diff --git a/src/protocols/PresentationTime.cpp b/src/protocols/PresentationTime.cpp index a2fc270c..335cf557 100644 --- a/src/protocols/PresentationTime.cpp +++ b/src/protocols/PresentationTime.cpp @@ -6,8 +6,6 @@ #include "core/Output.hpp" #include -#define LOGM PROTO::presentation->protoLog - CQueuedPresentationData::CQueuedPresentationData(SP surf) : surface(surf) { ; } diff --git a/src/protocols/PrimarySelection.cpp b/src/protocols/PrimarySelection.cpp index 78eb8d63..4fede706 100644 --- a/src/protocols/PrimarySelection.cpp +++ b/src/protocols/PrimarySelection.cpp @@ -4,8 +4,6 @@ #include "core/Seat.hpp" #include "../config/ConfigValue.hpp" -#define LOGM PROTO::primarySelection->protoLog - CPrimarySelectionOffer::CPrimarySelectionOffer(SP resource_, SP source_) : source(source_), resource(resource_) { if (!good()) return; diff --git a/src/protocols/Screencopy.cpp b/src/protocols/Screencopy.cpp index a8afba84..f246f6dd 100644 --- a/src/protocols/Screencopy.cpp +++ b/src/protocols/Screencopy.cpp @@ -9,8 +9,6 @@ #include -#define LOGM PROTO::screencopy->protoLog - CScreencopyFrame::~CScreencopyFrame() { if (buffer && buffer->locked()) buffer->unlock(); diff --git a/src/protocols/ServerDecorationKDE.cpp b/src/protocols/ServerDecorationKDE.cpp index 42da52a9..c7b98a9c 100644 --- a/src/protocols/ServerDecorationKDE.cpp +++ b/src/protocols/ServerDecorationKDE.cpp @@ -1,8 +1,6 @@ #include "ServerDecorationKDE.hpp" #include "core/Compositor.hpp" -#define LOGM PROTO::serverDecorationKDE->protoLog - CServerDecorationKDE::CServerDecorationKDE(SP resource_, SP surf) : resource(resource_) { if (!good()) return; diff --git a/src/protocols/SessionLock.cpp b/src/protocols/SessionLock.cpp index df97413c..7b0d8b3b 100644 --- a/src/protocols/SessionLock.cpp +++ b/src/protocols/SessionLock.cpp @@ -5,8 +5,6 @@ #include "core/Compositor.hpp" #include "core/Output.hpp" -#define LOGM PROTO::sessionLock->protoLog - CSessionLockSurface::CSessionLockSurface(SP resource_, SP surface_, CMonitor* pMonitor_, WP owner_) : resource(resource_), sessionLock(owner_), pSurface(surface_), pMonitor(pMonitor_) { if (!resource->resource()) diff --git a/src/protocols/ShortcutsInhibit.cpp b/src/protocols/ShortcutsInhibit.cpp index 1a0433e6..e4424ed7 100644 --- a/src/protocols/ShortcutsInhibit.cpp +++ b/src/protocols/ShortcutsInhibit.cpp @@ -3,8 +3,6 @@ #include "../Compositor.hpp" #include "core/Compositor.hpp" -#define LOGM PROTO::shortcutsInhibit->protoLog - CKeyboardShortcutsInhibitor::CKeyboardShortcutsInhibitor(SP resource_, SP surf) : resource(resource_), pSurface(surf) { if (!resource->resource()) return; diff --git a/src/protocols/Tablet.cpp b/src/protocols/Tablet.cpp index 72c7cfde..b974152e 100644 --- a/src/protocols/Tablet.cpp +++ b/src/protocols/Tablet.cpp @@ -7,8 +7,6 @@ #include #include -#define LOGM PROTO::tablet->protoLog - CTabletPadStripV2Resource::CTabletPadStripV2Resource(SP resource_, uint32_t id_) : id(id_), resource(resource_) { if (!good()) return; diff --git a/src/protocols/TextInputV1.cpp b/src/protocols/TextInputV1.cpp index 78e910cb..f25f5aca 100644 --- a/src/protocols/TextInputV1.cpp +++ b/src/protocols/TextInputV1.cpp @@ -3,8 +3,6 @@ #include "../Compositor.hpp" #include "core/Compositor.hpp" -#define LOGM PROTO::textInputV1->protoLog - CTextInputV1::~CTextInputV1() { events.destroy.emit(); } diff --git a/src/protocols/TextInputV3.cpp b/src/protocols/TextInputV3.cpp index 1302a57f..99d799f3 100644 --- a/src/protocols/TextInputV3.cpp +++ b/src/protocols/TextInputV3.cpp @@ -2,8 +2,6 @@ #include #include "core/Compositor.hpp" -#define LOGM PROTO::textInputV3->protoLog - void CTextInputV3::SState::reset() { cause = ZWP_TEXT_INPUT_V3_CHANGE_CAUSE_INPUT_METHOD; surrounding.updated = false; diff --git a/src/protocols/ToplevelExport.cpp b/src/protocols/ToplevelExport.cpp index fb3fde2b..05e991d6 100644 --- a/src/protocols/ToplevelExport.cpp +++ b/src/protocols/ToplevelExport.cpp @@ -8,8 +8,6 @@ #include -#define LOGM PROTO::toplevelExport->protoLog - CToplevelExportClient::CToplevelExportClient(SP resource_) : resource(resource_) { if (!good()) return; diff --git a/src/protocols/Viewporter.cpp b/src/protocols/Viewporter.cpp index 78f3039f..58cb851d 100644 --- a/src/protocols/Viewporter.cpp +++ b/src/protocols/Viewporter.cpp @@ -2,8 +2,6 @@ #include "core/Compositor.hpp" #include -#define LOGM PROTO::viewport->protoLog - CViewportResource::CViewportResource(SP resource_, SP surface_) : surface(surface_), resource(resource_) { if (!good()) return; diff --git a/src/protocols/VirtualKeyboard.cpp b/src/protocols/VirtualKeyboard.cpp index 2642ec11..27a4f248 100644 --- a/src/protocols/VirtualKeyboard.cpp +++ b/src/protocols/VirtualKeyboard.cpp @@ -2,8 +2,6 @@ #include #include "../devices/IKeyboard.hpp" -#define LOGM PROTO::virtualKeyboard->protoLog - CVirtualKeyboardV1Resource::CVirtualKeyboardV1Resource(SP resource_) : resource(resource_) { if (!good()) return; diff --git a/src/protocols/VirtualPointer.cpp b/src/protocols/VirtualPointer.cpp index 8626241a..eb92a640 100644 --- a/src/protocols/VirtualPointer.cpp +++ b/src/protocols/VirtualPointer.cpp @@ -1,8 +1,6 @@ #include "VirtualPointer.hpp" #include "core/Output.hpp" -#define LOGM PROTO::virtualPointer->protoLog - CVirtualPointerV1Resource::CVirtualPointerV1Resource(SP resource_, WP boundOutput_) : boundOutput(boundOutput_), resource(resource_) { if (!good()) return; diff --git a/src/protocols/WaylandProtocol.cpp b/src/protocols/WaylandProtocol.cpp index 954f160d..0782d323 100644 --- a/src/protocols/WaylandProtocol.cpp +++ b/src/protocols/WaylandProtocol.cpp @@ -21,7 +21,7 @@ IWaylandProtocol::IWaylandProtocol(const wl_interface* iface, const int& ver, co m_pGlobal = wl_global_create(g_pCompositor->m_sWLDisplay, iface, ver, this, &bindManagerInternal); if (!m_pGlobal) { - protoLog(ERR, "could not create a global"); + LOGM(ERR, "could not create a global [{}]", m_szName); return; } @@ -30,7 +30,7 @@ IWaylandProtocol::IWaylandProtocol(const wl_interface* iface, const int& ver, co m_liDisplayDestroy.parent = this; wl_display_add_destroy_listener(g_pCompositor->m_sWLDisplay, &m_liDisplayDestroy.listener); - protoLog(LOG, "Registered global"); + LOGM(LOG, "Registered global [{}]", m_szName); } IWaylandProtocol::~IWaylandProtocol() { diff --git a/src/protocols/WaylandProtocol.hpp b/src/protocols/WaylandProtocol.hpp index 4d4e7925..0fa8daab 100644 --- a/src/protocols/WaylandProtocol.hpp +++ b/src/protocols/WaylandProtocol.hpp @@ -11,6 +11,35 @@ #define PROTO NProtocols +#define EXTRACT_CLASS_NAME() \ + []() constexpr -> std::string_view { \ + constexpr std::string_view prettyFunction = __PRETTY_FUNCTION__; \ + constexpr size_t colons = prettyFunction.find("::"); \ + if (colons != std::string_view::npos) { \ + constexpr size_t begin = prettyFunction.substr(0, colons).rfind(' ') + 1; \ + constexpr size_t end = colons - begin; \ + return prettyFunction.substr(begin, end); \ + } else { \ + return "Global"; \ + } \ + }() + +#define LOGM(level, ...) \ + do { \ + std::ostringstream oss; \ + if (level == WARN || level == ERR || level == CRIT) { \ + oss << "[" << __FILE__ << ":" << __LINE__ << "] "; \ + } else if (level == LOG || level == INFO || level == TRACE) { \ + oss << "[" << EXTRACT_CLASS_NAME() << "] "; \ + } \ + if constexpr (std::is_same_v) { \ + oss << __VA_ARGS__; \ + Debug::log(level, oss.str()); \ + } else { \ + Debug::log(level, std::format("{}{}", oss.str(), std::format(__VA_ARGS__))); \ + } \ + } while (0) + class IWaylandProtocol; struct IWaylandProtocolDestroyWrapper { wl_listener listener; @@ -22,15 +51,10 @@ class IWaylandProtocol { IWaylandProtocol(const wl_interface* iface, const int& ver, const std::string& name); virtual ~IWaylandProtocol(); - virtual void onDisplayDestroy(); - virtual void removeGlobal(); + virtual void onDisplayDestroy(); + virtual void removeGlobal(); - virtual void bindManager(wl_client* client, void* data, uint32_t ver, uint32_t id) = 0; - - template - void protoLog(LogLevel level, std::format_string fmt, Args&&... args) { - Debug::log(level, std::format("[{}] ", m_szName) + std::vformat(fmt.get(), std::make_format_args(args...))); - }; + virtual void bindManager(wl_client* client, void* data, uint32_t ver, uint32_t id) = 0; IWaylandProtocolDestroyWrapper m_liDisplayDestroy; diff --git a/src/protocols/XDGActivation.cpp b/src/protocols/XDGActivation.cpp index 40f33f02..4a6c7bfe 100644 --- a/src/protocols/XDGActivation.cpp +++ b/src/protocols/XDGActivation.cpp @@ -4,8 +4,6 @@ #include "core/Compositor.hpp" #include -#define LOGM PROTO::activation->protoLog - CXDGActivationToken::CXDGActivationToken(SP resource_) : resource(resource_) { if (!resource_->resource()) return; diff --git a/src/protocols/XDGDecoration.cpp b/src/protocols/XDGDecoration.cpp index 021a1141..07b1694c 100644 --- a/src/protocols/XDGDecoration.cpp +++ b/src/protocols/XDGDecoration.cpp @@ -1,8 +1,6 @@ #include "XDGDecoration.hpp" #include -#define LOGM PROTO::xdgDecoration->protoLog - CXDGDecoration::CXDGDecoration(SP resource_, wl_resource* toplevel) : resource(resource_), pToplevelResource(toplevel) { if (!resource->resource()) return; diff --git a/src/protocols/XDGOutput.cpp b/src/protocols/XDGOutput.cpp index 073aa502..9c2c353c 100644 --- a/src/protocols/XDGOutput.cpp +++ b/src/protocols/XDGOutput.cpp @@ -12,8 +12,6 @@ // -#define LOGM PROTO::xdgOutput->protoLog - void CXDGOutputProtocol::onManagerResourceDestroy(wl_resource* res) { std::erase_if(m_vManagerResources, [&](const auto& other) { return other->resource() == res; }); } diff --git a/src/protocols/XDGShell.cpp b/src/protocols/XDGShell.cpp index aea23329..eaf5c333 100644 --- a/src/protocols/XDGShell.cpp +++ b/src/protocols/XDGShell.cpp @@ -6,8 +6,6 @@ #include "core/Compositor.hpp" #include -#define LOGM PROTO::xdgShell->protoLog - void SXDGPositionerState::setAnchor(xdgPositionerAnchor edges) { anchor.setTop(edges == XDG_POSITIONER_ANCHOR_TOP || edges == XDG_POSITIONER_ANCHOR_TOP_LEFT || edges == XDG_POSITIONER_ANCHOR_TOP_RIGHT); anchor.setLeft(edges == XDG_POSITIONER_ANCHOR_LEFT || edges == XDG_POSITIONER_ANCHOR_TOP_LEFT || edges == XDG_POSITIONER_ANCHOR_BOTTOM_LEFT); diff --git a/src/protocols/XWaylandShell.cpp b/src/protocols/XWaylandShell.cpp index 6cc5256f..d6c3b1a8 100644 --- a/src/protocols/XWaylandShell.cpp +++ b/src/protocols/XWaylandShell.cpp @@ -2,8 +2,6 @@ #include "core/Compositor.hpp" #include -#define LOGM PROTO::xwaylandShell->protoLog - CXWaylandSurfaceResource::CXWaylandSurfaceResource(SP resource_, SP surface_) : surface(surface_), resource(resource_) { if (!good()) return; diff --git a/src/protocols/core/Compositor.cpp b/src/protocols/core/Compositor.cpp index a767dd52..8b6f46b1 100644 --- a/src/protocols/core/Compositor.cpp +++ b/src/protocols/core/Compositor.cpp @@ -13,8 +13,6 @@ #include "../../render/Renderer.hpp" #include -#define LOGM PROTO::compositor->protoLog - class CDefaultSurfaceRole : public ISurfaceRole { public: virtual eSurfaceRole role() { diff --git a/src/protocols/core/DataDevice.cpp b/src/protocols/core/DataDevice.cpp index fe3905d0..4ed28f24 100644 --- a/src/protocols/core/DataDevice.cpp +++ b/src/protocols/core/DataDevice.cpp @@ -6,8 +6,6 @@ #include "Seat.hpp" #include "Compositor.hpp" -#define LOGM PROTO::data->protoLog - CWLDataOfferResource::CWLDataOfferResource(SP resource_, SP source_) : source(source_), resource(resource_) { if (!good()) return; diff --git a/src/protocols/core/Seat.cpp b/src/protocols/core/Seat.cpp index bb6a9d4d..a111c12c 100644 --- a/src/protocols/core/Seat.cpp +++ b/src/protocols/core/Seat.cpp @@ -9,8 +9,6 @@ #include -#define LOGM PROTO::seat->protoLog - CWLTouchResource::CWLTouchResource(SP resource_, SP owner_) : owner(owner_), resource(resource_) { if (!good()) return; diff --git a/src/protocols/core/Shm.cpp b/src/protocols/core/Shm.cpp index 75c2134a..99459d9a 100644 --- a/src/protocols/core/Shm.cpp +++ b/src/protocols/core/Shm.cpp @@ -7,8 +7,6 @@ #include "../../Compositor.hpp" #include "../../helpers/Format.hpp" -#define LOGM PROTO::shm->protoLog - CWLSHMBuffer::CWLSHMBuffer(SP pool_, uint32_t id, int32_t offset_, const Vector2D& size_, int32_t stride_, uint32_t fmt_) { if (!pool_->pool->data) return; diff --git a/src/protocols/core/Subcompositor.cpp b/src/protocols/core/Subcompositor.cpp index 2a7c06dc..e0679eff 100644 --- a/src/protocols/core/Subcompositor.cpp +++ b/src/protocols/core/Subcompositor.cpp @@ -2,8 +2,6 @@ #include "Compositor.hpp" #include -#define LOGM PROTO::subcompositor->protoLog - CWLSubsurfaceResource::CWLSubsurfaceResource(SP resource_, SP surface_, SP parent_) : surface(surface_), parent(parent_), resource(resource_) { if (!good()) From 682b30fba89c043e86d9c96bdb8df133c1683054 Mon Sep 17 00:00:00 2001 From: Vladimir-csp <4061903+Vladimir-csp@users.noreply.github.com> Date: Fri, 16 Aug 2024 10:19:08 +0300 Subject: [PATCH 0278/2181] env: Add HYPRLAND_NO_SD_VARS env condition (#7358) * Add HYPRLAND_NO_SD_VARS env condition wip #7083 * Formatting shuffle * Formatting --- src/Compositor.cpp | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/src/Compositor.cpp b/src/Compositor.cpp index 4024fadf..9d247a56 100644 --- a/src/Compositor.cpp +++ b/src/Compositor.cpp @@ -429,7 +429,7 @@ void CCompositor::cleanEnvironment() { if (m_bDesktopEnvSet) unsetenv("XDG_CURRENT_DESKTOP"); - if (m_pAqBackend->hasSession()) { + if (m_pAqBackend->hasSession() && !envEnabled("HYPRLAND_NO_SD_VARS")) { const auto CMD = #ifdef USES_SYSTEMD "systemctl --user unset-environment DISPLAY WAYLAND_DISPLAY HYPRLAND_INSTANCE_SIGNATURE XDG_CURRENT_DESKTOP QT_QPA_PLATFORMTHEME PATH XDG_DATA_DIRS && hash " @@ -659,7 +659,11 @@ void CCompositor::prepareFallbackOutput() { void CCompositor::startCompositor() { signal(SIGPIPE, SIG_IGN); - if (m_pAqBackend->hasSession() /* Session-less Hyprland usually means a nest, don't update the env in that case */) { + if ( + /* Session-less Hyprland usually means a nest, don't update the env in that case */ + m_pAqBackend->hasSession() && + /* Activation environment management is not disabled */ + !envEnabled("HYPRLAND_NO_SD_VARS")) { const auto CMD = #ifdef USES_SYSTEMD "systemctl --user import-environment DISPLAY WAYLAND_DISPLAY HYPRLAND_INSTANCE_SIGNATURE XDG_CURRENT_DESKTOP QT_QPA_PLATFORMTHEME PATH XDG_DATA_DIRS && hash " From 1840a907a8c6b1f59cfa6738a8f46b320e8df8b1 Mon Sep 17 00:00:00 2001 From: Tom Englund Date: Fri, 16 Aug 2024 11:09:01 +0200 Subject: [PATCH 0279/2181] renderbuffer: ensure framebuffer gets deleted (#7363) after commit 4b4971c it uses m_iFbAllocated and deletes if upon calling release() but Renderbuffer generates directly on m_iFb without calling alloc() meaning it wont be deleted on release(), set m_iFbAllocated to true after generating the buffer. --- src/render/Renderbuffer.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/render/Renderbuffer.cpp b/src/render/Renderbuffer.cpp index 58ed88d6..c4425ce9 100644 --- a/src/render/Renderbuffer.cpp +++ b/src/render/Renderbuffer.cpp @@ -35,7 +35,8 @@ CRenderbuffer::CRenderbuffer(SP buffer, uint32_t format) : glBindRenderbuffer(GL_RENDERBUFFER, 0); glGenFramebuffers(1, &m_sFramebuffer.m_iFb); - m_sFramebuffer.m_vSize = buffer->size; + m_sFramebuffer.m_iFbAllocated = true; + m_sFramebuffer.m_vSize = buffer->size; m_sFramebuffer.bind(); glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, m_iRBO); From c5feee1e357f3c3c59ebe406630601c627807963 Mon Sep 17 00:00:00 2001 From: Tom Englund Date: Fri, 16 Aug 2024 18:00:59 +0200 Subject: [PATCH 0280/2181] xcursormgr: dont apply scale on gsettings (#7316) gtk scales the cursor size itself since its CSD so if we scale the size its gonna get double scaled. incorporate the scale into xcursormanager to keep track of it. --- src/managers/CursorManager.cpp | 10 +++++----- src/managers/XCursorManager.cpp | 18 ++++++++++-------- src/managers/XCursorManager.hpp | 9 +++++---- 3 files changed, 20 insertions(+), 17 deletions(-) diff --git a/src/managers/CursorManager.cpp b/src/managers/CursorManager.cpp index e2dd5bb3..1c047f85 100644 --- a/src/managers/CursorManager.cpp +++ b/src/managers/CursorManager.cpp @@ -102,7 +102,7 @@ CCursorManager::CCursorManager() { // since we fallback to xcursor always load it on startup. otherwise we end up with a empty theme if hyprcursor is enabled in the config // and then later is disabled. - m_pXcursor->loadTheme(getenv("XCURSOR_THEME") ? getenv("XCURSOR_THEME") : "default", m_iSize * std::ceil(m_fCursorScale)); + m_pXcursor->loadTheme(getenv("XCURSOR_THEME") ? getenv("XCURSOR_THEME") : "default", m_iSize, m_fCursorScale); m_pAnimationTimer = makeShared(std::nullopt, cursorAnimTimer, this); g_pEventLoopManager->addTimer(m_pAnimationTimer); @@ -163,7 +163,7 @@ void CCursorManager::setCursorFromName(const std::string& name) { auto setXCursor = [this](auto const& name) { float scale = std::ceil(m_fCursorScale); - auto xcursor = m_pXcursor->getShape(name, m_iSize * scale); + auto xcursor = m_pXcursor->getShape(name, m_iSize, m_fCursorScale); auto& icon = xcursor->images.front(); auto buf = makeShared((uint8_t*)icon.pixels.data(), icon.size, icon.hotspot); setCursorBuffer(buf, icon.hotspot / scale, scale); @@ -277,7 +277,7 @@ void CCursorManager::setXWaylandCursor() { g_pXWayland->setCursor(cairo_image_surface_get_data(CURSOR.surface), cairo_image_surface_get_stride(CURSOR.surface), {CURSOR.size, CURSOR.size}, {CURSOR.hotspotX, CURSOR.hotspotY}); else { - auto xcursor = m_pXcursor->getShape("left_ptr", m_iSize * std::ceil(m_fCursorScale)); + auto xcursor = m_pXcursor->getShape("left_ptr", m_iSize, 1); auto& icon = xcursor->images.front(); g_pXWayland->setCursor((uint8_t*)icon.pixels.data(), icon.size.x * 4, icon.size, icon.hotspot); @@ -329,10 +329,10 @@ bool CCursorManager::changeTheme(const std::string& name, const int size) { m_pHyprcursor = std::make_unique(m_szTheme.empty() ? nullptr : m_szTheme.c_str(), options); if (!m_pHyprcursor->valid()) { Debug::log(ERR, "Hyprcursor failed loading theme \"{}\", falling back to XCursor.", m_szTheme); - m_pXcursor->loadTheme(m_szTheme.empty() ? xcursor_theme : m_szTheme, m_iSize); + m_pXcursor->loadTheme(m_szTheme.empty() ? xcursor_theme : m_szTheme, m_iSize, m_fCursorScale); } } else - m_pXcursor->loadTheme(m_szTheme.empty() ? xcursor_theme : m_szTheme, m_iSize); + m_pXcursor->loadTheme(m_szTheme.empty() ? xcursor_theme : m_szTheme, m_iSize, m_fCursorScale); updateTheme(); diff --git a/src/managers/XCursorManager.cpp b/src/managers/XCursorManager.cpp index 0921bcd4..6f000f9f 100644 --- a/src/managers/XCursorManager.cpp +++ b/src/managers/XCursorManager.cpp @@ -100,12 +100,13 @@ CXCursorManager::CXCursorManager() { defaultCursor = hyprCursor; } -void CXCursorManager::loadTheme(std::string const& name, int size) { - if (lastLoadSize == size && themeName == name) +void CXCursorManager::loadTheme(std::string const& name, int size, float scale) { + if (lastLoadSize == (size * std::ceil(scale)) && themeName == name && lastLoadScale == scale) return; - lastLoadSize = size; - themeName = name.empty() ? "default" : name; + lastLoadSize = size * std::ceil(scale); + lastLoadScale = scale; + themeName = name.empty() ? "default" : name; defaultCursor.reset(); cursors.clear(); @@ -156,10 +157,10 @@ void CXCursorManager::loadTheme(std::string const& name, int size) { syncGsettings(); } -SP CXCursorManager::getShape(std::string const& shape, int size) { +SP CXCursorManager::getShape(std::string const& shape, int size, float scale) { // monitor scaling changed etc, so reload theme with new size. - if (size != lastLoadSize) - loadTheme(themeName, size); + if ((size * std::ceil(scale)) != lastLoadSize || scale != lastLoadScale) + loadTheme(themeName, size, scale); // try to get an icon we know if we have one for (auto const& c : cursors) { @@ -602,6 +603,7 @@ void CXCursorManager::syncGsettings() { g_object_unref(gsettings); }; + int unscaledSize = lastLoadSize / std::ceil(lastLoadScale); setValue("cursor-theme", themeName, "org.gnome.desktop.interface"); - setValue("cursor-size", lastLoadSize, "org.gnome.desktop.interface"); + setValue("cursor-size", unscaledSize, "org.gnome.desktop.interface"); } diff --git a/src/managers/XCursorManager.hpp b/src/managers/XCursorManager.hpp index 48fda5dd..1f3c24db 100644 --- a/src/managers/XCursorManager.hpp +++ b/src/managers/XCursorManager.hpp @@ -29,8 +29,8 @@ class CXCursorManager { CXCursorManager(); ~CXCursorManager() = default; - void loadTheme(const std::string& name, int size); - SP getShape(std::string const& shape, int size); + void loadTheme(const std::string& name, int size, float scale); + SP getShape(std::string const& shape, int size, float scale); void syncGsettings(); private: @@ -40,8 +40,9 @@ class CXCursorManager { std::vector> loadStandardCursors(std::string const& name, int size); std::vector> loadAllFromDir(std::string const& path, int size); - int lastLoadSize = 0; - std::string themeName = ""; + int lastLoadSize = 0; + float lastLoadScale = 0; + std::string themeName = ""; SP defaultCursor; SP hyprCursor; std::vector> cursors; From 92744b5b9aa386257bf243c957ab64f7f4171a19 Mon Sep 17 00:00:00 2001 From: Vaxry <43317083+vaxerski@users.noreply.github.com> Date: Sat, 17 Aug 2024 17:33:16 +0100 Subject: [PATCH 0281/2181] IPC: Add config descriptions (#7377) Thanks @gulafaran for the work --- Co-authored-by: @gulafaran --- src/config/ConfigDescriptions.hpp | 1344 +++++++++++++++++++++++++++ src/config/ConfigManager.cpp | 63 +- src/config/ConfigManager.hpp | 66 ++ src/debug/HyprCtl.cpp | 16 + src/helpers/Color.cpp | 2 +- src/helpers/Color.hpp | 2 +- src/managers/input/InputManager.cpp | 11 +- 7 files changed, 1491 insertions(+), 13 deletions(-) create mode 100644 src/config/ConfigDescriptions.hpp diff --git a/src/config/ConfigDescriptions.hpp b/src/config/ConfigDescriptions.hpp new file mode 100644 index 00000000..3c830132 --- /dev/null +++ b/src/config/ConfigDescriptions.hpp @@ -0,0 +1,1344 @@ +#pragma once + +#include "ConfigManager.hpp" + +inline static const std::vector CONFIG_OPTIONS = { + + /* + * general: + */ + + SConfigOptionDescription{ + .value = "general:border_size", + .description = "size of the border around windows", + .type = CONFIG_OPTION_INT, + .data = SConfigOptionDescription::SRangeData{1, 0, 20}, + }, + SConfigOptionDescription{ + .value = "general:no_border_on_floating", + .description = "disable borders for floating windows", + .type = CONFIG_OPTION_BOOL, + .data = SConfigOptionDescription::SBoolData{false}, + }, + SConfigOptionDescription{ + .value = "general:gaps_in", + .description = "gaps between windows\n\nsupports css style gaps (top, right, bottom, left -> 5 10 15 20)", + .type = CONFIG_OPTION_STRING_SHORT, + .data = SConfigOptionDescription::SStringData{"5"}, + }, + SConfigOptionDescription{ + .value = "general:gaps_out", + .description = "gaps between windows and monitor edges\n\nsupports css style gaps (top, right, bottom, left -> 5 10 15 20)", + .type = CONFIG_OPTION_STRING_SHORT, + .data = SConfigOptionDescription::SStringData{"20"}, + }, + SConfigOptionDescription{ + .value = "general:gaps_workspaces", + .description = "gaps between workspaces. Stacks with gaps_out.", + .type = CONFIG_OPTION_INT, + .data = SConfigOptionDescription::SRangeData{0, 0, 100}, + }, + SConfigOptionDescription{ + .value = "general:col.inactive_border", + .description = "border color for inactive windows", + .type = CONFIG_OPTION_GRADIENT, + .data = SConfigOptionDescription::SGradientData{"0xff444444"}, + }, + SConfigOptionDescription{ + .value = "general:col.active_border", + .description = "border color for the active window", + .type = CONFIG_OPTION_GRADIENT, + .data = SConfigOptionDescription::SGradientData{"0xffffffff"}, + }, + SConfigOptionDescription{ + .value = "general:col.nogroup_border", + .description = "inactive border color for window that cannot be added to a group (see denywindowfromgroup dispatcher)", + .type = CONFIG_OPTION_GRADIENT, + .data = SConfigOptionDescription::SGradientData{"0xffffaaff"}, + }, + SConfigOptionDescription{ + .value = "general:col.nogroup_border_active", + .description = "active border color for window that cannot be added to a group", + .type = CONFIG_OPTION_GRADIENT, + .data = SConfigOptionDescription::SGradientData{"0xffff00ff"}, + }, + SConfigOptionDescription{ + .value = "general:layout", + .description = "which layout to use. [dwindle/master]", + .type = CONFIG_OPTION_STRING_SHORT, + .data = SConfigOptionDescription::SStringData{"dwindle"}, + }, + SConfigOptionDescription{ + .value = "general:no_focus_fallback", + .description = "if true, will not fall back to the next available window when moving focus in a direction where no window was found", + .type = CONFIG_OPTION_BOOL, + .data = SConfigOptionDescription::SBoolData{false}, + }, + SConfigOptionDescription{ + .value = "general:resize_on_border", + .description = "enables resizing windows by clicking and dragging on borders and gaps", + .type = CONFIG_OPTION_BOOL, + .data = SConfigOptionDescription::SBoolData{false}, + }, + SConfigOptionDescription{ + .value = "general:extend_border_grab_area", + .description = "extends the area around the border where you can click and drag on, only used when general:resize_on_border is on.", + .type = CONFIG_OPTION_INT, + .data = SConfigOptionDescription::SRangeData{15, 0, 100}, + }, + SConfigOptionDescription{ + .value = "general:hover_icon_on_border", + .description = "show a cursor icon when hovering over borders, only used when general:resize_on_border is on.", + .type = CONFIG_OPTION_BOOL, + .data = SConfigOptionDescription::SBoolData{true}, + }, + SConfigOptionDescription{ + .value = "general:allow_tearing", + .description = "master switch for allowing tearing to occur. See the Tearing page.", + .type = CONFIG_OPTION_BOOL, + .data = SConfigOptionDescription::SBoolData{false}, + }, + SConfigOptionDescription{ + .value = "general:resize_corner", + .description = "force floating windows to use a specific corner when being resized (1-4 going clockwise from top left, 0 to disable)", + .type = CONFIG_OPTION_INT, + .data = SConfigOptionDescription::SRangeData{0, 0, 4}, + }, + + /* + * decoration: + */ + + SConfigOptionDescription{ + .value = "decoration:rounding", + .description = "rounded corners' radius (in layout px)", + .type = CONFIG_OPTION_INT, + .data = SConfigOptionDescription::SRangeData{0, 0, 20}, + }, + SConfigOptionDescription{ + .value = "decoration:active_opacity", + .description = "opacity of active windows. [0.0 - 1.0]", + .type = CONFIG_OPTION_FLOAT, + .data = SConfigOptionDescription::SFloatData{1, 0, 1}, + }, + SConfigOptionDescription{ + .value = "decoration:inactive_opacity", + .description = "opacity of inactive windows. [0.0 - 1.0]", + .type = CONFIG_OPTION_FLOAT, + .data = SConfigOptionDescription::SFloatData{1, 0, 1}, + }, + SConfigOptionDescription{ + .value = "decoration:fullscreen_opacity", + .description = "opacity of fullscreen windows. [0.0 - 1.0]", + .type = CONFIG_OPTION_FLOAT, + .data = SConfigOptionDescription::SFloatData{1, 0, 1}, + }, + SConfigOptionDescription{ + .value = "decoration:drop_shadow", + .description = "enable drop shadows on windows", + .type = CONFIG_OPTION_BOOL, + .data = SConfigOptionDescription::SBoolData{true}, + }, + SConfigOptionDescription{ + .value = "decoration:shadow_range", + .description = "Shadow range (size) in layout px", + .type = CONFIG_OPTION_INT, + .data = SConfigOptionDescription::SRangeData{4, 0, 100}, + }, + SConfigOptionDescription{ + .value = "decoration:shadow_render_power", + .description = "in what power to render the falloff (more power, the faster the falloff) [1 - 4]", + .type = CONFIG_OPTION_INT, + .data = SConfigOptionDescription::SRangeData{3, 1, 4}, + }, + SConfigOptionDescription{ + .value = "decoration:shadow_ignore_window", + .description = "if true, the shadow will not be rendered behind the window itself, only around it.", + .type = CONFIG_OPTION_BOOL, + .data = SConfigOptionDescription::SBoolData{true}, + }, + SConfigOptionDescription{ + .value = "decoration:col.shadow", + .description = "shadow's color. Alpha dictates shadow's opacity.", + .type = CONFIG_OPTION_COLOR, + .data = SConfigOptionDescription::SColorData{0xee1a1a1a}, + }, + SConfigOptionDescription{ + .value = "decoration:col.shadow_inactive", + .description = "inactive shadow color. (if not set, will fall back to col.shadow)", + .type = CONFIG_OPTION_COLOR, + .data = SConfigOptionDescription::SColorData{}, //##TODO UNSET? + }, + SConfigOptionDescription{ + .value = "decoration:shadow_offset", + .description = "shadow's rendering offset.", + .type = CONFIG_OPTION_VECTOR, + .data = SConfigOptionDescription::SVectorData{{}, {-250, -250}, {250, 250}}, + }, + SConfigOptionDescription{ + .value = "decoration:shadow_scale", + .description = "shadow's scale. [0.0 - 1.0]", + .type = CONFIG_OPTION_FLOAT, + .data = SConfigOptionDescription::SFloatData{1, 0, 1}, + }, + SConfigOptionDescription{ + .value = "decoration:dim_inactive", + .description = "enables dimming of inactive windows", + .type = CONFIG_OPTION_BOOL, + .data = SConfigOptionDescription::SBoolData{false}, + }, + SConfigOptionDescription{ + .value = "decoration:dim_strength", + .description = "how much inactive windows should be dimmed [0.0 - 1.0]", + .type = CONFIG_OPTION_FLOAT, + .data = SConfigOptionDescription::SFloatData{0.5, 0, 1}, + }, + SConfigOptionDescription{ + .value = "decoration:dim_special", + .description = "how much to dim the rest of the screen by when a special workspace is open. [0.0 - 1.0]", + .type = CONFIG_OPTION_FLOAT, + .data = SConfigOptionDescription::SFloatData{0.2, 0, 1}, + }, + SConfigOptionDescription{ + .value = "decoration:dim_around", + .description = "how much the dimaround window rule should dim by. [0.0 - 1.0]", + .type = CONFIG_OPTION_FLOAT, + .data = SConfigOptionDescription::SFloatData{0.4, 0, 1}, + }, + SConfigOptionDescription{ + .value = "decoration:screen_shader", + .description = "screen_shader a path to a custom shader to be applied at the end of rendering. See examples/screenShader.frag for an example.", + .type = CONFIG_OPTION_STRING_LONG, + .data = SConfigOptionDescription::SStringData{""}, //##TODO UNSET? + }, + + /* + * blur: + */ + + SConfigOptionDescription{ + .value = "blur:enabled", + .description = "enable kawase window background blur", + .type = CONFIG_OPTION_BOOL, + .data = SConfigOptionDescription::SBoolData{true}, + }, + SConfigOptionDescription{ + .value = "blur:size", + .description = "blur size (distance)", + .type = CONFIG_OPTION_INT, + .data = SConfigOptionDescription::SRangeData{8, 0, 100}, + }, + SConfigOptionDescription{ + .value = "blur:passes", + .description = "the amount of passes to perform", + .type = CONFIG_OPTION_INT, + .data = SConfigOptionDescription::SRangeData{1, 0, 10}, + }, + SConfigOptionDescription{ + .value = "blur:ignore_opacity", + .description = "make the blur layer ignore the opacity of the window", + .type = CONFIG_OPTION_BOOL, + .data = SConfigOptionDescription::SBoolData{false}, + }, + SConfigOptionDescription{ + .value = "blur:new_optimizations", + .description = "whether to enable further optimizations to the blur. Recommended to leave on, as it will massively improve performance.", + .type = CONFIG_OPTION_BOOL, + .data = SConfigOptionDescription::SBoolData{true}, + }, + SConfigOptionDescription{ + .value = "blur:xray", + .description = "if enabled, floating windows will ignore tiled windows in their blur. Only available if blur_new_optimizations is true. Will reduce overhead on floating " + "blur significantly.", + .type = CONFIG_OPTION_BOOL, + .data = SConfigOptionDescription::SBoolData{false}, + }, + SConfigOptionDescription{ + .value = "blur:noise", + .description = "how much noise to apply. [0.0 - 1.0]", + .type = CONFIG_OPTION_FLOAT, + .data = SConfigOptionDescription::SFloatData{0.0117, 0, 1}, + }, + SConfigOptionDescription{ + .value = "blur:contrast", + .description = "contrast modulation for blur. [0.0 - 2.0]", + .type = CONFIG_OPTION_FLOAT, + .data = SConfigOptionDescription::SFloatData{0.8916, 0, 2}, + }, + SConfigOptionDescription{ + .value = "blur:brightness", + .description = "brightness modulation for blur. [0.0 - 2.0]", + .type = CONFIG_OPTION_FLOAT, + .data = SConfigOptionDescription::SFloatData{0.8172, 0, 2}, + }, + SConfigOptionDescription{ + .value = "blur:vibrancy", + .description = "Increase saturation of blurred colors. [0.0 - 1.0]", + .type = CONFIG_OPTION_FLOAT, + .data = SConfigOptionDescription::SFloatData{0.1696, 0, 1}, + }, + SConfigOptionDescription{ + .value = "blur:vibrancy_darkness", + .description = "How strong the effect of vibrancy is on dark areas . [0.0 - 1.0]", + .type = CONFIG_OPTION_FLOAT, + .data = SConfigOptionDescription::SFloatData{0, 0, 1}, + }, + SConfigOptionDescription{ + .value = "blur:special", + .description = "whether to blur behind the special workspace (note: expensive)", + .type = CONFIG_OPTION_BOOL, + .data = SConfigOptionDescription::SBoolData{false}, + }, + SConfigOptionDescription{ + .value = "blur:popups", + .description = "whether to blur popups (e.g. right-click menus)", + .type = CONFIG_OPTION_BOOL, + .data = SConfigOptionDescription::SBoolData{false}, + }, + SConfigOptionDescription{ + .value = "blur:popups_ignorealpha", + .description = "works like ignorealpha in layer rules. If pixel opacity is below set value, will not blur. [0.0 - 1.0]", + .type = CONFIG_OPTION_FLOAT, + .data = SConfigOptionDescription::SFloatData{0.2, 0, 1}, + }, + + /* + * animations: + */ + + SConfigOptionDescription{ + .value = "animations:enabled", + .description = "enable animations", + .type = CONFIG_OPTION_BOOL, + .data = SConfigOptionDescription::SBoolData{true}, + }, + SConfigOptionDescription{ + .value = "animations:first_launch_animation", + .description = "enable first launch animation", + .type = CONFIG_OPTION_BOOL, + .data = SConfigOptionDescription::SBoolData{true}, + }, + + /* + * input: + */ + + SConfigOptionDescription{ + .value = "input:kb_model", + .description = "Appropriate XKB keymap parameter. See the note below.", + .type = CONFIG_OPTION_STRING_SHORT, + .data = SConfigOptionDescription::SStringData{STRVAL_EMPTY}, + }, + SConfigOptionDescription{ + .value = "input:kb_layout", + .description = "Appropriate XKB keymap parameter", + .type = CONFIG_OPTION_STRING_SHORT, + .data = SConfigOptionDescription::SStringData{"us"}, + }, + SConfigOptionDescription{ + .value = "input:kb_variant", + .description = "Appropriate XKB keymap parameter", + .type = CONFIG_OPTION_STRING_SHORT, + .data = SConfigOptionDescription::SStringData{""}, + }, + SConfigOptionDescription{ + .value = "input:kb_options", + .description = "Appropriate XKB keymap parameter", + .type = CONFIG_OPTION_STRING_SHORT, + .data = SConfigOptionDescription::SStringData{""}, + }, + SConfigOptionDescription{ + .value = "input:kb_rules", + .description = "Appropriate XKB keymap parameter", + .type = CONFIG_OPTION_STRING_SHORT, + .data = SConfigOptionDescription::SStringData{""}, + }, + SConfigOptionDescription{ + .value = "input:kb_file", + .description = "Appropriate XKB keymap parameter", + .type = CONFIG_OPTION_STRING_LONG, + .data = SConfigOptionDescription::SStringData{""}, //##TODO UNSET? + }, + SConfigOptionDescription{ + .value = "input:numlock_by_default", + .description = "Engage numlock by default.", + .type = CONFIG_OPTION_BOOL, + .data = SConfigOptionDescription::SBoolData{false}, + }, + SConfigOptionDescription{ + .value = "input:resolve_binds_by_sym", + .description = "Determines how keybinds act when multiple layouts are used. If false, keybinds will always act as if the first specified layout is active. If true, " + "keybinds specified by symbols are activated when you type the respective symbol with the current layout.", + .type = CONFIG_OPTION_BOOL, + .data = SConfigOptionDescription::SBoolData{false}, + }, + SConfigOptionDescription{ + .value = "input:repeat_rate", + .description = "The repeat rate for held-down keys, in repeats per second.", + .type = CONFIG_OPTION_INT, + .data = SConfigOptionDescription::SRangeData{25, 0, 200}, + }, + SConfigOptionDescription{ + .value = "input:repeat_delay", + .description = "Delay before a held-down key is repeated, in milliseconds.", + .type = CONFIG_OPTION_INT, + .data = SConfigOptionDescription::SRangeData{600, 0, 2000}, + }, + SConfigOptionDescription{ + .value = "input:sensitivity", + .description = "Sets the mouse input sensitivity. Value is clamped to the range -1.0 to 1.0.", + .type = CONFIG_OPTION_FLOAT, + .data = SConfigOptionDescription::SFloatData{0, -1, 1}, + }, + SConfigOptionDescription{ + .value = "input:accel_profile", + .description = "Sets the cursor acceleration profile. Can be one of adaptive, flat. Can also be custom, see below. Leave empty to use libinput's default mode for your " + "input device. [adaptive/flat/custom]", + .type = CONFIG_OPTION_STRING_SHORT, + .data = SConfigOptionDescription::SStringData{""}, //##TODO UNSET? + }, + SConfigOptionDescription{ + .value = "input:force_no_accel", + .description = "Force no cursor acceleration. This bypasses most of your pointer settings to get as raw of a signal as possible. Enabling this is not recommended due to " + "potential cursor desynchronization.", + .type = CONFIG_OPTION_BOOL, + .data = SConfigOptionDescription::SBoolData{false}, + }, + SConfigOptionDescription{ + .value = "input:left_handed", + .description = "Switches RMB and LMB", + .type = CONFIG_OPTION_BOOL, + .data = SConfigOptionDescription::SBoolData{false}, + }, + SConfigOptionDescription{ + .value = "input:scroll_points", + .description = "Sets the scroll acceleration profile, when accel_profile is set to custom. Has to be in the form . Leave empty to have a flat scroll curve.", + .type = CONFIG_OPTION_STRING_SHORT, + .data = SConfigOptionDescription::SStringData{""}, //##TODO UNSET? + }, + SConfigOptionDescription{ + .value = "input:scroll_method", + .description = "Sets the scroll method. Can be one of 2fg (2 fingers), edge, on_button_down, no_scroll. [2fg/edge/on_button_down/no_scroll]", + .type = CONFIG_OPTION_STRING_SHORT, + .data = SConfigOptionDescription::SStringData{""}, //##TODO UNSET? + }, + SConfigOptionDescription{ + .value = "input:scroll_button", + .description = "Sets the scroll button. Has to be an int, cannot be a string. Check wev if you have any doubts regarding the ID. 0 means default.", + .type = CONFIG_OPTION_INT, + .data = SConfigOptionDescription::SRangeData{0, 0, 300}, + }, + SConfigOptionDescription{ + .value = "input:scroll_button_lock", + .description = "If the scroll button lock is enabled, the button does not need to be held down. Pressing and releasing the button toggles the button lock, which logically " + "holds the button down or releases it. While the button is logically held down, motion events are converted to scroll events.", + .type = CONFIG_OPTION_BOOL, + .data = SConfigOptionDescription::SBoolData{false}, + }, + SConfigOptionDescription{ + .value = "input:scroll_factor", + .description = "Multiplier added to scroll movement for external mice. Note that there is a separate setting for touchpad scroll_factor.", + .type = CONFIG_OPTION_FLOAT, + .data = SConfigOptionDescription::SFloatData{1, 0, 2}, + }, + SConfigOptionDescription{ + .value = "input:natural_scroll", + .description = "Inverts scrolling direction. When enabled, scrolling moves content directly, rather than manipulating a scrollbar.", + .type = CONFIG_OPTION_BOOL, + .data = SConfigOptionDescription::SBoolData{false}, + }, + SConfigOptionDescription{ + .value = "input:follow_mouse", + .description = "Specify if and how cursor movement should affect window focus. See the note below. [0/1/2/3]", + .type = CONFIG_OPTION_INT, + .data = SConfigOptionDescription::SRangeData{1, 0, 3}, + }, + SConfigOptionDescription{ + .value = "input:mouse_refocus", + .description = "if disabled, mouse focus won't switch to the hovered window unless the mouse crosses a window boundary when follow_mouse=1.", + .type = CONFIG_OPTION_BOOL, + .data = SConfigOptionDescription::SBoolData{true}, + }, + SConfigOptionDescription{ + .value = "input:float_switch_override_focus", + .description = "If enabled (1 or 2), focus will change to the window under the cursor when changing from tiled-to-floating and vice versa. If 2, focus will also follow " + "mouse on float-to-float switches.", + .type = CONFIG_OPTION_INT, + .data = SConfigOptionDescription::SRangeData{1, 0, 2}, + }, + SConfigOptionDescription{ + .value = "input:special_fallthrough", + .description = "if enabled, having only floating windows in the special workspace will not block focusing windows in the regular workspace.", + .type = CONFIG_OPTION_BOOL, + .data = SConfigOptionDescription::SBoolData{false}, + }, + SConfigOptionDescription{ + .value = "input:off_window_axis_events", + .description = "Handles axis events around (gaps/border for tiled, dragarea/border for floated) a focused window. 0 ignores axis events 1 sends out-of-bound coordinates 2 " + "fakes pointer coordinates to the closest point inside the window 3 warps the cursor to the closest point inside the window", + .type = CONFIG_OPTION_INT, + .data = SConfigOptionDescription::SRangeData{1, 0, 3}, + }, + SConfigOptionDescription{ + .value = "input:emulate_discrete_scroll", + .description = "Emulates discrete scrolling from high resolution scrolling events. 0 disables it, 1 enables handling of non-standard events only, and 2 force enables all " + "scroll wheel events to be handled", + .type = CONFIG_OPTION_INT, + .data = SConfigOptionDescription::SRangeData{1, 0, 2}, + }, + + /* + * input:touchpad: + */ + + SConfigOptionDescription{ + .value = "input:touchpad:disable_while_typing", + .description = "Disable the touchpad while typing.", + .type = CONFIG_OPTION_BOOL, + .data = SConfigOptionDescription::SBoolData{true}, + }, + SConfigOptionDescription{ + .value = "input:touchpad:natural_scroll", + .description = "Inverts scrolling direction. When enabled, scrolling moves content directly, rather than manipulating a scrollbar.", + .type = CONFIG_OPTION_BOOL, + .data = SConfigOptionDescription::SBoolData{false}, + }, + SConfigOptionDescription{ + .value = "input:touchpad:scroll_factor", + .description = "Multiplier applied to the amount of scroll movement.", + .type = CONFIG_OPTION_FLOAT, + .data = SConfigOptionDescription::SFloatData{1, 0, 2}, + }, + SConfigOptionDescription{ + .value = "input:touchpad:middle_button_emulation", + .description = + "Sending LMB and RMB simultaneously will be interpreted as a middle click. This disables any touchpad area that would normally send a middle click based on location.", + .type = CONFIG_OPTION_BOOL, + .data = SConfigOptionDescription::SBoolData{false}, + }, + SConfigOptionDescription{ + .value = "input:touchpad:tap_button_map", + .description = "Sets the tap button mapping for touchpad button emulation. Can be one of lrm (default) or lmr (Left, Middle, Right Buttons). [lrm/lmr]", + .type = CONFIG_OPTION_STRING_SHORT, + .data = SConfigOptionDescription::SStringData{""}, //##TODO UNSET? + }, + SConfigOptionDescription{ + .value = "input:touchpad:clickfinger_behavior", + .description = + "Button presses with 1, 2, or 3 fingers will be mapped to LMB, RMB, and MMB respectively. This disables interpretation of clicks based on location on the touchpad.", + .type = CONFIG_OPTION_BOOL, + .data = SConfigOptionDescription::SBoolData{false}, + }, + SConfigOptionDescription{ + .value = "input:touchpad:tap-to-click", + .description = "Tapping on the touchpad with 1, 2, or 3 fingers will send LMB, RMB, and MMB respectively.", + .type = CONFIG_OPTION_BOOL, + .data = SConfigOptionDescription::SBoolData{true}, + }, + SConfigOptionDescription{ + .value = "input:touchpad:drag_lock", + .description = "When enabled, lifting the finger off for a short time while dragging will not drop the dragged item.", + .type = CONFIG_OPTION_BOOL, + .data = SConfigOptionDescription::SBoolData{false}, + }, + SConfigOptionDescription{ + .value = "input:touchpad:tap-and-drag", + .description = "Sets the tap and drag mode for the touchpad", + .type = CONFIG_OPTION_BOOL, + .data = SConfigOptionDescription::SBoolData{false}, + }, + + /* + * input:touchdevice: + */ + + SConfigOptionDescription{ + .value = "input:touchdevice:transform", + .description = "Transform the input from touchdevices. The possible transformations are the same as those of the monitors", + .type = CONFIG_OPTION_INT, + .data = SConfigOptionDescription::SRangeData{0, 0, 6}, // ##TODO RANGE? + }, + SConfigOptionDescription{ + .value = "input:touchdevice:output", + .description = "The monitor to bind touch devices. The default is auto-detection. To stop auto-detection, use an empty string or the [[Empty]] value.", + .type = CONFIG_OPTION_STRING_SHORT, + .data = SConfigOptionDescription::SStringData{""}, //##TODO UNSET? + }, + SConfigOptionDescription{ + .value = "input:touchdevice:enabled", + .description = "Whether input is enabled for touch devices.", + .type = CONFIG_OPTION_BOOL, + .data = SConfigOptionDescription::SBoolData{true}, + }, + + /* + * input:tablet: + */ + + SConfigOptionDescription{ + .value = "input:tablet:transform", + .description = "transform the input from tablets. The possible transformations are the same as those of the monitors", + .type = CONFIG_OPTION_INT, + .data = SConfigOptionDescription::SRangeData{0, 0, 6}, // ##TODO RANGE? + }, + SConfigOptionDescription{ + .value = "input:tablet:output", + .description = "the monitor to bind tablets. Empty means unbound..", + .type = CONFIG_OPTION_STRING_SHORT, + .data = SConfigOptionDescription::SStringData{""}, //##TODO UNSET? + }, + SConfigOptionDescription{ + .value = "input:tablet:region_position", + .description = "position of the mapped region in monitor layout.", + .type = CONFIG_OPTION_VECTOR, + .data = SConfigOptionDescription::SVectorData{{}, {-20000, -20000}, {20000, 20000}}, + }, + SConfigOptionDescription{ + .value = "input:tablet:region_size", + .description = "size of the mapped region. When this variable is set, tablet input will be mapped to the region. [0, 0] or invalid size means unset.", + .type = CONFIG_OPTION_VECTOR, + .data = SConfigOptionDescription::SVectorData{{}, {-100, -100}, {4000, 4000}}, + }, + SConfigOptionDescription{ + .value = "input:tablet:relative_input", + .description = "whether the input should be relative", + .type = CONFIG_OPTION_BOOL, + .data = SConfigOptionDescription::SBoolData{false}, + }, + SConfigOptionDescription{ + .value = "input:tablet:left_handed", + .description = "if enabled, the tablet will be rotated 180 degrees", + .type = CONFIG_OPTION_BOOL, + .data = SConfigOptionDescription::SBoolData{false}, + }, + SConfigOptionDescription{ + .value = "input:tablet:active_area_size", + .description = "size of tablet's active area in mm", + .type = CONFIG_OPTION_VECTOR, + .data = SConfigOptionDescription::SVectorData{{}, {}, {500, 500}}, + }, + SConfigOptionDescription{ + .value = "input:tablet:active_area_position", + .description = "position of the active area in mm", + .type = CONFIG_OPTION_VECTOR, + .data = SConfigOptionDescription::SVectorData{{}, {}, {500, 500}}, + }, + + /* ##TODO + * + * PER DEVICE SETTINGS? + * + * */ + + /* + * gestures: + */ + + SConfigOptionDescription{ + .value = "gestures:workspace_swipe", + .description = "enable workspace swipe gesture on touchpad", + .type = CONFIG_OPTION_BOOL, + .data = SConfigOptionDescription::SBoolData{false}, + }, + SConfigOptionDescription{ + .value = "gestures:workspace_swipe_fingers", + .description = "how many fingers for the touchpad gesture", + .type = CONFIG_OPTION_INT, + .data = SConfigOptionDescription::SRangeData{3, 0, 5}, //##TODO RANGE? + }, + SConfigOptionDescription{ + .value = "gestures:workspace_swipe_min_fingers", + .description = "if enabled, workspace_swipe_fingers is considered the minimum number of fingers to swipe", + .type = CONFIG_OPTION_BOOL, + .data = SConfigOptionDescription::SBoolData{false}, + }, + SConfigOptionDescription{ + .value = "gestures:workspace_swipe_distance", + .description = "in px, the distance of the touchpad gesture", + .type = CONFIG_OPTION_INT, + .data = SConfigOptionDescription::SRangeData{300, 0, 2000}, //##TODO RANGE? + }, + SConfigOptionDescription{ + .value = "gestures:workspace_swipe_touch", + .description = "enable workspace swiping from the edge of a touchscreen", + .type = CONFIG_OPTION_BOOL, + .data = SConfigOptionDescription::SBoolData{false}, + }, + SConfigOptionDescription{ + .value = "gestures:workspace_swipe_invert", + .description = "invert the direction (touchpad only)", + .type = CONFIG_OPTION_BOOL, + .data = SConfigOptionDescription::SBoolData{true}, + }, + SConfigOptionDescription{ + .value = "gestures:workspace_swipe_touch_invert", + .description = "invert the direction (touchscreen only)", + .type = CONFIG_OPTION_BOOL, + .data = SConfigOptionDescription::SBoolData{false}, + }, + SConfigOptionDescription{ + .value = "gestures:workspace_swipe_min_speed_to_force", + .description = "minimum speed in px per timepoint to force the change ignoring cancel_ratio. Setting to 0 will disable this mechanic.", + .type = CONFIG_OPTION_INT, + .data = SConfigOptionDescription::SRangeData{30, 0, 200}, //##TODO RANGE? + }, + SConfigOptionDescription{ + .value = "gestures:workspace_swipe_cancel_ratio", + .description = "how much the swipe has to proceed in order to commence it. (0.7 -> if > 0.7 * distance, switch, if less, revert) [0.0 - 1.0]", + .type = CONFIG_OPTION_FLOAT, + .data = SConfigOptionDescription::SFloatData{0.5, 0, 1}, + }, + SConfigOptionDescription{ + .value = "gestures:workspace_swipe_create_new", + .description = "whether a swipe right on the last workspace should create a new one.", + .type = CONFIG_OPTION_BOOL, + .data = SConfigOptionDescription::SBoolData{true}, + }, + SConfigOptionDescription{ + .value = "gestures:workspace_swipe_direction_lock", + .description = "if enabled, switching direction will be locked when you swipe past the direction_lock_threshold (touchpad only).", + .type = CONFIG_OPTION_BOOL, + .data = SConfigOptionDescription::SBoolData{true}, + }, + SConfigOptionDescription{ + .value = "gestures:workspace_swipe_direction_lock_threshold", + .description = "in px, the distance to swipe before direction lock activates (touchpad only).", + .type = CONFIG_OPTION_INT, + .data = SConfigOptionDescription::SRangeData{10, 0, 200}, //##TODO RANGE? + }, + SConfigOptionDescription{ + .value = "gestures:workspace_swipe_forever", + .description = "if enabled, swiping will not clamp at the neighboring workspaces but continue to the further ones.", + .type = CONFIG_OPTION_BOOL, + .data = SConfigOptionDescription::SBoolData{false}, + }, + SConfigOptionDescription{ + .value = "gestures:workspace_swipe_use_r", + .description = "if enabled, swiping will use the r prefix instead of the m prefix for finding workspaces.", + .type = CONFIG_OPTION_BOOL, + .data = SConfigOptionDescription::SBoolData{false}, + }, + + /* + * group: + */ + + SConfigOptionDescription{ + .value = "group:insert_after_current", + .description = "whether new windows in a group spawn after current or at group tail", + .type = CONFIG_OPTION_BOOL, + .data = SConfigOptionDescription::SBoolData{true}, + }, + SConfigOptionDescription{ + .value = "group:focus_removed_window", + .description = "whether Hyprland should focus on the window that has just been moved out of the group", + .type = CONFIG_OPTION_BOOL, + .data = SConfigOptionDescription::SBoolData{true}, + }, + SConfigOptionDescription{ + .value = "general:col.border_active", + .description = "border color for inactive windows", + .type = CONFIG_OPTION_GRADIENT, + .data = SConfigOptionDescription::SGradientData{"0x66ffff00"}, + }, + SConfigOptionDescription{ + .value = "general:col.border_inactive", + .description = "border color for the active window", + .type = CONFIG_OPTION_GRADIENT, + .data = SConfigOptionDescription::SGradientData{"0x66777700"}, + }, + SConfigOptionDescription{ + .value = "general:col.border_locked_active", + .description = "inactive border color for window that cannot be added to a group (see denywindowfromgroup dispatcher)", + .type = CONFIG_OPTION_GRADIENT, + .data = SConfigOptionDescription::SGradientData{"0x66ff5500"}, + }, + SConfigOptionDescription{ + .value = "general:col.border_locked_inactive", + .description = "active border color for window that cannot be added to a group", + .type = CONFIG_OPTION_GRADIENT, + .data = SConfigOptionDescription::SGradientData{"0x66775500"}, + }, + + /* + * group:groupbar: + */ + + SConfigOptionDescription{ + .value = "group:groupbar:enabled", + .description = "enables groupbars", + .type = CONFIG_OPTION_BOOL, + .data = SConfigOptionDescription::SBoolData{true}, + }, + SConfigOptionDescription{ + .value = "group:groupbar:font_family", + .description = "font used to display groupbar titles, use misc:font_family if not specified", + .type = CONFIG_OPTION_STRING_SHORT, + .data = SConfigOptionDescription::SStringData{STRVAL_EMPTY}, //##TODO UNSET? + }, + SConfigOptionDescription{ + .value = "group:groupbar:font_size", + .description = "font size of groupbar title", + .type = CONFIG_OPTION_INT, + .data = SConfigOptionDescription::SRangeData{8, 2, 64}, + }, + SConfigOptionDescription{ + .value = "group:groupbar:gradients", + .description = "enables gradients", + .type = CONFIG_OPTION_BOOL, + .data = SConfigOptionDescription::SBoolData{true}, + }, + SConfigOptionDescription{ + .value = "group:groupbar:height", + .description = "height of the groupbar", + .type = CONFIG_OPTION_INT, + .data = SConfigOptionDescription::SRangeData{14, 1, 64}, + }, + SConfigOptionDescription{ + .value = "group:groupbar:stacked", + .description = "render the groupbar as a vertical stack", + .type = CONFIG_OPTION_BOOL, + .data = SConfigOptionDescription::SBoolData{false}, + }, + SConfigOptionDescription{ + .value = "group:groupbar:priority", + .description = "sets the decoration priority for groupbars", + .type = CONFIG_OPTION_INT, + .data = SConfigOptionDescription::SRangeData{3, 0, 6}, //##TODO RANGE? + }, + SConfigOptionDescription{ + .value = "group:groupbar:render_titles", + .description = "whether to render titles in the group bar decoration", + .type = CONFIG_OPTION_BOOL, + .data = SConfigOptionDescription::SBoolData{true}, + }, + SConfigOptionDescription{ + .value = "group:groupbar:scrolling", + .description = "whether scrolling in the groupbar changes group active window", + .type = CONFIG_OPTION_BOOL, + .data = SConfigOptionDescription::SBoolData{true}, + }, + SConfigOptionDescription{ + .value = "group:groupbar:text_color", + .description = "controls the group bar text color", + .type = CONFIG_OPTION_COLOR, + .data = SConfigOptionDescription::SColorData{0xffffffff}, + }, + SConfigOptionDescription{ + .value = "group:groupbar:col.active", + .description = "active group border color", + .type = CONFIG_OPTION_COLOR, + .data = SConfigOptionDescription::SColorData{0x66ffff00}, + }, + SConfigOptionDescription{ + .value = "group:groupbar:col.inactive", + .description = "inactive (out of focus) group border color", + .type = CONFIG_OPTION_COLOR, + .data = SConfigOptionDescription::SColorData{0x66777700}, + }, + SConfigOptionDescription{ + .value = "group:groupbar:col.locked_active", + .description = "active locked group border color", + .type = CONFIG_OPTION_COLOR, + .data = SConfigOptionDescription::SColorData{0x66ff5500}, + }, + SConfigOptionDescription{ + .value = "group:groupbar:col.locked_inactive", + .description = "controls the group bar text color", + .type = CONFIG_OPTION_COLOR, + .data = SConfigOptionDescription::SColorData{0x66775500}, + }, + + /* + * misc: + */ + + SConfigOptionDescription{ + .value = "misc:disable_hyprland_logo", + .description = "disables the random Hyprland logo / anime girl background. :(", + .type = CONFIG_OPTION_BOOL, + .data = SConfigOptionDescription::SBoolData{false}, + }, + SConfigOptionDescription{ + .value = "misc:disable_splash_rendering", + .description = "disables the Hyprland splash rendering. (requires a monitor reload to take effect)", + .type = CONFIG_OPTION_BOOL, + .data = SConfigOptionDescription::SBoolData{false}, + }, + SConfigOptionDescription{ + .value = "misc:col.splash", + .description = "Changes the color of the splash text (requires a monitor reload to take effect).", + .type = CONFIG_OPTION_COLOR, + .data = SConfigOptionDescription::SColorData{0xffffffff}, + }, + SConfigOptionDescription{ + .value = "misc:font_family", + .description = "Set the global default font to render the text including debug fps/notification, config error messages and etc., selected from system fonts.", + .type = CONFIG_OPTION_STRING_SHORT, + .data = SConfigOptionDescription::SStringData{"Sans"}, + }, + SConfigOptionDescription{ + .value = "misc:splash_font_family", + .description = "Changes the font used to render the splash text, selected from system fonts (requires a monitor reload to take effect).", + .type = CONFIG_OPTION_STRING_SHORT, + .data = SConfigOptionDescription::SStringData{STRVAL_EMPTY}, //##TODO UNSET? + }, + SConfigOptionDescription{ + .value = "misc:force_default_wallpaper", + .description = "Enforce any of the 3 default wallpapers. Setting this to 0 or 1 disables the anime background. -1 means “random”. [-1/0/1/2]", + .type = CONFIG_OPTION_INT, + .data = SConfigOptionDescription::SRangeData{-1, -1, 2}, + }, + SConfigOptionDescription{ + .value = "misc:vfr", + .description = "controls the VFR status of Hyprland. Heavily recommended to leave enabled to conserve resources.", + .type = CONFIG_OPTION_BOOL, + .data = SConfigOptionDescription::SBoolData{true}, + }, + SConfigOptionDescription{ + .value = "misc:vrr", + .description = " controls the VRR (Adaptive Sync) of your monitors. 0 - off, 1 - on, 2 - fullscreen only [0/1/2]", + .type = CONFIG_OPTION_INT, + .data = SConfigOptionDescription::SRangeData{0, 0, 2}, + }, + SConfigOptionDescription{ + .value = "misc:mouse_move_enables_dpms", + .description = "If DPMS is set to off, wake up the monitors if the mouse move", + .type = CONFIG_OPTION_BOOL, + .data = SConfigOptionDescription::SBoolData{false}, + }, + SConfigOptionDescription{ + .value = "misc:key_press_enables_dpms", + .description = "If DPMS is set to off, wake up the monitors if a key is pressed.", + .type = CONFIG_OPTION_BOOL, + .data = SConfigOptionDescription::SBoolData{false}, + }, + SConfigOptionDescription{ + .value = "misc:always_follow_on_dnd", + .description = "Will make mouse focus follow the mouse when drag and dropping. Recommended to leave it enabled, especially for people using focus follows mouse at 0.", + .type = CONFIG_OPTION_BOOL, + .data = SConfigOptionDescription::SBoolData{true}, + }, + SConfigOptionDescription{ + .value = "misc:layers_hog_keyboard_focus", + .description = "If true, will make keyboard-interactive layers keep their focus on mouse move (e.g. wofi, bemenu)", + .type = CONFIG_OPTION_BOOL, + .data = SConfigOptionDescription::SBoolData{true}, + }, + SConfigOptionDescription{ + .value = "misc:animate_manual_resizes", + .description = "If true, will animate manual window resizes/moves", + .type = CONFIG_OPTION_BOOL, + .data = SConfigOptionDescription::SBoolData{false}, + }, + SConfigOptionDescription{ + .value = "misc:animate_mouse_windowdragging", + .description = "If true, will animate windows being dragged by mouse, note that this can cause weird behavior on some curves", + .type = CONFIG_OPTION_BOOL, + .data = SConfigOptionDescription::SBoolData{false}, + }, + SConfigOptionDescription{ + .value = "misc:disable_autoreload", + .description = "If true, the config will not reload automatically on save, and instead needs to be reloaded with hyprctl reload. Might save on battery.", + .type = CONFIG_OPTION_BOOL, + .data = SConfigOptionDescription::SBoolData{false}, + }, + SConfigOptionDescription{ + .value = "misc:enable_swallow", + .description = "Enable window swallowing", + .type = CONFIG_OPTION_BOOL, + .data = SConfigOptionDescription::SBoolData{false}, + }, + SConfigOptionDescription{ + .value = "misc:swallow_regex", + .description = + "The class regex to be used for windows that should be swallowed (usually, a terminal). To know more about the list of regex which can be used use this cheatsheet.", + .type = CONFIG_OPTION_STRING_SHORT, + .data = SConfigOptionDescription::SStringData{""}, //##TODO UNSET? + }, + SConfigOptionDescription{ + .value = "misc:swallow_exception_regex", + .description = "The title regex to be used for windows that should not be swallowed by the windows specified in swallow_regex (e.g. wev). The regex is matched against the " + "parent (e.g. Kitty) window’s title on the assumption that it changes to whatever process it’s running.", + .type = CONFIG_OPTION_STRING_SHORT, + .data = SConfigOptionDescription::SStringData{""}, //##TODO UNSET? + }, + SConfigOptionDescription{ + .value = "misc:focus_on_activate", + .description = "Whether Hyprland should focus an app that requests to be focused (an activate request)", + .type = CONFIG_OPTION_BOOL, + .data = SConfigOptionDescription::SBoolData{false}, + }, + SConfigOptionDescription{ + .value = "misc:mouse_move_focuses_monitor", + .description = "Whether mouse moving into a different monitor should focus it", + .type = CONFIG_OPTION_BOOL, + .data = SConfigOptionDescription::SBoolData{true}, + }, + SConfigOptionDescription{ + .value = "misc:render_ahead_of_time", + .description = "[Warning: buggy] starts rendering before your monitor displays a frame in order to lower latency", + .type = CONFIG_OPTION_BOOL, + .data = SConfigOptionDescription::SBoolData{false}, + }, + SConfigOptionDescription{ + .value = "misc:render_ahead_safezone", + .description = "how many ms of safezone to add to rendering ahead of time. Recommended 1-2.", + .type = CONFIG_OPTION_INT, + .data = SConfigOptionDescription::SRangeData{1, 1, 10}, + }, + SConfigOptionDescription{ + .value = "misc:allow_session_lock_restore", + .description = "if true, will allow you to restart a lockscreen app in case it crashes (red screen of death)", + .type = CONFIG_OPTION_BOOL, + .data = SConfigOptionDescription::SBoolData{false}, + }, + SConfigOptionDescription{ + .value = "misc:background_color", + .description = "change the background color. (requires enabled disable_hyprland_logo)", + .type = CONFIG_OPTION_COLOR, + .data = SConfigOptionDescription::SColorData{0x111111}, + }, + SConfigOptionDescription{ + .value = "misc:close_special_on_empty", + .description = "close the special workspace if the last window is removed", + .type = CONFIG_OPTION_BOOL, + .data = SConfigOptionDescription::SBoolData{true}, + }, + SConfigOptionDescription{ + .value = "misc:new_window_takes_over_fullscreen", + .description = "if there is a fullscreen or maximized window, decide whether a new tiled window opened should replace it, stay behind or disable the fullscreen/maximized " + "state. 0 - behind, 1 - takes over, 2 - unfullscreen/unmaxize [0/1/2]", + .type = CONFIG_OPTION_INT, + .data = SConfigOptionDescription::SRangeData{0, 0, 2}, + }, + SConfigOptionDescription{ + .value = "misc:exit_window_retains_fullscreen", + .description = "if true, closing a fullscreen window makes the next focused window fullscreen", + .type = CONFIG_OPTION_BOOL, + .data = SConfigOptionDescription::SBoolData{false}, + }, + SConfigOptionDescription{ + .value = "misc:initial_workspace_tracking", + .description = "if enabled, windows will open on the workspace they were invoked on. 0 - disabled, 1 - single-shot, 2 - persistent (all children too)", + .type = CONFIG_OPTION_INT, + .data = SConfigOptionDescription::SRangeData{1, 0, 2}, + }, + SConfigOptionDescription{ + .value = "misc:middle_click_paste", + .description = "whether to enable middle-click-paste (aka primary selection)", + .type = CONFIG_OPTION_BOOL, + .data = SConfigOptionDescription::SBoolData{true}, + }, + + /* + * binds: + */ + + SConfigOptionDescription{ + .value = "binds:pass_mouse_when_bound", + .description = "if disabled, will not pass the mouse events to apps / dragging windows around if a keybind has been triggered.", + .type = CONFIG_OPTION_BOOL, + .data = SConfigOptionDescription::SBoolData{false}, + }, + SConfigOptionDescription{ + .value = "binds:scroll_event_delay", + .description = "in ms, how many ms to wait after a scroll event to allow passing another one for the binds.", + .type = CONFIG_OPTION_INT, + .data = SConfigOptionDescription::SRangeData{300, 0, 2000}, + }, + SConfigOptionDescription{ + .value = "binds:workspace_back_and_forth", + .description = "If enabled, an attempt to switch to the currently focused workspace will instead switch to the previous workspace. Akin to i3’s auto_back_and_forth.", + .type = CONFIG_OPTION_BOOL, + .data = SConfigOptionDescription::SBoolData{false}, + }, + SConfigOptionDescription{ + .value = "binds:allow_workspace_cycles", + .description = "If enabled, workspaces don’t forget their previous workspace, so cycles can be created by switching to the first workspace in a sequence, then endlessly " + "going to the previous workspace.", + .type = CONFIG_OPTION_BOOL, + .data = SConfigOptionDescription::SBoolData{false}, + }, + SConfigOptionDescription{ + .value = "binds:workspace_center_on", + .description = "Whether switching workspaces should center the cursor on the workspace (0) or on the last active window for that workspace (1)", + .type = CONFIG_OPTION_INT, + .data = SConfigOptionDescription::SRangeData{0, 0, 1}, + }, + SConfigOptionDescription{ + .value = "binds:focus_preferred_method", + .description = "sets the preferred focus finding method when using focuswindow/movewindow/etc with a direction. 0 - history (recent have priority), 1 - length (longer " + "shared edges have priority)", + .type = CONFIG_OPTION_INT, + .data = SConfigOptionDescription::SRangeData{0, 0, 1}, + }, + SConfigOptionDescription{ + .value = "binds:ignore_group_lock", + .description = "If enabled, dispatchers like moveintogroup, moveoutofgroup and movewindoworgroup will ignore lock per group.", + .type = CONFIG_OPTION_BOOL, + .data = SConfigOptionDescription::SBoolData{false}, + }, + SConfigOptionDescription{ + .value = "binds:movefocus_cycles_fullscreen", + .description = "If enabled, when on a fullscreen window, movefocus will cycle fullscreen, if not, it will move the focus in a direction.", + .type = CONFIG_OPTION_BOOL, + .data = SConfigOptionDescription::SBoolData{true}, + }, + SConfigOptionDescription{ + .value = "binds:disable_keybind_grabbing", + .description = "If enabled, apps that request keybinds to be disabled (e.g. VMs) will not be able to do so.", + .type = CONFIG_OPTION_BOOL, + .data = SConfigOptionDescription::SBoolData{false}, + }, + SConfigOptionDescription{ + .value = "binds:window_direction_monitor_fallback", + .description = "If enabled, moving a window or focus over the edge of a monitor with a direction will move it to the next monitor in that direction.", + .type = CONFIG_OPTION_BOOL, + .data = SConfigOptionDescription::SBoolData{true}, + }, + + /* + * xwayland: + */ + + SConfigOptionDescription{ + .value = "xwayland:use_nearest_neighbor", + .description = "uses the nearest neighbor filtering for xwayland apps, making them pixelated rather than blurry", + .type = CONFIG_OPTION_BOOL, + .data = SConfigOptionDescription::SBoolData{true}, + }, + SConfigOptionDescription{ + .value = "xwayland:force_zero_scaling", + .description = "forces a scale of 1 on xwayland windows on scaled displays.", + .type = CONFIG_OPTION_BOOL, + .data = SConfigOptionDescription::SBoolData{false}, + }, + + /* + * opengl: + */ + + SConfigOptionDescription{ + .value = "opengl:nvidia_anti_flicker", + .description = "reduces flickering on nvidia at the cost of possible frame drops on lower-end GPUs. On non-nvidia, this is ignored.", + .type = CONFIG_OPTION_BOOL, + .data = SConfigOptionDescription::SBoolData{true}, + }, + SConfigOptionDescription{ + .value = "opengl:force_introspection", + .description = "forces introspection at all times. Introspection is aimed at reducing GPU usage in certain cases, but might cause graphical glitches on nvidia. 0 - " + "nothing, 1 - force always on, 2 - force always on if nvidia", + .type = CONFIG_OPTION_INT, + .data = SConfigOptionDescription::SRangeData{2, 0, 2}, + }, + + /* + * render: + */ + + SConfigOptionDescription{ + .value = "render:explicit_sync", + .description = "Whether to enable explicit sync support. Requires a hyprland restart. 0 - no, 1 - yes, 2 - auto based on the gpu driver", + .type = CONFIG_OPTION_INT, + .data = SConfigOptionDescription::SRangeData{2, 0, 2}, + }, + SConfigOptionDescription{ + .value = "render:explicit_sync_kms", + .description = "Whether to enable explicit sync support for the KMS layer. Requires explicit_sync to be enabled. 0 - no, 1 - yes, 2 - auto based on the gpu driver", + .type = CONFIG_OPTION_INT, + .data = SConfigOptionDescription::SRangeData{2, 0, 2}, + }, + SConfigOptionDescription{ + .value = "render:direct_scanout", + .description = "Enables direct scanout. Direct scanout attempts to reduce lag when there is only one fullscreen application on a screen (e.g. game). It is also " + "recommended to set this to false if the fullscreen application shows graphical glitches.", + .type = CONFIG_OPTION_BOOL, + .data = SConfigOptionDescription::SBoolData{false}, + }, + + /* + * cursor: + */ + + SConfigOptionDescription{ + .value = "cursor:use_nearest_neighbor", + .description = "sync xcursor theme with gsettings, it applies cursor-theme and cursor-size on theme load to gsettings making most CSD gtk based clients use same xcursor " + "theme and size.", + .type = CONFIG_OPTION_BOOL, + .data = SConfigOptionDescription::SBoolData{true}, + }, + SConfigOptionDescription{ + .value = "cursor:no_hardware_cursors", + .description = "disables hardware cursors", + .type = CONFIG_OPTION_BOOL, + .data = SConfigOptionDescription::SBoolData{false}, + }, + SConfigOptionDescription{ + .value = "cursor:no_break_fs_vrr", + .description = "disables scheduling new frames on cursor movement for fullscreen apps with VRR enabled to avoid framerate spikes (requires no_hardware_cursors = true)", + .type = CONFIG_OPTION_BOOL, + .data = SConfigOptionDescription::SBoolData{false}, + }, + SConfigOptionDescription{ + .value = "cursor:min_refresh_rate", + .description = "minimum refresh rate for cursor movement when no_break_fs_vrr is active. Set to minimum supported refresh rate or higher", + .type = CONFIG_OPTION_INT, + .data = SConfigOptionDescription::SRangeData{24, 10, 500}, + }, + SConfigOptionDescription{ + .value = "cursor:hotspot_padding", + .description = "the padding, in logical px, between screen edges and the cursor", + .type = CONFIG_OPTION_INT, + .data = SConfigOptionDescription::SRangeData{1, 0, 20}, + }, + SConfigOptionDescription{ + .value = "cursor:inactive_timeout", + .description = "in seconds, after how many seconds of cursor’s inactivity to hide it. Set to 0 for never.", + .type = CONFIG_OPTION_INT, + .data = SConfigOptionDescription::SRangeData{0, 0, 20}, + }, + SConfigOptionDescription{ + .value = "cursor:no_warps", + .description = "if true, will not warp the cursor in many cases (focusing, keybinds, etc)", + .type = CONFIG_OPTION_BOOL, + .data = SConfigOptionDescription::SBoolData{false}, + }, + SConfigOptionDescription{ + .value = "cursor:persistent_warps", + .description = "When a window is refocused, the cursor returns to its last position relative to that window, rather than to the centre.", + .type = CONFIG_OPTION_BOOL, + .data = SConfigOptionDescription::SBoolData{false}, + }, + SConfigOptionDescription{ + .value = "cursor:warp_on_change_workspace", + .description = "If true, move the cursor to the last focused window after changing the workspace.", + .type = CONFIG_OPTION_BOOL, + .data = SConfigOptionDescription::SBoolData{false}, + }, + SConfigOptionDescription{ + .value = "cursor:default_monitor", + .description = "the name of a default monitor for the cursor to be set to on startup (see hyprctl monitors for names)", + .type = CONFIG_OPTION_STRING_SHORT, + .data = SConfigOptionDescription::SStringData{""}, //##TODO UNSET? + }, + SConfigOptionDescription{ + .value = "cursor:zoom_factor", + .description = "the factor to zoom by around the cursor. Like a magnifying glass. Minimum 1.0 (meaning no zoom)", + .type = CONFIG_OPTION_FLOAT, + .data = SConfigOptionDescription::SFloatData{1, 1, 10}, + }, + SConfigOptionDescription{ + .value = "cursor:zoom_rigid", + .description = "whether the zoom should follow the cursor rigidly (cursor is always centered if it can be) or loosely", + .type = CONFIG_OPTION_BOOL, + .data = SConfigOptionDescription::SBoolData{false}, + }, + SConfigOptionDescription{ + .value = "cursor:enable_hyprcursor", + .description = "whether to enable hyprcursor support", + .type = CONFIG_OPTION_BOOL, + .data = SConfigOptionDescription::SBoolData{true}, + }, + SConfigOptionDescription{ + .value = "cursor:hide_on_key_press", + .description = "Hides the cursor when you press any key until the mouse is moved.", + .type = CONFIG_OPTION_BOOL, + .data = SConfigOptionDescription::SBoolData{false}, + }, + SConfigOptionDescription{ + .value = "cursor:hide_on_touch", + .description = "Hides the cursor when the last input was a touch input until a mouse input is done.", + .type = CONFIG_OPTION_BOOL, + .data = SConfigOptionDescription::SBoolData{true}, + }, + SConfigOptionDescription{ + .value = "cursor:allow_dumb_copy", + .description = "Makes HW cursors work on Nvidia, at the cost of a possible hitch whenever the image changes", + .type = CONFIG_OPTION_BOOL, + .data = SConfigOptionDescription::SBoolData{false}, + }, + + /* + * debug: + */ + + SConfigOptionDescription{ + .value = "debug:overlay", + .description = "print the debug performance overlay. Disable VFR for accurate results.", + .type = CONFIG_OPTION_BOOL, + .data = SConfigOptionDescription::SBoolData{false}, + }, + SConfigOptionDescription{ + .value = "debug:damage_blink", + .description = "disable logging to a file", + .type = CONFIG_OPTION_BOOL, + .data = SConfigOptionDescription::SBoolData{false}, + }, + SConfigOptionDescription{ + .value = "debug:disable_logs", + .description = "disable logging to a file", + .type = CONFIG_OPTION_BOOL, + .data = SConfigOptionDescription::SBoolData{true}, + }, + SConfigOptionDescription{ + .value = "debug:disable_time", + .description = "disables time logging", + .type = CONFIG_OPTION_BOOL, + .data = SConfigOptionDescription::SBoolData{true}, + }, + SConfigOptionDescription{ + .value = "debug:damage_tracking", + .description = "redraw only the needed bits of the display. Do not change. (default: full - 2) monitor - 1, none - 0", + .type = CONFIG_OPTION_INT, + .data = SConfigOptionDescription::SRangeData{2, 0, 2}, + }, + SConfigOptionDescription{ + .value = "debug:enable_stdout_logs", + .description = "enables logging to stdout", + .type = CONFIG_OPTION_BOOL, + .data = SConfigOptionDescription::SBoolData{false}, + }, + SConfigOptionDescription{ + .value = "debug:manual_crash", + .description = "set to 1 and then back to 0 to crash Hyprland.", + .type = CONFIG_OPTION_INT, + .data = SConfigOptionDescription::SRangeData{0, 0, 1}, + }, + SConfigOptionDescription{ + .value = "debug:suppress_errors", + .description = "if true, do not display config file parsing errors.", + .type = CONFIG_OPTION_BOOL, + .data = SConfigOptionDescription::SBoolData{false}, + }, + SConfigOptionDescription{ + .value = "debug:watchdog_timeout", + .description = "sets the timeout in seconds for watchdog to abort processing of a signal of the main thread. Set to 0 to disable.", + .type = CONFIG_OPTION_INT, + .data = SConfigOptionDescription::SRangeData{5, 0, 20}, + }, + SConfigOptionDescription{ + .value = "debug:disable_scale_checks", + .description = "disables verification of the scale factors. Will result in pixel alignment and rounding errors.", + .type = CONFIG_OPTION_BOOL, + .data = SConfigOptionDescription::SBoolData{false}, + }, + SConfigOptionDescription{ + .value = "debug:error_limit", + .description = "limits the number of displayed config file parsing errors.", + .type = CONFIG_OPTION_INT, + .data = SConfigOptionDescription::SRangeData{5, 0, 20}, + }, + SConfigOptionDescription{ + .value = "debug:error_position", + .description = "sets the position of the error bar. top - 0, bottom - 1", + .type = CONFIG_OPTION_INT, + .data = SConfigOptionDescription::SRangeData{0, 0, 1}, + }, + SConfigOptionDescription{ + .value = "debug:colored_stdout_logs", + .description = "enables colors in the stdout logs.", + .type = CONFIG_OPTION_BOOL, + .data = SConfigOptionDescription::SBoolData{true}, + }, +}; \ No newline at end of file diff --git a/src/config/ConfigManager.cpp b/src/config/ConfigManager.cpp index 41d3871c..1856bd49 100644 --- a/src/config/ConfigManager.cpp +++ b/src/config/ConfigManager.cpp @@ -28,7 +28,9 @@ #include using namespace Hyprutils::String; -extern "C" char** environ; +extern "C" char** environ; + +#include "ConfigDescriptions.hpp" static Hyprlang::CParseResult configHandleGradientSet(const char* VALUE, void** data) { std::string V = VALUE; @@ -312,8 +314,6 @@ CConfigManager::CConfigManager() { configPaths.emplace_back(getMainConfigPath()); m_pConfig = std::make_unique(configPaths.begin()->c_str(), Hyprlang::SConfigOptions{.throwAllErrors = true, .allowMissingConfig = true}); - m_pConfig->addConfigValue("general:sensitivity", {1.0f}); - m_pConfig->addConfigValue("general:apply_sens_to_raw", Hyprlang::INT{0}); m_pConfig->addConfigValue("general:border_size", Hyprlang::INT{1}); m_pConfig->addConfigValue("general:no_border_on_floating", Hyprlang::INT{0}); m_pConfig->addConfigValue("general:border_part_of_window", Hyprlang::INT{1}); @@ -2607,3 +2607,60 @@ std::optional CConfigManager::handlePlugin(const std::string& comma return {}; } + +const std::vector& CConfigManager::getAllDescriptions() { + return CONFIG_OPTIONS; +} + +std::string SConfigOptionDescription::jsonify() const { + auto parseData = [this]() -> std::string { + return std::visit( + [](auto&& val) { + using T = std::decay_t; + if constexpr (std::is_same_v) { + return std::format(R"#( "value": "{}")#", val.value); + } else if constexpr (std::is_same_v) { + return std::format(R"#( "value": {}, + "min": {}, + "max": {})#", + val.value, val.min, val.max); + } else if constexpr (std::is_same_v) { + return std::format(R"#( "value": {}, + "min": {}, + "max": {})#", + val.value, val.min, val.max); + } else if constexpr (std::is_same_v) { + return std::format(R"#( "value": {})#", val.color.getAsHex()); + } else if constexpr (std::is_same_v) { + return std::format(R"#( "value": {})#", val.value); + } else if constexpr (std::is_same_v) { + return std::format(R"#( "value": {})#", val.choices); + } else if constexpr (std::is_same_v) { + return std::format(R"#( "x": {}, + "y": {}, + "min_x": {}, + "min_y": {}, + "max_x": {}, + "max_y": {})#", + val.vec.x, val.vec.y, val.min.x, val.min.y, val.max.x, val.max.y); + } else if constexpr (std::is_same_v) { + return std::format(R"#( "value": "{}")#", val.gradient); + } + return std::string{""}; + }, + data); + }; + + std::string json = std::format(R"#({{ + "value": "{}", + "description": "{}", + "type": {}, + "flags": {}, + "data": {{ + {} + }} +}})#", + value, description, (uint16_t)type, (uint32_t)flags, parseData()); + + return json; +} diff --git a/src/config/ConfigManager.hpp b/src/config/ConfigManager.hpp index 38dd0872..4241031b 100644 --- a/src/config/ConfigManager.hpp +++ b/src/config/ConfigManager.hpp @@ -83,6 +83,70 @@ struct SExecRequestedRule { uint64_t iPid = 0; }; +enum eConfigOptionType : uint16_t { + CONFIG_OPTION_BOOL = 0, + CONFIG_OPTION_INT = 1, /* e.g. 0/1/2*/ + CONFIG_OPTION_FLOAT = 2, + CONFIG_OPTION_STRING_SHORT = 3, /* e.g. "auto" */ + CONFIG_OPTION_STRING_LONG = 4, /* e.g. a command */ + CONFIG_OPTION_COLOR = 5, + CONFIG_OPTION_CHOICE = 6, /* e.g. "one", "two", "three" */ + CONFIG_OPTION_GRADIENT = 7, + CONFIG_OPTION_VECTOR = 8, +}; + +enum eConfigOptionFlags : uint32_t { + CONFIG_OPTION_FLAG_PERCENTAGE = (1 << 0), +}; + +struct SConfigOptionDescription { + + struct SBoolData { + bool value = false; + }; + + struct SRangeData { + int value = 0, min = 0, max = 2; + }; + + struct SFloatData { + float value = 0, min = 0, max = 100; + }; + + struct SStringData { + std::string value; + }; + + struct SColorData { + CColor color; + }; + + struct SChoiceData { + int firstIndex = 0; + std::string choices; // comma-separated + }; + + struct SGradientData { + std::string gradient; + }; + + struct SVectorData { + Vector2D vec, min, max; + }; + + std::string value; // e.g. general:gaps_in + std::string description; + std::string specialCategory; // if value is special (e.g. device:abc) value will be abc and special device + bool specialKey = false; + eConfigOptionType type = CONFIG_OPTION_BOOL; + uint32_t flags = 0; // eConfigOptionFlags + + std::string jsonify() const; + + // + std::variant data; +}; + class CConfigManager { public: CConfigManager(); @@ -115,6 +179,8 @@ class CConfigManager { std::vector getMatchingRules(PHLWINDOW, bool dynamic = true, bool shadowExec = false); std::vector getMatchingRules(PHLLS); + const std::vector& getAllDescriptions(); + std::unordered_map m_mAdditionalReservedAreas; std::unordered_map getAnimationConfig(); diff --git a/src/debug/HyprCtl.cpp b/src/debug/HyprCtl.cpp index 3ab0fa7a..717fb5c0 100644 --- a/src/debug/HyprCtl.cpp +++ b/src/debug/HyprCtl.cpp @@ -1561,6 +1561,21 @@ std::string getIsLocked(eHyprCtlOutputFormat format, std::string request) { return lockedStr; } +std::string getDescriptions(eHyprCtlOutputFormat format, std::string request) { + std::string json = "{"; + const auto& DESCS = g_pConfigManager->getAllDescriptions(); + + for (const auto& d : DESCS) { + json += d.jsonify() + ",\n"; + } + + json.pop_back(); + json.pop_back(); + + json += "}\n"; + return json; +} + CHyprCtl::CHyprCtl() { registerCommand(SHyprCtlCommand{"workspaces", true, workspacesRequest}); registerCommand(SHyprCtlCommand{"workspacerules", true, workspaceRulesRequest}); @@ -1581,6 +1596,7 @@ CHyprCtl::CHyprCtl() { registerCommand(SHyprCtlCommand{"layouts", true, layoutsRequest}); registerCommand(SHyprCtlCommand{"configerrors", true, configErrorsRequest}); registerCommand(SHyprCtlCommand{"locked", true, getIsLocked}); + registerCommand(SHyprCtlCommand{"descriptions", true, getDescriptions}); registerCommand(SHyprCtlCommand{"monitors", false, monitorsRequest}); registerCommand(SHyprCtlCommand{"reload", false, reloadRequest}); diff --git a/src/helpers/Color.cpp b/src/helpers/Color.cpp index 67526dc7..f9a207bb 100644 --- a/src/helpers/Color.cpp +++ b/src/helpers/Color.cpp @@ -21,6 +21,6 @@ CColor::CColor(uint64_t hex) { this->a = ALPHA(hex); } -uint32_t CColor::getAsHex() { +uint32_t CColor::getAsHex() const { return (uint32_t)(a * 255.f) * 0x1000000 + (uint32_t)(r * 255.f) * 0x10000 + (uint32_t)(g * 255.f) * 0x100 + (uint32_t)(b * 255.f) * 0x1; } \ No newline at end of file diff --git a/src/helpers/Color.hpp b/src/helpers/Color.hpp index 7ec55b0d..8abfe748 100644 --- a/src/helpers/Color.hpp +++ b/src/helpers/Color.hpp @@ -10,7 +10,7 @@ class CColor { float r = 0, g = 0, b = 0, a = 1.f; - uint32_t getAsHex(); + uint32_t getAsHex() const; CColor operator-(const CColor& c2) const { return CColor(r - c2.r, g - c2.g, b - c2.b, a - c2.a); diff --git a/src/managers/input/InputManager.cpp b/src/managers/input/InputManager.cpp index c502cb0d..069cdddb 100644 --- a/src/managers/input/InputManager.cpp +++ b/src/managers/input/InputManager.cpp @@ -82,18 +82,13 @@ CInputManager::~CInputManager() { } void CInputManager::onMouseMoved(IPointer::SMotionEvent e) { - static auto PSENS = CConfigValue("general:sensitivity"); - static auto PNOACCEL = CConfigValue("input:force_no_accel"); - static auto PSENSTORAW = CConfigValue("general:apply_sens_to_raw"); + static auto PNOACCEL = CConfigValue("input:force_no_accel"); const auto DELTA = *PNOACCEL == 1 ? e.unaccel : e.delta; - if (*PSENSTORAW == 1) - PROTO::relativePointer->sendRelativeMotion((uint64_t)e.timeMs * 1000, DELTA * *PSENS, e.unaccel * *PSENS); - else - PROTO::relativePointer->sendRelativeMotion((uint64_t)e.timeMs * 1000, DELTA, e.unaccel); + PROTO::relativePointer->sendRelativeMotion((uint64_t)e.timeMs * 1000, DELTA, e.unaccel); - g_pPointerManager->move(DELTA * *PSENS); + g_pPointerManager->move(DELTA); mouseMoveUnified(e.timeMs); From 912e7ba82defdb10efc892a5db578598c972fe4a Mon Sep 17 00:00:00 2001 From: vaxerski Date: Sat, 17 Aug 2024 19:27:11 +0200 Subject: [PATCH 0282/2181] render: fixup format mismatch after leaving DS fixes #7373 --- src/debug/HyprCtl.cpp | 20 ++++++++++---------- src/helpers/Monitor.cpp | 2 +- src/helpers/Monitor.hpp | 1 + src/render/Renderer.cpp | 4 ++++ 4 files changed, 16 insertions(+), 11 deletions(-) diff --git a/src/debug/HyprCtl.cpp b/src/debug/HyprCtl.cpp index 717fb5c0..78c8504a 100644 --- a/src/debug/HyprCtl.cpp +++ b/src/debug/HyprCtl.cpp @@ -158,16 +158,16 @@ std::string monitorsRequest(eHyprCtlOutputFormat format, std::string request) { if (!m->output || m->ID == -1) continue; - result += - std::format("Monitor {} (ID {}):\n\t{}x{}@{:.5f} at {}x{}\n\tdescription: {}\n\tmake: {}\n\tmodel: {}\n\tserial: {}\n\tactive workspace: {} ({})\n\t" - "special workspace: {} ({})\n\treserved: {} {} {} {}\n\tscale: {:.2f}\n\ttransform: {}\n\tfocused: {}\n\t" - "dpmsStatus: {}\n\tvrr: {}\n\tactivelyTearing: {}\n\tdisabled: {}\n\tcurrentFormat: {}\n\tavailableModes: {}\n\n", - m->szName, m->ID, (int)m->vecPixelSize.x, (int)m->vecPixelSize.y, m->refreshRate, (int)m->vecPosition.x, (int)m->vecPosition.y, m->szShortDescription, - m->output->make, m->output->model, m->output->serial, m->activeWorkspaceID(), (!m->activeWorkspace ? "" : m->activeWorkspace->m_szName), - m->activeSpecialWorkspaceID(), (m->activeSpecialWorkspace ? m->activeSpecialWorkspace->m_szName : ""), (int)m->vecReservedTopLeft.x, - (int)m->vecReservedTopLeft.y, (int)m->vecReservedBottomRight.x, (int)m->vecReservedBottomRight.y, m->scale, (int)m->transform, - (m == g_pCompositor->m_pLastMonitor ? "yes" : "no"), (int)m->dpmsStatus, (int)(m->output->state ? m->output->state->state().adaptiveSync : false), - m->tearingState.activelyTearing, !m->m_bEnabled, formatToString(m->output->state->state().drmFormat), availableModesForOutput(m.get(), format)); + result += std::format( + "Monitor {} (ID {}):\n\t{}x{}@{:.5f} at {}x{}\n\tdescription: {}\n\tmake: {}\n\tmodel: {}\n\tserial: {}\n\tactive workspace: {} ({})\n\t" + "special workspace: {} ({})\n\treserved: {} {} {} {}\n\tscale: {:.2f}\n\ttransform: {}\n\tfocused: {}\n\t" + "dpmsStatus: {}\n\tvrr: {}\n\tactivelyTearing: {}\n\tdisabled: {}\n\tcurrentFormat: A {} H {}\n\tavailableModes: {}\n\n", + m->szName, m->ID, (int)m->vecPixelSize.x, (int)m->vecPixelSize.y, m->refreshRate, (int)m->vecPosition.x, (int)m->vecPosition.y, m->szShortDescription, + m->output->make, m->output->model, m->output->serial, m->activeWorkspaceID(), (!m->activeWorkspace ? "" : m->activeWorkspace->m_szName), + m->activeSpecialWorkspaceID(), (m->activeSpecialWorkspace ? m->activeSpecialWorkspace->m_szName : ""), (int)m->vecReservedTopLeft.x, (int)m->vecReservedTopLeft.y, + (int)m->vecReservedBottomRight.x, (int)m->vecReservedBottomRight.y, m->scale, (int)m->transform, (m == g_pCompositor->m_pLastMonitor ? "yes" : "no"), + (int)m->dpmsStatus, (int)(m->output->state ? m->output->state->state().adaptiveSync : false), m->tearingState.activelyTearing, !m->m_bEnabled, + formatToString(m->output->state->state().drmFormat), formatToString(m->drmFormat), availableModesForOutput(m.get(), format)); } } diff --git a/src/helpers/Monitor.cpp b/src/helpers/Monitor.cpp index f6b61d57..9542d2c4 100644 --- a/src/helpers/Monitor.cpp +++ b/src/helpers/Monitor.cpp @@ -946,7 +946,7 @@ bool CMonitorState::updateSwapchain() { Debug::log(WARN, "updateSwapchain: No mode?"); return true; } - options.format = STATE.drmFormat; + options.format = m_pOwner->drmFormat; options.scanout = true; options.length = 2; options.size = MODE->pixelSize; diff --git a/src/helpers/Monitor.hpp b/src/helpers/Monitor.hpp index 7429ecf1..dcfcb63b 100644 --- a/src/helpers/Monitor.hpp +++ b/src/helpers/Monitor.hpp @@ -100,6 +100,7 @@ class CMonitor { std::optional forceSize; SP currentMode; SP cursorSwapchain; + uint32_t drmFormat = DRM_FORMAT_INVALID; bool dpmsStatus = true; bool vrrActive = false; // this can be TRUE even if VRR is not active in the case that this display does not support it. diff --git a/src/render/Renderer.cpp b/src/render/Renderer.cpp index 6bf6a761..b363c287 100644 --- a/src/render/Renderer.cpp +++ b/src/render/Renderer.cpp @@ -1207,6 +1207,9 @@ void CHyprRenderer::renderMonitor(CMonitor* pMonitor) { } else if (!pMonitor->lastScanout.expired()) { Debug::log(LOG, "Left a direct scanout."); pMonitor->lastScanout.reset(); + + // reset DRM format, make sure it's the one we want. + pMonitor->output->state->setFormat(pMonitor->drmFormat); } } @@ -2155,6 +2158,7 @@ bool CHyprRenderer::applyMonitorRule(CMonitor* pMonitor, SMonitorRule* pMonitorR for (auto& fmt : formats[(int)!RULE->enable10bit]) { pMonitor->output->state->setFormat(fmt.second); + pMonitor->drmFormat = fmt.second; if (!pMonitor->state.test()) { Debug::log(ERR, "output {} failed basic test on format {}", pMonitor->szName, fmt.first); From d21a6b12b8983bba8745a62fd595a1dbee882012 Mon Sep 17 00:00:00 2001 From: leiserfg Date: Sun, 18 Aug 2024 08:43:30 +0200 Subject: [PATCH 0283/2181] Update aquamarine input in flake --- flake.lock | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/flake.lock b/flake.lock index b4868793..c70d31d1 100644 --- a/flake.lock +++ b/flake.lock @@ -16,11 +16,11 @@ ] }, "locked": { - "lastModified": 1723405438, - "narHash": "sha256-bpmC2m7OhlDvqgQZdZ2jBLyeIkq/Jld3X4bqRAxBSp8=", + "lastModified": 1723920171, + "narHash": "sha256-dVCMrAe+D/5S91erhwQj2DSzHOVzAanWqoy+vPWB9DY=", "owner": "hyprwm", "repo": "aquamarine", - "rev": "9312aa28271c91e5d67ecb9def527b2bbcff0e66", + "rev": "71d49670fe246cdaff4860b0effba0ab9f163b72", "type": "github" }, "original": { From b2a18aa80a29ecf400ae1e8c964d4313f7223bf5 Mon Sep 17 00:00:00 2001 From: Sami Liedes Date: Sun, 18 Aug 2024 10:14:42 +0300 Subject: [PATCH 0284/2181] input: Fix disabling tap-to-click (#7304) * Allow disabling tap-to-click * Style fix --- src/managers/input/InputManager.cpp | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/managers/input/InputManager.cpp b/src/managers/input/InputManager.cpp index 069cdddb..e5f921a2 100644 --- a/src/managers/input/InputManager.cpp +++ b/src/managers/input/InputManager.cpp @@ -1107,8 +1107,9 @@ void CInputManager::setPointerConfigs() { libinput_device_config_tap_set_drag_lock_enabled(LIBINPUTDEV, LIBINPUT_CONFIG_DRAG_LOCK_ENABLED); if (libinput_device_config_tap_get_finger_count(LIBINPUTDEV)) // this is for tapping (like on a laptop) - if (g_pConfigManager->getDeviceInt(devname, "tap-to-click", "input:touchpad:tap-to-click") == 1) - libinput_device_config_tap_set_enabled(LIBINPUTDEV, LIBINPUT_CONFIG_TAP_ENABLED); + libinput_device_config_tap_set_enabled(LIBINPUTDEV, + g_pConfigManager->getDeviceInt(devname, "tap-to-click", "input:touchpad:tap-to-click") == 1 ? LIBINPUT_CONFIG_TAP_ENABLED : + LIBINPUT_CONFIG_TAP_DISABLED); if (libinput_device_config_scroll_has_natural_scroll(LIBINPUTDEV)) { From 1006663b6eaa55149e9a21aa8a34e41c85eb08ca Mon Sep 17 00:00:00 2001 From: Tom Englund Date: Sun, 18 Aug 2024 10:23:27 +0200 Subject: [PATCH 0285/2181] shm: align size to stride (#7383) calculate the size to the stride we got to better align it. --- src/protocols/core/Shm.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/protocols/core/Shm.cpp b/src/protocols/core/Shm.cpp index 99459d9a..9996a607 100644 --- a/src/protocols/core/Shm.cpp +++ b/src/protocols/core/Shm.cpp @@ -63,7 +63,7 @@ Aquamarine::SSHMAttrs CWLSHMBuffer::shm() { } std::tuple CWLSHMBuffer::beginDataPtr(uint32_t flags) { - return {(uint8_t*)pool->data + offset, fmt, size.x * size.y * 4}; + return {(uint8_t*)pool->data + offset, fmt, stride * size.y}; } void CWLSHMBuffer::endDataPtr() { From 279ec1c291021479b050c83a0435ac7076c1aee0 Mon Sep 17 00:00:00 2001 From: vaxerski Date: Sun, 18 Aug 2024 19:51:54 +0200 Subject: [PATCH 0286/2181] linux-dmabuf: allow on split-node systems ref #7364 --- src/protocols/LinuxDMABUF.cpp | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/protocols/LinuxDMABUF.cpp b/src/protocols/LinuxDMABUF.cpp index 3cdb5b34..32625792 100644 --- a/src/protocols/LinuxDMABUF.cpp +++ b/src/protocols/LinuxDMABUF.cpp @@ -490,9 +490,8 @@ CLinuxDMABufV1Protocol::CLinuxDMABufV1Protocol(const wl_interface* iface, const return; } } else { - LOGM(ERR, "DRM device {} has no render node, disabling linux dmabuf", device->nodes[DRM_NODE_PRIMARY] ? device->nodes[DRM_NODE_PRIMARY] : "null"); + LOGM(ERR, "DRM device {} has no render node, disabling linux dmabuf checks", device->nodes[DRM_NODE_PRIMARY] ? device->nodes[DRM_NODE_PRIMARY] : "null"); drmFreeDevice(&device); - removeGlobal(); } }); } From 50348a3ddbb6bc3367300c9bba2ff682e4a356e3 Mon Sep 17 00:00:00 2001 From: vaxerski Date: Sun, 18 Aug 2024 20:19:13 +0200 Subject: [PATCH 0287/2181] renderer: pass custom modelines to aq ref #7390 --- src/render/Renderer.cpp | 14 +++----------- 1 file changed, 3 insertions(+), 11 deletions(-) diff --git a/src/render/Renderer.cpp b/src/render/Renderer.cpp index b363c287..c2ecbbf3 100644 --- a/src/render/Renderer.cpp +++ b/src/render/Renderer.cpp @@ -1994,17 +1994,9 @@ bool CHyprRenderer::applyMonitorRule(CMonitor* pMonitor, SMonitorRule* pMonitorR if (pMonitor->output->getBackend()->type() != Aquamarine::eBackendType::AQ_BACKEND_DRM) { Debug::log(ERR, "Tried to set custom modeline on non-DRM output"); fail = true; - } else { - // FIXME: - // auto* mode = wlr_drm_connector_add_mode(pMonitor->output, &RULE->drmMode); - // if (mode) { - // wlr_output_state_set_mode(pMonitor->state.wlr(), mode); - // pMonitor->customDrmMode = RULE->drmMode; - // } else { - // Debug::log(ERR, "wlr_drm_connector_add_mode failed"); - // fail = true; - // } - } + } else + pMonitor->output->state->setCustomMode(makeShared( + Aquamarine::SOutputMode{.pixelSize = {RULE->drmMode.hdisplay, RULE->drmMode.vdisplay}, .refreshRate = RULE->drmMode.vrefresh, .modeInfo = RULE->drmMode})); } else pMonitor->output->state->setCustomMode(makeShared(Aquamarine::SOutputMode{.pixelSize = RULE->resolution, .refreshRate = WLRREFRESHRATE})); From 5afc4dc42e2409da62b7bcdf0ead90329e8d7a92 Mon Sep 17 00:00:00 2001 From: Tom Englund Date: Sun, 18 Aug 2024 21:02:46 +0200 Subject: [PATCH 0288/2181] compositor: update suspendstate on window move (#7396) hyprctl dispatch -- movetoworkspacesilent x,"^kitty$" where X is the current workspace makes kitty stops updating until current workspace is changed while it is on the screen. update the suspend state after it has been moved. --- src/Compositor.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/src/Compositor.cpp b/src/Compositor.cpp index 9d247a56..1437a653 100644 --- a/src/Compositor.cpp +++ b/src/Compositor.cpp @@ -2737,6 +2737,7 @@ void CCompositor::moveWindowToWorkspaceSafe(PHLWINDOW pWindow, PHLWORKSPACE pWor g_pCompositor->updateWorkspaceWindows(pWorkspace->m_iID); g_pCompositor->updateWorkspaceWindows(pWindow->workspaceID()); + g_pCompositor->updateSuspendedStates(); } PHLWINDOW CCompositor::getForceFocus() { From bf611fbbf3183e6f96529d79189be56189a46e1b Mon Sep 17 00:00:00 2001 From: vaxerski Date: Sun, 18 Aug 2024 22:40:21 +0200 Subject: [PATCH 0289/2181] screencopy: nuke unused stuff --- src/protocols/Screencopy.cpp | 11 ----------- 1 file changed, 11 deletions(-) diff --git a/src/protocols/Screencopy.cpp b/src/protocols/Screencopy.cpp index f246f6dd..8a7fd567 100644 --- a/src/protocols/Screencopy.cpp +++ b/src/protocols/Screencopy.cpp @@ -38,17 +38,6 @@ CScreencopyFrame::CScreencopyFrame(SP resource_, int32_t g_pHyprRenderer->makeEGLCurrent(); - if (g_pHyprOpenGL->m_mMonitorRenderResources.contains(pMonitor)) { - const auto& RDATA = g_pHyprOpenGL->m_mMonitorRenderResources.at(pMonitor); - // bind the fb for its format. Suppress gl errors. -#ifndef GLES2 - glBindFramebuffer(GL_READ_FRAMEBUFFER, RDATA.offloadFB.m_iFb); -#else - glBindFramebuffer(GL_FRAMEBUFFER, RDATA.offloadFB.m_iFb); -#endif - } else - LOGM(ERR, "No RDATA in screencopy???"); - shmFormat = g_pHyprOpenGL->getPreferredReadFormat(pMonitor); if (shmFormat == DRM_FORMAT_INVALID) { LOGM(ERR, "No format supported by renderer in capture output"); From fa12efdd2aae6851305245f16a801fb571fbe2c1 Mon Sep 17 00:00:00 2001 From: vaxerski Date: Sun, 18 Aug 2024 22:54:47 +0200 Subject: [PATCH 0290/2181] protocol: fix logm template checks --- src/protocols/WaylandProtocol.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/protocols/WaylandProtocol.hpp b/src/protocols/WaylandProtocol.hpp index 0fa8daab..87c75ed8 100644 --- a/src/protocols/WaylandProtocol.hpp +++ b/src/protocols/WaylandProtocol.hpp @@ -32,7 +32,7 @@ } else if (level == LOG || level == INFO || level == TRACE) { \ oss << "[" << EXTRACT_CLASS_NAME() << "] "; \ } \ - if constexpr (std::is_same_v) { \ + if constexpr (std::tuple_size::value == 1 && std::is_same_v) { \ oss << __VA_ARGS__; \ Debug::log(level, oss.str()); \ } else { \ From f4045ab8d032186b7c5409cd9f05eeaa813320ba Mon Sep 17 00:00:00 2001 From: vaxerski Date: Sun, 18 Aug 2024 22:57:21 +0200 Subject: [PATCH 0291/2181] screencopy: fix 10b format r/b flip --- src/protocols/Screencopy.cpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/protocols/Screencopy.cpp b/src/protocols/Screencopy.cpp index 8a7fd567..b25d9456 100644 --- a/src/protocols/Screencopy.cpp +++ b/src/protocols/Screencopy.cpp @@ -46,6 +46,10 @@ CScreencopyFrame::CScreencopyFrame(SP resource_, int32_t return; } + // TODO: hack, we can't bit flip so we'll format flip heh, GL_BGRA_EXT wont work here + if (shmFormat == DRM_FORMAT_XRGB2101010 || shmFormat == DRM_FORMAT_ARGB2101010) + shmFormat = DRM_FORMAT_XBGR2101010; + const auto PSHMINFO = FormatUtils::getPixelFormatFromDRM(shmFormat); if (!PSHMINFO) { LOGM(ERR, "No pixel format supported by renderer in capture output"); From 11dfb8397becca85cad078dd31bf043d1c40ceac Mon Sep 17 00:00:00 2001 From: diniamo Date: Sun, 18 Aug 2024 20:43:04 +0200 Subject: [PATCH 0292/2181] flake: update aquamarine --- flake.lock | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/flake.lock b/flake.lock index c70d31d1..97016819 100644 --- a/flake.lock +++ b/flake.lock @@ -16,11 +16,11 @@ ] }, "locked": { - "lastModified": 1723920171, - "narHash": "sha256-dVCMrAe+D/5S91erhwQj2DSzHOVzAanWqoy+vPWB9DY=", + "lastModified": 1724006173, + "narHash": "sha256-1ROh0buuxiMyc6eIb3CIbJsmYO7PhLqSYs55mOx1XTk=", "owner": "hyprwm", "repo": "aquamarine", - "rev": "71d49670fe246cdaff4860b0effba0ab9f163b72", + "rev": "7f8df01d4297b9068a9592400f16044602844f86", "type": "github" }, "original": { From 83d88fa56467a2b749fb2320e1595281107bd326 Mon Sep 17 00:00:00 2001 From: loseardes77 Date: Sun, 18 Aug 2024 22:25:23 +0200 Subject: [PATCH 0293/2181] hyprpm, hyprctl: update shell completions --- hyprctl/hyprctl.bash | 89 ++++++------ hyprctl/hyprctl.fish | 305 ++++++++++++++++++++++-------------------- hyprctl/hyprctl.usage | 20 ++- hyprctl/hyprctl.zsh | 271 ++++++++++++++++++++----------------- hyprpm/hyprpm.bash | 58 ++++---- hyprpm/hyprpm.fish | 85 ++++++------ hyprpm/hyprpm.usage | 4 +- hyprpm/hyprpm.zsh | 46 ++++--- 8 files changed, 471 insertions(+), 407 deletions(-) diff --git a/hyprctl/hyprctl.bash b/hyprctl/hyprctl.bash index c69cca21..e26e623e 100644 --- a/hyprctl/hyprctl.bash +++ b/hyprctl/hyprctl.bash @@ -1,17 +1,17 @@ -_hyprctl_cmd_2 () { +_hyprctl_cmd_1 () { hyprctl monitors | awk '/Monitor/{ print $2 }' } _hyprctl_cmd_3 () { - hyprpm list | awk '/Plugin/{ print $4 }' + hyprctl clients | awk '/class/{print $2}' +} + +_hyprctl_cmd_2 () { + hyprctl devices | sed -n '/Keyboard at/{n; s/^\s\+//; p}' } _hyprctl_cmd_0 () { - hyprctl clients | awk '/class/{ print $2 }' -} - -_hyprctl_cmd_1 () { - hyprctl devices | sed -n '/Keyboard at/{n; s/^\s\+//; p}' + hyprpm list | awk '/Plugin/{print $4}' } _hyprctl () { @@ -23,25 +23,25 @@ _hyprctl () { local words cword _get_comp_words_by_ref -n "$COMP_WORDBREAKS" words cword - local -a literals=("cyclenext" "globalshortcuts" "cursorpos" "bordersize" "renameworkspace" "animationstyle" "focuswindow" "0" "auto" "swapnext" "forceallowsinput" "moveactive" "activebordercolor" "alphafullscreen" "wayland" "layers" "minsize" "monitors" "1" "kill" "settiled" "3" "focusmonitor" "swapwindow" "moveoutofgroup" "notify" "movecursor" "setcursor" "seterror" "movecurrentworkspacetomonitor" "4" "nomaxsize" "forcenoanims" "setprop" "-i" "-q" "togglefloating" "workspacerules" "movetoworkspace" "disable" "setignoregrouplock" "workspaces" "movegroupwindow" "closewindow" "0" "--instance" "binds" "movewindow" "splitratio" "alpha" "denywindowfromgroup" "workspace" "configerrors" "togglegroup" "getoption" "forceopaque" "keepaspectratio" "killactive" "pass" "decorations" "devices" "focuscurrentorlast" "submap" "global" "alphafullscreenoverride" "forcerendererreload" "movewindowpixel" "headless" "version" "dpms" "resizeactive" "moveintogroup" "5" "alphaoverride" "setfloating" "rollinglog" "::=" "rounding" "layouts" "moveworkspacetomonitor" "exec" "alphainactiveoverride" "alterzorder" "fakefullscreen" "nofocus" "keyword" "forcenoborder" "forcenodim" "--quiet" "pin" "output" "forcenoblur" "togglespecialworkspace" "fullscreen" "toggleopaque" "focusworkspaceoncurrentmonitor" "next" "changegroupactive" "-j" "instances" "execr" "exit" "clients" "all" "--batch" "dismissnotify" "inactivebordercolor" "switchxkblayout" "movetoworkspacesilent" "tagwindow" "movewindoworgroup" "-r" "movefocus" "focusurgentorlast" "remove" "activeworkspace" "dispatch" "create" "centerwindow" "2" "hyprpaper" "-1" "reload" "alphainactive" "systeminfo" "plugin" "dimaround" "activewindow" "swapactiveworkspaces" "splash" "sendshortcut" "maxsize" "lockactivegroup" "windowdancecompat" "forceopaqueoverriden" "lockgroups" "movecursortocorner" "x11" "prev" "1" "resizewindowpixel" "forcenoshadow") - + declare -a literals=(resizeactive 2 changegroupactive -r moveintogroup forceallowsinput 4 ::= systeminfo all layouts setprop animationstyle switchxkblayout create denywindowfromgroup headless activebordercolor exec setcursor wayland focusurgentorlast workspacerules movecurrentworkspacetomonitor movetoworkspacesilent hyprpaper alpha inactivebordercolor movegroupwindow movecursortocorner movewindowpixel prev movewindow globalshortcuts clients dimaround setignoregrouplock splash execr monitors 0 forcenoborder -q animations 1 nomaxsize splitratio moveactive pass swapnext devices layers rounding lockactivegroup 5 moveworkspacetomonitor -f -i --quiet forcenodim pin 0 1 forceopaque forcenoshadow setfloating minsize alphaoverride sendshortcut workspaces cyclenext alterzorder togglegroup lockgroups bordersize dpms focuscurrentorlast -1 --batch notify remove instances 1 3 moveoutofgroup killactive 2 movetoworkspace movecursor configerrors closewindow swapwindow tagwindow forcerendererreload centerwindow auto focuswindow seterror nofocus alphafullscreen binds version -h togglespecialworkspace fullscreen windowdancecompat 0 keyword toggleopaque 3 --instance togglefloating renameworkspace alphafullscreenoverride activeworkspace x11 kill forceopaqueoverriden output global dispatch reload forcenoblur -j event --help disable -1 activewindow keepaspectratio dismissnotify focusmonitor movefocus plugin exit workspace fullscreenstate getoption alphainactiveoverride alphainactive decorations settiled config-only descriptions resizewindowpixel fakefullscreen rollinglog swapactiveworkspaces submap next movewindoworgroup cursorpos forcenoanims focusworkspaceoncurrentmonitor maxsize) declare -A literal_transitions - literal_transitions[0]="([105]=1 [75]=2 [33]=3 [35]=4 [1]=2 [2]=2 [78]=2 [107]=5 [37]=2 [111]=4 [41]=2 [46]=2 [115]=2 [85]=6 [116]=8 [52]=2 [88]=4 [54]=2 [90]=9 [120]=2 [122]=2 [124]=2 [15]=2 [59]=10 [60]=2 [17]=11 [125]=12 [19]=2 [127]=2 [129]=2 [25]=13 [68]=2 [98]=4 [99]=2 [27]=2 [28]=14 [102]=2 [104]=4)" - literal_transitions[3]="([73]=17 [13]=2 [32]=17 [55]=17 [56]=17 [91]=17 [106]=2 [123]=2 [77]=1 [16]=2 [126]=17 [3]=1 [5]=2 [64]=17 [131]=2 [133]=17 [81]=17 [134]=17 [84]=17 [31]=17 [49]=2 [12]=2 [86]=17 [10]=17 [87]=17 [141]=17)" - literal_transitions[7]="([105]=1 [75]=2 [33]=3 [1]=2 [2]=2 [78]=2 [107]=5 [37]=2 [41]=2 [46]=2 [115]=2 [85]=6 [116]=8 [52]=2 [54]=2 [90]=9 [120]=2 [122]=2 [124]=2 [15]=2 [59]=10 [60]=2 [17]=11 [125]=12 [19]=2 [127]=2 [129]=2 [25]=13 [68]=2 [99]=2 [27]=2 [28]=14 [102]=2)" - literal_transitions[8]="([101]=2 [130]=2 [132]=2 [0]=2 [74]=2 [36]=2 [108]=2 [109]=2 [38]=2 [110]=2 [4]=2 [79]=2 [40]=2 [80]=2 [113]=2 [6]=2 [42]=2 [43]=2 [82]=2 [83]=2 [47]=2 [48]=2 [9]=2 [50]=2 [51]=2 [53]=2 [11]=2 [112]=2 [89]=2 [118]=2 [57]=2 [92]=2 [58]=2 [93]=2 [94]=2 [61]=2 [62]=2 [128]=2 [95]=2 [63]=2 [20]=2 [97]=2 [22]=2 [23]=2 [65]=2 [66]=2 [135]=2 [136]=2 [24]=2 [26]=2 [69]=2 [100]=2 [70]=2 [140]=2 [29]=2 [71]=2)" - literal_transitions[9]="([117]=20 [114]=16)" - literal_transitions[11]="([103]=2)" - literal_transitions[13]="([21]=1 [119]=1 [30]=1 [139]=1 [121]=1 [44]=1 [72]=1)" - literal_transitions[14]="([39]=2)" - literal_transitions[15]="([138]=2 [96]=2)" - literal_transitions[17]="([18]=2 [7]=2)" - literal_transitions[18]="([76]=19)" - literal_transitions[19]="([34]=4 [45]=4)" - literal_transitions[20]="([8]=2 [67]=2 [14]=2 [137]=2)" - - declare -A match_anything_transitions - match_anything_transitions=([1]=2 [0]=7 [6]=2 [15]=2 [10]=2 [5]=15 [14]=18 [7]=7 [2]=18 [16]=2 [12]=2 [11]=18) + literal_transitions[0]="([120]=14 [43]=2 [125]=21 [81]=2 [3]=21 [51]=2 [50]=2 [128]=2 [89]=2 [58]=21 [8]=2 [10]=2 [11]=3 [130]=4 [13]=5 [97]=6 [101]=2 [102]=21 [133]=7 [100]=2 [137]=2 [22]=2 [19]=2 [140]=8 [25]=2 [143]=2 [107]=9 [146]=10 [69]=2 [33]=2 [34]=2 [78]=21 [114]=2 [37]=2 [151]=2 [116]=2 [121]=13 [123]=21 [39]=11 [42]=21 [79]=15 [118]=12)" + literal_transitions[1]="([81]=2 [51]=2 [50]=2 [128]=2 [8]=2 [89]=2 [10]=2 [11]=3 [130]=4 [13]=5 [97]=6 [101]=2 [133]=7 [100]=2 [22]=2 [19]=2 [137]=2 [140]=8 [25]=2 [143]=2 [107]=9 [146]=10 [69]=2 [33]=2 [34]=2 [114]=2 [37]=2 [151]=2 [116]=2 [39]=11 [118]=12 [121]=13 [120]=14 [79]=15 [43]=2)" + literal_transitions[3]="([139]=2 [63]=16 [64]=16 [45]=16 [105]=16 [27]=2 [26]=2 [52]=4 [5]=16 [66]=2 [67]=16 [129]=16 [113]=16 [12]=2 [74]=4 [99]=2 [35]=16 [152]=16 [98]=16 [59]=16 [117]=16 [41]=16 [17]=2 [138]=16 [154]=2 [122]=16)" + literal_transitions[6]="([126]=2)" + literal_transitions[10]="([56]=2)" + literal_transitions[11]="([9]=2)" + literal_transitions[12]="([14]=19 [80]=22)" + literal_transitions[13]="([142]=2)" + literal_transitions[14]="([0]=2 [84]=2 [2]=2 [85]=2 [4]=2 [87]=2 [88]=2 [90]=2 [91]=2 [92]=2 [93]=2 [94]=2 [96]=2 [15]=2 [18]=2 [103]=2 [21]=2 [104]=2 [23]=2 [24]=2 [28]=2 [29]=2 [30]=2 [108]=2 [111]=2 [32]=2 [112]=2 [36]=2 [38]=2 [119]=2 [124]=2 [46]=2 [47]=2 [48]=2 [49]=2 [53]=2 [55]=2 [131]=2 [132]=2 [134]=2 [135]=2 [60]=2 [136]=20 [141]=2 [65]=2 [144]=2 [145]=2 [68]=2 [147]=2 [70]=2 [71]=2 [72]=2 [73]=2 [148]=2 [75]=2 [76]=2 [150]=2 [153]=2)" + literal_transitions[15]="([86]=4 [6]=4 [109]=4 [61]=4 [77]=4 [54]=4 [62]=4)" + literal_transitions[16]="([40]=2 [44]=2)" + literal_transitions[17]="([7]=23)" + literal_transitions[18]="([31]=2 [149]=2)" + literal_transitions[19]="([95]=2 [16]=2 [115]=2 [20]=2)" + literal_transitions[20]="([106]=2 [82]=2 [127]=2 [1]=2 [83]=2)" + literal_transitions[23]="([57]=21 [110]=21)" + declare -A match_anything_transitions=([6]=17 [7]=2 [0]=1 [22]=2 [5]=18 [4]=2 [2]=17 [18]=2 [11]=17 [8]=2 [9]=2 [13]=17 [10]=17 [1]=1) declare -A subword_transitions local state=0 @@ -79,21 +79,9 @@ _hyprctl () { done + local -a matches=() + local prefix="${words[$cword]}" - - local shortest_suffix="$word" - for ((i=0; i < ${#COMP_WORDBREAKS}; i++)); do - local char="${COMP_WORDBREAKS:$i:1}" - local candidate="${word##*$char}" - if [[ ${#candidate} -lt ${#shortest_suffix} ]]; then - shortest_suffix=$candidate - fi - done - local superfluous_prefix="" - if [[ "$shortest_suffix" != "$word" ]]; then - local superfluous_prefix=${word%$shortest_suffix} - fi - if [[ -v "literal_transitions[$state]" ]]; then local state_transitions_initializer=${literal_transitions[$state]} declare -A state_transitions @@ -102,25 +90,38 @@ _hyprctl () { for literal_id in "${!state_transitions[@]}"; do local literal="${literals[$literal_id]}" if [[ $literal = "${prefix}"* ]]; then - local completion=${literal#"$superfluous_prefix"} - COMPREPLY+=("$completion ") + matches+=("$literal ") fi done fi declare -A commands - commands=([5]=1 [16]=2 [12]=3 [10]=0) + commands=([7]=0 [22]=1 [8]=3 [5]=2) if [[ -v "commands[$state]" ]]; then local command_id=${commands[$state]} local completions=() - mapfile -t completions < <(_hyprctl_cmd_${command_id} "$prefix" | cut -f1) + readarray -t completions < <(_hyprctl_cmd_${command_id} "$prefix" | cut -f1) for item in "${completions[@]}"; do if [[ $item = "${prefix}"* ]]; then - COMPREPLY+=("$item") + matches+=("$item") fi done fi + local shortest_suffix="$prefix" + for ((i=0; i < ${#COMP_WORDBREAKS}; i++)); do + local char="${COMP_WORDBREAKS:$i:1}" + local candidate=${prefix##*$char} + if [[ ${#candidate} -lt ${#shortest_suffix} ]]; then + shortest_suffix=$candidate + fi + done + local superfluous_prefix="" + if [[ "$shortest_suffix" != "$prefix" ]]; then + local superfluous_prefix=${prefix%$shortest_suffix} + fi + COMPREPLY=("${matches[@]#$superfluous_prefix}") + return 0 } diff --git a/hyprctl/hyprctl.fish b/hyprctl/hyprctl.fish index c5c03e49..11309416 100644 --- a/hyprctl/hyprctl.fish +++ b/hyprctl/hyprctl.fish @@ -1,21 +1,21 @@ -function _hyprctl_3 +function _hyprctl_2 set 1 $argv[1] hyprctl monitors | awk '/Monitor/{ print $2 }' end function _hyprctl_4 set 1 $argv[1] - hyprpm list | awk '/Plugin/{ print $4 }' + hyprctl clients | awk '/class/{print $2}' +end + +function _hyprctl_3 + set 1 $argv[1] + hyprctl devices | sed -n '/Keyboard at/{n; s/^\s\+//; p}' end function _hyprctl_1 set 1 $argv[1] - hyprctl clients | awk '/class/{ print $2 }' -end - -function _hyprctl_2 - set 1 $argv[1] - hyprctl devices | sed -n '/Keyboard at/{n; s/^\s\+//; p}' + hyprpm list | awk '/Plugin/{print $4}' end function _hyprctl @@ -29,145 +29,160 @@ function _hyprctl set COMP_CWORD (count $COMP_WORDS) end - set --local literals "cyclenext" "globalshortcuts" "cursorpos" "bordersize" "renameworkspace" "animationstyle" "focuswindow" "0" "auto" "swapnext" "forceallowsinput" "moveactive" "activebordercolor" "alphafullscreen" "wayland" "layers" "minsize" "monitors" "1" "kill" "settiled" "3" "focusmonitor" "swapwindow" "moveoutofgroup" "notify" "movecursor" "setcursor" "seterror" "movecurrentworkspacetomonitor" "4" "nomaxsize" "forcenoanims" "setprop" "-i" "-q" "togglefloating" "workspacerules" "movetoworkspace" "disable" "setignoregrouplock" "workspaces" "movegroupwindow" "closewindow" "0" "--instance" "binds" "movewindow" "splitratio" "alpha" "denywindowfromgroup" "workspace" "configerrors" "togglegroup" "getoption" "forceopaque" "keepaspectratio" "killactive" "pass" "decorations" "devices" "focuscurrentorlast" "submap" "global" "alphafullscreenoverride" "forcerendererreload" "movewindowpixel" "headless" "version" "dpms" "resizeactive" "moveintogroup" "5" "alphaoverride" "setfloating" "rollinglog" "::=" "rounding" "layouts" "moveworkspacetomonitor" "exec" "alphainactiveoverride" "alterzorder" "fakefullscreen" "nofocus" "keyword" "forcenoborder" "forcenodim" "--quiet" "pin" "output" "forcenoblur" "togglespecialworkspace" "fullscreen" "toggleopaque" "focusworkspaceoncurrentmonitor" "next" "changegroupactive" "-j" "instances" "execr" "exit" "clients" "all" "--batch" "dismissnotify" "inactivebordercolor" "switchxkblayout" "movetoworkspacesilent" "tagwindow" "movewindoworgroup" "-r" "movefocus" "focusurgentorlast" "remove" "activeworkspace" "dispatch" "create" "centerwindow" "2" "hyprpaper" "-1" "reload" "alphainactive" "systeminfo" "plugin" "dimaround" "activewindow" "swapactiveworkspaces" "splash" "sendshortcut" "maxsize" "lockactivegroup" "windowdancecompat" "forceopaqueoverriden" "lockgroups" "movecursortocorner" "x11" "prev" "1" "resizewindowpixel" "forcenoshadow" + set literals "resizeactive" "2" "changegroupactive" "-r" "moveintogroup" "forceallowsinput" "4" "::=" "systeminfo" "all" "layouts" "setprop" "animationstyle" "switchxkblayout" "create" "denywindowfromgroup" "headless" "activebordercolor" "exec" "setcursor" "wayland" "focusurgentorlast" "workspacerules" "movecurrentworkspacetomonitor" "movetoworkspacesilent" "hyprpaper" "alpha" "inactivebordercolor" "movegroupwindow" "movecursortocorner" "movewindowpixel" "prev" "movewindow" "globalshortcuts" "clients" "dimaround" "setignoregrouplock" "splash" "execr" "monitors" "0" "forcenoborder" "-q" "animations" "1" "nomaxsize" "splitratio" "moveactive" "pass" "swapnext" "devices" "layers" "rounding" "lockactivegroup" "5" "moveworkspacetomonitor" "-f" "-i" "--quiet" "forcenodim" "pin" "0" "1" "forceopaque" "forcenoshadow" "setfloating" "minsize" "alphaoverride" "sendshortcut" "workspaces" "cyclenext" "alterzorder" "togglegroup" "lockgroups" "bordersize" "dpms" "focuscurrentorlast" "-1" "--batch" "notify" "remove" "instances" "1" "3" "moveoutofgroup" "killactive" "2" "movetoworkspace" "movecursor" "configerrors" "closewindow" "swapwindow" "tagwindow" "forcerendererreload" "centerwindow" "auto" "focuswindow" "seterror" "nofocus" "alphafullscreen" "binds" "version" "-h" "togglespecialworkspace" "fullscreen" "windowdancecompat" "0" "keyword" "toggleopaque" "3" "--instance" "togglefloating" "renameworkspace" "alphafullscreenoverride" "activeworkspace" "x11" "kill" "forceopaqueoverriden" "output" "global" "dispatch" "reload" "forcenoblur" "-j" "event" "--help" "disable" "-1" "activewindow" "keepaspectratio" "dismissnotify" "focusmonitor" "movefocus" "plugin" "exit" "workspace" "fullscreenstate" "getoption" "alphainactiveoverride" "alphainactive" "decorations" "settiled" "config-only" "descriptions" "resizewindowpixel" "fakefullscreen" "rollinglog" "swapactiveworkspaces" "submap" "next" "movewindoworgroup" "cursorpos" "forcenoanims" "focusworkspaceoncurrentmonitor" "maxsize" - set --local descriptions - set descriptions[1] "Focus the next window on a workspace" - set descriptions[3] "Get the current cursor pos in global layout coordinates" - set descriptions[5] "Rename a workspace" - set descriptions[7] "Focus the first window matching" - set descriptions[10] "Swap the focused window with the next window" - set descriptions[12] "Move the active window" - set descriptions[16] "List the layers" - set descriptions[18] "List active outputs with their properties" - set descriptions[20] "Get into a kill mode, where you can kill an app by clicking on it" - set descriptions[21] "Set the current window's floating state to false" - set descriptions[22] "ERROR" - set descriptions[23] "Focus a monitor" - set descriptions[24] "Swap the active window with another window" - set descriptions[25] "Move the active window out of a group" - set descriptions[26] "Send a notification using the built-in Hyprland notification system" - set descriptions[27] "Move the cursor to a specified position" - set descriptions[28] "Set the cursor theme and reloads the cursor manager" - set descriptions[29] "Set the hyprctl error string" - set descriptions[30] "Move the active workspace to a monitor" - set descriptions[31] "CONFUSED" - set descriptions[34] "Set a property of a window" - set descriptions[35] "Specify the Hyprland instance" - set descriptions[36] "Disable output" - set descriptions[37] "Toggle the current window's floating state" - set descriptions[38] "Get the list of defined workspace rules" - set descriptions[39] "Move the focused window to a workspace" - set descriptions[41] "Temporarily enable or disable binds:ignore_group_lock" - set descriptions[42] "List all workspaces with their properties" - set descriptions[43] "Swap the active window with the next or previous in a group" - set descriptions[44] "Close a specified window" - set descriptions[45] "WARNING" - set descriptions[46] "Specify the Hyprland instance" - set descriptions[47] "List all registered binds" - set descriptions[48] "Move the active window in a direction or to a monitor" - set descriptions[49] "Change the split ratio" - set descriptions[51] "Prohibit the active window from becoming or being inserted into group" - set descriptions[52] "Change the workspace" - set descriptions[53] "List all current config parsing errors" - set descriptions[54] "Toggle the current active window into a group" - set descriptions[55] "Get the config option status (values)" - set descriptions[58] "Close the active window" - set descriptions[59] "Pass the key to a specified window" - set descriptions[60] "List all decorations and their info" - set descriptions[61] "List all connected keyboards and mice" - set descriptions[62] "Switch focus from current to previously focused window" - set descriptions[63] "Change the current mapping group" - set descriptions[64] "Execute a Global Shortcut using the GlobalShortcuts portal" - set descriptions[66] "Force the renderer to reload all resources and outputs" - set descriptions[67] "Move a selected window" - set descriptions[69] "Print the Hyprland version: flags, commit and branch of build" - set descriptions[70] "Set all monitors' DPMS status" - set descriptions[71] "Resize the active window" - set descriptions[72] "Move the active window into a group" - set descriptions[73] "OK" - set descriptions[75] "Set the current window's floating state to true" - set descriptions[76] "Print tail of the log" - set descriptions[79] "List all layouts available (including plugin ones)" - set descriptions[80] "Move a workspace to a monitor" - set descriptions[81] "Execute a shell command" - set descriptions[83] "Modify the window stack order of the active or specified window" - set descriptions[84] "Toggle the focused window's internal fullscreen state" - set descriptions[86] "Issue a keyword to call a config keyword dynamically" - set descriptions[89] "Disable output" - set descriptions[90] "Pin a window" - set descriptions[91] "Allows adding/removing fake outputs to a specific backend" - set descriptions[93] "Toggle a special workspace on/off" - set descriptions[94] "Toggle the focused window's fullscreen state" - set descriptions[95] "Toggle the current window to always be opaque" - set descriptions[96] "Focus the requested workspace" - set descriptions[98] "Switch to the next window in a group" - set descriptions[99] "Output in JSON format" - set descriptions[100] "List all running Hyprland instances and their info" - set descriptions[101] "Execute a raw shell command" - set descriptions[102] "Exit the compositor with no questions asked" - set descriptions[103] "List all windows with their properties" - set descriptions[105] "Execute a batch of commands separated by ;" - set descriptions[106] "Dismiss all or up to amount of notifications" - set descriptions[108] "Set the xkb layout index for a keyboard" - set descriptions[109] "Move window doesnt switch to the workspace" - set descriptions[110] "Apply a tag to the window" - set descriptions[111] "Behave as moveintogroup" - set descriptions[112] "Refresh state after issuing the command" - set descriptions[113] "Move the focus in a direction" - set descriptions[114] "Focus the urgent window or the last window" - set descriptions[116] "Get the active workspace name and its properties" - set descriptions[117] "Issue a dispatch to call a keybind dispatcher with an arg" - set descriptions[119] "Center the active window" - set descriptions[120] "HINT" - set descriptions[121] "Interact with hyprpaper if present" - set descriptions[122] "No Icon" - set descriptions[123] "Force reload the config" - set descriptions[125] "Print system info" - set descriptions[126] "Interact with a plugin" - set descriptions[128] "Get the active window name and its properties" - set descriptions[129] "Swap the active workspaces between two monitors" - set descriptions[130] "Print the current random splash" - set descriptions[131] "On shortcut X sends shortcut Y to a specified window" - set descriptions[133] "Lock the focused group" - set descriptions[136] "Lock the groups" - set descriptions[137] "Move the cursor to the corner of the active window" - set descriptions[140] "INFO" - set descriptions[141] "Resize a selected window" + set descriptions + set descriptions[1] "Resize the active window" + set descriptions[2] "Fullscreen" + set descriptions[3] "Switch to the next window in a group" + set descriptions[4] "Refresh state after issuing the command" + set descriptions[5] "Move the active window into a group" + set descriptions[7] "CONFUSED" + set descriptions[9] "Print system info" + set descriptions[11] "List all layouts available (including plugin ones)" + set descriptions[12] "Set a property of a window" + set descriptions[14] "Set the xkb layout index for a keyboard" + set descriptions[16] "Prohibit the active window from becoming or being inserted into group" + set descriptions[19] "Execute a shell command" + set descriptions[20] "Set the cursor theme and reloads the cursor manager" + set descriptions[22] "Focus the urgent window or the last window" + set descriptions[23] "Get the list of defined workspace rules" + set descriptions[24] "Move the active workspace to a monitor" + set descriptions[25] "Move window doesnt switch to the workspace" + set descriptions[26] "Interact with hyprpaper if present" + set descriptions[29] "Swap the active window with the next or previous in a group" + set descriptions[30] "Move the cursor to the corner of the active window" + set descriptions[31] "Move a selected window" + set descriptions[33] "Move the active window in a direction or to a monitor" + set descriptions[34] "Lists all global shortcuts" + set descriptions[35] "List all windows with their properties" + set descriptions[37] "Temporarily enable or disable binds:ignore_group_lock" + set descriptions[38] "Print the current random splash" + set descriptions[39] "Execute a raw shell command" + set descriptions[40] "List active outputs with their properties" + set descriptions[43] "Disable output" + set descriptions[44] "Gets the current config info about animations and beziers" + set descriptions[47] "Change the split ratio" + set descriptions[48] "Move the active window" + set descriptions[49] "Pass the key to a specified window" + set descriptions[50] "Swap the focused window with the next window" + set descriptions[51] "List all connected keyboards and mice" + set descriptions[52] "List the layers" + set descriptions[54] "Lock the focused group" + set descriptions[55] "OK" + set descriptions[56] "Move a workspace to a monitor" + set descriptions[58] "Specify the Hyprland instance" + set descriptions[59] "Disable output" + set descriptions[61] "Pin a window" + set descriptions[62] "WARNING" + set descriptions[63] "INFO" + set descriptions[66] "Set the current window's floating state to true" + set descriptions[69] "On shortcut X sends shortcut Y to a specified window" + set descriptions[70] "List all workspaces with their properties" + set descriptions[71] "Focus the next window on a workspace" + set descriptions[72] "Modify the window stack order of the active or specified window" + set descriptions[73] "Toggle the current active window into a group" + set descriptions[74] "Lock the groups" + set descriptions[76] "Set all monitors' DPMS status" + set descriptions[77] "Switch focus from current to previously focused window" + set descriptions[78] "No Icon" + set descriptions[79] "Execute a batch of commands separated by ;" + set descriptions[80] "Send a notification using the built-in Hyprland notification system" + set descriptions[82] "List all running Hyprland instances and their info" + set descriptions[83] "Maximize no fullscreen" + set descriptions[84] "Maximize and fullscreen" + set descriptions[85] "Move the active window out of a group" + set descriptions[86] "Close the active window" + set descriptions[87] "HINT" + set descriptions[88] "Move the focused window to a workspace" + set descriptions[89] "Move the cursor to a specified position" + set descriptions[90] "List all current config parsing errors" + set descriptions[91] "Close a specified window" + set descriptions[92] "Swap the active window with another window" + set descriptions[93] "Apply a tag to the window" + set descriptions[94] "Force the renderer to reload all resources and outputs" + set descriptions[95] "Center the active window" + set descriptions[97] "Focus the first window matching" + set descriptions[98] "Set the hyprctl error string" + set descriptions[101] "List all registered binds" + set descriptions[102] "Print the Hyprland version: flags, commit and branch of build" + set descriptions[103] "Prints the help message" + set descriptions[104] "Toggle a special workspace on/off" + set descriptions[105] "Toggle the focused window's fullscreen state" + set descriptions[107] "None" + set descriptions[108] "Issue a keyword to call a config keyword dynamically" + set descriptions[109] "Toggle the current window to always be opaque" + set descriptions[110] "ERROR" + set descriptions[111] "Specify the Hyprland instance" + set descriptions[112] "Toggle the current window's floating state" + set descriptions[113] "Rename a workspace" + set descriptions[115] "Get the active workspace name and its properties" + set descriptions[117] "Get into a kill mode, where you can kill an app by clicking on it" + set descriptions[119] "Allows adding/removing fake outputs to a specific backend" + set descriptions[120] "Execute a Global Shortcut using the GlobalShortcuts portal" + set descriptions[121] "Issue a dispatch to call a keybind dispatcher with an arg" + set descriptions[122] "Force reload the config" + set descriptions[124] "Output in JSON format" + set descriptions[125] "Emits a custom event to socket2" + set descriptions[126] "Prints the help message" + set descriptions[128] "Current" + set descriptions[129] "Get the active window name and its properties" + set descriptions[131] "Dismiss all or up to amount of notifications" + set descriptions[132] "Focus a monitor" + set descriptions[133] "Move the focus in a direction" + set descriptions[134] "Interact with a plugin" + set descriptions[135] "Exit the compositor with no questions asked" + set descriptions[136] "Change the workspace" + set descriptions[137] "Sets the focused window’s fullscreen mode and the one sent to the client" + set descriptions[138] "Get the config option status (values)" + set descriptions[141] "List all decorations and their info" + set descriptions[142] "Set the current window's floating state to false" + set descriptions[144] "Return a parsable JSON with all the config options, descriptions, value types and ranges" + set descriptions[145] "Resize a selected window" + set descriptions[146] "Toggle the focused window's internal fullscreen state" + set descriptions[147] "Print tail of the log" + set descriptions[148] "Swap the active workspaces between two monitors" + set descriptions[149] "Change the current mapping group" + set descriptions[151] "Behave as moveintogroup" + set descriptions[152] "Get the current cursor pos in global layout coordinates" + set descriptions[154] "Focus the requested workspace" - set --local literal_transitions - set literal_transitions[1] "set inputs 106 76 34 36 2 3 79 108 38 112 42 47 116 86 117 53 89 55 91 121 123 125 16 60 61 18 126 20 128 130 26 69 99 100 28 29 103 105; set tos 2 3 4 5 3 3 3 6 3 5 3 3 3 7 9 3 5 3 10 3 3 3 3 11 3 12 13 3 3 3 14 3 5 3 3 15 3 5" - set literal_transitions[4] "set inputs 74 14 33 56 57 92 107 124 78 17 127 4 6 65 132 134 82 135 85 32 50 13 87 11 88 142; set tos 18 3 18 18 18 18 3 3 2 3 18 2 3 18 3 18 18 18 18 18 3 3 18 18 18 18" - set literal_transitions[8] "set inputs 106 76 34 2 3 79 108 38 42 47 116 86 117 53 55 91 121 123 125 16 60 61 18 126 20 128 130 26 69 100 28 29 103; set tos 2 3 4 3 3 3 6 3 3 3 3 7 9 3 3 10 3 3 3 3 11 3 12 13 3 3 3 14 3 3 3 15 3" - set literal_transitions[9] "set inputs 102 131 133 1 75 37 109 110 39 111 5 80 41 81 114 7 43 44 83 84 48 49 10 51 52 54 12 113 90 119 58 93 59 94 95 62 63 129 96 64 21 98 23 24 66 67 136 137 25 27 70 101 71 141 30 72; set tos 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3" - set literal_transitions[10] "set inputs 118 115; set tos 21 17" - set literal_transitions[12] "set inputs 104; set tos 3" - set literal_transitions[14] "set inputs 22 120 31 140 122 45 73; set tos 2 2 2 2 2 2 2" - set literal_transitions[15] "set inputs 40; set tos 3" - set literal_transitions[16] "set inputs 139 97; set tos 3 3" - set literal_transitions[18] "set inputs 19 8; set tos 3 3" - set literal_transitions[19] "set inputs 77; set tos 20" - set literal_transitions[20] "set inputs 35 46; set tos 5 5" - set literal_transitions[21] "set inputs 9 68 15 138; set tos 3 3 3 3" + set literal_transitions + set literal_transitions[1] "set inputs 121 44 126 82 4 52 51 129 90 59 9 11 12 131 14 98 102 103 134 101 138 23 20 141 26 144 108 147 70 34 35 79 115 38 152 117 122 124 40 43 80 119; set tos 15 3 22 3 22 3 3 3 3 22 3 3 4 5 6 7 3 22 8 3 3 3 3 9 3 3 10 11 3 3 3 22 3 3 3 3 14 22 12 22 16 13" + set literal_transitions[2] "set inputs 82 52 51 129 9 90 11 12 131 14 98 102 134 101 23 20 138 141 26 144 108 147 70 34 35 115 38 152 117 40 119 122 121 80 44; set tos 3 3 3 3 3 3 3 4 5 6 7 3 8 3 3 3 3 9 3 3 10 11 3 3 3 3 3 3 3 12 13 14 15 16 3" + set literal_transitions[4] "set inputs 140 64 65 46 106 28 27 53 6 67 68 130 114 13 75 100 36 153 99 60 118 42 18 139 155 123; set tos 3 17 17 17 17 3 3 5 17 3 17 17 17 3 5 3 17 17 17 17 17 17 3 17 3 17" + set literal_transitions[7] "set inputs 127; set tos 3" + set literal_transitions[11] "set inputs 57; set tos 3" + set literal_transitions[12] "set inputs 10; set tos 3" + set literal_transitions[13] "set inputs 15 81; set tos 20 23" + set literal_transitions[14] "set inputs 143; set tos 3" + set literal_transitions[15] "set inputs 1 85 3 86 5 88 89 91 92 93 94 95 97 16 19 104 22 105 24 25 29 30 31 109 112 33 113 37 39 120 125 47 48 49 50 54 56 132 133 135 136 61 137 142 66 145 146 69 148 71 72 73 74 149 76 77 151 154; set tos 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 21 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3" + set literal_transitions[16] "set inputs 87 7 110 62 78 55 63; set tos 5 5 5 5 5 5 5" + set literal_transitions[17] "set inputs 41 45; set tos 3 3" + set literal_transitions[18] "set inputs 8; set tos 24" + set literal_transitions[19] "set inputs 32 150; set tos 3 3" + set literal_transitions[20] "set inputs 96 17 116 21; set tos 3 3 3 3" + set literal_transitions[21] "set inputs 107 83 128 2 84; set tos 3 3 3 3 3" + set literal_transitions[24] "set inputs 58 111; set tos 22 22" - set --local match_anything_transitions_from 2 1 7 16 11 6 15 8 3 17 13 12 - set --local match_anything_transitions_to 3 8 3 3 3 16 19 8 19 3 3 19 + set match_anything_transitions_from 7 8 1 23 6 5 3 19 12 9 10 14 11 2 + set match_anything_transitions_to 18 3 2 3 19 3 18 3 18 3 3 18 18 2 - set --local state 1 - set --local word_index 2 + set state 1 + set word_index 2 while test $word_index -lt $COMP_CWORD - set --local -- word $COMP_WORDS[$word_index] + set -- word $COMP_WORDS[$word_index] if set --query literal_transitions[$state] && test -n $literal_transitions[$state] - set --local --erase inputs - set --local --erase tos + set --erase inputs + set --erase tos eval $literal_transitions[$state] if contains -- $word $literals - set --local literal_matched 0 + set literal_matched 0 for literal_id in (seq 1 (count $literals)) if test $literals[$literal_id] = $word - set --local index (contains --index -- $literal_id $inputs) + set index (contains --index -- $literal_id $inputs) set state $tos[$index] set word_index (math $word_index + 1) set literal_matched 1 @@ -181,7 +196,7 @@ function _hyprctl end if set --query match_anything_transitions_from[$state] && test -n $match_anything_transitions_from[$state] - set --local index (contains --index -- $state $match_anything_transitions_from) + set index (contains --index -- $state $match_anything_transitions_from) set state $match_anything_transitions_to[$index] set word_index (math $word_index + 1) continue @@ -191,8 +206,8 @@ function _hyprctl end if set --query literal_transitions[$state] && test -n $literal_transitions[$state] - set --local --erase inputs - set --local --erase tos + set --erase inputs + set --erase tos eval $literal_transitions[$state] for literal_id in $inputs if test -n $descriptions[$literal_id] @@ -203,14 +218,14 @@ function _hyprctl end end - set command_states 6 17 13 11 - set command_ids 2 3 4 1 + set command_states 8 23 9 6 + set command_ids 1 2 4 3 if contains $state $command_states - set --local index (contains --index $state $command_states) - set --local function_id $command_ids[$index] - set --local function_name _hyprctl_$function_id - set --local --erase inputs - set --local --erase tos + set index (contains --index $state $command_states) + set function_id $command_ids[$index] + set function_name _hyprctl_$function_id + set --erase inputs + set --erase tos $function_name "$COMP_WORDS[$COMP_CWORD]" end diff --git a/hyprctl/hyprctl.usage b/hyprctl/hyprctl.usage index 298d253e..b2c55682 100644 --- a/hyprctl/hyprctl.usage +++ b/hyprctl/hyprctl.usage @@ -2,13 +2,14 @@ # Repo: https://github.com/adaszko/complgen # Generate completion scripts: "complgen aot --bash-script hyprctl.bash --fish-script hyprctl.fish --zsh-script hyprctl.zsh ./hyprctl.usage" -hyprctl []... +hyprctl []... ::= (-i | --instance) "Specify the Hyprland instance" | (-j) "Output in JSON format" | (-r) "Refresh state after issuing the command" | (--batch) "Execute a batch of commands separated by ;" | (-q | --quiet) "Disable output" + | (-h | --help) "Prints the help message" ; ::= {{{ hyprctl clients | awk '/class/{print $2}' }}}; @@ -59,16 +60,18 @@ hyprctl []... ::= (activewindow) "Get the active window name and its properties" | (activeworkspace) "Get the active workspace name and its properties" + | (animations) "Gets the current config info about animations and beziers" | (binds) "List all registered binds" | (clients) "List all windows with their properties" | (configerrors) "List all current config parsing errors" | (cursorpos) "Get the current cursor pos in global layout coordinates" | (decorations ) "List all decorations and their info" + | (descriptions) "Return a parsable JSON with all the config options, descriptions, value types and ranges" | (devices) "List all connected keyboards and mice" | (dismissnotify ) "Dismiss all or up to amount of notifications" | (dispatch ) "Issue a dispatch to call a keybind dispatcher with an arg" | (getoption) "Get the config option status (values)" - | (globalshortcuts) "" + | (globalshortcuts) "Lists all global shortcuts" | (hyprpaper) "Interact with hyprpaper if present" | (instances) "List all running Hyprland instances and their info" | (keyword ) "Issue a keyword to call a config keyword dynamically" @@ -79,8 +82,8 @@ hyprctl []... | (notify ) "Send a notification using the built-in Hyprland notification system" | (output (create (wayland | x11 | headless | auto) | remove )) "Allows adding/removing fake outputs to a specific backend" | (plugin ) "Interact with a plugin" - | (reload) "Force reload the config" - | (rollinglog) "Print tail of the log" + | (reload [config-only]) "Force reload the config" + | (rollinglog [-f]) "Print tail of the log" | (setcursor) "Set the cursor theme and reloads the cursor manager" | (seterror [disable]) "Set the hyprctl error string" | (setprop ) "Set a property of a window" @@ -92,6 +95,13 @@ hyprctl []... | (workspaces) "List all workspaces with their properties" ; + ::= (-1) "Current" + | (0) "None" + | (1) "Maximize no fullscreen" + | (2) "Fullscreen" + | (3) "Maximize and fullscreen" + ; + ::= (exec) "Execute a shell command" | (execr) "Execute a raw shell command" | (pass) "Pass the key to a specified window" @@ -106,6 +116,7 @@ hyprctl []... | (settiled) "Set the current window's floating state to false" | (fullscreen) "Toggle the focused window's fullscreen state" | (fakefullscreen) "Toggle the focused window's internal fullscreen state" + | (fullscreenstate ) "Sets the focused window’s fullscreen mode and the one sent to the client" | (dpms) "Set all monitors' DPMS status" | (pin) "Pin a window" | (movefocus) "Move the focus in a direction" @@ -148,4 +159,5 @@ hyprctl []... | (setignoregrouplock) "Temporarily enable or disable binds:ignore_group_lock" | (global) "Execute a Global Shortcut using the GlobalShortcuts portal" | (submap) "Change the current mapping group" + | (event) "Emits a custom event to socket2" ; diff --git a/hyprctl/hyprctl.zsh b/hyprctl/hyprctl.zsh index aeac9663..9a858100 100644 --- a/hyprctl/hyprctl.zsh +++ b/hyprctl/hyprctl.zsh @@ -1,145 +1,160 @@ #compdef hyprctl -_hyprctl_cmd_2 () { +_hyprctl_cmd_1 () { hyprctl monitors | awk '/Monitor/{ print $2 }' } _hyprctl_cmd_3 () { - hyprpm list | awk '/Plugin/{ print $4 }' + hyprctl clients | awk '/class/{print $2}' } -_hyprctl_cmd_0 () { - hyprctl clients | awk '/class/{ print $2 }' -} - -_hyprctl_cmd_1 () { +_hyprctl_cmd_2 () { hyprctl devices | sed -n '/Keyboard at/{n; s/^\s\+//; p}' } +_hyprctl_cmd_0 () { + hyprpm list | awk '/Plugin/{print $4}' +} + _hyprctl () { - local -a literals=("cyclenext" "globalshortcuts" "cursorpos" "bordersize" "renameworkspace" "animationstyle" "focuswindow" "0" "auto" "swapnext" "forceallowsinput" "moveactive" "activebordercolor" "alphafullscreen" "wayland" "layers" "minsize" "monitors" "1" "kill" "settiled" "3" "focusmonitor" "swapwindow" "moveoutofgroup" "notify" "movecursor" "setcursor" "seterror" "movecurrentworkspacetomonitor" "4" "nomaxsize" "forcenoanims" "setprop" "-i" "-q" "togglefloating" "workspacerules" "movetoworkspace" "disable" "setignoregrouplock" "workspaces" "movegroupwindow" "closewindow" "0" "--instance" "binds" "movewindow" "splitratio" "alpha" "denywindowfromgroup" "workspace" "configerrors" "togglegroup" "getoption" "forceopaque" "keepaspectratio" "killactive" "pass" "decorations" "devices" "focuscurrentorlast" "submap" "global" "alphafullscreenoverride" "forcerendererreload" "movewindowpixel" "headless" "version" "dpms" "resizeactive" "moveintogroup" "5" "alphaoverride" "setfloating" "rollinglog" "::=" "rounding" "layouts" "moveworkspacetomonitor" "exec" "alphainactiveoverride" "alterzorder" "fakefullscreen" "nofocus" "keyword" "forcenoborder" "forcenodim" "--quiet" "pin" "output" "forcenoblur" "togglespecialworkspace" "fullscreen" "toggleopaque" "focusworkspaceoncurrentmonitor" "next" "changegroupactive" "-j" "instances" "execr" "exit" "clients" "all" "--batch" "dismissnotify" "inactivebordercolor" "switchxkblayout" "movetoworkspacesilent" "tagwindow" "movewindoworgroup" "-r" "movefocus" "focusurgentorlast" "remove" "activeworkspace" "dispatch" "create" "centerwindow" "2" "hyprpaper" "-1" "reload" "alphainactive" "systeminfo" "plugin" "dimaround" "activewindow" "swapactiveworkspaces" "splash" "sendshortcut" "maxsize" "lockactivegroup" "windowdancecompat" "forceopaqueoverriden" "lockgroups" "movecursortocorner" "x11" "prev" "1" "resizewindowpixel" "forcenoshadow") + local -a literals=("resizeactive" "2" "changegroupactive" "-r" "moveintogroup" "forceallowsinput" "4" "::=" "systeminfo" "all" "layouts" "setprop" "animationstyle" "switchxkblayout" "create" "denywindowfromgroup" "headless" "activebordercolor" "exec" "setcursor" "wayland" "focusurgentorlast" "workspacerules" "movecurrentworkspacetomonitor" "movetoworkspacesilent" "hyprpaper" "alpha" "inactivebordercolor" "movegroupwindow" "movecursortocorner" "movewindowpixel" "prev" "movewindow" "globalshortcuts" "clients" "dimaround" "setignoregrouplock" "splash" "execr" "monitors" "0" "forcenoborder" "-q" "animations" "1" "nomaxsize" "splitratio" "moveactive" "pass" "swapnext" "devices" "layers" "rounding" "lockactivegroup" "5" "moveworkspacetomonitor" "-f" "-i" "--quiet" "forcenodim" "pin" "0" "1" "forceopaque" "forcenoshadow" "setfloating" "minsize" "alphaoverride" "sendshortcut" "workspaces" "cyclenext" "alterzorder" "togglegroup" "lockgroups" "bordersize" "dpms" "focuscurrentorlast" "-1" "--batch" "notify" "remove" "instances" "1" "3" "moveoutofgroup" "killactive" "2" "movetoworkspace" "movecursor" "configerrors" "closewindow" "swapwindow" "tagwindow" "forcerendererreload" "centerwindow" "auto" "focuswindow" "seterror" "nofocus" "alphafullscreen" "binds" "version" "-h" "togglespecialworkspace" "fullscreen" "windowdancecompat" "0" "keyword" "toggleopaque" "3" "--instance" "togglefloating" "renameworkspace" "alphafullscreenoverride" "activeworkspace" "x11" "kill" "forceopaqueoverriden" "output" "global" "dispatch" "reload" "forcenoblur" "-j" "event" "--help" "disable" "-1" "activewindow" "keepaspectratio" "dismissnotify" "focusmonitor" "movefocus" "plugin" "exit" "workspace" "fullscreenstate" "getoption" "alphainactiveoverride" "alphainactive" "decorations" "settiled" "config-only" "descriptions" "resizewindowpixel" "fakefullscreen" "rollinglog" "swapactiveworkspaces" "submap" "next" "movewindoworgroup" "cursorpos" "forcenoanims" "focusworkspaceoncurrentmonitor" "maxsize") local -A descriptions - descriptions[1]="Focus the next window on a workspace" - descriptions[3]="Get the current cursor pos in global layout coordinates" - descriptions[5]="Rename a workspace" - descriptions[7]="Focus the first window matching" - descriptions[10]="Swap the focused window with the next window" - descriptions[12]="Move the active window" - descriptions[16]="List the layers" - descriptions[18]="List active outputs with their properties" - descriptions[20]="Get into a kill mode, where you can kill an app by clicking on it" - descriptions[21]="Set the current window's floating state to false" - descriptions[22]="ERROR" - descriptions[23]="Focus a monitor" - descriptions[24]="Swap the active window with another window" - descriptions[25]="Move the active window out of a group" - descriptions[26]="Send a notification using the built-in Hyprland notification system" - descriptions[27]="Move the cursor to a specified position" - descriptions[28]="Set the cursor theme and reloads the cursor manager" - descriptions[29]="Set the hyprctl error string" - descriptions[30]="Move the active workspace to a monitor" - descriptions[31]="CONFUSED" - descriptions[34]="Set a property of a window" - descriptions[35]="Specify the Hyprland instance" - descriptions[36]="Disable output" - descriptions[37]="Toggle the current window's floating state" - descriptions[38]="Get the list of defined workspace rules" - descriptions[39]="Move the focused window to a workspace" - descriptions[41]="Temporarily enable or disable binds:ignore_group_lock" - descriptions[42]="List all workspaces with their properties" - descriptions[43]="Swap the active window with the next or previous in a group" - descriptions[44]="Close a specified window" - descriptions[45]="WARNING" - descriptions[46]="Specify the Hyprland instance" - descriptions[47]="List all registered binds" - descriptions[48]="Move the active window in a direction or to a monitor" - descriptions[49]="Change the split ratio" - descriptions[51]="Prohibit the active window from becoming or being inserted into group" - descriptions[52]="Change the workspace" - descriptions[53]="List all current config parsing errors" - descriptions[54]="Toggle the current active window into a group" - descriptions[55]="Get the config option status (values)" - descriptions[58]="Close the active window" - descriptions[59]="Pass the key to a specified window" - descriptions[60]="List all decorations and their info" - descriptions[61]="List all connected keyboards and mice" - descriptions[62]="Switch focus from current to previously focused window" - descriptions[63]="Change the current mapping group" - descriptions[64]="Execute a Global Shortcut using the GlobalShortcuts portal" - descriptions[66]="Force the renderer to reload all resources and outputs" - descriptions[67]="Move a selected window" - descriptions[69]="Print the Hyprland version: flags, commit and branch of build" - descriptions[70]="Set all monitors' DPMS status" - descriptions[71]="Resize the active window" - descriptions[72]="Move the active window into a group" - descriptions[73]="OK" - descriptions[75]="Set the current window's floating state to true" - descriptions[76]="Print tail of the log" - descriptions[79]="List all layouts available (including plugin ones)" - descriptions[80]="Move a workspace to a monitor" - descriptions[81]="Execute a shell command" - descriptions[83]="Modify the window stack order of the active or specified window" - descriptions[84]="Toggle the focused window's internal fullscreen state" - descriptions[86]="Issue a keyword to call a config keyword dynamically" - descriptions[89]="Disable output" - descriptions[90]="Pin a window" - descriptions[91]="Allows adding/removing fake outputs to a specific backend" - descriptions[93]="Toggle a special workspace on/off" - descriptions[94]="Toggle the focused window's fullscreen state" - descriptions[95]="Toggle the current window to always be opaque" - descriptions[96]="Focus the requested workspace" - descriptions[98]="Switch to the next window in a group" - descriptions[99]="Output in JSON format" - descriptions[100]="List all running Hyprland instances and their info" - descriptions[101]="Execute a raw shell command" - descriptions[102]="Exit the compositor with no questions asked" - descriptions[103]="List all windows with their properties" - descriptions[105]="Execute a batch of commands separated by ;" - descriptions[106]="Dismiss all or up to amount of notifications" - descriptions[108]="Set the xkb layout index for a keyboard" - descriptions[109]="Move window doesnt switch to the workspace" - descriptions[110]="Apply a tag to the window" - descriptions[111]="Behave as moveintogroup" - descriptions[112]="Refresh state after issuing the command" - descriptions[113]="Move the focus in a direction" - descriptions[114]="Focus the urgent window or the last window" - descriptions[116]="Get the active workspace name and its properties" - descriptions[117]="Issue a dispatch to call a keybind dispatcher with an arg" - descriptions[119]="Center the active window" - descriptions[120]="HINT" - descriptions[121]="Interact with hyprpaper if present" - descriptions[122]="No Icon" - descriptions[123]="Force reload the config" - descriptions[125]="Print system info" - descriptions[126]="Interact with a plugin" - descriptions[128]="Get the active window name and its properties" - descriptions[129]="Swap the active workspaces between two monitors" - descriptions[130]="Print the current random splash" - descriptions[131]="On shortcut X sends shortcut Y to a specified window" - descriptions[133]="Lock the focused group" - descriptions[136]="Lock the groups" - descriptions[137]="Move the cursor to the corner of the active window" - descriptions[140]="INFO" - descriptions[141]="Resize a selected window" + descriptions[1]="Resize the active window" + descriptions[2]="Fullscreen" + descriptions[3]="Switch to the next window in a group" + descriptions[4]="Refresh state after issuing the command" + descriptions[5]="Move the active window into a group" + descriptions[7]="CONFUSED" + descriptions[9]="Print system info" + descriptions[11]="List all layouts available (including plugin ones)" + descriptions[12]="Set a property of a window" + descriptions[14]="Set the xkb layout index for a keyboard" + descriptions[16]="Prohibit the active window from becoming or being inserted into group" + descriptions[19]="Execute a shell command" + descriptions[20]="Set the cursor theme and reloads the cursor manager" + descriptions[22]="Focus the urgent window or the last window" + descriptions[23]="Get the list of defined workspace rules" + descriptions[24]="Move the active workspace to a monitor" + descriptions[25]="Move window doesnt switch to the workspace" + descriptions[26]="Interact with hyprpaper if present" + descriptions[29]="Swap the active window with the next or previous in a group" + descriptions[30]="Move the cursor to the corner of the active window" + descriptions[31]="Move a selected window" + descriptions[33]="Move the active window in a direction or to a monitor" + descriptions[34]="Lists all global shortcuts" + descriptions[35]="List all windows with their properties" + descriptions[37]="Temporarily enable or disable binds:ignore_group_lock" + descriptions[38]="Print the current random splash" + descriptions[39]="Execute a raw shell command" + descriptions[40]="List active outputs with their properties" + descriptions[43]="Disable output" + descriptions[44]="Gets the current config info about animations and beziers" + descriptions[47]="Change the split ratio" + descriptions[48]="Move the active window" + descriptions[49]="Pass the key to a specified window" + descriptions[50]="Swap the focused window with the next window" + descriptions[51]="List all connected keyboards and mice" + descriptions[52]="List the layers" + descriptions[54]="Lock the focused group" + descriptions[55]="OK" + descriptions[56]="Move a workspace to a monitor" + descriptions[58]="Specify the Hyprland instance" + descriptions[59]="Disable output" + descriptions[61]="Pin a window" + descriptions[62]="WARNING" + descriptions[63]="INFO" + descriptions[66]="Set the current window's floating state to true" + descriptions[69]="On shortcut X sends shortcut Y to a specified window" + descriptions[70]="List all workspaces with their properties" + descriptions[71]="Focus the next window on a workspace" + descriptions[72]="Modify the window stack order of the active or specified window" + descriptions[73]="Toggle the current active window into a group" + descriptions[74]="Lock the groups" + descriptions[76]="Set all monitors' DPMS status" + descriptions[77]="Switch focus from current to previously focused window" + descriptions[78]="No Icon" + descriptions[79]="Execute a batch of commands separated by ;" + descriptions[80]="Send a notification using the built-in Hyprland notification system" + descriptions[82]="List all running Hyprland instances and their info" + descriptions[83]="Maximize no fullscreen" + descriptions[84]="Maximize and fullscreen" + descriptions[85]="Move the active window out of a group" + descriptions[86]="Close the active window" + descriptions[87]="HINT" + descriptions[88]="Move the focused window to a workspace" + descriptions[89]="Move the cursor to a specified position" + descriptions[90]="List all current config parsing errors" + descriptions[91]="Close a specified window" + descriptions[92]="Swap the active window with another window" + descriptions[93]="Apply a tag to the window" + descriptions[94]="Force the renderer to reload all resources and outputs" + descriptions[95]="Center the active window" + descriptions[97]="Focus the first window matching" + descriptions[98]="Set the hyprctl error string" + descriptions[101]="List all registered binds" + descriptions[102]="Print the Hyprland version: flags, commit and branch of build" + descriptions[103]="Prints the help message" + descriptions[104]="Toggle a special workspace on/off" + descriptions[105]="Toggle the focused window's fullscreen state" + descriptions[107]="None" + descriptions[108]="Issue a keyword to call a config keyword dynamically" + descriptions[109]="Toggle the current window to always be opaque" + descriptions[110]="ERROR" + descriptions[111]="Specify the Hyprland instance" + descriptions[112]="Toggle the current window's floating state" + descriptions[113]="Rename a workspace" + descriptions[115]="Get the active workspace name and its properties" + descriptions[117]="Get into a kill mode, where you can kill an app by clicking on it" + descriptions[119]="Allows adding/removing fake outputs to a specific backend" + descriptions[120]="Execute a Global Shortcut using the GlobalShortcuts portal" + descriptions[121]="Issue a dispatch to call a keybind dispatcher with an arg" + descriptions[122]="Force reload the config" + descriptions[124]="Output in JSON format" + descriptions[125]="Emits a custom event to socket2" + descriptions[126]="Prints the help message" + descriptions[128]="Current" + descriptions[129]="Get the active window name and its properties" + descriptions[131]="Dismiss all or up to amount of notifications" + descriptions[132]="Focus a monitor" + descriptions[133]="Move the focus in a direction" + descriptions[134]="Interact with a plugin" + descriptions[135]="Exit the compositor with no questions asked" + descriptions[136]="Change the workspace" + descriptions[137]="Sets the focused window’s fullscreen mode and the one sent to the client" + descriptions[138]="Get the config option status (values)" + descriptions[141]="List all decorations and their info" + descriptions[142]="Set the current window's floating state to false" + descriptions[144]="Return a parsable JSON with all the config options, descriptions, value types and ranges" + descriptions[145]="Resize a selected window" + descriptions[146]="Toggle the focused window's internal fullscreen state" + descriptions[147]="Print tail of the log" + descriptions[148]="Swap the active workspaces between two monitors" + descriptions[149]="Change the current mapping group" + descriptions[151]="Behave as moveintogroup" + descriptions[152]="Get the current cursor pos in global layout coordinates" + descriptions[154]="Focus the requested workspace" local -A literal_transitions - literal_transitions[1]="([106]=2 [76]=3 [34]=4 [36]=5 [2]=3 [3]=3 [79]=3 [108]=6 [38]=3 [112]=5 [42]=3 [47]=3 [116]=3 [86]=7 [117]=9 [53]=3 [89]=5 [55]=3 [91]=10 [121]=3 [123]=3 [125]=3 [16]=3 [60]=11 [61]=3 [18]=12 [126]=13 [20]=3 [128]=3 [130]=3 [26]=14 [69]=3 [99]=5 [100]=3 [28]=3 [29]=15 [103]=3 [105]=5)" - literal_transitions[4]="([74]=18 [14]=3 [33]=18 [56]=18 [57]=18 [92]=18 [107]=3 [124]=3 [78]=2 [17]=3 [127]=18 [4]=2 [6]=3 [65]=18 [132]=3 [134]=18 [82]=18 [135]=18 [85]=18 [32]=18 [50]=3 [13]=3 [87]=18 [11]=18 [88]=18 [142]=18)" - literal_transitions[8]="([106]=2 [76]=3 [34]=4 [2]=3 [3]=3 [79]=3 [108]=6 [38]=3 [42]=3 [47]=3 [116]=3 [86]=7 [117]=9 [53]=3 [55]=3 [91]=10 [121]=3 [123]=3 [125]=3 [16]=3 [60]=11 [61]=3 [18]=12 [126]=13 [20]=3 [128]=3 [130]=3 [26]=14 [69]=3 [100]=3 [28]=3 [29]=15 [103]=3)" - literal_transitions[9]="([102]=3 [131]=3 [133]=3 [1]=3 [75]=3 [37]=3 [109]=3 [110]=3 [39]=3 [111]=3 [5]=3 [80]=3 [41]=3 [81]=3 [114]=3 [7]=3 [43]=3 [44]=3 [83]=3 [84]=3 [48]=3 [49]=3 [10]=3 [51]=3 [52]=3 [54]=3 [12]=3 [113]=3 [90]=3 [119]=3 [58]=3 [93]=3 [59]=3 [94]=3 [95]=3 [62]=3 [63]=3 [129]=3 [96]=3 [64]=3 [21]=3 [98]=3 [23]=3 [24]=3 [66]=3 [67]=3 [136]=3 [137]=3 [25]=3 [27]=3 [70]=3 [101]=3 [71]=3 [141]=3 [30]=3 [72]=3)" - literal_transitions[10]="([118]=21 [115]=17)" - literal_transitions[12]="([104]=3)" - literal_transitions[14]="([22]=2 [120]=2 [31]=2 [140]=2 [122]=2 [45]=2 [73]=2)" - literal_transitions[15]="([40]=3)" - literal_transitions[16]="([139]=3 [97]=3)" - literal_transitions[18]="([19]=3 [8]=3)" - literal_transitions[19]="([77]=20)" - literal_transitions[20]="([35]=5 [46]=5)" - literal_transitions[21]="([9]=3 [68]=3 [15]=3 [138]=3)" + literal_transitions[1]="([121]=15 [44]=3 [126]=22 [82]=3 [4]=22 [52]=3 [51]=3 [129]=3 [90]=3 [59]=22 [9]=3 [11]=3 [12]=4 [131]=5 [14]=6 [98]=7 [102]=3 [103]=22 [134]=8 [101]=3 [138]=3 [23]=3 [20]=3 [141]=9 [26]=3 [144]=3 [108]=10 [147]=11 [70]=3 [34]=3 [35]=3 [79]=22 [115]=3 [38]=3 [152]=3 [117]=3 [122]=14 [124]=22 [40]=12 [43]=22 [80]=16 [119]=13)" + literal_transitions[2]="([82]=3 [52]=3 [51]=3 [129]=3 [9]=3 [90]=3 [11]=3 [12]=4 [131]=5 [14]=6 [98]=7 [102]=3 [134]=8 [101]=3 [23]=3 [20]=3 [138]=3 [141]=9 [26]=3 [144]=3 [108]=10 [147]=11 [70]=3 [34]=3 [35]=3 [115]=3 [38]=3 [152]=3 [117]=3 [40]=12 [119]=13 [122]=14 [121]=15 [80]=16 [44]=3)" + literal_transitions[4]="([140]=3 [64]=17 [65]=17 [46]=17 [106]=17 [28]=3 [27]=3 [53]=5 [6]=17 [67]=3 [68]=17 [130]=17 [114]=17 [13]=3 [75]=5 [100]=3 [36]=17 [153]=17 [99]=17 [60]=17 [118]=17 [42]=17 [18]=3 [139]=17 [155]=3 [123]=17)" + literal_transitions[7]="([127]=3)" + literal_transitions[11]="([57]=3)" + literal_transitions[12]="([10]=3)" + literal_transitions[13]="([15]=20 [81]=23)" + literal_transitions[14]="([143]=3)" + literal_transitions[15]="([1]=3 [85]=3 [3]=3 [86]=3 [5]=3 [88]=3 [89]=3 [91]=3 [92]=3 [93]=3 [94]=3 [95]=3 [97]=3 [16]=3 [19]=3 [104]=3 [22]=3 [105]=3 [24]=3 [25]=3 [29]=3 [30]=3 [31]=3 [109]=3 [112]=3 [33]=3 [113]=3 [37]=3 [39]=3 [120]=3 [125]=3 [47]=3 [48]=3 [49]=3 [50]=3 [54]=3 [56]=3 [132]=3 [133]=3 [135]=3 [136]=3 [61]=3 [137]=21 [142]=3 [66]=3 [145]=3 [146]=3 [69]=3 [148]=3 [71]=3 [72]=3 [73]=3 [74]=3 [149]=3 [76]=3 [77]=3 [151]=3 [154]=3)" + literal_transitions[16]="([87]=5 [7]=5 [110]=5 [62]=5 [78]=5 [55]=5 [63]=5)" + literal_transitions[17]="([41]=3 [45]=3)" + literal_transitions[18]="([8]=24)" + literal_transitions[19]="([32]=3 [150]=3)" + literal_transitions[20]="([96]=3 [17]=3 [116]=3 [21]=3)" + literal_transitions[21]="([107]=3 [83]=3 [128]=3 [2]=3 [84]=3)" + literal_transitions[24]="([58]=22 [111]=22)" local -A match_anything_transitions - match_anything_transitions=([2]=3 [1]=8 [7]=3 [16]=3 [11]=3 [6]=16 [15]=19 [8]=8 [3]=19 [17]=3 [13]=3 [12]=19) + match_anything_transitions=([7]=18 [8]=3 [1]=2 [23]=3 [6]=19 [5]=3 [3]=18 [19]=3 [12]=18 [9]=3 [10]=3 [14]=18 [11]=18 [2]=2) declare -A subword_transitions @@ -199,7 +214,7 @@ _hyprctl () { fi done fi - local -A commands=([6]=1 [17]=2 [13]=3 [11]=0) + local -A commands=([8]=0 [23]=1 [9]=3 [6]=2) if [[ -v "commands[$state]" ]]; then local command_id=${commands[$state]} @@ -252,4 +267,8 @@ _hyprctl () { return 0 } -compdef _hyprctl hyprctl +if [[ $ZSH_EVAL_CONTEXT =~ :file$ ]]; then + compdef _hyprctl hyprctl +else + _hyprctl +fi diff --git a/hyprpm/hyprpm.bash b/hyprpm/hyprpm.bash index ffc33e19..3c2bc90b 100644 --- a/hyprpm/hyprpm.bash +++ b/hyprpm/hyprpm.bash @@ -2,6 +2,10 @@ _hyprpm_cmd_0 () { hyprpm list | awk '/Plugin/{print $4}' } +_hyprpm_cmd_1 () { + hyprpm list | awk '/Repository/{print $4}' | sed 's/:$//' +} + _hyprpm () { if [[ $(type -t _get_comp_words_by_ref) != function ]]; then echo _get_comp_words_by_ref: function not defined. Make sure the bash-completions system package is installed @@ -11,16 +15,13 @@ _hyprpm () { local words cword _get_comp_words_by_ref -n "$COMP_WORDBREAKS" words cword - local -a literals=("-n" "::=" "list" "disable" "--help" "update" "add" "--verbose" "-v" "--force" "remove" "enable" "--notify" "-h" "reload" "-f") - + declare -a literals=(--no-shallow -n ::= disable list --help update add --verbose -v --force -s remove enable --notify -h reload -f) declare -A literal_transitions - literal_transitions[0]="([9]=6 [2]=2 [7]=6 [8]=6 [4]=6 [10]=2 [11]=3 [5]=2 [13]=6 [3]=3 [14]=2 [15]=6 [6]=2)" - literal_transitions[1]="([10]=2 [11]=3 [3]=3 [2]=2 [14]=2 [5]=2 [6]=2)" - literal_transitions[4]="([1]=5)" - literal_transitions[5]="([0]=6 [12]=6)" - - declare -A match_anything_transitions - match_anything_transitions=([3]=2 [2]=4 [0]=1 [1]=1) + literal_transitions[0]="([0]=7 [3]=3 [4]=4 [8]=7 [9]=7 [6]=4 [7]=4 [11]=7 [5]=7 [10]=7 [12]=2 [13]=3 [15]=7 [16]=4 [17]=7)" + literal_transitions[1]="([12]=2 [13]=3 [3]=3 [4]=4 [16]=4 [6]=4 [7]=4)" + literal_transitions[5]="([2]=6)" + literal_transitions[6]="([1]=7 [14]=7)" + declare -A match_anything_transitions=([1]=1 [4]=5 [3]=4 [2]=4 [0]=1) declare -A subword_transitions local state=0 @@ -58,21 +59,9 @@ _hyprpm () { done + local -a matches=() + local prefix="${words[$cword]}" - - local shortest_suffix="$word" - for ((i=0; i < ${#COMP_WORDBREAKS}; i++)); do - local char="${COMP_WORDBREAKS:$i:1}" - local candidate="${word##*$char}" - if [[ ${#candidate} -lt ${#shortest_suffix} ]]; then - shortest_suffix=$candidate - fi - done - local superfluous_prefix="" - if [[ "$shortest_suffix" != "$word" ]]; then - local superfluous_prefix=${word%$shortest_suffix} - fi - if [[ -v "literal_transitions[$state]" ]]; then local state_transitions_initializer=${literal_transitions[$state]} declare -A state_transitions @@ -81,25 +70,38 @@ _hyprpm () { for literal_id in "${!state_transitions[@]}"; do local literal="${literals[$literal_id]}" if [[ $literal = "${prefix}"* ]]; then - local completion=${literal#"$superfluous_prefix"} - COMPREPLY+=("$completion ") + matches+=("$literal ") fi done fi declare -A commands - commands=([3]=0) + commands=([3]=0 [2]=1) if [[ -v "commands[$state]" ]]; then local command_id=${commands[$state]} local completions=() - mapfile -t completions < <(_hyprpm_cmd_${command_id} "$prefix" | cut -f1) + readarray -t completions < <(_hyprpm_cmd_${command_id} "$prefix" | cut -f1) for item in "${completions[@]}"; do if [[ $item = "${prefix}"* ]]; then - COMPREPLY+=("$item") + matches+=("$item") fi done fi + local shortest_suffix="$prefix" + for ((i=0; i < ${#COMP_WORDBREAKS}; i++)); do + local char="${COMP_WORDBREAKS:$i:1}" + local candidate=${prefix##*$char} + if [[ ${#candidate} -lt ${#shortest_suffix} ]]; then + shortest_suffix=$candidate + fi + done + local superfluous_prefix="" + if [[ "$shortest_suffix" != "$prefix" ]]; then + local superfluous_prefix=${prefix%$shortest_suffix} + fi + COMPREPLY=("${matches[@]#$superfluous_prefix}") + return 0 } diff --git a/hyprpm/hyprpm.fish b/hyprpm/hyprpm.fish index 7be4f224..82561bd8 100644 --- a/hyprpm/hyprpm.fish +++ b/hyprpm/hyprpm.fish @@ -3,6 +3,11 @@ function _hyprpm_1 hyprpm list | awk '/Plugin/{print $4}' end +function _hyprpm_2 + set 1 $argv[1] + hyprpm list | awk '/Repository/{print $4}' | sed 's/:$//' +end + function _hyprpm set COMP_LINE (commandline --cut-at-cursor) @@ -14,49 +19,51 @@ function _hyprpm set COMP_CWORD (count $COMP_WORDS) end - set --local literals "-n" "::=" "list" "disable" "--help" "update" "add" "--verbose" "-v" "--force" "remove" "enable" "--notify" "-h" "reload" "-f" + set literals "--no-shallow" "-n" "::=" "disable" "list" "--help" "update" "add" "--verbose" "-v" "--force" "-s" "remove" "enable" "--notify" "-h" "reload" "-f" - set --local descriptions - set descriptions[1] "Send a hyprland notification for important events (e.g. load fail)" - set descriptions[3] "List all installed plugins" + set descriptions + set descriptions[1] "Disable shallow cloning of Hyprland sources" + set descriptions[2] "Send a hyprland notification for important events (e.g. load fail)" set descriptions[4] "Unload a plugin" - set descriptions[5] "Show help menu" - set descriptions[6] "Check and update all plugins if needed" - set descriptions[7] "Install a new plugin repository from git" - set descriptions[8] "Enable too much loggin" + set descriptions[5] "List all installed plugins" + set descriptions[6] "Show help menu" + set descriptions[7] "Check and update all plugins if needed" + set descriptions[8] "Install a new plugin repository from git" set descriptions[9] "Enable too much loggin" - set descriptions[10] "Force an operation ignoring checks (e.g. update -f)" - set descriptions[11] "Remove a plugin repository" - set descriptions[12] "Load a plugin" - set descriptions[13] "Send a hyprland notification for important events (e.g. load fail)" - set descriptions[14] "Show help menu" - set descriptions[15] "Reload all plugins" - set descriptions[16] "Force an operation ignoring checks (e.g. update -f)" + set descriptions[10] "Enable too much loggin" + set descriptions[11] "Force an operation ignoring checks (e.g. update -f)" + set descriptions[12] "Disable shallow cloning of Hyprland sources" + set descriptions[13] "Remove a plugin repository" + set descriptions[14] "Load a plugin" + set descriptions[15] "Send a hyprland notification for important events (e.g. load fail)" + set descriptions[16] "Show help menu" + set descriptions[17] "Reload all plugins" + set descriptions[18] "Force an operation ignoring checks (e.g. update -f)" - set --local literal_transitions - set literal_transitions[1] "set inputs 10 3 8 9 5 11 12 6 14 4 15 16 7; set tos 7 3 7 7 7 3 4 3 7 4 3 7 3" - set literal_transitions[2] "set inputs 11 12 4 3 15 6 7; set tos 3 4 4 3 3 3 3" - set literal_transitions[5] "set inputs 2; set tos 6" - set literal_transitions[6] "set inputs 1 13; set tos 7 7" + set literal_transitions + set literal_transitions[1] "set inputs 1 4 5 9 10 7 8 12 6 11 13 14 16 17 18; set tos 8 4 5 8 8 5 5 8 8 8 3 4 8 5 8" + set literal_transitions[2] "set inputs 13 14 4 5 17 7 8; set tos 3 4 4 5 5 5 5" + set literal_transitions[6] "set inputs 3; set tos 7" + set literal_transitions[7] "set inputs 2 15; set tos 8 8" - set --local match_anything_transitions_from 4 3 1 2 - set --local match_anything_transitions_to 3 5 2 2 + set match_anything_transitions_from 2 5 4 3 1 + set match_anything_transitions_to 2 6 5 5 2 - set --local state 1 - set --local word_index 2 + set state 1 + set word_index 2 while test $word_index -lt $COMP_CWORD - set --local -- word $COMP_WORDS[$word_index] + set -- word $COMP_WORDS[$word_index] if set --query literal_transitions[$state] && test -n $literal_transitions[$state] - set --local --erase inputs - set --local --erase tos + set --erase inputs + set --erase tos eval $literal_transitions[$state] if contains -- $word $literals - set --local literal_matched 0 + set literal_matched 0 for literal_id in (seq 1 (count $literals)) if test $literals[$literal_id] = $word - set --local index (contains --index -- $literal_id $inputs) + set index (contains --index -- $literal_id $inputs) set state $tos[$index] set word_index (math $word_index + 1) set literal_matched 1 @@ -70,7 +77,7 @@ function _hyprpm end if set --query match_anything_transitions_from[$state] && test -n $match_anything_transitions_from[$state] - set --local index (contains --index -- $state $match_anything_transitions_from) + set index (contains --index -- $state $match_anything_transitions_from) set state $match_anything_transitions_to[$index] set word_index (math $word_index + 1) continue @@ -80,8 +87,8 @@ function _hyprpm end if set --query literal_transitions[$state] && test -n $literal_transitions[$state] - set --local --erase inputs - set --local --erase tos + set --erase inputs + set --erase tos eval $literal_transitions[$state] for literal_id in $inputs if test -n $descriptions[$literal_id] @@ -92,14 +99,14 @@ function _hyprpm end end - set command_states 4 - set command_ids 1 + set command_states 4 3 + set command_ids 1 2 if contains $state $command_states - set --local index (contains --index $state $command_states) - set --local function_id $command_ids[$index] - set --local function_name _hyprpm_$function_id - set --local --erase inputs - set --local --erase tos + set index (contains --index $state $command_states) + set function_id $command_ids[$index] + set function_name _hyprpm_$function_id + set --erase inputs + set --erase tos $function_name "$COMP_WORDS[$COMP_CWORD]" end diff --git a/hyprpm/hyprpm.usage b/hyprpm/hyprpm.usage index 369c9d2b..24e631c5 100644 --- a/hyprpm/hyprpm.usage +++ b/hyprpm/hyprpm.usage @@ -5,10 +5,11 @@ hyprpm []... | (--help | -h) "Show help menu" | (--verbose | -v) "Enable too much loggin" | (--force | -f) "Force an operation ignoring checks (e.g. update -f)" + | (--no-shallow | -s) "Disable shallow cloning of Hyprland sources" ; ::= (add) "Install a new plugin repository from git" - | (remove) "Remove a plugin repository" + | (remove ) "Remove a plugin repository" | (update) "Check and update all plugins if needed" | (list) "List all installed plugins" | (enable ) "Load a plugin" @@ -17,3 +18,4 @@ hyprpm []... ; ::= {{{ hyprpm list | awk '/Plugin/{print $4}' }}}; + ::= {{{ hyprpm list | awk '/Repository/{print $4}' | sed 's/:$//' }}}; diff --git a/hyprpm/hyprpm.zsh b/hyprpm/hyprpm.zsh index 854e8426..859c5313 100644 --- a/hyprpm/hyprpm.zsh +++ b/hyprpm/hyprpm.zsh @@ -4,34 +4,40 @@ _hyprpm_cmd_0 () { hyprpm list | awk '/Plugin/{print $4}' } +_hyprpm_cmd_1 () { + hyprpm list | awk '/Repository/{print $4}' | sed 's/:$//' +} + _hyprpm () { - local -a literals=("-n" "::=" "list" "disable" "--help" "update" "add" "--verbose" "-v" "--force" "remove" "enable" "--notify" "-h" "reload" "-f") + local -a literals=("--no-shallow" "-n" "::=" "disable" "list" "--help" "update" "add" "--verbose" "-v" "--force" "-s" "remove" "enable" "--notify" "-h" "reload" "-f") local -A descriptions - descriptions[1]="Send a hyprland notification for important events (e.g. load fail)" - descriptions[3]="List all installed plugins" + descriptions[1]="Disable shallow cloning of Hyprland sources" + descriptions[2]="Send a hyprland notification for important events (e.g. load fail)" descriptions[4]="Unload a plugin" - descriptions[5]="Show help menu" - descriptions[6]="Check and update all plugins if needed" - descriptions[7]="Install a new plugin repository from git" - descriptions[8]="Enable too much loggin" + descriptions[5]="List all installed plugins" + descriptions[6]="Show help menu" + descriptions[7]="Check and update all plugins if needed" + descriptions[8]="Install a new plugin repository from git" descriptions[9]="Enable too much loggin" - descriptions[10]="Force an operation ignoring checks (e.g. update -f)" - descriptions[11]="Remove a plugin repository" - descriptions[12]="Load a plugin" - descriptions[13]="Send a hyprland notification for important events (e.g. load fail)" - descriptions[14]="Show help menu" - descriptions[15]="Reload all plugins" - descriptions[16]="Force an operation ignoring checks (e.g. update -f)" + descriptions[10]="Enable too much loggin" + descriptions[11]="Force an operation ignoring checks (e.g. update -f)" + descriptions[12]="Disable shallow cloning of Hyprland sources" + descriptions[13]="Remove a plugin repository" + descriptions[14]="Load a plugin" + descriptions[15]="Send a hyprland notification for important events (e.g. load fail)" + descriptions[16]="Show help menu" + descriptions[17]="Reload all plugins" + descriptions[18]="Force an operation ignoring checks (e.g. update -f)" local -A literal_transitions - literal_transitions[1]="([10]=7 [3]=3 [8]=7 [9]=7 [5]=7 [11]=3 [12]=4 [6]=3 [14]=7 [4]=4 [15]=3 [16]=7 [7]=3)" - literal_transitions[2]="([11]=3 [12]=4 [4]=4 [3]=3 [15]=3 [6]=3 [7]=3)" - literal_transitions[5]="([2]=6)" - literal_transitions[6]="([1]=7 [13]=7)" + literal_transitions[1]="([1]=8 [4]=4 [5]=5 [9]=8 [10]=8 [7]=5 [8]=5 [12]=8 [6]=8 [11]=8 [13]=3 [14]=4 [16]=8 [17]=5 [18]=8)" + literal_transitions[2]="([13]=3 [14]=4 [4]=4 [5]=5 [17]=5 [7]=5 [8]=5)" + literal_transitions[6]="([3]=7)" + literal_transitions[7]="([2]=8 [15]=8)" local -A match_anything_transitions - match_anything_transitions=([4]=3 [3]=5 [1]=2 [2]=2) + match_anything_transitions=([2]=2 [5]=6 [4]=5 [3]=5 [1]=2) declare -A subword_transitions @@ -91,7 +97,7 @@ _hyprpm () { fi done fi - local -A commands=([4]=0) + local -A commands=([4]=0 [3]=1) if [[ -v "commands[$state]" ]]; then local command_id=${commands[$state]} From 33015546c62a7b73793d62983a84b097362cec1a Mon Sep 17 00:00:00 2001 From: Jan Beich Date: Mon, 19 Aug 2024 12:46:36 +0000 Subject: [PATCH 0294/2181] config: add missing header for libc++ after 92744b5b9aa3 (#7403) In file included from src/pch/pch.hpp:1: In file included from src/Compositor.hpp:11: src/config/ConfigManager.hpp:147:10: error: no template named 'variant' in namespace 'std' 147 | std::variant data; | ~~~~~^ --- src/config/ConfigManager.hpp | 1 + 1 file changed, 1 insertion(+) diff --git a/src/config/ConfigManager.hpp b/src/config/ConfigManager.hpp index 4241031b..4d087753 100644 --- a/src/config/ConfigManager.hpp +++ b/src/config/ConfigManager.hpp @@ -6,6 +6,7 @@ #include "../debug/Log.hpp" #include #include "../defines.hpp" +#include #include #include #include From 01e3da4d51927427860368c88a523f47c479b710 Mon Sep 17 00:00:00 2001 From: JL2210 Date: Mon, 19 Aug 2024 09:02:09 -0400 Subject: [PATCH 0295/2181] examples: more systemd examples (#7409) These allow launching hyprland with a systemd service. They provide graphical-session.target which allows enabling services such as the ones for Waybar and Mako. --- example/hyprland-session.service | 14 ++++++++++++++ example/hyprland-systemd.desktop | 5 +++++ 2 files changed, 19 insertions(+) create mode 100644 example/hyprland-session.service create mode 100644 example/hyprland-systemd.desktop diff --git a/example/hyprland-session.service b/example/hyprland-session.service new file mode 100644 index 00000000..7d33f5b3 --- /dev/null +++ b/example/hyprland-session.service @@ -0,0 +1,14 @@ +[Unit] +Description=Hyprland - Tiling compositor with the looks +Documentation=man:Hyprland(1) +BindsTo=graphical-session.target +Before=graphical-session.target +Wants=graphical-session-pre.target +After=graphical-session-pre.target + +[Service] +Type=notify +ExecStart=/usr/bin/Hyprland +ExecStop=/usr/bin/hyprctl dispatch exit +Restart=on-failure +Slice=session.slice diff --git a/example/hyprland-systemd.desktop b/example/hyprland-systemd.desktop new file mode 100644 index 00000000..b36a87b2 --- /dev/null +++ b/example/hyprland-systemd.desktop @@ -0,0 +1,5 @@ +[Desktop Entry] +Name=Hyprland +Comment=An intelligent dynamic tiling Wayland compositor +Exec=systemctl --user start --wait hyprland-session +Type=Application From 272d9048706379201b761c3159c24a20cd62fad1 Mon Sep 17 00:00:00 2001 From: vaxerski Date: Mon, 19 Aug 2024 18:36:06 +0200 Subject: [PATCH 0296/2181] monitors: avoid crash on wayland output removal --- src/events/Monitors.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/events/Monitors.cpp b/src/events/Monitors.cpp index b2778062..60fb5bef 100644 --- a/src/events/Monitors.cpp +++ b/src/events/Monitors.cpp @@ -98,7 +98,7 @@ void Events::listener_monitorDestroy(void* owner, void* data) { if (!pMonitor) return; - Debug::log(LOG, "Destroy called for monitor {}", pMonitor->output->name); + Debug::log(LOG, "Destroy called for monitor {}", pMonitor->szName); pMonitor->onDisconnect(true); From c86db7bbb0cf14d4955ee3a4d13c0ed9f8a0e0ae Mon Sep 17 00:00:00 2001 From: vaxerski Date: Mon, 19 Aug 2024 18:44:22 +0200 Subject: [PATCH 0297/2181] monitor: avoid dangling references to old monitors being undestroyed ref #7414 --- src/Compositor.cpp | 3 +-- src/events/Events.hpp | 1 - src/events/Monitors.cpp | 25 ------------------------- src/helpers/Monitor.cpp | 21 +++++++++++++++++---- src/helpers/Monitor.hpp | 2 +- 5 files changed, 19 insertions(+), 33 deletions(-) diff --git a/src/Compositor.cpp b/src/Compositor.cpp index 1437a653..75c22743 100644 --- a/src/Compositor.cpp +++ b/src/Compositor.cpp @@ -2935,7 +2935,7 @@ PHLWINDOW CCompositor::windowForCPointer(CWindow* pWindow) { void CCompositor::onNewMonitor(SP output) { // add it to real - auto PNEWMONITOR = g_pCompositor->m_vRealMonitors.emplace_back(makeShared()); + auto PNEWMONITOR = g_pCompositor->m_vRealMonitors.emplace_back(makeShared(output)); if (std::string("HEADLESS-1") == output->name) { g_pCompositor->m_pUnsafeOutput = PNEWMONITOR.get(); output->name = "FALLBACK"; // we are allowed to do this :) @@ -2944,7 +2944,6 @@ void CCompositor::onNewMonitor(SP output) { Debug::log(LOG, "New output with name {}", output->name); PNEWMONITOR->szName = output->name; - PNEWMONITOR->output = output; PNEWMONITOR->self = PNEWMONITOR; const bool FALLBACK = g_pCompositor->m_pUnsafeOutput ? output == g_pCompositor->m_pUnsafeOutput->output : false; PNEWMONITOR->ID = FALLBACK ? MONITOR_INVALID : g_pCompositor->getNextAvailableMonitorID(output->name); diff --git a/src/events/Events.hpp b/src/events/Events.hpp index 8e73f54a..0af16f64 100644 --- a/src/events/Events.hpp +++ b/src/events/Events.hpp @@ -27,7 +27,6 @@ namespace Events { // Monitor part 2 the sequel DYNLISTENFUNC(monitorFrame); - DYNLISTENFUNC(monitorDestroy); DYNLISTENFUNC(monitorStateRequest); DYNLISTENFUNC(monitorDamage); DYNLISTENFUNC(monitorNeedsFrame); diff --git a/src/events/Monitors.cpp b/src/events/Monitors.cpp index 60fb5bef..9d2210f6 100644 --- a/src/events/Monitors.cpp +++ b/src/events/Monitors.cpp @@ -85,31 +85,6 @@ void Events::listener_monitorFrame(void* owner, void* data) { } } -void Events::listener_monitorDestroy(void* owner, void* data) { - CMonitor* pMonitor = (CMonitor*)owner; - - for (auto& m : g_pCompositor->m_vRealMonitors) { - if (m->output == pMonitor->output) { - pMonitor = m.get(); - break; - } - } - - if (!pMonitor) - return; - - Debug::log(LOG, "Destroy called for monitor {}", pMonitor->szName); - - pMonitor->onDisconnect(true); - - pMonitor->output = nullptr; - pMonitor->m_bRenderingInitPassed = false; - - Debug::log(LOG, "Removing monitor {} from realMonitors", pMonitor->szName); - - std::erase_if(g_pCompositor->m_vRealMonitors, [&](SP& el) { return el.get() == pMonitor; }); -} - void Events::listener_monitorNeedsFrame(void* owner, void* data) { const auto PMONITOR = (CMonitor*)owner; diff --git a/src/helpers/Monitor.cpp b/src/helpers/Monitor.cpp index 9542d2c4..2c6282e1 100644 --- a/src/helpers/Monitor.cpp +++ b/src/helpers/Monitor.cpp @@ -25,7 +25,7 @@ int ratHandler(void* data) { return 1; } -CMonitor::CMonitor() : state(this) { +CMonitor::CMonitor(SP output_) : state(this), output(output_) { ; } @@ -40,16 +40,29 @@ void CMonitor::onConnect(bool noRule) { outTimeline = CSyncTimeline::create(output->getBackend()->drmFD()); } - listeners.frame = output->events.frame.registerListener([this](std::any d) { Events::listener_monitorFrame(this, nullptr); }); - listeners.destroy = output->events.destroy.registerListener([this](std::any d) { Events::listener_monitorDestroy(this, nullptr); }); - listeners.commit = output->events.commit.registerListener([this](std::any d) { Events::listener_monitorCommit(this, nullptr); }); + listeners.frame = output->events.frame.registerListener([this](std::any d) { Events::listener_monitorFrame(this, nullptr); }); + listeners.commit = output->events.commit.registerListener([this](std::any d) { Events::listener_monitorCommit(this, nullptr); }); listeners.needsFrame = output->events.needsFrame.registerListener([this](std::any d) { g_pCompositor->scheduleFrameForMonitor(this, Aquamarine::IOutput::AQ_SCHEDULE_NEEDS_FRAME); }); + listeners.presented = output->events.present.registerListener([this](std::any d) { auto E = std::any_cast(d); PROTO::presentation->onPresented(this, E.when, E.refresh, E.seq, E.flags); }); + listeners.destroy = output->events.destroy.registerListener([this](std::any d) { + Debug::log(LOG, "Destroy called for monitor {}", szName); + + onDisconnect(true); + + output = nullptr; + m_bRenderingInitPassed = false; + + Debug::log(LOG, "Removing monitor {} from realMonitors", szName); + + std::erase_if(g_pCompositor->m_vRealMonitors, [&](SP& el) { return el.get() == this; }); + }); + listeners.state = output->events.state.registerListener([this](std::any d) { auto E = std::any_cast(d); diff --git a/src/helpers/Monitor.hpp b/src/helpers/Monitor.hpp index dcfcb63b..01a5d28d 100644 --- a/src/helpers/Monitor.hpp +++ b/src/helpers/Monitor.hpp @@ -59,7 +59,7 @@ class CMonitorState { class CMonitor { public: - CMonitor(); + CMonitor(SP output); ~CMonitor(); Vector2D vecPosition = Vector2D(-1, -1); // means unset From 4eff224a7f6f4baa5600f687d6f2ef4ad8340ad3 Mon Sep 17 00:00:00 2001 From: Ali Atashrooz Date: Wed, 21 Aug 2024 13:54:02 +0330 Subject: [PATCH 0298/2181] example/config: fix typo in default config (#7446) * Update hyprland.conf * Update defaultConfig.hpp --- example/hyprland.conf | 6 +++--- src/config/defaultConfig.hpp | 6 +++--- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/example/hyprland.conf b/example/hyprland.conf index f69309c2..d55d25fd 100644 --- a/example/hyprland.conf +++ b/example/hyprland.conf @@ -169,9 +169,9 @@ device { } -#################### -### KEYBINDINGSS ### -#################### +################### +### KEYBINDINGS ### +################### # See https://wiki.hyprland.org/Configuring/Keywords/ $mainMod = SUPER # Sets "Windows" key as main modifier diff --git a/src/config/defaultConfig.hpp b/src/config/defaultConfig.hpp index 98b617d0..59265fee 100644 --- a/src/config/defaultConfig.hpp +++ b/src/config/defaultConfig.hpp @@ -182,9 +182,9 @@ device { } -#################### -### KEYBINDINGSS ### -#################### +################### +### KEYBINDINGS ### +################### # See https://wiki.hyprland.org/Configuring/Keywords/ $mainMod = SUPER # Sets "Windows" key as main modifier From 946ed1f32ae8e3840d1b3bb04c6e048ca7501fba Mon Sep 17 00:00:00 2001 From: ParaN3xus <136563585+ParaN3xus@users.noreply.github.com> Date: Wed, 21 Aug 2024 18:24:42 +0800 Subject: [PATCH 0299/2181] core: add option to control which window to focus on close (#7368) --- src/config/ConfigDescriptions.hpp | 9 ++++++++- src/config/ConfigManager.cpp | 1 + src/events/Windows.cpp | 7 ++++++- 3 files changed, 15 insertions(+), 2 deletions(-) diff --git a/src/config/ConfigDescriptions.hpp b/src/config/ConfigDescriptions.hpp index 3c830132..73b995ae 100644 --- a/src/config/ConfigDescriptions.hpp +++ b/src/config/ConfigDescriptions.hpp @@ -453,6 +453,13 @@ inline static const std::vector CONFIG_OPTIONS = { .type = CONFIG_OPTION_INT, .data = SConfigOptionDescription::SRangeData{1, 0, 3}, }, + SConfigOptionDescription{ + .value = "input:focus_on_close", + .description = "Controls the window focus behavior when a window is closed. When set to 0, focus will shift to the next window candidate. When set to 1, focus will shift " + "to the window under the cursor.", + .type = CONFIG_OPTION_CHOICE, + .data = SConfigOptionDescription::SChoiceData{0, "next,cursor"}, + }, SConfigOptionDescription{ .value = "input:mouse_refocus", .description = "if disabled, mouse focus won't switch to the hovered window unless the mouse crosses a window boundary when follow_mouse=1.", @@ -1341,4 +1348,4 @@ inline static const std::vector CONFIG_OPTIONS = { .type = CONFIG_OPTION_BOOL, .data = SConfigOptionDescription::SBoolData{true}, }, -}; \ No newline at end of file +}; diff --git a/src/config/ConfigManager.cpp b/src/config/ConfigManager.cpp index 1856bd49..155b75d3 100644 --- a/src/config/ConfigManager.cpp +++ b/src/config/ConfigManager.cpp @@ -449,6 +449,7 @@ CConfigManager::CConfigManager() { m_pConfig->addConfigValue("animations:first_launch_animation", Hyprlang::INT{1}); m_pConfig->addConfigValue("input:follow_mouse", Hyprlang::INT{1}); + m_pConfig->addConfigValue("input:focus_on_close", Hyprlang::INT{0}); m_pConfig->addConfigValue("input:mouse_refocus", Hyprlang::INT{1}); m_pConfig->addConfigValue("input:special_fallthrough", Hyprlang::INT{0}); m_pConfig->addConfigValue("input:off_window_axis_events", Hyprlang::INT{1}); diff --git a/src/events/Windows.cpp b/src/events/Windows.cpp index 2eb7038f..e4e3900b 100644 --- a/src/events/Windows.cpp +++ b/src/events/Windows.cpp @@ -648,7 +648,12 @@ void Events::listener_unmapWindow(void* owner, void* data) { // refocus on a new window if needed if (wasLastWindow) { - const auto PWINDOWCANDIDATE = g_pLayoutManager->getCurrentLayout()->getNextWindowCandidate(PWINDOW); + static auto FOCUSONCLOSE = CConfigValue("input:focus_on_close"); + PHLWINDOW PWINDOWCANDIDATE = nullptr; + if (*FOCUSONCLOSE) + PWINDOWCANDIDATE = (g_pCompositor->vectorToWindowUnified(g_pInputManager->getMouseCoordsInternal(), RESERVED_EXTENTS | INPUT_EXTENTS | ALLOW_FLOATING)); + else + PWINDOWCANDIDATE = g_pLayoutManager->getCurrentLayout()->getNextWindowCandidate(PWINDOW); Debug::log(LOG, "On closed window, new focused candidate is {}", PWINDOWCANDIDATE); From 3e7325af57c4670ebea65d2669f49526819c2260 Mon Sep 17 00:00:00 2001 From: Tom Englund Date: Wed, 21 Aug 2024 12:52:40 +0200 Subject: [PATCH 0300/2181] output: dont cast enum out of range (#7448) avoid casting non typed enum out of range, looks like WL_OUTPUT_MODE_CURRENT was the intention here. --- src/protocols/core/Output.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/protocols/core/Output.cpp b/src/protocols/core/Output.cpp index 878d1484..8d0b0121 100644 --- a/src/protocols/core/Output.cpp +++ b/src/protocols/core/Output.cpp @@ -55,7 +55,7 @@ void CWLOutputResource::updateState() { if (resource->version() >= 2) resource->sendScale(std::ceil(monitor->scale)); - resource->sendMode((wl_output_mode)(WL_OUTPUT_MODE_CURRENT | WL_OUTPUT_MODE_PREFERRED), monitor->vecPixelSize.x, monitor->vecPixelSize.y, monitor->refreshRate * 1000.0); + resource->sendMode((wl_output_mode)(WL_OUTPUT_MODE_CURRENT), monitor->vecPixelSize.x, monitor->vecPixelSize.y, monitor->refreshRate * 1000.0); if (resource->version() >= 2) resource->sendDone(); From 883463f9dd7f1cdc68c3e32017c0a71ccbe39b26 Mon Sep 17 00:00:00 2001 From: vaxerski Date: Wed, 21 Aug 2024 14:37:50 +0200 Subject: [PATCH 0301/2181] animations: add workspace in/out configs --- src/config/ConfigManager.cpp | 10 +++++++++- src/desktop/Workspace.cpp | 12 ++++++++++-- src/managers/AnimationManager.cpp | 2 +- 3 files changed, 20 insertions(+), 4 deletions(-) diff --git a/src/config/ConfigManager.cpp b/src/config/ConfigManager.cpp index 155b75d3..e2ae2c47 100644 --- a/src/config/ConfigManager.cpp +++ b/src/config/ConfigManager.cpp @@ -724,7 +724,6 @@ void CConfigManager::setDefaultAnimationVars() { INITANIMCFG("fade"); INITANIMCFG("border"); INITANIMCFG("borderangle"); - INITANIMCFG("workspaces"); // windows INITANIMCFG("windowsIn"); @@ -745,7 +744,12 @@ void CConfigManager::setDefaultAnimationVars() { // border // workspaces + INITANIMCFG("workspaces"); + INITANIMCFG("workspacesIn"); + INITANIMCFG("workspacesOut"); INITANIMCFG("specialWorkspace"); + INITANIMCFG("specialWorkspaceIn"); + INITANIMCFG("specialWorkspaceOut"); } // init the values @@ -774,7 +778,11 @@ void CConfigManager::setDefaultAnimationVars() { CREATEANIMCFG("fadeLayersIn", "fadeLayers"); CREATEANIMCFG("fadeLayersOut", "fadeLayers"); + CREATEANIMCFG("workspacesIn", "workspaces"); + CREATEANIMCFG("workspacesOut", "workspaces"); CREATEANIMCFG("specialWorkspace", "workspaces"); + CREATEANIMCFG("specialWorkspaceIn", "specialWorkspace"); + CREATEANIMCFG("specialWorkspaceOut", "specialWorkspace"); } std::optional CConfigManager::resetHLConfig() { diff --git a/src/desktop/Workspace.cpp b/src/desktop/Workspace.cpp index d9ac7927..a9412e6d 100644 --- a/src/desktop/Workspace.cpp +++ b/src/desktop/Workspace.cpp @@ -22,10 +22,11 @@ CWorkspace::CWorkspace(WORKSPACEID id, MONITORID monitorID, std::string name, bo void CWorkspace::init(PHLWORKSPACE self) { m_pSelf = self; - m_vRenderOffset.create(m_bIsSpecialWorkspace ? g_pConfigManager->getAnimationPropertyConfig("specialWorkspace") : g_pConfigManager->getAnimationPropertyConfig("workspaces"), + m_vRenderOffset.create(m_bIsSpecialWorkspace ? g_pConfigManager->getAnimationPropertyConfig("specialWorkspaceIn") : + g_pConfigManager->getAnimationPropertyConfig("workspacesIn"), self, AVARDAMAGE_ENTIRE); m_fAlpha.create(AVARTYPE_FLOAT, - m_bIsSpecialWorkspace ? g_pConfigManager->getAnimationPropertyConfig("specialWorkspace") : g_pConfigManager->getAnimationPropertyConfig("workspaces"), self, + m_bIsSpecialWorkspace ? g_pConfigManager->getAnimationPropertyConfig("specialWorkspaceIn") : g_pConfigManager->getAnimationPropertyConfig("workspacesIn"), self, AVARDAMAGE_ENTIRE); m_fAlpha.setValueAndWarp(1.f); @@ -81,6 +82,13 @@ CWorkspace::~CWorkspace() { } void CWorkspace::startAnim(bool in, bool left, bool instant) { + if (!instant) { + const std::string ANIMNAME = std::format("{}{}", m_bIsSpecialWorkspace ? "specialWorkspace" : "workspaces", in ? "In" : "Out"); + + m_fAlpha.m_pConfig = g_pConfigManager->getAnimationPropertyConfig(ANIMNAME); + m_vRenderOffset.m_pConfig = g_pConfigManager->getAnimationPropertyConfig(ANIMNAME); + } + const auto ANIMSTYLE = m_fAlpha.m_pConfig->pValues->internalStyle; static auto PWORKSPACEGAP = CConfigValue("general:gaps_workspaces"); diff --git a/src/managers/AnimationManager.cpp b/src/managers/AnimationManager.cpp index dcc7a45f..beb880be 100644 --- a/src/managers/AnimationManager.cpp +++ b/src/managers/AnimationManager.cpp @@ -471,7 +471,7 @@ std::string CAnimationManager::styleValidInConfigVar(const std::string& config, } return "unknown style"; - } else if (config == "workspaces" || config == "specialWorkspace") { + } else if (config.starts_with("workspaces") || config.starts_with("specialWorkspace")) { if (style == "slide" || style == "slidevert" || style == "fade") return ""; else if (style.starts_with("slidefade")) { From 1b1ecf77e0c195460eb5335652d65de6fd83cf7b Mon Sep 17 00:00:00 2001 From: Mihai Fufezan Date: Wed, 21 Aug 2024 22:37:28 +0300 Subject: [PATCH 0302/2181] Nix: include xcursor regardless of xwayland --- nix/default.nix | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/nix/default.nix b/nix/default.nix index 9bae9d83..c8eaf731 100644 --- a/nix/default.nix +++ b/nix/default.nix @@ -136,11 +136,11 @@ assert lib.assertMsg (!hidpiXWayland) "The option `hidpiXWayland` has been remov tomlplusplus wayland wayland-protocols + xorg.libXcursor ] (lib.optionals stdenv.hostPlatform.isMusl [libexecinfo]) (lib.optionals enableXWayland [ xorg.libxcb - xorg.libXcursor xorg.libXdmcp xorg.xcbutil xorg.xcbutilerrors From c5786be695224c2d2771854436844b88a6b48fc5 Mon Sep 17 00:00:00 2001 From: James R Larrowe Date: Tue, 20 Aug 2024 13:36:41 -0400 Subject: [PATCH 0303/2181] Fix static asan patch --- scripts/hyprlandStaticAsan.diff | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/scripts/hyprlandStaticAsan.diff b/scripts/hyprlandStaticAsan.diff index e74eb6ab..b352d65d 100644 --- a/scripts/hyprlandStaticAsan.diff +++ b/scripts/hyprlandStaticAsan.diff @@ -1,13 +1,13 @@ diff --git a/CMakeLists.txt b/CMakeLists.txt -index f54cdf5d..ad7c3e73 100755 +index f26a5c3c..3dfef333 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt -@@ -130,6 +130,8 @@ if(CMAKE_BUILD_TYPE MATCHES Debug OR CMAKE_BUILD_TYPE MATCHES DEBUG) - message(STATUS "Enabling ASan") +@@ -143,6 +143,8 @@ if(CMAKE_BUILD_TYPE MATCHES Debug OR CMAKE_BUILD_TYPE MATCHES DEBUG) + message(STATUS "Enabling ASan") - target_link_libraries(Hyprland asan) -+ pkg_check_modules(ffidep REQUIRED IMPORTED_TARGET libffi) -+ target_link_libraries(Hyprland ${CMAKE_SOURCE_DIR}/libwayland-server.a PkgConfig::ffidep) - target_compile_options(Hyprland PUBLIC -fsanitize=address) - endif() + target_link_libraries(Hyprland asan) ++ pkg_check_modules(ffidep REQUIRED IMPORTED_TARGET libffi) ++ target_link_libraries(Hyprland ${CMAKE_SOURCE_DIR}/libwayland-server.a PkgConfig::ffidep) + target_compile_options(Hyprland PUBLIC -fsanitize=address) + endif() From 8162fae37728b3ae2b1a82a32663e76c59c4ce61 Mon Sep 17 00:00:00 2001 From: James R Larrowe Date: Tue, 20 Aug 2024 13:54:51 -0400 Subject: [PATCH 0304/2181] Fix Makefile too ... did this ever work? --- Makefile | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Makefile b/Makefile index adf6fbe8..bc7b750b 100644 --- a/Makefile +++ b/Makefile @@ -87,8 +87,8 @@ asan: #git reset --hard @echo -en "If you want to apply a patch, input its path (leave empty for none):\n" - @read patchvar - @if [-n "$patchvar"]; then patch -p1 < $patchvar || echo ""; else echo "No patch specified"; fi + @read patchvar; \ + if [ -n "$$patchvar" ]; then patch -p1 < "$$patchvar" || echo ""; else echo "No patch specified"; fi git clone --recursive https://gitlab.freedesktop.org/wayland/wayland cd wayland && patch -p1 < ../scripts/waylandStatic.diff && meson setup build --buildtype=debug -Db_sanitize=address -Ddocumentation=false && ninja -C build && cd .. From cae937c51bd220d6676c6027d05ea51fc3c821bb Mon Sep 17 00:00:00 2001 From: Tom Englund Date: Wed, 21 Aug 2024 23:05:03 +0200 Subject: [PATCH 0305/2181] layersurface: dont rollover on size_t (#7451) unneded rollover on size_t if force equals -1 --- src/desktop/LayerSurface.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/desktop/LayerSurface.cpp b/src/desktop/LayerSurface.cpp index c352fa74..8fd448ef 100644 --- a/src/desktop/LayerSurface.cpp +++ b/src/desktop/LayerSurface.cpp @@ -432,8 +432,8 @@ void CLayerSurface::startAnimation(bool in, bool instant) { PMONITOR->vecPosition + Vector2D{PMONITOR->vecSize.x, PMONITOR->vecSize.y / 2}, }; - float closest = std::numeric_limits::max(); - size_t leader = force; + float closest = std::numeric_limits::max(); + int leader = force; if (leader == -1) { for (size_t i = 0; i < 4; ++i) { float dist = MIDDLE.distance(edgePoints[i]); From a437e44a6af8e8f42966ffe3a26c1d562fce6b33 Mon Sep 17 00:00:00 2001 From: Florian Klink Date: Thu, 22 Aug 2024 13:04:13 +0300 Subject: [PATCH 0306/2181] CMakeLists: wayland.xml is in wayland-scanner pkgdatadir See https://gitlab.freedesktop.org/wayland/wayland/-/blob/6c4a695045155583a99f3fbce7bb745f79c2e726/meson.build#L129-136 Similar fix as https://github.com/hyprwm/aquamarine/pull/55. --- CMakeLists.txt | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index f26a5c3c..b1373e07 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -51,7 +51,7 @@ find_package(PkgConfig REQUIRED) pkg_get_variable(WAYLAND_PROTOCOLS_DIR wayland-protocols pkgdatadir) message(STATUS "Found wayland-protocols at ${WAYLAND_PROTOCOLS_DIR}") -pkg_get_variable(WAYLAND_SERVER_DIR wayland-server pkgdatadir) +pkg_get_variable(WAYLAND_SCANNER_PKGDATA_DIR wayland-scanner pkgdatadir) if(CMAKE_BUILD_TYPE MATCHES Debug OR CMAKE_BUILD_TYPE MATCHES DEBUG) message(STATUS "Configuring Hyprland in Debug with CMake") @@ -259,7 +259,7 @@ function(protocolWayland) OUTPUT ${CMAKE_SOURCE_DIR}/protocols/wayland.cpp ${CMAKE_SOURCE_DIR}/protocols/wayland.hpp COMMAND hyprwayland-scanner --wayland-enums - ${WAYLAND_SERVER_DIR}/wayland.xml ${CMAKE_SOURCE_DIR}/protocols/ + ${WAYLAND_SCANNER_PKGDATA_DIR}/wayland.xml ${CMAKE_SOURCE_DIR}/protocols/ WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}) target_sources(Hyprland PRIVATE protocols/wayland.cpp protocols/wayland.hpp) target_sources(generate-protocol-headers From 4fa63104c94ca5e2d2e3baaf3b3926db246b964c Mon Sep 17 00:00:00 2001 From: Mihai Fufezan Date: Thu, 22 Aug 2024 14:30:10 +0300 Subject: [PATCH 0307/2181] Nix: exclude wayland-scanner until next staging merge --- CMakeLists.txt | 13 ++++++------- nix/default.nix | 3 ++- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index b1373e07..e8ea4797 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -52,6 +52,8 @@ find_package(PkgConfig REQUIRED) pkg_get_variable(WAYLAND_PROTOCOLS_DIR wayland-protocols pkgdatadir) message(STATUS "Found wayland-protocols at ${WAYLAND_PROTOCOLS_DIR}") pkg_get_variable(WAYLAND_SCANNER_PKGDATA_DIR wayland-scanner pkgdatadir) +message( + STATUS "Found wayland-scanner pkgdatadir at ${WAYLAND_SCANNER_PKGDATA_DIR}") if(CMAKE_BUILD_TYPE MATCHES Debug OR CMAKE_BUILD_TYPE MATCHES DEBUG) message(STATUS "Configuring Hyprland in Debug with CMake") @@ -87,11 +89,7 @@ else() endif() find_package(OpenGL REQUIRED COMPONENTS ${GLES_VERSION}) -pkg_check_modules( - hyprctl_deps - REQUIRED - IMPORTED_TARGET - hyprutils>=0.2.1) +pkg_check_modules(hyprctl_deps REQUIRED IMPORTED_TARGET hyprutils>=0.2.1) pkg_check_modules( deps @@ -258,8 +256,9 @@ function(protocolWayland) add_custom_command( OUTPUT ${CMAKE_SOURCE_DIR}/protocols/wayland.cpp ${CMAKE_SOURCE_DIR}/protocols/wayland.hpp - COMMAND hyprwayland-scanner --wayland-enums - ${WAYLAND_SCANNER_PKGDATA_DIR}/wayland.xml ${CMAKE_SOURCE_DIR}/protocols/ + COMMAND + hyprwayland-scanner --wayland-enums + ${WAYLAND_SCANNER_PKGDATA_DIR}/wayland.xml ${CMAKE_SOURCE_DIR}/protocols/ WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}) target_sources(Hyprland PRIVATE protocols/wayland.cpp protocols/wayland.hpp) target_sources(generate-protocol-headers diff --git a/nix/default.nix b/nix/default.nix index c8eaf731..64796a90 100644 --- a/nix/default.nix +++ b/nix/default.nix @@ -97,7 +97,8 @@ assert lib.assertMsg (!hidpiXWayland) "The option `hidpiXWayland` has been remov ninja pkg-config python3 # for udis86 - wayland-scanner + # re-add after https://github.com/NixOS/nixpkgs/pull/214906 hits nixos-unstable + # wayland-scanner ]; outputs = [ From bdb296a83c595f3814f8159d2cffd25c3edfb842 Mon Sep 17 00:00:00 2001 From: Mihai Fufezan Date: Thu, 22 Aug 2024 14:30:17 +0300 Subject: [PATCH 0308/2181] flake.lock: update --- flake.lock | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/flake.lock b/flake.lock index 97016819..fd06ac7d 100644 --- a/flake.lock +++ b/flake.lock @@ -16,11 +16,11 @@ ] }, "locked": { - "lastModified": 1724006173, - "narHash": "sha256-1ROh0buuxiMyc6eIb3CIbJsmYO7PhLqSYs55mOx1XTk=", + "lastModified": 1724273991, + "narHash": "sha256-+aUSOXKGpS5CRm1oTitgNAr05ThQNbKIXalZHl3nC6Y=", "owner": "hyprwm", "repo": "aquamarine", - "rev": "7f8df01d4297b9068a9592400f16044602844f86", + "rev": "9a3161ad4c78dc420d1cbb3aae638222608c7de4", "type": "github" }, "original": { @@ -93,11 +93,11 @@ ] }, "locked": { - "lastModified": 1721324361, - "narHash": "sha256-BiJKO0IIdnSwHQBSrEJlKlFr753urkLE48wtt0UhNG4=", + "lastModified": 1724174162, + "narHash": "sha256-fOOBLwil6M9QWMCiSULwjMQzrXhHXUnEqmjHX5ZHeVI=", "owner": "hyprwm", "repo": "hyprlang", - "rev": "adbefbf49664a6c2c8bf36b6487fd31e3eb68086", + "rev": "16e5c9465f04477d8a3dd48a0a26bf437986336c", "type": "github" }, "original": { @@ -154,11 +154,11 @@ }, "nixpkgs": { "locked": { - "lastModified": 1723637854, - "narHash": "sha256-med8+5DSWa2UnOqtdICndjDAEjxr5D7zaIiK4pn0Q7c=", + "lastModified": 1724224976, + "narHash": "sha256-Z/ELQhrSd7bMzTO8r7NZgi9g5emh+aRKoCdaAv5fiO0=", "owner": "NixOS", "repo": "nixpkgs", - "rev": "c3aa7b8938b17aebd2deecf7be0636000d62a2b9", + "rev": "c374d94f1536013ca8e92341b540eba4c22f9c62", "type": "github" }, "original": { @@ -209,11 +209,11 @@ ] }, "locked": { - "lastModified": 1722365976, - "narHash": "sha256-Khdm+mDzYA//XaU0M+hftod+rKr5q9SSHSEuiQ0/9ow=", + "lastModified": 1724073926, + "narHash": "sha256-nWlUL43jOFHf+KW6Hqrx+W/r1XdXuDyb0wC/SrHsOu4=", "owner": "hyprwm", "repo": "xdg-desktop-portal-hyprland", - "rev": "7f2a77ddf60390248e2a3de2261d7102a13e5341", + "rev": "a08ecbbf33598924e93542f737fc6169a26b481e", "type": "github" }, "original": { From f634b9e61af7dae0ca70379bd207eea45bb417d1 Mon Sep 17 00:00:00 2001 From: Red <21181998+Redender64@users.noreply.github.com> Date: Thu, 22 Aug 2024 11:36:12 +0000 Subject: [PATCH 0309/2181] Fix crash reports having execute permission --- src/debug/CrashReporter.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/debug/CrashReporter.cpp b/src/debug/CrashReporter.cpp index c31975b8..000d8c5d 100644 --- a/src/debug/CrashReporter.cpp +++ b/src/debug/CrashReporter.cpp @@ -86,7 +86,7 @@ void CrashReporter::createAndSaveCrash(int sig) { stderr.flush(); } - reportFd = open(reportPath.get_str(), O_WRONLY | O_CREAT, S_IRWXU); + reportFd = open(reportPath.get_str(), O_WRONLY | O_CREAT, S_IRUSR | S_IWUSR); if (reportFd < 0) { exit_with_error("Failed to open crash report path for writing"); } From 3b663f4afcecb1abc93a61d6448183c5978f5cd2 Mon Sep 17 00:00:00 2001 From: vaxerski Date: Fri, 23 Aug 2024 14:13:43 +0200 Subject: [PATCH 0310/2181] screencopy: fixup 10-bit sharing via shm on nvidia --- src/protocols/Screencopy.cpp | 2 +- src/protocols/ToplevelExport.cpp | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/protocols/Screencopy.cpp b/src/protocols/Screencopy.cpp index b25d9456..1559476b 100644 --- a/src/protocols/Screencopy.cpp +++ b/src/protocols/Screencopy.cpp @@ -238,7 +238,7 @@ bool CScreencopyFrame::copyShm() { g_pHyprRenderer->makeEGLCurrent(); CFramebuffer fb; - fb.alloc(box.w, box.h, g_pHyprRenderer->isNvidia() ? DRM_FORMAT_XBGR8888 : pMonitor->output->state->state().drmFormat); + fb.alloc(box.w, box.h, pMonitor->output->state->state().drmFormat); if (!g_pHyprRenderer->beginRender(pMonitor, fakeDamage, RENDER_MODE_FULL_FAKE, nullptr, &fb, true)) { LOGM(ERR, "Can't copy: failed to begin rendering"); diff --git a/src/protocols/ToplevelExport.cpp b/src/protocols/ToplevelExport.cpp index 05e991d6..916f7395 100644 --- a/src/protocols/ToplevelExport.cpp +++ b/src/protocols/ToplevelExport.cpp @@ -245,7 +245,7 @@ bool CToplevelExportFrame::copyShm(timespec* now) { g_pHyprRenderer->makeEGLCurrent(); CFramebuffer outFB; - outFB.alloc(PMONITOR->vecPixelSize.x, PMONITOR->vecPixelSize.y, g_pHyprRenderer->isNvidia() ? DRM_FORMAT_XBGR8888 : PMONITOR->output->state->state().drmFormat); + outFB.alloc(PMONITOR->vecPixelSize.x, PMONITOR->vecPixelSize.y, PMONITOR->output->state->state().drmFormat); if (overlayCursor) { g_pPointerManager->lockSoftwareForMonitor(PMONITOR->self.lock()); From df4f222482a7c2a1116ef5c91ba6e4b55d94ad6c Mon Sep 17 00:00:00 2001 From: Tom Englund Date: Fri, 23 Aug 2024 15:06:52 +0200 Subject: [PATCH 0311/2181] layersurface: remove layer on destroy from monitor (#7457) remove destroyed layer weakptrs on destroy, we can hit multiple null ptr derefs in renderering on mirroring and unmirroring displays otherwise. --- src/desktop/LayerSurface.cpp | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/desktop/LayerSurface.cpp b/src/desktop/LayerSurface.cpp index 8fd448ef..46aea86c 100644 --- a/src/desktop/LayerSurface.cpp +++ b/src/desktop/LayerSurface.cpp @@ -107,6 +107,12 @@ void CLayerSurface::onDestroy() { g_pHyprRenderer->damageBox(&geomFixed); } + for (auto& mon : g_pCompositor->m_vRealMonitors) { + for (auto& lsl : mon->m_aLayerSurfaceLayers) { + std::erase_if(lsl, [this](auto& ls) { return ls.expired() || ls.get() == this; }); + } + } + readyToDelete = true; layerSurface.reset(); if (surface) From a3b75559b35880a85149ab0b644cc0c26cdfdae1 Mon Sep 17 00:00:00 2001 From: MahouShoujoMivutilde <14999778+MahouShoujoMivutilde@users.noreply.github.com> Date: Fri, 23 Aug 2024 22:35:52 +0300 Subject: [PATCH 0312/2181] input: Fix modifier keys getting stuck if depressed during config reload (#7486) The problem: If `input:numlock_by_default = true`, depressed mods will get stuck on config reload; this takes effect after some other mod is pressed. This restores 0.41.2 behavior, with the exception that selected keyboard layout is preserved. https://github.com/hyprwm/Hyprland/blob/918d8340afd652b011b937d29d5eea0be08467f5/src/managers/input/InputManager.cpp#L993-L1002 --- src/devices/IKeyboard.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/devices/IKeyboard.cpp b/src/devices/IKeyboard.cpp index e05cbd04..13440169 100644 --- a/src/devices/IKeyboard.cpp +++ b/src/devices/IKeyboard.cpp @@ -119,7 +119,8 @@ void IKeyboard::setKeymap(const SStringRuleNames& rules) { if (IDX != XKB_MOD_INVALID) modifiersState.locked |= (uint32_t)1 << IDX; - updateModifiers(modifiersState.depressed, modifiersState.latched, modifiersState.locked, modifiersState.group); + // 0 to avoid mods getting stuck if depressed during reload + updateModifiers(0, 0, modifiersState.locked, modifiersState.group); } for (size_t i = 0; i < LEDNAMES.size(); ++i) { From 688fe5c14781c63a1db23d4d02bf239283068ff6 Mon Sep 17 00:00:00 2001 From: Sungyoon Cho Date: Sat, 24 Aug 2024 04:42:14 +0900 Subject: [PATCH 0313/2181] windowrules: add fullscreenstate field (#7466) * windowrules: add fullscreenstate field * fix typo --- src/Compositor.cpp | 7 ++-- src/config/ConfigManager.cpp | 62 ++++++++++++++++++++++++++++-------- src/desktop/Window.hpp | 15 +++++---- 3 files changed, 61 insertions(+), 23 deletions(-) diff --git a/src/Compositor.cpp b/src/Compositor.cpp index 75c22743..c9a698ce 100644 --- a/src/Compositor.cpp +++ b/src/Compositor.cpp @@ -2326,8 +2326,12 @@ void CCompositor::setWindowFullscreenState(const PHLWINDOW PWINDOW, sFullscreenS PWINDOW->m_sFullscreenState.client = state.client; g_pXWaylandManager->setWindowFullscreen(PWINDOW, state.client & FSMODE_FULLSCREEN); - if (!CHANGEINTERNAL) + if (!CHANGEINTERNAL) { + PWINDOW->updateDynamicRules(); + updateWindowAnimatedDecorationValues(PWINDOW); + g_pLayoutManager->getCurrentLayout()->recalculateMonitor(PWINDOW->m_iMonitorID); return; + } g_pLayoutManager->getCurrentLayout()->fullscreenRequestForWindow(PWINDOW, CURRENT_EFFECTIVE_MODE, EFFECTIVE_MODE); @@ -2339,7 +2343,6 @@ void CCompositor::setWindowFullscreenState(const PHLWINDOW PWINDOW, sFullscreenS EMIT_HOOK_EVENT("fullscreen", PWINDOW); PWINDOW->updateDynamicRules(); - PWINDOW->updateWindowDecos(); updateWindowAnimatedDecorationValues(PWINDOW); g_pLayoutManager->getCurrentLayout()->recalculateMonitor(PWINDOW->m_iMonitorID); diff --git a/src/config/ConfigManager.cpp b/src/config/ConfigManager.cpp index e2ae2c47..51b1e1d2 100644 --- a/src/config/ConfigManager.cpp +++ b/src/config/ConfigManager.cpp @@ -1212,6 +1212,32 @@ std::vector CConfigManager::getMatchingRules(PHLWINDOW pWindow, boo continue; } + if (!rule.szFullscreenState.empty()) { + const auto ARGS = CVarList(rule.szFullscreenState, 2, ' '); + // + std::optional internalMode, clientMode; + + if (ARGS[0] == "*") + internalMode = {}; + else if (isNumber(ARGS[0])) + internalMode = (eFullscreenMode)std::stoi(ARGS[0]); + else + throw std::runtime_error("szFullscreenState internal mode not valid"); + + if (ARGS[1] == "*") + clientMode = {}; + else if (isNumber(ARGS[1])) + clientMode = (eFullscreenMode)std::stoi(ARGS[1]); + else + throw std::runtime_error("szFullscreenState client mode not valid"); + + if (internalMode.has_value() && pWindow->m_sFullscreenState.internal != internalMode) + continue; + + if (clientMode.has_value() && pWindow->m_sFullscreenState.client != clientMode) + continue; + } + if (!rule.szOnWorkspace.empty()) { const auto PWORKSPACE = pWindow->m_pWorkspace; if (!PWORKSPACE || !PWORKSPACE->matchesStaticSelector(rule.szOnWorkspace)) @@ -2219,17 +2245,18 @@ std::optional CConfigManager::handleWindowRuleV2(const std::string& rule.szRule = RULE; rule.szValue = VALUE; - const auto TAGPOS = VALUE.find("tag:"); - const auto TITLEPOS = VALUE.find("title:"); - const auto CLASSPOS = VALUE.find("class:"); - const auto INITIALTITLEPOS = VALUE.find("initialTitle:"); - const auto INITIALCLASSPOS = VALUE.find("initialClass:"); - const auto X11POS = VALUE.find("xwayland:"); - const auto FLOATPOS = VALUE.find("floating:"); - const auto FULLSCREENPOS = VALUE.find("fullscreen:"); - const auto PINNEDPOS = VALUE.find("pinned:"); - const auto FOCUSPOS = VALUE.find("focus:"); - const auto ONWORKSPACEPOS = VALUE.find("onworkspace:"); + const auto TAGPOS = VALUE.find("tag:"); + const auto TITLEPOS = VALUE.find("title:"); + const auto CLASSPOS = VALUE.find("class:"); + const auto INITIALTITLEPOS = VALUE.find("initialTitle:"); + const auto INITIALCLASSPOS = VALUE.find("initialClass:"); + const auto X11POS = VALUE.find("xwayland:"); + const auto FLOATPOS = VALUE.find("floating:"); + const auto FULLSCREENPOS = VALUE.find("fullscreen:"); + const auto PINNEDPOS = VALUE.find("pinned:"); + const auto FOCUSPOS = VALUE.find("focus:"); + const auto FULLSCREENSTATEPOS = VALUE.find("fullscreenstate:"); + const auto ONWORKSPACEPOS = VALUE.find("onworkspace:"); // find workspacepos that isn't onworkspacepos size_t WORKSPACEPOS = std::string::npos; @@ -2242,9 +2269,8 @@ std::optional CConfigManager::handleWindowRuleV2(const std::string& currentPos = VALUE.find("workspace:", currentPos + 1); } - const auto checkPos = std::unordered_set{ - TAGPOS, TITLEPOS, CLASSPOS, INITIALTITLEPOS, INITIALCLASSPOS, X11POS, FLOATPOS, FULLSCREENPOS, PINNEDPOS, WORKSPACEPOS, FOCUSPOS, ONWORKSPACEPOS, - }; + const auto checkPos = std::unordered_set{TAGPOS, TITLEPOS, CLASSPOS, INITIALTITLEPOS, INITIALCLASSPOS, X11POS, FLOATPOS, + FULLSCREENPOS, PINNEDPOS, FULLSCREENSTATEPOS, WORKSPACEPOS, FOCUSPOS, ONWORKSPACEPOS}; if (checkPos.size() == 1 && checkPos.contains(std::string::npos)) { Debug::log(ERR, "Invalid rulev2 syntax: {}", VALUE); return "Invalid rulev2 syntax: " + VALUE; @@ -2273,6 +2299,8 @@ std::optional CConfigManager::handleWindowRuleV2(const std::string& min = FULLSCREENPOS; if (PINNEDPOS > pos && PINNEDPOS < min) min = PINNEDPOS; + if (FULLSCREENSTATEPOS > pos && FULLSCREENSTATEPOS < min) + min = FULLSCREENSTATEPOS; if (ONWORKSPACEPOS > pos && ONWORKSPACEPOS < min) min = ONWORKSPACEPOS; if (WORKSPACEPOS > pos && WORKSPACEPOS < min) @@ -2317,6 +2345,9 @@ std::optional CConfigManager::handleWindowRuleV2(const std::string& if (PINNEDPOS != std::string::npos) rule.bPinned = extract(PINNEDPOS + 7) == "1" ? 1 : 0; + if (FULLSCREENSTATEPOS != std::string::npos) + rule.szFullscreenState = extract(FULLSCREENSTATEPOS + 16); + if (WORKSPACEPOS != std::string::npos) rule.szWorkspace = extract(WORKSPACEPOS + 10); @@ -2358,6 +2389,9 @@ std::optional CConfigManager::handleWindowRuleV2(const std::string& if (rule.bPinned != -1 && rule.bPinned != other.bPinned) return false; + if (!rule.szFullscreenState.empty() && rule.szFullscreenState != other.szFullscreenState) + return false; + if (!rule.szWorkspace.empty() && rule.szWorkspace != other.szWorkspace) return false; diff --git a/src/desktop/Window.hpp b/src/desktop/Window.hpp index 2e5b54b1..e1850fb3 100644 --- a/src/desktop/Window.hpp +++ b/src/desktop/Window.hpp @@ -196,13 +196,14 @@ struct SWindowRule { std::string szInitialTitle; std::string szInitialClass; std::string szTag; - int bX11 = -1; // -1 means "ANY" - int bFloating = -1; - int bFullscreen = -1; - int bPinned = -1; - int bFocus = -1; - std::string szOnWorkspace = ""; // empty means any - std::string szWorkspace = ""; // empty means any + int bX11 = -1; // -1 means "ANY" + int bFloating = -1; + int bFullscreen = -1; + int bPinned = -1; + int bFocus = -1; + std::string szFullscreenState = ""; // empty means any + std::string szOnWorkspace = ""; // empty means any + std::string szWorkspace = ""; // empty means any }; struct SInitialWorkspaceToken { From e45e606fbd7f7e805eb5a1c81482ea44b66e88d2 Mon Sep 17 00:00:00 2001 From: Vaxry Date: Sat, 24 Aug 2024 15:22:10 +0200 Subject: [PATCH 0314/2181] layersurface: don't unref from monitor until dtor reee --- src/desktop/LayerSurface.cpp | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/desktop/LayerSurface.cpp b/src/desktop/LayerSurface.cpp index 46aea86c..8d13bf19 100644 --- a/src/desktop/LayerSurface.cpp +++ b/src/desktop/LayerSurface.cpp @@ -71,6 +71,12 @@ CLayerSurface::~CLayerSurface() { surface->unassign(); g_pHyprRenderer->makeEGLCurrent(); std::erase_if(g_pHyprOpenGL->m_mLayerFramebuffers, [&](const auto& other) { return other.first.expired() || other.first.lock() == self.lock(); }); + + for (auto& mon : g_pCompositor->m_vRealMonitors) { + for (auto& lsl : mon->m_aLayerSurfaceLayers) { + std::erase_if(lsl, [this](auto& ls) { return ls.expired() || ls.get() == this; }); + } + } } void CLayerSurface::onDestroy() { @@ -107,12 +113,6 @@ void CLayerSurface::onDestroy() { g_pHyprRenderer->damageBox(&geomFixed); } - for (auto& mon : g_pCompositor->m_vRealMonitors) { - for (auto& lsl : mon->m_aLayerSurfaceLayers) { - std::erase_if(lsl, [this](auto& ls) { return ls.expired() || ls.get() == this; }); - } - } - readyToDelete = true; layerSurface.reset(); if (surface) From 82c67e61a96b23c7b962ab8e3ed9079f671942e1 Mon Sep 17 00:00:00 2001 From: Vaxry Date: Sat, 24 Aug 2024 15:24:55 +0200 Subject: [PATCH 0315/2181] config: fix uninitialized values with mode parsing --- src/config/ConfigManager.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/config/ConfigManager.cpp b/src/config/ConfigManager.cpp index 51b1e1d2..0390b9d9 100644 --- a/src/config/ConfigManager.cpp +++ b/src/config/ConfigManager.cpp @@ -1218,14 +1218,14 @@ std::vector CConfigManager::getMatchingRules(PHLWINDOW pWindow, boo std::optional internalMode, clientMode; if (ARGS[0] == "*") - internalMode = {}; + internalMode = std::nullopt; else if (isNumber(ARGS[0])) internalMode = (eFullscreenMode)std::stoi(ARGS[0]); else throw std::runtime_error("szFullscreenState internal mode not valid"); if (ARGS[1] == "*") - clientMode = {}; + clientMode = std::nullopt; else if (isNumber(ARGS[1])) clientMode = (eFullscreenMode)std::stoi(ARGS[1]); else From 66586c38f53f16bcf762f019359a3c9042546a72 Mon Sep 17 00:00:00 2001 From: Ikalco <73481042+ikalco@users.noreply.github.com> Date: Sat, 24 Aug 2024 11:45:53 -0500 Subject: [PATCH 0316/2181] keybinds: refactor dispatchers to be better (#7331) --- src/debug/HyprCtl.cpp | 6 +- src/managers/KeybindManager.cpp | 578 ++++++++++++++++++++------------ src/managers/KeybindManager.hpp | 171 +++++----- src/plugins/PluginAPI.cpp | 7 +- 4 files changed, 457 insertions(+), 305 deletions(-) diff --git a/src/debug/HyprCtl.cpp b/src/debug/HyprCtl.cpp index 78c8504a..a92c3a53 100644 --- a/src/debug/HyprCtl.cpp +++ b/src/debug/HyprCtl.cpp @@ -962,11 +962,11 @@ std::string dispatchRequest(eHyprCtlOutputFormat format, std::string in) { if (DISPATCHER == g_pKeybindManager->m_mDispatchers.end()) return "Invalid dispatcher"; - DISPATCHER->second(DISPATCHARG); + SDispatchResult res = DISPATCHER->second(DISPATCHARG); - Debug::log(LOG, "Hyprctl: dispatcher {} : {}", DISPATCHSTR, DISPATCHARG); + Debug::log(LOG, "Hyprctl: dispatcher {} : {}{}", DISPATCHSTR, DISPATCHARG, res.success ? "" : " -> " + res.error); - return "ok"; + return res.success ? "ok" : res.error; } std::string dispatchKeyword(eHyprCtlOutputFormat format, std::string in) { diff --git a/src/managers/KeybindManager.cpp b/src/managers/KeybindManager.cpp index 38593497..8bf7152e 100644 --- a/src/managers/KeybindManager.cpp +++ b/src/managers/KeybindManager.cpp @@ -405,7 +405,7 @@ bool CKeybindManager::onKeyEvent(std::any event, SP pKeyboard) { m_dPressedKeys.push_back(KEY); - suppressEvent = handleKeybinds(MODS, KEY, true); + suppressEvent = !handleKeybinds(MODS, KEY, true).passEvent; if (suppressEvent) shadowKeybinds(keysym, KEYCODE); @@ -427,7 +427,7 @@ bool CKeybindManager::onKeyEvent(std::any event, SP pKeyboard) { if (!foundInPressedKeys) { Debug::log(ERR, "BUG THIS: key not found in m_dPressedKeys"); // fallback with wrong `KEY.modmaskAtPressTime`, this can be buggy - suppressEvent = handleKeybinds(MODS, KEY, false); + suppressEvent = !handleKeybinds(MODS, KEY, false).passEvent; } shadowKeybinds(); @@ -457,14 +457,14 @@ bool CKeybindManager::onAxisEvent(const IPointer::SAxisEvent& e) { bool found = false; if (e.source == WL_POINTER_AXIS_SOURCE_WHEEL && e.axis == WL_POINTER_AXIS_VERTICAL_SCROLL) { if (e.delta < 0) - found = handleKeybinds(MODS, SPressedKeyWithMods{.keyName = "mouse_down"}, true); + found = !handleKeybinds(MODS, SPressedKeyWithMods{.keyName = "mouse_down"}, true).passEvent; else - found = handleKeybinds(MODS, SPressedKeyWithMods{.keyName = "mouse_up"}, true); + found = !handleKeybinds(MODS, SPressedKeyWithMods{.keyName = "mouse_up"}, true).passEvent; } else if (e.source == WL_POINTER_AXIS_SOURCE_WHEEL && e.axis == WL_POINTER_AXIS_HORIZONTAL_SCROLL) { if (e.delta < 0) - found = handleKeybinds(MODS, SPressedKeyWithMods{.keyName = "mouse_left"}, true); + found = !handleKeybinds(MODS, SPressedKeyWithMods{.keyName = "mouse_left"}, true).passEvent; else - found = handleKeybinds(MODS, SPressedKeyWithMods{.keyName = "mouse_right"}, true); + found = !handleKeybinds(MODS, SPressedKeyWithMods{.keyName = "mouse_right"}, true).passEvent; } if (found) @@ -500,7 +500,7 @@ bool CKeybindManager::onMouseEvent(const IPointer::SButtonEvent& e) { if (e.state == WL_POINTER_BUTTON_STATE_PRESSED) { m_dPressedKeys.push_back(KEY); - suppressEvent = handleKeybinds(MODS, KEY, true); + suppressEvent = !handleKeybinds(MODS, KEY, true).passEvent; if (suppressEvent) shadowKeybinds(); @@ -510,7 +510,7 @@ bool CKeybindManager::onMouseEvent(const IPointer::SButtonEvent& e) { bool foundInPressedKeys = false; for (auto it = m_dPressedKeys.begin(); it != m_dPressedKeys.end();) { if (it->keyName == KEY_NAME) { - suppressEvent = handleKeybinds(MODS, *it, false); + suppressEvent = !handleKeybinds(MODS, *it, false).passEvent; foundInPressedKeys = true; suppressEvent = !it->sent; it = m_dPressedKeys.erase(it); @@ -521,7 +521,7 @@ bool CKeybindManager::onMouseEvent(const IPointer::SButtonEvent& e) { if (!foundInPressedKeys) { Debug::log(ERR, "BUG THIS: key not found in m_dPressedKeys (2)"); // fallback with wrong `KEY.modmaskAtPressTime`, this can be buggy - suppressEvent = handleKeybinds(MODS, KEY, false); + suppressEvent = !handleKeybinds(MODS, KEY, false).passEvent; } shadowKeybinds(); @@ -590,8 +590,10 @@ eMultiKeyCase CKeybindManager::mkBindMatches(const SKeybind keybind) { return mkKeysymSetMatches(keybind.sMkKeys, m_sMkKeys); } -bool CKeybindManager::handleKeybinds(const uint32_t modmask, const SPressedKeyWithMods& key, bool pressed) { - bool found = false; +SDispatchResult CKeybindManager::handleKeybinds(const uint32_t modmask, const SPressedKeyWithMods& key, bool pressed) { + static auto PDISABLEINHIBIT = CConfigValue("binds:disable_keybind_grabbing"); + bool found = false; + SDispatchResult res; if (pressed) { if (keycodeToModifier(key.keycode)) @@ -605,11 +607,6 @@ bool CKeybindManager::handleKeybinds(const uint32_t modmask, const SPressedKeyWi m_sMkKeys.erase(key.keysym); } - static auto PDISABLEINHIBIT = CConfigValue("binds:disable_keybind_grabbing"); - - if (!*PDISABLEINHIBIT && PROTO::shortcutsInhibit->isInhibited()) - Debug::log(LOG, "Keybind handling is disabled due to an inhibitor"); - for (auto& k : m_lKeybinds) { const bool SPECIALDISPATCHER = k.handler == "global" || k.handler == "pass" || k.handler == "sendshortcut" || k.handler == "mouse"; const bool SPECIALTRIGGERED = @@ -711,10 +708,11 @@ bool CKeybindManager::handleKeybinds(const uint32_t modmask, const SPressedKeyWi m_iPassPressed = (int)pressed; + // if the dispatchers says to pass event then we will if (k.handler == "mouse") - DISPATCHER->second((pressed ? "1" : "0") + k.arg); + res = DISPATCHER->second((pressed ? "1" : "0") + k.arg); else - DISPATCHER->second(k.arg); + res = DISPATCHER->second(k.arg); m_iPassPressed = -1; @@ -737,7 +735,18 @@ bool CKeybindManager::handleKeybinds(const uint32_t modmask, const SPressedKeyWi found = true; } - return found; + // if keybind wasn't found (or dispatcher said to) then pass event + res.passEvent |= !found; + + if (!found && !*PDISABLEINHIBIT && PROTO::shortcutsInhibit->isInhibited()) { + Debug::log(LOG, "Keybind handling is disabled due to an inhibitor"); + + res.success = false; + if (res.error.empty()) + res.error = "Keybind handling is disabled due to an inhibitor"; + } + + return res; } void CKeybindManager::shadowKeybinds(const xkb_keysym_t& doesntHave, const uint32_t doesntHaveCode) { @@ -838,7 +847,7 @@ bool CKeybindManager::handleInternalKeybinds(xkb_keysym_t keysym) { // Dispatchers -void CKeybindManager::spawn(std::string args) { +SDispatchResult CKeybindManager::spawn(std::string args) { args = trim(args); @@ -850,7 +859,7 @@ void CKeybindManager::spawn(std::string args) { args = args.substr(args.find_first_of(']') + 1); } - const uint64_t PROC = spawnRaw(args); + const uint64_t PROC = spawnRawProc(args); if (!RULES.empty()) { const auto RULESLIST = CVarList(RULES, 0, ';'); @@ -861,9 +870,16 @@ void CKeybindManager::spawn(std::string args) { Debug::log(LOG, "Applied {} rule arguments for exec.", RULESLIST.size()); } + + return {.success = PROC > 0, .error = std::format("Failed to start process {}", args)}; } -uint64_t CKeybindManager::spawnRaw(std::string args) { +SDispatchResult CKeybindManager::spawnRaw(std::string args) { + const uint64_t PROC = spawnRawProc(args); + return {.success = PROC > 0, .error = std::format("Failed to start process {}", args)}; +} + +uint64_t CKeybindManager::spawnRawProc(std::string args) { Debug::log(LOG, "Executing {}", args); const auto HLENV = getHyprlandLaunchEnv(); @@ -924,26 +940,30 @@ uint64_t CKeybindManager::spawnRaw(std::string args) { return grandchild; } -void CKeybindManager::killActive(std::string args) { +SDispatchResult CKeybindManager::killActive(std::string args) { g_pCompositor->closeWindow(g_pCompositor->m_pLastWindow.lock()); + + return {}; } -void CKeybindManager::kill(std::string args) { +SDispatchResult CKeybindManager::kill(std::string args) { const auto PWINDOW = g_pCompositor->getWindowByRegex(args); if (!PWINDOW) { Debug::log(ERR, "kill: no window found"); - return; + return {.success = false, .error = "kill: no window found"}; } g_pCompositor->closeWindow(PWINDOW); + + return {}; } void CKeybindManager::clearKeybinds() { m_lKeybinds.clear(); } -static void toggleActiveFloatingCore(std::string args, std::optional floatState) { +static SDispatchResult toggleActiveFloatingCore(std::string args, std::optional floatState) { PHLWINDOW PWINDOW = nullptr; if (args != "active" && args.length() > 1) @@ -952,10 +972,10 @@ static void toggleActiveFloatingCore(std::string args, std::optional float PWINDOW = g_pCompositor->m_pLastWindow.lock(); if (!PWINDOW) - return; + return {.success = false, .error = "Window not found"}; if (floatState.has_value() && floatState == PWINDOW->m_bIsFloating) - return; + return {}; // remove drag status if (!g_pInputManager->currentlyDraggedWindow.expired()) @@ -981,25 +1001,27 @@ static void toggleActiveFloatingCore(std::string args, std::optional float g_pCompositor->updateWorkspaceWindowData(PWINDOW->workspaceID()); g_pLayoutManager->getCurrentLayout()->recalculateMonitor(PWINDOW->m_iMonitorID); g_pCompositor->updateAllWindowsAnimatedDecorationValues(); + + return {}; } -void CKeybindManager::toggleActiveFloating(std::string args) { +SDispatchResult CKeybindManager::toggleActiveFloating(std::string args) { return toggleActiveFloatingCore(args, std::nullopt); } -void CKeybindManager::setActiveFloating(std::string args) { +SDispatchResult CKeybindManager::setActiveFloating(std::string args) { return toggleActiveFloatingCore(args, true); } -void CKeybindManager::setActiveTiled(std::string args) { +SDispatchResult CKeybindManager::setActiveTiled(std::string args) { return toggleActiveFloatingCore(args, false); } -void CKeybindManager::centerWindow(std::string args) { +SDispatchResult CKeybindManager::centerWindow(std::string args) { const auto PWINDOW = g_pCompositor->m_pLastWindow.lock(); if (!PWINDOW || !PWINDOW->m_bIsFloating || PWINDOW->isFullscreen()) - return; + return {.success = false, .error = "No floating window found"}; const auto PMONITOR = g_pCompositor->getMonitorFromID(PWINDOW->m_iMonitorID); @@ -1009,9 +1031,11 @@ void CKeybindManager::centerWindow(std::string args) { PWINDOW->m_vRealPosition = PMONITOR->middle() - PWINDOW->m_vRealSize.goal() / 2.f + RESERVEDOFFSET; PWINDOW->m_vPosition = PWINDOW->m_vRealPosition.goal(); + + return {}; } -void CKeybindManager::toggleActivePseudo(std::string args) { +SDispatchResult CKeybindManager::toggleActivePseudo(std::string args) { PHLWINDOW PWINDOW = nullptr; if (args != "active" && args.length() > 1) @@ -1020,12 +1044,14 @@ void CKeybindManager::toggleActivePseudo(std::string args) { PWINDOW = g_pCompositor->m_pLastWindow.lock(); if (!PWINDOW) - return; + return {.success = false, .error = "Window not found"}; PWINDOW->m_bIsPseudotiled = !PWINDOW->m_bIsPseudotiled; if (!PWINDOW->isFullscreen()) g_pLayoutManager->getCurrentLayout()->recalculateWindow(PWINDOW); + + return {}; } SWorkspaceIDName getWorkspaceToChangeFromArgs(std::string args, PHLWORKSPACE PCURRENTWORKSPACE) { @@ -1051,7 +1077,7 @@ SWorkspaceIDName getWorkspaceToChangeFromArgs(std::string args, PHLWORKSPACE PCU return {ID, PPREVWS.name.empty() ? std::to_string(PPREVWS.id) : PPREVWS.name}; } -void CKeybindManager::changeworkspace(std::string args) { +SDispatchResult CKeybindManager::changeworkspace(std::string args) { // Workspace_back_and_forth being enabled means that an attempt to switch to // the current workspace will instead switch to the previous. static auto PBACKANDFORTH = CConfigValue("binds:workspace_back_and_forth"); @@ -1061,7 +1087,7 @@ void CKeybindManager::changeworkspace(std::string args) { const auto PMONITOR = g_pCompositor->m_pLastMonitor.get(); if (!PMONITOR) - return; + return {.success = false, .error = "Last monitor not found"}; const auto PCURRENTWORKSPACE = PMONITOR->activeWorkspace; const bool EXPLICITPREVIOUS = args.contains("previous"); @@ -1069,18 +1095,17 @@ void CKeybindManager::changeworkspace(std::string args) { const auto& [workspaceToChangeTo, workspaceName] = getWorkspaceToChangeFromArgs(args, PCURRENTWORKSPACE); if (workspaceToChangeTo == WORKSPACE_INVALID) { Debug::log(ERR, "Error in changeworkspace, invalid value"); - return; + return {.success = false, .error = "Error in changeworkspace, invalid value"}; } - if (workspaceToChangeTo == WORKSPACE_NOT_CHANGED) { - return; - } + if (workspaceToChangeTo == WORKSPACE_NOT_CHANGED) + return {}; const auto PREVWS = PCURRENTWORKSPACE->getPrevWorkspaceIDName(args.contains("_per_monitor")); const bool BISWORKSPACECURRENT = workspaceToChangeTo == PCURRENTWORKSPACE->m_iID; if (BISWORKSPACECURRENT && (!(*PBACKANDFORTH || EXPLICITPREVIOUS) || PREVWS.id == -1)) - return; + return {.success = false, .error = "Previous workspace doesn't exist"}; g_pInputManager->unconstrainMouse(); g_pInputManager->m_bEmptyFocusCursorSet = false; @@ -1093,7 +1118,7 @@ void CKeybindManager::changeworkspace(std::string args) { if (!BISWORKSPACECURRENT && pWorkspaceToChangeTo->m_bIsSpecialWorkspace) { PMONITOR->setSpecialWorkspace(pWorkspaceToChangeTo); g_pInputManager->simulateMouseMovement(); - return; + return {}; } g_pInputManager->releaseAllMouseButtons(); @@ -1101,7 +1126,7 @@ void CKeybindManager::changeworkspace(std::string args) { const auto PMONITORWORKSPACEOWNER = PMONITOR->ID == pWorkspaceToChangeTo->m_iMonitorID ? PMONITOR : g_pCompositor->getMonitorFromID(pWorkspaceToChangeTo->m_iMonitorID); if (!PMONITORWORKSPACEOWNER) - return; + return {.success = false, .error = "Workspace to switch to has no monitor"}; updateRelativeCursorCoords(); @@ -1143,13 +1168,15 @@ void CKeybindManager::changeworkspace(std::string args) { if (PLAST && (!HLSurface || HLSurface->getWindow())) PLAST->warpCursor(); } + + return {}; } -void CKeybindManager::fullscreenActive(std::string args) { +SDispatchResult CKeybindManager::fullscreenActive(std::string args) { const auto PWINDOW = g_pCompositor->m_pLastWindow.lock(); if (!PWINDOW) - return; + return {.success = false, .error = "Window not found"}; const eFullscreenMode MODE = args == "1" ? FSMODE_MAXIMIZED : FSMODE_FULLSCREEN; @@ -1157,14 +1184,16 @@ void CKeybindManager::fullscreenActive(std::string args) { g_pCompositor->setWindowFullscreenInternal(PWINDOW, FSMODE_NONE); else g_pCompositor->setWindowFullscreenInternal(PWINDOW, MODE); + + return {}; } -void CKeybindManager::fullscreenStateActive(std::string args) { +SDispatchResult CKeybindManager::fullscreenStateActive(std::string args) { const auto PWINDOW = g_pCompositor->m_pLastWindow.lock(); const auto ARGS = CVarList(args, 2, ' '); if (!PWINDOW) - return; + return {.success = false, .error = "Window not found"}; PWINDOW->m_sWindowData.syncFullscreen = CWindowOverridableVar(false, PRIORITY_SET_PROP); @@ -1189,9 +1218,11 @@ void CKeybindManager::fullscreenStateActive(std::string args) { g_pCompositor->setWindowFullscreenState(PWINDOW, STATE); PWINDOW->m_sWindowData.syncFullscreen = CWindowOverridableVar(PWINDOW->m_sFullscreenState.internal == PWINDOW->m_sFullscreenState.client, PRIORITY_SET_PROP); + + return {}; } -void CKeybindManager::moveActiveToWorkspace(std::string args) { +SDispatchResult CKeybindManager::moveActiveToWorkspace(std::string args) { PHLWINDOW PWINDOW = nullptr; @@ -1203,17 +1234,17 @@ void CKeybindManager::moveActiveToWorkspace(std::string args) { } if (!PWINDOW) - return; + return {.success = false, .error = "Window not found"}; const auto& [WORKSPACEID, workspaceName] = getWorkspaceIDNameFromString(args); if (WORKSPACEID == WORKSPACE_INVALID) { Debug::log(LOG, "Invalid workspace in moveActiveToWorkspace"); - return; + return {.success = false, .error = "Invalid workspace in moveActiveToWorkspace"}; } if (WORKSPACEID == PWINDOW->workspaceID()) { Debug::log(LOG, "Not moving to workspace because it didn't change."); - return; + return {.success = false, .error = "Not moving to workspace because it didn't change."}; } auto pWorkspace = g_pCompositor->getWorkspaceByID(WORKSPACEID); @@ -1249,9 +1280,11 @@ void CKeybindManager::moveActiveToWorkspace(std::string args) { g_pCompositor->focusWindow(PWINDOW); PWINDOW->warpCursor(); + + return {}; } -void CKeybindManager::moveActiveToWorkspaceSilent(std::string args) { +SDispatchResult CKeybindManager::moveActiveToWorkspaceSilent(std::string args) { PHLWINDOW PWINDOW = nullptr; const auto ORIGINALARGS = args; @@ -1264,16 +1297,16 @@ void CKeybindManager::moveActiveToWorkspaceSilent(std::string args) { } if (!PWINDOW) - return; + return {.success = false, .error = "Window not found"}; const auto& [WORKSPACEID, workspaceName] = getWorkspaceIDNameFromString(args); if (WORKSPACEID == WORKSPACE_INVALID) { Debug::log(ERR, "Error in moveActiveToWorkspaceSilent, invalid value"); - return; + return {.success = false, .error = "Error in moveActiveToWorkspaceSilent, invalid value"}; } if (WORKSPACEID == PWINDOW->workspaceID()) - return; + return {}; g_pHyprRenderer->damageWindow(PWINDOW); @@ -1293,16 +1326,18 @@ void CKeybindManager::moveActiveToWorkspaceSilent(std::string args) { else g_pInputManager->refocus(); } + + return {}; } -void CKeybindManager::moveFocusTo(std::string args) { +SDispatchResult CKeybindManager::moveFocusTo(std::string args) { static auto PFULLCYCLE = CConfigValue("binds:movefocus_cycles_fullscreen"); static auto PMONITORFALLBACK = CConfigValue("binds:window_direction_monitor_fallback"); char arg = args[0]; if (!isDirection(args)) { Debug::log(ERR, "Cannot move focus in direction {}, unsupported direction. Supported: l,r,u/t,d/b", arg); - return; + return {.success = false, .error = std::format("Cannot move focus in direction {}, unsupported direction. Supported: l,r,u/t,d/b", arg)}; } const auto PLASTWINDOW = g_pCompositor->m_pLastWindow.lock(); @@ -1310,7 +1345,7 @@ void CKeybindManager::moveFocusTo(std::string args) { if (*PMONITORFALLBACK) tryMoveFocusToMonitor(g_pCompositor->getMonitorInDirection(arg)); - return; + return {}; } const auto PWINDOWTOCHANGETO = *PFULLCYCLE && PLASTWINDOW->isFullscreen() ? @@ -1320,69 +1355,81 @@ void CKeybindManager::moveFocusTo(std::string args) { // Found window in direction, switch to it if (PWINDOWTOCHANGETO) { switchToWindow(PWINDOWTOCHANGETO); - return; + return {}; } Debug::log(LOG, "No window found in direction {}, looking for a monitor", arg); if (*PMONITORFALLBACK && tryMoveFocusToMonitor(g_pCompositor->getMonitorInDirection(arg))) - return; + return {}; static auto PNOFALLBACK = CConfigValue("general:no_focus_fallback"); if (*PNOFALLBACK) - return; + return {.success = false, .error = std::format("Nothing to focus to in direction {}", arg)}; Debug::log(LOG, "No monitor found in direction {}, falling back to next window on current workspace", arg); const auto PWINDOWNEXT = g_pCompositor->getNextWindowOnWorkspace(PLASTWINDOW, true); if (PWINDOWNEXT) switchToWindow(PWINDOWNEXT); + + return {}; } -void CKeybindManager::focusUrgentOrLast(std::string args) { +SDispatchResult CKeybindManager::focusUrgentOrLast(std::string args) { const auto PWINDOWURGENT = g_pCompositor->getUrgentWindow(); const auto PWINDOWPREV = g_pCompositor->m_pLastWindow.lock() ? (g_pCompositor->m_vWindowFocusHistory.size() < 2 ? nullptr : g_pCompositor->m_vWindowFocusHistory[1].lock()) : (g_pCompositor->m_vWindowFocusHistory.empty() ? nullptr : g_pCompositor->m_vWindowFocusHistory[0].lock()); if (!PWINDOWURGENT && !PWINDOWPREV) - return; + return {.success = false, .error = "Window not found"}; switchToWindow(PWINDOWURGENT ? PWINDOWURGENT : PWINDOWPREV); + + return {}; } -void CKeybindManager::focusCurrentOrLast(std::string args) { +SDispatchResult CKeybindManager::focusCurrentOrLast(std::string args) { const auto PWINDOWPREV = g_pCompositor->m_pLastWindow.lock() ? (g_pCompositor->m_vWindowFocusHistory.size() < 2 ? nullptr : g_pCompositor->m_vWindowFocusHistory[1].lock()) : (g_pCompositor->m_vWindowFocusHistory.empty() ? nullptr : g_pCompositor->m_vWindowFocusHistory[0].lock()); if (!PWINDOWPREV) - return; + return {.success = false, .error = "Window not found"}; switchToWindow(PWINDOWPREV); + + return {}; } -void CKeybindManager::swapActive(std::string args) { +SDispatchResult CKeybindManager::swapActive(std::string args) { char arg = args[0]; if (!isDirection(args)) { Debug::log(ERR, "Cannot move window in direction {}, unsupported direction. Supported: l,r,u/t,d/b", arg); - return; + return {.success = false, .error = std::format("Cannot move window in direction {}, unsupported direction. Supported: l,r,u/t,d/b", arg)}; } Debug::log(LOG, "Swapping active window in direction {}", arg); const auto PLASTWINDOW = g_pCompositor->m_pLastWindow.lock(); - if (!PLASTWINDOW || PLASTWINDOW->isFullscreen()) - return; + + if (!PLASTWINDOW) + return {.success = false, .error = "Window to swap with not found"}; + + if (PLASTWINDOW->isFullscreen()) + return {.success = false, .error = "Can't swap fullscreen window"}; const auto PWINDOWTOCHANGETO = g_pCompositor->getWindowInDirection(PLASTWINDOW, arg); if (!PWINDOWTOCHANGETO) - return; + return {.success = false, .error = "Window to swap with not found"}; updateRelativeCursorCoords(); g_pLayoutManager->getCurrentLayout()->switchWindows(PLASTWINDOW, PWINDOWTOCHANGETO); PLASTWINDOW->warpCursor(); + + return {}; } -void CKeybindManager::moveActiveTo(std::string args) { +SDispatchResult CKeybindManager::moveActiveTo(std::string args) { char arg = args[0]; bool silent = args.ends_with(" silent"); if (silent) @@ -1391,25 +1438,28 @@ void CKeybindManager::moveActiveTo(std::string args) { if (args.starts_with("mon:")) { const auto PNEWMONITOR = g_pCompositor->getMonitorFromString(args.substr(4)); if (!PNEWMONITOR) - return; + return {.success = false, .error = std::format("Monitor {} not found", args.substr(4))}; if (silent) moveActiveToWorkspaceSilent(PNEWMONITOR->activeWorkspace->getConfigName()); else moveActiveToWorkspace(PNEWMONITOR->activeWorkspace->getConfigName()); - return; + return {}; } if (!isDirection(args)) { Debug::log(ERR, "Cannot move window in direction {}, unsupported direction. Supported: l,r,u/t,d/b", arg); - return; + return {.success = false, .error = std::format("Cannot move window in direction {}, unsupported direction. Supported: l,r,u/t,d/b", arg)}; } const auto PLASTWINDOW = g_pCompositor->m_pLastWindow.lock(); - if (!PLASTWINDOW || PLASTWINDOW->isFullscreen()) - return; + if (!PLASTWINDOW) + return {.success = false, .error = "Window to move not found"}; + + if (PLASTWINDOW->isFullscreen()) + return {.success = false, .error = "Can't move fullscreen window"}; if (PLASTWINDOW->m_bIsFloating) { std::optional vPosx, vPosy; @@ -1427,7 +1477,7 @@ void CKeybindManager::moveActiveTo(std::string args) { PLASTWINDOW->m_vRealPosition = Vector2D(vPosx.value_or(PLASTWINDOW->m_vRealPosition.goal().x), vPosy.value_or(PLASTWINDOW->m_vRealPosition.goal().y)); - return; + return {}; } // If the window to change to is on the same workspace, switch them @@ -1438,30 +1488,32 @@ void CKeybindManager::moveActiveTo(std::string args) { g_pLayoutManager->getCurrentLayout()->moveWindowTo(PLASTWINDOW, args, silent); if (!silent) PLASTWINDOW->warpCursor(); - return; + return {}; } static auto PMONITORFALLBACK = CConfigValue("binds:window_direction_monitor_fallback"); if (!*PMONITORFALLBACK) - return; + return {}; // Otherwise, we always want to move to the next monitor in that direction const auto PMONITORTOCHANGETO = g_pCompositor->getMonitorInDirection(arg); if (!PMONITORTOCHANGETO) - return; + return {.success = false, .error = "Nowhere to move active window to"}; const auto PWORKSPACE = PMONITORTOCHANGETO->activeWorkspace; if (silent) moveActiveToWorkspaceSilent(PWORKSPACE->getConfigName()); else moveActiveToWorkspace(PWORKSPACE->getConfigName()); + + return {}; } -void CKeybindManager::toggleGroup(std::string args) { +SDispatchResult CKeybindManager::toggleGroup(std::string args) { const auto PWINDOW = g_pCompositor->m_pLastWindow.lock(); if (!PWINDOW) - return; + return {.success = false, .error = "Window not found"}; if (PWINDOW->isFullscreen()) g_pCompositor->setWindowFullscreenInternal(PWINDOW, FSMODE_NONE); @@ -1470,30 +1522,32 @@ void CKeybindManager::toggleGroup(std::string args) { PWINDOW->createGroup(); else PWINDOW->destroyGroup(); + + return {}; } -void CKeybindManager::changeGroupActive(std::string args) { +SDispatchResult CKeybindManager::changeGroupActive(std::string args) { const auto PWINDOW = g_pCompositor->m_pLastWindow.lock(); if (!PWINDOW) - return; + return {.success = false, .error = "Window not found"}; if (PWINDOW->m_sGroupData.pNextWindow.expired()) - return; + return {.success = false, .error = "No next window in group"}; if (PWINDOW->m_sGroupData.pNextWindow.lock() == PWINDOW) - return; + return {.success = false, .error = "Only one window in group"}; if (isNumber(args, false)) { // index starts from '1'; '0' means last window const int INDEX = std::stoi(args); if (INDEX > PWINDOW->getGroupSize()) - return; + return {}; if (INDEX == 0) PWINDOW->setGroupCurrent(PWINDOW->getGroupTail()); else PWINDOW->setGroupCurrent(PWINDOW->getGroupWindowByIndex(INDEX - 1)); - return; + return {}; } if (args != "b" && args != "prev") { @@ -1501,39 +1555,45 @@ void CKeybindManager::changeGroupActive(std::string args) { } else { PWINDOW->setGroupCurrent(PWINDOW->getGroupPrevious()); } + + return {}; } -void CKeybindManager::toggleSplit(std::string args) { +SDispatchResult CKeybindManager::toggleSplit(std::string args) { SLayoutMessageHeader header; header.pWindow = g_pCompositor->m_pLastWindow.lock(); if (!header.pWindow) - return; + return {.success = false, .error = "Window not found"}; const auto PWORKSPACE = header.pWindow->m_pWorkspace; if (PWORKSPACE->m_bHasFullscreenWindow) - return; + return {.success = false, .error = "Can't split windows that already split"}; g_pLayoutManager->getCurrentLayout()->layoutMessage(header, "togglesplit"); + + return {}; } -void CKeybindManager::swapSplit(std::string args) { +SDispatchResult CKeybindManager::swapSplit(std::string args) { SLayoutMessageHeader header; header.pWindow = g_pCompositor->m_pLastWindow.lock(); if (!header.pWindow) - return; + return {.success = false, .error = "Window not found"}; const auto PWORKSPACE = header.pWindow->m_pWorkspace; if (PWORKSPACE->m_bHasFullscreenWindow) - return; + return {.success = false, .error = "Can't split windows that already split"}; g_pLayoutManager->getCurrentLayout()->layoutMessage(header, "swapsplit"); + + return {}; } -void CKeybindManager::alterSplitRatio(std::string args) { +SDispatchResult CKeybindManager::alterSplitRatio(std::string args) { std::optional splitResult; bool exact = false; @@ -1545,39 +1605,43 @@ void CKeybindManager::alterSplitRatio(std::string args) { if (!splitResult.has_value()) { Debug::log(ERR, "Splitratio invalid in alterSplitRatio!"); - return; + return {.success = false, .error = "Splitratio invalid in alterSplitRatio!"}; } const auto PLASTWINDOW = g_pCompositor->m_pLastWindow.lock(); if (!PLASTWINDOW) - return; + return {.success = false, .error = "Window not found"}; g_pLayoutManager->getCurrentLayout()->alterSplitRatio(PLASTWINDOW, splitResult.value(), exact); + + return {}; } -void CKeybindManager::focusMonitor(std::string arg) { +SDispatchResult CKeybindManager::focusMonitor(std::string arg) { const auto PMONITOR = g_pCompositor->getMonitorFromString(arg); tryMoveFocusToMonitor(PMONITOR); + + return {}; } -void CKeybindManager::moveCursorToCorner(std::string arg) { +SDispatchResult CKeybindManager::moveCursorToCorner(std::string arg) { if (!isNumber(arg)) { Debug::log(ERR, "moveCursorToCorner, arg has to be a number."); - return; + return {.success = false, .error = "moveCursorToCorner, arg has to be a number."}; } const auto CORNER = std::stoi(arg); if (CORNER < 0 || CORNER > 3) { Debug::log(ERR, "moveCursorToCorner, corner not 0 - 3."); - return; + return {.success = false, .error = "moveCursorToCorner, corner not 0 - 3."}; } const auto PWINDOW = g_pCompositor->m_pLastWindow.lock(); if (!PWINDOW) - return; + return {.success = false, .error = "Window not found"}; switch (CORNER) { case 0: @@ -1598,16 +1662,18 @@ void CKeybindManager::moveCursorToCorner(std::string arg) { g_pCompositor->warpCursorTo({PWINDOW->m_vRealPosition.value().x, PWINDOW->m_vRealPosition.value().y}, true); break; } + + return {}; } -void CKeybindManager::moveCursor(std::string args) { +SDispatchResult CKeybindManager::moveCursor(std::string args) { std::string x_str, y_str; int x, y; size_t i = args.find_first_of(' '); if (i == std::string::npos) { Debug::log(ERR, "moveCursor, takes 2 arguments."); - return; + return {.success = false, .error = "moveCursor, takes 2 arguments"}; } x_str = args.substr(0, i); @@ -1615,26 +1681,28 @@ void CKeybindManager::moveCursor(std::string args) { if (!isNumber(x_str)) { Debug::log(ERR, "moveCursor, x argument has to be a number."); - return; + return {.success = false, .error = "moveCursor, x argument has to be a number."}; } if (!isNumber(y_str)) { Debug::log(ERR, "moveCursor, y argument has to be a number."); - return; + return {.success = false, .error = "moveCursor, y argument has to be a number."}; } x = std::stoi(x_str); y = std::stoi(y_str); g_pCompositor->warpCursorTo({x, y}, true); + + return {}; } -void CKeybindManager::workspaceOpt(std::string args) { +SDispatchResult CKeybindManager::workspaceOpt(std::string args) { // current workspace const auto PWORKSPACE = g_pCompositor->m_pLastMonitor->activeWorkspace; if (!PWORKSPACE) - return; // ???? + return {.success = false, .error = "Workspace not found"}; // ???? if (args == "allpseudo") { PWORKSPACE->m_bDefaultPseudo = !PWORKSPACE->m_bDefaultPseudo; @@ -1677,14 +1745,16 @@ void CKeybindManager::workspaceOpt(std::string args) { } } else { Debug::log(ERR, "Invalid arg in workspaceOpt, opt \"{}\" doesn't exist.", args); - return; + return {.success = false, .error = std::format("Invalid arg in workspaceOpt, opt \"{}\" doesn't exist.", args)}; } // recalc mon g_pLayoutManager->getCurrentLayout()->recalculateMonitor(g_pCompositor->m_pLastMonitor->ID); + + return {}; } -void CKeybindManager::renameWorkspace(std::string args) { +SDispatchResult CKeybindManager::renameWorkspace(std::string args) { try { const auto FIRSTSPACEPOS = args.find_first_of(' '); if (FIRSTSPACEPOS != std::string::npos) { @@ -1694,34 +1764,42 @@ void CKeybindManager::renameWorkspace(std::string args) { } else { g_pCompositor->renameWorkspace(std::stoi(args), ""); } - } catch (std::exception& e) { Debug::log(ERR, "Invalid arg in renameWorkspace, expected numeric id only or a numeric id and string name. \"{}\": \"{}\"", args, e.what()); } + } catch (std::exception& e) { + Debug::log(ERR, "Invalid arg in renameWorkspace, expected numeric id only or a numeric id and string name. \"{}\": \"{}\"", args, e.what()); + return {.success = false, .error = std::format("Invalid arg in renameWorkspace, expected numeric id only or a numeric id and string name. \"{}\": \"{}\"", args, e.what())}; + } + + return {}; } -void CKeybindManager::exitHyprland(std::string argz) { +SDispatchResult CKeybindManager::exitHyprland(std::string argz) { g_pCompositor->stopCompositor(); + return {}; } -void CKeybindManager::moveCurrentWorkspaceToMonitor(std::string args) { +SDispatchResult CKeybindManager::moveCurrentWorkspaceToMonitor(std::string args) { CMonitor* PMONITOR = g_pCompositor->getMonitorFromString(args); if (!PMONITOR) { Debug::log(ERR, "Ignoring moveCurrentWorkspaceToMonitor: monitor doesnt exist"); - return; + return {.success = false, .error = "Ignoring moveCurrentWorkspaceToMonitor: monitor doesnt exist"}; } // get the current workspace const auto PCURRENTWORKSPACE = g_pCompositor->m_pLastMonitor->activeWorkspace; if (!PCURRENTWORKSPACE) { Debug::log(ERR, "moveCurrentWorkspaceToMonitor invalid workspace!"); - return; + return {.success = false, .error = "moveCurrentWorkspaceToMonitor invalid workspace!"}; } g_pCompositor->moveWorkspaceToMonitor(PCURRENTWORKSPACE, PMONITOR); + + return {}; } -void CKeybindManager::moveWorkspaceToMonitor(std::string args) { +SDispatchResult CKeybindManager::moveWorkspaceToMonitor(std::string args) { if (!args.contains(' ')) - return; + return {}; std::string workspace = args.substr(0, args.find_first_of(' ')); std::string monitor = args.substr(args.find_first_of(' ') + 1); @@ -1730,38 +1808,40 @@ void CKeybindManager::moveWorkspaceToMonitor(std::string args) { if (!PMONITOR) { Debug::log(ERR, "Ignoring moveWorkspaceToMonitor: monitor doesnt exist"); - return; + return {.success = false, .error = "Ignoring moveWorkspaceToMonitor: monitor doesnt exist"}; } const auto WORKSPACEID = getWorkspaceIDNameFromString(workspace).id; if (WORKSPACEID == WORKSPACE_INVALID) { Debug::log(ERR, "moveWorkspaceToMonitor invalid workspace!"); - return; + return {.success = false, .error = "moveWorkspaceToMonitor invalid workspace!"}; } const auto PWORKSPACE = g_pCompositor->getWorkspaceByID(WORKSPACEID); if (!PWORKSPACE) { Debug::log(ERR, "moveWorkspaceToMonitor workspace doesn't exist!"); - return; + return {.success = false, .error = "moveWorkspaceToMonitor workspace doesn't exist!"}; } g_pCompositor->moveWorkspaceToMonitor(PWORKSPACE, PMONITOR); + + return {}; } -void CKeybindManager::focusWorkspaceOnCurrentMonitor(std::string args) { +SDispatchResult CKeybindManager::focusWorkspaceOnCurrentMonitor(std::string args) { auto workspaceID = getWorkspaceIDNameFromString(args).id; if (workspaceID == WORKSPACE_INVALID) { Debug::log(ERR, "focusWorkspaceOnCurrentMonitor invalid workspace!"); - return; + return {.success = false, .error = "focusWorkspaceOnCurrentMonitor invalid workspace!"}; } const auto PCURRMONITOR = g_pCompositor->m_pLastMonitor.get(); if (!PCURRMONITOR) { Debug::log(ERR, "focusWorkspaceOnCurrentMonitor monitor doesn't exist!"); - return; + return {.success = false, .error = "focusWorkspaceOnCurrentMonitor monitor doesn't exist!"}; } auto pWorkspace = g_pCompositor->getWorkspaceByID(workspaceID); @@ -1770,7 +1850,7 @@ void CKeybindManager::focusWorkspaceOnCurrentMonitor(std::string args) { pWorkspace = g_pCompositor->createNewWorkspace(workspaceID, PCURRMONITOR->ID); // we can skip the moving, since it's already on the current monitor changeworkspace(pWorkspace->getConfigName()); - return; + return {}; } static auto PBACKANDFORTH = CConfigValue("binds:workspace_back_and_forth"); @@ -1789,24 +1869,26 @@ void CKeybindManager::focusWorkspaceOnCurrentMonitor(std::string args) { const auto POLDMONITOR = g_pCompositor->getMonitorFromID(pWorkspace->m_iMonitorID); if (!POLDMONITOR) { // wat Debug::log(ERR, "focusWorkspaceOnCurrentMonitor old monitor doesn't exist!"); - return; + return {.success = false, .error = "focusWorkspaceOnCurrentMonitor old monitor doesn't exist!"}; } if (POLDMONITOR->activeWorkspaceID() == workspaceID) { g_pCompositor->swapActiveWorkspaces(POLDMONITOR, PCURRMONITOR); - return; + return {}; } else { g_pCompositor->moveWorkspaceToMonitor(pWorkspace, PCURRMONITOR, true); } } changeworkspace(pWorkspace->getConfigName()); + + return {}; } -void CKeybindManager::toggleSpecialWorkspace(std::string args) { +SDispatchResult CKeybindManager::toggleSpecialWorkspace(std::string args) { const auto& [workspaceID, workspaceName] = getWorkspaceIDNameFromString("special:" + args); if (workspaceID == WORKSPACE_INVALID || !g_pCompositor->isWorkspaceSpecial(workspaceID)) { Debug::log(ERR, "Invalid workspace passed to special"); - return; + return {.success = false, .error = "Invalid workspace passed to special"}; } bool requestedWorkspaceIsAlreadyOpen = false; @@ -1833,9 +1915,11 @@ void CKeybindManager::toggleSpecialWorkspace(std::string args) { PMONITOR->setSpecialWorkspace(PSPECIALWORKSPACE); } + + return {}; } -void CKeybindManager::forceRendererReload(std::string args) { +SDispatchResult CKeybindManager::forceRendererReload(std::string args) { bool overAgain = false; for (auto& m : g_pCompositor->m_vMonitors) { @@ -1851,37 +1935,43 @@ void CKeybindManager::forceRendererReload(std::string args) { if (overAgain) forceRendererReload(args); + + return {}; } -void CKeybindManager::resizeActive(std::string args) { +SDispatchResult CKeybindManager::resizeActive(std::string args) { const auto PLASTWINDOW = g_pCompositor->m_pLastWindow.lock(); if (!PLASTWINDOW || PLASTWINDOW->isFullscreen()) - return; + return {}; const auto SIZ = g_pCompositor->parseWindowVectorArgsRelative(args, PLASTWINDOW->m_vRealSize.goal()); if (SIZ.x < 1 || SIZ.y < 1) - return; + return {}; g_pLayoutManager->getCurrentLayout()->resizeActiveWindow(SIZ - PLASTWINDOW->m_vRealSize.goal()); if (PLASTWINDOW->m_vRealSize.goal().x > 1 && PLASTWINDOW->m_vRealSize.goal().y > 1) PLASTWINDOW->setHidden(false); + + return {}; } -void CKeybindManager::moveActive(std::string args) { +SDispatchResult CKeybindManager::moveActive(std::string args) { const auto PLASTWINDOW = g_pCompositor->m_pLastWindow.lock(); if (!PLASTWINDOW || PLASTWINDOW->isFullscreen()) - return; + return {}; const auto POS = g_pCompositor->parseWindowVectorArgsRelative(args, PLASTWINDOW->m_vRealPosition.goal()); g_pLayoutManager->getCurrentLayout()->moveActiveWindow(POS - PLASTWINDOW->m_vRealPosition.goal()); + + return {}; } -void CKeybindManager::moveWindow(std::string args) { +SDispatchResult CKeybindManager::moveWindow(std::string args) { const auto WINDOWREGEX = args.substr(args.find_first_of(',') + 1); const auto MOVECMD = args.substr(0, args.find_first_of(',')); @@ -1890,18 +1980,20 @@ void CKeybindManager::moveWindow(std::string args) { if (!PWINDOW) { Debug::log(ERR, "moveWindow: no window"); - return; + return {.success = false, .error = "moveWindow: no window"}; } if (PWINDOW->isFullscreen()) - return; + return {}; const auto POS = g_pCompositor->parseWindowVectorArgsRelative(MOVECMD, PWINDOW->m_vRealPosition.goal()); g_pLayoutManager->getCurrentLayout()->moveActiveWindow(POS - PWINDOW->m_vRealPosition.goal(), PWINDOW); + + return {}; } -void CKeybindManager::resizeWindow(std::string args) { +SDispatchResult CKeybindManager::resizeWindow(std::string args) { const auto WINDOWREGEX = args.substr(args.find_first_of(',') + 1); const auto MOVECMD = args.substr(0, args.find_first_of(',')); @@ -1910,24 +2002,26 @@ void CKeybindManager::resizeWindow(std::string args) { if (!PWINDOW) { Debug::log(ERR, "resizeWindow: no window"); - return; + return {.success = false, .error = "resizeWindow: no window"}; } if (PWINDOW->isFullscreen()) - return; + return {}; const auto SIZ = g_pCompositor->parseWindowVectorArgsRelative(MOVECMD, PWINDOW->m_vRealSize.goal()); if (SIZ.x < 1 || SIZ.y < 1) - return; + return {}; g_pLayoutManager->getCurrentLayout()->resizeActiveWindow(SIZ - PWINDOW->m_vRealSize.goal(), CORNER_NONE, PWINDOW); if (PWINDOW->m_vRealSize.goal().x > 1 && PWINDOW->m_vRealSize.goal().y > 1) PWINDOW->setHidden(false); + + return {}; } -void CKeybindManager::circleNext(std::string arg) { +SDispatchResult CKeybindManager::circleNext(std::string arg) { if (g_pCompositor->m_pLastWindow.expired()) { // if we have a clear focus, find the first window and get the next focusable. @@ -1937,7 +2031,7 @@ void CKeybindManager::circleNext(std::string arg) { switchToWindow(PWINDOW); } - return; + return {}; } CVarList args{arg, 0, 's', true}; @@ -1952,20 +2046,22 @@ void CKeybindManager::circleNext(std::string arg) { switchToWindow(g_pCompositor->getPrevWindowOnWorkspace(g_pCompositor->m_pLastWindow.lock(), true, floatStatus)); else switchToWindow(g_pCompositor->getNextWindowOnWorkspace(g_pCompositor->m_pLastWindow.lock(), true, floatStatus)); + + return {}; } -void CKeybindManager::focusWindow(std::string regexp) { +SDispatchResult CKeybindManager::focusWindow(std::string regexp) { const auto PWINDOW = g_pCompositor->getWindowByRegex(regexp); if (!PWINDOW) - return; + return {}; Debug::log(LOG, "Focusing to window name: {}", PWINDOW->m_szTitle); const auto PWORKSPACE = PWINDOW->m_pWorkspace; if (!PWORKSPACE) { Debug::log(ERR, "BUG THIS: null workspace in focusWindow"); - return; + return {.success = false, .error = "BUG THIS: null workspace in focusWindow"}; } updateRelativeCursorCoords(); @@ -2001,9 +2097,11 @@ void CKeybindManager::focusWindow(std::string regexp) { g_pCompositor->focusWindow(PWINDOW); PWINDOW->warpCursor(); + + return {}; } -void CKeybindManager::tagWindow(std::string args) { +SDispatchResult CKeybindManager::tagWindow(std::string args) { PHLWINDOW PWINDOW = nullptr; CVarList vars{args, 0, 's', true}; @@ -2012,21 +2110,23 @@ void CKeybindManager::tagWindow(std::string args) { else if (vars.size() == 2) PWINDOW = g_pCompositor->getWindowByRegex(vars[1]); else - return; + return {}; if (PWINDOW && PWINDOW->m_tags.applyTag(vars[0])) { PWINDOW->updateDynamicRules(); g_pCompositor->updateWindowAnimatedDecorationValues(PWINDOW->m_pSelf.lock()); } + + return {}; } -void CKeybindManager::setSubmap(std::string submap) { +SDispatchResult CKeybindManager::setSubmap(std::string submap) { if (submap == "reset" || submap == "") { m_szCurrentSelectedSubmap = ""; Debug::log(LOG, "Reset active submap to the default one."); g_pEventManager->postEvent(SHyprIPCEvent{"submap", ""}); EMIT_HOOK_EVENT("submap", m_szCurrentSelectedSubmap); - return; + return {}; } for (auto& k : g_pKeybindManager->m_lKeybinds) { @@ -2035,26 +2135,27 @@ void CKeybindManager::setSubmap(std::string submap) { Debug::log(LOG, "Changed keybind submap to {}", submap); g_pEventManager->postEvent(SHyprIPCEvent{"submap", submap}); EMIT_HOOK_EVENT("submap", m_szCurrentSelectedSubmap); - return; + return {}; } } Debug::log(ERR, "Cannot set submap {}, submap doesn't exist (wasn't registered!)", submap); + return {.success = false, .error = std::format("Cannot set submap {}, submap doesn't exist (wasn't registered!)", submap)}; } -void CKeybindManager::pass(std::string regexp) { +SDispatchResult CKeybindManager::pass(std::string regexp) { // find the first window passing the regex const auto PWINDOW = g_pCompositor->getWindowByRegex(regexp); if (!PWINDOW) { Debug::log(ERR, "pass: window not found"); - return; + return {.success = false, .error = "pass: window not found"}; } if (!g_pSeatManager->keyboard) { Debug::log(ERR, "No kb in pass?"); - return; + return {.success = false, .error = "No kb in pass?"}; } const auto XWTOXW = PWINDOW->m_bIsX11 && g_pCompositor->m_pLastWindow.lock() && g_pCompositor->m_pLastWindow->m_bIsX11; @@ -2093,7 +2194,7 @@ void CKeybindManager::pass(std::string regexp) { } if (XWTOXW) - return; + return {}; // Massive hack: // this will make g_pSeatManager NOT send the leave event to XWayland apps, provided we are not on an XWayland window already. @@ -2114,14 +2215,16 @@ void CKeybindManager::pass(std::string regexp) { g_pSeatManager->setKeyboardFocus(LASTKBSURF); else g_pSeatManager->setPointerFocus(LASTMOUSESURF, SL); + + return {}; } -void CKeybindManager::sendshortcut(std::string args) { +SDispatchResult CKeybindManager::sendshortcut(std::string args) { // args=[,WINDOW_RULES] const auto ARGS = CVarList(args, 3); if (ARGS.size() != 3) { Debug::log(ERR, "sendshortcut: invalid args"); - return; + return {.success = false, .error = "sendshortcut: invalid args"}; } const auto MOD = g_pKeybindManager->stringToModMask(ARGS[0]); @@ -2139,7 +2242,7 @@ void CKeybindManager::sendshortcut(std::string args) { isMouse = 1; if (keycode < 272) { Debug::log(ERR, "sendshortcut: invalid mouse button"); - return; + return {.success = false, .error = "sendshortcut: invalid mouse button"}; } } else { @@ -2154,7 +2257,7 @@ void CKeybindManager::sendshortcut(std::string args) { if (!KB) { Debug::log(ERR, "sendshortcut: no kb"); - return; + return {.success = false, .error = "sendshortcut: no kb"}; } const auto KEYPAIRSTRING = std::format("{}{}", (uintptr_t)KB.get(), KEY); @@ -2178,7 +2281,7 @@ void CKeybindManager::sendshortcut(std::string args) { if (!keycode) { Debug::log(ERR, "sendshortcut: key not found"); - return; + return {.success = false, .error = "sendshortcut: key not found"}; } } else @@ -2187,7 +2290,7 @@ void CKeybindManager::sendshortcut(std::string args) { if (!keycode) { Debug::log(ERR, "sendshortcut: invalid key"); - return; + return {.success = false, .error = "sendshortcut: invalid key"}; } const std::string regexp = ARGS[2]; @@ -2201,12 +2304,12 @@ void CKeybindManager::sendshortcut(std::string args) { if (!PWINDOW) { Debug::log(ERR, "sendshortcut: window not found"); - return; + return {.success = false, .error = "sendshortcut: window not found"}; } if (!g_pSeatManager->keyboard) { Debug::log(ERR, "No kb in sendshortcut?"); - return; + return {.success = false, .error = "No kb in sendshortcut?"}; } if (!isMouse) @@ -2247,7 +2350,7 @@ void CKeybindManager::sendshortcut(std::string args) { } if (!PWINDOW) - return; + return {}; if (PWINDOW->m_bIsX11) { //xwayland hack, see pass if (!isMouse) { @@ -2265,16 +2368,21 @@ void CKeybindManager::sendshortcut(std::string args) { g_pSeatManager->setKeyboardFocus(LASTSURFACE); else g_pSeatManager->setPointerFocus(LASTSURFACE, SL); + + return {}; } -void CKeybindManager::layoutmsg(std::string msg) { +SDispatchResult CKeybindManager::layoutmsg(std::string msg) { SLayoutMessageHeader hd = {g_pCompositor->m_pLastWindow.lock()}; g_pLayoutManager->getCurrentLayout()->layoutMessage(hd, msg); + + return {}; } -void CKeybindManager::dpms(std::string arg) { - bool enable = arg.starts_with("on"); - std::string port = ""; +SDispatchResult CKeybindManager::dpms(std::string arg) { + SDispatchResult res; + bool enable = arg.starts_with("on"); + std::string port = ""; if (arg.starts_with("toggle")) enable = !std::any_of(g_pCompositor->m_vMonitors.begin(), g_pCompositor->m_vMonitors.end(), [&](const auto& other) { return !other->dpmsStatus; }); // enable if any is off @@ -2294,6 +2402,8 @@ void CKeybindManager::dpms(std::string arg) { if (!m->state.commit()) { Debug::log(ERR, "Couldn't commit output {}", m->szName); + res.success = false; + res.error = "Couldn't commit output {}"; } if (enable) @@ -2305,14 +2415,16 @@ void CKeybindManager::dpms(std::string arg) { g_pCompositor->m_bDPMSStateON = enable; g_pPointerManager->recheckEnteredOutputs(); + + return res; } -void CKeybindManager::swapnext(std::string arg) { +SDispatchResult CKeybindManager::swapnext(std::string arg) { PHLWINDOW toSwap = nullptr; if (g_pCompositor->m_pLastWindow.expired()) - return; + return {}; const auto PLASTWINDOW = g_pCompositor->m_pLastWindow.lock(); @@ -2339,9 +2451,11 @@ void CKeybindManager::swapnext(std::string arg) { PLASTWINDOW->m_pLastCycledWindow = toSwap; g_pCompositor->focusWindow(PLASTWINDOW); + + return {}; } -void CKeybindManager::swapActiveWorkspaces(std::string args) { +SDispatchResult CKeybindManager::swapActiveWorkspaces(std::string args) { const auto MON1 = args.substr(0, args.find_first_of(' ')); const auto MON2 = args.substr(args.find_first_of(' ') + 1); @@ -2349,12 +2463,14 @@ void CKeybindManager::swapActiveWorkspaces(std::string args) { const auto PMON2 = g_pCompositor->getMonitorFromString(MON2); if (!PMON1 || !PMON2 || PMON1 == PMON2) - return; + return {}; g_pCompositor->swapActiveWorkspaces(PMON1, PMON2); + + return {}; } -void CKeybindManager::pinActive(std::string args) { +SDispatchResult CKeybindManager::pinActive(std::string args) { PHLWINDOW PWINDOW = nullptr; @@ -2365,11 +2481,11 @@ void CKeybindManager::pinActive(std::string args) { if (!PWINDOW) { Debug::log(ERR, "pin: window not found"); - return; + return {.success = false, .error = "pin: window not found"}; } if (!PWINDOW->m_bIsFloating || PWINDOW->isFullscreen()) - return; + return {}; PWINDOW->m_bPinned = !PWINDOW->m_bPinned; @@ -2377,7 +2493,7 @@ void CKeybindManager::pinActive(std::string args) { if (!PMONITOR) { Debug::log(ERR, "pin: monitor not found"); - return; + return {.success = false, .error = "pin: window not found"}; } PWINDOW->m_pWorkspace = PMONITOR->activeWorkspace; @@ -2391,40 +2507,41 @@ void CKeybindManager::pinActive(std::string args) { g_pEventManager->postEvent(SHyprIPCEvent{"pin", std::format("{:x},{}", (uintptr_t)PWINDOW.get(), (int)PWINDOW->m_bPinned)}); EMIT_HOOK_EVENT("pin", PWINDOW); + + return {}; } -void CKeybindManager::mouse(std::string args) { +SDispatchResult CKeybindManager::mouse(std::string args) { const auto ARGS = CVarList(args.substr(1), 2, ' '); const auto PRESSED = args[0] == '1'; if (!PRESSED) { - changeMouseBindMode(MBIND_INVALID); - return; + return changeMouseBindMode(MBIND_INVALID); } if (ARGS[0] == "movewindow") { - changeMouseBindMode(MBIND_MOVE); + return changeMouseBindMode(MBIND_MOVE); } else { try { switch (std::stoi(ARGS[1])) { - case 1: changeMouseBindMode(MBIND_RESIZE_FORCE_RATIO); break; - case 2: changeMouseBindMode(MBIND_RESIZE_BLOCK_RATIO); break; - default: changeMouseBindMode(MBIND_RESIZE); + case 1: return changeMouseBindMode(MBIND_RESIZE_FORCE_RATIO); break; + case 2: return changeMouseBindMode(MBIND_RESIZE_BLOCK_RATIO); break; + default: return changeMouseBindMode(MBIND_RESIZE); } - } catch (std::exception& e) { changeMouseBindMode(MBIND_RESIZE); } + } catch (std::exception& e) { return changeMouseBindMode(MBIND_RESIZE); } } } -void CKeybindManager::changeMouseBindMode(const eMouseBindMode MODE) { +SDispatchResult CKeybindManager::changeMouseBindMode(const eMouseBindMode MODE) { if (MODE != MBIND_INVALID) { if (!g_pInputManager->currentlyDraggedWindow.expired() || g_pInputManager->dragMode != MBIND_INVALID) - return; + return {}; const auto MOUSECOORDS = g_pInputManager->getMouseCoordsInternal(); const PHLWINDOW PWINDOW = g_pCompositor->vectorToWindowUnified(MOUSECOORDS, RESERVED_EXTENTS | INPUT_EXTENTS | ALLOW_FLOATING); if (!PWINDOW) - return; + return SDispatchResult{.passEvent = true}; if (!PWINDOW->isFullscreen() && MODE == MBIND_MOVE) PWINDOW->checkInputOnDecos(INPUT_TYPE_DRAG_START, MOUSECOORDS); @@ -2437,19 +2554,23 @@ void CKeybindManager::changeMouseBindMode(const eMouseBindMode MODE) { g_pLayoutManager->getCurrentLayout()->onBeginDragWindow(); } else { if (g_pInputManager->currentlyDraggedWindow.expired() || g_pInputManager->dragMode == MBIND_INVALID) - return; + return {}; g_pLayoutManager->getCurrentLayout()->onEndDragWindow(); g_pInputManager->dragMode = MODE; } + + return {}; } -void CKeybindManager::bringActiveToTop(std::string args) { +SDispatchResult CKeybindManager::bringActiveToTop(std::string args) { if (g_pCompositor->m_pLastWindow.lock() && g_pCompositor->m_pLastWindow->m_bIsFloating) g_pCompositor->changeWindowZOrder(g_pCompositor->m_pLastWindow.lock(), true); + + return {}; } -void CKeybindManager::alterZOrder(std::string args) { +SDispatchResult CKeybindManager::alterZOrder(std::string args) { const auto WINDOWREGEX = args.substr(args.find_first_of(',') + 1); const auto POSITION = args.substr(0, args.find_first_of(',')); auto PWINDOW = g_pCompositor->getWindowByRegex(WINDOWREGEX); @@ -2459,7 +2580,7 @@ void CKeybindManager::alterZOrder(std::string args) { if (!PWINDOW) { Debug::log(ERR, "alterZOrder: no window"); - return; + return {.success = false, .error = "alterZOrder: no window"}; } if (POSITION == "top") @@ -2468,13 +2589,15 @@ void CKeybindManager::alterZOrder(std::string args) { g_pCompositor->changeWindowZOrder(PWINDOW, 0); else { Debug::log(ERR, "alterZOrder: bad position: {}", POSITION); - return; + return {.success = false, .error = "alterZOrder: bad position: {}"}; } g_pInputManager->simulateMouseMovement(); + + return {}; } -void CKeybindManager::lockGroups(std::string args) { +SDispatchResult CKeybindManager::lockGroups(std::string args) { if (args == "lock" || args.empty() || args == "lockgroups") g_pKeybindManager->m_bGroupsLocked = true; else if (args == "toggle") @@ -2483,13 +2606,15 @@ void CKeybindManager::lockGroups(std::string args) { g_pKeybindManager->m_bGroupsLocked = false; g_pEventManager->postEvent(SHyprIPCEvent{"lockgroups", g_pKeybindManager->m_bGroupsLocked ? "1" : "0"}); + + return {}; } -void CKeybindManager::lockActiveGroup(std::string args) { +SDispatchResult CKeybindManager::lockActiveGroup(std::string args) { const auto PWINDOW = g_pCompositor->m_pLastWindow.lock(); if (!PWINDOW || !PWINDOW->m_sGroupData.pNextWindow.lock()) - return; + return {}; const auto PHEAD = PWINDOW->getGroupHead(); @@ -2501,6 +2626,8 @@ void CKeybindManager::lockActiveGroup(std::string args) { PHEAD->m_sGroupData.locked = false; g_pCompositor->updateWindowAnimatedDecorationValues(PWINDOW); + + return {}; } void CKeybindManager::moveWindowIntoGroup(PHLWINDOW pWindow, PHLWINDOW pWindowInDirection) { @@ -2573,41 +2700,43 @@ void CKeybindManager::moveWindowOutOfGroup(PHLWINDOW pWindow, const std::string& g_pEventManager->postEvent(SHyprIPCEvent{"moveoutofgroup", std::format("{:x}", (uintptr_t)pWindow.get())}); } -void CKeybindManager::moveIntoGroup(std::string args) { +SDispatchResult CKeybindManager::moveIntoGroup(std::string args) { char arg = args[0]; static auto PIGNOREGROUPLOCK = CConfigValue("binds:ignore_group_lock"); if (!*PIGNOREGROUPLOCK && g_pKeybindManager->m_bGroupsLocked) - return; + return {}; if (!isDirection(args)) { Debug::log(ERR, "Cannot move into group in direction {}, unsupported direction. Supported: l,r,u/t,d/b", arg); - return; + return {.success = false, .error = std::format("Cannot move into group in direction {}, unsupported direction. Supported: l,r,u/t,d/b", arg)}; } const auto PWINDOW = g_pCompositor->m_pLastWindow.lock(); if (!PWINDOW || PWINDOW->m_bIsFloating || PWINDOW->m_sGroupData.deny) - return; + return {}; auto PWINDOWINDIR = g_pCompositor->getWindowInDirection(PWINDOW, arg); if (!PWINDOWINDIR || !PWINDOWINDIR->m_sGroupData.pNextWindow.lock()) - return; + return {}; // Do not move window into locked group if binds:ignore_group_lock is false if (!*PIGNOREGROUPLOCK && (PWINDOWINDIR->getGroupHead()->m_sGroupData.locked || (PWINDOW->m_sGroupData.pNextWindow.lock() && PWINDOW->getGroupHead()->m_sGroupData.locked))) - return; + return {}; moveWindowIntoGroup(PWINDOW, PWINDOWINDIR); + + return {}; } -void CKeybindManager::moveOutOfGroup(std::string args) { +SDispatchResult CKeybindManager::moveOutOfGroup(std::string args) { static auto PIGNOREGROUPLOCK = CConfigValue("binds:ignore_group_lock"); if (!*PIGNOREGROUPLOCK && g_pKeybindManager->m_bGroupsLocked) - return; + return {}; PHLWINDOW PWINDOW = nullptr; @@ -2617,28 +2746,30 @@ void CKeybindManager::moveOutOfGroup(std::string args) { PWINDOW = g_pCompositor->m_pLastWindow.lock(); if (!PWINDOW || !PWINDOW->m_sGroupData.pNextWindow.lock()) - return; + return {}; moveWindowOutOfGroup(PWINDOW); + + return {}; } -void CKeybindManager::moveWindowOrGroup(std::string args) { +SDispatchResult CKeybindManager::moveWindowOrGroup(std::string args) { char arg = args[0]; static auto PIGNOREGROUPLOCK = CConfigValue("binds:ignore_group_lock"); if (!isDirection(args)) { Debug::log(ERR, "Cannot move into group in direction {}, unsupported direction. Supported: l,r,u/t,d/b", arg); - return; + return {.success = false, .error = std::format("Cannot move into group in direction {}, unsupported direction. Supported: l,r,u/t,d/b", arg)}; } const auto PWINDOW = g_pCompositor->m_pLastWindow.lock(); if (!PWINDOW || PWINDOW->isFullscreen()) - return; + return {}; if (!*PIGNOREGROUPLOCK && g_pKeybindManager->m_bGroupsLocked) { g_pLayoutManager->getCurrentLayout()->moveWindowTo(PWINDOW, args); - return; + return {}; } const auto PWINDOWINDIR = g_pCompositor->getWindowInDirection(PWINDOW, arg); @@ -2670,9 +2801,11 @@ void CKeybindManager::moveWindowOrGroup(std::string args) { } g_pCompositor->updateWindowAnimatedDecorationValues(PWINDOW); + + return {}; } -void CKeybindManager::setIgnoreGroupLock(std::string args) { +SDispatchResult CKeybindManager::setIgnoreGroupLock(std::string args) { static auto PIGNOREGROUPLOCK = (Hyprlang::INT* const*)g_pConfigManager->getConfigValuePtr("binds:ignore_group_lock"); if (args == "toggle") @@ -2681,12 +2814,14 @@ void CKeybindManager::setIgnoreGroupLock(std::string args) { **PIGNOREGROUPLOCK = args == "on"; g_pEventManager->postEvent(SHyprIPCEvent{"ignoregrouplock", std::to_string(**PIGNOREGROUPLOCK)}); + + return {}; } -void CKeybindManager::denyWindowFromGroup(std::string args) { +SDispatchResult CKeybindManager::denyWindowFromGroup(std::string args) { const auto PWINDOW = g_pCompositor->m_pLastWindow.lock(); if (!PWINDOW || (PWINDOW && PWINDOW->m_sGroupData.pNextWindow.lock())) - return; + return {}; if (args == "toggle") PWINDOW->m_sGroupData.deny = !PWINDOW->m_sGroupData.deny; @@ -2694,28 +2829,32 @@ void CKeybindManager::denyWindowFromGroup(std::string args) { PWINDOW->m_sGroupData.deny = args == "on"; g_pCompositor->updateWindowAnimatedDecorationValues(PWINDOW); + + return {}; } -void CKeybindManager::global(std::string args) { +SDispatchResult CKeybindManager::global(std::string args) { const auto APPID = args.substr(0, args.find_first_of(':')); const auto NAME = args.substr(args.find_first_of(':') + 1); if (NAME.empty()) - return; + return {}; if (!PROTO::globalShortcuts->isTaken(APPID, NAME)) - return; + return {}; PROTO::globalShortcuts->sendGlobalShortcutEvent(APPID, NAME, g_pKeybindManager->m_iPassPressed); + + return {}; } -void CKeybindManager::moveGroupWindow(std::string args) { +SDispatchResult CKeybindManager::moveGroupWindow(std::string args) { const auto BACK = args == "b" || args == "prev"; const auto PLASTWINDOW = g_pCompositor->m_pLastWindow.lock(); if (!PLASTWINDOW || !PLASTWINDOW->m_sGroupData.pNextWindow.lock()) - return; + return {}; if ((!BACK && PLASTWINDOW->m_sGroupData.pNextWindow->m_sGroupData.head) || (BACK && PLASTWINDOW->m_sGroupData.head)) { std::swap(PLASTWINDOW->m_sGroupData.head, PLASTWINDOW->m_sGroupData.pNextWindow->m_sGroupData.head); @@ -2724,8 +2863,11 @@ void CKeybindManager::moveGroupWindow(std::string args) { PLASTWINDOW->switchWithWindowInGroup(BACK ? PLASTWINDOW->getGroupPrevious() : PLASTWINDOW->m_sGroupData.pNextWindow.lock()); PLASTWINDOW->updateWindowDecos(); + + return {}; } -void CKeybindManager::event(std::string args) { +SDispatchResult CKeybindManager::event(std::string args) { g_pEventManager->postEvent(SHyprIPCEvent{"custom", args}); + return {}; } diff --git a/src/managers/KeybindManager.hpp b/src/managers/KeybindManager.hpp index 26b42b00..d1f26c2c 100644 --- a/src/managers/KeybindManager.hpp +++ b/src/managers/KeybindManager.hpp @@ -71,33 +71,39 @@ enum eMultiKeyCase { MK_FULL_MATCH }; +struct SDispatchResult { + bool passEvent = false; + bool success = true; + std::string error; +}; + class CKeybindManager { public: CKeybindManager(); ~CKeybindManager(); - bool onKeyEvent(std::any, SP); - bool onAxisEvent(const IPointer::SAxisEvent&); - bool onMouseEvent(const IPointer::SButtonEvent&); - void resizeWithBorder(const IPointer::SButtonEvent&); - void onSwitchEvent(const std::string&); - void onSwitchOnEvent(const std::string&); - void onSwitchOffEvent(const std::string&); + bool onKeyEvent(std::any, SP); + bool onAxisEvent(const IPointer::SAxisEvent&); + bool onMouseEvent(const IPointer::SButtonEvent&); + void resizeWithBorder(const IPointer::SButtonEvent&); + void onSwitchEvent(const std::string&); + void onSwitchOnEvent(const std::string&); + void onSwitchOffEvent(const std::string&); - void addKeybind(SKeybind); - void removeKeybind(uint32_t, const SParsedKey&); - uint32_t stringToModMask(std::string); - uint32_t keycodeToModifier(xkb_keycode_t); - void clearKeybinds(); - void shadowKeybinds(const xkb_keysym_t& doesntHave = 0, const uint32_t doesntHaveCode = 0); + void addKeybind(SKeybind); + void removeKeybind(uint32_t, const SParsedKey&); + uint32_t stringToModMask(std::string); + uint32_t keycodeToModifier(xkb_keycode_t); + void clearKeybinds(); + void shadowKeybinds(const xkb_keysym_t& doesntHave = 0, const uint32_t doesntHaveCode = 0); - std::unordered_map> m_mDispatchers; + std::unordered_map> m_mDispatchers; - wl_event_source* m_pActiveKeybindEventSource = nullptr; + wl_event_source* m_pActiveKeybindEventSource = nullptr; - bool m_bGroupsLocked = false; + bool m_bGroupsLocked = false; - std::list m_lKeybinds; + std::list m_lKeybinds; //since we cant find keycode through keyname in xkb: //on sendshortcut call, we once search for keyname (e.g. "g") the correct keycode (e.g. 42) @@ -105,7 +111,7 @@ class CKeybindManager { //we also store the keyboard pointer (in the string) to differentiate between different keyboard (layouts) std::unordered_map m_mKeyToCodeCache; - static void changeMouseBindMode(const eMouseBindMode mode); + static SDispatchResult changeMouseBindMode(const eMouseBindMode mode); private: std::deque m_dPressedKeys; @@ -124,7 +130,7 @@ class CKeybindManager { CTimer m_tScrollTimer; - bool handleKeybinds(const uint32_t, const SPressedKeyWithMods&, bool); + SDispatchResult handleKeybinds(const uint32_t, const SPressedKeyWithMods&, bool); std::set m_sMkKeys = {}; std::set m_sMkMods = {}; @@ -143,71 +149,72 @@ class CKeybindManager { static void moveWindowOutOfGroup(PHLWINDOW pWindow, const std::string& dir = ""); static void moveWindowIntoGroup(PHLWINDOW pWindow, PHLWINDOW pWindowInDirection); static void switchToWindow(PHLWINDOW PWINDOWTOCHANGETO); + static uint64_t spawnRawProc(std::string); // -------------- Dispatchers -------------- // - static void killActive(std::string); - static void kill(std::string); - static void spawn(std::string); - static uint64_t spawnRaw(std::string); - static void toggleActiveFloating(std::string); - static void toggleActivePseudo(std::string); - static void setActiveFloating(std::string); - static void setActiveTiled(std::string); - static void changeworkspace(std::string); - static void fullscreenActive(std::string); - static void fullscreenStateActive(std::string args); - static void moveActiveToWorkspace(std::string); - static void moveActiveToWorkspaceSilent(std::string); - static void moveFocusTo(std::string); - static void focusUrgentOrLast(std::string); - static void focusCurrentOrLast(std::string); - static void centerWindow(std::string); - static void moveActiveTo(std::string); - static void swapActive(std::string); - static void toggleGroup(std::string); - static void changeGroupActive(std::string); - static void alterSplitRatio(std::string); - static void focusMonitor(std::string); - static void toggleSplit(std::string); - static void swapSplit(std::string); - static void moveCursorToCorner(std::string); - static void moveCursor(std::string); - static void workspaceOpt(std::string); - static void renameWorkspace(std::string); - static void exitHyprland(std::string); - static void moveCurrentWorkspaceToMonitor(std::string); - static void moveWorkspaceToMonitor(std::string); - static void focusWorkspaceOnCurrentMonitor(std::string); - static void toggleSpecialWorkspace(std::string); - static void forceRendererReload(std::string); - static void resizeActive(std::string); - static void moveActive(std::string); - static void moveWindow(std::string); - static void resizeWindow(std::string); - static void circleNext(std::string); - static void focusWindow(std::string); - static void tagWindow(std::string); - static void setSubmap(std::string); - static void pass(std::string); - static void sendshortcut(std::string); - static void layoutmsg(std::string); - static void dpms(std::string); - static void swapnext(std::string); - static void swapActiveWorkspaces(std::string); - static void pinActive(std::string); - static void mouse(std::string); - static void bringActiveToTop(std::string); - static void alterZOrder(std::string); - static void lockGroups(std::string); - static void lockActiveGroup(std::string); - static void moveIntoGroup(std::string); - static void moveOutOfGroup(std::string); - static void moveGroupWindow(std::string); - static void moveWindowOrGroup(std::string); - static void setIgnoreGroupLock(std::string); - static void denyWindowFromGroup(std::string); - static void global(std::string); - static void event(std::string); + static SDispatchResult killActive(std::string); + static SDispatchResult kill(std::string); + static SDispatchResult spawn(std::string); + static SDispatchResult spawnRaw(std::string); + static SDispatchResult toggleActiveFloating(std::string); + static SDispatchResult toggleActivePseudo(std::string); + static SDispatchResult setActiveFloating(std::string); + static SDispatchResult setActiveTiled(std::string); + static SDispatchResult changeworkspace(std::string); + static SDispatchResult fullscreenActive(std::string); + static SDispatchResult fullscreenStateActive(std::string args); + static SDispatchResult moveActiveToWorkspace(std::string); + static SDispatchResult moveActiveToWorkspaceSilent(std::string); + static SDispatchResult moveFocusTo(std::string); + static SDispatchResult focusUrgentOrLast(std::string); + static SDispatchResult focusCurrentOrLast(std::string); + static SDispatchResult centerWindow(std::string); + static SDispatchResult moveActiveTo(std::string); + static SDispatchResult swapActive(std::string); + static SDispatchResult toggleGroup(std::string); + static SDispatchResult changeGroupActive(std::string); + static SDispatchResult alterSplitRatio(std::string); + static SDispatchResult focusMonitor(std::string); + static SDispatchResult toggleSplit(std::string); + static SDispatchResult swapSplit(std::string); + static SDispatchResult moveCursorToCorner(std::string); + static SDispatchResult moveCursor(std::string); + static SDispatchResult workspaceOpt(std::string); + static SDispatchResult renameWorkspace(std::string); + static SDispatchResult exitHyprland(std::string); + static SDispatchResult moveCurrentWorkspaceToMonitor(std::string); + static SDispatchResult moveWorkspaceToMonitor(std::string); + static SDispatchResult focusWorkspaceOnCurrentMonitor(std::string); + static SDispatchResult toggleSpecialWorkspace(std::string); + static SDispatchResult forceRendererReload(std::string); + static SDispatchResult resizeActive(std::string); + static SDispatchResult moveActive(std::string); + static SDispatchResult moveWindow(std::string); + static SDispatchResult resizeWindow(std::string); + static SDispatchResult circleNext(std::string); + static SDispatchResult focusWindow(std::string); + static SDispatchResult tagWindow(std::string); + static SDispatchResult setSubmap(std::string); + static SDispatchResult pass(std::string); + static SDispatchResult sendshortcut(std::string); + static SDispatchResult layoutmsg(std::string); + static SDispatchResult dpms(std::string); + static SDispatchResult swapnext(std::string); + static SDispatchResult swapActiveWorkspaces(std::string); + static SDispatchResult pinActive(std::string); + static SDispatchResult mouse(std::string); + static SDispatchResult bringActiveToTop(std::string); + static SDispatchResult alterZOrder(std::string); + static SDispatchResult lockGroups(std::string); + static SDispatchResult lockActiveGroup(std::string); + static SDispatchResult moveIntoGroup(std::string); + static SDispatchResult moveOutOfGroup(std::string); + static SDispatchResult moveGroupWindow(std::string); + static SDispatchResult moveWindowOrGroup(std::string); + static SDispatchResult setIgnoreGroupLock(std::string); + static SDispatchResult denyWindowFromGroup(std::string); + static SDispatchResult global(std::string); + static SDispatchResult event(std::string); friend class CCompositor; friend class CInputManager; diff --git a/src/plugins/PluginAPI.cpp b/src/plugins/PluginAPI.cpp index 098e3f12..398d4ce1 100644 --- a/src/plugins/PluginAPI.cpp +++ b/src/plugins/PluginAPI.cpp @@ -194,7 +194,10 @@ APICALL bool HyprlandAPI::addDispatcher(HANDLE handle, const std::string& name, PLUGIN->registeredDispatchers.push_back(name); - g_pKeybindManager->m_mDispatchers[name] = handler; + g_pKeybindManager->m_mDispatchers[name] = [handler](std::string arg1) -> SDispatchResult { + handler(arg1); + return {}; + }; return true; } @@ -378,4 +381,4 @@ APICALL bool HyprlandAPI::unregisterHyprCtlCommand(HANDLE handle, SPunregisterCommand(cmd); return true; -} \ No newline at end of file +} From aac90d92797825a65b9faab038586a3b88448667 Mon Sep 17 00:00:00 2001 From: "Nelo-T. Wallus" Date: Sun, 25 Aug 2024 13:13:48 +0200 Subject: [PATCH 0317/2181] hyprpm: Fix checking dependencies (#7504) * hyprpm: Fix checking dependencies * hyprpm: Check for dependency "pkg-config" --------- Co-authored-by: Nelo-T. Wallus --- hyprpm/src/core/PluginManager.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/hyprpm/src/core/PluginManager.cpp b/hyprpm/src/core/PluginManager.cpp index 6988547c..ab457ca6 100644 --- a/hyprpm/src/core/PluginManager.cpp +++ b/hyprpm/src/core/PluginManager.cpp @@ -904,9 +904,9 @@ std::string CPluginManager::headerErrorShort(const eHeadersErrors err) { } bool CPluginManager::hasDeps() { - std::vector deps = {"meson", "cpio", "cmake"}; + std::vector deps = {"meson", "cpio", "cmake", "pkg-config"}; for (auto& d : deps) { - if (!execAndGet("which " + d + " 2>&1").contains("/")) + if (!execAndGet("command -v " + d).contains("/")) return false; } From b672118f9238a48a18efd741cbcda387c5552238 Mon Sep 17 00:00:00 2001 From: trianta <56975502+Trimutex@users.noreply.github.com> Date: Sun, 25 Aug 2024 09:37:03 -0500 Subject: [PATCH 0318/2181] xwayland: deactivate xwayland focus if wayland is focused (#7458) * xwayland: deactivate xwayland focus if wayland is focused * xwayland: deactivate last xwayland surface after focusing wayland --- src/managers/XWaylandManager.cpp | 5 ++++- src/xwayland/XWM.cpp | 2 +- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/src/managers/XWaylandManager.cpp b/src/managers/XWaylandManager.cpp index f329dbe1..2f0632e0 100644 --- a/src/managers/XWaylandManager.cpp +++ b/src/managers/XWaylandManager.cpp @@ -43,8 +43,11 @@ void CHyprXWaylandManager::activateSurface(SP pSurface, bool w->m_pXWaylandSurface->restackToTop(); } w->m_pXWaylandSurface->activate(activate); - } else + } else { w->m_pXDGSurface->toplevel->setActive(activate); + if (g_pCompositor->m_pLastFocus && g_pCompositor->m_pLastWindow->m_bIsX11) + activateSurface(g_pCompositor->m_pLastFocus.lock(), false); + } } } diff --git a/src/xwayland/XWM.cpp b/src/xwayland/XWM.cpp index f6b6864c..a409b440 100644 --- a/src/xwayland/XWM.cpp +++ b/src/xwayland/XWM.cpp @@ -897,7 +897,7 @@ void CXWM::activateSurface(SP surf, bool activate) { if ((surf == focusedSurface && activate) || (surf && surf->overrideRedirect)) return; - if (!surf) { + if (!surf || (!activate && g_pCompositor->m_pLastWindow && !g_pCompositor->m_pLastWindow->m_bIsX11)) { setActiveWindow((uint32_t)XCB_WINDOW_NONE); focusWindow(nullptr); } else { From 83ab3ae0afeafe25ca2038888478740d0a80396a Mon Sep 17 00:00:00 2001 From: Vaxry Date: Mon, 26 Aug 2024 10:24:45 +0200 Subject: [PATCH 0319/2181] xwaylandmgr: minor refactor to activateSurface Make it more efficient now that we can + fix possible nullptr deref fixes #7514 --- src/managers/XWaylandManager.cpp | 36 +++++++++++++++++--------------- 1 file changed, 19 insertions(+), 17 deletions(-) diff --git a/src/managers/XWaylandManager.cpp b/src/managers/XWaylandManager.cpp index 2f0632e0..a6fd97f5 100644 --- a/src/managers/XWaylandManager.cpp +++ b/src/managers/XWaylandManager.cpp @@ -28,26 +28,28 @@ void CHyprXWaylandManager::activateSurface(SP pSurface, bool if (!pSurface) return; - // TODO: - // this cannot be nicely done until we rewrite wlr_surface - for (auto& w : g_pCompositor->m_vWindows) { - if (!w->m_bIsMapped) - continue; + auto HLSurface = CWLSurface::fromResource(pSurface); + if (!HLSurface) { + Debug::log(TRACE, "CHyprXWaylandManager::activateSurface on non-desktop surface, ignoring"); + return; + } - if (w->m_pWLSurface->resource() != pSurface) - continue; + const auto PWINDOW = HLSurface->getWindow(); + if (!PWINDOW) { + Debug::log(TRACE, "CHyprXWaylandManager::activateSurface on non-window surface, ignoring"); + return; + } - if (w->m_bIsX11) { - if (activate) { - w->m_pXWaylandSurface->setMinimized(false); - w->m_pXWaylandSurface->restackToTop(); - } - w->m_pXWaylandSurface->activate(activate); - } else { - w->m_pXDGSurface->toplevel->setActive(activate); - if (g_pCompositor->m_pLastFocus && g_pCompositor->m_pLastWindow->m_bIsX11) - activateSurface(g_pCompositor->m_pLastFocus.lock(), false); + if (PWINDOW->m_bIsX11 && PWINDOW->m_pXWaylandSurface) { + if (activate) { + PWINDOW->m_pXWaylandSurface->setMinimized(false); + PWINDOW->m_pXWaylandSurface->restackToTop(); } + PWINDOW->m_pXWaylandSurface->activate(activate); + } else if (!PWINDOW->m_bIsX11 && PWINDOW->m_pXDGSurface) { + PWINDOW->m_pXDGSurface->toplevel->setActive(activate); + if (g_pCompositor->m_pLastFocus && g_pCompositor->m_pLastWindow && g_pCompositor->m_pLastWindow->m_bIsX11) + activateSurface(g_pCompositor->m_pLastFocus.lock(), false); } } From 28f6c2df5923bfe514d238399f934fc80bb1449d Mon Sep 17 00:00:00 2001 From: Maximilian Seidler <78690852+PaideiaDilemma@users.noreply.github.com> Date: Mon, 26 Aug 2024 08:27:34 +0000 Subject: [PATCH 0320/2181] sessionLock: fix misc:allow_session_lock_restore (#7511) * Revert "sessionLock: fix the check for locking a locked session (#6843)" This reverts commit 9ff83f4aa97269bf26381a84501d0b19f1926961. * sessionLock: remove early check for session beeing locked It is checked in the `onNewSessionLock` handler, which also respects the `misc:allow_session_lock_restore` option. --- src/protocols/SessionLock.cpp | 7 ------- 1 file changed, 7 deletions(-) diff --git a/src/protocols/SessionLock.cpp b/src/protocols/SessionLock.cpp index 7b0d8b3b..fe44face 100644 --- a/src/protocols/SessionLock.cpp +++ b/src/protocols/SessionLock.cpp @@ -175,13 +175,6 @@ void CSessionLockProtocol::onLock(CExtSessionLockManagerV1* pMgr, uint32_t id) { return; } - if (locked) { - LOGM(ERR, "Tried to lock a locked session"); - RESOURCE->inert = true; - RESOURCE->resource->sendFinished(); - return; - } - events.newLock.emit(RESOURCE); locked = true; From ca85455a8ed5dbe920a47c1a48de1dd993446481 Mon Sep 17 00:00:00 2001 From: Adithya Ajith <50308085+adharmic@users.noreply.github.com> Date: Mon, 26 Aug 2024 05:25:52 -0500 Subject: [PATCH 0321/2181] misc: Rename all instances of "emtpy" to "empty" (#7522) --- src/Compositor.cpp | 4 ++-- src/Compositor.hpp | 2 +- src/desktop/Workspace.cpp | 10 +++++----- src/desktop/Workspace.hpp | 4 ++-- 4 files changed, 10 insertions(+), 10 deletions(-) diff --git a/src/Compositor.cpp b/src/Compositor.cpp index c9a698ce..a419e741 100644 --- a/src/Compositor.cpp +++ b/src/Compositor.cpp @@ -2624,7 +2624,7 @@ void CCompositor::forceReportSizesToWindowsOnWorkspace(const WORKSPACEID& wid) { } } -PHLWORKSPACE CCompositor::createNewWorkspace(const WORKSPACEID& id, const MONITORID& monid, const std::string& name, bool isEmtpy) { +PHLWORKSPACE CCompositor::createNewWorkspace(const WORKSPACEID& id, const MONITORID& monid, const std::string& name, bool isEmpty) { const auto NAME = name == "" ? std::to_string(id) : name; auto monID = monid; @@ -2635,7 +2635,7 @@ PHLWORKSPACE CCompositor::createNewWorkspace(const WORKSPACEID& id, const MONITO const bool SPECIAL = id >= SPECIAL_WORKSPACE_START && id <= -2; - const auto PWORKSPACE = m_vWorkspaces.emplace_back(CWorkspace::create(id, monID, NAME, SPECIAL, isEmtpy)); + const auto PWORKSPACE = m_vWorkspaces.emplace_back(CWorkspace::create(id, monID, NAME, SPECIAL, isEmpty)); PWORKSPACE->m_fAlpha.setValueAndWarp(0); diff --git a/src/Compositor.hpp b/src/Compositor.hpp index a570a06e..bb986f5e 100644 --- a/src/Compositor.hpp +++ b/src/Compositor.hpp @@ -165,7 +165,7 @@ class CCompositor { Vector2D parseWindowVectorArgsRelative(const std::string&, const Vector2D&); void forceReportSizesToWindowsOnWorkspace(const WORKSPACEID&); PHLWORKSPACE createNewWorkspace(const WORKSPACEID&, const MONITORID&, const std::string& name = "", - bool isEmtpy = true); // will be deleted next frame if left empty and unfocused! + bool isEmpty = true); // will be deleted next frame if left empty and unfocused! void renameWorkspace(const WORKSPACEID&, const std::string& name = ""); void setActiveMonitor(CMonitor*); bool isWorkspaceSpecial(const WORKSPACEID&); diff --git a/src/desktop/Workspace.cpp b/src/desktop/Workspace.cpp index a9412e6d..72d9705e 100644 --- a/src/desktop/Workspace.cpp +++ b/src/desktop/Workspace.cpp @@ -5,18 +5,18 @@ #include using namespace Hyprutils::String; -PHLWORKSPACE CWorkspace::create(WORKSPACEID id, MONITORID monitorID, std::string name, bool special, bool isEmtpy) { - PHLWORKSPACE workspace = makeShared(id, monitorID, name, special, isEmtpy); +PHLWORKSPACE CWorkspace::create(WORKSPACEID id, MONITORID monitorID, std::string name, bool special, bool isEmpty) { + PHLWORKSPACE workspace = makeShared(id, monitorID, name, special, isEmpty); workspace->init(workspace); return workspace; } -CWorkspace::CWorkspace(WORKSPACEID id, MONITORID monitorID, std::string name, bool special, bool isEmtpy) { +CWorkspace::CWorkspace(WORKSPACEID id, MONITORID monitorID, std::string name, bool special, bool isEmpty) { m_iMonitorID = monitorID; m_iID = id; m_szName = name; m_bIsSpecialWorkspace = special; - m_bWasCreatedEmtpy = isEmtpy; + m_bWasCreatedEmpty = isEmpty; } void CWorkspace::init(PHLWORKSPACE self) { @@ -49,7 +49,7 @@ void CWorkspace::init(PHLWORKSPACE self) { const auto WORKSPACERULE = g_pConfigManager->getWorkspaceRuleFor(self); m_bPersistent = WORKSPACERULE.isPersistent; - if (self->m_bWasCreatedEmtpy) + if (self->m_bWasCreatedEmpty) if (auto cmd = WORKSPACERULE.onCreatedEmptyRunCmd) g_pKeybindManager->spawn(*cmd); diff --git a/src/desktop/Workspace.hpp b/src/desktop/Workspace.hpp index 9cacb0cc..7a32459c 100644 --- a/src/desktop/Workspace.hpp +++ b/src/desktop/Workspace.hpp @@ -17,7 +17,7 @@ class CWindow; class CWorkspace { public: - static PHLWORKSPACE create(WORKSPACEID id, MONITORID monitorID, std::string name, bool special = false, bool isEmtpy = true); + static PHLWORKSPACE create(WORKSPACEID id, MONITORID monitorID, std::string name, bool special = false, bool isEmpty = true); // use create() don't use this CWorkspace(WORKSPACEID id, MONITORID monitorID, std::string name, bool special = false, bool isEmpty = true); ~CWorkspace(); @@ -57,7 +57,7 @@ class CWorkspace { // last monitor (used on reconnect) std::string m_szLastMonitor = ""; - bool m_bWasCreatedEmtpy = true; + bool m_bWasCreatedEmpty = true; bool m_bPersistent = false; From 9c5a37a797ea1f1829859ab5b07016b2f27f739c Mon Sep 17 00:00:00 2001 From: Tom Englund Date: Mon, 26 Aug 2024 14:08:30 +0200 Subject: [PATCH 0322/2181] build: fix 32bit builds (#7510) ensure the correct type is passed to std::clamp and std::max int64_t is different on 64bit compared to 32bit, also in presentationtime tv_sec is __time_t and on 32bit its a 32bit type so right shift count >= width of type. so only bit shift on 64bit. and avoid potential nullptr deref in the for loops, check for .end() before *it <= endID. --- src/helpers/MiscFunctions.cpp | 10 +++++----- src/protocols/PresentationTime.cpp | 6 +++++- 2 files changed, 10 insertions(+), 6 deletions(-) diff --git a/src/helpers/MiscFunctions.cpp b/src/helpers/MiscFunctions.cpp index 86f24e3a..ef319946 100644 --- a/src/helpers/MiscFunctions.cpp +++ b/src/helpers/MiscFunctions.cpp @@ -353,13 +353,13 @@ SWorkspaceIDName getWorkspaceIDNameFromString(const std::string& in) { char walkDir = in[1]; // sanitize. 0 means invalid oob in - - predictedWSID = std::max(predictedWSID, 0L); + predictedWSID = std::max(predictedWSID, static_cast(0)); // Count how many invalidWSes are in between (how bad the prediction was) WORKSPACEID beginID = in[1] == '+' ? activeWSID + 1 : predictedWSID; WORKSPACEID endID = in[1] == '+' ? predictedWSID : activeWSID; auto begin = invalidWSes.upper_bound(beginID - 1); // upper_bound is >, we want >= - for (auto it = begin; *it <= endID && it != invalidWSes.end(); it++) { + for (auto it = begin; it != invalidWSes.end() && *it <= endID; it++) { remainingWSes++; } @@ -376,7 +376,7 @@ SWorkspaceIDName getWorkspaceIDNameFromString(const std::string& in) { } currentItem += remains; - currentItem = std::max(currentItem, 0UL); + currentItem = std::max(currentItem, static_cast(0)); if (currentItem >= namedWSes.size()) { // At the seam between namedWSes and normal WSes. Behave like r+[diff] at imaginary ws 0 size_t diff = currentItem - (namedWSes.size() - 1); @@ -384,7 +384,7 @@ SWorkspaceIDName getWorkspaceIDNameFromString(const std::string& in) { WORKSPACEID beginID = 1; WORKSPACEID endID = predictedWSID; auto begin = invalidWSes.upper_bound(beginID - 1); // upper_bound is >, we want >= - for (auto it = begin; *it <= endID && it != invalidWSes.end(); it++) { + for (auto it = begin; it != invalidWSes.end() && *it <= endID; it++) { remainingWSes++; } walkDir = '+'; @@ -413,7 +413,7 @@ SWorkspaceIDName getWorkspaceIDNameFromString(const std::string& in) { // Need remainingWSes more auto namedWSIdx = namedWSes.size() - remainingWSes; // Sanitze - namedWSIdx = std::clamp(namedWSIdx, 0UL, namedWSes.size() - 1); + namedWSIdx = std::clamp(namedWSIdx, static_cast(0), namedWSes.size() - static_cast(1)); finalWSID = namedWSes[namedWSIdx]; } else { // Couldn't find valid workspace in negative direction, search last first one back up positive direction diff --git a/src/protocols/PresentationTime.cpp b/src/protocols/PresentationTime.cpp index 335cf557..638435c7 100644 --- a/src/protocols/PresentationTime.cpp +++ b/src/protocols/PresentationTime.cpp @@ -58,8 +58,12 @@ void CPresentationFeedback::sendQueued(SP data, timespe if (reportedFlags & Aquamarine::IOutput::AQ_OUTPUT_PRESENT_HW_COMPLETION) flags |= WP_PRESENTATION_FEEDBACK_KIND_HW_COMPLETION; + __time_t tv_sec = 0; + if (sizeof(__time_t) > 4) + tv_sec = when->tv_sec >> 32; + if (data->wasPresented) - resource->sendPresented((uint32_t)(when->tv_sec >> 32), (uint32_t)(when->tv_sec & 0xFFFFFFFF), (uint32_t)(when->tv_nsec), untilRefreshNs, (uint32_t)(seq >> 32), + resource->sendPresented((uint32_t)tv_sec, (uint32_t)(when->tv_sec & 0xFFFFFFFF), (uint32_t)(when->tv_nsec), untilRefreshNs, (uint32_t)(seq >> 32), (uint32_t)(seq & 0xFFFFFFFF), (wpPresentationFeedbackKind)flags); else resource->sendDiscarded(); From 8d6c18076f3268a6c85c6085d29f898267028101 Mon Sep 17 00:00:00 2001 From: Tom Englund Date: Mon, 26 Aug 2024 17:25:39 +0200 Subject: [PATCH 0323/2181] core: make most for loops use const references (#7527) why not let the compiler optimise things for us at hyprspeeds when we can. --- src/Compositor.cpp | 32 ++++++------- src/config/ConfigManager.cpp | 36 +++++++------- src/debug/HyprCtl.cpp | 26 +++++------ src/debug/HyprDebugOverlay.cpp | 8 ++-- src/desktop/LayerSurface.cpp | 2 +- src/desktop/Window.cpp | 16 +++---- src/helpers/Monitor.cpp | 4 +- src/layout/DwindleLayout.cpp | 2 +- src/layout/IHyprLayout.cpp | 2 +- src/layout/MasterLayout.cpp | 8 ++-- src/managers/AnimationManager.cpp | 2 +- src/managers/KeybindManager.cpp | 8 ++-- src/managers/PointerManager.cpp | 14 +++--- src/managers/SeatManager.cpp | 70 ++++++++++++++-------------- src/managers/SessionLockManager.cpp | 4 +- src/managers/XWaylandManager.cpp | 4 +- src/managers/input/IdleInhibitor.cpp | 2 +- src/managers/input/InputManager.cpp | 6 +-- src/managers/input/Swipe.cpp | 6 +-- src/managers/input/Tablets.cpp | 4 +- src/plugins/HookSystem.cpp | 2 +- src/protocols/DRMLease.cpp | 4 +- src/protocols/DataDeviceWlr.cpp | 6 +-- src/protocols/core/Compositor.cpp | 8 ++-- src/protocols/core/DataDevice.cpp | 8 ++-- src/protocols/core/Output.cpp | 2 +- src/protocols/core/Seat.cpp | 2 +- src/render/OpenGL.cpp | 8 ++-- src/render/Renderer.cpp | 24 +++++----- src/xwayland/XSurface.cpp | 4 +- src/xwayland/XWM.cpp | 14 +++--- 31 files changed, 169 insertions(+), 169 deletions(-) diff --git a/src/Compositor.cpp b/src/Compositor.cpp index a419e741..0aa7f213 100644 --- a/src/Compositor.cpp +++ b/src/Compositor.cpp @@ -314,7 +314,7 @@ void CCompositor::initServer(std::string socketName, int socketFd) { initManagers(STAGE_LATE); - for (auto& o : pendingOutputs) { + for (auto const& o : pendingOutputs) { onNewMonitor(o); } pendingOutputs.clear(); @@ -403,7 +403,7 @@ void CCompositor::initAllSignals() { m_bSessionActive = false; - for (auto& m : m_vMonitors) { + for (auto const& m : m_vMonitors) { m->noFrameSchedule = true; m->framesToSkip = 1; } @@ -741,7 +741,7 @@ CMonitor* CCompositor::getMonitorFromVector(const Vector2D& point) { float bestDistance = 0.f; SP pBestMon; - for (auto& m : m_vMonitors) { + for (auto const& m : m_vMonitors) { float dist = vecToRectDistanceSquared(point, m->vecPosition, m->vecPosition + m->vecSize); if (dist < bestDistance || !pBestMon) { @@ -1164,8 +1164,8 @@ void CCompositor::focusSurface(SP pSurface, PHLWINDOW pWindo } SP CCompositor::vectorToLayerPopupSurface(const Vector2D& pos, CMonitor* monitor, Vector2D* sCoords, PHLLS* ppLayerSurfaceFound) { - for (auto& lsl : monitor->m_aLayerSurfaceLayers | std::views::reverse) { - for (auto& ls : lsl | std::views::reverse) { + for (auto const& lsl : monitor->m_aLayerSurfaceLayers | std::views::reverse) { + for (auto const& ls : lsl | std::views::reverse) { if (ls->fadingOut || !ls->layerSurface || (ls->layerSurface && !ls->layerSurface->mapped) || ls->alpha.value() == 0.f) continue; @@ -1183,7 +1183,7 @@ SP CCompositor::vectorToLayerPopupSurface(const Vector2D& po } SP CCompositor::vectorToLayerSurface(const Vector2D& pos, std::vector* layerSurfaces, Vector2D* sCoords, PHLLS* ppLayerSurfaceFound) { - for (auto& ls : *layerSurfaces | std::views::reverse) { + for (auto const& ls : *layerSurfaces | std::views::reverse) { if (ls->fadingOut || !ls->layerSurface || (ls->layerSurface && !ls->layerSurface->surface->mapped) || ls->alpha.value() == 0.f) continue; @@ -1458,7 +1458,7 @@ void CCompositor::cleanupFadingOut(const MONITORID& monid) { g_pHyprOpenGL->markBlurDirtyForMonitor(getMonitorFromID(monid)); if (ls->fadingOut && ls->readyToDelete && ls->isFadedOut()) { - for (auto& m : m_vMonitors) { + for (auto const& m : m_vMonitors) { for (auto& lsl : m->m_aLayerSurfaceLayers) { if (!lsl.empty() && std::find_if(lsl.begin(), lsl.end(), [&](auto& other) { return other == ls; }) != lsl.end()) { std::erase_if(lsl, [&](auto& other) { return other == ls || !other; }); @@ -1718,7 +1718,7 @@ PHLWINDOW CCompositor::getPrevWindowOnWorkspace(PHLWINDOW pWindow, bool focusabl WORKSPACEID CCompositor::getNextAvailableNamedWorkspace() { WORKSPACEID lowest = -1337 + 1; - for (auto& w : m_vWorkspaces) { + for (auto const& w : m_vWorkspaces) { if (w->m_iID < -1 && w->m_iID < lowest) lowest = w->m_iID; } @@ -1748,7 +1748,7 @@ PHLWORKSPACE CCompositor::getWorkspaceByString(const std::string& str) { } bool CCompositor::isPointOnAnyMonitor(const Vector2D& point) { - for (auto& m : m_vMonitors) { + for (auto const& m : m_vMonitors) { if (VECINRECT(point, m->vecPosition.x, m->vecPosition.y, m->vecSize.x + m->vecPosition.x, m->vecSize.y + m->vecPosition.y)) return true; } @@ -1834,7 +1834,7 @@ CMonitor* CCompositor::getMonitorInDirection(CMonitor* pSourceMonitor, const cha } void CCompositor::updateAllWindowsAnimatedDecorationValues() { - for (auto& w : m_vWindows) { + for (auto const& w : m_vWindows) { if (!w->m_bIsMapped) continue; @@ -2139,7 +2139,7 @@ void CCompositor::moveWorkspaceToMonitor(PHLWORKSPACE pWorkspace, CMonitor* pMon if (!SWITCHINGISACTIVE) nextWorkspaceOnMonitorID = pWorkspace->m_iID; else { - for (auto& w : m_vWorkspaces) { + for (auto const& w : m_vWorkspaces) { if (w->m_iMonitorID == POLDMON->ID && w->m_iID != pWorkspace->m_iID && !w->m_bIsSpecialWorkspace) { nextWorkspaceOnMonitorID = w->m_iID; break; @@ -2237,7 +2237,7 @@ bool CCompositor::workspaceIDOutOfBounds(const WORKSPACEID& id) { WORKSPACEID lowestID = INT64_MAX; WORKSPACEID highestID = INT64_MIN; - for (auto& w : m_vWorkspaces) { + for (auto const& w : m_vWorkspaces) { if (w->m_bIsSpecialWorkspace) continue; @@ -2271,7 +2271,7 @@ void CCompositor::updateFullscreenFadeOnWorkspace(PHLWORKSPACE pWorkspace) { const auto PMONITOR = getMonitorFromID(pWorkspace->m_iMonitorID); if (pWorkspace->m_iID == PMONITOR->activeWorkspaceID() || pWorkspace->m_iID == PMONITOR->activeSpecialWorkspaceID()) { - for (auto& ls : PMONITOR->m_aLayerSurfaceLayers[ZWLR_LAYER_SHELL_V1_LAYER_TOP]) { + for (auto const& ls : PMONITOR->m_aLayerSurfaceLayers[ZWLR_LAYER_SHELL_V1_LAYER_TOP]) { if (!ls->fadingOut) ls->alpha = FULLSCREEN && pWorkspace->m_efFullscreenMode == FSMODE_FULLSCREEN ? 0.f : 1.f; } @@ -2376,7 +2376,7 @@ PHLWINDOW CCompositor::getX11Parent(PHLWINDOW pWindow) { if (!pWindow->m_bIsX11) return nullptr; - for (auto& w : m_vWindows) { + for (auto const& w : m_vWindows) { if (!w->m_bIsX11) continue; @@ -2543,7 +2543,7 @@ void CCompositor::closeWindow(PHLWINDOW pWindow) { PHLLS CCompositor::getLayerSurfaceFromSurface(SP pSurface) { std::pair, bool> result = {pSurface, false}; - for (auto& ls : m_vLayers) { + for (auto const& ls : m_vLayers) { if (ls->layerSurface && ls->layerSurface->surface == pSurface) return ls; @@ -2679,7 +2679,7 @@ bool CCompositor::isWorkspaceSpecial(const WORKSPACEID& id) { WORKSPACEID CCompositor::getNewSpecialID() { WORKSPACEID highest = SPECIAL_WORKSPACE_START; - for (auto& ws : m_vWorkspaces) { + for (auto const& ws : m_vWorkspaces) { if (ws->m_bIsSpecialWorkspace && ws->m_iID > highest) { highest = ws->m_iID; } diff --git a/src/config/ConfigManager.cpp b/src/config/ConfigManager.cpp index 0390b9d9..007869ee 100644 --- a/src/config/ConfigManager.cpp +++ b/src/config/ConfigManager.cpp @@ -813,11 +813,11 @@ void CConfigManager::postConfigReload(const Hyprlang::CParseResult& result) { static const auto PENABLEEXPLICIT = CConfigValue("render:explicit_sync"); static int prevEnabledExplicit = *PENABLEEXPLICIT; - for (auto& w : g_pCompositor->m_vWindows) { + for (auto const& w : g_pCompositor->m_vWindows) { w->uncacheWindowDecos(); } - for (auto& m : g_pCompositor->m_vMonitors) + for (auto const& m : g_pCompositor->m_vMonitors) g_pLayoutManager->getCurrentLayout()->recalculateMonitor(m->ID); // Update the keyboard layout to the cfg'd one if this is not the first launch @@ -901,7 +901,7 @@ void CConfigManager::postConfigReload(const Hyprlang::CParseResult& result) { m->forceFullFrames = 2; // also force mirrors, as the aspect ratio could've changed - for (auto& mirror : m->mirrors) + for (auto const& mirror : m->mirrors) mirror->forceFullFrames = 3; } @@ -940,7 +940,7 @@ std::string CConfigManager::parseKeyword(const std::string& COMMAND, const std:: // invalidate layouts if they changed if (COMMAND == "monitor" || COMMAND.contains("gaps_") || COMMAND.starts_with("dwindle:") || COMMAND.starts_with("master:")) { - for (auto& m : g_pCompositor->m_vMonitors) + for (auto const& m : g_pCompositor->m_vMonitors) g_pLayoutManager->getCurrentLayout()->recalculateMonitor(m->ID); } @@ -1034,7 +1034,7 @@ std::string CConfigManager::getDeviceString(const std::string& dev, const std::s } SMonitorRule CConfigManager::getMonitorRuleFor(const CMonitor& PMONITOR) { - for (auto& r : m_dMonitorRules | std::views::reverse) { + for (auto const& r : m_dMonitorRules | std::views::reverse) { if (PMONITOR.matchesStaticSelector(r.name)) { return r; } @@ -1042,7 +1042,7 @@ SMonitorRule CConfigManager::getMonitorRuleFor(const CMonitor& PMONITOR) { Debug::log(WARN, "No rule found for {}, trying to use the first.", PMONITOR.szName); - for (auto& r : m_dMonitorRules) { + for (auto const& r : m_dMonitorRules) { if (r.name.empty()) { return r; } @@ -1354,7 +1354,7 @@ void CConfigManager::dispatchExecOnce() { firstExecDispatched = true; isLaunchingExecOnce = true; - for (auto& c : firstExecRequests) { + for (auto const& c : firstExecRequests) { handleRawExec("", c); } @@ -1438,7 +1438,7 @@ bool CConfigManager::deviceConfigExists(const std::string& dev) { } bool CConfigManager::shouldBlurLS(const std::string& ns) { - for (auto& bls : m_dBlurLSNamespaces) { + for (auto const& bls : m_dBlurLSNamespaces) { if (bls == ns) { return true; } @@ -1553,7 +1553,7 @@ CMonitor* CConfigManager::getBoundMonitorForWS(const std::string& wsname) { } std::string CConfigManager::getBoundMonitorStringForWS(const std::string& wsname) { - for (auto& wr : m_dWorkspaceRules) { + for (auto const& wr : m_dWorkspaceRules) { const auto WSNAME = wr.workspaceName.starts_with("name:") ? wr.workspaceName.substr(5) : wr.workspaceName; if (WSNAME == wsname) @@ -1624,7 +1624,7 @@ void CConfigManager::addPluginKeyword(HANDLE handle, const std::string& name, Hy } void CConfigManager::removePluginConfig(HANDLE handle) { - for (auto& k : pluginKeywords) { + for (auto const& k : pluginKeywords) { if (k.handle != handle) continue; @@ -1647,7 +1647,7 @@ std::string CConfigManager::getDefaultWorkspaceFor(const std::string& name) { if (other->monitor == name) return other->workspaceString; if (other->monitor.substr(0, 5) == "desc:") { - auto monitor = g_pCompositor->getMonitorFromDesc(other->monitor.substr(5)); + auto const monitor = g_pCompositor->getMonitorFromDesc(other->monitor.substr(5)); if (monitor && monitor->szName == name) return other->workspaceString; } @@ -2044,7 +2044,7 @@ std::optional CConfigManager::handleBind(const std::string& command bool dontInhibit = false; const auto BINDARGS = command.substr(4); - for (auto& arg : BINDARGS) { + for (auto const& arg : BINDARGS) { if (arg == 'l') { locked = true; } else if (arg == 'r') { @@ -2222,9 +2222,9 @@ std::optional CConfigManager::handleLayerRule(const std::string& co m_dLayerRules.push_back({VALUE, RULE}); - for (auto& m : g_pCompositor->m_vMonitors) - for (auto& lsl : m->m_aLayerSurfaceLayers) - for (auto& ls : lsl) + for (auto const& m : g_pCompositor->m_vMonitors) + for (auto const& lsl : m->m_aLayerSurfaceLayers) + for (auto const& ls : lsl) ls->applyRules(); return {}; @@ -2423,9 +2423,9 @@ void CConfigManager::updateBlurredLS(const std::string& name, const bool forceBl matchName = matchName.substr(8); } - for (auto& m : g_pCompositor->m_vMonitors) { - for (auto& lsl : m->m_aLayerSurfaceLayers) { - for (auto& ls : lsl) { + for (auto const& m : g_pCompositor->m_vMonitors) { + for (auto const& lsl : m->m_aLayerSurfaceLayers) { + for (auto const& ls : lsl) { if (BYADDRESS) { if (std::format("0x{:x}", (uintptr_t)ls.get()) == matchName) ls->forceBlur = forceBlur; diff --git a/src/debug/HyprCtl.cpp b/src/debug/HyprCtl.cpp index a92c3a53..2fc5cc7d 100644 --- a/src/debug/HyprCtl.cpp +++ b/src/debug/HyprCtl.cpp @@ -146,7 +146,7 @@ std::string monitorsRequest(eHyprCtlOutputFormat format, std::string request) { if (format == eHyprCtlOutputFormat::FORMAT_JSON) { result += "["; - for (auto& m : allMonitors ? g_pCompositor->m_vRealMonitors : g_pCompositor->m_vMonitors) { + for (auto const& m : allMonitors ? g_pCompositor->m_vRealMonitors : g_pCompositor->m_vMonitors) { result += CHyprCtl::getMonitorData(m, format); } @@ -154,7 +154,7 @@ std::string monitorsRequest(eHyprCtlOutputFormat format, std::string request) { result += "]"; } else { - for (auto& m : allMonitors ? g_pCompositor->m_vRealMonitors : g_pCompositor->m_vMonitors) { + for (auto const& m : allMonitors ? g_pCompositor->m_vRealMonitors : g_pCompositor->m_vMonitors) { if (!m->output || m->ID == -1) continue; @@ -272,7 +272,7 @@ std::string clientsRequest(eHyprCtlOutputFormat format, std::string request) { if (format == eHyprCtlOutputFormat::FORMAT_JSON) { result += "["; - for (auto& w : g_pCompositor->m_vWindows) { + for (auto const& w : g_pCompositor->m_vWindows) { if (!w->m_bIsMapped && !g_pHyprCtl->m_sCurrentRequestParams.all) continue; @@ -283,7 +283,7 @@ std::string clientsRequest(eHyprCtlOutputFormat format, std::string request) { result += "]"; } else { - for (auto& w : g_pCompositor->m_vWindows) { + for (auto const& w : g_pCompositor->m_vWindows) { if (!w->m_bIsMapped && !g_pHyprCtl->m_sCurrentRequestParams.all) continue; @@ -381,7 +381,7 @@ std::string workspacesRequest(eHyprCtlOutputFormat format, std::string request) if (format == eHyprCtlOutputFormat::FORMAT_JSON) { result += "["; - for (auto& w : g_pCompositor->m_vWorkspaces) { + for (auto const& w : g_pCompositor->m_vWorkspaces) { result += CHyprCtl::getWorkspaceData(w, format); result += ","; } @@ -389,7 +389,7 @@ std::string workspacesRequest(eHyprCtlOutputFormat format, std::string request) trimTrailingComma(result); result += "]"; } else { - for (auto& w : g_pCompositor->m_vWorkspaces) { + for (auto const& w : g_pCompositor->m_vWorkspaces) { result += CHyprCtl::getWorkspaceData(w, format); } } @@ -401,7 +401,7 @@ std::string workspaceRulesRequest(eHyprCtlOutputFormat format, std::string reque std::string result = ""; if (format == eHyprCtlOutputFormat::FORMAT_JSON) { result += "["; - for (auto& r : g_pConfigManager->getAllWorkspaceRules()) { + for (auto const& r : g_pConfigManager->getAllWorkspaceRules()) { result += getWorkspaceRuleData(r, format); result += ","; } @@ -409,7 +409,7 @@ std::string workspaceRulesRequest(eHyprCtlOutputFormat format, std::string reque trimTrailingComma(result); result += "]"; } else { - for (auto& r : g_pConfigManager->getAllWorkspaceRules()) { + for (auto const& r : g_pConfigManager->getAllWorkspaceRules()) { result += getWorkspaceRuleData(r, format); } } @@ -437,7 +437,7 @@ std::string layersRequest(eHyprCtlOutputFormat format, std::string request) { if (format == eHyprCtlOutputFormat::FORMAT_JSON) { result += "{\n"; - for (auto& mon : g_pCompositor->m_vMonitors) { + for (auto const& mon : g_pCompositor->m_vMonitors) { result += std::format( R"#("{}": {{ "levels": {{ @@ -744,7 +744,7 @@ std::string animationsRequest(eHyprCtlOutputFormat format, std::string request) ret += ",\n["; - for (auto& bz : g_pAnimationManager->getAllBeziers()) { + for (auto const& bz : g_pAnimationManager->getAllBeziers()) { ret += std::format(R"#( {{ "name": "{}" @@ -782,7 +782,7 @@ std::string globalShortcutsRequest(eHyprCtlOutputFormat format, std::string requ ret += std::format("{}:{} -> {}\n", sh.appid, sh.id, sh.description); } else { ret += "["; - for (auto& sh : SHORTCUTS) { + for (auto const& sh : SHORTCUTS) { ret += std::format(R"#( {{ "name": "{}", @@ -1286,7 +1286,7 @@ std::string dispatchSetProp(eHyprCtlOutputFormat format, std::string request) { g_pCompositor->focusWindow(PLASTWINDOW); } - for (auto& m : g_pCompositor->m_vMonitors) + for (auto const& m : g_pCompositor->m_vMonitors) g_pLayoutManager->getCurrentLayout()->recalculateMonitor(m->ID); return "ok"; @@ -1386,7 +1386,7 @@ std::string dispatchOutput(eHyprCtlOutputFormat format, std::string request) { bool added = false; if (!vars[3].empty()) { - for (auto& m : g_pCompositor->m_vRealMonitors) { + for (auto const& m : g_pCompositor->m_vRealMonitors) { if (m->szName == vars[3]) return "Name already taken"; } diff --git a/src/debug/HyprDebugOverlay.cpp b/src/debug/HyprDebugOverlay.cpp index fbd8cd71..22c741a6 100644 --- a/src/debug/HyprDebugOverlay.cpp +++ b/src/debug/HyprDebugOverlay.cpp @@ -57,7 +57,7 @@ int CHyprMonitorDebugOverlay::draw(int offset) { float avgFrametime = 0; float maxFrametime = 0; float minFrametime = 9999; - for (auto& ft : m_dLastFrametimes) { + for (auto const& ft : m_dLastFrametimes) { if (ft > maxFrametime) maxFrametime = ft; if (ft < minFrametime) @@ -70,7 +70,7 @@ int CHyprMonitorDebugOverlay::draw(int offset) { float avgRenderTime = 0; float maxRenderTime = 0; float minRenderTime = 9999; - for (auto& rt : m_dLastRenderTimes) { + for (auto const& rt : m_dLastRenderTimes) { if (rt > maxRenderTime) maxRenderTime = rt; if (rt < minRenderTime) @@ -83,7 +83,7 @@ int CHyprMonitorDebugOverlay::draw(int offset) { float avgRenderTimeNoOverlay = 0; float maxRenderTimeNoOverlay = 0; float minRenderTimeNoOverlay = 9999; - for (auto& rt : m_dLastRenderTimesNoOverlay) { + for (auto const& rt : m_dLastRenderTimesNoOverlay) { if (rt > maxRenderTimeNoOverlay) maxRenderTimeNoOverlay = rt; if (rt < minRenderTimeNoOverlay) @@ -96,7 +96,7 @@ int CHyprMonitorDebugOverlay::draw(int offset) { float avgAnimMgrTick = 0; float maxAnimMgrTick = 0; float minAnimMgrTick = 9999; - for (auto& at : m_dLastAnimationTicks) { + for (auto const& at : m_dLastAnimationTicks) { if (at > maxAnimMgrTick) maxAnimMgrTick = at; if (at < minAnimMgrTick) diff --git a/src/desktop/LayerSurface.cpp b/src/desktop/LayerSurface.cpp index 8d13bf19..331dba9c 100644 --- a/src/desktop/LayerSurface.cpp +++ b/src/desktop/LayerSurface.cpp @@ -72,7 +72,7 @@ CLayerSurface::~CLayerSurface() { g_pHyprRenderer->makeEGLCurrent(); std::erase_if(g_pHyprOpenGL->m_mLayerFramebuffers, [&](const auto& other) { return other.first.expired() || other.first.lock() == self.lock(); }); - for (auto& mon : g_pCompositor->m_vRealMonitors) { + for (auto const& mon : g_pCompositor->m_vRealMonitors) { for (auto& lsl : mon->m_aLayerSurfaceLayers) { std::erase_if(lsl, [this](auto& ls) { return ls.expired() || ls.get() == this; }); } diff --git a/src/desktop/Window.cpp b/src/desktop/Window.cpp index dcdcb573..64337097 100644 --- a/src/desktop/Window.cpp +++ b/src/desktop/Window.cpp @@ -252,7 +252,7 @@ void CWindow::updateWindowDecos() { if (!m_bIsMapped || isHidden()) return; - for (auto& wd : m_vDecosToRemove) { + for (auto const& wd : m_vDecosToRemove) { for (auto it = m_dWindowDecorations.begin(); it != m_dWindowDecorations.end(); it++) { if (it->get() == wd) { g_pDecorationPositioner->uncacheDecoration(it->get()); @@ -270,11 +270,11 @@ void CWindow::updateWindowDecos() { // make a copy because updateWindow can remove decos. std::vector decos; - for (auto& wd : m_dWindowDecorations) { + for (auto const& wd : m_dWindowDecorations) { decos.push_back(wd.get()); } - for (auto& wd : decos) { + for (auto const& wd : decos) { if (std::find_if(m_dWindowDecorations.begin(), m_dWindowDecorations.end(), [wd](const auto& other) { return other.get() == wd; }) == m_dWindowDecorations.end()) continue; wd->updateWindow(m_pSelf.lock()); @@ -454,7 +454,7 @@ PHLWINDOW CWindow::X11TransientFor() { s = s->parent; } - for (auto& w : g_pCompositor->m_vWindows) { + for (auto const& w : g_pCompositor->m_vWindows) { if (w->m_pXWaylandSurface != s) continue; return w; @@ -464,7 +464,7 @@ PHLWINDOW CWindow::X11TransientFor() { } void CWindow::removeDecorationByType(eDecorationType type) { - for (auto& wd : m_dWindowDecorations) { + for (auto const& wd : m_dWindowDecorations) { if (wd->getDecorationType() == type) m_vDecosToRemove.push_back(wd.get()); } @@ -617,7 +617,7 @@ void CWindow::applyDynamicRule(const SWindowRule& r) { int opacityIDX = 0; - for (auto& r : vars) { + for (auto const& r : vars) { if (r == "opacity") continue; @@ -770,7 +770,7 @@ void CWindow::updateDynamicRules() { m_tags.removeDynamicTags(); m_vMatchedRules = g_pConfigManager->getMatchingRules(m_pSelf.lock()); - for (auto& r : m_vMatchedRules) { + for (auto const& r : m_vMatchedRules) { applyDynamicRule(r); } @@ -881,7 +881,7 @@ void CWindow::destroyGroup() { addresses += std::format("{:x},", (uintptr_t)curr.get()); } while (curr.get() != this); - for (auto& w : members) { + for (auto const& w : members) { if (w->m_sGroupData.head) g_pLayoutManager->getCurrentLayout()->onWindowRemoved(curr); w->m_sGroupData.head = false; diff --git a/src/helpers/Monitor.cpp b/src/helpers/Monitor.cpp index 2c6282e1..8b533d8a 100644 --- a/src/helpers/Monitor.cpp +++ b/src/helpers/Monitor.cpp @@ -207,7 +207,7 @@ void CMonitor::onConnect(bool noRule) { // verify last mon valid bool found = false; - for (auto& m : g_pCompositor->m_vMonitors) { + for (auto const& m : g_pCompositor->m_vMonitors) { if (m == g_pCompositor->m_pLastMonitor) { found = true; break; @@ -272,7 +272,7 @@ void CMonitor::onDisconnect(bool destroy) { listeners.commit.reset(); for (size_t i = 0; i < 4; ++i) { - for (auto& ls : m_aLayerSurfaceLayers[i]) { + for (auto const& ls : m_aLayerSurfaceLayers[i]) { if (ls->layerSurface && !ls->fadingOut) ls->layerSurface->sendClosed(); } diff --git a/src/layout/DwindleLayout.cpp b/src/layout/DwindleLayout.cpp index 20085ff7..db69cc04 100644 --- a/src/layout/DwindleLayout.cpp +++ b/src/layout/DwindleLayout.cpp @@ -49,7 +49,7 @@ void SDwindleNodeData::getAllChildrenRecursive(std::deque* pD int CHyprDwindleLayout::getNodesOnWorkspace(const WORKSPACEID& id) { int no = 0; - for (auto& n : m_lDwindleNodesData) { + for (auto const& n : m_lDwindleNodesData) { if (n.workspaceID == id && n.valid) ++no; } diff --git a/src/layout/IHyprLayout.cpp b/src/layout/IHyprLayout.cpp index 233933d4..9b3d02b4 100644 --- a/src/layout/IHyprLayout.cpp +++ b/src/layout/IHyprLayout.cpp @@ -691,7 +691,7 @@ Vector2D IHyprLayout::predictSizeForNewWindow(PHLWINDOW pWindow) { bool shouldBeFloated = g_pXWaylandManager->shouldBeFloated(pWindow, true); if (!shouldBeFloated) { - for (auto& r : g_pConfigManager->getMatchingRules(pWindow, true, true)) { + for (auto const& r : g_pConfigManager->getMatchingRules(pWindow, true, true)) { if (r.szRule.starts_with("float")) { shouldBeFloated = true; break; diff --git a/src/layout/MasterLayout.cpp b/src/layout/MasterLayout.cpp index e0b48e98..d234d300 100644 --- a/src/layout/MasterLayout.cpp +++ b/src/layout/MasterLayout.cpp @@ -16,7 +16,7 @@ SMasterNodeData* CHyprMasterLayout::getNodeFromWindow(PHLWINDOW pWindow) { int CHyprMasterLayout::getNodesOnWorkspace(const WORKSPACEID& ws) { int no = 0; - for (auto& n : m_lMasterNodesData) { + for (auto const& n : m_lMasterNodesData) { if (n.workspaceID == ws) no++; } @@ -26,7 +26,7 @@ int CHyprMasterLayout::getNodesOnWorkspace(const WORKSPACEID& ws) { int CHyprMasterLayout::getMastersOnWorkspace(const WORKSPACEID& ws) { int no = 0; - for (auto& n : m_lMasterNodesData) { + for (auto const& n : m_lMasterNodesData) { if (n.workspaceID == ws && n.isMaster) no++; } @@ -381,7 +381,7 @@ void CHyprMasterLayout::calculateWorkspace(PHLWORKSPACE pWorkspace) { if (*PSMARTRESIZING) { // check the total width and height so that later // if larger/smaller than screen size them down/up - for (auto& nd : m_lMasterNodesData) { + for (auto const& nd : m_lMasterNodesData) { if (nd.workspaceID == pWorkspace->m_iID) { if (nd.isMaster) masterAccumulatedSize += totalSize / MASTERS * nd.percSize; @@ -552,7 +552,7 @@ void CHyprMasterLayout::calculateWorkspace(PHLWORKSPACE pWorkspace) { float slaveAccumulatedHeightL = 0; float slaveAccumulatedHeightR = 0; if (*PSMARTRESIZING) { - for (auto& nd : m_lMasterNodesData) { + for (auto const& nd : m_lMasterNodesData) { if (nd.workspaceID != pWorkspace->m_iID || nd.isMaster) continue; diff --git a/src/managers/AnimationManager.cpp b/src/managers/AnimationManager.cpp index beb880be..e2e98735 100644 --- a/src/managers/AnimationManager.cpp +++ b/src/managers/AnimationManager.cpp @@ -131,7 +131,7 @@ void CAnimationManager::tick() { } // damage any workspace window that is on any monitor - for (auto& w : g_pCompositor->m_vWindows) { + for (auto const& w : g_pCompositor->m_vWindows) { if (!validMapped(w) || w->m_pWorkspace != PWORKSPACE || w->m_bPinned) continue; diff --git a/src/managers/KeybindManager.cpp b/src/managers/KeybindManager.cpp index 8bf7152e..7eb96730 100644 --- a/src/managers/KeybindManager.cpp +++ b/src/managers/KeybindManager.cpp @@ -765,7 +765,7 @@ void CKeybindManager::shadowKeybinds(const xkb_keysym_t& doesntHave, const uint3 const auto KBKEY = xkb_keysym_from_name(k.key.c_str(), XKB_KEYSYM_CASE_INSENSITIVE); const auto KBKEYUPPER = xkb_keysym_to_upper(KBKEY); - for (auto& pk : m_dPressedKeys) { + for (auto const& pk : m_dPressedKeys) { if ((pk.keysym != 0 && (pk.keysym == KBKEY || pk.keysym == KBKEYUPPER))) { shadow = true; @@ -864,7 +864,7 @@ SDispatchResult CKeybindManager::spawn(std::string args) { if (!RULES.empty()) { const auto RULESLIST = CVarList(RULES, 0, ';'); - for (auto& r : RULESLIST) { + for (auto const& r : RULESLIST) { g_pConfigManager->addExecRule({r, (unsigned long)PROC}); } @@ -1708,7 +1708,7 @@ SDispatchResult CKeybindManager::workspaceOpt(std::string args) { PWORKSPACE->m_bDefaultPseudo = !PWORKSPACE->m_bDefaultPseudo; // apply - for (auto& w : g_pCompositor->m_vWindows) { + for (auto const& w : g_pCompositor->m_vWindows) { if (!w->m_bIsMapped || w->m_pWorkspace != PWORKSPACE) continue; @@ -2129,7 +2129,7 @@ SDispatchResult CKeybindManager::setSubmap(std::string submap) { return {}; } - for (auto& k : g_pKeybindManager->m_lKeybinds) { + for (auto const& k : g_pKeybindManager->m_lKeybinds) { if (k.submap == submap) { m_szCurrentSelectedSubmap = submap; Debug::log(LOG, "Changed keybind submap to {}", submap); diff --git a/src/managers/PointerManager.cpp b/src/managers/PointerManager.cpp index 72ff5ae7..80f1ab4f 100644 --- a/src/managers/PointerManager.cpp +++ b/src/managers/PointerManager.cpp @@ -90,7 +90,7 @@ void CPointerManager::unlockSoftwareAll() { } void CPointerManager::lockSoftwareForMonitor(CMonitor* Monitor) { - for (auto& m : g_pCompositor->m_vMonitors) { + for (auto const& m : g_pCompositor->m_vMonitors) { if (m->ID == Monitor->ID) { lockSoftwareForMonitor(m); return; @@ -107,7 +107,7 @@ void CPointerManager::lockSoftwareForMonitor(SP mon) { } void CPointerManager::unlockSoftwareForMonitor(CMonitor* Monitor) { - for (auto& m : g_pCompositor->m_vMonitors) { + for (auto const& m : g_pCompositor->m_vMonitors) { if (m->ID == Monitor->ID) { unlockSoftwareForMonitor(m); return; @@ -225,7 +225,7 @@ void CPointerManager::recheckEnteredOutputs() { auto box = getCursorBoxGlobal(); - for (auto& s : monitorStates) { + for (auto const& s : monitorStates) { if (s->monitor.expired() || s->monitor->isMirror() || !s->monitor->m_bEnabled) continue; @@ -279,7 +279,7 @@ void CPointerManager::resetCursorImage(bool apply) { currentCursorImage.scale = 1.F; currentCursorImage.hotspot = {0, 0}; - for (auto& s : monitorStates) { + for (auto const& s : monitorStates) { if (s->monitor.expired() || s->monitor->isMirror() || !s->monitor->m_bEnabled) continue; @@ -289,7 +289,7 @@ void CPointerManager::resetCursorImage(bool apply) { if (!apply) return; - for (auto& ms : monitorStates) { + for (auto const& ms : monitorStates) { if (!ms->monitor || !ms->monitor->m_bEnabled || !ms->monitor->dpmsStatus) { Debug::log(TRACE, "Not updating hw cursors: disabled / dpms off display"); continue; @@ -334,7 +334,7 @@ void CPointerManager::onCursorMoved() { if (!hasCursor()) return; - for (auto& m : g_pCompositor->m_vMonitors) { + for (auto const& m : g_pCompositor->m_vMonitors) { auto state = stateFor(m); state->box = getCursorBoxLogicalForMonitor(state->monitor.lock()); @@ -1006,7 +1006,7 @@ void CPointerManager::detachTablet(SP tablet) { } void CPointerManager::damageCursor(SP pMonitor) { - for (auto& mw : monitorStates) { + for (auto const& mw : monitorStates) { if (mw->monitor != pMonitor) continue; diff --git a/src/managers/SeatManager.cpp b/src/managers/SeatManager.cpp index 801ae55a..e296dcc8 100644 --- a/src/managers/SeatManager.cpp +++ b/src/managers/SeatManager.cpp @@ -24,7 +24,7 @@ void CSeatManager::onNewSeatResource(SP resource) { } SP CSeatManager::containerForResource(SP seatResource) { - for (auto& c : seatResources) { + for (auto const& c : seatResources) { if (c->resource == seatResource) return c; } @@ -112,11 +112,11 @@ void CSeatManager::setKeyboardFocus(SP surf) { if (state.keyboardFocusResource) { auto client = state.keyboardFocusResource->client(); - for (auto& s : seatResources) { + for (auto const& s : seatResources) { if (s->resource->client() != client) continue; - for (auto& k : s->resource->keyboards) { + for (auto const& k : s->resource->keyboards) { if (!k) continue; @@ -134,12 +134,12 @@ void CSeatManager::setKeyboardFocus(SP surf) { } auto client = surf->client(); - for (auto& r : seatResources | std::views::reverse) { + for (auto const& r : seatResources | std::views::reverse) { if (r->resource->client() != client) continue; state.keyboardFocusResource = r->resource; - for (auto& k : r->resource->keyboards) { + for (auto const& k : r->resource->keyboards) { if (!k) continue; @@ -157,11 +157,11 @@ void CSeatManager::sendKeyboardKey(uint32_t timeMs, uint32_t key, wl_keyboard_ke if (!state.keyboardFocusResource) return; - for (auto& s : seatResources) { + for (auto const& s : seatResources) { if (s->resource->client() != state.keyboardFocusResource->client()) continue; - for (auto& k : s->resource->keyboards) { + for (auto const& k : s->resource->keyboards) { if (!k) continue; @@ -174,11 +174,11 @@ void CSeatManager::sendKeyboardMods(uint32_t depressed, uint32_t latched, uint32 if (!state.keyboardFocusResource) return; - for (auto& s : seatResources) { + for (auto const& s : seatResources) { if (s->resource->client() != state.keyboardFocusResource->client()) continue; - for (auto& k : s->resource->keyboards) { + for (auto const& k : s->resource->keyboards) { if (!k) continue; @@ -205,11 +205,11 @@ void CSeatManager::setPointerFocus(SP surf, const Vector2D& if (state.pointerFocusResource) { auto client = state.pointerFocusResource->client(); - for (auto& s : seatResources) { + for (auto const& s : seatResources) { if (s->resource->client() != client) continue; - for (auto& p : s->resource->pointers) { + for (auto const& p : s->resource->pointers) { if (!p) continue; @@ -230,12 +230,12 @@ void CSeatManager::setPointerFocus(SP surf, const Vector2D& } auto client = surf->client(); - for (auto& r : seatResources | std::views::reverse) { + for (auto const& r : seatResources | std::views::reverse) { if (r->resource->client() != client) continue; state.pointerFocusResource = r->resource; - for (auto& p : r->resource->pointers) { + for (auto const& p : r->resource->pointers) { if (!p) continue; @@ -257,11 +257,11 @@ void CSeatManager::sendPointerMotion(uint32_t timeMs, const Vector2D& local) { if (!state.pointerFocusResource) return; - for (auto& s : seatResources) { + for (auto const& s : seatResources) { if (s->resource->client() != state.pointerFocusResource->client()) continue; - for (auto& p : s->resource->pointers) { + for (auto const& p : s->resource->pointers) { if (!p) continue; @@ -276,11 +276,11 @@ void CSeatManager::sendPointerButton(uint32_t timeMs, uint32_t key, wl_pointer_b if (!state.pointerFocusResource) return; - for (auto& s : seatResources) { + for (auto const& s : seatResources) { if (s->resource->client() != state.pointerFocusResource->client()) continue; - for (auto& p : s->resource->pointers) { + for (auto const& p : s->resource->pointers) { if (!p) continue; @@ -300,11 +300,11 @@ void CSeatManager::sendPointerFrame(WP pResource) { if (!pResource) return; - for (auto& s : seatResources) { + for (auto const& s : seatResources) { if (s->resource->client() != pResource->client()) continue; - for (auto& p : s->resource->pointers) { + for (auto const& p : s->resource->pointers) { if (!p) continue; @@ -318,11 +318,11 @@ void CSeatManager::sendPointerAxis(uint32_t timeMs, wl_pointer_axis axis, double if (!state.pointerFocusResource) return; - for (auto& s : seatResources) { + for (auto const& s : seatResources) { if (s->resource->client() != state.pointerFocusResource->client()) continue; - for (auto& p : s->resource->pointers) { + for (auto const& p : s->resource->pointers) { if (!p) continue; @@ -346,12 +346,12 @@ void CSeatManager::sendTouchDown(SP surf, uint32_t timeMs, i state.touchFocus = surf; auto client = surf->client(); - for (auto& r : seatResources | std::views::reverse) { + for (auto const& r : seatResources | std::views::reverse) { if (r->resource->client() != client) continue; state.touchFocusResource = r->resource; - for (auto& t : r->resource->touches) { + for (auto const& t : r->resource->touches) { if (!t) continue; @@ -372,12 +372,12 @@ void CSeatManager::sendTouchUp(uint32_t timeMs, int32_t id) { return; auto client = state.touchFocusResource->client(); - for (auto& r : seatResources | std::views::reverse) { + for (auto const& r : seatResources | std::views::reverse) { if (r->resource->client() != client) continue; state.touchFocusResource = r->resource; - for (auto& t : r->resource->touches) { + for (auto const& t : r->resource->touches) { if (!t) continue; @@ -395,11 +395,11 @@ void CSeatManager::sendTouchMotion(uint32_t timeMs, int32_t id, const Vector2D& if (!state.touchFocusResource) return; - for (auto& s : seatResources) { + for (auto const& s : seatResources) { if (s->resource->client() != state.touchFocusResource->client()) continue; - for (auto& t : s->resource->touches) { + for (auto const& t : s->resource->touches) { if (!t) continue; @@ -412,11 +412,11 @@ void CSeatManager::sendTouchFrame() { if (!state.touchFocusResource) return; - for (auto& s : seatResources) { + for (auto const& s : seatResources) { if (s->resource->client() != state.touchFocusResource->client()) continue; - for (auto& t : s->resource->touches) { + for (auto const& t : s->resource->touches) { if (!t) continue; @@ -429,11 +429,11 @@ void CSeatManager::sendTouchCancel() { if (!state.touchFocusResource) return; - for (auto& s : seatResources) { + for (auto const& s : seatResources) { if (s->resource->client() != state.touchFocusResource->client()) continue; - for (auto& t : s->resource->touches) { + for (auto const& t : s->resource->touches) { if (!t) continue; @@ -446,11 +446,11 @@ void CSeatManager::sendTouchShape(int32_t id, const Vector2D& shape) { if (!state.touchFocusResource) return; - for (auto& s : seatResources) { + for (auto const& s : seatResources) { if (s->resource->client() != state.touchFocusResource->client()) continue; - for (auto& t : s->resource->touches) { + for (auto const& t : s->resource->touches) { if (!t) continue; @@ -463,11 +463,11 @@ void CSeatManager::sendTouchOrientation(int32_t id, double angle) { if (!state.touchFocusResource) return; - for (auto& s : seatResources) { + for (auto const& s : seatResources) { if (s->resource->client() != state.touchFocusResource->client()) continue; - for (auto& t : s->resource->touches) { + for (auto const& t : s->resource->touches) { if (!t) continue; diff --git a/src/managers/SessionLockManager.cpp b/src/managers/SessionLockManager.cpp index a82432a8..86108cac 100644 --- a/src/managers/SessionLockManager.cpp +++ b/src/managers/SessionLockManager.cpp @@ -137,7 +137,7 @@ bool CSessionLockManager::isSurfaceSessionLock(SP pSurface) if (!m_pSessionLock) return false; - for (auto& sls : m_pSessionLock->vSessionLockSurfaces) { + for (auto const& sls : m_pSessionLock->vSessionLockSurfaces) { if (sls->surface->surface() == pSurface) return true; } @@ -154,7 +154,7 @@ void CSessionLockManager::removeSessionLockSurface(SSessionLockSurface* pSLS) { if (g_pCompositor->m_pLastFocus) return; - for (auto& sls : m_pSessionLock->vSessionLockSurfaces) { + for (auto const& sls : m_pSessionLock->vSessionLockSurfaces) { if (!sls->mapped) continue; diff --git a/src/managers/XWaylandManager.cpp b/src/managers/XWaylandManager.cpp index a6fd97f5..4654eeb7 100644 --- a/src/managers/XWaylandManager.cpp +++ b/src/managers/XWaylandManager.cpp @@ -147,7 +147,7 @@ void CHyprXWaylandManager::setWindowSize(PHLWINDOW pWindow, Vector2D size, bool bool CHyprXWaylandManager::shouldBeFloated(PHLWINDOW pWindow, bool pending) { if (pWindow->m_bIsX11) { - for (auto& a : pWindow->m_pXWaylandSurface->atoms) + for (auto const& a : pWindow->m_pXWaylandSurface->atoms) if (a == HYPRATOMS["_NET_WM_WINDOW_TYPE_DIALOG"] || a == HYPRATOMS["_NET_WM_WINDOW_TYPE_SPLASH"] || a == HYPRATOMS["_NET_WM_WINDOW_TYPE_TOOLBAR"] || a == HYPRATOMS["_NET_WM_WINDOW_TYPE_UTILITY"] || a == HYPRATOMS["_NET_WM_WINDOW_TYPE_TOOLTIP"] || a == HYPRATOMS["_NET_WM_WINDOW_TYPE_POPUP_MENU"] || a == HYPRATOMS["_NET_WM_WINDOW_TYPE_DOCK"] || a == HYPRATOMS["_NET_WM_WINDOW_TYPE_DROPDOWN_MENU"] || a == HYPRATOMS["_NET_WM_WINDOW_TYPE_MENU"] || @@ -193,7 +193,7 @@ void CHyprXWaylandManager::checkBorders(PHLWINDOW pWindow) { if (!pWindow->m_bIsX11) return; - for (auto& a : pWindow->m_pXWaylandSurface->atoms) { + for (auto const& a : pWindow->m_pXWaylandSurface->atoms) { if (a == HYPRATOMS["_NET_WM_WINDOW_TYPE_POPUP_MENU"] || a == HYPRATOMS["_NET_WM_WINDOW_TYPE_NOTIFICATION"] || a == HYPRATOMS["_NET_WM_WINDOW_TYPE_DROPDOWN_MENU"] || a == HYPRATOMS["_NET_WM_WINDOW_TYPE_COMBO"] || a == HYPRATOMS["_NET_WM_WINDOW_TYPE_MENU"] || a == HYPRATOMS["_NET_WM_WINDOW_TYPE_SPLASH"] || a == HYPRATOMS["_NET_WM_WINDOW_TYPE_TOOLTIP"]) { diff --git a/src/managers/input/IdleInhibitor.cpp b/src/managers/input/IdleInhibitor.cpp index 2c335a7e..4bcb4df3 100644 --- a/src/managers/input/IdleInhibitor.cpp +++ b/src/managers/input/IdleInhibitor.cpp @@ -31,7 +31,7 @@ void CInputManager::newIdleInhibitor(std::any inhibitor) { void CInputManager::recheckIdleInhibitorStatus() { - for (auto& ii : m_vIdleInhibitors) { + for (auto const& ii : m_vIdleInhibitors) { if (ii->nonDesktop) { PROTO::idle->setInhibit(true); return; diff --git a/src/managers/input/InputManager.cpp b/src/managers/input/InputManager.cpp index e5f921a2..a4a63a84 100644 --- a/src/managers/input/InputManager.cpp +++ b/src/managers/input/InputManager.cpp @@ -919,7 +919,7 @@ void CInputManager::setupKeyboard(SP keeb) { } void CInputManager::setKeyboardLayout() { - for (auto& k : m_vKeyboards) + for (auto const& k : m_vKeyboards) applyConfigToKeyboard(k); g_pKeybindManager->updateXKBTranslationState(); @@ -1197,7 +1197,7 @@ void CInputManager::destroyKeyboard(SP pKeyboard) { if (m_vKeyboards.size() > 0) { bool found = false; - for (auto& k : m_vKeyboards | std::views::reverse) { + for (auto const& k : m_vKeyboards | std::views::reverse) { if (!k) continue; @@ -1673,7 +1673,7 @@ void CInputManager::releaseAllMouseButtons() { if (PROTO::data->dndActive()) return; - for (auto& mb : buttonsCopy) { + for (auto const& mb : buttonsCopy) { g_pSeatManager->sendPointerButton(0, mb, WL_POINTER_BUTTON_STATE_RELEASED); } diff --git a/src/managers/input/Swipe.cpp b/src/managers/input/Swipe.cpp index 6ee690cd..aa1d3274 100644 --- a/src/managers/input/Swipe.cpp +++ b/src/managers/input/Swipe.cpp @@ -14,7 +14,7 @@ void CInputManager::onSwipeBegin(IPointer::SSwipeBeginEvent e) { return; int onMonitor = 0; - for (auto& w : g_pCompositor->m_vWorkspaces) { + for (auto const& w : g_pCompositor->m_vWorkspaces) { if (w->m_iMonitorID == g_pCompositor->m_pLastMonitor->ID && !g_pCompositor->isWorkspaceSpecial(w->m_iID)) { onMonitor++; } @@ -38,7 +38,7 @@ void CInputManager::beginWorkspaceSwipe() { m_sActiveSwipe.speedPoints = 0; if (PWORKSPACE->m_bHasFullscreenWindow) { - for (auto& ls : g_pCompositor->m_pLastMonitor->m_aLayerSurfaceLayers[2]) { + for (auto const& ls : g_pCompositor->m_pLastMonitor->m_aLayerSurfaceLayers[2]) { ls->alpha = 1.f; } } @@ -193,7 +193,7 @@ void CInputManager::endWorkspaceSwipe() { g_pInputManager->refocus(); // apply alpha - for (auto& ls : g_pCompositor->m_pLastMonitor->m_aLayerSurfaceLayers[2]) { + for (auto const& ls : g_pCompositor->m_pLastMonitor->m_aLayerSurfaceLayers[2]) { ls->alpha = pSwitchedTo->m_bHasFullscreenWindow && pSwitchedTo->m_efFullscreenMode == FSMODE_FULLSCREEN ? 0.f : 1.f; } } diff --git a/src/managers/input/Tablets.cpp b/src/managers/input/Tablets.cpp index 5e50e851..23d328bc 100644 --- a/src/managers/input/Tablets.cpp +++ b/src/managers/input/Tablets.cpp @@ -14,7 +14,7 @@ static void unfocusTool(SP tool) { tool->setSurface(nullptr); if (tool->isDown) PROTO::tablet->up(tool); - for (auto& b : tool->buttonsDown) { + for (auto const& b : tool->buttonsDown) { PROTO::tablet->buttonTool(tool, b, false); } PROTO::tablet->proximityOut(tool); @@ -31,7 +31,7 @@ static void focusTool(SP tool, SP tablet, SPproximityIn(tool, tablet, surf); if (tool->isDown) PROTO::tablet->down(tool); - for (auto& b : tool->buttonsDown) { + for (auto const& b : tool->buttonsDown) { PROTO::tablet->buttonTool(tool, b, true); } } diff --git a/src/plugins/HookSystem.cpp b/src/plugins/HookSystem.cpp index 9118456b..745b2593 100644 --- a/src/plugins/HookSystem.cpp +++ b/src/plugins/HookSystem.cpp @@ -81,7 +81,7 @@ CFunctionHook::SAssembly CFunctionHook::fixInstructionProbeRIPCalls(const SInstr std::vector finalBytes; finalBytes.resize(probe.len); - for (auto& len : probe.insSizes) { + for (auto const& len : probe.insSizes) { // copy original bytes to our finalBytes for (size_t i = 0; i < len; ++i) { diff --git a/src/protocols/DRMLease.cpp b/src/protocols/DRMLease.cpp index bc0945f1..f906740c 100644 --- a/src/protocols/DRMLease.cpp +++ b/src/protocols/DRMLease.cpp @@ -50,12 +50,12 @@ CDRMLeaseResource::CDRMLeaseResource(SP resource_, SPmonitor->isBeingLeased = true; } listeners.destroyLease = lease->events.destroy.registerListener([this](std::any d) { - for (auto& m : requested) { + for (auto const& m : requested) { if (m && m->monitor) m->monitor->isBeingLeased = false; } diff --git a/src/protocols/DataDeviceWlr.cpp b/src/protocols/DataDeviceWlr.cpp index ad6ee89a..dce64508 100644 --- a/src/protocols/DataDeviceWlr.cpp +++ b/src/protocols/DataDeviceWlr.cpp @@ -291,7 +291,7 @@ void CDataDeviceWLRProtocol::sendSelectionToDevice(SP dev, SP source, bool primary) { - for (auto& o : m_vOffers) { + for (auto const& o : m_vOffers) { if (o->source && o->source->hasDnd()) continue; if (o->primary != primary) @@ -302,7 +302,7 @@ void CDataDeviceWLRProtocol::setSelection(SP source, bool primary) if (!source) { LOGM(LOG, "resetting {}selection", primary ? "primary " : " "); - for (auto& d : m_vDevices) { + for (auto const& d : m_vDevices) { sendSelectionToDevice(d, nullptr, primary); } @@ -311,7 +311,7 @@ void CDataDeviceWLRProtocol::setSelection(SP source, bool primary) LOGM(LOG, "New {}selection for data source {:x}", primary ? "primary" : "", (uintptr_t)source.get()); - for (auto& d : m_vDevices) { + for (auto const& d : m_vDevices) { sendSelectionToDevice(d, source, primary); } } diff --git a/src/protocols/core/Compositor.cpp b/src/protocols/core/Compositor.cpp index 8b6f46b1..75f1e646 100644 --- a/src/protocols/core/Compositor.cpp +++ b/src/protocols/core/Compositor.cpp @@ -260,7 +260,7 @@ void CWLSurfaceResource::bfHelper(std::vector> nodes, std for (auto& n : nodes) { std::erase_if(n->subsurfaces, [](const auto& e) { return e.expired(); }); // subsurfaces is sorted lowest -> highest - for (auto& c : n->subsurfaces) { + for (auto const& c : n->subsurfaces) { if (c->zIndex >= 0) break; if (c->surface.expired()) @@ -274,7 +274,7 @@ void CWLSurfaceResource::bfHelper(std::vector> nodes, std nodes2.clear(); - for (auto& n : nodes) { + for (auto const& n : nodes) { Vector2D offset = {}; if (n->role->role() == SURFACE_ROLE_SUBSURFACE) { auto subsurface = ((CSubsurfaceRole*)n->role.get())->subsurface.lock(); @@ -284,8 +284,8 @@ void CWLSurfaceResource::bfHelper(std::vector> nodes, std fn(n, offset, data); } - for (auto& n : nodes) { - for (auto& c : n->subsurfaces) { + for (auto const& n : nodes) { + for (auto const& c : n->subsurfaces) { if (c->zIndex < 0) continue; if (c->surface.expired()) diff --git a/src/protocols/core/DataDevice.cpp b/src/protocols/core/DataDevice.cpp index 4ed28f24..943c790f 100644 --- a/src/protocols/core/DataDevice.cpp +++ b/src/protocols/core/DataDevice.cpp @@ -306,7 +306,7 @@ CWLDataDeviceManagerResource::CWLDataDeviceManagerResource(SPself = RESOURCE; - for (auto& s : sources) { + for (auto const& s : sources) { if (!s) continue; s->device = RESOURCE; @@ -390,7 +390,7 @@ void CWLDataDeviceProtocol::onDestroyDataSource(WP source } void CWLDataDeviceProtocol::setSelection(SP source) { - for (auto& o : m_vOffers) { + for (auto const& o : m_vOffers) { if (o->source && o->source->hasDnd()) continue; o->dead = true; @@ -439,7 +439,7 @@ void CWLDataDeviceProtocol::updateSelection() { } void CWLDataDeviceProtocol::onKeyboardFocus() { - for (auto& o : m_vOffers) { + for (auto const& o : m_vOffers) { o->dead = true; } @@ -606,7 +606,7 @@ bool CWLDataDeviceProtocol::wasDragSuccessful() { if (!dnd.focusedDevice || !dnd.currentSource) return false; - for (auto& o : m_vOffers) { + for (auto const& o : m_vOffers) { if (o->dead || !o->source || !o->source->hasDnd()) continue; diff --git a/src/protocols/core/Output.cpp b/src/protocols/core/Output.cpp index 8d0b0121..bcf62fae 100644 --- a/src/protocols/core/Output.cpp +++ b/src/protocols/core/Output.cpp @@ -118,7 +118,7 @@ bool CWLOutputProtocol::isDefunct() { } void CWLOutputProtocol::sendDone() { - for (auto& r : m_vOutputs) { + for (auto const& r : m_vOutputs) { r->resource->sendDone(); } } diff --git a/src/protocols/core/Seat.cpp b/src/protocols/core/Seat.cpp index a111c12c..f7764389 100644 --- a/src/protocols/core/Seat.cpp +++ b/src/protocols/core/Seat.cpp @@ -172,7 +172,7 @@ void CWLPointerResource::sendLeave() { if (!PROTO::data->dndActive()) { timespec now; clock_gettime(CLOCK_MONOTONIC, &now); - for (auto& b : pressedButtons) { + for (auto const& b : pressedButtons) { sendButton(now.tv_sec * 1000 + now.tv_nsec / 1000000, b, WL_POINTER_BUTTON_STATE_RELEASED); } } diff --git a/src/render/OpenGL.cpp b/src/render/OpenGL.cpp index 63cc2203..2aeda8be 100644 --- a/src/render/OpenGL.cpp +++ b/src/render/OpenGL.cpp @@ -690,7 +690,7 @@ bool CHyprOpenGLImpl::passRequiresIntrospection(CMonitor* pMonitor) { } if (*PBLURSPECIAL) { - for (auto& ws : g_pCompositor->m_vWorkspaces) { + for (auto const& ws : g_pCompositor->m_vWorkspaces) { if (!ws->m_bIsSpecialWorkspace || ws->m_iMonitorID != pMonitor->ID) continue; @@ -1936,9 +1936,9 @@ void CHyprOpenGLImpl::preRender(CMonitor* pMonitor) { } } - for (auto& m : g_pCompositor->m_vMonitors) { - for (auto& lsl : m->m_aLayerSurfaceLayers) { - for (auto& ls : lsl) { + for (auto const& m : g_pCompositor->m_vMonitors) { + for (auto const& lsl : m->m_aLayerSurfaceLayers) { + for (auto const& ls : lsl) { if (!ls->layerSurface || ls->xray != 1) continue; diff --git a/src/render/Renderer.cpp b/src/render/Renderer.cpp index c2ecbbf3..2ef7e208 100644 --- a/src/render/Renderer.cpp +++ b/src/render/Renderer.cpp @@ -331,7 +331,7 @@ bool CHyprRenderer::shouldRenderWindow(PHLWINDOW pWindow) { if (g_pCompositor->isWorkspaceVisible(pWindow->m_pWorkspace)) return true; - for (auto& m : g_pCompositor->m_vMonitors) { + for (auto const& m : g_pCompositor->m_vMonitors) { if (PWORKSPACE && PWORKSPACE->m_iMonitorID == m->ID && (PWORKSPACE->m_vRenderOffset.isBeingAnimated() || PWORKSPACE->m_fAlpha.isBeingAnimated())) return true; @@ -915,7 +915,7 @@ void CHyprRenderer::renderAllClientsForWorkspace(CMonitor* pMonitor, PHLWORKSPAC g_pHyprOpenGL->m_RenderData.damage = preOccludedDamage; // and then special - for (auto& ws : g_pCompositor->m_vWorkspaces) { + for (auto const& ws : g_pCompositor->m_vWorkspaces) { if (ws->m_iMonitorID == pMonitor->ID && ws->m_fAlpha.value() > 0.f && ws->m_bIsSpecialWorkspace) { const auto SPECIALANIMPROGRS = ws->m_vRenderOffset.isBeingAnimated() ? ws->m_vRenderOffset.getCurveValue() : ws->m_fAlpha.getCurveValue(); const bool ANIMOUT = !pMonitor->activeSpecialWorkspace; @@ -935,7 +935,7 @@ void CHyprRenderer::renderAllClientsForWorkspace(CMonitor* pMonitor, PHLWORKSPAC } // special - for (auto& ws : g_pCompositor->m_vWorkspaces) { + for (auto const& ws : g_pCompositor->m_vWorkspaces) { if (ws->m_fAlpha.value() > 0.f && ws->m_bIsSpecialWorkspace) { if (ws->m_bHasFullscreenWindow) renderWorkspaceWindowsFullscreen(pMonitor, ws, time); @@ -1489,7 +1489,7 @@ void CHyprRenderer::renderWorkspace(CMonitor* pMonitor, PHLWORKSPACE pWorkspace, } void CHyprRenderer::sendFrameEventsToWorkspace(CMonitor* pMonitor, PHLWORKSPACE pWorkspace, timespec* now) { - for (auto& w : g_pCompositor->m_vWindows) { + for (auto const& w : g_pCompositor->m_vWindows) { if (w->isHidden() || !w->m_bIsMapped || w->m_bFadingOut || !w->m_pWLSurface->resource()) continue; @@ -1499,8 +1499,8 @@ void CHyprRenderer::sendFrameEventsToWorkspace(CMonitor* pMonitor, PHLWORKSPACE w->m_pWLSurface->resource()->breadthfirst([now](SP r, const Vector2D& offset, void* d) { r->frame(now); }, nullptr); } - for (auto& lsl : pMonitor->m_aLayerSurfaceLayers) { - for (auto& ls : lsl) { + for (auto const& lsl : pMonitor->m_aLayerSurfaceLayers) { + for (auto const& ls : lsl) { if (ls->fadingOut || !ls->surface->resource()) continue; @@ -1673,10 +1673,10 @@ void CHyprRenderer::arrangeLayersForMonitor(const MONITORID& monitor) { CBox usableArea = {PMONITOR->vecPosition.x, PMONITOR->vecPosition.y, PMONITOR->vecSize.x, PMONITOR->vecSize.y}; - for (auto& la : PMONITOR->m_aLayerSurfaceLayers) + for (auto const& la : PMONITOR->m_aLayerSurfaceLayers) arrangeLayerArray(PMONITOR, la, true, &usableArea); - for (auto& la : PMONITOR->m_aLayerSurfaceLayers) + for (auto const& la : PMONITOR->m_aLayerSurfaceLayers) arrangeLayerArray(PMONITOR, la, false, &usableArea); PMONITOR->vecReservedTopLeft = Vector2D(usableArea.x, usableArea.y) - PMONITOR->vecPosition; @@ -1808,7 +1808,7 @@ void CHyprRenderer::damageBox(const int& x, const int& y, const int& w, const in } void CHyprRenderer::damageRegion(const CRegion& rg) { - for (auto& RECT : rg.getRects()) { + for (auto const& RECT : rg.getRects()) { damageBox(RECT.x1, RECT.y1, RECT.x2 - RECT.x1, RECT.y2 - RECT.y1); } } @@ -2370,7 +2370,7 @@ std::tuple CHyprRenderer::getRenderTimes(CMonitor* pMonitor float avgRenderTime = 0; float maxRenderTime = 0; float minRenderTime = 9999; - for (auto& rt : POVERLAY->m_dLastRenderTimes) { + for (auto const& rt : POVERLAY->m_dLastRenderTimes) { if (rt > maxRenderTime) maxRenderTime = rt; if (rt < minRenderTime) @@ -2528,12 +2528,12 @@ void CHyprRenderer::recheckSolitaryForMonitor(CMonitor* pMonitor) { if (!pMonitor->m_aLayerSurfaceLayers[ZWLR_LAYER_SHELL_V1_LAYER_OVERLAY].empty()) return; - for (auto& topls : pMonitor->m_aLayerSurfaceLayers[ZWLR_LAYER_SHELL_V1_LAYER_TOP]) { + for (auto const& topls : pMonitor->m_aLayerSurfaceLayers[ZWLR_LAYER_SHELL_V1_LAYER_TOP]) { if (topls->alpha.value() != 0.f) return; } - for (auto& w : g_pCompositor->m_vWindows) { + for (auto const& w : g_pCompositor->m_vWindows) { if (w == PCANDIDATE || (!w->m_bIsMapped && !w->m_bFadingOut) || w->isHidden()) continue; diff --git a/src/xwayland/XSurface.cpp b/src/xwayland/XSurface.cpp index 30ffbc68..02fe2b3b 100644 --- a/src/xwayland/XSurface.cpp +++ b/src/xwayland/XSurface.cpp @@ -151,8 +151,8 @@ bool CXWaylandSurface::wantsFocus() { HYPRATOMS["_NET_WM_WINDOW_TYPE_UTILITY"], }; - for (auto& searched : search) { - for (auto& a : atoms) { + for (auto const& searched : search) { + for (auto const& a : atoms) { if (a == searched) return false; } diff --git a/src/xwayland/XWM.cpp b/src/xwayland/XWM.cpp index a409b440..995ec7f2 100644 --- a/src/xwayland/XWM.cpp +++ b/src/xwayland/XWM.cpp @@ -24,7 +24,7 @@ static int onX11Event(int fd, uint32_t mask, void* data) { } SP CXWM::windowForXID(xcb_window_t wid) { - for (auto& s : surfaces) { + for (auto const& s : surfaces) { if (s->xID == wid) return s; } @@ -156,7 +156,7 @@ void CXWM::readProp(SP XSURF, uint32_t atom, xcb_get_property_ std::string propName; if (Debug::trace) { propName = std::format("{}?", atom); - for (auto& ha : HYPRATOMS) { + for (auto const& ha : HYPRATOMS) { if (ha.second != atom) continue; @@ -285,7 +285,7 @@ void CXWM::handleClientMessage(xcb_client_message_event_t* e) { return; std::string propName = "?"; - for (auto& ha : HYPRATOMS) { + for (auto const& ha : HYPRATOMS) { if (ha.second != e->type) continue; @@ -317,7 +317,7 @@ void CXWM::handleClientMessage(xcb_client_message_event_t* e) { Debug::log(LOG, "[xwm] surface {:x} requests serial {:x}", (uintptr_t)XSURF.get(), XSURF->wlSerial); - for (auto& res : shellResources) { + for (auto const& res : shellResources) { if (!res) continue; @@ -579,7 +579,7 @@ void CXWM::handleSelectionRequest(xcb_selection_request_event_t* e) { atoms.push_back(HYPRATOMS["TIMESTAMP"]); atoms.push_back(HYPRATOMS["TARGETS"]); - for (auto& m : mimes) { + for (auto const& m : mimes) { atoms.push_back(mimeToAtom(m)); } @@ -944,7 +944,7 @@ void CXWM::onNewSurface(SP surf) { const auto WLID = surf->id(); - for (auto& sr : surfaces) { + for (auto const& sr : surfaces) { if (sr->surface || sr->wlID != WLID) continue; @@ -961,7 +961,7 @@ void CXWM::onNewResource(SP resource) { std::erase_if(shellResources, [](const auto& e) { return e.expired(); }); shellResources.push_back(resource); - for (auto& surf : surfaces) { + for (auto const& surf : surfaces) { if (surf->resource || surf->wlSerial != resource->serial) continue; From 1ea47950f4262ec1215087948c7275f8e0115af2 Mon Sep 17 00:00:00 2001 From: Tom Englund Date: Mon, 26 Aug 2024 18:02:44 +0200 Subject: [PATCH 0324/2181] misc: fix some minor typos (#7530) * keybindmgr: fix typo in swap prev seems a suspicious extra ) got added, remove it. * configmgr: dont dereference invalid iterator i think the idea here was to print the key and not the iterator at or past .end() --- src/config/ConfigManager.cpp | 2 +- src/managers/KeybindManager.cpp | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/config/ConfigManager.cpp b/src/config/ConfigManager.cpp index 007869ee..5ce380a0 100644 --- a/src/config/ConfigManager.cpp +++ b/src/config/ConfigManager.cpp @@ -1720,7 +1720,7 @@ static bool parseModeLine(const std::string& modeline, drmModeModeInfo& mode) { if (it != flagsmap.end()) mode.flags |= it->second; else - Debug::log(ERR, "invalid flag {} in modeline", it->first); + Debug::log(ERR, "invalid flag {} in modeline", key); } snprintf(mode.name, sizeof(mode.name), "%dx%d@%d", mode.hdisplay, mode.vdisplay, mode.vrefresh / 1000); diff --git a/src/managers/KeybindManager.cpp b/src/managers/KeybindManager.cpp index 7eb96730..9fac656c 100644 --- a/src/managers/KeybindManager.cpp +++ b/src/managers/KeybindManager.cpp @@ -2441,7 +2441,7 @@ SDispatchResult CKeybindManager::swapnext(std::string arg) { // sometimes we may come back to ourselves. if (toSwap == PLASTWINDOW) { if (arg == "last" || arg == "l" || arg == "prev" || arg == "p") - toSwap = g_pCompositor->getPrevWindowOnWorkspace(PLASTWINDOW), true; + toSwap = g_pCompositor->getPrevWindowOnWorkspace(PLASTWINDOW, true); else toSwap = g_pCompositor->getNextWindowOnWorkspace(PLASTWINDOW, true); } From 72c7818ae66a18d126e2b4245d649fe3a93d3b8e Mon Sep 17 00:00:00 2001 From: Tom Englund Date: Mon, 26 Aug 2024 20:24:30 +0200 Subject: [PATCH 0325/2181] misc: constify the remaining for loops (#7534) now we roll loops at blazing constified speed. --- hyprctl/main.cpp | 4 +- hyprpm/src/core/DataState.cpp | 2 +- hyprpm/src/core/Manifest.cpp | 4 +- hyprpm/src/core/PluginManager.cpp | 38 +++--- src/Compositor.cpp | 112 +++++++++--------- src/config/ConfigManager.cpp | 26 ++-- src/debug/HyprCtl.cpp | 74 ++++++------ src/debug/HyprDebugOverlay.cpp | 2 +- src/debug/HyprNotificationOverlay.cpp | 4 +- src/desktop/LayerSurface.cpp | 2 +- src/desktop/Popup.cpp | 10 +- src/desktop/Subsurface.cpp | 6 +- src/desktop/Window.cpp | 16 +-- src/desktop/Workspace.cpp | 4 +- src/events/Windows.cpp | 4 +- src/helpers/BezierCurve.cpp | 2 +- src/helpers/Format.cpp | 4 +- src/helpers/MiscFunctions.cpp | 12 +- src/helpers/Monitor.cpp | 22 ++-- src/layout/DwindleLayout.cpp | 4 +- src/layout/IHyprLayout.cpp | 6 +- src/layout/MasterLayout.cpp | 10 +- src/managers/AnimationManager.cpp | 10 +- src/managers/CursorManager.cpp | 6 +- src/managers/HookSystemManager.cpp | 4 +- src/managers/KeybindManager.cpp | 12 +- src/managers/PointerManager.cpp | 20 ++-- src/managers/ProtocolManager.cpp | 2 +- src/managers/SeatManager.cpp | 2 +- src/managers/SessionLockManager.cpp | 6 +- src/managers/XCursorManager.cpp | 2 +- src/managers/XWaylandManager.cpp | 2 +- src/managers/eventLoop/EventLoopManager.cpp | 10 +- src/managers/input/IdleInhibitor.cpp | 2 +- src/managers/input/InputManager.cpp | 20 ++-- src/managers/input/InputMethodRelay.cpp | 14 +-- src/managers/input/Tablets.cpp | 2 +- src/plugins/PluginAPI.cpp | 4 +- src/plugins/PluginSystem.cpp | 20 ++-- src/protocols/DRMLease.cpp | 12 +- src/protocols/DataDeviceWlr.cpp | 4 +- src/protocols/FocusGrab.cpp | 2 +- src/protocols/ForeignToplevel.cpp | 8 +- src/protocols/ForeignToplevelWlr.cpp | 16 +-- src/protocols/FractionalScale.cpp | 2 +- src/protocols/GammaControl.cpp | 4 +- src/protocols/GlobalShortcuts.cpp | 12 +- src/protocols/IdleNotify.cpp | 4 +- src/protocols/InputMethodV2.cpp | 10 +- src/protocols/LinuxDMABUF.cpp | 20 ++-- src/protocols/MesaDRM.cpp | 6 +- src/protocols/OutputManagement.cpp | 24 ++-- src/protocols/PointerGestures.cpp | 16 +-- src/protocols/PresentationTime.cpp | 4 +- src/protocols/PrimarySelection.cpp | 8 +- src/protocols/RelativePointer.cpp | 2 +- src/protocols/Screencopy.cpp | 8 +- src/protocols/SessionLock.cpp | 2 +- src/protocols/ShortcutsInhibit.cpp | 4 +- src/protocols/Tablet.cpp | 58 ++++----- src/protocols/TearingControl.cpp | 4 +- src/protocols/ToplevelExport.cpp | 6 +- src/protocols/VirtualKeyboard.cpp | 2 +- src/protocols/XDGOutput.cpp | 4 +- src/protocols/XDGShell.cpp | 6 +- src/protocols/core/Compositor.cpp | 6 +- src/protocols/core/DataDevice.cpp | 2 +- src/protocols/core/Output.cpp | 4 +- src/protocols/core/Seat.cpp | 8 +- src/protocols/core/Shm.cpp | 4 +- src/protocols/core/Subcompositor.cpp | 4 +- src/render/OpenGL.cpp | 54 ++++----- src/render/Renderer.cpp | 88 +++++++------- src/render/Texture.cpp | 2 +- .../decorations/CHyprBorderDecoration.cpp | 2 +- .../decorations/CHyprDropShadowDecoration.cpp | 2 +- .../decorations/CHyprGroupBarDecoration.cpp | 2 +- .../decorations/DecorationPositioner.cpp | 6 +- src/xwayland/XWM.cpp | 6 +- 79 files changed, 472 insertions(+), 472 deletions(-) diff --git a/hyprctl/main.cpp b/hyprctl/main.cpp index 5d5113b8..1ad189b7 100644 --- a/hyprctl/main.cpp +++ b/hyprctl/main.cpp @@ -287,12 +287,12 @@ void instancesRequest(bool json) { std::vector inst = instances(); if (!json) { - for (auto& el : inst) { + for (auto const& el : inst) { result += std::format("instance {}:\n\ttime: {}\n\tpid: {}\n\twl socket: {}\n\n", el.id, el.time, el.pid, el.wlSocket); } } else { result += '['; - for (auto& el : inst) { + for (auto const& el : inst) { result += std::format(R"#( {{ "instance": "{}", diff --git a/hyprpm/src/core/DataState.cpp b/hyprpm/src/core/DataState.cpp index 61ad336f..05c63f4e 100644 --- a/hyprpm/src/core/DataState.cpp +++ b/hyprpm/src/core/DataState.cpp @@ -49,7 +49,7 @@ void DataState::addNewPluginRepo(const SPluginRepository& repo) { {"rev", repo.rev} }} }; - for (auto& p : repo.plugins) { + for (auto const& p : repo.plugins) { // copy .so to the good place if (std::filesystem::exists(p.filename)) std::filesystem::copy_file(p.filename, PATH + "/" + p.name + ".so"); diff --git a/hyprpm/src/core/Manifest.cpp b/hyprpm/src/core/Manifest.cpp index 42a8357c..754d9d69 100644 --- a/hyprpm/src/core/Manifest.cpp +++ b/hyprpm/src/core/Manifest.cpp @@ -6,7 +6,7 @@ CManifest::CManifest(const eManifestType type, const std::string& path) { auto manifest = toml::parse_file(path); if (type == MANIFEST_HYPRLOAD) { - for (auto& [key, val] : manifest) { + for (auto const& [key, val] : manifest) { if (key.str().ends_with(".build")) continue; @@ -63,7 +63,7 @@ CManifest::CManifest(const eManifestType type, const std::string& path) { } } - for (auto& [key, val] : manifest) { + for (auto const& [key, val] : manifest) { if (key.str() == "repository") continue; diff --git a/hyprpm/src/core/PluginManager.cpp b/hyprpm/src/core/PluginManager.cpp index ab457ca6..669789b4 100644 --- a/hyprpm/src/core/PluginManager.cpp +++ b/hyprpm/src/core/PluginManager.cpp @@ -204,9 +204,9 @@ bool CPluginManager::addNewPluginRepo(const std::string& url, const std::string& progress.m_iSteps = 2; progress.printMessageAbove(std::string{Colors::GREEN} + "✔" + Colors::RESET + " parsed manifest, found " + std::to_string(pManifest->m_vPlugins.size()) + " plugins:"); - for (auto& pl : pManifest->m_vPlugins) { + for (auto const& pl : pManifest->m_vPlugins) { std::string message = std::string{Colors::RESET} + " → " + pl.name + " by "; - for (auto& a : pl.authors) { + for (auto const& a : pl.authors) { message += a + ", "; } if (pl.authors.size() > 0) { @@ -222,7 +222,7 @@ bool CPluginManager::addNewPluginRepo(const std::string& url, const std::string& progress.printMessageAbove(std::string{Colors::RESET} + " → Manifest has " + std::to_string(pManifest->m_sRepository.commitPins.size()) + " pins, checking"); - for (auto& [hl, plugin] : pManifest->m_sRepository.commitPins) { + for (auto const& [hl, plugin] : pManifest->m_sRepository.commitPins) { if (hl != HLVER.hash) continue; @@ -264,7 +264,7 @@ bool CPluginManager::addNewPluginRepo(const std::string& url, const std::string& progress.printMessageAbove(std::string{Colors::RESET} + " → Building " + p.name); - for (auto& bs : p.buildSteps) { + for (auto const& bs : p.buildSteps) { std::string cmd = std::format("cd {} && PKG_CONFIG_PATH=\"{}/share/pkgconfig\" {}", m_szWorkingPluginDirectory, DataState::getHeadersPath(), bs); out += " -> " + cmd + "\n" + execAndGet(cmd) + "\n"; } @@ -299,7 +299,7 @@ bool CPluginManager::addNewPluginRepo(const std::string& url, const std::string& repo.url = url; repo.rev = rev; repo.hash = repohash; - for (auto& p : pManifest->m_vPlugins) { + for (auto const& p : pManifest->m_vPlugins) { repo.plugins.push_back(SPlugin{p.name, m_szWorkingPluginDirectory + "/" + p.output, false, p.failed}); } DataState::addNewPluginRepo(repo); @@ -579,7 +579,7 @@ bool CPluginManager::updatePlugins(bool forceUpdateAll) { const std::string USERNAME = getpwuid(getuid())->pw_name; m_szWorkingPluginDirectory = "/tmp/hyprpm/" + USERNAME; - for (auto& repo : REPOS) { + for (auto const& repo : REPOS) { bool update = forceUpdateAll; progress.m_iSteps++; @@ -658,7 +658,7 @@ bool CPluginManager::updatePlugins(bool forceUpdateAll) { progress.printMessageAbove(std::string{Colors::RESET} + " → Manifest has " + std::to_string(pManifest->m_sRepository.commitPins.size()) + " pins, checking"); - for (auto& [hl, plugin] : pManifest->m_sRepository.commitPins) { + for (auto const& [hl, plugin] : pManifest->m_sRepository.commitPins) { if (hl != HLVER.hash) continue; @@ -679,7 +679,7 @@ bool CPluginManager::updatePlugins(bool forceUpdateAll) { progress.printMessageAbove(std::string{Colors::RESET} + " → Building " + p.name); - for (auto& bs : p.buildSteps) { + for (auto const& bs : p.buildSteps) { std::string cmd = std::format("cd {} && PKG_CONFIG_PATH=\"{}/share/pkgconfig\" {}", m_szWorkingPluginDirectory, DataState::getHeadersPath(), bs); out += " -> " + cmd + "\n" + execAndGet(cmd) + "\n"; } @@ -709,7 +709,7 @@ bool CPluginManager::updatePlugins(bool forceUpdateAll) { if (repohash.length() > 0) repohash.pop_back(); newrepo.hash = repohash; - for (auto& p : pManifest->m_vPlugins) { + for (auto const& p : pManifest->m_vPlugins) { const auto OLDPLUGINIT = std::find_if(repo.plugins.begin(), repo.plugins.end(), [&](const auto& other) { return other.name == p.name; }); newrepo.plugins.push_back(SPlugin{p.name, m_szWorkingPluginDirectory + "/" + p.output, OLDPLUGINIT != repo.plugins.end() ? OLDPLUGINIT->enabled : false}); } @@ -794,8 +794,8 @@ ePluginLoadStateReturn CPluginManager::ensurePluginsLoadState() { const auto REPOS = DataState::getAllRepositories(); auto enabled = [REPOS](const std::string& plugin) -> bool { - for (auto& r : REPOS) { - for (auto& p : r.plugins) { + for (auto const& r : REPOS) { + for (auto const& p : r.plugins) { if (p.name == plugin && p.enabled) return true; } @@ -805,8 +805,8 @@ ePluginLoadStateReturn CPluginManager::ensurePluginsLoadState() { }; auto repoForName = [REPOS](const std::string& name) -> std::string { - for (auto& r : REPOS) { - for (auto& p : r.plugins) { + for (auto const& r : REPOS) { + for (auto const& p : r.plugins) { if (p.name == name) return r.name; } @@ -816,7 +816,7 @@ ePluginLoadStateReturn CPluginManager::ensurePluginsLoadState() { }; // unload disabled plugins - for (auto& p : loadedPlugins) { + for (auto const& p : loadedPlugins) { if (!enabled(p)) { // unload loadUnloadPlugin(HYPRPMPATH + repoForName(p) + "/" + p + ".so", false); @@ -825,8 +825,8 @@ ePluginLoadStateReturn CPluginManager::ensurePluginsLoadState() { } // load enabled plugins - for (auto& r : REPOS) { - for (auto& p : r.plugins) { + for (auto const& r : REPOS) { + for (auto const& p : r.plugins) { if (!p.enabled) continue; @@ -855,10 +855,10 @@ bool CPluginManager::loadUnloadPlugin(const std::string& path, bool load) { void CPluginManager::listAllPlugins() { const auto REPOS = DataState::getAllRepositories(); - for (auto& r : REPOS) { + for (auto const& r : REPOS) { std::cout << std::string{Colors::RESET} + " → Repository " + r.name + ":\n"; - for (auto& p : r.plugins) { + for (auto const& p : r.plugins) { std::cout << std::string{Colors::RESET} + " │ Plugin " + p.name; @@ -905,7 +905,7 @@ std::string CPluginManager::headerErrorShort(const eHeadersErrors err) { bool CPluginManager::hasDeps() { std::vector deps = {"meson", "cpio", "cmake", "pkg-config"}; - for (auto& d : deps) { + for (auto const& d : deps) { if (!execAndGet("command -v " + d).contains("/")) return false; } diff --git a/src/Compositor.cpp b/src/Compositor.cpp index 0aa7f213..cacbeece 100644 --- a/src/Compositor.cpp +++ b/src/Compositor.cpp @@ -391,7 +391,7 @@ void CCompositor::initAllSignals() { m_bSessionActive = true; - for (auto& m : m_vMonitors) { + for (auto const& m : m_vMonitors) { scheduleFrameForMonitor(m.get()); g_pHyprRenderer->applyMonitorRule(m.get(), &m->activeMonitorRule, true); } @@ -477,7 +477,7 @@ void CCompositor::cleanup() { m_vWorkspaces.clear(); m_vWindows.clear(); - for (auto& m : m_vMonitors) { + for (auto const& m : m_vMonitors) { g_pHyprOpenGL->destroyMonitorResources(m.get()); m->output->state->setEnabled(false); @@ -641,7 +641,7 @@ void CCompositor::removeLockFile() { void CCompositor::prepareFallbackOutput() { // create a backup monitor SP headless; - for (auto& impl : m_pAqBackend->getImplementations()) { + for (auto const& impl : m_pAqBackend->getImplementations()) { if (impl->type() == Aquamarine::AQ_BACKEND_HEADLESS) { headless = impl; break; @@ -698,7 +698,7 @@ void CCompositor::startCompositor() { } CMonitor* CCompositor::getMonitorFromID(const MONITORID& id) { - for (auto& m : m_vMonitors) { + for (auto const& m : m_vMonitors) { if (m->ID == id) { return m.get(); } @@ -708,7 +708,7 @@ CMonitor* CCompositor::getMonitorFromID(const MONITORID& id) { } CMonitor* CCompositor::getMonitorFromName(const std::string& name) { - for (auto& m : m_vMonitors) { + for (auto const& m : m_vMonitors) { if (m->szName == name) { return m.get(); } @@ -717,7 +717,7 @@ CMonitor* CCompositor::getMonitorFromName(const std::string& name) { } CMonitor* CCompositor::getMonitorFromDesc(const std::string& desc) { - for (auto& m : m_vMonitors) { + for (auto const& m : m_vMonitors) { if (m->szDescription.starts_with(desc)) return m.get(); } @@ -730,7 +730,7 @@ CMonitor* CCompositor::getMonitorFromCursor() { CMonitor* CCompositor::getMonitorFromVector(const Vector2D& point) { SP mon; - for (auto& m : m_vMonitors) { + for (auto const& m : m_vMonitors) { if (CBox{m->vecPosition, m->vecSize}.containsPoint(point)) { mon = m; break; @@ -771,7 +771,7 @@ void CCompositor::removeWindowFromVectorSafe(PHLWINDOW pWindow) { } bool CCompositor::monitorExists(CMonitor* pMonitor) { - for (auto& m : m_vRealMonitors) { + for (auto const& m : m_vRealMonitors) { if (m.get() == pMonitor) return true; } @@ -789,7 +789,7 @@ PHLWINDOW CCompositor::vectorToWindowUnified(const Vector2D& pos, uint8_t proper // pinned windows on top of floating regardless if (properties & ALLOW_FLOATING) { - for (auto& w : m_vWindows | std::views::reverse) { + for (auto const& w : m_vWindows | std::views::reverse) { const auto BB = w->getWindowBoxUnified(properties); CBox box = BB.copy().expand(w->m_iX11Type != 2 ? BORDER_GRAB_AREA : 0); if (w->m_bIsFloating && w->m_bIsMapped && !w->isHidden() && !w->m_bX11ShouldntFocus && w->m_bPinned && !w->m_sWindowData.noFocus.valueOrDefault() && @@ -807,7 +807,7 @@ PHLWINDOW CCompositor::vectorToWindowUnified(const Vector2D& pos, uint8_t proper auto windowForWorkspace = [&](bool special) -> PHLWINDOW { auto floating = [&](bool aboveFullscreen) -> PHLWINDOW { - for (auto& w : m_vWindows | std::views::reverse) { + for (auto const& w : m_vWindows | std::views::reverse) { if (special && !w->onSpecialWorkspace()) // because special floating may creep up into regular continue; @@ -870,7 +870,7 @@ PHLWINDOW CCompositor::vectorToWindowUnified(const Vector2D& pos, uint8_t proper return found; // for windows, we need to check their extensions too, first. - for (auto& w : m_vWindows) { + for (auto const& w : m_vWindows) { if (special != w->onSpecialWorkspace()) continue; @@ -881,7 +881,7 @@ PHLWINDOW CCompositor::vectorToWindowUnified(const Vector2D& pos, uint8_t proper } } - for (auto& w : m_vWindows) { + for (auto const& w : m_vWindows) { if (special != w->onSpecialWorkspace()) continue; @@ -963,7 +963,7 @@ Vector2D CCompositor::vectorToSurfaceLocal(const Vector2D& vec, PHLWINDOW pWindo } CMonitor* CCompositor::getMonitorFromOutput(SP out) { - for (auto& m : m_vMonitors) { + for (auto const& m : m_vMonitors) { if (m->output == out) { return m.get(); } @@ -973,7 +973,7 @@ CMonitor* CCompositor::getMonitorFromOutput(SP out) { } CMonitor* CCompositor::getRealMonitorFromOutput(SP out) { - for (auto& m : m_vRealMonitors) { + for (auto const& m : m_vRealMonitors) { if (m->output == out) { return m.get(); } @@ -1212,7 +1212,7 @@ PHLWINDOW CCompositor::getWindowFromSurface(SP pSurface) { } PHLWINDOW CCompositor::getWindowFromHandle(uint32_t handle) { - for (auto& w : m_vWindows) { + for (auto const& w : m_vWindows) { if ((uint32_t)(((uint64_t)w.get()) & 0xFFFFFFFF) == handle) { return w; } @@ -1222,7 +1222,7 @@ PHLWINDOW CCompositor::getWindowFromHandle(uint32_t handle) { } PHLWINDOW CCompositor::getFullscreenWindowOnWorkspace(const WORKSPACEID& ID) { - for (auto& w : m_vWindows) { + for (auto const& w : m_vWindows) { if (w->workspaceID() == ID && w->isFullscreen()) return w; } @@ -1246,7 +1246,7 @@ bool CCompositor::isWorkspaceVisibleNotCovered(PHLWORKSPACE w) { } PHLWORKSPACE CCompositor::getWorkspaceByID(const WORKSPACEID& id) { - for (auto& w : m_vWorkspaces) { + for (auto const& w : m_vWorkspaces) { if (w->m_iID == id && !w->inert()) return w; } @@ -1271,7 +1271,7 @@ void CCompositor::sanityCheckWorkspaces() { int CCompositor::getWindowsOnWorkspace(const WORKSPACEID& id, std::optional onlyTiled, std::optional onlyVisible) { int no = 0; - for (auto& w : m_vWindows) { + for (auto const& w : m_vWindows) { if (w->workspaceID() != id || !w->m_bIsMapped) continue; if (onlyTiled.has_value() && w->m_bIsFloating == onlyTiled.value()) @@ -1286,7 +1286,7 @@ int CCompositor::getWindowsOnWorkspace(const WORKSPACEID& id, std::optional onlyTiled, std::optional onlyVisible) { int no = 0; - for (auto& w : m_vWindows) { + for (auto const& w : m_vWindows) { if (w->workspaceID() != id || !w->m_bIsMapped) continue; if (!w->m_sGroupData.head) @@ -1301,7 +1301,7 @@ int CCompositor::getGroupsOnWorkspace(const WORKSPACEID& id, std::optional } PHLWINDOW CCompositor::getUrgentWindow() { - for (auto& w : m_vWindows) { + for (auto const& w : m_vWindows) { if (w->m_bIsMapped && w->m_bIsUrgent) return w; } @@ -1310,7 +1310,7 @@ PHLWINDOW CCompositor::getUrgentWindow() { } bool CCompositor::hasUrgentWindowOnWorkspace(const WORKSPACEID& id) { - for (auto& w : m_vWindows) { + for (auto const& w : m_vWindows) { if (w->workspaceID() == id && w->m_bIsMapped && w->m_bIsUrgent) return true; } @@ -1319,7 +1319,7 @@ bool CCompositor::hasUrgentWindowOnWorkspace(const WORKSPACEID& id) { } PHLWINDOW CCompositor::getFirstWindowOnWorkspace(const WORKSPACEID& id) { - for (auto& w : m_vWindows) { + for (auto const& w : m_vWindows) { if (w->workspaceID() == id && w->m_bIsMapped && !w->isHidden()) return w; } @@ -1335,7 +1335,7 @@ PHLWINDOW CCompositor::getTopLeftWindowOnWorkspace(const WORKSPACEID& id) { const auto PMONITOR = getMonitorFromID(PWORKSPACE->m_iMonitorID); - for (auto& w : m_vWindows) { + for (auto const& w : m_vWindows) { if (w->workspaceID() != id || !w->m_bIsMapped || w->isHidden()) continue; @@ -1400,7 +1400,7 @@ void CCompositor::changeWindowZOrder(PHLWINDOW pWindow, bool top) { else toMove.emplace_front(pw); - for (auto& w : m_vWindows) { + for (auto const& w : m_vWindows) { if (w->m_bIsMapped && !w->isHidden() && w->m_bIsX11 && w->X11TransientFor() == pw && w != pw && std::find(toMove.begin(), toMove.end(), w) == toMove.end()) { x11Stack(w, top, x11Stack); } @@ -1416,7 +1416,7 @@ void CCompositor::changeWindowZOrder(PHLWINDOW pWindow, bool top) { } void CCompositor::cleanupFadingOut(const MONITORID& monid) { - for (auto& ww : m_vWindowsFadingOut) { + for (auto const& ww : m_vWindowsFadingOut) { auto w = ww.lock(); @@ -1441,7 +1441,7 @@ void CCompositor::cleanupFadingOut(const MONITORID& monid) { bool layersDirty = false; - for (auto& lsr : m_vSurfacesFadingOut) { + for (auto const& lsr : m_vSurfacesFadingOut) { auto ls = lsr.lock(); @@ -1530,7 +1530,7 @@ PHLWINDOW CCompositor::getWindowInDirection(PHLWINDOW pWindow, char dir) { if (!pWindow->m_bIsFloating) { // for tiled windows, we calc edges - for (auto& w : m_vWindows) { + for (auto const& w : m_vWindows) { if (w == pWindow || !w->m_bIsMapped || w->isHidden() || (!w->isFullscreen() && w->m_bIsFloating) || !isWorkspaceVisible(w->m_pWorkspace)) continue; @@ -1622,7 +1622,7 @@ PHLWINDOW CCompositor::getWindowInDirection(PHLWINDOW pWindow, char dir) { float bestAngleAbs = 2.0 * M_PI; constexpr float THRESHOLD = 0.3 * M_PI; - for (auto& w : m_vWindows) { + for (auto const& w : m_vWindows) { if (w == pWindow || !w->m_bIsMapped || w->isHidden() || (!w->isFullscreen() && !w->m_bIsFloating) || !isWorkspaceVisible(w->m_pWorkspace)) continue; @@ -1660,7 +1660,7 @@ PHLWINDOW CCompositor::getWindowInDirection(PHLWINDOW pWindow, char dir) { PHLWINDOW CCompositor::getNextWindowOnWorkspace(PHLWINDOW pWindow, bool focusableOnly, std::optional floating) { bool gotToWindow = false; - for (auto& w : m_vWindows) { + for (auto const& w : m_vWindows) { if (w != pWindow && !gotToWindow) continue; @@ -1676,7 +1676,7 @@ PHLWINDOW CCompositor::getNextWindowOnWorkspace(PHLWINDOW pWindow, bool focusabl return w; } - for (auto& w : m_vWindows) { + for (auto const& w : m_vWindows) { if (floating.has_value() && w->m_bIsFloating != floating.value()) continue; @@ -1689,7 +1689,7 @@ PHLWINDOW CCompositor::getNextWindowOnWorkspace(PHLWINDOW pWindow, bool focusabl PHLWINDOW CCompositor::getPrevWindowOnWorkspace(PHLWINDOW pWindow, bool focusableOnly, std::optional floating) { bool gotToWindow = false; - for (auto& w : m_vWindows | std::views::reverse) { + for (auto const& w : m_vWindows | std::views::reverse) { if (w != pWindow && !gotToWindow) continue; @@ -1705,7 +1705,7 @@ PHLWINDOW CCompositor::getPrevWindowOnWorkspace(PHLWINDOW pWindow, bool focusabl return w; } - for (auto& w : m_vWindows | std::views::reverse) { + for (auto const& w : m_vWindows | std::views::reverse) { if (floating.has_value() && w->m_bIsFloating != floating.value()) continue; @@ -1727,7 +1727,7 @@ WORKSPACEID CCompositor::getNextAvailableNamedWorkspace() { } PHLWORKSPACE CCompositor::getWorkspaceByName(const std::string& name) { - for (auto& w : m_vWorkspaces) { + for (auto const& w : m_vWorkspaces) { if (w->m_szName == name && !w->inert()) return w; } @@ -1779,7 +1779,7 @@ CMonitor* CCompositor::getMonitorInDirection(CMonitor* pSourceMonitor, const cha auto longestIntersect = -1; CMonitor* longestIntersectMonitor = nullptr; - for (auto& m : m_vMonitors) { + for (auto const& m : m_vMonitors) { if (m == m_pLastMonitor) continue; @@ -1843,7 +1843,7 @@ void CCompositor::updateAllWindowsAnimatedDecorationValues() { } void CCompositor::updateWorkspaceWindows(const int64_t& id) { - for (auto& w : m_vWindows) { + for (auto const& w : m_vWindows) { if (!w->m_bIsMapped || w->workspaceID() != id) continue; @@ -1968,7 +1968,7 @@ void CCompositor::swapActiveWorkspaces(CMonitor* pMonitorA, CMonitor* pMonitorB) PWORKSPACEA->m_iMonitorID = pMonitorB->ID; PWORKSPACEA->moveToMonitor(pMonitorB->ID); - for (auto& w : m_vWindows) { + for (auto const& w : m_vWindows) { if (w->m_pWorkspace == PWORKSPACEA) { if (w->m_bPinned) { w->m_pWorkspace = PWORKSPACEB; @@ -1993,7 +1993,7 @@ void CCompositor::swapActiveWorkspaces(CMonitor* pMonitorA, CMonitor* pMonitorB) PWORKSPACEB->m_iMonitorID = pMonitorA->ID; PWORKSPACEB->moveToMonitor(pMonitorA->ID); - for (auto& w : m_vWindows) { + for (auto const& w : m_vWindows) { if (w->m_pWorkspace == PWORKSPACEB) { if (w->m_bPinned) { w->m_pWorkspace = PWORKSPACEA; @@ -2108,7 +2108,7 @@ CMonitor* CCompositor::getMonitorFromString(const std::string& name) { return nullptr; } } else { - for (auto& m : m_vMonitors) { + for (auto const& m : m_vMonitors) { if (!m->output) continue; @@ -2168,7 +2168,7 @@ void CCompositor::moveWorkspaceToMonitor(PHLWORKSPACE pWorkspace, CMonitor* pMon pWorkspace->m_iMonitorID = pMonitor->ID; pWorkspace->moveToMonitor(pMonitor->ID); - for (auto& w : m_vWindows) { + for (auto const& w : m_vWindows) { if (w->m_pWorkspace == pWorkspace) { if (w->m_bPinned) { w->m_pWorkspace = g_pCompositor->getWorkspaceByID(nextWorkspaceOnMonitorID); @@ -2255,7 +2255,7 @@ void CCompositor::updateFullscreenFadeOnWorkspace(PHLWORKSPACE pWorkspace) { const auto FULLSCREEN = pWorkspace->m_bHasFullscreenWindow; - for (auto& w : g_pCompositor->m_vWindows) { + for (auto const& w : g_pCompositor->m_vWindows) { if (w->m_pWorkspace == pWorkspace) { if (w->m_bFadingOut || w->m_bPinned || w->isFullscreen()) @@ -2347,7 +2347,7 @@ void CCompositor::setWindowFullscreenState(const PHLWINDOW PWINDOW, sFullscreenS g_pLayoutManager->getCurrentLayout()->recalculateMonitor(PWINDOW->m_iMonitorID); // make all windows on the same workspace under the fullscreen window - for (auto& w : m_vWindows) { + for (auto const& w : m_vWindows) { if (w->m_pWorkspace == PWORKSPACE && !w->isFullscreen() && !w->m_bFadingOut && !w->m_bPinned) w->m_bCreatedOverFullscreen = false; } @@ -2388,7 +2388,7 @@ PHLWINDOW CCompositor::getX11Parent(PHLWINDOW pWindow) { } void CCompositor::updateWorkspaceWindowDecos(const WORKSPACEID& id) { - for (auto& w : m_vWindows) { + for (auto const& w : m_vWindows) { if (w->workspaceID() != id) continue; @@ -2400,7 +2400,7 @@ void CCompositor::updateWorkspaceWindowData(const WORKSPACEID& id) { const auto PWORKSPACE = getWorkspaceByID(id); const auto WORKSPACERULE = PWORKSPACE ? g_pConfigManager->getWorkspaceRuleFor(PWORKSPACE) : SWorkspaceRule{}; - for (auto& w : m_vWindows) { + for (auto const& w : m_vWindows) { if (w->workspaceID() != id) continue; @@ -2453,7 +2453,7 @@ PHLWINDOW CCompositor::getWindowByRegex(const std::string& regexp) { const bool FLOAT = regexp.starts_with("floating"); - for (auto& w : m_vWindows) { + for (auto const& w : m_vWindows) { if (!w->m_bIsMapped || w->m_bIsFloating != FLOAT || w->m_pWorkspace != m_pLastWindow->m_pWorkspace || w->isHidden()) continue; @@ -2463,7 +2463,7 @@ PHLWINDOW CCompositor::getWindowByRegex(const std::string& regexp) { return nullptr; } - for (auto& w : g_pCompositor->m_vWindows) { + for (auto const& w : g_pCompositor->m_vWindows) { if (!w->m_bIsMapped || (w->isHidden() && !g_pLayoutManager->getCurrentLayout()->isWindowReachable(w))) continue; @@ -2617,7 +2617,7 @@ Vector2D CCompositor::parseWindowVectorArgsRelative(const std::string& args, con } void CCompositor::forceReportSizesToWindowsOnWorkspace(const WORKSPACEID& wid) { - for (auto& w : m_vWindows) { + for (auto const& w : m_vWindows) { if (w->workspaceID() == wid && w->m_bIsMapped && !w->isHidden()) { g_pXWaylandManager->setWindowSize(w, w->m_vRealSize.value(), true); } @@ -2744,7 +2744,7 @@ void CCompositor::moveWindowToWorkspaceSafe(PHLWINDOW pWindow, PHLWORKSPACE pWor } PHLWINDOW CCompositor::getForceFocus() { - for (auto& w : m_vWindows) { + for (auto const& w : m_vWindows) { if (!w->m_bIsMapped || w->isHidden() || !isWorkspaceVisible(w->m_pWorkspace)) continue; @@ -2763,7 +2763,7 @@ void CCompositor::arrangeMonitors() { std::vector toArrange; std::vector arranged; - for (auto& m : m_vMonitors) + for (auto const& m : m_vMonitors) toArrange.push_back(m.get()); Debug::log(LOG, "arrangeMonitors: {} to arrange", toArrange.size()); @@ -2795,7 +2795,7 @@ void CCompositor::arrangeMonitors() { int maxYOffsetDown = 0; // Finds the max and min values of explicitely placed monitors. - for (auto& m : arranged) { + for (auto const& m : arranged) { if (m->vecPosition.x + m->vecSize.x > maxXOffsetRight) maxXOffsetRight = m->vecPosition.x + m->vecSize.x; if (m->vecPosition.x < maxXOffsetLeft) @@ -2807,7 +2807,7 @@ void CCompositor::arrangeMonitors() { } // Iterates through all non-explicitly placed monitors. - for (auto& m : toArrange) { + for (auto const& m : toArrange) { // Moves the monitor to their appropriate position on the x/y axis and // increments/decrements the corresponding max offset. Vector2D newPosition = {0, 0}; @@ -2838,7 +2838,7 @@ void CCompositor::arrangeMonitors() { // reset maxXOffsetRight (reuse) // and set xwayland positions aka auto for all maxXOffsetRight = 0; - for (auto& m : m_vMonitors) { + for (auto const& m : m_vMonitors) { Debug::log(LOG, "arrangeMonitors: {} xwayland [{}, {}]", m->szName, maxXOffsetRight, 0); m->vecXWaylandPosition = {maxXOffsetRight, 0}; maxXOffsetRight += (*PXWLFORCESCALEZERO ? m->vecTransformedSize.x : m->vecSize.x); @@ -2873,7 +2873,7 @@ void CCompositor::leaveUnsafeState() { m_bUnsafeState = false; CMonitor* pNewMonitor = nullptr; - for (auto& pMonitor : m_vMonitors) { + for (auto const& pMonitor : m_vMonitors) { if (pMonitor->output != m_pUnsafeOutput->output) { pNewMonitor = pMonitor.get(); break; @@ -2885,7 +2885,7 @@ void CCompositor::leaveUnsafeState() { if (m_pUnsafeOutput->m_bEnabled) m_pUnsafeOutput->onDisconnect(); - for (auto& m : m_vMonitors) { + for (auto const& m : m_vMonitors) { scheduleFrameForMonitor(m.get()); } } @@ -2917,7 +2917,7 @@ void CCompositor::setPreferredTransformForSurface(SP pSurfac } void CCompositor::updateSuspendedStates() { - for (auto& w : g_pCompositor->m_vWindows) { + for (auto const& w : g_pCompositor->m_vWindows) { if (!w->m_bIsMapped) continue; @@ -2926,7 +2926,7 @@ void CCompositor::updateSuspendedStates() { } PHLWINDOW CCompositor::windowForCPointer(CWindow* pWindow) { - for (auto& w : m_vWindows) { + for (auto const& w : m_vWindows) { if (w.get() != pWindow) continue; @@ -2970,7 +2970,7 @@ void CCompositor::onNewMonitor(SP output) { g_pConfigManager->m_bWantsMonitorReload = true; g_pCompositor->scheduleFrameForMonitor(PNEWMONITOR.get(), IOutput::AQ_SCHEDULE_NEW_MONITOR); - for (auto& w : g_pCompositor->m_vWindows) { + for (auto const& w : g_pCompositor->m_vWindows) { if (w->m_iMonitorID == PNEWMONITOR->ID) { w->m_iLastSurfaceMonitorID = MONITOR_INVALID; w->updateSurfaceScaleTransformDetails(); diff --git a/src/config/ConfigManager.cpp b/src/config/ConfigManager.cpp index 5ce380a0..f402958b 100644 --- a/src/config/ConfigManager.cpp +++ b/src/config/ConfigManager.cpp @@ -45,7 +45,7 @@ static Hyprlang::CParseResult configHandleGradientSet(const char* VALUE, void** std::string parseError = ""; - for (auto& var : varlist) { + for (auto const& var : varlist) { if (var.find("deg") != std::string::npos) { // last arg try { @@ -863,7 +863,7 @@ void CConfigManager::postConfigReload(const Hyprlang::CParseResult& result) { refreshGroupBarGradients(); // Updates dynamic window and workspace rules - for (auto& w : g_pCompositor->m_vWorkspaces) { + for (auto const& w : g_pCompositor->m_vWorkspaces) { if (w->inert()) continue; g_pCompositor->updateWorkspaceWindows(w->m_iID); @@ -891,7 +891,7 @@ void CConfigManager::postConfigReload(const Hyprlang::CParseResult& result) { Debug::coloredLogs = reinterpret_cast(m_pConfig->getConfigValuePtr("debug:colored_stdout_logs")->getDataStaticPtr()); - for (auto& m : g_pCompositor->m_vMonitors) { + for (auto const& m : g_pCompositor->m_vMonitors) { // mark blur dirty g_pHyprOpenGL->markBlurDirtyForMonitor(m.get()); @@ -978,7 +978,7 @@ void CConfigManager::tick() { bool parse = false; - for (auto& cf : configPaths) { + for (auto const& cf : configPaths) { struct stat fileStat; int err = stat(cf.c_str(), &fileStat); if (err != 0) { @@ -1059,7 +1059,7 @@ SMonitorRule CConfigManager::getMonitorRuleFor(const CMonitor& PMONITOR) { SWorkspaceRule CConfigManager::getWorkspaceRuleFor(PHLWORKSPACE pWorkspace) { SWorkspaceRule mergedRule{}; - for (auto& rule : m_dWorkspaceRules) { + for (auto const& rule : m_dWorkspaceRules) { if (!pWorkspace->matchesStaticSelector(rule.workspaceString)) continue; @@ -1132,7 +1132,7 @@ std::vector CConfigManager::getMatchingRules(PHLWINDOW pWindow, boo // local tags for dynamic tag rule match auto tags = pWindow->m_tags; - for (auto& rule : m_dWindowRules) { + for (auto const& rule : m_dWindowRules) { // check if we have a matching rule if (!rule.v2) { try { @@ -1297,7 +1297,7 @@ std::vector CConfigManager::getMatchingRules(PHLWINDOW pWindow, boo bool anyExecFound = false; - for (auto& er : execRequestedRules) { + for (auto const& er : execRequestedRules) { if (std::ranges::any_of(PIDs, [&](const auto& pid) { return pid == er.iPid; })) { returns.push_back({er.szRule, "execRule"}); anyExecFound = true; @@ -1317,7 +1317,7 @@ std::vector CConfigManager::getMatchingRules(PHLLS pLS) { if (!pLS->layerSurface || pLS->fadingOut) return returns; - for (auto& lr : m_dLayerRules) { + for (auto const& lr : m_dLayerRules) { if (lr.targetNamespace.starts_with("address:0x")) { if (std::format("address:0x{:x}", (uintptr_t)pLS.get()) != lr.targetNamespace) continue; @@ -1391,7 +1391,7 @@ void CConfigManager::performMonitorReload() { bool overAgain = false; - for (auto& m : g_pCompositor->m_vRealMonitors) { + for (auto const& m : g_pCompositor->m_vRealMonitors) { if (!m->output || m->isUnsafeFallback) continue; @@ -1448,7 +1448,7 @@ bool CConfigManager::shouldBlurLS(const std::string& ns) { } void CConfigManager::ensureMonitorStatus() { - for (auto& rm : g_pCompositor->m_vRealMonitors) { + for (auto const& rm : g_pCompositor->m_vRealMonitors) { if (!rm->output || rm->isUnsafeFallback) continue; @@ -1531,7 +1531,7 @@ void CConfigManager::ensureVRR(CMonitor* pMonitor) { return; } - for (auto& m : g_pCompositor->m_vMonitors) { + for (auto const& m : g_pCompositor->m_vMonitors) { ensureVRRForDisplay(m.get()); } } @@ -1632,7 +1632,7 @@ void CConfigManager::removePluginConfig(HANDLE handle) { } std::erase_if(pluginKeywords, [&](const auto& other) { return other.handle == handle; }); - for (auto& [h, n] : pluginVariables) { + for (auto const& [h, n] : pluginVariables) { if (h != handle) continue; @@ -2534,7 +2534,7 @@ std::optional CConfigManager::handleWorkspaceRules(const std::strin }; CVarList rulesList{rules, 0, ',', true}; - for (auto& r : rulesList) { + for (auto const& r : rulesList) { const auto R = assignRule(r); if (R.has_value()) return R; diff --git a/src/debug/HyprCtl.cpp b/src/debug/HyprCtl.cpp index 2fc5cc7d..40708cf8 100644 --- a/src/debug/HyprCtl.cpp +++ b/src/debug/HyprCtl.cpp @@ -57,7 +57,7 @@ static std::string formatToString(uint32_t drmFormat) { static std::string availableModesForOutput(CMonitor* pMonitor, eHyprCtlOutputFormat format) { std::string result; - for (auto& m : pMonitor->output->modes) { + for (auto const& m : pMonitor->output->modes) { if (format == FORMAT_NORMAL) result += std::format("{}x{}@{:.2f}Hz ", m->pixelSize.x, m->pixelSize.y, m->refreshRate / 1000.0); else @@ -445,13 +445,13 @@ std::string layersRequest(eHyprCtlOutputFormat format, std::string request) { escapeJSONStrings(mon->szName)); int layerLevel = 0; - for (auto& level : mon->m_aLayerSurfaceLayers) { + for (auto const& level : mon->m_aLayerSurfaceLayers) { result += std::format( R"#( "{}": [ )#", layerLevel); - for (auto& layer : level) { + for (auto const& layer : level) { result += std::format( R"#( {{ "address": "0x{:x}", @@ -484,14 +484,14 @@ std::string layersRequest(eHyprCtlOutputFormat format, std::string request) { result += "\n}\n"; } else { - for (auto& mon : g_pCompositor->m_vMonitors) { + for (auto const& mon : g_pCompositor->m_vMonitors) { result += std::format("Monitor {}:\n", mon->szName); int layerLevel = 0; static const std::array levelNames = {"background", "bottom", "top", "overlay"}; - for (auto& level : mon->m_aLayerSurfaceLayers) { + for (auto const& level : mon->m_aLayerSurfaceLayers) { result += std::format("\tLayer level {} ({}):\n", layerLevel, levelNames[layerLevel]); - for (auto& layer : level) { + for (auto const& layer : level) { result += std::format("\t\tLayer {:x}: xywh: {} {} {} {}, namespace: {}\n", (uintptr_t)layer.get(), layer->geometry.x, layer->geometry.y, layer->geometry.width, layer->geometry.height, layer->szNamespace); } @@ -510,7 +510,7 @@ std::string layoutsRequest(eHyprCtlOutputFormat format, std::string request) { if (format == eHyprCtlOutputFormat::FORMAT_JSON) { result += "["; - for (auto& m : g_pLayoutManager->getAllLayoutNames()) { + for (auto const& m : g_pLayoutManager->getAllLayoutNames()) { result += std::format( R"#( "{}",)#", @@ -520,7 +520,7 @@ std::string layoutsRequest(eHyprCtlOutputFormat format, std::string request) { result += "\n]\n"; } else { - for (auto& m : g_pLayoutManager->getAllLayoutNames()) { + for (auto const& m : g_pLayoutManager->getAllLayoutNames()) { result += std::format("{}\n", m); } } @@ -557,7 +557,7 @@ std::string devicesRequest(eHyprCtlOutputFormat format, std::string request) { result += "{\n"; result += "\"mice\": [\n"; - for (auto& m : g_pInputManager->m_vPointers) { + for (auto const& m : g_pInputManager->m_vPointers) { result += std::format( R"#( {{ "address": "0x{:x}", @@ -572,7 +572,7 @@ std::string devicesRequest(eHyprCtlOutputFormat format, std::string request) { result += "\n],\n"; result += "\"keyboards\": [\n"; - for (auto& k : g_pInputManager->m_vKeyboards) { + for (auto const& k : g_pInputManager->m_vKeyboards) { const auto KM = k->getActiveLayout(); result += std::format( R"#( {{ @@ -596,7 +596,7 @@ std::string devicesRequest(eHyprCtlOutputFormat format, std::string request) { result += "\"tablets\": [\n"; - for (auto& d : g_pInputManager->m_vTabletPads) { + for (auto const& d : g_pInputManager->m_vTabletPads) { result += std::format( R"#( {{ "address": "0x{:x}", @@ -609,7 +609,7 @@ std::string devicesRequest(eHyprCtlOutputFormat format, std::string request) { (uintptr_t)d.get(), (uintptr_t)d->parent.get(), escapeJSONStrings(d->parent ? d->parent->hlName : "")); } - for (auto& d : g_pInputManager->m_vTablets) { + for (auto const& d : g_pInputManager->m_vTablets) { result += std::format( R"#( {{ "address": "0x{:x}", @@ -618,7 +618,7 @@ std::string devicesRequest(eHyprCtlOutputFormat format, std::string request) { (uintptr_t)d.get(), escapeJSONStrings(d->hlName)); } - for (auto& d : g_pInputManager->m_vTabletTools) { + for (auto const& d : g_pInputManager->m_vTabletTools) { result += std::format( R"#( {{ "address": "0x{:x}", @@ -632,7 +632,7 @@ std::string devicesRequest(eHyprCtlOutputFormat format, std::string request) { result += "\"touch\": [\n"; - for (auto& d : g_pInputManager->m_vTouches) { + for (auto const& d : g_pInputManager->m_vTouches) { result += std::format( R"#( {{ "address": "0x{:x}", @@ -646,7 +646,7 @@ std::string devicesRequest(eHyprCtlOutputFormat format, std::string request) { result += "\"switches\": [\n"; - for (auto& d : g_pInputManager->m_lSwitches) { + for (auto const& d : g_pInputManager->m_lSwitches) { result += std::format( R"#( {{ "address": "0x{:x}", @@ -663,14 +663,14 @@ std::string devicesRequest(eHyprCtlOutputFormat format, std::string request) { } else { result += "mice:\n"; - for (auto& m : g_pInputManager->m_vPointers) { + for (auto const& m : g_pInputManager->m_vPointers) { result += std::format("\tMouse at {:x}:\n\t\t{}\n\t\t\tdefault speed: {:.5f}\n", (uintptr_t)m.get(), m->hlName, (m->aq() && m->aq()->getLibinputHandle() ? libinput_device_config_accel_get_default_speed(m->aq()->getLibinputHandle()) : 0.f)); } result += "\n\nKeyboards:\n"; - for (auto& k : g_pInputManager->m_vKeyboards) { + for (auto const& k : g_pInputManager->m_vKeyboards) { const auto KM = k->getActiveLayout(); result += std::format("\tKeyboard at {:x}:\n\t\t{}\n\t\t\trules: r \"{}\", m \"{}\", l \"{}\", v \"{}\", o \"{}\"\n\t\t\tactive keymap: {}\n\t\t\tmain: {}\n", (uintptr_t)k.get(), k->hlName, k->currentRules.rules, k->currentRules.model, k->currentRules.layout, k->currentRules.variant, @@ -679,27 +679,27 @@ std::string devicesRequest(eHyprCtlOutputFormat format, std::string request) { result += "\n\nTablets:\n"; - for (auto& d : g_pInputManager->m_vTabletPads) { + for (auto const& d : g_pInputManager->m_vTabletPads) { result += std::format("\tTablet Pad at {:x} (belongs to {:x} -> {})\n", (uintptr_t)d.get(), (uintptr_t)d->parent.get(), d->parent ? d->parent->hlName : ""); } - for (auto& d : g_pInputManager->m_vTablets) { + for (auto const& d : g_pInputManager->m_vTablets) { result += std::format("\tTablet at {:x}:\n\t\t{}\n\t\t\tsize: {}x{}mm\n", (uintptr_t)d.get(), d->hlName, d->aq()->physicalSize.x, d->aq()->physicalSize.y); } - for (auto& d : g_pInputManager->m_vTabletTools) { + for (auto const& d : g_pInputManager->m_vTabletTools) { result += std::format("\tTablet Tool at {:x}\n", (uintptr_t)d.get()); } result += "\n\nTouch:\n"; - for (auto& d : g_pInputManager->m_vTouches) { + for (auto const& d : g_pInputManager->m_vTouches) { result += std::format("\tTouch Device at {:x}:\n\t\t{}\n", (uintptr_t)d.get(), d->hlName); } result += "\n\nSwitches:\n"; - for (auto& d : g_pInputManager->m_lSwitches) { + for (auto const& d : g_pInputManager->m_lSwitches) { result += std::format("\tSwitch Device at {:x}:\n\t\t{}\n", (uintptr_t)&d, d.pDevice ? d.pDevice->getName() : ""); } } @@ -712,21 +712,21 @@ std::string animationsRequest(eHyprCtlOutputFormat format, std::string request) if (format == eHyprCtlOutputFormat::FORMAT_NORMAL) { ret += "animations:\n"; - for (auto& ac : g_pConfigManager->getAnimationConfig()) { + for (auto const& ac : g_pConfigManager->getAnimationConfig()) { ret += std::format("\n\tname: {}\n\t\toverriden: {}\n\t\tbezier: {}\n\t\tenabled: {}\n\t\tspeed: {:.2f}\n\t\tstyle: {}\n", ac.first, (int)ac.second.overridden, ac.second.internalBezier, ac.second.internalEnabled, ac.second.internalSpeed, ac.second.internalStyle); } ret += "beziers:\n"; - for (auto& bz : g_pAnimationManager->getAllBeziers()) { + for (auto const& bz : g_pAnimationManager->getAllBeziers()) { ret += std::format("\n\tname: {}\n", bz.first); } } else { // json ret += "[["; - for (auto& ac : g_pConfigManager->getAnimationConfig()) { + for (auto const& ac : g_pConfigManager->getAnimationConfig()) { ret += std::format(R"#( {{ "name": "{}", @@ -778,7 +778,7 @@ std::string globalShortcutsRequest(eHyprCtlOutputFormat format, std::string requ std::string ret = ""; const auto SHORTCUTS = PROTO::globalShortcuts->getAllShortcuts(); if (format == eHyprCtlOutputFormat::FORMAT_NORMAL) { - for (auto& sh : SHORTCUTS) + for (auto const& sh : SHORTCUTS) ret += std::format("{}:{} -> {}\n", sh.appid, sh.id, sh.description); } else { ret += "["; @@ -800,7 +800,7 @@ std::string globalShortcutsRequest(eHyprCtlOutputFormat format, std::string requ std::string bindsRequest(eHyprCtlOutputFormat format, std::string request) { std::string ret = ""; if (format == eHyprCtlOutputFormat::FORMAT_NORMAL) { - for (auto& kb : g_pKeybindManager->m_lKeybinds) { + for (auto const& kb : g_pKeybindManager->m_lKeybinds) { ret += "bind"; if (kb.locked) ret += "l"; @@ -821,7 +821,7 @@ std::string bindsRequest(eHyprCtlOutputFormat format, std::string request) { } else { // json ret += "["; - for (auto& kb : g_pKeybindManager->m_lKeybinds) { + for (auto const& kb : g_pKeybindManager->m_lKeybinds) { ret += std::format( R"#( {{ @@ -935,7 +935,7 @@ std::string systemInfoRequest(eHyprCtlOutputFormat format, std::string request) result += "os-release: " + execAndGet("cat /etc/os-release") + "\n\n"; result += "plugins:\n"; - for (auto& pl : g_pPluginSystem->getAllPlugins()) { + for (auto const& pl : g_pPluginSystem->getAllPlugins()) { result += std::format(" {} by {} ver {}\n", pl->name, pl->author, pl->version); } @@ -1006,7 +1006,7 @@ std::string dispatchKeyword(eHyprCtlOutputFormat format, std::string in) { // decorations will probably need a repaint if (COMMAND.contains("decoration:") || COMMAND.contains("border") || COMMAND == "workspace" || COMMAND.contains("zoom_factor") || COMMAND == "source") { - for (auto& m : g_pCompositor->m_vMonitors) { + for (auto const& m : g_pCompositor->m_vMonitors) { g_pHyprRenderer->damageMonitor(m.get()); g_pLayoutManager->getCurrentLayout()->recalculateMonitor(m->ID); } @@ -1359,7 +1359,7 @@ std::string decorationRequest(eHyprCtlOutputFormat format, std::string request) std::string result = ""; if (format == eHyprCtlOutputFormat::FORMAT_JSON) { result += "["; - for (auto& wd : PWINDOW->m_dWindowDecorations) { + for (auto const& wd : PWINDOW->m_dWindowDecorations) { result += "{\n\"decorationName\": \"" + wd->getDisplayName() + "\",\n\"priority\": " + std::to_string(wd->getPositioningInfo().priority) + "\n},"; } @@ -1367,7 +1367,7 @@ std::string decorationRequest(eHyprCtlOutputFormat format, std::string request) result += "]"; } else { result = +"Decoration\tPriority\n"; - for (auto& wd : PWINDOW->m_dWindowDecorations) { + for (auto const& wd : PWINDOW->m_dWindowDecorations) { result += wd->getDisplayName() + "\t" + std::to_string(wd->getPositioningInfo().priority) + "\n"; } } @@ -1396,7 +1396,7 @@ std::string dispatchOutput(eHyprCtlOutputFormat format, std::string request) { if (g_pCompositor->getMonitorFromName(vars[3])) return "A real monitor already uses that name."; - for (auto& impl : g_pCompositor->m_pAqBackend->getImplementations() | std::views::reverse) { + for (auto const& impl : g_pCompositor->m_pAqBackend->getImplementations() | std::views::reverse) { auto type = impl->type(); if (type == Aquamarine::AQ_BACKEND_HEADLESS && (vars[2] == "headless" || vars[2] == "auto")) { @@ -1464,7 +1464,7 @@ std::string dispatchPlugin(eHyprCtlOutputFormat format, std::string request) { return "no plugins loaded"; std::string list = ""; - for (auto& p : PLUGINS) { + for (auto const& p : PLUGINS) { list += std::format("\nPlugin {} by {}:\n\tHandle: {:x}\n\tVersion: {}\n\tDescription: {}\n", p->name, p->author, (uintptr_t)p->m_pHandle, p->version, p->description); } @@ -1673,7 +1673,7 @@ std::string CHyprCtl::getReply(std::string request) { std::string result = ""; // parse exact cmds first, then non-exact. - for (auto& cmd : m_vCommands) { + for (auto const& cmd : m_vCommands) { if (!cmd->exact) continue; @@ -1684,7 +1684,7 @@ std::string CHyprCtl::getReply(std::string request) { } if (result.empty()) - for (auto& cmd : m_vCommands) { + for (auto const& cmd : m_vCommands) { if (cmd->exact) continue; @@ -1715,7 +1715,7 @@ std::string CHyprCtl::getReply(std::string request) { rd.blurFBDirty = true; } - for (auto& m : g_pCompositor->m_vMonitors) { + for (auto const& m : g_pCompositor->m_vMonitors) { g_pHyprRenderer->damageMonitor(m.get()); g_pLayoutManager->getCurrentLayout()->recalculateMonitor(m->ID); } diff --git a/src/debug/HyprDebugOverlay.cpp b/src/debug/HyprDebugOverlay.cpp index 22c741a6..2da64e63 100644 --- a/src/debug/HyprDebugOverlay.cpp +++ b/src/debug/HyprDebugOverlay.cpp @@ -217,7 +217,7 @@ void CHyprDebugOverlay::draw() { // draw the things int offsetY = 0; - for (auto& m : g_pCompositor->m_vMonitors) { + for (auto const& m : g_pCompositor->m_vMonitors) { offsetY += m_mMonitorOverlays[m.get()].draw(offsetY); offsetY += 5; // for padding between mons } diff --git a/src/debug/HyprNotificationOverlay.cpp b/src/debug/HyprNotificationOverlay.cpp index 3f8bb579..29da20c8 100644 --- a/src/debug/HyprNotificationOverlay.cpp +++ b/src/debug/HyprNotificationOverlay.cpp @@ -44,7 +44,7 @@ void CHyprNotificationOverlay::addNotification(const std::string& text, const CC PNOTIF->icon = icon; PNOTIF->fontSize = fontSize; - for (auto& m : g_pCompositor->m_vMonitors) { + for (auto const& m : g_pCompositor->m_vMonitors) { g_pCompositor->scheduleFrameForMonitor(m.get()); } } @@ -87,7 +87,7 @@ CBox CHyprNotificationOverlay::drawNotifications(CMonitor* pMonitor) { const auto iconBackendID = iconBackendFromLayout(layout); const auto PBEZIER = g_pAnimationManager->getBezier("default"); - for (auto& notif : m_dNotifications) { + for (auto const& notif : m_dNotifications) { const auto ICONPADFORNOTIF = notif->icon == ICON_NONE ? 0 : ICON_PAD; const auto FONTSIZE = std::clamp((int)(notif->fontSize * ((pMonitor->vecPixelSize.x * SCALE) / 1920.f)), 8, 40); diff --git a/src/desktop/LayerSurface.cpp b/src/desktop/LayerSurface.cpp index 331dba9c..155a2605 100644 --- a/src/desktop/LayerSurface.cpp +++ b/src/desktop/LayerSurface.cpp @@ -366,7 +366,7 @@ void CLayerSurface::applyRules() { xray = -1; animationStyle.reset(); - for (auto& rule : g_pConfigManager->getMatchingRules(self.lock())) { + for (auto const& rule : g_pConfigManager->getMatchingRules(self.lock())) { if (rule.rule == "noanim") noAnimations = true; else if (rule.rule == "blur") diff --git a/src/desktop/Popup.cpp b/src/desktop/Popup.cpp index e48b7400..a4952ef7 100644 --- a/src/desktop/Popup.cpp +++ b/src/desktop/Popup.cpp @@ -251,7 +251,7 @@ void CPopup::recheckTree() { void CPopup::recheckChildrenRecursive() { auto cpy = m_vChildren; - for (auto& c : cpy) { + for (auto const& c : cpy) { c->onCommit(true); c->recheckChildrenRecursive(); } @@ -282,14 +282,14 @@ bool CPopup::visible() { } void CPopup::bfHelper(std::vector nodes, std::function fn, void* data) { - for (auto& n : nodes) { + for (auto const& n : nodes) { fn(n, data); } std::vector nodes2; - for (auto& n : nodes) { - for (auto& c : n->m_vChildren) { + for (auto const& n : nodes) { + for (auto const& c : n->m_vChildren) { nodes2.push_back(c.get()); } } @@ -308,7 +308,7 @@ CPopup* CPopup::at(const Vector2D& globalCoords, bool allowsInput) { std::vector popups; breadthfirst([](CPopup* popup, void* data) { ((std::vector*)data)->push_back(popup); }, &popups); - for (auto& p : popups | std::views::reverse) { + for (auto const& p : popups | std::views::reverse) { if (!p->m_pResource) continue; diff --git a/src/desktop/Subsurface.cpp b/src/desktop/Subsurface.cpp index 71ee16f0..64dd7cf5 100644 --- a/src/desktop/Subsurface.cpp +++ b/src/desktop/Subsurface.cpp @@ -65,7 +65,7 @@ void CSubsurface::checkSiblingDamage() { const double SCALE = m_pWindowParent.lock() && m_pWindowParent->m_bIsX11 ? 1.0 / m_pWindowParent->m_fX11SurfaceScaledBy : 1.0; - for (auto& n : m_pParent->m_vChildren) { + for (auto const& n : m_pParent->m_vChildren) { if (n.get() == this) continue; @@ -75,7 +75,7 @@ void CSubsurface::checkSiblingDamage() { } void CSubsurface::recheckDamageForSubsurfaces() { - for (auto& n : m_vChildren) { + for (auto const& n : m_vChildren) { const auto COORDS = n->coordsGlobal(); g_pHyprRenderer->damageSurface(n->m_pWLSurface->resource(), COORDS.x, COORDS.y); } @@ -183,7 +183,7 @@ Vector2D CSubsurface::coordsGlobal() { } void CSubsurface::initExistingSubsurfaces(SP pSurface) { - for (auto& s : pSurface->subsurfaces) { + for (auto const& s : pSurface->subsurfaces) { if (!s || s->surface->hlSurface /* already assigned */) continue; onNewSubsurface(s.lock()); diff --git a/src/desktop/Window.cpp b/src/desktop/Window.cpp index 64337097..582e96a0 100644 --- a/src/desktop/Window.cpp +++ b/src/desktop/Window.cpp @@ -296,7 +296,7 @@ void CWindow::removeWindowDeco(IHyprWindowDecoration* deco) { } void CWindow::uncacheWindowDecos() { - for (auto& wd : m_dWindowDecorations) { + for (auto const& wd : m_dWindowDecorations) { g_pDecorationPositioner->uncacheDecoration(wd.get()); } } @@ -305,7 +305,7 @@ bool CWindow::checkInputOnDecos(const eInputType type, const Vector2D& mouseCoor if (type != INPUT_TYPE_DRAG_END && hasPopupAt(mouseCoords)) return false; - for (auto& wd : m_dWindowDecorations) { + for (auto const& wd : m_dWindowDecorations) { if (!(wd->getDecorationFlags() & DECORATION_ALLOWS_MOUSE_INPUT)) continue; @@ -337,7 +337,7 @@ pid_t CWindow::getPID() { } IHyprWindowDecoration* CWindow::getDecorationByType(eDecorationType type) { - for (auto& wd : m_dWindowDecorations) { + for (auto const& wd : m_dWindowDecorations) { if (wd->getDecorationType() == type) return wd.get(); } @@ -666,7 +666,7 @@ void CWindow::applyDynamicRule(const SWindowRule& r) { return; } - for (auto& token : colorsAndAngles) { + for (auto const& token : colorsAndAngles) { // The first angle, or an explicit "0deg", splits the two gradients if (active && token.contains("deg")) { activeBorderGradient.m_fAngle = std::stoi(token.substr(0, token.size() - 3)) * (PI / 180.0); @@ -889,7 +889,7 @@ void CWindow::destroyGroup() { const bool GROUPSLOCKEDPREV = g_pKeybindManager->m_bGroupsLocked; g_pKeybindManager->m_bGroupsLocked = true; - for (auto& w : members) { + for (auto const& w : members) { g_pLayoutManager->getCurrentLayout()->onWindowCreated(w); w->updateWindowDecos(); } @@ -1282,7 +1282,7 @@ std::unordered_map CWindow::getEnv() { CVarList envs(std::string{buffer.data(), buffer.size() - 1}, 0, '\n', true); - for (auto& e : envs) { + for (auto const& e : envs) { if (!e.contains('=')) continue; @@ -1511,7 +1511,7 @@ PHLWINDOW CWindow::getSwallower() { if (!currentPid) break; - for (auto& w : g_pCompositor->m_vWindows) { + for (auto const& w : g_pCompositor->m_vWindows) { if (!w->m_bIsMapped || w->isHidden()) continue; @@ -1536,7 +1536,7 @@ PHLWINDOW CWindow::getSwallower() { return candidates.at(0); // walk up the focus history and find the last focused - for (auto& w : g_pCompositor->m_vWindowFocusHistory) { + for (auto const& w : g_pCompositor->m_vWindowFocusHistory) { if (!w) continue; diff --git a/src/desktop/Workspace.cpp b/src/desktop/Workspace.cpp index 72d9705e..35fc5727 100644 --- a/src/desktop/Workspace.cpp +++ b/src/desktop/Workspace.cpp @@ -94,7 +94,7 @@ void CWorkspace::startAnim(bool in, bool left, bool instant) { // set floating windows offset callbacks m_vRenderOffset.setUpdateCallback([&](void*) { - for (auto& w : g_pCompositor->m_vWindows) { + for (auto const& w : g_pCompositor->m_vWindows) { if (!validMapped(w) || w->workspaceID() != m_iID) continue; @@ -386,7 +386,7 @@ bool CWorkspace::matchesStaticSelector(const std::string& selector_) { bool wantsCountVisible = false; int flagCount = 0; - for (auto& flag : prop) { + for (auto const& flag : prop) { if (flag == 't' && wantsOnlyTiled == -1) { wantsOnlyTiled = 1; flagCount++; diff --git a/src/events/Windows.cpp b/src/events/Windows.cpp index e4e3900b..cd000223 100644 --- a/src/events/Windows.cpp +++ b/src/events/Windows.cpp @@ -139,7 +139,7 @@ void Events::listener_mapWindow(void* owner, void* data) { if (PWINDOW->m_bWantsInitialFullscreen || (PWINDOW->m_bIsX11 && PWINDOW->m_pXWaylandSurface->fullscreen)) requestedClientFSMode = FSMODE_FULLSCREEN; - for (auto& r : PWINDOW->m_vMatchedRules) { + for (auto const& r : PWINDOW->m_vMatchedRules) { if (r.szRule.starts_with("monitor")) { try { const auto MONITORSTR = trim(r.szRule.substr(r.szRule.find(' '))); @@ -326,7 +326,7 @@ void Events::listener_mapWindow(void* owner, void* data) { PWINDOW->m_bCreatedOverFullscreen = true; // size and move rules - for (auto& r : PWINDOW->m_vMatchedRules) { + for (auto const& r : PWINDOW->m_vMatchedRules) { if (r.szRule.starts_with("size")) { try { const auto VALUE = r.szRule.substr(r.szRule.find(' ') + 1); diff --git a/src/helpers/BezierCurve.cpp b/src/helpers/BezierCurve.cpp index dd0ff2b0..ea567ad6 100644 --- a/src/helpers/BezierCurve.cpp +++ b/src/helpers/BezierCurve.cpp @@ -12,7 +12,7 @@ void CBezierCurve::setup(std::vector* pVec) { m_dPoints.emplace_back(Vector2D(0, 0)); - for (auto& p : *pVec) { + for (auto const& p : *pVec) { m_dPoints.push_back(p); } diff --git a/src/helpers/Format.cpp b/src/helpers/Format.cpp index afc8b1c5..bc54b76e 100644 --- a/src/helpers/Format.cpp +++ b/src/helpers/Format.cpp @@ -252,7 +252,7 @@ DRMFormat FormatUtils::shmToDRM(SHMFormat shm) { } const SPixelFormat* FormatUtils::getPixelFormatFromDRM(DRMFormat drm) { - for (auto& fmt : GLES3_FORMATS) { + for (auto const& fmt : GLES3_FORMATS) { if (fmt.drmFormat == drm) return &fmt; } @@ -261,7 +261,7 @@ const SPixelFormat* FormatUtils::getPixelFormatFromDRM(DRMFormat drm) { } const SPixelFormat* FormatUtils::getPixelFormatFromGL(uint32_t glFormat, uint32_t glType, bool alpha) { - for (auto& fmt : GLES3_FORMATS) { + for (auto const& fmt : GLES3_FORMATS) { if (fmt.glFormat == (int)glFormat && fmt.glType == (int)glType && fmt.withAlpha == alpha) return &fmt; } diff --git a/src/helpers/MiscFunctions.cpp b/src/helpers/MiscFunctions.cpp index ef319946..b9970399 100644 --- a/src/helpers/MiscFunctions.cpp +++ b/src/helpers/MiscFunctions.cpp @@ -180,7 +180,7 @@ void handleNoop(struct wl_listener* listener, void* data) { std::string escapeJSONStrings(const std::string& str) { std::ostringstream oss; - for (auto& c : str) { + for (auto const& c : str) { switch (c) { case '"': oss << "\\\""; break; case '\\': oss << "\\\\"; break; @@ -251,7 +251,7 @@ SWorkspaceIDName getWorkspaceIDNameFromString(const std::string& in) { std::set invalidWSes; if (same_mon) { - for (auto& rule : g_pConfigManager->getAllWorkspaceRules()) { + for (auto const& rule : g_pConfigManager->getAllWorkspaceRules()) { const auto PMONITOR = g_pCompositor->getMonitorFromName(rule.monitor); if (PMONITOR && (PMONITOR->ID != g_pCompositor->m_pLastMonitor->ID)) invalidWSes.insert(rule.workspaceId); @@ -301,13 +301,13 @@ SWorkspaceIDName getWorkspaceIDNameFromString(const std::string& in) { std::set invalidWSes; // Collect all the workspaces we can't jump to. - for (auto& ws : g_pCompositor->m_vWorkspaces) { + for (auto const& ws : g_pCompositor->m_vWorkspaces) { if (ws->m_bIsSpecialWorkspace || (ws->m_iMonitorID != g_pCompositor->m_pLastMonitor->ID)) { // Can't jump to this workspace invalidWSes.insert(ws->m_iID); } } - for (auto& rule : g_pConfigManager->getAllWorkspaceRules()) { + for (auto const& rule : g_pConfigManager->getAllWorkspaceRules()) { const auto PMONITOR = g_pCompositor->getMonitorFromName(rule.monitor); if (!PMONITOR || PMONITOR->ID == g_pCompositor->m_pLastMonitor->ID) { // Can't be invalid @@ -319,7 +319,7 @@ SWorkspaceIDName getWorkspaceIDNameFromString(const std::string& in) { // Prepare all named workspaces in case when we need them std::vector namedWSes; - for (auto& ws : g_pCompositor->m_vWorkspaces) { + for (auto const& ws : g_pCompositor->m_vWorkspaces) { if (ws->m_bIsSpecialWorkspace || (ws->m_iMonitorID != g_pCompositor->m_pLastMonitor->ID) || ws->m_iID >= 0) continue; @@ -463,7 +463,7 @@ SWorkspaceIDName getWorkspaceIDNameFromString(const std::string& in) { int remains = (int)result.id; std::vector validWSes; - for (auto& ws : g_pCompositor->m_vWorkspaces) { + for (auto const& ws : g_pCompositor->m_vWorkspaces) { if (ws->m_bIsSpecialWorkspace || (ws->m_iMonitorID != g_pCompositor->m_pLastMonitor->ID && !onAllMonitors)) continue; diff --git a/src/helpers/Monitor.cpp b/src/helpers/Monitor.cpp index 8b533d8a..d81ccb3d 100644 --- a/src/helpers/Monitor.cpp +++ b/src/helpers/Monitor.cpp @@ -171,7 +171,7 @@ void CMonitor::onConnect(bool noRule) { setupDefaultWS(monitorRule); - for (auto& ws : g_pCompositor->m_vWorkspaces) { + for (auto const& ws : g_pCompositor->m_vWorkspaces) { if (!valid(ws)) continue; @@ -242,7 +242,7 @@ void CMonitor::onDisconnect(bool destroy) { // Cleanup everything. Move windows back, snap cursor, shit. CMonitor* BACKUPMON = nullptr; - for (auto& m : g_pCompositor->m_vMonitors) { + for (auto const& m : g_pCompositor->m_vMonitors) { if (m.get() != this) { BACKUPMON = m.get(); break; @@ -259,7 +259,7 @@ void CMonitor::onDisconnect(bool destroy) { } if (!mirrors.empty()) { - for (auto& m : mirrors) { + for (auto const& m : mirrors) { m->setMirror(""); } @@ -298,13 +298,13 @@ void CMonitor::onDisconnect(bool destroy) { // move workspaces std::deque wspToMove; - for (auto& w : g_pCompositor->m_vWorkspaces) { + for (auto const& w : g_pCompositor->m_vWorkspaces) { if (w->m_iMonitorID == ID || !g_pCompositor->getMonitorFromID(w->m_iMonitorID)) { wspToMove.push_back(w); } } - for (auto& w : wspToMove) { + for (auto const& w : wspToMove) { w->m_szLastMonitor = szName; g_pCompositor->moveWorkspaceToMonitor(w, BACKUPMON); w->startAnim(true, true, true); @@ -332,7 +332,7 @@ void CMonitor::onDisconnect(bool destroy) { int mostHz = 0; CMonitor* pMonitorMostHz = nullptr; - for (auto& m : g_pCompositor->m_vMonitors) { + for (auto const& m : g_pCompositor->m_vMonitors) { if (m->refreshRate > mostHz && m.get() != this) { pMonitorMostHz = m.get(); mostHz = m->refreshRate; @@ -516,7 +516,7 @@ void CMonitor::setMirror(const std::string& mirrorOf) { g_pHyprRenderer->applyMonitorRule(this, (SMonitorRule*)&RULE, true); // will apply the offset and stuff } else { CMonitor* BACKUPMON = nullptr; - for (auto& m : g_pCompositor->m_vMonitors) { + for (auto const& m : g_pCompositor->m_vMonitors) { if (m.get() != this) { BACKUPMON = m.get(); break; @@ -525,13 +525,13 @@ void CMonitor::setMirror(const std::string& mirrorOf) { // move all the WS std::deque wspToMove; - for (auto& w : g_pCompositor->m_vWorkspaces) { + for (auto const& w : g_pCompositor->m_vWorkspaces) { if (w->m_iMonitorID == ID) { wspToMove.push_back(w); } } - for (auto& w : wspToMove) { + for (auto const& w : wspToMove) { g_pCompositor->moveWorkspaceToMonitor(w, BACKUPMON); w->startAnim(true, true, true); } @@ -605,7 +605,7 @@ void CMonitor::changeWorkspace(const PHLWORKSPACE& pWorkspace, bool internal, bo pWorkspace->startAnim(true, ANIMTOLEFT); // move pinned windows - for (auto& w : g_pCompositor->m_vWindows) { + for (auto const& w : g_pCompositor->m_vWindows) { if (w->m_pWorkspace == POLDWORKSPACE && w->m_bPinned) w->moveToWorkspace(pWorkspace); } @@ -714,7 +714,7 @@ void CMonitor::setSpecialWorkspace(const PHLWORKSPACE& pWorkspace) { if (animate) pWorkspace->startAnim(true, true); - for (auto& w : g_pCompositor->m_vWindows) { + for (auto const& w : g_pCompositor->m_vWindows) { if (w->m_pWorkspace == pWorkspace) { w->m_iMonitorID = ID; w->updateSurfaceScaleTransformDetails(); diff --git a/src/layout/DwindleLayout.cpp b/src/layout/DwindleLayout.cpp index db69cc04..c936d59c 100644 --- a/src/layout/DwindleLayout.cpp +++ b/src/layout/DwindleLayout.cpp @@ -104,7 +104,7 @@ void CHyprDwindleLayout::applyNodeDataToWindow(SDwindleNodeData* pNode, bool for CMonitor* PMONITOR = nullptr; if (g_pCompositor->isWorkspaceSpecial(pNode->workspaceID)) { - for (auto& m : g_pCompositor->m_vMonitors) { + for (auto const& m : g_pCompositor->m_vMonitors) { if (m->activeSpecialWorkspaceID() == pNode->workspaceID) { PMONITOR = m.get(); break; @@ -1075,7 +1075,7 @@ std::string CHyprDwindleLayout::getLayoutName() { } void CHyprDwindleLayout::onEnable() { - for (auto& w : g_pCompositor->m_vWindows) { + for (auto const& w : g_pCompositor->m_vWindows) { if (w->m_bIsFloating || !w->m_bIsMapped || w->isHidden()) continue; diff --git a/src/layout/IHyprLayout.cpp b/src/layout/IHyprLayout.cpp index 9b3d02b4..f6339beb 100644 --- a/src/layout/IHyprLayout.cpp +++ b/src/layout/IHyprLayout.cpp @@ -591,7 +591,7 @@ PHLWINDOW IHyprLayout::getNextWindowCandidate(PHLWINDOW pWindow) { if (pWindow->m_bIsFloating) { // find whether there is a floating window below this one - for (auto& w : g_pCompositor->m_vWindows) { + for (auto const& w : g_pCompositor->m_vWindows) { if (w->m_bIsMapped && !w->isHidden() && w->m_bIsFloating && w->m_iX11Type != 2 && w->m_pWorkspace == pWindow->m_pWorkspace && !w->m_bX11ShouldntFocus && !w->m_sWindowData.noFocus.valueOrDefault() && w != pWindow) { if (VECINRECT((pWindow->m_vSize / 2.f + pWindow->m_vPosition), w->m_vPosition.x, w->m_vPosition.y, w->m_vPosition.x + w->m_vSize.x, @@ -611,7 +611,7 @@ PHLWINDOW IHyprLayout::getNextWindowCandidate(PHLWINDOW pWindow) { return PWINDOWCANDIDATE; // if not, floating window - for (auto& w : g_pCompositor->m_vWindows) { + for (auto const& w : g_pCompositor->m_vWindows) { if (w->m_bIsMapped && !w->isHidden() && w->m_bIsFloating && w->m_iX11Type != 2 && w->m_pWorkspace == pWindow->m_pWorkspace && !w->m_bX11ShouldntFocus && !w->m_sWindowData.noFocus.valueOrDefault() && w != pWindow) return w; @@ -660,7 +660,7 @@ void IHyprLayout::requestFocusForWindow(PHLWINDOW pWindow) { Vector2D IHyprLayout::predictSizeForNewWindowFloating(PHLWINDOW pWindow) { // get all rules, see if we have any size overrides. Vector2D sizeOverride = {}; if (g_pCompositor->m_pLastMonitor) { - for (auto& r : g_pConfigManager->getMatchingRules(pWindow, true, true)) { + for (auto const& r : g_pConfigManager->getMatchingRules(pWindow, true, true)) { if (r.szRule.starts_with("size")) { try { const auto VALUE = r.szRule.substr(r.szRule.find(' ') + 1); diff --git a/src/layout/MasterLayout.cpp b/src/layout/MasterLayout.cpp index d234d300..8fa324b0 100644 --- a/src/layout/MasterLayout.cpp +++ b/src/layout/MasterLayout.cpp @@ -172,7 +172,7 @@ void CHyprMasterLayout::onWindowCreatedTiling(PHLWINDOW pWindow, eDirection dire } else if (WINDOWSONWORKSPACE == 2) { // when dropping as the second tiled window in the workspace, // make it the master only if the cursor is on the master side of the screen - for (auto& nd : m_lMasterNodesData) { + for (auto const& nd : m_lMasterNodesData) { if (nd.isMaster && nd.workspaceID == PNODE->workspaceID) { switch (orientation) { case ORIENTATION_LEFT: @@ -619,7 +619,7 @@ void CHyprMasterLayout::applyNodeDataToWindow(SMasterNodeData* pNode) { CMonitor* PMONITOR = nullptr; if (g_pCompositor->isWorkspaceSpecial(pNode->workspaceID)) { - for (auto& m : g_pCompositor->m_vMonitors) { + for (auto const& m : g_pCompositor->m_vMonitors) { if (m->activeSpecialWorkspaceID() == pNode->workspaceID) { PMONITOR = m.get(); break; @@ -1106,7 +1106,7 @@ std::any CHyprMasterLayout::layoutMessage(SLayoutMessageHeader header, std::stri const auto NEWFOCUS = newFocusToChild ? NEWCHILD : NEWMASTER; switchToWindow(NEWFOCUS); } else { - for (auto& n : m_lMasterNodesData) { + for (auto const& n : m_lMasterNodesData) { if (n.workspaceID == PMASTER->workspaceID && !n.isMaster) { const auto NEWMASTER = n.pWindow.lock(); switchWindows(NEWMASTER, NEWCHILD); @@ -1141,7 +1141,7 @@ std::any CHyprMasterLayout::layoutMessage(SLayoutMessageHeader header, std::stri return 0; } else { // if master is focused keep master focused (don't do anything) - for (auto& n : m_lMasterNodesData) { + for (auto const& n : m_lMasterNodesData) { if (n.workspaceID == PMASTER->workspaceID && !n.isMaster) { switchToWindow(n.pWindow.lock()); break; @@ -1469,7 +1469,7 @@ Vector2D CHyprMasterLayout::predictSizeForNewWindowTiled() { } void CHyprMasterLayout::onEnable() { - for (auto& w : g_pCompositor->m_vWindows) { + for (auto const& w : g_pCompositor->m_vWindows) { if (w->m_bIsFloating || !w->m_bIsMapped || w->isHidden()) continue; diff --git a/src/managers/AnimationManager.cpp b/src/managers/AnimationManager.cpp index e2e98735..e2fe7089 100644 --- a/src/managers/AnimationManager.cpp +++ b/src/managers/AnimationManager.cpp @@ -70,7 +70,7 @@ void CAnimationManager::tick() { std::vector animationEndedVars; - for (auto& av : m_vActiveAnimatedVariables) { + for (auto const& av : m_vActiveAnimatedVariables) { if (av->m_eDamagePolicy == AVARDAMAGE_SHADOW && !*PSHADOWSENABLED) { av->warp(false); @@ -113,7 +113,7 @@ void CAnimationManager::tick() { g_pHyprRenderer->damageMonitor(PMONITOR); // TODO: just make this into a damn callback already vax... - for (auto& w : g_pCompositor->m_vWindows) { + for (auto const& w : g_pCompositor->m_vWindows) { if (!w->m_bIsMapped || w->isHidden() || w->m_pWorkspace != PWORKSPACE) continue; @@ -214,7 +214,7 @@ void CAnimationManager::tick() { PWINDOW->updateWindowDecos(); g_pHyprRenderer->damageWindow(PWINDOW); } else if (PWORKSPACE) { - for (auto& w : g_pCompositor->m_vWindows) { + for (auto const& w : g_pCompositor->m_vWindows) { if (!validMapped(w) || w->m_pWorkspace != PWORKSPACE) continue; @@ -263,7 +263,7 @@ void CAnimationManager::tick() { } // do it here, because if this alters the animation vars deque we would be in trouble above. - for (auto& ave : animationEndedVars) { + for (auto const& ave : animationEndedVars) { ave->onAnimationEnd(); } } @@ -293,7 +293,7 @@ bool CAnimationManager::deltazero(const CColor& a, const CColor& b) { } bool CAnimationManager::bezierExists(const std::string& bezier) { - for (auto& [bc, bz] : m_mBezierCurves) { + for (auto const& [bc, bz] : m_mBezierCurves) { if (bc == bezier) return true; } diff --git a/src/managers/CursorManager.cpp b/src/managers/CursorManager.cpp index 1c047f85..6f8292f7 100644 --- a/src/managers/CursorManager.cpp +++ b/src/managers/CursorManager.cpp @@ -193,7 +193,7 @@ void CCursorManager::setCursorFromName(const std::string& name) { // fallback to a default if available constexpr const std::array fallbackShapes = {"default", "left_ptr", "left-ptr"}; - for (auto& s : fallbackShapes) { + for (auto const& s : fallbackShapes) { m_sCurrentCursorShapeData = m_pHyprcursor->getShape(s, m_sCurrentStyleInfo); if (m_sCurrentCursorShapeData.images.size() > 0) @@ -288,7 +288,7 @@ void CCursorManager::updateTheme() { static auto PUSEHYPRCURSOR = CConfigValue("cursor:enable_hyprcursor"); float highestScale = 1.0; - for (auto& m : g_pCompositor->m_vMonitors) { + for (auto const& m : g_pCompositor->m_vMonitors) { if (m->scale > highestScale) highestScale = m->scale; } @@ -307,7 +307,7 @@ void CCursorManager::updateTheme() { setCursorFromName("left_ptr"); - for (auto& m : g_pCompositor->m_vMonitors) { + for (auto const& m : g_pCompositor->m_vMonitors) { m->forceFullFrames = 5; g_pCompositor->scheduleFrameForMonitor(m.get(), Aquamarine::IOutput::AQ_SCHEDULE_CURSOR_SHAPE); } diff --git a/src/managers/HookSystemManager.cpp b/src/managers/HookSystemManager.cpp index 208c79ae..624d2fe1 100644 --- a/src/managers/HookSystemManager.cpp +++ b/src/managers/HookSystemManager.cpp @@ -30,7 +30,7 @@ void CHookSystemManager::emit(std::vector* const callbacks, SCal std::vector faultyHandles; volatile bool needsDeadCleanup = false; - for (auto& cb : *callbacks) { + for (auto const& cb : *callbacks) { m_bCurrentEventPlugin = false; @@ -70,7 +70,7 @@ void CHookSystemManager::emit(std::vector* const callbacks, SCal std::erase_if(*callbacks, [](const auto& fn) { return !fn.fn.lock(); }); if (!faultyHandles.empty()) { - for (auto& h : faultyHandles) + for (auto const& h : faultyHandles) g_pPluginSystem->unloadPlugin(g_pPluginSystem->getPluginByHandle(h), true); } } diff --git a/src/managers/KeybindManager.cpp b/src/managers/KeybindManager.cpp index 9fac656c..df3f2572 100644 --- a/src/managers/KeybindManager.cpp +++ b/src/managers/KeybindManager.cpp @@ -908,7 +908,7 @@ uint64_t CKeybindManager::spawnRawProc(std::string args) { grandchild = fork(); if (grandchild == 0) { // run in grandchild - for (auto& e : HLENV) { + for (auto const& e : HLENV) { setenv(e.first.c_str(), e.second.c_str(), 1); } setenv("WAYLAND_DISPLAY", g_pCompositor->m_szWLDisplaySocket.c_str(), 1); @@ -1720,10 +1720,10 @@ SDispatchResult CKeybindManager::workspaceOpt(std::string args) { // we make a copy because changeWindowFloatingMode might invalidate the iterator std::deque ptrs; - for (auto& w : g_pCompositor->m_vWindows) + for (auto const& w : g_pCompositor->m_vWindows) ptrs.push_back(w); - for (auto& w : ptrs) { + for (auto const& w : ptrs) { if (!w->m_bIsMapped || w->m_pWorkspace != PWORKSPACE || w->isHidden()) continue; @@ -1895,7 +1895,7 @@ SDispatchResult CKeybindManager::toggleSpecialWorkspace(std::string args) { const auto PMONITOR = g_pCompositor->m_pLastMonitor; auto specialOpenOnMonitor = PMONITOR->activeSpecialWorkspaceID(); - for (auto& m : g_pCompositor->m_vMonitors) { + for (auto const& m : g_pCompositor->m_vMonitors) { if (m->activeSpecialWorkspaceID() == workspaceID) { requestedWorkspaceIsAlreadyOpen = true; break; @@ -1922,7 +1922,7 @@ SDispatchResult CKeybindManager::toggleSpecialWorkspace(std::string args) { SDispatchResult CKeybindManager::forceRendererReload(std::string args) { bool overAgain = false; - for (auto& m : g_pCompositor->m_vMonitors) { + for (auto const& m : g_pCompositor->m_vMonitors) { if (!m->output) continue; @@ -2390,7 +2390,7 @@ SDispatchResult CKeybindManager::dpms(std::string arg) { if (arg.find_first_of(' ') != std::string::npos) port = arg.substr(arg.find_first_of(' ') + 1); - for (auto& m : g_pCompositor->m_vMonitors) { + for (auto const& m : g_pCompositor->m_vMonitors) { if (!port.empty() && m->szName != port) continue; diff --git a/src/managers/PointerManager.cpp b/src/managers/PointerManager.cpp index 80f1ab4f..f0f74428 100644 --- a/src/managers/PointerManager.cpp +++ b/src/managers/PointerManager.cpp @@ -76,14 +76,14 @@ void CPointerManager::checkDefaultCursorWarp(SP monitor, std::string m } void CPointerManager::lockSoftwareAll() { - for (auto& state : monitorStates) + for (auto const& state : monitorStates) state->softwareLocks++; updateCursorBackend(); } void CPointerManager::unlockSoftwareAll() { - for (auto& state : monitorStates) + for (auto const& state : monitorStates) state->softwareLocks--; updateCursorBackend(); @@ -261,7 +261,7 @@ void CPointerManager::resetCursorImage(bool apply) { damageIfSoftware(); if (currentCursorImage.surface) { - for (auto& m : g_pCompositor->m_vMonitors) { + for (auto const& m : g_pCompositor->m_vMonitors) { currentCursorImage.surface->resource()->leave(m); } @@ -306,7 +306,7 @@ void CPointerManager::resetCursorImage(bool apply) { void CPointerManager::updateCursorBackend() { static auto PNOHW = CConfigValue("cursor:no_hardware_cursors"); - for (auto& m : g_pCompositor->m_vMonitors) { + for (auto const& m : g_pCompositor->m_vMonitors) { auto state = stateFor(m); if (!m->m_bEnabled || !m->dpmsStatus) { @@ -600,7 +600,7 @@ Vector2D CPointerManager::closestValid(const Vector2D& pos) { // static auto INSIDE_LAYOUT = [this](const CBox& box) -> bool { - for (auto& b : currentMonitorLayout.monitorBoxes) { + for (auto const& b : currentMonitorLayout.monitorBoxes) { if (box.inside(b)) return true; } @@ -608,7 +608,7 @@ Vector2D CPointerManager::closestValid(const Vector2D& pos) { }; static auto INSIDE_LAYOUT_COORD = [this](const Vector2D& vec) -> bool { - for (auto& b : currentMonitorLayout.monitorBoxes) { + for (auto const& b : currentMonitorLayout.monitorBoxes) { if (b.containsPoint(vec)) return true; } @@ -619,7 +619,7 @@ Vector2D CPointerManager::closestValid(const Vector2D& pos) { Vector2D leader; float distanceSq = __FLT_MAX__; - for (auto& b : currentMonitorLayout.monitorBoxes) { + for (auto const& b : currentMonitorLayout.monitorBoxes) { auto p = b.closestPoint(vec); auto distSq = p.distanceSq(vec); @@ -673,7 +673,7 @@ void CPointerManager::damageIfSoftware() { static auto PNOHW = CConfigValue("cursor:no_hardware_cursors"); - for (auto& mw : monitorStates) { + for (auto const& mw : monitorStates) { if (mw->monitor.expired()) continue; @@ -748,7 +748,7 @@ void CPointerManager::warpAbsolute(Vector2D abs, SP dev) { if (POINTER->boundOutput == "entire") { // find x and y size of the entire space Vector2D bottomRight = {-9999999, -9999999}, topLeft = {9999999, 9999999}; - for (auto& m : g_pCompositor->m_vMonitors) { + for (auto const& m : g_pCompositor->m_vMonitors) { const auto EXTENT = m->logicalBox().extent(); const auto POS = m->logicalBox().pos(); if (EXTENT.x > bottomRight.x) @@ -787,7 +787,7 @@ void CPointerManager::warpAbsolute(Vector2D abs, SP dev) { void CPointerManager::onMonitorLayoutChange() { currentMonitorLayout.monitorBoxes.clear(); - for (auto& m : g_pCompositor->m_vMonitors) { + for (auto const& m : g_pCompositor->m_vMonitors) { if (m->isMirror() || !m->m_bEnabled) continue; diff --git a/src/managers/ProtocolManager.cpp b/src/managers/ProtocolManager.cpp index 6e5cd16f..bace4451 100644 --- a/src/managers/ProtocolManager.cpp +++ b/src/managers/ProtocolManager.cpp @@ -151,7 +151,7 @@ CProtocolManager::CProtocolManager() { PROTO::toplevelExport = std::make_unique(&hyprland_toplevel_export_manager_v1_interface, 2, "ToplevelExport"); PROTO::globalShortcuts = std::make_unique(&hyprland_global_shortcuts_manager_v1_interface, 1, "GlobalShortcuts"); - for (auto& b : g_pCompositor->m_pAqBackend->getImplementations()) { + for (auto const& b : g_pCompositor->m_pAqBackend->getImplementations()) { if (b->type() != Aquamarine::AQ_BACKEND_DRM) continue; diff --git a/src/managers/SeatManager.cpp b/src/managers/SeatManager.cpp index e296dcc8..3e4063f4 100644 --- a/src/managers/SeatManager.cpp +++ b/src/managers/SeatManager.cpp @@ -483,7 +483,7 @@ void CSeatManager::refocusGrab() { if (seatGrab->surfs.size() > 0) { // try to find a surf in focus first const auto MOUSE = g_pInputManager->getMouseCoordsInternal(); - for (auto& s : seatGrab->surfs) { + for (auto const& s : seatGrab->surfs) { auto hlSurf = CWLSurface::fromResource(s.lock()); if (!hlSurf) continue; diff --git a/src/managers/SessionLockManager.cpp b/src/managers/SessionLockManager.cpp index 86108cac..81e22889 100644 --- a/src/managers/SessionLockManager.cpp +++ b/src/managers/SessionLockManager.cpp @@ -67,7 +67,7 @@ void CSessionLockManager::onNewSessionLock(SP pLock) { m_pSessionLock.reset(); g_pInputManager->refocus(); - for (auto& m : g_pCompositor->m_vMonitors) + for (auto const& m : g_pCompositor->m_vMonitors) g_pHyprRenderer->damageMonitor(m.get()); }); @@ -75,7 +75,7 @@ void CSessionLockManager::onNewSessionLock(SP pLock) { m_pSessionLock.reset(); g_pCompositor->focusSurface(nullptr); - for (auto& m : g_pCompositor->m_vMonitors) + for (auto const& m : g_pCompositor->m_vMonitors) g_pHyprRenderer->damageMonitor(m.get()); }); @@ -90,7 +90,7 @@ SSessionLockSurface* CSessionLockManager::getSessionLockSurfaceForMonitor(uint64 if (!m_pSessionLock) return nullptr; - for (auto& sls : m_pSessionLock->vSessionLockSurfaces) { + for (auto const& sls : m_pSessionLock->vSessionLockSurfaces) { if (sls->iMonitorID == id) { if (sls->mapped) return sls.get(); diff --git a/src/managers/XCursorManager.cpp b/src/managers/XCursorManager.cpp index 6f000f9f..7fc21a28 100644 --- a/src/managers/XCursorManager.cpp +++ b/src/managers/XCursorManager.cpp @@ -304,7 +304,7 @@ std::unordered_set CXCursorManager::themePaths(std::string const& t scanTheme(theme); while (!inherits.empty()) { auto oldInherits = inherits; - for (auto& i : oldInherits) + for (auto const& i : oldInherits) scanTheme(i); if (oldInherits.size() == inherits.size()) diff --git a/src/managers/XWaylandManager.cpp b/src/managers/XWaylandManager.cpp index 4654eeb7..b37e796b 100644 --- a/src/managers/XWaylandManager.cpp +++ b/src/managers/XWaylandManager.cpp @@ -255,7 +255,7 @@ Vector2D CHyprXWaylandManager::xwaylandToWaylandCoords(const Vector2D& coord) { CMonitor* pMonitor = nullptr; double bestDistance = __FLT_MAX__; - for (auto& m : g_pCompositor->m_vMonitors) { + for (auto const& m : g_pCompositor->m_vMonitors) { const auto SIZ = *PXWLFORCESCALEZERO ? m->vecTransformedSize : m->vecSize; double distance = diff --git a/src/managers/eventLoop/EventLoopManager.cpp b/src/managers/eventLoop/EventLoopManager.cpp index d1b85cf2..e9b0fa3e 100644 --- a/src/managers/eventLoop/EventLoopManager.cpp +++ b/src/managers/eventLoop/EventLoopManager.cpp @@ -19,7 +19,7 @@ CEventLoopManager::CEventLoopManager(wl_display* display, wl_event_loop* wlEvent } CEventLoopManager::~CEventLoopManager() { - for (auto& eventSource : m_sWayland.aqEventSources) { + for (auto const& eventSource : m_sWayland.aqEventSources) { wl_event_source_remove(eventSource); } @@ -46,7 +46,7 @@ void CEventLoopManager::enterLoop() { m_sWayland.eventSource = wl_event_loop_add_fd(m_sWayland.loop, m_sTimers.timerfd, WL_EVENT_READABLE, timerWrite, nullptr); aqPollFDs = g_pCompositor->m_pAqBackend->getPollFDs(); - for (auto& fd : aqPollFDs) { + for (auto const& fd : aqPollFDs) { m_sWayland.aqEventSources.emplace_back(wl_event_loop_add_fd(m_sWayland.loop, fd->fd, WL_EVENT_READABLE, aquamarineFDWrite, fd.get())); } @@ -56,7 +56,7 @@ void CEventLoopManager::enterLoop() { } void CEventLoopManager::onTimerFire() { - for (auto& t : m_sTimers.timers) { + for (auto const& t : m_sTimers.timers) { if (t.strongRef() > 1 /* if it's 1, it was lost. Don't call it. */ && t->passed() && !t->cancelled()) t->call(t); } @@ -93,7 +93,7 @@ void CEventLoopManager::nudgeTimers() { long nextTimerUs = 10 * 1000 * 1000; // 10s - for (auto& t : m_sTimers.timers) { + for (auto const& t : m_sTimers.timers) { if (const auto µs = t->leftUs(); µs < nextTimerUs) nextTimerUs = µs; } @@ -122,7 +122,7 @@ void CEventLoopManager::doLater(const std::function& fn) { auto cpy = IDLE->fns; IDLE->fns.clear(); IDLE->eventSource = nullptr; - for (auto& c : cpy) { + for (auto const& c : cpy) { if (c) c(); } diff --git a/src/managers/input/IdleInhibitor.cpp b/src/managers/input/IdleInhibitor.cpp index 4bcb4df3..a6f25142 100644 --- a/src/managers/input/IdleInhibitor.cpp +++ b/src/managers/input/IdleInhibitor.cpp @@ -49,7 +49,7 @@ void CInputManager::recheckIdleInhibitorStatus() { } // check manual user-set inhibitors - for (auto& w : g_pCompositor->m_vWindows) { + for (auto const& w : g_pCompositor->m_vWindows) { if (w->m_eIdleInhibitMode == IDLEINHIBIT_NONE) continue; diff --git a/src/managers/input/InputManager.cpp b/src/managers/input/InputManager.cpp index a4a63a84..6b04c13f 100644 --- a/src/managers/input/InputManager.cpp +++ b/src/managers/input/InputManager.cpp @@ -1033,7 +1033,7 @@ void CInputManager::setupMouse(SP mauz) { } void CInputManager::setPointerConfigs() { - for (auto& m : m_vPointers) { + for (auto const& m : m_vPointers) { auto devname = m->hlName; const auto HASCONFIG = g_pConfigManager->deviceConfigExists(devname); @@ -1268,7 +1268,7 @@ void CInputManager::updateKeyboardsLeds(SP pKeyboard) { if (!leds.has_value()) return; - for (auto& k : m_vKeyboards) { + for (auto const& k : m_vKeyboards) { k->updateLEDs(leds.value()); } } @@ -1402,7 +1402,7 @@ void CInputManager::unconstrainMouse() { if (g_pSeatManager->mouse.expired()) return; - for (auto& c : m_vConstraints) { + for (auto const& c : m_vConstraints) { const auto C = c.lock(); if (!C) @@ -1416,7 +1416,7 @@ void CInputManager::unconstrainMouse() { } bool CInputManager::isConstrained() { - for (auto& c : m_vConstraints) { + for (auto const& c : m_vConstraints) { const auto C = c.lock(); if (!C) @@ -1434,7 +1434,7 @@ bool CInputManager::isConstrained() { void CInputManager::updateCapabilities() { uint32_t caps = 0; - for (auto& h : m_vHIDs) { + for (auto const& h : m_vHIDs) { if (h.expired()) continue; @@ -1449,7 +1449,7 @@ uint32_t CInputManager::accumulateModsFromAllKBs() { uint32_t finalMask = 0; - for (auto& kb : m_vKeyboards) { + for (auto const& kb : m_vKeyboards) { if (kb->isVirtual() && shouldIgnoreVirtualKeyboard(kb)) continue; @@ -1464,7 +1464,7 @@ uint32_t CInputManager::accumulateModsFromAllKBs() { void CInputManager::disableAllKeyboards(bool virt) { - for (auto& k : m_vKeyboards) { + for (auto const& k : m_vKeyboards) { if (k->isVirtual() != virt) continue; @@ -1540,13 +1540,13 @@ void CInputManager::setTouchDeviceConfigs(SP dev) { return; } - for (auto& m : m_vTouches) { + for (auto const& m : m_vTouches) { setConfig(m); } } void CInputManager::setTabletConfigs() { - for (auto& t : m_vTablets) { + for (auto const& t : m_vTablets) { if (t->aq()->getLibinputHandle()) { const auto NAME = t->hlName; const auto LIBINPUTDEV = t->aq()->getLibinputHandle(); @@ -1711,7 +1711,7 @@ void CInputManager::setCursorIconOnBorder(PHLWINDOW w) { bool onDeco = false; - for (auto& wd : w->m_dWindowDecorations) { + for (auto const& wd : w->m_dWindowDecorations) { if (!(wd->getDecorationFlags() & DECORATION_ALLOWS_MOUSE_INPUT)) continue; diff --git a/src/managers/input/InputMethodRelay.cpp b/src/managers/input/InputMethodRelay.cpp index 7cfd54b4..1608e123 100644 --- a/src/managers/input/InputMethodRelay.cpp +++ b/src/managers/input/InputMethodRelay.cpp @@ -57,7 +57,7 @@ void CInputMethodRelay::onNewIME(SP pIME) { if (!g_pCompositor->m_pLastFocus) return; - for (auto& ti : m_vTextInputs) { + for (auto const& ti : m_vTextInputs) { if (ti->client() != g_pCompositor->m_pLastFocus->client()) continue; @@ -80,7 +80,7 @@ CTextInput* CInputMethodRelay::getFocusedTextInput() { if (!g_pCompositor->m_pLastFocus) return nullptr; - for (auto& ti : m_vTextInputs) { + for (auto const& ti : m_vTextInputs) { if (ti->focusedSurface() == g_pCompositor->m_pLastFocus) return ti.get(); } @@ -101,7 +101,7 @@ void CInputMethodRelay::removeTextInput(CTextInput* pInput) { } void CInputMethodRelay::updateAllPopups() { - for (auto& p : m_vIMEPopups) { + for (auto const& p : m_vIMEPopups) { p->onCommit(); } } @@ -138,7 +138,7 @@ void CInputMethodRelay::onKeyboardFocus(SP pSurface) { m_pLastKbFocus = pSurface; - for (auto& ti : m_vTextInputs) { + for (auto const& ti : m_vTextInputs) { if (!ti->focusedSurface()) continue; @@ -148,7 +148,7 @@ void CInputMethodRelay::onKeyboardFocus(SP pSurface) { if (!pSurface) return; - for (auto& ti : m_vTextInputs) { + for (auto const& ti : m_vTextInputs) { if (!ti->isV3()) continue; @@ -160,7 +160,7 @@ void CInputMethodRelay::onKeyboardFocus(SP pSurface) { } CInputPopup* CInputMethodRelay::popupFromCoords(const Vector2D& point) { - for (auto& p : m_vIMEPopups) { + for (auto const& p : m_vIMEPopups) { if (p->isVecInPopup(point)) return p.get(); } @@ -169,7 +169,7 @@ CInputPopup* CInputMethodRelay::popupFromCoords(const Vector2D& point) { } CInputPopup* CInputMethodRelay::popupFromSurface(const SP surface) { - for (auto& p : m_vIMEPopups) { + for (auto const& p : m_vIMEPopups) { if (p->getSurface() == surface) return p.get(); } diff --git a/src/managers/input/Tablets.cpp b/src/managers/input/Tablets.cpp index 23d328bc..f33937e8 100644 --- a/src/managers/input/Tablets.cpp +++ b/src/managers/input/Tablets.cpp @@ -229,7 +229,7 @@ void CInputManager::newTablet(SP pDevice) { SP CInputManager::ensureTabletToolPresent(SP pTool) { - for (auto& t : m_vTabletTools) { + for (auto const& t : m_vTabletTools) { if (t->aq() == pTool) return t; } diff --git a/src/plugins/PluginAPI.cpp b/src/plugins/PluginAPI.cpp index 398d4ce1..ef3ae06a 100644 --- a/src/plugins/PluginAPI.cpp +++ b/src/plugins/PluginAPI.cpp @@ -124,8 +124,8 @@ APICALL bool HyprlandAPI::removeWindowDecoration(HANDLE handle, IHyprWindowDecor if (!PLUGIN) return false; - for (auto& w : g_pCompositor->m_vWindows) { - for (auto& d : w->m_dWindowDecorations) { + for (auto const& w : g_pCompositor->m_vWindows) { + for (auto const& d : w->m_dWindowDecorations) { if (d.get() == pDecoration) { w->removeWindowDeco(pDecoration); return true; diff --git a/src/plugins/PluginSystem.cpp b/src/plugins/PluginSystem.cpp index 122faafd..0f1f97a2 100644 --- a/src/plugins/PluginSystem.cpp +++ b/src/plugins/PluginSystem.cpp @@ -98,27 +98,27 @@ void CPluginSystem::unloadPlugin(const CPlugin* plugin, bool eject) { exitFunc(); } - for (auto& [k, v] : plugin->registeredCallbacks) { + for (auto const& [k, v] : plugin->registeredCallbacks) { if (const auto SHP = v.lock()) g_pHookSystem->unhook(SHP); } const auto ls = plugin->registeredLayouts; - for (auto& l : ls) + for (auto const& l : ls) g_pLayoutManager->removeLayout(l); g_pFunctionHookSystem->removeAllHooksFrom(plugin->m_pHandle); const auto rd = plugin->registeredDecorations; - for (auto& d : rd) + for (auto const& d : rd) HyprlandAPI::removeWindowDecoration(plugin->m_pHandle, d); const auto rdi = plugin->registeredDispatchers; - for (auto& d : rdi) + for (auto const& d : rdi) HyprlandAPI::removeDispatcher(plugin->m_pHandle, d); const auto rhc = plugin->registeredHyprctlCommands; - for (auto& c : rhc) + for (auto const& c : rhc) HyprlandAPI::unregisterHyprCtlCommand(plugin->m_pHandle, c); g_pConfigManager->removePluginConfig(plugin->m_pHandle); @@ -139,7 +139,7 @@ void CPluginSystem::unloadPlugin(const CPlugin* plugin, bool eject) { } void CPluginSystem::unloadAllPlugins() { - for (auto& p : m_vLoadedPlugins | std::views::reverse) + for (auto const& p : m_vLoadedPlugins | std::views::reverse) unloadPlugin(p.get(), false); // Unload remaining plugins gracefully } @@ -147,7 +147,7 @@ std::vector CPluginSystem::updateConfigPlugins(const std::vector failures; // unload all plugins that are no longer present - for (auto& p : m_vLoadedPlugins | std::views::reverse) { + for (auto const& p : m_vLoadedPlugins | std::views::reverse) { if (p->m_bLoadedWithConfig && std::find(plugins.begin(), plugins.end(), p->path) == plugins.end()) { Debug::log(LOG, "Unloading plugin {} which is no longer present in config", p->path); unloadPlugin(p.get(), false); @@ -156,7 +156,7 @@ std::vector CPluginSystem::updateConfigPlugins(const std::vectorpath == path; }) == m_vLoadedPlugins.end()) { Debug::log(LOG, "Loading plugin {} which is now present in config", path); const auto plugin = loadPlugin(path); @@ -173,7 +173,7 @@ std::vector CPluginSystem::updateConfigPlugins(const std::vectorpath == path) return p.get(); } @@ -182,7 +182,7 @@ CPlugin* CPluginSystem::getPluginByPath(const std::string& path) { } CPlugin* CPluginSystem::getPluginByHandle(HANDLE handle) { - for (auto& p : m_vLoadedPlugins) { + for (auto const& p : m_vLoadedPlugins) { if (p->m_pHandle == handle) return p.get(); } diff --git a/src/protocols/DRMLease.cpp b/src/protocols/DRMLease.cpp index f906740c..37f2e2eb 100644 --- a/src/protocols/DRMLease.cpp +++ b/src/protocols/DRMLease.cpp @@ -14,7 +14,7 @@ CDRMLeaseResource::CDRMLeaseResource(SP resource_, SPparent; requested = request->requested; - for (auto& m : requested) { + for (auto const& m : requested) { if (!m->monitor || m->monitor->isBeingLeased) { LOGM(ERR, "Rejecting lease: no monitor or monitor is being leased for {}", (m->monitor ? m->monitor->szName : "null")); resource->sendFinished(); @@ -26,14 +26,14 @@ CDRMLeaseResource::CDRMLeaseResource(SP resource_, SPmonitor->szName); } return roll; }()); std::vector> outputs; - for (auto& m : requested) { + for (auto const& m : requested) { outputs.emplace_back(m->monitor->output); } @@ -184,7 +184,7 @@ CDRMLeaseDeviceResource::CDRMLeaseDeviceResource(SP resourc resource->sendDrmFd(fd); close(fd); - for (auto& m : PROTO::lease->primaryDevice->offeredOutputs) { + for (auto const& m : PROTO::lease->primaryDevice->offeredOutputs) { sendConnector(m.lock()); } @@ -234,7 +234,7 @@ CDRMLeaseDevice::CDRMLeaseDevice(SP drmBackend) : backe } CDRMLeaseProtocol::CDRMLeaseProtocol(const wl_interface* iface, const int& ver, const std::string& name) : IWaylandProtocol(iface, ver, name) { - for (auto& b : g_pCompositor->m_pAqBackend->getImplementations()) { + for (auto const& b : g_pCompositor->m_pAqBackend->getImplementations()) { if (b->type() != Aquamarine::AQ_BACKEND_DRM) continue; @@ -292,7 +292,7 @@ void CDRMLeaseProtocol::offer(SP monitor) { primaryDevice->offeredOutputs.emplace_back(monitor); - for (auto& m : m_vManagers) { + for (auto const& m : m_vManagers) { m->sendConnector(monitor); m->resource->sendDone(); } diff --git a/src/protocols/DataDeviceWlr.cpp b/src/protocols/DataDeviceWlr.cpp index dce64508..d2d06644 100644 --- a/src/protocols/DataDeviceWlr.cpp +++ b/src/protocols/DataDeviceWlr.cpp @@ -37,7 +37,7 @@ void CWLRDataOffer::sendData() { if (!source) return; - for (auto& m : source->mimes()) { + for (auto const& m : source->mimes()) { resource->sendOffer(m.c_str()); } } @@ -191,7 +191,7 @@ CWLRDataControlManagerResource::CWLRDataControlManagerResource(SPself = RESOURCE; device = RESOURCE; - for (auto& s : sources) { + for (auto const& s : sources) { if (!s) continue; s->device = RESOURCE; diff --git a/src/protocols/FocusGrab.cpp b/src/protocols/FocusGrab.cpp index 2d6b2ee2..aff232e4 100644 --- a/src/protocols/FocusGrab.cpp +++ b/src/protocols/FocusGrab.cpp @@ -103,7 +103,7 @@ void CFocusGrab::refocusKeyboard() { return; SP surface = nullptr; - for (auto& [surf, state] : m_mSurfaces) { + for (auto const& [surf, state] : m_mSurfaces) { if (state->state == CFocusGrabSurfaceState::Comitted) { surface = surf.lock(); break; diff --git a/src/protocols/ForeignToplevel.cpp b/src/protocols/ForeignToplevel.cpp index 59888ce2..1f8cbcbe 100644 --- a/src/protocols/ForeignToplevel.cpp +++ b/src/protocols/ForeignToplevel.cpp @@ -30,7 +30,7 @@ CForeignToplevelList::CForeignToplevelList(SP resourc LOGM(LOG, "CForeignToplevelList: finished"); }); - for (auto& w : g_pCompositor->m_vWindows) { + for (auto const& w : g_pCompositor->m_vWindows) { if (!w->m_bIsMapped || w->m_bFadingOut) continue; @@ -112,19 +112,19 @@ bool CForeignToplevelList::good() { CForeignToplevelProtocol::CForeignToplevelProtocol(const wl_interface* iface, const int& ver, const std::string& name) : IWaylandProtocol(iface, ver, name) { static auto P = g_pHookSystem->hookDynamic("openWindow", [this](void* self, SCallbackInfo& info, std::any data) { - for (auto& m : m_vManagers) { + for (auto const& m : m_vManagers) { m->onMap(std::any_cast(data)); } }); static auto P1 = g_pHookSystem->hookDynamic("closeWindow", [this](void* self, SCallbackInfo& info, std::any data) { - for (auto& m : m_vManagers) { + for (auto const& m : m_vManagers) { m->onUnmap(std::any_cast(data)); } }); static auto P2 = g_pHookSystem->hookDynamic("windowTitle", [this](void* self, SCallbackInfo& info, std::any data) { - for (auto& m : m_vManagers) { + for (auto const& m : m_vManagers) { m->onTitle(std::any_cast(data)); } }); diff --git a/src/protocols/ForeignToplevelWlr.cpp b/src/protocols/ForeignToplevelWlr.cpp index bd597a91..291969db 100644 --- a/src/protocols/ForeignToplevelWlr.cpp +++ b/src/protocols/ForeignToplevelWlr.cpp @@ -179,7 +179,7 @@ CForeignToplevelWlrManager::CForeignToplevelWlrManager(SPonManagerResourceDestroy(this); }); - for (auto& w : g_pCompositor->m_vWindows) { + for (auto const& w : g_pCompositor->m_vWindows) { if (!w->m_bIsMapped || w->m_bFadingOut) continue; @@ -313,42 +313,42 @@ bool CForeignToplevelWlrManager::good() { CForeignToplevelWlrProtocol::CForeignToplevelWlrProtocol(const wl_interface* iface, const int& ver, const std::string& name) : IWaylandProtocol(iface, ver, name) { static auto P = g_pHookSystem->hookDynamic("openWindow", [this](void* self, SCallbackInfo& info, std::any data) { const auto PWINDOW = std::any_cast(data); - for (auto& m : m_vManagers) { + for (auto const& m : m_vManagers) { m->onMap(PWINDOW); } }); static auto P1 = g_pHookSystem->hookDynamic("closeWindow", [this](void* self, SCallbackInfo& info, std::any data) { const auto PWINDOW = std::any_cast(data); - for (auto& m : m_vManagers) { + for (auto const& m : m_vManagers) { m->onUnmap(PWINDOW); } }); static auto P2 = g_pHookSystem->hookDynamic("windowTitle", [this](void* self, SCallbackInfo& info, std::any data) { const auto PWINDOW = std::any_cast(data); - for (auto& m : m_vManagers) { + for (auto const& m : m_vManagers) { m->onTitle(PWINDOW); } }); static auto P3 = g_pHookSystem->hookDynamic("activeWindow", [this](void* self, SCallbackInfo& info, std::any data) { const auto PWINDOW = std::any_cast(data); - for (auto& m : m_vManagers) { + for (auto const& m : m_vManagers) { m->onNewFocus(PWINDOW); } }); static auto P4 = g_pHookSystem->hookDynamic("moveWindow", [this](void* self, SCallbackInfo& info, std::any data) { const auto PWINDOW = std::any_cast(std::any_cast>(data).at(0)); - for (auto& m : m_vManagers) { + for (auto const& m : m_vManagers) { m->onMoveMonitor(PWINDOW); } }); static auto P5 = g_pHookSystem->hookDynamic("fullscreen", [this](void* self, SCallbackInfo& info, std::any data) { const auto PWINDOW = std::any_cast(data); - for (auto& m : m_vManagers) { + for (auto const& m : m_vManagers) { m->onFullscreen(PWINDOW); } }); @@ -374,7 +374,7 @@ void CForeignToplevelWlrProtocol::destroyHandle(CForeignToplevelHandleWlr* handl } PHLWINDOW CForeignToplevelWlrProtocol::windowFromHandleResource(wl_resource* res) { - for (auto& h : m_vHandles) { + for (auto const& h : m_vHandles) { if (h->res() != res) continue; diff --git a/src/protocols/FractionalScale.cpp b/src/protocols/FractionalScale.cpp index d39fa67c..d8010eac 100644 --- a/src/protocols/FractionalScale.cpp +++ b/src/protocols/FractionalScale.cpp @@ -24,7 +24,7 @@ void CFractionalScaleProtocol::onManagerResourceDestroy(wl_resource* res) { } void CFractionalScaleProtocol::onGetFractionalScale(CWpFractionalScaleManagerV1* pMgr, uint32_t id, SP surface) { - for (auto& [k, v] : m_mAddons) { + for (auto const& [k, v] : m_mAddons) { if (k == surface) { LOGM(ERR, "Surface {:x} already has a fractionalScale addon", (uintptr_t)surface.get()); pMgr->error(WP_FRACTIONAL_SCALE_MANAGER_V1_ERROR_FRACTIONAL_SCALE_EXISTS, "Fractional scale already exists"); diff --git a/src/protocols/GammaControl.cpp b/src/protocols/GammaControl.cpp index c902d00e..cb75a202 100644 --- a/src/protocols/GammaControl.cpp +++ b/src/protocols/GammaControl.cpp @@ -25,7 +25,7 @@ CGammaControl::CGammaControl(SP resource_, wl_resource* out return; } - for (auto& g : PROTO::gamma->m_vGammaControllers) { + for (auto const& g : PROTO::gamma->m_vGammaControllers) { if (g->pMonitor == pMonitor) { resource->sendFailed(); return; @@ -180,7 +180,7 @@ void CGammaControlProtocol::onGetGammaControl(CZwlrGammaControlManagerV1* pMgr, } void CGammaControlProtocol::applyGammaToState(CMonitor* pMonitor) { - for (auto& g : m_vGammaControllers) { + for (auto const& g : m_vGammaControllers) { if (g->getMonitor() != pMonitor) continue; diff --git a/src/protocols/GlobalShortcuts.cpp b/src/protocols/GlobalShortcuts.cpp index 92bfbae4..b02126ef 100644 --- a/src/protocols/GlobalShortcuts.cpp +++ b/src/protocols/GlobalShortcuts.cpp @@ -54,8 +54,8 @@ void CGlobalShortcutsProtocol::destroyResource(CShortcutClient* client) { } bool CGlobalShortcutsProtocol::isTaken(std::string appid, std::string trigger) { - for (auto& c : m_vClients) { - for (auto& sh : c->shortcuts) { + for (auto const& c : m_vClients) { + for (auto const& sh : c->shortcuts) { if (sh->appid == appid && sh->id == trigger) { return true; } @@ -66,8 +66,8 @@ bool CGlobalShortcutsProtocol::isTaken(std::string appid, std::string trigger) { } void CGlobalShortcutsProtocol::sendGlobalShortcutEvent(std::string appid, std::string trigger, bool pressed) { - for (auto& c : m_vClients) { - for (auto& sh : c->shortcuts) { + for (auto const& c : m_vClients) { + for (auto const& sh : c->shortcuts) { if (sh->appid == appid && sh->id == trigger) { timespec now; clock_gettime(CLOCK_MONOTONIC, &now); @@ -84,8 +84,8 @@ void CGlobalShortcutsProtocol::sendGlobalShortcutEvent(std::string appid, std::s std::vector CGlobalShortcutsProtocol::getAllShortcuts() { std::vector copy; - for (auto& c : m_vClients) { - for (auto& sh : c->shortcuts) { + for (auto const& c : m_vClients) { + for (auto const& sh : c->shortcuts) { copy.push_back(*sh); } } diff --git a/src/protocols/IdleNotify.cpp b/src/protocols/IdleNotify.cpp index 8d915ac6..3517a62d 100644 --- a/src/protocols/IdleNotify.cpp +++ b/src/protocols/IdleNotify.cpp @@ -86,14 +86,14 @@ void CIdleNotifyProtocol::onGetNotification(CExtIdleNotifierV1* pMgr, uint32_t i } void CIdleNotifyProtocol::onActivity() { - for (auto& n : m_vNotifications) { + for (auto const& n : m_vNotifications) { n->onActivity(); } } void CIdleNotifyProtocol::setInhibit(bool inhibited) { isInhibited = inhibited; - for (auto& n : m_vNotifications) { + for (auto const& n : m_vNotifications) { n->onActivity(); } } \ No newline at end of file diff --git a/src/protocols/InputMethodV2.cpp b/src/protocols/InputMethodV2.cpp index a0820e0b..5fd1e893 100644 --- a/src/protocols/InputMethodV2.cpp +++ b/src/protocols/InputMethodV2.cpp @@ -268,7 +268,7 @@ wl_client* CInputMethodV2::grabClient() { if (grabs.empty()) return nullptr; - for (auto& gw : grabs) { + for (auto const& gw : grabs) { auto g = gw.lock(); if (!g) @@ -282,7 +282,7 @@ wl_client* CInputMethodV2::grabClient() { void CInputMethodV2::sendInputRectangle(const CBox& box) { inputRectangle = box; - for (auto& wp : popups) { + for (auto const& wp : popups) { auto p = wp.lock(); if (!p) @@ -293,7 +293,7 @@ void CInputMethodV2::sendInputRectangle(const CBox& box) { } void CInputMethodV2::sendKey(uint32_t time, uint32_t key, wl_keyboard_key_state state) { - for (auto& gw : grabs) { + for (auto const& gw : grabs) { auto g = gw.lock(); if (!g) @@ -304,7 +304,7 @@ void CInputMethodV2::sendKey(uint32_t time, uint32_t key, wl_keyboard_key_state } void CInputMethodV2::sendMods(uint32_t depressed, uint32_t latched, uint32_t locked, uint32_t group) { - for (auto& gw : grabs) { + for (auto const& gw : grabs) { auto g = gw.lock(); if (!g) @@ -315,7 +315,7 @@ void CInputMethodV2::sendMods(uint32_t depressed, uint32_t latched, uint32_t loc } void CInputMethodV2::setKeyboard(SP keyboard) { - for (auto& gw : grabs) { + for (auto const& gw : grabs) { auto g = gw.lock(); if (!g) diff --git a/src/protocols/LinuxDMABUF.cpp b/src/protocols/LinuxDMABUF.cpp index 32625792..d9dd1d01 100644 --- a/src/protocols/LinuxDMABUF.cpp +++ b/src/protocols/LinuxDMABUF.cpp @@ -31,8 +31,8 @@ CDMABUFFormatTable::CDMABUFFormatTable(SDMABUFTranche _rendererTranche, std::vec size_t i = 0; rendererTranche.indicies.clear(); - for (auto& fmt : rendererTranche.formats) { - for (auto& mod : fmt.modifiers) { + for (auto const& fmt : rendererTranche.formats) { + for (auto const& mod : fmt.modifiers) { auto format = std::make_pair<>(fmt.drmFormat, mod); auto [_, inserted] = formats.insert(format); if (inserted) { @@ -53,8 +53,8 @@ CDMABUFFormatTable::CDMABUFFormatTable(SDMABUFTranche _rendererTranche, std::vec for (auto& [monitor, tranche] : monitorTranches) { tranche.indicies.clear(); - for (auto& fmt : tranche.formats) { - for (auto& mod : fmt.modifiers) { + for (auto const& fmt : tranche.formats) { + for (auto const& mod : fmt.modifiers) { // apparently these can implode on planes, so dont use them if (mod == DRM_FORMAT_MOD_INVALID || mod == DRM_FORMAT_MOD_LINEAR) continue; @@ -270,7 +270,7 @@ bool CLinuxDMABBUFParamsResource::verify() { } bool empty = false; - for (auto& plane : attrs->fds) { + for (auto const& plane : attrs->fds) { if (empty && plane != -1) { resource->error(ZWP_LINUX_BUFFER_PARAMS_V1_ERROR_INVALID_FORMAT, "Gap in planes"); return false; @@ -402,8 +402,8 @@ bool CLinuxDMABUFResource::good() { } void CLinuxDMABUFResource::sendMods() { - for (auto& fmt : PROTO::linuxDma->formatTable->rendererTranche.formats) { - for (auto& mod : fmt.modifiers) { + for (auto const& fmt : PROTO::linuxDma->formatTable->rendererTranche.formats) { + for (auto const& mod : fmt.modifiers) { if (resource->version() < 3) { if (mod == DRM_FORMAT_MOD_INVALID || mod == DRM_FORMAT_MOD_LINEAR) resource->sendFormat(fmt.drmFormat); @@ -442,7 +442,7 @@ CLinuxDMABufV1Protocol::CLinuxDMABufV1Protocol(const wl_interface* iface, const // this assumes there's only 1 device used for both scanout and rendering // also that each monitor never changes its primary plane - for (auto& mon : g_pCompositor->m_vMonitors) { + for (auto const& mon : g_pCompositor->m_vMonitors) { auto tranche = SDMABUFTranche{ .device = mainDevice, .flags = ZWP_LINUX_DMABUF_FEEDBACK_V1_TRANCHE_FLAGS_SCANOUT, @@ -505,7 +505,7 @@ void CLinuxDMABufV1Protocol::resetFormatTable() { // this might be a big copy auto newFormatTable = std::make_unique(formatTable->rendererTranche, formatTable->monitorTranches); - for (auto& feedback : m_vFeedbacks) { + for (auto const& feedback : m_vFeedbacks) { feedback->resource->sendFormatTable(newFormatTable->tableFD, newFormatTable->tableSize); if (feedback->lastFeedbackWasScanout) { SP mon; @@ -562,7 +562,7 @@ void CLinuxDMABufV1Protocol::destroyResource(CLinuxDMABuffer* resource) { void CLinuxDMABufV1Protocol::updateScanoutTranche(SP surface, SP pMonitor) { SP feedbackResource; - for (auto& f : m_vFeedbacks) { + for (auto const& f : m_vFeedbacks) { if (f->surface != surface) continue; diff --git a/src/protocols/MesaDRM.cpp b/src/protocols/MesaDRM.cpp index 9fcd5f9b..b4efd2c8 100644 --- a/src/protocols/MesaDRM.cpp +++ b/src/protocols/MesaDRM.cpp @@ -60,11 +60,11 @@ CMesaDRMResource::CMesaDRMResource(SP resource_) : resource(resource_) { uint64_t mod = DRM_FORMAT_MOD_INVALID; auto fmts = g_pHyprOpenGL->getDRMFormats(); - for (auto& f : fmts) { + for (auto const& f : fmts) { if (f.drmFormat != fmt) continue; - for (auto& m : f.modifiers) { + for (auto const& m : f.modifiers) { if (m == DRM_FORMAT_MOD_LINEAR) continue; @@ -100,7 +100,7 @@ CMesaDRMResource::CMesaDRMResource(SP resource_) : resource(resource_) { resource->sendCapabilities(WL_DRM_CAPABILITY_PRIME); auto fmts = g_pHyprOpenGL->getDRMFormats(); - for (auto& fmt : fmts) { + for (auto const& fmt : fmts) { resource->sendFormat(fmt.drmFormat); } } diff --git a/src/protocols/OutputManagement.cpp b/src/protocols/OutputManagement.cpp index cfe388fa..09552b19 100644 --- a/src/protocols/OutputManagement.cpp +++ b/src/protocols/OutputManagement.cpp @@ -28,7 +28,7 @@ COutputManager::COutputManager(SP resource_) : resource(re }); // send all heads at start - for (auto& m : g_pCompositor->m_vRealMonitors) { + for (auto const& m : g_pCompositor->m_vRealMonitors) { if (m.get() == g_pCompositor->m_pUnsafeOutput) continue; @@ -67,7 +67,7 @@ void COutputManager::ensureMonitorSent(CMonitor* pMonitor) { if (pMonitor == g_pCompositor->m_pUnsafeOutput) return; - for (auto& hw : heads) { + for (auto const& hw : heads) { auto h = hw.lock(); if (!h) @@ -96,7 +96,7 @@ COutputHead::COutputHead(SP resource_, CMonitor* pMonitor_) : listeners.monitorDestroy = pMonitor->events.destroy.registerListener([this](std::any d) { resource->sendFinished(); - for (auto& mw : modes) { + for (auto const& mw : modes) { auto m = mw.lock(); if (!m) @@ -106,7 +106,7 @@ COutputHead::COutputHead(SP resource_, CMonitor* pMonitor_) : } pMonitor = nullptr; - for (auto& m : PROTO::outputManagement->m_vManagers) { + for (auto const& m : PROTO::outputManagement->m_vManagers) { m->sendDone(); } }); @@ -147,7 +147,7 @@ void COutputHead::sendAllData() { if (modes.empty()) { if (!pMonitor->output->modes.empty()) { - for (auto& m : pMonitor->output->modes) { + for (auto const& m : pMonitor->output->modes) { makeAndSendNewMode(m); } } else if (pMonitor->output->state->state().customMode) { @@ -158,7 +158,7 @@ void COutputHead::sendAllData() { // send current mode if (pMonitor->m_bEnabled) { - for (auto& mw : modes) { + for (auto const& mw : modes) { auto m = mw.lock(); if (!m) @@ -189,7 +189,7 @@ void COutputHead::updateMode() { resource->sendAdaptiveSync(pMonitor->vrrActive ? ZWLR_OUTPUT_HEAD_V1_ADAPTIVE_SYNC_STATE_ENABLED : ZWLR_OUTPUT_HEAD_V1_ADAPTIVE_SYNC_STATE_DISABLED); if (pMonitor->m_bEnabled) { - for (auto& mw : modes) { + for (auto const& mw : modes) { auto m = mw.lock(); if (!m) @@ -346,7 +346,7 @@ bool COutputConfiguration::applyTestConfiguration(bool test) { LOGM(LOG, "Applying configuration"); - for (auto& headw : heads) { + for (auto const& headw : heads) { auto head = headw.lock(); if (!head) @@ -577,15 +577,15 @@ void COutputManagementProtocol::destroyResource(COutputConfigurationHead* resour } void COutputManagementProtocol::updateAllOutputs() { - for (auto& m : g_pCompositor->m_vRealMonitors) { - for (auto& mgr : m_vManagers) { + for (auto const& m : g_pCompositor->m_vRealMonitors) { + for (auto const& mgr : m_vManagers) { mgr->ensureMonitorSent(m.get()); } } } SP COutputManagementProtocol::headFromResource(wl_resource* r) { - for (auto& h : m_vHeads) { + for (auto const& h : m_vHeads) { if (h->resource->resource() == r) return h; } @@ -594,7 +594,7 @@ SP COutputManagementProtocol::headFromResource(wl_resource* r) { } SP COutputManagementProtocol::modeFromResource(wl_resource* r) { - for (auto& h : m_vModes) { + for (auto const& h : m_vModes) { if (h->resource->resource() == r) return h; } diff --git a/src/protocols/PointerGestures.cpp b/src/protocols/PointerGestures.cpp index c83e3887..4eb74102 100644 --- a/src/protocols/PointerGestures.cpp +++ b/src/protocols/PointerGestures.cpp @@ -111,7 +111,7 @@ void CPointerGesturesProtocol::swipeBegin(uint32_t timeMs, uint32_t fingers) { const auto SERIAL = g_pSeatManager->nextSerial(g_pSeatManager->state.pointerFocusResource.lock()); - for (auto& sw : m_vSwipes) { + for (auto const& sw : m_vSwipes) { if (sw->resource->client() != FOCUSEDCLIENT) continue; @@ -125,7 +125,7 @@ void CPointerGesturesProtocol::swipeUpdate(uint32_t timeMs, const Vector2D& delt const auto FOCUSEDCLIENT = g_pSeatManager->state.pointerFocusResource->client(); - for (auto& sw : m_vSwipes) { + for (auto const& sw : m_vSwipes) { if (sw->resource->client() != FOCUSEDCLIENT) continue; @@ -141,7 +141,7 @@ void CPointerGesturesProtocol::swipeEnd(uint32_t timeMs, bool cancelled) { const auto SERIAL = g_pSeatManager->nextSerial(g_pSeatManager->state.pointerFocusResource.lock()); - for (auto& sw : m_vSwipes) { + for (auto const& sw : m_vSwipes) { if (sw->resource->client() != FOCUSEDCLIENT) continue; @@ -157,7 +157,7 @@ void CPointerGesturesProtocol::pinchBegin(uint32_t timeMs, uint32_t fingers) { const auto SERIAL = g_pSeatManager->nextSerial(g_pSeatManager->state.pointerFocusResource.lock()); - for (auto& sw : m_vPinches) { + for (auto const& sw : m_vPinches) { if (sw->resource->client() != FOCUSEDCLIENT) continue; @@ -171,7 +171,7 @@ void CPointerGesturesProtocol::pinchUpdate(uint32_t timeMs, const Vector2D& delt const auto FOCUSEDCLIENT = g_pSeatManager->state.pointerFocusResource->client(); - for (auto& sw : m_vPinches) { + for (auto const& sw : m_vPinches) { if (sw->resource->client() != FOCUSEDCLIENT) continue; @@ -187,7 +187,7 @@ void CPointerGesturesProtocol::pinchEnd(uint32_t timeMs, bool cancelled) { const auto SERIAL = g_pSeatManager->nextSerial(g_pSeatManager->state.pointerFocusResource.lock()); - for (auto& sw : m_vPinches) { + for (auto const& sw : m_vPinches) { if (sw->resource->client() != FOCUSEDCLIENT) continue; @@ -203,7 +203,7 @@ void CPointerGesturesProtocol::holdBegin(uint32_t timeMs, uint32_t fingers) { const auto SERIAL = g_pSeatManager->nextSerial(g_pSeatManager->state.pointerFocusResource.lock()); - for (auto& sw : m_vHolds) { + for (auto const& sw : m_vHolds) { if (sw->resource->client() != FOCUSEDCLIENT) continue; @@ -219,7 +219,7 @@ void CPointerGesturesProtocol::holdEnd(uint32_t timeMs, bool cancelled) { const auto SERIAL = g_pSeatManager->nextSerial(g_pSeatManager->state.pointerFocusResource.lock()); - for (auto& sw : m_vHolds) { + for (auto const& sw : m_vHolds) { if (sw->resource->client() != FOCUSEDCLIENT) continue; diff --git a/src/protocols/PresentationTime.cpp b/src/protocols/PresentationTime.cpp index 638435c7..b1108042 100644 --- a/src/protocols/PresentationTime.cpp +++ b/src/protocols/PresentationTime.cpp @@ -114,11 +114,11 @@ void CPresentationProtocol::onPresented(CMonitor* pMonitor, timespec* when, uint when = &now; } - for (auto& feedback : m_vFeedbacks) { + for (auto const& feedback : m_vFeedbacks) { if (!feedback->surface) continue; - for (auto& data : m_vQueue) { + for (auto const& data : m_vQueue) { if (!data->surface || data->surface != feedback->surface) continue; diff --git a/src/protocols/PrimarySelection.cpp b/src/protocols/PrimarySelection.cpp index 4fede706..f1db2d65 100644 --- a/src/protocols/PrimarySelection.cpp +++ b/src/protocols/PrimarySelection.cpp @@ -38,7 +38,7 @@ void CPrimarySelectionOffer::sendData() { if (!source) return; - for (auto& m : source->mimes()) { + for (auto const& m : source->mimes()) { resource->sendOffer(m.c_str()); } } @@ -177,7 +177,7 @@ CPrimarySelectionManager::CPrimarySelectionManager(SPself = RESOURCE; device = RESOURCE; - for (auto& s : sources) { + for (auto const& s : sources) { if (!s) continue; s->device = RESOURCE; @@ -272,7 +272,7 @@ void CPrimarySelectionProtocol::sendSelectionToDevice(SP source) { - for (auto& o : m_vOffers) { + for (auto const& o : m_vOffers) { if (o->source && o->source->hasDnd()) continue; o->dead = true; @@ -321,7 +321,7 @@ void CPrimarySelectionProtocol::updateSelection() { } void CPrimarySelectionProtocol::onPointerFocus() { - for (auto& o : m_vOffers) { + for (auto const& o : m_vOffers) { o->dead = true; } diff --git a/src/protocols/RelativePointer.cpp b/src/protocols/RelativePointer.cpp index e4818758..16248c02 100644 --- a/src/protocols/RelativePointer.cpp +++ b/src/protocols/RelativePointer.cpp @@ -65,7 +65,7 @@ void CRelativePointerProtocol::sendRelativeMotion(uint64_t time, const Vector2D& const auto FOCUSED = g_pSeatManager->state.pointerFocusResource->client(); - for (auto& rp : m_vRelativePointers) { + for (auto const& rp : m_vRelativePointers) { if (FOCUSED != rp->client()) continue; diff --git a/src/protocols/Screencopy.cpp b/src/protocols/Screencopy.cpp index 1559476b..63024541 100644 --- a/src/protocols/Screencopy.cpp +++ b/src/protocols/Screencopy.cpp @@ -155,7 +155,7 @@ void CScreencopyFrame::copy(CZwlrScreencopyFrameV1* pFrame, wl_resource* buffer_ lockedSWCursors = true; // TODO: make it per-monitor if (!PROTO::screencopy->m_bTimerArmed) { - for (auto& m : g_pCompositor->m_vMonitors) { + for (auto const& m : g_pCompositor->m_vMonitors) { g_pPointerManager->lockSoftwareForMonitor(m); } PROTO::screencopy->m_bTimerArmed = true; @@ -365,7 +365,7 @@ CScreencopyProtocol::CScreencopyProtocol(const wl_interface* iface, const int& v std::nullopt, [this](SP self, void* data) { // TODO: make it per-monitor - for (auto& m : g_pCompositor->m_vMonitors) { + for (auto const& m : g_pCompositor->m_vMonitors) { g_pPointerManager->unlockSoftwareForMonitor(m); } m_bTimerArmed = false; @@ -411,7 +411,7 @@ void CScreencopyProtocol::onOutputCommit(CMonitor* pMonitor) { std::vector> framesToRemove; // share frame if correct output - for (auto& f : m_vFramesAwaitingWrite) { + for (auto const& f : m_vFramesAwaitingWrite) { if (!f->pMonitor || !f->buffer) { framesToRemove.push_back(f); continue; @@ -428,7 +428,7 @@ void CScreencopyProtocol::onOutputCommit(CMonitor* pMonitor) { framesToRemove.push_back(f); } - for (auto& f : framesToRemove) { + for (auto const& f : framesToRemove) { destroyResource(f.get()); } } diff --git a/src/protocols/SessionLock.cpp b/src/protocols/SessionLock.cpp index fe44face..b1f701bf 100644 --- a/src/protocols/SessionLock.cpp +++ b/src/protocols/SessionLock.cpp @@ -187,7 +187,7 @@ void CSessionLockProtocol::onGetLockSurface(CExtSessionLockV1* lock, uint32_t id auto PMONITOR = CWLOutputResource::fromResource(output)->monitor.get(); SP sessionLock; - for (auto& l : m_vLocks) { + for (auto const& l : m_vLocks) { if (l->resource.get() == lock) { sessionLock = l; break; diff --git a/src/protocols/ShortcutsInhibit.cpp b/src/protocols/ShortcutsInhibit.cpp index e4424ed7..308b385d 100644 --- a/src/protocols/ShortcutsInhibit.cpp +++ b/src/protocols/ShortcutsInhibit.cpp @@ -48,7 +48,7 @@ void CKeyboardShortcutsInhibitProtocol::onInhibit(CZwpKeyboardShortcutsInhibitMa SP surf = CWLSurfaceResource::fromResource(surface); const auto CLIENT = pMgr->client(); - for (auto& in : m_vInhibitors) { + for (auto const& in : m_vInhibitors) { if (in->surface() != surf) continue; @@ -74,7 +74,7 @@ bool CKeyboardShortcutsInhibitProtocol::isInhibited() { if (const auto PWINDOW = g_pCompositor->getWindowFromSurface(g_pCompositor->m_pLastFocus.lock()); PWINDOW && PWINDOW->m_sWindowData.noShortcutsInhibit.valueOrDefault()) return false; - for (auto& in : m_vInhibitors) { + for (auto const& in : m_vInhibitors) { if (in->surface() != g_pCompositor->m_pLastFocus) continue; diff --git a/src/protocols/Tablet.cpp b/src/protocols/Tablet.cpp index b974152e..d7f741b9 100644 --- a/src/protocols/Tablet.cpp +++ b/src/protocols/Tablet.cpp @@ -96,7 +96,7 @@ bool CTabletPadV2Resource::good() { void CTabletPadV2Resource::sendData() { // this is dodgy as fuck. I hate wl_array. it's expanded wl_array_for_each because C++ would complain about the implicit casts - for (auto& p : pad->aq()->paths) { + for (auto const& p : pad->aq()->paths) { resource->sendPath(p.c_str()); } @@ -140,7 +140,7 @@ void CTabletV2Resource::sendData() { resource->sendName(tablet->deviceName.c_str()); resource->sendId(tablet->aq()->usbVendorID, tablet->aq()->usbProductID); - for (auto& p : tablet->aq()->paths) { + for (auto const& p : tablet->aq()->paths) { resource->sendPath(p.c_str()); } @@ -287,21 +287,21 @@ void CTabletSeat::sendTablet(SP tablet) { } void CTabletSeat::sendData() { - for (auto& tw : PROTO::tablet->tablets) { + for (auto const& tw : PROTO::tablet->tablets) { if (tw.expired()) continue; sendTablet(tw.lock()); } - for (auto& tw : PROTO::tablet->tools) { + for (auto const& tw : PROTO::tablet->tools) { if (tw.expired()) continue; sendTool(tw.lock()); } - for (auto& tw : PROTO::tablet->pads) { + for (auto const& tw : PROTO::tablet->pads) { if (tw.expired()) continue; @@ -367,7 +367,7 @@ void CTabletV2Protocol::onGetSeat(CZwpTabletManagerV2* pMgr, uint32_t id, wl_res } void CTabletV2Protocol::registerDevice(SP tablet) { - for (auto& s : m_vSeats) { + for (auto const& s : m_vSeats) { s->sendTablet(tablet); } @@ -375,7 +375,7 @@ void CTabletV2Protocol::registerDevice(SP tablet) { } void CTabletV2Protocol::registerDevice(SP tool) { - for (auto& s : m_vSeats) { + for (auto const& s : m_vSeats) { s->sendTool(tool); } @@ -383,7 +383,7 @@ void CTabletV2Protocol::registerDevice(SP tool) { } void CTabletV2Protocol::registerDevice(SP pad) { - for (auto& s : m_vSeats) { + for (auto const& s : m_vSeats) { s->sendPad(pad); } @@ -391,7 +391,7 @@ void CTabletV2Protocol::registerDevice(SP pad) { } void CTabletV2Protocol::unregisterDevice(SP tablet) { - for (auto& t : m_vTablets) { + for (auto const& t : m_vTablets) { if (t->tablet == tablet) { t->resource->sendRemoved(); t->inert = true; @@ -401,7 +401,7 @@ void CTabletV2Protocol::unregisterDevice(SP tablet) { } void CTabletV2Protocol::unregisterDevice(SP tool) { - for (auto& t : m_vTools) { + for (auto const& t : m_vTools) { if (t->tool == tool) { t->resource->sendRemoved(); t->inert = true; @@ -411,7 +411,7 @@ void CTabletV2Protocol::unregisterDevice(SP tool) { } void CTabletV2Protocol::unregisterDevice(SP pad) { - for (auto& t : m_vPads) { + for (auto const& t : m_vPads) { if (t->pad == pad) { t->resource->sendRemoved(); t->inert = true; @@ -426,7 +426,7 @@ void CTabletV2Protocol::recheckRegisteredDevices() { std::erase_if(pads, [](const auto& e) { return e.expired(); }); // now we need to send removed events - for (auto& t : m_vTablets) { + for (auto const& t : m_vTablets) { if (!t->tablet.expired() || t->inert) continue; @@ -434,7 +434,7 @@ void CTabletV2Protocol::recheckRegisteredDevices() { t->inert = true; } - for (auto& t : m_vTools) { + for (auto const& t : m_vTools) { if (!t->tool.expired() || t->inert) continue; @@ -448,7 +448,7 @@ void CTabletV2Protocol::recheckRegisteredDevices() { t->inert = true; } - for (auto& t : m_vPads) { + for (auto const& t : m_vPads) { if (!t->pad.expired() || t->inert) continue; @@ -458,7 +458,7 @@ void CTabletV2Protocol::recheckRegisteredDevices() { } void CTabletV2Protocol::pressure(SP tool, double value) { - for (auto& t : m_vTools) { + for (auto const& t : m_vTools) { if (t->tool != tool || !t->current) continue; @@ -468,7 +468,7 @@ void CTabletV2Protocol::pressure(SP tool, double value) { } void CTabletV2Protocol::distance(SP tool, double value) { - for (auto& t : m_vTools) { + for (auto const& t : m_vTools) { if (t->tool != tool || !t->current) continue; @@ -478,7 +478,7 @@ void CTabletV2Protocol::distance(SP tool, double value) { } void CTabletV2Protocol::rotation(SP tool, double value) { - for (auto& t : m_vTools) { + for (auto const& t : m_vTools) { if (t->tool != tool || !t->current) continue; @@ -488,7 +488,7 @@ void CTabletV2Protocol::rotation(SP tool, double value) { } void CTabletV2Protocol::slider(SP tool, double value) { - for (auto& t : m_vTools) { + for (auto const& t : m_vTools) { if (t->tool != tool || !t->current) continue; @@ -498,7 +498,7 @@ void CTabletV2Protocol::slider(SP tool, double value) { } void CTabletV2Protocol::wheel(SP tool, double value) { - for (auto& t : m_vTools) { + for (auto const& t : m_vTools) { if (t->tool != tool || !t->current) continue; @@ -508,7 +508,7 @@ void CTabletV2Protocol::wheel(SP tool, double value) { } void CTabletV2Protocol::tilt(SP tool, const Vector2D& value) { - for (auto& t : m_vTools) { + for (auto const& t : m_vTools) { if (t->tool != tool || !t->current) continue; @@ -518,7 +518,7 @@ void CTabletV2Protocol::tilt(SP tool, const Vector2D& value) { } void CTabletV2Protocol::up(SP tool) { - for (auto& t : m_vTools) { + for (auto const& t : m_vTools) { if (t->tool != tool || !t->current) continue; @@ -528,7 +528,7 @@ void CTabletV2Protocol::up(SP tool) { } void CTabletV2Protocol::down(SP tool) { - for (auto& t : m_vTools) { + for (auto const& t : m_vTools) { if (t->tool != tool || !t->current) continue; @@ -545,7 +545,7 @@ void CTabletV2Protocol::proximityIn(SP tool, SP tablet, SP SP toolResource; SP tabletResource; - for (auto& t : m_vTools) { + for (auto const& t : m_vTools) { if (t->tool != tool || t->resource->client() != CLIENT) continue; @@ -559,7 +559,7 @@ void CTabletV2Protocol::proximityIn(SP tool, SP tablet, SP toolResource = t; - for (auto& tab : m_vTablets) { + for (auto const& tab : m_vTablets) { if (tab->tablet != tablet) continue; @@ -587,7 +587,7 @@ void CTabletV2Protocol::proximityIn(SP tool, SP tablet, SP } void CTabletV2Protocol::proximityOut(SP tool) { - for (auto& t : m_vTools) { + for (auto const& t : m_vTools) { if (t->tool != tool || !t->current) continue; @@ -599,7 +599,7 @@ void CTabletV2Protocol::proximityOut(SP tool) { } void CTabletV2Protocol::buttonTool(SP tool, uint32_t button, uint32_t state) { - for (auto& t : m_vTools) { + for (auto const& t : m_vTools) { if (t->tool != tool || !t->current) continue; @@ -610,7 +610,7 @@ void CTabletV2Protocol::buttonTool(SP tool, uint32_t button, uint32 } void CTabletV2Protocol::motion(SP tool, const Vector2D& value) { - for (auto& t : m_vTools) { + for (auto const& t : m_vTools) { if (t->tool != tool || !t->current) continue; @@ -620,7 +620,7 @@ void CTabletV2Protocol::motion(SP tool, const Vector2D& value) { } void CTabletV2Protocol::mode(SP pad, uint32_t group, uint32_t mode, uint32_t timeMs) { - for (auto& t : m_vPads) { + for (auto const& t : m_vPads) { if (t->pad != pad) continue; if (t->groups.size() <= group) { @@ -633,7 +633,7 @@ void CTabletV2Protocol::mode(SP pad, uint32_t group, uint32_t mode, } void CTabletV2Protocol::buttonPad(SP pad, uint32_t button, uint32_t timeMs, uint32_t state) { - for (auto& t : m_vPads) { + for (auto const& t : m_vPads) { if (t->pad != pad) continue; t->resource->sendButton(timeMs, button, zwpTabletToolV2ButtonState{state}); diff --git a/src/protocols/TearingControl.cpp b/src/protocols/TearingControl.cpp index 7f3c0a18..66a4efd2 100644 --- a/src/protocols/TearingControl.cpp +++ b/src/protocols/TearingControl.cpp @@ -38,7 +38,7 @@ void CTearingControlProtocol::onControllerDestroy(CTearingControl* control) { } void CTearingControlProtocol::onWindowDestroy(PHLWINDOW pWindow) { - for (auto& c : m_vTearingControllers) { + for (auto const& c : m_vTearingControllers) { if (c->pWindow.lock() == pWindow) c->pWindow.reset(); } @@ -52,7 +52,7 @@ CTearingControl::CTearingControl(SP resource_, SPsetDestroy([this](CWpTearingControlV1* res) { PROTO::tearing->onControllerDestroy(this); }); resource->setSetPresentationHint([this](CWpTearingControlV1* res, wpTearingControlV1PresentationHint hint) { this->onHint(hint); }); - for (auto& w : g_pCompositor->m_vWindows) { + for (auto const& w : g_pCompositor->m_vWindows) { if (w->m_pWLSurface->resource() == surf_) { pWindow = w; break; diff --git a/src/protocols/ToplevelExport.cpp b/src/protocols/ToplevelExport.cpp index 916f7395..b28a827a 100644 --- a/src/protocols/ToplevelExport.cpp +++ b/src/protocols/ToplevelExport.cpp @@ -369,7 +369,7 @@ void CToplevelExportProtocol::onOutputCommit(CMonitor* pMonitor) { std::vector> framesToRemove; // share frame if correct output - for (auto& f : m_vFramesAwaitingWrite) { + for (auto const& f : m_vFramesAwaitingWrite) { if (!f->pWindow || !validMapped(f->pWindow)) { framesToRemove.push_back(f); continue; @@ -393,13 +393,13 @@ void CToplevelExportProtocol::onOutputCommit(CMonitor* pMonitor) { framesToRemove.push_back(f); } - for (auto& f : framesToRemove) { + for (auto const& f : framesToRemove) { destroyResource(f.get()); } } void CToplevelExportProtocol::onWindowUnmap(PHLWINDOW pWindow) { - for (auto& f : m_vFrames) { + for (auto const& f : m_vFrames) { if (f->pWindow == pWindow) f->pWindow.reset(); } diff --git a/src/protocols/VirtualKeyboard.cpp b/src/protocols/VirtualKeyboard.cpp index 27a4f248..bb51315d 100644 --- a/src/protocols/VirtualKeyboard.cpp +++ b/src/protocols/VirtualKeyboard.cpp @@ -108,7 +108,7 @@ void CVirtualKeyboardV1Resource::releasePressed() { timespec now; clock_gettime(CLOCK_MONOTONIC, &now); - for (auto& p : pressed) { + for (auto const& p : pressed) { events.key.emit(IKeyboard::SKeyEvent{ .timeMs = now.tv_sec * 1000 + now.tv_nsec / 1000000, .keycode = p, diff --git a/src/protocols/XDGOutput.cpp b/src/protocols/XDGOutput.cpp index 9c2c353c..5d620667 100644 --- a/src/protocols/XDGOutput.cpp +++ b/src/protocols/XDGOutput.cpp @@ -39,7 +39,7 @@ CXDGOutputProtocol::CXDGOutputProtocol(const wl_interface* iface, const int& ver static auto P2 = g_pHookSystem->hookDynamic("configReloaded", [this](void* self, SCallbackInfo& info, std::any param) { this->updateAllOutputs(); }); static auto P3 = g_pHookSystem->hookDynamic("monitorRemoved", [this](void* self, SCallbackInfo& info, std::any param) { const auto PMONITOR = std::any_cast(param); - for (auto& o : m_vXDGOutputs) { + for (auto const& o : m_vXDGOutputs) { if (o->monitor == PMONITOR) o->monitor = nullptr; } @@ -84,7 +84,7 @@ void CXDGOutputProtocol::onManagerGetXDGOutput(CZxdgOutputManagerV1* mgr, uint32 } void CXDGOutputProtocol::updateAllOutputs() { - for (auto& o : m_vXDGOutputs) { + for (auto const& o : m_vXDGOutputs) { if (!o->monitor) continue; diff --git a/src/protocols/XDGShell.cpp b/src/protocols/XDGShell.cpp index eaf5c333..39a511c3 100644 --- a/src/protocols/XDGShell.cpp +++ b/src/protocols/XDGShell.cpp @@ -388,7 +388,7 @@ CXDGSurfaceResource::CXDGSurfaceResource(SP resource_, SPm_vWindows.emplace_back(CWindow::create(self.lock())); - for (auto& p : popups) { + for (auto const& p : popups) { if (!p) continue; events.newPopup.emit(p); @@ -714,7 +714,7 @@ CXDGShellProtocol::CXDGShellProtocol(const wl_interface* iface, const int& ver, grab->keyboard = true; grab->pointer = true; grab->setCallback([this]() { - for (auto& g : grabbed) { + for (auto const& g : grabbed) { g->done(); } grabbed.clear(); @@ -779,7 +779,7 @@ void CXDGShellProtocol::addOrStartGrab(SP popup) { void CXDGShellProtocol::onPopupDestroy(WP popup) { if (popup == grabOwner) { g_pSeatManager->setGrab(nullptr); - for (auto& g : grabbed) { + for (auto const& g : grabbed) { g->done(); } grabbed.clear(); diff --git a/src/protocols/core/Compositor.cpp b/src/protocols/core/Compositor.cpp index 75f1e646..f7f6dcda 100644 --- a/src/protocols/core/Compositor.cpp +++ b/src/protocols/core/Compositor.cpp @@ -241,7 +241,7 @@ void CWLSurfaceResource::frame(timespec* now) { if (callbacks.empty()) return; - for (auto& c : callbacks) { + for (auto const& c : callbacks) { c->send(now); } @@ -257,7 +257,7 @@ void CWLSurfaceResource::bfHelper(std::vector> nodes, std std::vector> nodes2; // first, gather all nodes below - for (auto& n : nodes) { + for (auto const& n : nodes) { std::erase_if(n->subsurfaces, [](const auto& e) { return e.expired(); }); // subsurfaces is sorted lowest -> highest for (auto const& c : n->subsurfaces) { @@ -310,7 +310,7 @@ std::pair, Vector2D> CWLSurfaceResource::at(const Vector2 void* data) { ((std::vector, Vector2D>>*)data)->emplace_back(std::make_pair<>(surf, offset)); }, &surfs); - for (auto& [surf, pos] : surfs | std::views::reverse) { + for (auto const& [surf, pos] : surfs | std::views::reverse) { if (!allowsInput) { const auto BOX = CBox{pos, surf->current.size}; if (BOX.containsPoint(localCoords)) diff --git a/src/protocols/core/DataDevice.cpp b/src/protocols/core/DataDevice.cpp index 943c790f..b7640af3 100644 --- a/src/protocols/core/DataDevice.cpp +++ b/src/protocols/core/DataDevice.cpp @@ -80,7 +80,7 @@ void CWLDataOfferResource::sendData() { resource->sendAction(WL_DATA_DEVICE_MANAGER_DND_ACTION_MOVE); } - for (auto& m : source->mimes()) { + for (auto const& m : source->mimes()) { LOGM(LOG, " | offer {:x} supports mime {}", (uintptr_t)this, m); resource->sendOffer(m.c_str()); } diff --git a/src/protocols/core/Output.cpp b/src/protocols/core/Output.cpp index bcf62fae..394dc8e2 100644 --- a/src/protocols/core/Output.cpp +++ b/src/protocols/core/Output.cpp @@ -65,7 +65,7 @@ CWLOutputProtocol::CWLOutputProtocol(const wl_interface* iface, const int& ver, IWaylandProtocol(iface, ver, name), monitor(pMonitor), szName(pMonitor->szName) { listeners.modeChanged = monitor->events.modeChanged.registerListener([this](std::any d) { - for (auto& o : m_vOutputs) { + for (auto const& o : m_vOutputs) { o->updateState(); } }); @@ -95,7 +95,7 @@ void CWLOutputProtocol::destroyResource(CWLOutputResource* resource) { } SP CWLOutputProtocol::outputResourceFrom(wl_client* client) { - for (auto& r : m_vOutputs) { + for (auto const& r : m_vOutputs) { if (r->client() != client) continue; diff --git a/src/protocols/core/Seat.cpp b/src/protocols/core/Seat.cpp index f7764389..6ae0ddc4 100644 --- a/src/protocols/core/Seat.cpp +++ b/src/protocols/core/Seat.cpp @@ -525,7 +525,7 @@ void CWLSeatProtocol::updateCapabilities(uint32_t caps) { currentCaps = caps; - for (auto& s : m_vSeatResources) { + for (auto const& s : m_vSeatResources) { s->sendCapabilities(caps); } } @@ -534,7 +534,7 @@ void CWLSeatProtocol::updateKeymap() { if (!(currentCaps & eHIDCapabilityType::HID_INPUT_CAPABILITY_KEYBOARD)) return; - for (auto& k : m_vKeyboards) { + for (auto const& k : m_vKeyboards) { k->sendKeymap(g_pSeatManager->keyboard.lock()); } } @@ -543,13 +543,13 @@ void CWLSeatProtocol::updateRepeatInfo(uint32_t rate, uint32_t delayMs) { if (!(currentCaps & eHIDCapabilityType::HID_INPUT_CAPABILITY_KEYBOARD)) return; - for (auto& k : m_vKeyboards) { + for (auto const& k : m_vKeyboards) { k->repeatInfo(rate, delayMs); } } SP CWLSeatProtocol::seatResourceForClient(wl_client* client) { - for (auto& r : m_vSeatResources) { + for (auto const& r : m_vSeatResources) { if (r->client() == client) return r; } diff --git a/src/protocols/core/Shm.cpp b/src/protocols/core/Shm.cpp index 9996a607..b09326bd 100644 --- a/src/protocols/core/Shm.cpp +++ b/src/protocols/core/Shm.cpp @@ -171,7 +171,7 @@ CWLSHMResource::CWLSHMResource(SP resource_) : resource(resource_) { }); // send a few supported formats. No need for any other I think? - for (auto& s : PROTO::shm->shmFormats) { + for (auto const& s : PROTO::shm->shmFormats) { resource->sendFormat((wl_shm_format)s); } } @@ -193,7 +193,7 @@ void CWLSHMProtocol::bindManager(wl_client* client, void* data, uint32_t ver, ui DRM_FORMAT_XBGR8888, DRM_FORMAT_ABGR8888, DRM_FORMAT_XRGB2101010, DRM_FORMAT_ARGB2101010, DRM_FORMAT_XBGR2101010, DRM_FORMAT_ABGR2101010, }; - for (auto& fmt : g_pHyprOpenGL->getDRMFormats()) { + for (auto const& fmt : g_pHyprOpenGL->getDRMFormats()) { if (std::find(supportedShmFourccFormats.begin(), supportedShmFourccFormats.end(), fmt.drmFormat) == supportedShmFourccFormats.end()) continue; diff --git a/src/protocols/core/Subcompositor.cpp b/src/protocols/core/Subcompositor.cpp index e0679eff..46e20305 100644 --- a/src/protocols/core/Subcompositor.cpp +++ b/src/protocols/core/Subcompositor.cpp @@ -22,7 +22,7 @@ CWLSubsurfaceResource::CWLSubsurfaceResource(SP resource_, SP void { - for (auto& c : parent->subsurfaces) { + for (auto const& c : parent->subsurfaces) { if (c->zIndex >= idx) c->zIndex++; } @@ -53,7 +53,7 @@ CWLSubsurfaceResource::CWLSubsurfaceResource(SP resource_, SP void { - for (auto& c : parent->subsurfaces) { + for (auto const& c : parent->subsurfaces) { if (c->zIndex <= idx) c->zIndex--; } diff --git a/src/render/OpenGL.cpp b/src/render/OpenGL.cpp index 2aeda8be..67c11c23 100644 --- a/src/render/OpenGL.cpp +++ b/src/render/OpenGL.cpp @@ -213,7 +213,7 @@ EGLDeviceEXT CHyprOpenGLImpl::eglDeviceFromDRMFD(int drmFD) { return EGL_NO_DEVICE_EXT; } - for (auto& d : devices) { + for (auto const& d : devices) { auto devName = m_sProc.eglQueryDeviceStringEXT(d, EGL_DRM_DEVICE_FILE_EXT); if (!devName) continue; @@ -435,7 +435,7 @@ void CHyprOpenGLImpl::initDRMFormats() { std::vector dmaFormats; - for (auto& fmt : formats) { + for (auto const& fmt : formats) { std::vector mods; if (!DISABLE_MODS) { auto ret = getModsForFormat(fmt); @@ -460,7 +460,7 @@ void CHyprOpenGLImpl::initDRMFormats() { auto fmtName = drmGetFormatName(fmt); Debug::log(LOG, "EGL: GPU Supports Format {} (0x{:x})", fmtName ? fmtName : "?unknown?", fmt); - for (auto& mod : mods) { + for (auto const& mod : mods) { auto modName = drmGetFormatModifierName(mod); modifierData.emplace_back(std::make_pair<>(mod, modName ? modName : "?unknown?")); free(modName); @@ -476,7 +476,7 @@ void CHyprOpenGLImpl::initDRMFormats() { return true; }); - for (auto& [m, name] : modifierData) { + for (auto const& [m, name] : modifierData) { Debug::log(LOG, "EGL: | with modifier {} (0x{:x})", name, m); mods.emplace_back(m); } @@ -654,7 +654,7 @@ bool CHyprOpenGLImpl::passRequiresIntrospection(CMonitor* pMonitor) { if (!pMonitor->solitaryClient.expired()) return false; - for (auto& ls : pMonitor->m_aLayerSurfaceLayers[ZWLR_LAYER_SHELL_V1_LAYER_OVERLAY]) { + for (auto const& ls : pMonitor->m_aLayerSurfaceLayers[ZWLR_LAYER_SHELL_V1_LAYER_OVERLAY]) { const auto XRAYMODE = ls->xray == -1 ? *PXRAY : ls->xray; if (ls->forceBlur && !XRAYMODE) return true; @@ -663,7 +663,7 @@ bool CHyprOpenGLImpl::passRequiresIntrospection(CMonitor* pMonitor) { return true; } - for (auto& ls : pMonitor->m_aLayerSurfaceLayers[ZWLR_LAYER_SHELL_V1_LAYER_TOP]) { + for (auto const& ls : pMonitor->m_aLayerSurfaceLayers[ZWLR_LAYER_SHELL_V1_LAYER_TOP]) { const auto XRAYMODE = ls->xray == -1 ? *PXRAY : ls->xray; if (ls->forceBlur && !XRAYMODE) return true; @@ -673,7 +673,7 @@ bool CHyprOpenGLImpl::passRequiresIntrospection(CMonitor* pMonitor) { } // these two block optimization - for (auto& ls : pMonitor->m_aLayerSurfaceLayers[ZWLR_LAYER_SHELL_V1_LAYER_BACKGROUND]) { + for (auto const& ls : pMonitor->m_aLayerSurfaceLayers[ZWLR_LAYER_SHELL_V1_LAYER_BACKGROUND]) { if (ls->forceBlur) return true; @@ -681,7 +681,7 @@ bool CHyprOpenGLImpl::passRequiresIntrospection(CMonitor* pMonitor) { return true; } - for (auto& ls : pMonitor->m_aLayerSurfaceLayers[ZWLR_LAYER_SHELL_V1_LAYER_BOTTOM]) { + for (auto const& ls : pMonitor->m_aLayerSurfaceLayers[ZWLR_LAYER_SHELL_V1_LAYER_BOTTOM]) { if (ls->forceBlur) return true; @@ -704,7 +704,7 @@ bool CHyprOpenGLImpl::passRequiresIntrospection(CMonitor* pMonitor) { if (*PXRAY) return false; - for (auto& w : g_pCompositor->m_vWindows) { + for (auto const& w : g_pCompositor->m_vWindows) { if (!w->m_bIsMapped || w->isHidden()) continue; @@ -1168,7 +1168,7 @@ void CHyprOpenGLImpl::clear(const CColor& color) { glClearColor(color.r, color.g, color.b, color.a); if (!m_RenderData.damage.empty()) { - for (auto& RECT : m_RenderData.damage.getRects()) { + for (auto const& RECT : m_RenderData.damage.getRects()) { scissor(&RECT); glClear(GL_COLOR_BUFFER_BIT); } @@ -1327,13 +1327,13 @@ void CHyprOpenGLImpl::renderRectWithDamage(CBox* box, const CColor& col, CRegion damageClip.intersect(*damage); if (!damageClip.empty()) { - for (auto& RECT : damageClip.getRects()) { + for (auto const& RECT : damageClip.getRects()) { scissor(&RECT); glDrawArrays(GL_TRIANGLE_STRIP, 0, 4); } } } else { - for (auto& RECT : damage->getRects()) { + for (auto const& RECT : damage->getRects()) { scissor(&RECT); glDrawArrays(GL_TRIANGLE_STRIP, 0, 4); } @@ -1523,13 +1523,13 @@ void CHyprOpenGLImpl::renderTextureInternalWithDamage(SP tex, CBox* pB damageClip.intersect(*damage); if (!damageClip.empty()) { - for (auto& RECT : damageClip.getRects()) { + for (auto const& RECT : damageClip.getRects()) { scissor(&RECT); glDrawArrays(GL_TRIANGLE_STRIP, 0, 4); } } } else { - for (auto& RECT : damage->getRects()) { + for (auto const& RECT : damage->getRects()) { scissor(&RECT); glDrawArrays(GL_TRIANGLE_STRIP, 0, 4); } @@ -1582,7 +1582,7 @@ void CHyprOpenGLImpl::renderTexturePrimitive(SP tex, CBox* pBox) { glEnableVertexAttribArray(shader->posAttrib); glEnableVertexAttribArray(shader->texAttrib); - for (auto& RECT : m_RenderData.damage.getRects()) { + for (auto const& RECT : m_RenderData.damage.getRects()) { scissor(&RECT); glDrawArrays(GL_TRIANGLE_STRIP, 0, 4); } @@ -1640,7 +1640,7 @@ void CHyprOpenGLImpl::renderTextureMatte(SP tex, CBox* pBox, CFramebuf glEnableVertexAttribArray(shader->posAttrib); glEnableVertexAttribArray(shader->texAttrib); - for (auto& RECT : m_RenderData.damage.getRects()) { + for (auto const& RECT : m_RenderData.damage.getRects()) { scissor(&RECT); glDrawArrays(GL_TRIANGLE_STRIP, 0, 4); } @@ -1725,7 +1725,7 @@ CFramebuffer* CHyprOpenGLImpl::blurMainFramebufferWithDamage(float a, CRegion* o glEnableVertexAttribArray(m_RenderData.pCurrentMonData->m_shBLURPREPARE.texAttrib); if (!damage.empty()) { - for (auto& RECT : damage.getRects()) { + for (auto const& RECT : damage.getRects()) { scissor(&RECT, false /* this region is already transformed */); glDrawArrays(GL_TRIANGLE_STRIP, 0, 4); } @@ -1778,7 +1778,7 @@ CFramebuffer* CHyprOpenGLImpl::blurMainFramebufferWithDamage(float a, CRegion* o glEnableVertexAttribArray(pShader->texAttrib); if (!pDamage->empty()) { - for (auto& RECT : pDamage->getRects()) { + for (auto const& RECT : pDamage->getRects()) { scissor(&RECT, false /* this region is already transformed */); glDrawArrays(GL_TRIANGLE_STRIP, 0, 4); } @@ -1848,7 +1848,7 @@ CFramebuffer* CHyprOpenGLImpl::blurMainFramebufferWithDamage(float a, CRegion* o glEnableVertexAttribArray(m_RenderData.pCurrentMonData->m_shBLURFINISH.texAttrib); if (!damage.empty()) { - for (auto& RECT : damage.getRects()) { + for (auto const& RECT : damage.getRects()) { scissor(&RECT, false /* this region is already transformed */); glDrawArrays(GL_TRIANGLE_STRIP, 0, 4); } @@ -1924,7 +1924,7 @@ void CHyprOpenGLImpl::preRender(CMonitor* pMonitor) { }; bool hasWindows = false; - for (auto& w : g_pCompositor->m_vWindows) { + for (auto const& w : g_pCompositor->m_vWindows) { if (w->m_pWorkspace == pMonitor->activeWorkspace && !w->isHidden() && w->m_bIsMapped && (!w->m_bIsFloating || *PBLURXRAY)) { // check if window is valid @@ -2215,13 +2215,13 @@ void CHyprOpenGLImpl::renderBorder(CBox* box, const CGradientValueData& grad, in damageClip.intersect(m_RenderData.damage); if (!damageClip.empty()) { - for (auto& RECT : damageClip.getRects()) { + for (auto const& RECT : damageClip.getRects()) { scissor(&RECT); glDrawArrays(GL_TRIANGLE_STRIP, 0, 4); } } } else { - for (auto& RECT : m_RenderData.damage.getRects()) { + for (auto const& RECT : m_RenderData.damage.getRects()) { scissor(&RECT); glDrawArrays(GL_TRIANGLE_STRIP, 0, 4); } @@ -2512,13 +2512,13 @@ void CHyprOpenGLImpl::renderRoundedShadow(CBox* box, int round, int range, const damageClip.intersect(m_RenderData.damage); if (!damageClip.empty()) { - for (auto& RECT : damageClip.getRects()) { + for (auto const& RECT : damageClip.getRects()) { scissor(&RECT); glDrawArrays(GL_TRIANGLE_STRIP, 0, 4); } } } else { - for (auto& RECT : m_RenderData.damage.getRects()) { + for (auto const& RECT : m_RenderData.damage.getRects()) { scissor(&RECT); glDrawArrays(GL_TRIANGLE_STRIP, 0, 4); } @@ -2928,7 +2928,7 @@ void SRenderModifData::applyToBox(CBox& box) { if (!enabled) return; - for (auto& [type, val] : modifs) { + for (auto const& [type, val] : modifs) { try { switch (type) { case RMOD_TYPE_SCALE: box.scale(std::any_cast(val)); break; @@ -2953,7 +2953,7 @@ void SRenderModifData::applyToRegion(CRegion& rg) { if (!enabled) return; - for (auto& [type, val] : modifs) { + for (auto const& [type, val] : modifs) { try { switch (type) { case RMOD_TYPE_SCALE: rg.scale(std::any_cast(val)); break; @@ -2971,7 +2971,7 @@ float SRenderModifData::combinedScale() { return 1; float scale = 1.f; - for (auto& [type, val] : modifs) { + for (auto const& [type, val] : modifs) { try { switch (type) { case RMOD_TYPE_SCALE: scale *= std::any_cast(val); break; diff --git a/src/render/Renderer.cpp b/src/render/Renderer.cpp index 2ef7e208..c601e369 100644 --- a/src/render/Renderer.cpp +++ b/src/render/Renderer.cpp @@ -35,7 +35,7 @@ static int cursorTicker(void* data) { CHyprRenderer::CHyprRenderer() { if (g_pCompositor->m_pAqBackend->hasSession()) { - for (auto& dev : g_pCompositor->m_pAqBackend->session->sessionDevices) { + for (auto const& dev : g_pCompositor->m_pAqBackend->session->sessionDevices) { const auto DRMV = drmGetVersion(dev->fd); if (!DRMV) continue; @@ -348,7 +348,7 @@ void CHyprRenderer::renderWorkspaceWindowsFullscreen(CMonitor* pMonitor, PHLWORK EMIT_HOOK_EVENT("render", RENDER_PRE_WINDOWS); // loop over the tiled windows that are fading out - for (auto& w : g_pCompositor->m_vWindows) { + for (auto const& w : g_pCompositor->m_vWindows) { if (!shouldRenderWindow(w, pMonitor)) continue; @@ -365,7 +365,7 @@ void CHyprRenderer::renderWorkspaceWindowsFullscreen(CMonitor* pMonitor, PHLWORK } // and floating ones too - for (auto& w : g_pCompositor->m_vWindows) { + for (auto const& w : g_pCompositor->m_vWindows) { if (!shouldRenderWindow(w, pMonitor)) continue; @@ -385,7 +385,7 @@ void CHyprRenderer::renderWorkspaceWindowsFullscreen(CMonitor* pMonitor, PHLWORK } // TODO: this pass sucks - for (auto& w : g_pCompositor->m_vWindows) { + for (auto const& w : g_pCompositor->m_vWindows) { const auto PWORKSPACE = w->m_pWorkspace; if (w->m_pWorkspace != pWorkspace || !w->isFullscreen()) { @@ -418,7 +418,7 @@ void CHyprRenderer::renderWorkspaceWindowsFullscreen(CMonitor* pMonitor, PHLWORK } // then render windows over fullscreen. - for (auto& w : g_pCompositor->m_vWindows) { + for (auto const& w : g_pCompositor->m_vWindows) { if (w->m_pWorkspace != pWorkspaceWindow->m_pWorkspace || (!w->m_bCreatedOverFullscreen && !w->m_bPinned) || (!w->m_bIsMapped && !w->m_bFadingOut) || w->isFullscreen()) continue; @@ -438,7 +438,7 @@ void CHyprRenderer::renderWorkspaceWindows(CMonitor* pMonitor, PHLWORKSPACE pWor EMIT_HOOK_EVENT("render", RENDER_PRE_WINDOWS); // Non-floating main - for (auto& w : g_pCompositor->m_vWindows) { + for (auto const& w : g_pCompositor->m_vWindows) { if (w->isHidden() || (!w->m_bIsMapped && !w->m_bFadingOut)) continue; @@ -465,7 +465,7 @@ void CHyprRenderer::renderWorkspaceWindows(CMonitor* pMonitor, PHLWORKSPACE pWor renderWindow(lastWindow, pMonitor, time, true, RENDER_PASS_MAIN); // Non-floating popup - for (auto& w : g_pCompositor->m_vWindows) { + for (auto const& w : g_pCompositor->m_vWindows) { if (w->isHidden() || (!w->m_bIsMapped && !w->m_bFadingOut)) continue; @@ -483,7 +483,7 @@ void CHyprRenderer::renderWorkspaceWindows(CMonitor* pMonitor, PHLWORKSPACE pWor } // floating on top - for (auto& w : g_pCompositor->m_vWindows) { + for (auto const& w : g_pCompositor->m_vWindows) { if (w->isHidden() || (!w->m_bIsMapped && !w->m_bFadingOut)) continue; @@ -585,20 +585,20 @@ void CHyprRenderer::renderWindow(PHLWINDOW pWindow, CMonitor* pMonitor, timespec if (TRANSFORMERSPRESENT) { g_pHyprOpenGL->bindOffMain(); - for (auto& t : pWindow->m_vTransformers) { + for (auto const& t : pWindow->m_vTransformers) { t->preWindowRender(&renderdata); } } if (renderdata.decorate) { - for (auto& wd : pWindow->m_dWindowDecorations) { + for (auto const& wd : pWindow->m_dWindowDecorations) { if (wd->getDecorationLayer() != DECORATION_LAYER_BOTTOM) continue; wd->draw(pMonitor, renderdata.alpha * renderdata.fadeAlpha); } - for (auto& wd : pWindow->m_dWindowDecorations) { + for (auto const& wd : pWindow->m_dWindowDecorations) { if (wd->getDecorationLayer() != DECORATION_LAYER_UNDER) continue; @@ -625,7 +625,7 @@ void CHyprRenderer::renderWindow(PHLWINDOW pWindow, CMonitor* pMonitor, timespec g_pHyprOpenGL->m_RenderData.useNearestNeighbor = false; if (renderdata.decorate) { - for (auto& wd : pWindow->m_dWindowDecorations) { + for (auto const& wd : pWindow->m_dWindowDecorations) { if (wd->getDecorationLayer() != DECORATION_LAYER_OVER) continue; @@ -636,7 +636,7 @@ void CHyprRenderer::renderWindow(PHLWINDOW pWindow, CMonitor* pMonitor, timespec if (TRANSFORMERSPRESENT) { CFramebuffer* last = g_pHyprOpenGL->m_RenderData.currentFB; - for (auto& t : pWindow->m_vTransformers) { + for (auto const& t : pWindow->m_vTransformers) { last = t->transform(last); } @@ -700,7 +700,7 @@ void CHyprRenderer::renderWindow(PHLWINDOW pWindow, CMonitor* pMonitor, timespec } if (decorate) { - for (auto& wd : pWindow->m_dWindowDecorations) { + for (auto const& wd : pWindow->m_dWindowDecorations) { if (wd->getDecorationLayer() != DECORATION_LAYER_OVERLAY) continue; @@ -852,16 +852,16 @@ void CHyprRenderer::renderAllClientsForWorkspace(CMonitor* pMonitor, PHLWORKSPAC } g_pHyprOpenGL->blend(true); - for (auto& ls : pMonitor->m_aLayerSurfaceLayers[ZWLR_LAYER_SHELL_V1_LAYER_BACKGROUND]) { + for (auto const& ls : pMonitor->m_aLayerSurfaceLayers[ZWLR_LAYER_SHELL_V1_LAYER_BACKGROUND]) { renderLayer(ls.lock(), pMonitor, time); } - for (auto& ls : pMonitor->m_aLayerSurfaceLayers[ZWLR_LAYER_SHELL_V1_LAYER_BOTTOM]) { + for (auto const& ls : pMonitor->m_aLayerSurfaceLayers[ZWLR_LAYER_SHELL_V1_LAYER_BOTTOM]) { renderLayer(ls.lock(), pMonitor, time); } - for (auto& ls : pMonitor->m_aLayerSurfaceLayers[ZWLR_LAYER_SHELL_V1_LAYER_TOP]) { + for (auto const& ls : pMonitor->m_aLayerSurfaceLayers[ZWLR_LAYER_SHELL_V1_LAYER_TOP]) { renderLayer(ls.lock(), pMonitor, time); } - for (auto& ls : pMonitor->m_aLayerSurfaceLayers[ZWLR_LAYER_SHELL_V1_LAYER_OVERLAY]) { + for (auto const& ls : pMonitor->m_aLayerSurfaceLayers[ZWLR_LAYER_SHELL_V1_LAYER_OVERLAY]) { renderLayer(ls.lock(), pMonitor, time); } @@ -892,10 +892,10 @@ void CHyprRenderer::renderAllClientsForWorkspace(CMonitor* pMonitor, PHLWORKSPAC } g_pHyprOpenGL->blend(true); - for (auto& ls : pMonitor->m_aLayerSurfaceLayers[ZWLR_LAYER_SHELL_V1_LAYER_BACKGROUND]) { + for (auto const& ls : pMonitor->m_aLayerSurfaceLayers[ZWLR_LAYER_SHELL_V1_LAYER_BACKGROUND]) { renderLayer(ls.lock(), pMonitor, time); } - for (auto& ls : pMonitor->m_aLayerSurfaceLayers[ZWLR_LAYER_SHELL_V1_LAYER_BOTTOM]) { + for (auto const& ls : pMonitor->m_aLayerSurfaceLayers[ZWLR_LAYER_SHELL_V1_LAYER_BOTTOM]) { renderLayer(ls.lock(), pMonitor, time); } @@ -945,7 +945,7 @@ void CHyprRenderer::renderAllClientsForWorkspace(CMonitor* pMonitor, PHLWORKSPAC } // pinned always above - for (auto& w : g_pCompositor->m_vWindows) { + for (auto const& w : g_pCompositor->m_vWindows) { if (w->isHidden() && !w->m_bIsMapped && !w->m_bFadingOut) continue; @@ -962,21 +962,21 @@ void CHyprRenderer::renderAllClientsForWorkspace(CMonitor* pMonitor, PHLWORKSPAC EMIT_HOOK_EVENT("render", RENDER_POST_WINDOWS); // Render surfaces above windows for monitor - for (auto& ls : pMonitor->m_aLayerSurfaceLayers[ZWLR_LAYER_SHELL_V1_LAYER_TOP]) { + for (auto const& ls : pMonitor->m_aLayerSurfaceLayers[ZWLR_LAYER_SHELL_V1_LAYER_TOP]) { renderLayer(ls.lock(), pMonitor, time); } // Render IME popups - for (auto& imep : g_pInputManager->m_sIMERelay.m_vIMEPopups) { + for (auto const& imep : g_pInputManager->m_sIMERelay.m_vIMEPopups) { renderIMEPopup(imep.get(), pMonitor, time); } - for (auto& ls : pMonitor->m_aLayerSurfaceLayers[ZWLR_LAYER_SHELL_V1_LAYER_OVERLAY]) { + for (auto const& ls : pMonitor->m_aLayerSurfaceLayers[ZWLR_LAYER_SHELL_V1_LAYER_OVERLAY]) { renderLayer(ls.lock(), pMonitor, time); } - for (auto& lsl : pMonitor->m_aLayerSurfaceLayers) { - for (auto& ls : lsl) { + for (auto const& lsl : pMonitor->m_aLayerSurfaceLayers) { + for (auto const& ls : lsl) { renderLayer(ls.lock(), pMonitor, time, true); } } @@ -1456,7 +1456,7 @@ bool CHyprRenderer::commitPendingAndDoExplicitSync(CMonitor* pMonitor) { if (!sync) Debug::log(TRACE, "Explicit: can't add sync, EGLSync failed"); else { - for (auto& e : explicitPresented) { + for (auto const& e : explicitPresented) { if (!e->current.buffer || !e->current.buffer->releaser) continue; @@ -1579,7 +1579,7 @@ static void applyExclusive(CBox& usableArea, uint32_t anchor, int32_t exclusive, void CHyprRenderer::arrangeLayerArray(CMonitor* pMonitor, const std::vector& layerSurfaces, bool exclusiveZone, CBox* usableArea) { CBox full_area = {pMonitor->vecPosition.x, pMonitor->vecPosition.y, pMonitor->vecSize.x, pMonitor->vecSize.y}; - for (auto& ls : layerSurfaces) { + for (auto const& ls : layerSurfaces) { if (!ls || ls->fadingOut || ls->readyToDelete || !ls->layerSurface || ls->noProcess) continue; @@ -1725,7 +1725,7 @@ void CHyprRenderer::damageSurface(SP pSurface, double x, dou CRegion damageBoxForEach; - for (auto& m : g_pCompositor->m_vMonitors) { + for (auto const& m : g_pCompositor->m_vMonitors) { if (!m->output) continue; @@ -1752,7 +1752,7 @@ void CHyprRenderer::damageWindow(PHLWINDOW pWindow, bool forceFull) { windowBox.translate(PWINDOWWORKSPACE->m_vRenderOffset.value()); windowBox.translate(pWindow->m_vFloatingOffset); - for (auto& m : g_pCompositor->m_vMonitors) { + for (auto const& m : g_pCompositor->m_vMonitors) { if (forceFull || g_pHyprRenderer->shouldRenderWindow(pWindow, m.get())) { // only damage if window is rendered on monitor CBox fixedDamageBox = {windowBox.x - m->vecPosition.x, windowBox.y - m->vecPosition.y, windowBox.width, windowBox.height}; fixedDamageBox.scale(m->scale); @@ -1760,7 +1760,7 @@ void CHyprRenderer::damageWindow(PHLWINDOW pWindow, bool forceFull) { } } - for (auto& wd : pWindow->m_dWindowDecorations) + for (auto const& wd : pWindow->m_dWindowDecorations) wd->damageEntire(); static auto PLOGDAMAGE = CConfigValue("debug:log_damage"); @@ -1786,7 +1786,7 @@ void CHyprRenderer::damageBox(CBox* pBox, bool skipFrameSchedule) { if (g_pCompositor->m_bUnsafeState) return; - for (auto& m : g_pCompositor->m_vMonitors) { + for (auto const& m : g_pCompositor->m_vMonitors) { if (m->isMirror()) continue; // don't damage mirrors traditionally @@ -1814,7 +1814,7 @@ void CHyprRenderer::damageRegion(const CRegion& rg) { } void CHyprRenderer::damageMirrorsWith(CMonitor* pMonitor, const CRegion& pRegion) { - for (auto& mirror : pMonitor->mirrors) { + for (auto const& mirror : pMonitor->mirrors) { // transform the damage here, so it won't get clipped by the monitor damage ring auto monitor = mirror; @@ -1932,7 +1932,7 @@ bool CHyprRenderer::applyMonitorRule(CMonitor* pMonitor, SMonitorRule* pMonitorR if (!pMonitor->output->modes.empty() && RULE->drmMode.type != DRM_MODE_TYPE_USERDEF) { bool found = false; - for (auto& mode : pMonitor->output->modes) { + for (auto const& mode : pMonitor->output->modes) { // if delta of refresh rate, w and h chosen and mode is < 1 we accept it if (DELTALESSTHAN(mode->pixelSize.x, RULE->resolution.x, 1) && DELTALESSTHAN(mode->pixelSize.y, RULE->resolution.y, 1) && DELTALESSTHAN(mode->refreshRate / 1000.f, RULE->refreshRate, 1)) { @@ -2035,7 +2035,7 @@ bool CHyprRenderer::applyMonitorRule(CMonitor* pMonitor, SMonitorRule* pMonitorR //(-1,-1) indicates a preference to refreshrate over resolution, (-1,-2) preference to resolution if (RULE->resolution == Vector2D(-1, -1)) { - for (auto& mode : pMonitor->output->modes) { + for (auto const& mode : pMonitor->output->modes) { if ((mode->pixelSize.x >= currentWidth && mode->pixelSize.y >= currentHeight && mode->refreshRate >= (currentRefresh - 1000.f)) || mode->refreshRate > (currentRefresh + 3000.f)) { pMonitor->output->state->setMode(mode); @@ -2048,7 +2048,7 @@ bool CHyprRenderer::applyMonitorRule(CMonitor* pMonitor, SMonitorRule* pMonitorR } } } else { - for (auto& mode : pMonitor->output->modes) { + for (auto const& mode : pMonitor->output->modes) { if ((mode->pixelSize.x >= currentWidth && mode->pixelSize.y >= currentHeight && mode->refreshRate >= (currentRefresh - 1000.f)) || (mode->pixelSize.x > currentWidth && mode->pixelSize.y > currentHeight)) { pMonitor->output->state->setMode(mode); @@ -2099,7 +2099,7 @@ bool CHyprRenderer::applyMonitorRule(CMonitor* pMonitor, SMonitorRule* pMonitorR Debug::log(ERR, "Monitor {} has NO PREFERRED MODE", pMonitor->output->name); if (!pMonitor->output->modes.empty()) { - for (auto& mode : pMonitor->output->modes) { + for (auto const& mode : pMonitor->output->modes) { pMonitor->output->state->setMode(mode); if (!pMonitor->state.test()) { @@ -2148,7 +2148,7 @@ bool CHyprRenderer::applyMonitorRule(CMonitor* pMonitor, SMonitorRule* pMonitorR bool set10bit = false; - for (auto& fmt : formats[(int)!RULE->enable10bit]) { + for (auto const& fmt : formats[(int)!RULE->enable10bit]) { pMonitor->output->state->setFormat(fmt.second); pMonitor->drmFormat = fmt.second; @@ -2245,7 +2245,7 @@ bool CHyprRenderer::applyMonitorRule(CMonitor* pMonitor, SMonitorRule* pMonitorR // Set scale for all surfaces on this monitor, needed for some clients // but not on unsafe state to avoid crashes if (!g_pCompositor->m_bUnsafeState) { - for (auto& w : g_pCompositor->m_vWindows) { + for (auto const& w : g_pCompositor->m_vWindows) { w->updateSurfaceScaleTransformDetails(); } } @@ -2317,7 +2317,7 @@ void CHyprRenderer::ensureCursorRenderingMode() { if (HIDE) { Debug::log(LOG, "Hiding the cursor (hl-mandated)"); - for (auto& m : g_pCompositor->m_vMonitors) { + for (auto const& m : g_pCompositor->m_vMonitors) { if (!g_pPointerManager->softwareLockedFor(m)) continue; @@ -2329,7 +2329,7 @@ void CHyprRenderer::ensureCursorRenderingMode() { } else { Debug::log(LOG, "Showing the cursor (hl-mandated)"); - for (auto& m : g_pCompositor->m_vMonitors) { + for (auto const& m : g_pCompositor->m_vMonitors) { if (!g_pPointerManager->softwareLockedFor(m)) continue; @@ -2421,7 +2421,7 @@ void CHyprRenderer::setOccludedForMainWorkspace(CRegion& region, PHLWORKSPACE pW if (!PMONITOR->activeSpecialWorkspace) return; - for (auto& w : g_pCompositor->m_vWindows) { + for (auto const& w : g_pCompositor->m_vWindows) { if (!w->m_bIsMapped || w->isHidden() || w->m_pWorkspace != PMONITOR->activeSpecialWorkspace) continue; @@ -2452,7 +2452,7 @@ void CHyprRenderer::setOccludedForBackLayers(CRegion& region, PHLWORKSPACE pWork static auto PBLURPASSES = CConfigValue("decoration:blur:passes"); const auto BLURRADIUS = *PBLUR ? (*PBLURPASSES > 10 ? pow(2, 15) : std::clamp(*PBLURSIZE, (int64_t)1, (int64_t)40) * pow(2, *PBLURPASSES)) : 0; - for (auto& w : g_pCompositor->m_vWindows) { + for (auto const& w : g_pCompositor->m_vWindows) { if (!w->m_bIsMapped || w->isHidden() || w->m_pWorkspace != pWorkspace) continue; @@ -2476,7 +2476,7 @@ void CHyprRenderer::setOccludedForBackLayers(CRegion& region, PHLWORKSPACE pWork } bool CHyprRenderer::canSkipBackBufferClear(CMonitor* pMonitor) { - for (auto& ls : pMonitor->m_aLayerSurfaceLayers[ZWLR_LAYER_SHELL_V1_LAYER_BACKGROUND]) { + for (auto const& ls : pMonitor->m_aLayerSurfaceLayers[ZWLR_LAYER_SHELL_V1_LAYER_BACKGROUND]) { if (!ls->layerSurface) continue; diff --git a/src/render/Texture.cpp b/src/render/Texture.cpp index 94d00184..91e70afa 100644 --- a/src/render/Texture.cpp +++ b/src/render/Texture.cpp @@ -120,7 +120,7 @@ void CTexture::update(uint32_t drmFormat, uint8_t* pixels, uint32_t stride, cons } #endif - for (auto& rect : rects) { + for (auto const& rect : rects) { GLCALL(glPixelStorei(GL_UNPACK_ROW_LENGTH_EXT, stride / format->bytesPerBlock)); GLCALL(glPixelStorei(GL_UNPACK_SKIP_PIXELS_EXT, rect.x1)); GLCALL(glPixelStorei(GL_UNPACK_SKIP_ROWS_EXT, rect.y1)); diff --git a/src/render/decorations/CHyprBorderDecoration.cpp b/src/render/decorations/CHyprBorderDecoration.cpp index f5e6e945..1eaaa0af 100644 --- a/src/render/decorations/CHyprBorderDecoration.cpp +++ b/src/render/decorations/CHyprBorderDecoration.cpp @@ -118,7 +118,7 @@ void CHyprBorderDecoration::damageEntire() { CRegion borderRegion(surfaceBoxExpandedBorder); borderRegion.subtract(surfaceBoxShrunkRounding); - for (auto& m : g_pCompositor->m_vMonitors) { + for (auto const& m : g_pCompositor->m_vMonitors) { if (!g_pHyprRenderer->shouldRenderWindow(m_pWindow.lock(), m.get())) { const CRegion monitorRegion({m->vecPosition, m->vecSize}); borderRegion.subtract(monitorRegion); diff --git a/src/render/decorations/CHyprDropShadowDecoration.cpp b/src/render/decorations/CHyprDropShadowDecoration.cpp index 423256d7..628a579a 100644 --- a/src/render/decorations/CHyprDropShadowDecoration.cpp +++ b/src/render/decorations/CHyprDropShadowDecoration.cpp @@ -66,7 +66,7 @@ void CHyprDropShadowDecoration::damageEntire() { shadowRegion.subtract(CRegion(surfaceBox)); } - for (auto& m : g_pCompositor->m_vMonitors) { + for (auto const& m : g_pCompositor->m_vMonitors) { if (!g_pHyprRenderer->shouldRenderWindow(PWINDOW, m.get())) { const CRegion monitorRegion({m->vecPosition, m->vecSize}); shadowRegion.subtract(monitorRegion); diff --git a/src/render/decorations/CHyprGroupBarDecoration.cpp b/src/render/decorations/CHyprGroupBarDecoration.cpp index 8163a8c1..4cdb9043 100644 --- a/src/render/decorations/CHyprGroupBarDecoration.cpp +++ b/src/render/decorations/CHyprGroupBarDecoration.cpp @@ -192,7 +192,7 @@ void CHyprGroupBarDecoration::draw(CMonitor* pMonitor, float a) { } CTitleTex* CHyprGroupBarDecoration::textureFromTitle(const std::string& title) { - for (auto& tex : m_sTitleTexs.titleTexs) { + for (auto const& tex : m_sTitleTexs.titleTexs) { if (tex->szContent == title) return tex.get(); } diff --git a/src/render/decorations/DecorationPositioner.cpp b/src/render/decorations/DecorationPositioner.cpp index d66a5760..4666a59e 100644 --- a/src/render/decorations/DecorationPositioner.cpp +++ b/src/render/decorations/DecorationPositioner.cpp @@ -125,7 +125,7 @@ void CDecorationPositioner::onWindowUpdate(PHLWINDOW pWindow) { // std::vector datas; - for (auto& wd : pWindow->m_dWindowDecorations) { + for (auto const& wd : pWindow->m_dWindowDecorations) { datas.push_back(getDataFor(wd.get(), pWindow)); } @@ -296,7 +296,7 @@ SBoxExtents CDecorationPositioner::getWindowDecorationReserved(PHLWINDOW pWindow SBoxExtents CDecorationPositioner::getWindowDecorationExtents(PHLWINDOW pWindow, bool inputOnly) { CBox accum = pWindow->getWindowMainSurfaceBox(); - for (auto& data : m_vWindowPositioningDatas) { + for (auto const& data : m_vWindowPositioningDatas) { if (data->pWindow.lock() != pWindow) continue; @@ -337,7 +337,7 @@ SBoxExtents CDecorationPositioner::getWindowDecorationExtents(PHLWINDOW pWindow, CBox CDecorationPositioner::getBoxWithIncludedDecos(PHLWINDOW pWindow) { CBox accum = pWindow->getWindowMainSurfaceBox(); - for (auto& data : m_vWindowPositioningDatas) { + for (auto const& data : m_vWindowPositioningDatas) { if (data->pWindow.lock() != pWindow) continue; diff --git a/src/xwayland/XWM.cpp b/src/xwayland/XWM.cpp index 995ec7f2..07208072 100644 --- a/src/xwayland/XWM.cpp +++ b/src/xwayland/XWM.cpp @@ -417,7 +417,7 @@ void CXWM::focusWindow(SP surf) { // send state to all toplevel surfaces, sometimes we might lose some // that could still stick with the focused atom - for (auto& s : mappedSurfaces) { + for (auto const& s : mappedSurfaces) { if (!s || s->overrideRedirect) continue; @@ -1025,7 +1025,7 @@ void CXWM::updateClientList() { std::erase_if(mappedSurfacesStacking, [](const auto& e) { return e.expired() || !e->mapped; }); std::vector windows; - for (auto& m : mappedSurfaces) { + for (auto const& m : mappedSurfaces) { windows.push_back(m->xID); } @@ -1033,7 +1033,7 @@ void CXWM::updateClientList() { windows.clear(); - for (auto& m : mappedSurfacesStacking) { + for (auto const& m : mappedSurfacesStacking) { windows.push_back(m->xID); } From 09dbcabcc71f412dcaf86dbed7b67d58a273fa50 Mon Sep 17 00:00:00 2001 From: raf Date: Mon, 26 Aug 2024 18:24:57 +0000 Subject: [PATCH 0326/2181] CI: disable stale workflow on forks (#7535) The stale workflow will run unconditionally, but will fail on forks due to `STALEBOT_PAT` not being set. Trigger the workflow *only* if we are on the main repo, where we can guarantee the PAT. Also formats the YML syntax to be slightly more readable. --- .github/workflows/stale.yml | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/.github/workflows/stale.yml b/.github/workflows/stale.yml index 51f6b91e..b8be5f55 100644 --- a/.github/workflows/stale.yml +++ b/.github/workflows/stale.yml @@ -7,22 +7,22 @@ name: Mark stale issues and pull requests on: schedule: - - cron: '7 */4 * * *' + - cron: "7 */4 * * *" workflow_dispatch: jobs: stale: - + if: github.repository == 'hyprwm/Hyprland' runs-on: ubuntu-latest permissions: issues: write pull-requests: write steps: - - uses: actions/stale@v5 - with: - repo-token: ${{ secrets.STALEBOT_PAT }} - stale-issue-label: 'stale' - stale-pr-label: 'stale' - operations-per-run: 40 - days-before-close: -1 + - uses: actions/stale@v5 + with: + repo-token: ${{ secrets.STALEBOT_PAT }} + stale-issue-label: "stale" + stale-pr-label: "stale" + operations-per-run: 40 + days-before-close: -1 From eb42adc4c090918ad6be9fcb24066da8cdfd9bd0 Mon Sep 17 00:00:00 2001 From: Serenity Braesch Date: Sat, 24 Aug 2024 01:53:08 -0600 Subject: [PATCH 0327/2181] Fix missing include needed by clang --- src/managers/XCursorManager.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/src/managers/XCursorManager.cpp b/src/managers/XCursorManager.cpp index 7fc21a28..1e7ca535 100644 --- a/src/managers/XCursorManager.cpp +++ b/src/managers/XCursorManager.cpp @@ -1,3 +1,4 @@ +#include #include #include #include From 6a8824253c38584d233380ece1e090dd9e7f2e3e Mon Sep 17 00:00:00 2001 From: Nick H Date: Tue, 27 Aug 2024 21:41:46 +0300 Subject: [PATCH 0328/2181] build: Fix NO_XWAYLAND compilation (#7538) --- src/xwayland/XWayland.hpp | 1 + 1 file changed, 1 insertion(+) diff --git a/src/xwayland/XWayland.hpp b/src/xwayland/XWayland.hpp index d1cc4421..40c0ba65 100644 --- a/src/xwayland/XWayland.hpp +++ b/src/xwayland/XWayland.hpp @@ -3,6 +3,7 @@ #include #include "../helpers/signal/Signal.hpp" #include "../helpers/memory/Memory.hpp" +#include "../macros.hpp" #include "XSurface.hpp" From 17ed4fc04cedbaad365bdebf6bfe0160c527f3fe Mon Sep 17 00:00:00 2001 From: Tom Englund Date: Tue, 27 Aug 2024 20:42:30 +0200 Subject: [PATCH 0329/2181] hyprctl: avoid parsing string::npos on invalid cmd (#7544) * hyprctl: avoid parsing string::npos on invalid cmd invalid lines passed to hyprctl keyword made the string parsing try to parse std::string::npos, avoid that and return an error text instead. * style --------- Co-authored-by: Vaxry --- src/debug/HyprCtl.cpp | 22 ++++++++++++++++++---- 1 file changed, 18 insertions(+), 4 deletions(-) diff --git a/src/debug/HyprCtl.cpp b/src/debug/HyprCtl.cpp index 40708cf8..ddd1c1ab 100644 --- a/src/debug/HyprCtl.cpp +++ b/src/debug/HyprCtl.cpp @@ -970,12 +970,26 @@ std::string dispatchRequest(eHyprCtlOutputFormat format, std::string in) { } std::string dispatchKeyword(eHyprCtlOutputFormat format, std::string in) { - // get rid of the keyword keyword - in = in.substr(in.find_first_of(' ') + 1); + // Find the first space to strip the keyword keyword + auto const firstSpacePos = in.find_first_of(' '); + if (firstSpacePos == std::string::npos) // Handle the case where there's no space found (invalid input) + return "Invalid input: no space found"; - const auto COMMAND = in.substr(0, in.find_first_of(' ')); + // Strip the keyword + in = in.substr(firstSpacePos + 1); - const auto VALUE = in.substr(in.find_first_of(' ') + 1); + // Find the next space for the COMMAND and VALUE + auto const secondSpacePos = in.find_first_of(' '); + if (secondSpacePos == std::string::npos) // Handle the case where there's no second space (invalid input) + return "Invalid input: command and value not properly formatted"; + + // Extract COMMAND and VALUE + const auto COMMAND = in.substr(0, secondSpacePos); + const auto VALUE = in.substr(secondSpacePos + 1); + + // If either COMMAND or VALUE is empty, handle accordingly + if (COMMAND.empty() || VALUE.empty()) + return "Invalid input: command or value is empty"; std::string retval = g_pConfigManager->parseKeyword(COMMAND, VALUE); From 7dd0f76e5aa1e3726f9d9fd1871bc667237ef6a8 Mon Sep 17 00:00:00 2001 From: Ikalco <73481042+ikalco@users.noreply.github.com> Date: Wed, 28 Aug 2024 06:19:06 -0500 Subject: [PATCH 0330/2181] logs: don't get timezone every time logging (#7550) its expensive cause cpp dum --- src/debug/Log.hpp | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/debug/Log.hpp b/src/debug/Log.hpp index 4fc8ed5b..d3190d4f 100644 --- a/src/debug/Log.hpp +++ b/src/debug/Log.hpp @@ -55,8 +55,9 @@ namespace Debug { // print date and time to the ofs if (disableTime && !**disableTime) { #ifndef _LIBCPP_VERSION - const auto zt = std::chrono::zoned_time{std::chrono::current_zone(), std::chrono::system_clock::now()}; - const auto hms = std::chrono::hh_mm_ss{zt.get_local_time() - std::chrono::floor(zt.get_local_time())}; + static auto current_zone = std::chrono::current_zone(); + const auto zt = std::chrono::zoned_time{current_zone, std::chrono::system_clock::now()}; + const auto hms = std::chrono::hh_mm_ss{zt.get_local_time() - std::chrono::floor(zt.get_local_time())}; #else // TODO: current clang 17 does not support `zoned_time`, remove this once clang 19 is ready const auto hms = std::chrono::hh_mm_ss{std::chrono::system_clock::now() - std::chrono::floor(std::chrono::system_clock::now())}; From 00ee1cf98e3d8ef7cf71a9a505ba8d1382697e35 Mon Sep 17 00:00:00 2001 From: Vaxry Date: Wed, 28 Aug 2024 13:45:06 +0200 Subject: [PATCH 0331/2181] data-device: send dndFinished when dnd offer is destroyed while unfinished fixes #7496 see https://invent.kde.org/plasma/kwin/-/commit/711c5bb43f2823766d5189dc8d567c8f4cec253c see https://bugs.kde.org/show_bug.cgi\?id\=482142 --- src/protocols/core/DataDevice.cpp | 8 ++++++++ src/protocols/core/DataDevice.hpp | 4 +++- src/protocols/types/DataDevice.cpp | 4 ++++ src/protocols/types/DataDevice.hpp | 1 + 4 files changed, 16 insertions(+), 1 deletion(-) diff --git a/src/protocols/core/DataDevice.cpp b/src/protocols/core/DataDevice.cpp index b7640af3..8c1a48d8 100644 --- a/src/protocols/core/DataDevice.cpp +++ b/src/protocols/core/DataDevice.cpp @@ -67,6 +67,13 @@ CWLDataOfferResource::CWLDataOfferResource(SP resource_, SPhasDnd() || dead) + return; + + source->sendDndFinished(); +} + bool CWLDataOfferResource::good() { return resource->resource(); } @@ -173,6 +180,7 @@ void CWLDataSourceResource::sendDndDropPerformed() { if (resource->version() < 3) return; resource->sendDndDropPerformed(); + dropped = true; } void CWLDataSourceResource::sendDndFinished() { diff --git a/src/protocols/core/DataDevice.hpp b/src/protocols/core/DataDevice.hpp index 22bb9376..8aaf46be 100644 --- a/src/protocols/core/DataDevice.hpp +++ b/src/protocols/core/DataDevice.hpp @@ -29,6 +29,7 @@ class CMonitor; class CWLDataOfferResource { public: CWLDataOfferResource(SP resource_, SP source_); + ~CWLDataOfferResource(); bool good(); void sendData(); @@ -63,14 +64,15 @@ class CWLDataSourceResource : public IDataSource { virtual bool hasDnd(); virtual bool dndDone(); virtual void error(uint32_t code, const std::string& msg); + virtual void sendDndFinished(); void sendDndDropPerformed(); - void sendDndFinished(); void sendDndAction(wl_data_device_manager_dnd_action a); bool used = false; bool dnd = false; bool dndSuccess = false; + bool dropped = false; WP device; WP self; diff --git a/src/protocols/types/DataDevice.cpp b/src/protocols/types/DataDevice.cpp index eb6969cc..e95f1c76 100644 --- a/src/protocols/types/DataDevice.cpp +++ b/src/protocols/types/DataDevice.cpp @@ -19,3 +19,7 @@ void IDataSource::markUsed() { eDataSourceType IDataSource::type() { return DATA_SOURCE_TYPE_WAYLAND; } + +void IDataSource::sendDndFinished() { + ; +} diff --git a/src/protocols/types/DataDevice.hpp b/src/protocols/types/DataDevice.hpp index 948f47a0..f6757e1c 100644 --- a/src/protocols/types/DataDevice.hpp +++ b/src/protocols/types/DataDevice.hpp @@ -21,6 +21,7 @@ class IDataSource { virtual void cancelled() = 0; virtual bool hasDnd(); virtual bool dndDone(); + virtual void sendDndFinished(); virtual bool used(); virtual void markUsed(); virtual void error(uint32_t code, const std::string& msg) = 0; From d105c7403c2b700e4572149ecadd21e1d1ad24d3 Mon Sep 17 00:00:00 2001 From: Vaxry Date: Wed, 28 Aug 2024 14:05:31 +0200 Subject: [PATCH 0332/2181] hyprctl: add next and all to switchxkblayout fixes #7555 --- src/debug/HyprCtl.cpp | 95 ++++++++++++++++++++++++++++--------------- 1 file changed, 63 insertions(+), 32 deletions(-) diff --git a/src/debug/HyprCtl.cpp b/src/debug/HyprCtl.cpp index ddd1c1ab..683665be 100644 --- a/src/debug/HyprCtl.cpp +++ b/src/debug/HyprCtl.cpp @@ -1136,46 +1136,77 @@ std::string dispatchSetCursor(eHyprCtlOutputFormat format, std::string request) } std::string switchXKBLayoutRequest(eHyprCtlOutputFormat format, std::string request) { - CVarList vars(request, 0, ' '); + CVarList vars(request, 0, ' '); - const auto KB = vars[1]; - const auto CMD = vars[2]; + const auto KB = vars[1]; + const auto CMD = vars[2]; - // get kb - const auto PKEYBOARD = std::find_if(g_pInputManager->m_vKeyboards.begin(), g_pInputManager->m_vKeyboards.end(), - [&](const auto& other) { return other->hlName == g_pInputManager->deviceNameToInternalString(KB); }); + SP pKeyboard; - if (PKEYBOARD == g_pInputManager->m_vKeyboards.end()) - return "device not found"; + auto updateKeyboard = [](const SP KEEB, const std::string& CMD) -> std::optional { + const auto LAYOUTS = xkb_keymap_num_layouts(KEEB->xkbKeymap); + xkb_layout_index_t activeLayout = 0; + while (activeLayout < LAYOUTS) { + if (xkb_state_layout_index_is_active(KEEB->xkbState, activeLayout, XKB_STATE_LAYOUT_EFFECTIVE) == 1) + break; - const auto KEEB = *PKEYBOARD; - - const auto LAYOUTS = xkb_keymap_num_layouts(KEEB->xkbKeymap); - xkb_layout_index_t activeLayout = 0; - while (activeLayout < LAYOUTS) { - if (xkb_state_layout_index_is_active(KEEB->xkbState, activeLayout, XKB_STATE_LAYOUT_EFFECTIVE) == 1) - break; - - activeLayout++; - } - - if (CMD == "next") - KEEB->updateModifiers(KEEB->modifiersState.depressed, KEEB->modifiersState.latched, KEEB->modifiersState.locked, activeLayout > LAYOUTS ? 0 : activeLayout + 1); - else if (CMD == "prev") - KEEB->updateModifiers(KEEB->modifiersState.depressed, KEEB->modifiersState.latched, KEEB->modifiersState.locked, activeLayout == 0 ? LAYOUTS - 1 : activeLayout - 1); - else { - int requestedLayout = 0; - try { - requestedLayout = std::stoi(CMD); - } catch (std::exception& e) { return "invalid arg 2"; } - - if (requestedLayout < 0 || (uint64_t)requestedLayout > LAYOUTS - 1) { - return "layout idx out of range of " + std::to_string(LAYOUTS); + activeLayout++; } - KEEB->updateModifiers(KEEB->modifiersState.depressed, KEEB->modifiersState.latched, KEEB->modifiersState.locked, requestedLayout); + if (CMD == "next") + KEEB->updateModifiers(KEEB->modifiersState.depressed, KEEB->modifiersState.latched, KEEB->modifiersState.locked, activeLayout > LAYOUTS ? 0 : activeLayout + 1); + else if (CMD == "prev") + KEEB->updateModifiers(KEEB->modifiersState.depressed, KEEB->modifiersState.latched, KEEB->modifiersState.locked, activeLayout == 0 ? LAYOUTS - 1 : activeLayout - 1); + else { + int requestedLayout = 0; + try { + requestedLayout = std::stoi(CMD); + } catch (std::exception& e) { return "invalid arg 2"; } + + if (requestedLayout < 0 || (uint64_t)requestedLayout > LAYOUTS - 1) { + return "layout idx out of range of " + std::to_string(LAYOUTS); + } + + KEEB->updateModifiers(KEEB->modifiersState.depressed, KEEB->modifiersState.latched, KEEB->modifiersState.locked, requestedLayout); + } + + return std::nullopt; + }; + + if (KB == "main" || KB == "active" || KB == "current") { + for (auto const& k : g_pInputManager->m_vKeyboards) { + if (!k->active) + continue; + + pKeyboard = k; + break; + } + } else if (KB == "all") { + std::string result = ""; + for (auto const& k : g_pInputManager->m_vKeyboards) { + auto res = updateKeyboard(k, CMD); + if (res.has_value()) + result += *res + "\n"; + } + return result.empty() ? "ok" : result; + } else { + auto k = std::find_if(g_pInputManager->m_vKeyboards.begin(), g_pInputManager->m_vKeyboards.end(), + [&](const auto& other) { return other->hlName == g_pInputManager->deviceNameToInternalString(KB); }); + + if (k == g_pInputManager->m_vKeyboards.end()) + return "device not found"; + + pKeyboard = *k; } + if (!pKeyboard) + return "no device"; + + auto result = updateKeyboard(pKeyboard, CMD); + + if (result.has_value()) + return *result; + return "ok"; } From 8210a1d7ac38f6af76ccbb831dc1d62b1ebc53db Mon Sep 17 00:00:00 2001 From: diniamo Date: Tue, 27 Aug 2024 09:48:38 +0200 Subject: [PATCH 0333/2181] nix(flake): update aquamarine --- flake.lock | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/flake.lock b/flake.lock index fd06ac7d..0eb6ba07 100644 --- a/flake.lock +++ b/flake.lock @@ -16,11 +16,11 @@ ] }, "locked": { - "lastModified": 1724273991, - "narHash": "sha256-+aUSOXKGpS5CRm1oTitgNAr05ThQNbKIXalZHl3nC6Y=", + "lastModified": 1724781866, + "narHash": "sha256-ItgACCJCwn8Rx7p8hJBpnU9eCtrdmkg4AbqMZL/rXlY=", "owner": "hyprwm", "repo": "aquamarine", - "rev": "9a3161ad4c78dc420d1cbb3aae638222608c7de4", + "rev": "7cc3d3179c06caf3769afb3eb0c69aa55676c96a", "type": "github" }, "original": { From 98e99cd03df5b4421f72f2a3f2d7de53f8261f1f Mon Sep 17 00:00:00 2001 From: Ikalco <73481042+ikalco@users.noreply.github.com> Date: Wed, 28 Aug 2024 08:07:13 -0500 Subject: [PATCH 0334/2181] renderer: ensure buffer format on commit (#7556) --- src/helpers/Monitor.cpp | 11 +++++++---- src/render/Renderer.cpp | 1 + 2 files changed, 8 insertions(+), 4 deletions(-) diff --git a/src/helpers/Monitor.cpp b/src/helpers/Monitor.cpp index d81ccb3d..2b8404ee 100644 --- a/src/helpers/Monitor.cpp +++ b/src/helpers/Monitor.cpp @@ -915,17 +915,20 @@ CMonitorState::~CMonitorState() { } void CMonitorState::ensureBufferPresent() { - if (!m_pOwner->output->state->state().enabled) { + const auto STATE = m_pOwner->output->state->state(); + if (!STATE.enabled) { Debug::log(TRACE, "CMonitorState::ensureBufferPresent: Ignoring, monitor is not enabled"); return; } - if (m_pOwner->output->state->state().buffer) - return; + if (STATE.buffer) { + if (const auto params = STATE.buffer->dmabuf(); params.success && params.format == m_pOwner->drmFormat) + return; + } // this is required for modesetting being possible and might be missing in case of first tests in the renderer // where we test modes and buffers - Debug::log(LOG, "CMonitorState::ensureBufferPresent: no buffer, attaching one from the swapchain for modeset being possible"); + Debug::log(LOG, "CMonitorState::ensureBufferPresent: no buffer or mismatched format, attaching one from the swapchain for modeset being possible"); m_pOwner->output->state->setBuffer(m_pOwner->output->swapchain->next(nullptr)); m_pOwner->output->swapchain->rollback(); // restore the counter, don't advance the swapchain } diff --git a/src/render/Renderer.cpp b/src/render/Renderer.cpp index c601e369..7d63468e 100644 --- a/src/render/Renderer.cpp +++ b/src/render/Renderer.cpp @@ -1910,6 +1910,7 @@ bool CHyprRenderer::applyMonitorRule(CMonitor* pMonitor, SMonitorRule* pMonitorR pMonitor->currentMode = nullptr; pMonitor->output->state->setFormat(DRM_FORMAT_XRGB8888); + pMonitor->drmFormat = DRM_FORMAT_XRGB8888; pMonitor->output->state->resetExplicitFences(); bool autoScale = false; From 9642311ac2ffa6605d84fef2bb5179f6588ae074 Mon Sep 17 00:00:00 2001 From: Vaxry Date: Wed, 28 Aug 2024 20:33:29 +0200 Subject: [PATCH 0335/2181] window: don't focus on activate if window isn't mapped yet ref #7089 --- src/desktop/Window.cpp | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/desktop/Window.cpp b/src/desktop/Window.cpp index 582e96a0..7da616c1 100644 --- a/src/desktop/Window.cpp +++ b/src/desktop/Window.cpp @@ -1307,6 +1307,11 @@ void CWindow::activate(bool force) { if (!force && (!m_sWindowData.focusOnActivate.valueOr(*PFOCUSONACTIVATE) || (m_eSuppressedEvents & SUPPRESS_ACTIVATE_FOCUSONLY) || (m_eSuppressedEvents & SUPPRESS_ACTIVATE))) return; + if (!m_bIsMapped) { + Debug::log(LOG, "Ignoring CWindow::activate focus/warp, window is not mapped yet."); + return; + } + if (m_bIsFloating) g_pCompositor->changeWindowZOrder(m_pSelf.lock(), true); From a95df6b57e68785c13fd2d7f93d9eba28b9406ed Mon Sep 17 00:00:00 2001 From: Vaxry Date: Wed, 28 Aug 2024 20:37:07 +0200 Subject: [PATCH 0336/2181] xwm: don't mark selection events as succeeded fixes #7401 --- src/xwayland/XWM.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/xwayland/XWM.cpp b/src/xwayland/XWM.cpp index 07208072..5ad146e4 100644 --- a/src/xwayland/XWM.cpp +++ b/src/xwayland/XWM.cpp @@ -539,7 +539,7 @@ bool CXWM::handleSelectionPropertyNotify(xcb_property_notify_event_t* e) { // Debug::log(ERR, "[xwm] FIXME: CXWM::handleSelectionPropertyNotify stub"); - return true; + return false; } void CXWM::handleSelectionRequest(xcb_selection_request_event_t* e) { From b9b8e6220f55af34e862b541a5a4b30ae6d8f15f Mon Sep 17 00:00:00 2001 From: Vaxry Date: Wed, 28 Aug 2024 21:54:49 +0200 Subject: [PATCH 0337/2181] renderer: fade out windows on silent moves --- src/desktop/Window.cpp | 10 ++++++++++ src/desktop/Window.hpp | 4 ++++ src/render/Renderer.cpp | 21 +++++++++++++++------ 3 files changed, 29 insertions(+), 6 deletions(-) diff --git a/src/desktop/Window.cpp b/src/desktop/Window.cpp index 7da616c1..a4ba366a 100644 --- a/src/desktop/Window.cpp +++ b/src/desktop/Window.cpp @@ -31,6 +31,7 @@ PHLWINDOW CWindow::create(SP surface) { pWindow->m_fActiveInactiveAlpha.create(g_pConfigManager->getAnimationPropertyConfig("fadeSwitch"), pWindow, AVARDAMAGE_ENTIRE); pWindow->m_cRealShadowColor.create(g_pConfigManager->getAnimationPropertyConfig("fadeShadow"), pWindow, AVARDAMAGE_SHADOW); pWindow->m_fDimPercent.create(g_pConfigManager->getAnimationPropertyConfig("fadeDim"), pWindow, AVARDAMAGE_ENTIRE); + pWindow->m_fMovingToWorkspaceAlpha.create(g_pConfigManager->getAnimationPropertyConfig("fadeOut"), pWindow, AVARDAMAGE_ENTIRE); pWindow->addWindowDeco(std::make_unique(pWindow)); pWindow->addWindowDeco(std::make_unique(pWindow)); @@ -52,6 +53,7 @@ PHLWINDOW CWindow::create(SP resource) { pWindow->m_fActiveInactiveAlpha.create(g_pConfigManager->getAnimationPropertyConfig("fadeSwitch"), pWindow, AVARDAMAGE_ENTIRE); pWindow->m_cRealShadowColor.create(g_pConfigManager->getAnimationPropertyConfig("fadeShadow"), pWindow, AVARDAMAGE_SHADOW); pWindow->m_fDimPercent.create(g_pConfigManager->getAnimationPropertyConfig("fadeDim"), pWindow, AVARDAMAGE_ENTIRE); + pWindow->m_fMovingToWorkspaceAlpha.create(g_pConfigManager->getAnimationPropertyConfig("fadeOut"), pWindow, AVARDAMAGE_ENTIRE); pWindow->addWindowDeco(std::make_unique(pWindow)); pWindow->addWindowDeco(std::make_unique(pWindow)); @@ -407,6 +409,11 @@ void CWindow::moveToWorkspace(PHLWORKSPACE pWorkspace) { const auto OLDWORKSPACE = m_pWorkspace; + m_iMonitorMovedFrom = OLDWORKSPACE ? OLDWORKSPACE->m_iMonitorID : -1; + m_fMovingToWorkspaceAlpha.setValueAndWarp(1.F); + m_fMovingToWorkspaceAlpha = 0.F; + m_fMovingToWorkspaceAlpha.setCallbackOnEnd([this](void* thisptr) { m_iMonitorMovedFrom = -1; }); + m_pWorkspace = pWorkspace; setAnimationsToMove(); @@ -502,6 +509,7 @@ void CWindow::onUnmap() { m_fAlpha.setCallbackOnEnd(unregisterVar); m_cRealShadowColor.setCallbackOnEnd(unregisterVar); m_fDimPercent.setCallbackOnEnd(unregisterVar); + m_fMovingToWorkspaceAlpha.setCallbackOnEnd(unregisterVar); m_vRealSize.setCallbackOnBegin(nullptr); @@ -542,6 +550,7 @@ void CWindow::onMap() { m_fAlpha.resetAllCallbacks(); m_cRealShadowColor.resetAllCallbacks(); m_fDimPercent.resetAllCallbacks(); + m_fMovingToWorkspaceAlpha.resetAllCallbacks(); m_vRealPosition.registerVar(); m_vRealSize.registerVar(); @@ -551,6 +560,7 @@ void CWindow::onMap() { m_fAlpha.registerVar(); m_cRealShadowColor.registerVar(); m_fDimPercent.registerVar(); + m_fMovingToWorkspaceAlpha.registerVar(); m_fBorderAngleAnimationProgress.setCallbackOnEnd([&](void* ptr) { onBorderAngleAnimEnd(ptr); }, false); diff --git a/src/desktop/Window.hpp b/src/desktop/Window.hpp index e1850fb3..bdc275bf 100644 --- a/src/desktop/Window.hpp +++ b/src/desktop/Window.hpp @@ -352,6 +352,10 @@ class CWindow { // animated tint CAnimatedVariable m_fDimPercent; + // animate moving to an invisible workspace + int m_iMonitorMovedFrom = -1; // -1 means not moving + CAnimatedVariable m_fMovingToWorkspaceAlpha; + // swallowing PHLWINDOWREF m_pSwallowed; diff --git a/src/render/Renderer.cpp b/src/render/Renderer.cpp index 7d63468e..33679731 100644 --- a/src/render/Renderer.cpp +++ b/src/render/Renderer.cpp @@ -266,6 +266,11 @@ bool CHyprRenderer::shouldRenderWindow(PHLWINDOW pWindow, CMonitor* pMonitor) { if (pWindow->m_bPinned) return true; + // if the window is being moved to a workspace that is not invisible, and the alpha is > 0.F, render it. + if (pWindow->m_iMonitorMovedFrom != -1 && pWindow->m_fMovingToWorkspaceAlpha.isBeingAnimated() && pWindow->m_fMovingToWorkspaceAlpha.value() > 0.F && + !g_pCompositor->isWorkspaceVisible(pWindow->m_pWorkspace)) + return true; + const auto PWINDOWWORKSPACE = pWindow->m_pWorkspace; if (PWINDOWWORKSPACE && PWINDOWWORKSPACE->m_iMonitorID == pMonitor->ID) { if (PWINDOWWORKSPACE->m_vRenderOffset.isBeingAnimated() || PWINDOWWORKSPACE->m_fAlpha.isBeingAnimated() || PWINDOWWORKSPACE->m_bForceRendering) @@ -540,14 +545,18 @@ void CHyprRenderer::renderWindow(PHLWINDOW pWindow, CMonitor* pMonitor, timespec if (ignoreAllGeometry) decorate = false; + // whether to use m_fMovingToWorkspaceAlpha, only if fading out into an invisible ws + const bool USE_WORKSPACE_FADE_ALPHA = pWindow->m_iMonitorMovedFrom != -1 && !g_pCompositor->isWorkspaceVisible(pWindow->m_pWorkspace); + renderdata.surface = pWindow->m_pWLSurface->resource(); renderdata.dontRound = pWindow->isEffectiveInternalFSMode(FSMODE_FULLSCREEN) || pWindow->m_sWindowData.noRounding.valueOrDefault(); - renderdata.fadeAlpha = pWindow->m_fAlpha.value() * (pWindow->m_bPinned ? 1.f : PWORKSPACE->m_fAlpha.value()); - renderdata.alpha = pWindow->m_fActiveInactiveAlpha.value(); - renderdata.decorate = decorate && !pWindow->m_bX11DoesntWantBorders && !pWindow->isEffectiveInternalFSMode(FSMODE_FULLSCREEN); - renderdata.rounding = ignoreAllGeometry || renderdata.dontRound ? 0 : pWindow->rounding() * pMonitor->scale; - renderdata.blur = !ignoreAllGeometry; // if it shouldn't, it will be ignored later - renderdata.pWindow = pWindow; + renderdata.fadeAlpha = pWindow->m_fAlpha.value() * (pWindow->m_bPinned || USE_WORKSPACE_FADE_ALPHA ? 1.f : PWORKSPACE->m_fAlpha.value()) * + (USE_WORKSPACE_FADE_ALPHA ? pWindow->m_fMovingToWorkspaceAlpha.value() : 1.F); + renderdata.alpha = pWindow->m_fActiveInactiveAlpha.value(); + renderdata.decorate = decorate && !pWindow->m_bX11DoesntWantBorders && !pWindow->isEffectiveInternalFSMode(FSMODE_FULLSCREEN); + renderdata.rounding = ignoreAllGeometry || renderdata.dontRound ? 0 : pWindow->rounding() * pMonitor->scale; + renderdata.blur = !ignoreAllGeometry; // if it shouldn't, it will be ignored later + renderdata.pWindow = pWindow; if (ignoreAllGeometry) { renderdata.alpha = 1.f; From 92a0dd164e9cc74060b63abae67b0204b6b6074c Mon Sep 17 00:00:00 2001 From: Mihai Fufezan Date: Thu, 29 Aug 2024 13:41:03 +0000 Subject: [PATCH 0338/2181] flake.lock: update --- flake.lock | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/flake.lock b/flake.lock index 0eb6ba07..219cc08b 100644 --- a/flake.lock +++ b/flake.lock @@ -16,11 +16,11 @@ ] }, "locked": { - "lastModified": 1724781866, - "narHash": "sha256-ItgACCJCwn8Rx7p8hJBpnU9eCtrdmkg4AbqMZL/rXlY=", + "lastModified": 1724850097, + "narHash": "sha256-3BHxvFb3NJzch1X8puRMkVZujOoarQ1llu3ZcwuvsKU=", "owner": "hyprwm", "repo": "aquamarine", - "rev": "7cc3d3179c06caf3769afb3eb0c69aa55676c96a", + "rev": "23c7925dd31e79e8c06086ace3edb129a070ac01", "type": "github" }, "original": { @@ -116,11 +116,11 @@ ] }, "locked": { - "lastModified": 1722869141, - "narHash": "sha256-0KU4qhyMp441qfwbirNg3+wbm489KnEjXOz2I/RbeFs=", + "lastModified": 1724863980, + "narHash": "sha256-7Ke9wFRYPUIXwm5ZndGHkWBKj6BsFTkSEXUNXQRHE54=", "owner": "hyprwm", "repo": "hyprutils", - "rev": "0252fd13e78e60fb0da512a212e56007515a49f7", + "rev": "aadf9a27dddd2272ca354ba5a22a0c2d1f919039", "type": "github" }, "original": { @@ -154,11 +154,11 @@ }, "nixpkgs": { "locked": { - "lastModified": 1724224976, - "narHash": "sha256-Z/ELQhrSd7bMzTO8r7NZgi9g5emh+aRKoCdaAv5fiO0=", + "lastModified": 1724819573, + "narHash": "sha256-GnR7/ibgIH1vhoy8cYdmXE6iyZqKqFxQSVkFgosBh6w=", "owner": "NixOS", "repo": "nixpkgs", - "rev": "c374d94f1536013ca8e92341b540eba4c22f9c62", + "rev": "71e91c409d1e654808b2621f28a327acfdad8dc2", "type": "github" }, "original": { From 604eb21a7e55d85ec7f6cb8cba39fc4c20a07a9d Mon Sep 17 00:00:00 2001 From: Vaxry <43317083+vaxerski@users.noreply.github.com> Date: Thu, 29 Aug 2024 23:30:12 +0200 Subject: [PATCH 0339/2181] renderer: better lockscreen dead behavior (#7574) --------- Co-authored-by: Mihai Fufezan --- CMakeLists.txt | 10 ++- assets/install/lockdead.png | Bin 0 -> 113201 bytes assets/install/lockdead2.png | Bin 0 -> 49466 bytes assets/install/meson.build | 6 ++ assets/{ => install}/wall0.png | Bin assets/{ => install}/wall1.png | Bin assets/{ => install}/wall2.png | Bin assets/meson.build | 7 +- src/managers/SessionLockManager.cpp | 5 ++ src/managers/SessionLockManager.hpp | 1 + src/render/OpenGL.cpp | 119 +++++++++++++++++++++++++--- src/render/OpenGL.hpp | 6 +- src/render/Renderer.cpp | 53 +++++++++---- src/render/Renderer.hpp | 1 + 14 files changed, 171 insertions(+), 37 deletions(-) create mode 100755 assets/install/lockdead.png create mode 100644 assets/install/lockdead2.png create mode 100644 assets/install/meson.build rename assets/{ => install}/wall0.png (100%) rename assets/{ => install}/wall1.png (100%) rename assets/{ => install}/wall2.png (100%) diff --git a/CMakeLists.txt b/CMakeLists.txt index e8ea4797..84a856b8 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -336,12 +336,14 @@ install( install(FILES ${CMAKE_SOURCE_DIR}/example/hyprland.desktop DESTINATION ${CMAKE_INSTALL_DATAROOTDIR}/wayland-sessions) -# allow Hyprland to find wallpapers +# allow Hyprland to find assets add_compile_definitions(DATAROOTDIR="${CMAKE_INSTALL_FULL_DATAROOTDIR}") -# wallpapers -file(GLOB_RECURSE WALLPAPERS "assets/wall*") -install(FILES ${WALLPAPERS} DESTINATION ${CMAKE_INSTALL_DATAROOTDIR}/hypr) +# installable assets +file(GLOB_RECURSE INSTALLABLE_ASSETS "assets/install/*") +list(FILTER INSTALLABLE_ASSETS EXCLUDE REGEX "meson.build") +install(FILES ${INSTALLABLE_ASSETS} + DESTINATION ${CMAKE_INSTALL_DATAROOTDIR}/hypr) # default config install(FILES ${CMAKE_SOURCE_DIR}/example/hyprland.conf diff --git a/assets/install/lockdead.png b/assets/install/lockdead.png new file mode 100755 index 0000000000000000000000000000000000000000..f8bae2255f9a4f576011355c8242cbb8a88079ce GIT binary patch literal 113201 zcmeAS@N?(olHy`uVBq!ia0y~yU~gbxV6os}VqjoM-xwysz`(#+;1OBOz#w-Bgc>200A5Oih{)C?9>v4q}24xJX@vryZ0+8 zWTx0Eg`4^s_!c;)W@LI)6{QAO`Gq7`WhYyvDB0U7*i=|mnkaMm6T-LDmj8IREY2mP;kyKN>wn`Gt*5rG%->zx70Ha)iPA=L8)nQ%_W&>IP`*KPy!&eA`^#FkPKXDft7PnYGO%# zQAmD%4lL~iz(QQX*%_2pEEF`tGxJjN%ZoKZ-hk>!bxABqwN)}QFf!3Ku+TNK3^6ja zGBLI?vCuX!vNAA$DD_P(NlZyBNyJoaWMyb%WoU?^I6oybt&*Tpc$8Z?=jY@X`R1pj z+A0|ucqiS6q^qmz?V9VyjeY;J6+Yh+Wc%ryU^%=FB>#2jQ( zL9R*xxhmBtG1>7OQxz)nOBHhR zle1G(K+GbA;^d;#)I5cx(h`M|j8w3c61u4%Cs1rE)S|?K0)>>!)D#6P4Fv_yG>{_{ z$`kWS6iV_HO7lQ20|~+0rK6CZuaKEnlCO}MmtT^RTBJ}?QmLSks+X>(kX%xfqn(&j zqU~m^siTmSpRSOZr=yUVm!eQqnrEe;kWpDslw6XdpsSk+P2CCx3Xd9QWT#e^=NF|Y zF4`nQWg9ZGK)bL zfg>%iG&d==NFg&1B9dRAkdvBLqL7?ll$Tnhr=)MEV51MJ2qDQ^ACa&@sSljEK^XvC z8(Dc|f}*GrnhkOa*WSWR;i<$>7PL;yX1(2`UUr2%usLRG@&1Iid;_h_U4v zsd;$IbcnLz{Irtt#G+Kk^whi(VyX?0=RtnQaDQ=P8GhHBS{PecnwXpGTAC-B=~^b6 z80lJAm?!BPr5acoTcjAJrWzZ;e2?jRa3y143aezubUie1lQRQj^nCQ!LB~_y$_c`4AA96WV{G7_RT#+eRMQj0Q?QUbCq za3?5G(LRFdj=07FBm!`xI~v6kxDbI93Hs=z1%&Sc2~0Oo^ne?jR@lk~VpC#JYMNCF zQu7B?t`Of)f!LoQ=xC)F2l(5EI-30`-RM6cF94)Vvg1r6MJJyIH@I zgcumtxO=)dhE&{obGNfPIlR`s?)2^y&+y-RH>agWZpt}5O=tb4wP&ZLL~eT0V(M`7 z`W6!rjVbvH0yF}qIcYFDDYTd>wy534o=7R=CMvv~h z|2L58{o>e}zs+rNWJH9%J zonwlQ5>Bp67EVipBG+EKdGn@=(!{fA+qZ9jDgPz@*McL)8FT%_yN`bR_N|ZY!qFr_ za7ZvPI8-|`@G=yXP4Q~IYO-VJo$vST-|T#@YwVv2tY^f8MEIOo@bG(e*QEr5 zGiT2}E!ugQQSa|`y9^Vlr7_*jX8Fa%pI3Qx9bI((`Q(2pc@PI$7=n^#y35KC3mxY5 zyLSDS&wE+*Eb03Hn$>@v&+NX-U!U}#a^|OyjE4JxD?=79Uc55oRYse){1Sgpv%{j{ z3U}_^TPNZ0{PWL=69sjgIKYNpI0g#&If9Gp9vp3bSN|{R`qTSM&p(=fTD&^1dVNi4 zp2vYxIUl04wpLYD?F!HcIaBa5cv9?f|CJ%T?!N1a*3)y!*c!F59+FRPNibzFG#D>1 zkY<~=_v&B&_#H;I_x@l0+aE7c@$%gS$M!a+i3%JK3wA{4$ek_lUMf`UwfLe(@#&*4 z_B`ThsjjX*nQ|$?AmKk~Jcxl|3)s77mu;BIK5zcty{Dx2|9Ag3+4}eYA5yK72W9?D z1IOfw9ewdDL%Lj)Ch;!FJS-+IuAOIDTTodUxha|t>_di9Q2t-AQbg?Xf$mRt|9>xD z^JS-u!~X}`%=+3%Y$h@nGE7dNKD~yas;(|hfF(0;XV~iAqe-H#^Dj*E-dO<&CWb4l zAg`qbYMm~gA0IQ}?*r{MFCzb3F23*n^x}mHQLSdo6T?==#>c0#Uf8^O^CaE{y>7{7 zv)4*EynpwuueUdm)d}nvNM2ard8%}N`~>auwa=EF-}L`q+JAXl|3t%uM;|o!E%#Ot z5>397w9&%SQuAizk+R*k^UsIhDf+eJY}(;-tYA|z@#in)i3ZCWxH7IYj;@K}CX*Svqmwo`A*E{lcT`Q)RPY$CO>7#dU3AnzO#X8Cz4 z=RC9g>#ARgXd+z>=$6a%(*YwjzS1p<2xBP3>UX$%H%P$vR^P4k!_T-$GSztpL zR)~W#3h&|&tvT2BZQmdCZFP13%-?@rz7DKpzVX+?(#$MOLqv=1!pab@<(EB+Py4D} zzIIJ4`>o6R>#Ktno`)3kTP#6_^e!@Z$sRXl`rj|F_k8);33A8MId;ic9TNgph6oD_ zuUYy>sIw)7Ib-+Td8eOh<$XJMuJ82IphdT#hFF6QS$LHvZ*58a@5@iQq}P1;dC7Ti zd>y}5KEr&krL*SD(GlwwoqQ)kNA2v=KU2J(zIdUL{isZBvf=ErH+Dii1TJD7m{&~s z^fckT?EB}sHb2fBoyTp?cTCy2sez4|Z)=pTt!=Df!@b+LZ{N5vA&p^e(8?M+`Rqq! zMl+`%!bKV6ny<_5#8-TnX8*qG6;t}dgYWk5&D=0W;*vsbTk?vluWsJF8MHFQupurw z`f`TJr8{pD3{Kp7^Yv?K=CfxI#{|TKQr|1Dl_5Phe&74~YTfbk#a{NO>neU9Ftu#u zG0yy4P)~q{HPjcO}7VY3tXl@hIL5Nq!6Vfl8e#lMf}ntUtRs#eV2~%-`Tt+fw@-2T#S<#XqA0`n{_WdPpQ7p0r!SrP6Q~Y&gKR;AQZo zIbLh7W+iWoI4a7~ee}_jCriAR9)e}ZYH)x!t_yMZQq-T)s;)< z*B9J=5V}&aneQyC>BS5aZ*T843|2CH-o_2rUVn{_j$Xr1RZCP>k$Sr3nfh6VTS*(A z6z%L{G^w3q*KNxUcEbfuP>jrJ3R?MLcXj^H&+EL!Z*cS5UHN^p{KWG=xjQ~A@Um3l zcxs;|IxRFuW^LH+jT-|EPwGzfGB!5O+8R~m-gfC_$+OQtyJpWlo7U^5{7naJtOLYV zL0(IfZruBRF1*~ftZ$}W{JtB1x100ko#E$vyY<5YuaySUPl6veZ#r@7}%JHGA*YtxK;jmVvZB9NfX)cH-K-^uOu(Nq_(3 z-85znP#R!TdVZ&GK^QOQ2 zw}1ZQrRV$aT>m~VTl8Dm>eAI4X0XlMdiC>zipX9%5~ern(qb1 zSM9CK&R(4~DOy9s&CN|k!eRB*S37s^3|d)IGW+|tZ`ZD0-x{Th5^4d~y#_n>Ui-V< zyiiQ;&90J#-@D&WJOAs}T8m9yn)5$@uX~mIf3}_cpUOuy=kLnPomr#hvtnILx&DI9c>kU+3fA@EybG`0*)Dm5*ARhHNBMeM0>OCbGtCb zM%ypTpEvgN=IL!ujC@k`L+T-1utPX!CU z7r%eA>x;npAIJ9JHLD2CI&q;dG;iyygGqaSS8p%67CYtdgKdrBZ!~kBDaKe`Z@!v! z_GytQ^NSp_Y@?Y=ZuoAw)!WN^?NDcMa4;z2GBEIQG$m}lxhF1PL14lDm-m^jeP?Sh zYhsXMSdgW)v?goM_hZ}3Yzya!@BjBm`tSN`zuVIm3bY)oSn_;d|0V6Gt{?1wW&PiJ zKGb6E3)AIGLbT@krQ6M4FYzqRNOEyt*W|OMRC#Z_<%_=iVCF z-TD6RdYNtAyvuw^Y_=a(tq$ydeC6$08Ch9f5iZfgch;`e-5b}n-6~_XnYno+xB9NT zd7vm_V0d)&-iHq#E{ZOnd~(UAG-bX>iM$#_xybU=N9Oyl`NVZxH80Ue!r-L`ee_!eqBqColP@dowqeb z+>eEUfg!`F@R#xG8&NiL*R!@}s4`?QgJQ97aoE(=a`qoKu1ml1^0Tq{ZuwtF5|Rp6 z6su`Ud~Lpcah|pPg|Amw|Jl5FSO4$PfzO-Y?o>&ByfS3f$&)9OHr|LjEHwMr+#W!{(SZO=e}R})@=NJ+niS{ z$$1uEwTs{Ksq4>ut@{@n+dtP@t@+=(bhgcbzp6@BM6JB~>gCIqU5qBZq1Uco&%C3w zx4F%Hy87gk5t6gQbgNvOdCfUFB{S2rDZGk-K^+u+4dtOLBuc;Sec%6Ma?S4l zUr#fiKg}cgb?yxpt)(@WoPAZQztqLC{XKJZ-ugdFYwR52`}0DDw?@hGuthSKm`F`c zV>r7qdal<}gX!#`zOnt^nR@?g?B;tdb#i8OkOq}}2bL7v{Pq7u<);7t)YPM<{skrS z+HHrHyuXtcq$N7B@yYE_CTd#R}J~}!&Y_;fXGiHZsuyqMn`1cen|1H1&fcJd) zo!j5h!cUi&SS&JTN$<$6IUnx+%wsY+Po4d276e$RSX|<^?6}sTnN?*G_%6e{bjZ4-bOH ztL$s{+E_GR6FSK}Zy*1EPW|S6H5-4+?+?&p)8)ummsP#UZS$5bA%z7_%9DTotaPmE z^_+cV=GMJ?_Vi@6F)%P(IQb%}bMvV!JJODQ_+YTip4s6x$TI~kQL6Jlf4}o@-#YI- zm(JUk*L&=cbZj#~+<6Rpj-Rl;~_~p)>IVQ|6 zKi%RZ#j9>If9~9=56nRACzH2cni4!=HDPZS{Mvl^<&iJx3>oU6e8d;1CA#?BzWo(z z-(37%xwYs2=W~tI-}6cuXfG6Uw2kN}{eM_@58I!gcmL+sYG$Q}J1@ViD#Us1){DCR z@lDx_v$x)=usL_@*~ych5HGD<%)9h%-u+v*l9rw?*(k!nvgBKbbgo(Mq&)e*%nvOX zu5f{R-T#9kdj8he^uAdhZ=d$?VEJCRhg%lytT_AQR{H6GuV?Q``}0wjdHs#x2;U4n zyIrU5-?_8K!tUnXyI(78gk%_AeEl`;c3Oj&ui=%ftqL4p%=xq#8m1kX|4&EndX9;d zYH8SVbE)N*CAnIYe!r0a63qRufM)5+4V?3b^iI?F?yWK{7kZL-Mg2!HkU2K z(&W?jn>lgo%>_6v-2alF!pOiNRQ~2m`mUg&-FJh$=iAEp8_l#?vCi%Pg8!G;Kkj2@ zxC$B~*x;|sb4z^|7&tL!770&ake&5x9?-Qz|gSp=vvJ}J1McX zObip=H8?Mol9fH1wt3CV^VZhZhYuf~WYxR+YS#So;UA->*m=x9bV!aNKoyjToVk{7 z-SgqW`gd=4o$2w~{r_h-v%VgWSbF9R)SD#_IpM`r7Tk=iE{|AM1g@Bi%3ZEx zl^RH_u?Sc=@#?Kxv#z*>F{~~1E3lgTv0~2D_#;V%GD!>!LN4MSj~_o?bNtqkm*-2a zs&8E$VIp-F)B>BO_{H&;2vY{b3L%h7a=>-;Z)@|<%U;-(t$Y6~T;q+$e1DgvAwTZa z)_<+Kx&FNDWXJoT1%IB>d6oS??(xcyxb@RT9hL`aa-LHYV`(%ExOw|_bWF?<2i6Bi zeAF)Ax+SGuE5@8*lfn=n?zJ>%ZP?}6Qh$3-nH5yIEiOz=Z8iQInRRu3y>-Z?jEK$K z1RabP;2V__vrMA=+HUn?SKrjxmw#XU z^T!4rJ|SL9lajW)KU{z5>yOHNTkibMpWyE7JmY6k)~A&p@AdE9`MUG-p2`dTb6@{n zeO>!cp2-f6wPF7L{+mxldVG$op6fT=Lq&@(gwpM)!~d=lpF=XZMi75$tRx{eJMAQTH3GB+$Mba_1Et1?lmvZFAdTJb=yuZ)xCe? z#)=&`OJdEft-Cu}A<6r~LJ_g#|Fh$Dejhcj=zd)L{#xVnCGB5UERW>Rnp$)2{_mUR zAB;0@o`3)D|K{lnADqm;?Xz~7c6FE~cjmQVGYOvP=x9-PtyZUlZ_AWrnO98pS}G+c z=eIOy&X<{e`c|@89n#X`KA~blsP$joC#f{vv)+mPA%`dl*k=V<8 zX3kH>7CioTE+FRt#I`nYKD89MIplao;|_ zcDW#ihTuibC!Q8<^|-v+WqcIf-8NG3Z@nkW1IKzdxM8kih%z`Sa(Io6jFPWo9>@U)6%~)uFuY z=|+;*9&X#Sr^o1ZfUuRNzpwAcyffY90;pzV^czCP@s;0fisz zt*mC9ej0I-buPP@n3#d8@PfGf#LJg2ula5JrEvcFc6Z(dYGU23dUY0;=O2E!A?1D6 zh3W~%A15w-{-yAjP9F!u3OP`jD#F#B`9O8|rulVqr`y?A)&HNrFCx)+@y=Nr-QC{& z&9B?|W@5GF)_`66ziR%hs_?kGFnoK|S~Ickjc$j6gM)>57Nn=8Y4zR9{IYf1Hn;U1 z$Fxl37CZhscI?=-Yhgw+=ggm9zB6V<7+V4B-njF-SXCDtW?wp=@zv23BTzF+aJt{} z!X1ul#a$;)p1g)(deyCG&z4QGo~po6(t50ld6Dv=w9Se7%np#W*YkL5^HP`Z_wSyG zuK3XTdGGum#;vzIuVo2ct#h3MD%~!zKJ%-5<@A2}y=5~b-k!OtP--R1+ZM^V<^KEW zw~h!)t!_D-7`FDn)TyGqZpkK6;$mWa{l{MfOG``ZP3Qi+fbrjVmX$%iK0XCq`ETC5 z@$vI}w1RQPb;0Lft0GVHU-~Vww|Lrl?{<@nDt?`eXzf`ijY`$iGJSC(_Z4; zuIsONvokR)Py=O}yP8wGIxpTkzi02B4+^V)9DCY*m%ld2V7uLtgNK@Z)j6J?eEI(e z>$xXiz}?2;OR^C>vyL5pSu#u1;qn28CdMzXUTI}tJ+gDB<>ZrF_U()N$UW(#O79Va z8H^SldM{QavR;UejxJ$ykYNj0?(Mqt@WX_?54-wbUid98#kDGZ^GyrU*cV!UO|4hf zRY)&7ZFcSUg>T=?K#5V5DT5)Sm}~jg|Nr;wdA+fCPEGK)_vJh>lR>S(b(?Rxn-%Yr z_)=d#IhbdcjeTw9w#(0!OZOhjF*`l0SM}ho#y^X$8XFt?EuYM$E4p7{^2r5z)DB#z z6LUL$=-M^0^tT6BuGF03%f3QfZ@CQ!fC5-eeyjLqIGoUKb?=S z&VLb#(G$-;#t?ggm5I@&iJ4)m69X?puFbp)JnvL@|9>c!_LTS6=NmikN#9%ZfoJj7 zb2Ai9Tt9SI-2SBY@b8>4+Ii zd=Oz$*!f^8lK{W!_S?NWJPZ1A%%oqJt>4kWs8;Rt^~mgwHMiehS^VhZjw!3{`QNTT zd9qTiflqAu>DKLv3@gC#7u>W>-G5A+X^^US*_k4_`G@3{~uDt z^|p2U-aB6}J(tz;=V`o|xp}G8+$-B|rWkF^YJ2ke=f{tQVWEst{b$dg_pUS(aF~2= z_c!@FX}(U@!U*AHt)sLp}Un%+ctiU2d+oOBB^W@2sh4w#y zjvbpWef-g4+5y%EVNk#It;gC){?*m_mF&xxIA4F-Z7ZH9b7#i!L(P{KZixPM?{C!2 z#ovw99qXT`{jA#ItmSxlLPbr@oKOdYnLb_y4cnsD&Y7iXH^1L>;q16&#~&Z$kUx;L zv0zg7+_|!6teIEnHy@nfp%TF^E8AaT#lC9!#SEu~0_nd#A3N5@;=LmFV2aVkdz~*- zTMj3lkzjy0DA#>uNDu$_y`QgciZ2$I`?LKv+q|u&OAgx@WxlokIcNX#bNnT?e+!=O z{dT(gSN!KSinZ=wOQe4SL2!v%gHCtoH?^0&d+T2(V|xjkAlz7d3j!g zl_B7JxnBSA!@I6~v){dQM`oIQ%d6d!FTZ?pCE(W0n;(DH2)z${BwVrP^iHRR4U)_Z z1xDa0775-m3eu+V{SNE3}TbT7vocuR;<8M9NE7gyqt(I`H z_xeZpKe{}jA~)AJi*bwB(nmax&CSil#l<7fTdZHdUO9~U!t1XeD`YOuXPnh`&oewc zJo3G-#ft@MC91-F?UtA4zkKBTYy0h&zlyW6x=OW0yxo`&bSgHmHGEUzXl{-8{yp#M z)VhCXnZW~rXIigKQagGiWXJ1J%WpOP^wzz5&+d9H-0SwW%2tYN)f>M@ zU((P0*gL$tos zzIb6QUwu)%@b0RI4-+U0ywV=FEeRj120{3{niYT7y;=SpT*wkUM?u{(n9HzU9$flSz@0kt=7oU1V@*(mrs3tyt*u+O@jZR_IJWZ7IX2l6~P} zj+u1!8Gn_CQuYN`C3}y3{aSi0c7BLfYY=n5R}B|S8=Eth?U$GOdHd8qv+oWDkG>ZK zFdR4us@cpy8Rq^ErJL*DJ)Khb?%#BM-gm0)8wxgm`TlIf-sj)Ght4}0r^oy^to7`j zZ@mkyW-Y#`q1`ZV?%b)j4BQr9++a4tZpY@$hoznzPcpPQ$0_T#H0bBwx@$f@zjj=I zeRPKWg1#e1CWO{I@448$$UNY$>FrOSj9y!{+wI%5>5|ap`K*o{txj{8F6e&LVsMxR zYLZ49ykd{rary86eP?{;|9>96>HnV1|954JhzUonW|b)Un_nGyeKLR8ovF6Z?Uof- zTPGSEo;5R6M{N1>xTI>o34Ix%=+@e+t-&gfnQcG?#A11C01vxYMwoRZupFS#qZfU zI%3JPC13t^&zu+V_bb2p7Tu{{-rnA9%?nlU^}Lvrlb+sQ`caaD#UPo1!4I^|V~fRB zFT1yI|32DXxpcmM{F}d@s-GO>oKlx3>9w>b)9ssl{OXEe$8W2v**{C??&nkN?VWrw zg?sI-bfcLOSNSdZm%1$uBp@MS+_I*e2q=j}vY8J54&d&w2lQ_4Vz4t0u8EH%|4u_@UvL@uXW(Q@uCe_swLFiy(wg{0F5bMShSdZsg2Rq;)ibc4mD5L`%?GjEZ2VNwO6}D_`Khz-;1+s zsQYyAFT<|0-0ZV`)OOujZ^3ip=FN$>lz*D!&73(iu{S#6^NxvY7&ErsTDnvRzgCr$z9%GVQ>bUYVhnoNY zIeKvKlL>5(zlDX)WBmKGJd|&Ny#4*}@2+e4l7WOi94e0vAgwt5cEHmJ>a; zT==!|%JY@aH}`Q@%~V!a-jT-K5DaSb>AEEvf8YPob<_MiC!;GqsF#0>FZaEDog?qF zZ0`0ibuaIpk-G4{=IexobJaC2hVHxkGR5}#Ouywz&B`N|Up|_&@zrws{JcD=UbipB zFAAi3(-IRKOP{y#2~S~SSfT&1Qudr<`qrd}0xMo^YLEYGDZ#Vtf|mG}m7t-W>}?@h zsb;e`US@nS1yu5S8@^zhH-GBi4`p#LpWn9$Sa<$`tYh|8lh(_(ihuv!HE(A`AzMjh z?#XTQ7|-hKcqpf=WWBJ(*2HdQ-OqzBUuOCkGA~fHl|8rSa7tz-r>QyPs~W{jgAe>x zI=$RiW0q9f$Xz?E{it--<(D}NZ?}I*I}-In%G-_EVK2B00j)97E3f~3d8+ft`=a+> z{JmrS)L2;K@10j7deP@&|#U`S0@YtHjTf724qCb~>2ncJ;gc z3m=7)-&}wG>;I3YZ)F`mcYjo!?75Qlg4^Q4>gwI6Knom_V@(;XxSlYYd3ozXv2C`NWBW*Rr}wHk>(sKKT*@)FF-9%11l)zMs2(nr)T6 zdhN8o&*%PKUnwRgmm}R}82K$+Qr6aO7h=n*EK3rPRav$=9en&T0p_3yR;^b}K76vhdH&s_kb4tstLp#Xj$0HB}*z5D-1>#5zp_wTcu5uN|u=>DAJE#JR=Gcz+&G2Q7_BQtfg)cMA@Z{J>% zn!#w&p}?_u^X4^%^=gw3HZw7l)~_zweRs{Ru%9*a?wu&OaBw5I@1As2+vL}SCr?tc z@1`zaZFElQQl|@3cNqgX2Cf1NWWiqzW(@mPx}6<54+n#B+Rz(S6V3i z-hNw){lfps_LgstTFb}QyoRBwwl+2h)Y6_cV@5*nEB^eSXU_1bl``?XU4Pq? z-RQMPr`zH$tQo2ezxHixb5itM7(JQO|Dt2)b(^~V`yU0zmxP(mKC4?I-OSf@@}%dr zuhA<*X3d`MY^VWQJf`sUw9?cX-8;qS-7C2H^mogr zE#KeO|J_t`?fSRJDPgUSQa0{Noy}-z%r4sG{%*C5L;ZK- zuFi|!@)#TioE8dbH%z-_5xM%Rp04gjHUsul7Iif>gC0hSTl%aH?aZrB{62TC@AAtd z2bluyH=lc0kg_@QTI~FjCp~QzFoy=MzItWup@#)Z6HlZV&7M8GB+<;w?3zADXT?Yf&&Eg2W|fn4Xp&h@mF{r=xu>(u3+Os)I(@GbNCTT(`kET3*mzVLPb z*QK%kbJo{ffB24HyY21Uy9`YVXU?DB%=BXEQq`9%7fe=_Tg_b)`1fG&922v{25b&4 z$KM}1#PoWeuhC4Gzq}2<9!>AMb?;u;&X^sqnN7cHEWYS*H!UY8r=;Xc(#8u@qq9pD zZ~eP^HT0VGM2mce@>B+hqeL`gw*7m(ZsOlha&f=@oUZ=0zP9gBOJJ3C8N=$8-!ES; zw=LdyXkGoUhxh#V`6e1~FXz5speEG0VV($RuGxdZH(7V})l-#qpA`ZQcV#iOxBo2( z*q}DI^>89%|5pZ+kFll`JuU=xhBZa44AI&e&W}Evz}VU=uit< z&Ui9##usM&`>+39*Z+L!x%>O~zb};L+VgHJ{@qZ&=J)RTFL%XgHq*;l@{A*?8zaKP!hT$xf7H`NBZFH(NM0&IwBg=e&_bgbC2RrlY|V+q z#gj{~s|$55U@$4Ua$6vF|Jt={H>UB6bRTt4XwWuiSfS5yfkDC0>g|KPJ->g?UoT_V zRX=anh3eDRPm2F3`mD(D)_R&y<@#;&DQ$sMay#=M?3}5%@a+0dR>z3AxOEl=8dJSK zfBu{<=g?g|-;zIHZh;`*D^7+#?Dl9rN|_FjH@jrR7nYjwMiHnlM|`~p?mL5l>RWIvquJO4%1uf%g-p3f_m zmj;hOsQY|8KYBx(u@Y#|sa$EqM1n5;X3++wNx0wY1F(r!H9B*U{O@d9B%^n=Lz>YxTwLj&^Cq{&oou7w@luDI*K=BTw9sthYYYeN+#dMhrqdGPY@ z8|z*3Y9`FIi{Gd5`@1z;T&by;Tuy$Mp!<1S`IUQ^9xmmsegD_F_2va|A2M?5&vON7 zT|q0C@P7VTGt=kUs#i~nEH~fmiQ_FO5U`wk?(N%LKgJAj6Q=vDOU;; z-I`<8U24s+z!8*fSyoKx`uK3)_x<}`fBd|sl^wJi<5##wOoh*;vnSKlPPrb?{?-^j zU%KMty9vwwE@#i$dh6@guU(8K8zbh-o0s?RMnjvn+v38!yuMJk%}P?AFPAS2Xa4i; zt>4m5ReN{u-n}M>0kpcXH2W!Y zFv*IaO!@R-soGw4Utiygl|pZs8G1p>U(VH~ERZPu2AMy2y5xMU|D5-~AC%4ws9tz^ z<&@@5*PHeCA}t&Ky}ZsI?ES?w_dZX_*Zmte9-O6o^UuIx?;88s`kDtnPpnr)4VS=HI+5Fx}ll*RNnUV%{RM_dvA>R^0P)mAkh8F zjFN3ORqqz{o2*@Vlu03LYt-ice~$l;vK&s6E8%NrW|w97Z*b6)lVKJEqY1+tSx4RY znQtpUJdX9ZKQr^+oxdN{*|;|<%BlsHv9y*ic|N=TY((RSh4=dRyC#~JI$6H}t+71G zwZK-+UzqL87wt1?#Tp{FZr+u+<%du*|+rN3@Lf}^s9^R-n&<3 zHP?gjm50u<_>Eg%KJKlvaMrQO-5T|>N0x_8{M$wQW5o!tMACyeRlXS zAAebKyV94czt5hjWgk`9e*5kV#?4V{mnHr@b&4zdPMzz8n2(Q_24&{u@%fiH38Sty z6x#FI@wk(QNRq66rwh~8jMt|V3^pv=mu58c*wou$D?`2vbGjwT{NpKyvS!c(ag9ZZ1q*M*}doH|9SEAgI|1X z?9yO8qZh~K%E<7sujXICV8X!QU47tGzsvvYkzb2wWCDM@$x)bY3aqyiykd|_vXz4 zvD~|+#tqAwxBp^y=ew>sYySNF7{dvC>g$|NYN@!^GO)`sFgRQWbqCelS+joDEO@?- zKP)cwU3p;gd)@aF{CoLV8fd*x$-4R=)Du(~%@h3p;xF_0dyCe;oN#Qz&73t$|8KgP zb65QxXH&xV+sYF;cu%bM^!HkN>DaNh(@%p|UrmqJT~fL-L~HU%6GOv|TeeK`P`UK7 zL~CkPM1+K-sP^04z~&TM%1?!vM~V!3xO-t7FU!CAW}j@NIw z#V^-`2_I5kZ@pCh^KYHbwObRs{Tvs3H@!AH%0|xp3qLdmF6f-%^>fMc_lNUeRDE(x z`}OC{(Ru9ldhy)l9xLN57Ho+AWmge0JhI%<{_Xo-i$nq_^NJWFrCO|xCKf9KA~^`3K+js{7!giFr7 z&|y2*&)?5a?jFPHtEYZ_V+-ZZEWPq(@#4j6N;e+4apm>bq>sn63b~eDFP!%JWntIV zDPF2N*Kcynkp!*oFSWD|WM3Sdu`y!LE0MDD^5%mIhc4{eKiO)o-?c3zw^B=HxxRo0 zcx1^fP-jBEcIx&I56-`rtGIfVi(Ah5olVu-1KR5+{rzsPUEUKv|MmWFmd>~QR(dZ8 zT6ygF@yJx|*Fm8UbAG(}{`>OFlBuHJ-b;gY#EN&{ZGWEmNj=*;>)%S3j_#z5YENb7 z31)6g;JmiVq;la-;rHcMK@qnjHALLp-6ytQl}#_RnY;Cchs{&FrOhR!rCU#>yZ?A` zByVff#?!Ar3v>MZHofD`$V80&($Jj zDSC4~9?HJl`}F+od38HJ?fFsv^U{N7MbAYV!d8aNNi4RJvp>7|*Q2E7yzSMswR?X> zR<}AO78YL2+a7P|Il1l@Xa~-wZ`ZDc$*ykQ!uT=s@6@SNlcndB@qT4|#hI}sd8Uur zH5K=lEEoP9y>RKJ$)*i%3qJGDZH<`Rcl_8fKbc>b`Ig4I9WMfnAe{a7txRd+1DkB8 z+s3A*SBoYunEHE#>5+PmtlKYoi!w7iOWUX3WBmAyg@NIM4`^8J;}xx+k9^LD-@9Ep zbMuD>&bHh4`-4_>az(HUwH$oA;tl)ujlbO9PrtYJLtn`S!Ns8EO5r~3nL56QpG{`H z;I(wpzQU4{lGIey`RBteKSt{8e)#=&sny+!HI8%EoaI`ex|L;)NQTKQ2ZaFNclz%# zw#1p{m`N|^=y74na1=Q7&|o#gmt)7+Kz=fgQ<|7?_wmBZw@$wM*ik%x`t<4jzVkDm zry0%Mxzlp@-8=({7e~(R;&hCc>^>T`C{1v0P1WQ@nso&D*!Gi!VkoXBbw=$;rh< zMV)$D6zX>V(ULt+pQg4SJ}9+fb%@sf`{%nt9(}A3RtmYrR#jTHciz8gpQa?Fr&}#V)_K|N86HyG))-gM?u%i{3kiDnI1m+Wm%wz$gB>&efxzE4=L z_hs+%sMe!b0(}=<%n%b7k7P8dU3H3KmfHid?$oNPs^a3!zlzR3a@jL=s_697rEl~X z#S4O##DC#b%f9Zi{<^!;#KV>xe`nh%9b|DAV7VnYhik(cqYD)te{RTG7#kOdZFg9; zBt+}@v11V%ll7)APF{OeJ^9kNV0H7^XTNy8oa3-u)2dxZSNGz6NL4;rC2G&ib7uZXPK`Qeedl?wmfTA?@go z4->ffoys(hb}W9r?fa&xjyK24r%acBv*F#rnOoiE=ggn~{QNE9$qK8lT3K33b{~z{ zD4xv~r#1D{&zjJ4%3|8LuVrs4^F6Y&#XY*yPHF4UC08c-EjOO)7a!W4w6S875aZmh zc86oHO~)T6{!O{1;-~oIa>%kgmbGEt z>s96Y!#7`3dY;=V)f-ivle6Yg6jQIm`-U}N)n9J)@%Mjxg^PjVLJBAl0-b|?&e{L{ z+3VeUu@9!yz598r{pmu_CFkdQFO~7pJz4jwG>m_t-jaeS>$RaKQoO6fn0x0ufA%aw zIep``&4(Xyur+tOEDF%LViKL3o~|y#cX`L&Uq76|TTre14A#u^TYme-jTJwfRE*w# zWys}udm&0#=GU(Pjg~1-OxU@6w$x5O>5^}5sw;h0pXcW>(^Vr`P+EE!u(L{p%+|lM0|+pAE~u z2j{;AH-bP5`?lMK##IFLaxIrVv*308?b9<(^Z$Ew?_kg(=4uZ0by{NG#>U3(?(ZMn z3Q$&7p6H=6*YA2rf%Bh@uV245QCn}SzifScTwI!JHg9ay*&MUYhZgv#DbLlC*^+G| z$Db~@%OX%D`|{i$35jcsj$1|e_3&-{`0?Y^sZ-CM^|d;cwDHE9H*3zOS(`O4+jlCe zW>cwpa@Y3VYHDgnPVrowpSwcSLb&C1w^UhC(Wa!MJg4>f8Mum z-Lf*PmAkb+zufih0`0JKOYWB*6ED=7dNe6ACdOvl4Ue@eRtFfH?PBgQz8|UUV=KT4 zI)q^s=!}6YwGS4BRJ8s6_bKY;`tyaC(r@;^m#7G=JF&pIxzyXWmb}fJb6y`-um2t^eyVoM>6Y3r{2MQ{ zOj*tq^t}K02%}Ux4HetgU?F#NA;Iky`ppz@&7ULlmC9tKJ#Vf zKbx|3|8w<&Ep#$A^eqeGOIy6Det+}UKMDV5|4Z<=-g%lOb8FPK2bJaJ-xY!v@6ViJ zYiGA_+qP-vpJ(?rdM&+l?b?#*V!|6Ym;az5wGu8I|!$*AjB|Lly?nWse?Bi{IA z&FI+LlgWN@{e_n$YLh#w4&AtMI+FNzW?XZSpPZcdiFO~ibj=K#Tv~_NzIB| z9}eEPGylAJ|M8c~Tiwoo`8v}lt*-9g)1u6+w=TPMB`H4Zl6H_bv$VXqpwRAb#5t$9 zD>_>eg>FvG&dy#Vt0HzYA|@v1lT_7}dLFjs!w(niGch;czG;)wU)|YfpMC!6v@pP? zrA(<-W%}u*mtSU>c;))tFFj=!9AC9}-qu~pxj#>wIFV^Kb=S(%2r~UPc?CjS!jxC?>u(xA>lg8f~ zE0Zj%keA(-p%y_auSAAETrj!${`>WtKC$K6@BQ}nZElulmXejvi;%FtzXfXz=Z3zR z5_Eq%=da9?wB)@kw>+vIJ2Pg0dh4Ky`l~WW^UVy<^wrKqO+TK$Y_C37Ut_Sb;nMlJ zevx`tFBSj(9pM^PweRQkr@KXDJMC8*3vl@O`(JMO&vM?qn^k_=^yzo=w)-u&{<|T5 z^;IgR!#5UiIS^sk5mru{1J(IG!8os9f(5kD>bAR5Dyr4F@^J~u`M|KXj=B;welRQpY zSzchfymIkR#g!4SW_^7Zyzz$MUanU{ziP$0TmN}4zn>Mh#KvOjnzd_h=4`Xt7hz?3 z(Xwmn=@$tmQoTD^m>C!{>_9nmy?5Q#nsfJyzqfh-|`?n zHL;mr&F9r@cz<_&XoOYCloKx4yiV`rffO zY<22coxGB_FK3w*m6lH3y1DDimw_bg*^toSokdFQD^IrRoyg8O* zR@{{_-D~NtmVhm)TV}8Dopdrq_VuoJ@7{I2em^&t%{O<(>8BB2xBfiM9G0WK@saV{ zxmigTw+c&AEa&=#DF@ig$jhgPGT*p&ugpSbZ4j@+;)@q7TP`ozw#@5k{Bs$iUr*y_U~sSo4Iq?qM2Q^! z20p{$#os+&e%im6sdySHYrR}_-2#ciFL%BkJash+G(l0YI4NmMvUGcJ=mQp3b2BqD zrbdR|ldO&_s;?Yff56(t=1xaJZ{4!P4-;6Uf7bk)GPVA-)9S06mYH>1a=aDU8g+K2 zQ`~fwxwj4`ZEQLGaI)_l`!dOm9x6_Ezw$)iPTO4g=;*9@TbJK;{F{}Tx$@W6uPZ)R z?~U^_75X)EVZaLBRg4`=C-mFuzkT;EXnXnYyH~VLerK?6Ts5cr`3g7jGlnyL))XK8 z_RVbd-?DzfLUv%aRUNraf_um|qmYsb%$IQG^ym*@1njNiwKKw0^ot@n6 zb-D8P^UrhlZQ%cVY2!x2Yl=S4xpv>}<2GPmXfOtCmG+xI?Il~>KK0)h!z*8YuCL$x z{_Xk@i?tcL8o`?En*(pw*Q|a0>1bE$q2Kqu&QgqRzm_Suy5Q4t-muRB#b&c(qoSnb z<;|sfv$pPX6jV&#^et2CgWToX9Z!QZtIuWqU3b{JFeRmBb5X3(%q&fb>dq^S63VrjV;g4&Q3~NG;2>p4U@6} zhs^I~ZuXzQeCK<4HZLu$ZR=y9&Lf#+k_-$Cb3mKcEK)_5Oj+N$dw+59Q!3WmnAG!dili76r3Q>wjFOTsKJ&7cANyEgvnE<_Wyq>i^BjI_3vh%4 zYd$3Iu1Wv;8;<-?A*uc4XY*I&5<(|*S@!uUr%3ue(n(mU3(jwGoI_s%*`{)wZ9jt zeMsAUQ`o+FebCA|e(I&mCx2bKxAv<4_T_gkUhrI_leN`KfMY{bpp{JD+*!W652P5i z9)75GIxk@JlFONeUr!|S8*WtJ@J+vVkE3bUtL|SyUxVsGtA6S17vcPxa;>xJ*20Cs zwU+*w8>X#XqPKD5#)FnDEBLQ0tuRk-+7ltR^Wrj z)Z&xf)7`nX)9>@NBd5L`J>;$dI##V9Ou&KpfF{SG2j|+}q?a3Bex9yZR{#9j!L?Ht z24DZ${B7ZNzCB6)-{SA5oSR;M{9R1L&#yN0S4H!y+g;q>J=M4FY;s#1858rwr=E|kImzYR`~%gqF0ot@Ugbak z<>?jgFQ&bD^JdBAmo7?CLo``)k$=D#bvh3 z-VazVJnEglapT4co48cxK<&WQa?xdv8B9CwzfXVq_^ke?YNIQhmVYB{F1>tmIA8de z;+(5qD?QI^HQ4={&{z@PT)o%e7R)bLbaE>Zfe?qBSjOXu(Y z|FpDG{2kBBtr^-s?&ldB-l~4RJ7V**RQq4A5;QM<`~39ii^`Ogl*-DVCaVu${H~{? z({a^ID*VOF!$})AXvya1=bLAQ>FkX-cc}Jkecsnw ziufG3lX_`&h^~>TaLY&u@gwH>JeMj=Nc(oT947ppQf>(+> zXA_du|N83HBdeBDd*(TBjy(NX5pnVDLCxBnoHtWWTGv|7&9&J7!sPRmm%CT!Z@gtZ z*U$XLLKy}I2Jp^Xi;oxLCH82k{=T~ROe=eRY5srdxCI+#UJNO)m?WulEY*I`+~5ta z4~w@KGGDNWUw*l_uMd>ncHC;4!P?@aIQ#6iCz|KO7w{&u2G8_a=D2l6ubXnVSMtID zi@!!;%dPaYOy+#p9-?*j>{;0*i?+N6EkXPF^39#LjUOR_FelytsLn(%GE1lh3v;@7)ri^T*?FSId-JUB5(4oqY8tnDy_QxV8T9 z!wm{Q)0{jH#tlV$4V?c27^@k`(P zYp2BTO{x=o|ST|%|)qj)AIC;?;HL0KhmB5 z?7j*!149GoG>iu=B6;cWr{6oP`S;HEg|9`F`AkIq#BG->3^@K`*O!2&v&H)F+^&CH z++LDvojR}W_~FBcSFc_jsusWIg{1^fl+Luxx+aRt)cM+*MIDx3e#y2}{mU)O&Y)*;dB*ykmj599Qcr3)$#3f=7Ope);FYewVY);@n}wFR!8=f!kHmpuUT` z%zB=fy_&zD+ManNegAKdjf_Ol!fSFe@628uJmU2Id*0eRxq8#J+fIw8-zxp-DD|t# zX5QMhYghXvrl%i&S>mO#{n7e`*B3C%ihpW6`)u4q4b#bPixa1+hzU>7c9N;9t7^(z zc*R0lS$WQpfH|=q@x@IFZaI}w zyu4g_V#n1i+m8?3?w{5=c1cKEVAk2REbVh8{|YQ(Ql-4_&I@i@yfD({xhAhwtc;$p zi}cA=FO=l0H%6>^w5WA?PRhBrTXyM`Mx4!@v-yO|-Vax=hTb}7mB%?(LrqOB!aV6H z)4Q$vYCFD9i*T2j8|W{V#moR%h1W1Sfai9#{r7Y0PK#@+clz5!%sam7>Vkz2zVGTi zdgK4J=_R&>^RDKeI?W%|ll$}5(T#?yV;sH)t(;OKr?gDm)XM4yf<&&tT~uqQJ8ep-fEWF&aWoyQu}`ymwwfbn$g_n zb#0-euZw$0^Q42X@+Wov?k@hktS_5i?%4j$M`gRE=gzzo+0hqs&T-?;ou0W7->q4` zR9ohElrYHcZ7g}S@7bD{UiKd{_U40*lL5^`1Xyp)Dya7T)}6m$nf>>e9UJ$a{&DE! zB!-_`wm<(TJ!A8;|6flxZ}ixGZkG7Us^EmCfaC(fEXxnX|MFPr@zXWy~>S^RLl zN5#=lc5!j>)iZz3@msF0rsfw}&~WSK`|q27IUCKiIc%+Zb-~%kPbPiYm6n#aYQB5E z(aea?H7{8n744J~cPP$dma%icXn*b6HH*y+D?ghgg@#(CtT5iND%pIOU$@)hh03#n zg}ii9FL#_0eU#O*Cc3j^PLY^k>fZx5Z$_TGxze%w5fcOC_y>oxB4WYsdGpi!>gyi; zIdIzBxk-wbb-#PS^wZn^d^exzdf5J#TIeRXU%bIFmyw4-X1JwKLc zg|$2=;m_(~Tl%DAUy?7&vU@i!Y%)taDtGPAYvJjKR>-|A4?CIm(JsK({Nam+q|hG0 z_wsYDMuQGV=>Uzpo^=-cSrqW?v2{dh&FRbY_bO+o?`S%d_U`YG=w0(x*4%gcc6m43 z_Qkm|CNXmu&q}`P7F4WtR1sRZ&?x&+ijLT1zr3YED=k)@b=(mg|0pYMP3!Np^z`#7 zxo%lp=ZbQZD!a6w-M?7I#>9B7ukZL{)3+J77=HbnyzCf5F<@xAeo=G~?H@)1oHTO*wM?4+{fB2Iz#l1=ke2*S&wc{tc)G zVfeL@n|b{{smt>pdhjfexie$>-v`=Lcb_#D2c7S9C^h>rn?Sb1=4a^_KU5SK7gtr? z%G>_>>#vn7S9T?T(oWjC`TpwPu51yECCzHt(mZToQ#*}g(z@iIzIpTJLR;*_B^f4C z=R)4SdaZf+^-?=yLqo^f=FKavpE~6gTh(_lBgMDp?DNmPtCtpt)a(5@*y8^29{=ip zhYw!Q&&|C!y|XYS*35rT@S(25SzHCu1T_hpEUd!T*d+#>#E)z`~8_i67cR1tb;bLrv&hNwO1$7X)<HqR7|FxfIg$Nsm3tZb_5oJYCMi?z?a{95JbU}PUd=nJ(zkj}@IR+Ha`$#z(rE8b@>^MGbu~DA&9f;=`y@A( znaDm6ivKLkz_36Vv@#`%xHQ4-?4 z6|!-L&T1AHz3H1Hbk63p_qrL|+n-+*zG3%nYg5zG5~YP#vr=`vJntJB8V344Q}s)J zvi$rbkvCPYpC8T2T*Gkd@kbNg@Tcl~l9+?)JyeAL>^%R)`A%N>UGv$S-^5K`-WA{2 zck1KELMzsbX#vg`?_XiM(#WqB9~^w4@a(JeU%r+It^Uf8*xK_bsptF%^|z1N+4Fw?T{DS(o`;I=JDMD?|Nr&;wA|kLmG>VtU*B5( zw^#ev?Iwkctx+E@zF+K|UFal}z3suRTeC{Sf)@GCojEhnRej6KUXBIs?(UI{C029y zEjm|JT(;tF-t#jXeU}EA&3@apW#ayX1ik62jTVTcGs^GYq?+rzH|p69hFzIEwd(c$ zoH)U;_sP+tu63s`_%Fy^SA9Y48`m|JN1JyAE4{O`+ACw*bmXe|Q77RmDu}eRnymn1&b+ySt@6X zoz%G}|KsBId}5ECC1n2b^-ezjs_<*n$8>SCq~M>Y<eW?p~( z*;HxfBmLd(yf^+>t3KM-WGwx+0PQq{7XIcawTEFylld zUFu~EEsfJ(&M~vIJ9kTSWyq>`(hh6ie*gV*^1iiU*_Yp`1ePzFtnxY~BK0fJ?6b$J z9yqM2Xl4SPH=Yh!iyY#s%(JH?{M+hk?c*K$ca=YAwRVo;y~SDA?|8lbZE@=UJA_qf ztBnN zE}t;yNZ8FmceUobPdl{COsQd7l+}5CPNlq{qds>Y7HoL-`r_)@vu3R_VpyfturB%N z!{qD&^Tex0g5V_$s(W6RSWWdR^hy@*c73(0cXr#E^?sNCSgV#i=;`k-J``4X_|Zp; zt)1teC!dvBK0hG)qd=YO%U9~Z=ksj+eCw9fYX@%?p*b(luW8=??zzD7%O`hE4Z0ua zwZE@8yTxVk#b^HKmw#q^y|XJz?QVCwbauGfWKS#qN0*ow7#^GfEgQ_zJQnj*W#c2O zqUmz4{vMgHDI>N;=#SjqZU6h{saHRV3%faOUbTJDzWm1YWd4WCcX@kzUs{>!8GWd# zVXtGM!QW$`bK;IXY+ILh?AAOFl|wVVEzHcyOnyEMe|zKRO-VVqbw>K@)EdsEZN6%A zIF7e)nWFl)+^7r6$7ZcDTVnPwL_*<;rLS7>W3}y<^p-g{Uk#jHBkeiocTLVpvBE5~ zw~l_HUA?`%QR+{Mo+)%k);Oy-Lk@D=#d*-O?1e$jp)ctZuV$sPf>!!}wOwX$KF*|G z_9F8Yc8k>G{d=dMTp6Xe^*HF5JS$1i;Y(%}6Wo`j*#Gc)s`AmCpJz`Ee`?LcQ+CG2 zf$RRAnf33_iM@aGe=)b-Y*=R16ThXTurM&lctK`xh{?eGoGkCD4oyXVehVF%xhWu{>IM-$EQtM>+KFYb-eV7+wyho z=FPh@roQ}q@Ky1eBikZ$e*OJ7YuWKn)w?b3Z(I1gDR|SI;^|50>B}=uXMXBWx-}^( zd)|k8lS_A9y&8J%OS)C++|V#<8=Etlk8-x(wyZt#u%O^qgm7OuZ1iPC(St>@6<@D{ zHfBhumDT@NYdzoV)^xbp>F1K=&$H`8cV_(fw`%I&`cF$sssf$h)tM_01vnFQw z<)e>3cJ1F7q2uT0XZHDFVe`QQk*B*u`<>Q?u{S%0u}wMuTs!P-f@K+7Nv(QY@ihI# z@hU{fol{Hi5nB7a;e08;VPft&QpZLazHE~<3 z{2J;^R}217H2S&`bjU`m!mH%3Sq=;g3>K=O(kb=Bg7?s-o70RRUk-!T;Th(*D<53Q z;AZ@Rz4E5Nw*SocRnL;n|203M96aM+jmZ9#RZEyM>Rg|><*f2sp3J&n_wL<~A3ye; z{qorQHl1r?D`vDw_qturmRey+41Q+8n7L z`{MTrX;CrZC{8}Td!lva=fm%vp7Za|iQ2#UHG<3RHzzTLO>GWZS<)o6hWBnrSlGP< zzE6+zwK^@#>~7tC2E`t#`#Hxr+)zyHoTwRvlppru*Ey5u{a((gb2jMyBx`DV`I z^v!a|*6%y3_4iGQ)$Gl!R|29xq`b7~LnOrPwvR4P{D?+s(E z)q8~I7F+m-UpSXEb+@4Wk%L?<2P|DX95+iC2FEYj9JpX>#)N%fDy8s$LkN zA=G){D&O9h>)$QzHnEDnx-s7D0lWed%(MV=4H^S40rkKo%Y#uzdSGck@>~5 z^_!314>{+R-FqYCT*$#1yZc)z0_Q}|Jed-a$@f~YuI_4Ij9&Qb%a2T=o`p+jh;Zpm zUma(x5&2#E$k*4i%q~xez}&bj*MOV{33QQphnu7pf(zbrB* zn!98dU#nBP^p#KIGnURfX;q;s#{D`XyDnBOL-dOF3(%O{%e5`{q+S%ImX=QSD~yhg zzL_)aUg%2~U-$UJ`8yI`-V=Ou{3Z7b?U%1#?tXE{`*@L#*y8V}Zr+Tv`fnk_S9O2+ zyIun+h6D~q6NV5^!&h(qU0bfjc43qId-;mWOpk6$wGX#NT&~u&Stoxuv$bRPUM_+xw0N^}DXmuBw_fbKC3d@#pm)WezBvEgwECo{r7n{Wroi( z50#+cdsQX9j$y}_nccZ@W5r6NO@7OhUArDliN5uq?H%jZC|M4ch~qD3-gmdGIhTHS zy4Ar${cDO%zw%z&cOq@`*_e`zeecz_oCPh=PMCYH?&~ajzPClStCq}jo6hwm&gXCM zIj1Y0M>>A8n7{pzZ}r9aWsZ-1eQ|MdW@hI(*DKO5m$Vy5F+eKPuB4hBzvc5*#`rzF z_?vy+Y{{VHKF&AgqMH}~_mB74yXaHRPf+9O_soMw4o%<^zkjCCLVN4N#Gu9UQR_|3 zAD)TiZgncXAF}x339UT^O-x&t-|YGNwbXBA`{J4Uy=J;%+|LDnOt#Ig&taH*Htn_0 z=T6i0k&gb8pZ9igTZY9ynDNVJaQzTkVg{oz&5qxlxFnnrQ1kmgx7ZP)*g+-n|5KYe+= z{$o_@-KJ%aS_J2WOb_M?&YFFyGUL|~i%RXXM_#m-rQ$y*m&%GS0>wHQB2 z4Sj1-*ev5>z~(I5wf1v*z_QCP)5In$?M+-;cXE}^#V60%euUP(j;?ZA8e}Qcr*%2~ zct!C0arwt8Q8P;>F2_**?6KYnz(?zSM8qt)r^{S_9g_e{Dx|LCDR z%irw1a?{PtEuy?XLq4=7Y4OeLd`$&S46|nSeLWyhJK^3uzk;AvGv#Y)pDJvmrKL;0 zWv9J6!?~D0&FymA#ordOI*Ofa4StY9MxwaX{!izr;wX9RaJ_>I1uuBb^$U%w-te8f z{-Dl2&~oAJ`BHag9RHHe=eO!~eD_Nqv#FxhrWvh5?>a^+V{f7GyQbe@+nd3^ETJnJ?~^J+&};4?vp3e9Ew-Hx?FyB z*D~!bl2(T=Y&5pA@)FllU*~(J#bDMwofjOXR&%TN%6XbFY%vGb)S^c>?2WnleWn-V zm&eb4|NnB-nN2ooQDUpOD6l*<~I|6gEnHU_;*IVEqe_E=r)^BrWbBJ z|14E4KK-oO+a>#XrjJ_K6Ggo%WhF}6Zssg&d(`9PZ}zwH#SVsDdM~eDsB3uo{kNs* zdgew4z5Z%eU$)$DdGgb*S7IJNe!RS2;)QyE|Ki0xRtGjpYRmRZ zOG|@7Rp{=uYhtC#L8}L2sK3&)8M#rUH?ibHLS1A!qE|>B=clK-{*TqZI`1$$g z=T!IcE|@-jy8nE=nLf*UdwKn4X0{)`c;=!}y6&mP+5Fd*GI_2ov69tRx)0tzXpySs z_j}4O9}}syX;Jc}8wxCPHb$^GKDgr{pl)$_-IDd`u3JLyJzn^DO4PjK@CBCM_X^)l z2tAWHd;gyY2P0d9l@|ZHGrx6njmF$fOpOO-UcWE#NbFGB-q|0(w;AOf(y5-HW_3OA ze#g-y)3uITtR-H{gAHRnZoDl!a)IGO9cUbPs&ZZJee3wUUyuCkx|#HSyWP?m60XXn zdRx8riM`wTe({+{(*Hl}-rRrRu)vqk_~~lN_RA|)wlZa0TjuBMd$l(B=TzQV2KRg8 zYb~aqzPR9HS4YdXuB{@oB_`?V=*+QDwlix;v)vVU*<)VtG{-gjFFtWv9kzOEe8m%m z7dcJ~6R#~4>^~m)Jxxtr-G5K$mBl=4%(5}j(a~33R$ux4Vu|B@r~4kqm9u*tH*MVL zI6K#9X2jjCr<{Fyf+IDzS!nOK4Ag%fQ}t!(+><^(568|j^`E@!SEg4=$7;t-W$b@1 zsjWYM@=)cP#;Tm7)n-@bzYIwF`aDFdG^||YL65%2)mIxg8opvE)%?Dv+~ehhW_~lJ zwqo&IV)WDrdL6>ZbsGfOOC z?QPFkLm9r!aZ+IlZ+uFoEuI`_+J8dEcjn7CF3ZEL9&Ovc{pE!Po7wk%zc_QwFQK`m z;$mVe_Md$Vy6Ehs?0h@#_{m;NU%W2fDO0Oo8g4jmT{w?#{-ctIjaknaF35q>+1BQ| zpP$yeagR?`?Xivjt=)RR_Z8RN%Dwg<-ss-+f0wchbZXkp|7<_!$Y=A1HOo7g@4T_@ zirG~8N`GHpQ*tG2OOYqcl$BcXPHU*j4H!So0RJC_G=kFJ)El!H( zg3p+I%PZ>TuCkQte}03-Z2tM*HTyPOMVLsPy>uz)C{L4}M5jyE+-ZL6qt;*d_wx&r zT+{LNM0606#r=uYir z^FYCw@qE*&lnsxrzxr%(&8z2;uT!9fd>5QyXLa}D zZf8^XzXuf^j*HI?dFj>Wclz?>%U|C5Ex(*&b~)2)yZ`Qfzn&{|uk2TTvzY(V@+0dP zI?veGy>EIQ(_a~@xtAnooNM_KR(i^2*1h`7&o9=_sbgK{#O$ydG*x>wXh#m{x+LS2 znm;xFqvM?7o7-OP=rgptQ+%C$=23IK_$hxsd}~~7-fkeWhR^=0?b*Y>b2qH~A|1&c zdQqZ(Ye48;2_CjR%kE{$5zZoaVQ&&G5!KgO=h zQ`jHg*|PZVl^4ZnQ-73CU2#2hPv*kwuOq!{gBJh%TlaELxKr`DUCGJGq07!+abEGc z<#6IJvDH_-YCX?PUwMAcvk-^--u8`keLqY%|EB!VoV zZoYH>+O@E$n;VXHp8vAg%-no+kM4`<>(;CZIiqQ@c{YDqPgm&aNOQjzkFR7}+IGc> zt1~R}H+{Q~Ay=ie?%c(~HrF%S^SmvW{`U{A?A+}Bg7;~TcD($9``;E!v)t8uzopbfoSnp#$|J>>lsqMGlmV_1vxXsTgb*XAB zIdkb@!#-XHUC=EAR~+n2?-l=he8%&_bp2Cx1=0WK?+JJ)>uCGp+)E+Q(RG`>V|HDr ze!csNv2ezUS1(Jf!az6v+IUE39s@{(^8rbMx@CCUGBI^YioNbu1$`@_&|B5O{w-LPspjlH-?=6<5Ue z$`{kwm>9zX{N(LZ56+A#XZ(6TIlI+crDf^i+}zyWt=Vbm>Hc@}O4t(SD)~jm?%J0g z?srn^*OiNU$M*+MI-BNS^Qw88^1a+g`r8%0sakFJ_4AYJJ@!og6Z_=FFLlpkZM~G) zZe=$2cJ^EW-*(--rkDK>gk&&exPqz?F}Ax0R5~$|1XOdcjcG-|C`SKSz2RX;N)){3#7NK{K5>{1>v8SzWL^{qkU4wfHZoflnP5w||SZvEo$Bl-6>ul-lk zusJSuV}wmvp~tINe#<9I?L5_4^d(hVS~@v7ncbUD?x?>d|1`HH`iuXa>~dYPdh;&5 zw^HY7r@wvs_ONM|l&{X!qMX;cd3p2R?(J$;?z{SIxn{bK-S&f?ndh^np3~M>{Ze&} zrQq74xqmz_uMAoBlRy1Hv|Fmj_Qjtvd14gOax8#=3i(gU$WaCYOW; z*9!SAH?^9~&(FX3lqJI!8Blh-o#FPd{QI513)iLV85zI$Yk&9tzRU+ZC0p+{l|H{U zZNaql?WzCEq&NRKw)i{fJTtC#R^L$Jx>eSOh8MMr7f1^_XixQ$a@eF4o;9D%w(RWu zTzCDjIksA1_Y%&^+5Qn(d-$Qn-?FZ?2Rl2<%gXwAuOG3DY|oCrw8BDwqd+aJ`{LEi zRo>?BRJ{{_eLi^c;7SR<`AJ8=f024w{nBH3T~MmZ#M4ioJ%7G7Oxym-GTYO)mK-*e zuixlf|C={&p2NFLH|JR_-A)*fWUZQ4>Iuy)Ow0Q1QY)+F9i zX+HSiW5u;=*Iopy{WM4a+_PodIlmM$Waxs@)wRM&RUcMOdE*}ccGsD+3-sgP{Clqd zZT~~ou8)aR9%neO`n0y=o`3xLmu$B2wfk#sbvHfOy67Q`eZw@rxAx~!-X2@am})dL zVzbWAuZ(`Bw}e|fR1S6ikI@t7ZSG(DTjyE%*InHTe)&&$_GBKmFqS!5`2NI+j(YjO z8o!eE#@XB2o?ZXbVSgd$P~ywm7ABX@KY!d)bm`|Q4N+^Cg+02GvvS7=+1#B+lQ`QC z|B+^B|7|l@&qmJQG}Q4Y;}^%d>>n%3!b)R{Oty&T^Azmj-7E8Jrf=WU2*#%ys~`F} znVjQ!Aw2(DhPkhwUzm;Sh4-r>qIdrMvHkms;82|u|8%WuyZQHSxh$gF7`96!bmg&Q z$9|-HTQ!M^i=R!~Jms}o_tSqbef*Zcc$J({_3%qwty;elBf}gX(1_j4Luv1J{}Tmm zI=AQC71Q@Pz5HwK2dkftcuo~=iI$hx_Wl3O(-qnL{~k#&UV$?v)#h+9PzXb+n(#d^788n&nZA7u;%UYA>>XJa&_cXmeUv z)oSY45LQoeLW zTn$`dJZDFl*>XP4zj{?agE$r(jW%6ldvw*rq^(hr&r_-v+pIXjpX;+`()p+@J6kV3 zKfL}$0Z;7H-3)W(4fv%PqCl5@TAWm!Wb@$V?+^1&$nE_hG`Jt^CN|F4}{{C?s0$N7O4Yco~}UwB#ahat-9v4)>#WZ}fUZf6`HUuQq@ zwCJkN`>@wDCK$gCoAcT?zTnNB^k1i1TU)Kd+69)I7acm4V|JQr!OO?R#l_)1GK=L) z-yB)JcCBvK!_8dfCQ`iVOEqs*R0Up|`E$kf*OC6l9kpK<2yt&+elurX-CoC6y&EHX z;y?b>a1>a<9=7?4bgpQrZrJ?&NtTYc*sN|?8hjBmmO2K z-=13WYt`Mr;|t!MtyF0H#UHyULTB2wS3F5PzT(v-nh|G1Uewt6FYhp}RO4h=5C%F# z#f4?7jm5?956w^1Rh~E8YH{S}hW2!ZQhoP#bCdNv5x73##KQ<;CpF8~TOLc$jy|rO~lJ?!qF_Yktn=O5*O;=z4 zdbym~-ZL|2N}gjdoqRH6&I8Zb6OTU@T=By%nARtFWKjW=_)ek=A1ov^r2#nd#r?d8KSbK(}?e*3IO z_3x9PKYw0sQU0>`@ZrPK($ekQ=hVG<^hn86_I1OedFR(3^SfPhDq_z*^_geS`i8BS zla{tFWH`GkR(+z7%$0vziX+)g-xl8bw|ISQOyh*o_q|a;O5NH{&eeRf``0Xf_CT=x z+Fnt|*}mdD4+~~|mN@%xv*cXWfHF3QC7?}@bEYhq=3n*e-p?%1W`cVqVBI`!MNr4@TF0rso8qi%3l#(& z`2S0tw?9-1wCn!uim!aZC-ko1bL%#z{RTRouCpuiF9^23Qm>%qr~PthW5}%1>vQGj7!u7ZXj-tHzP9PR6aDu4nvXyZXz`B^K9H3zHcd+CaPNm!D!5 z@q2xs*!b@KUm@2o^UKe7ygXlB{>{Jr^Iz}(C;I8>fm@6C;s1(zffWPZEUHwQ6H^*TE9r}tVDE32sWVT-08kbHXSxaCxKzI|?M z_5^;Hb$@$azhjQq(iPUSmbuz%!?bxbvc2ZNObxQ$z*S|^9D~5da8!x|n;`3JA+U%i72e2WpH1^yDiY>ff9vHM;~SZ~ zWVW1pu(&39Mt%PI_usd>n=cTy+k0c{R?~mC7#^*izWDtQ28KzXd&T_f3ztlDUsh%R zZ(5OFTu9#&bL`oEAPP+pQ|<(0(}an(*J%t5@@KEjXIdGgYti@P?|hZ#GBhbhe zXIi|*1Cte%k>(71Y3boS3u5)em!~-$?Gxu=`&#w)<~LivQYphi30c{x4+PJyPYwL5 zw;;KYts`U8K-9&1h}fhgB)xzuTW*{pIiK>dgFUr)v&t z76h5CWWDfb(x&X}?B42qv!goe?9wl8-sRII_MAT~xN+j%oK%MIHYstJN=jT0?=9+sfay3Us`aJD-9Wr|~)?Yup zYq!JM(h4Q}Ee{)if{H4S>&QrxQ$LXwn++f8YB!^y#e&X2ySIwk&;;!Sb_e$M5%f&)%N$ z7O%>$*nH@@TlU;KpL3cA6;~#T_A*CmJHCDUHa927L=SXI6X;$P9;Z1BrN0_H7hiNy znmF0DeM|0_y}Yx2*KDX|>7Sb|f{`~20 zn6Gbn8fy0AqGWD%cJ^}3-G!{Trmhh+^1$RB`Vu>py;Zfsc89HJJ$jRKO;C4TSLDam z%YBchxUPCH#h~E$=hgW~pOy$!p3l0F{rt`x;q3kdArl4WF3EQTT8}WU5;RXb@VaEplzxwX+S$m$!SU6m6RN2y_QS zMB<}^e=cyIs+Z0D`tYb8YeHogQlT)A-eEFnfQ2!*BX2)xbRhHXKd{trA@0Ek+v^vDO_iQLLpX*d> z7k_k~|Js99f0i!nzTYI$k^gtj_f)HPkDq%Ve0j0NJ^%inqwPz78VE2P5CC0>av&gj zWx-9hbtk{xsdok)V?W#ReYn88s#i^Kj+cL_`}OOflaFDN`z+1Y?pn~>CJ>-nOz8@~OlS##2&(`C^@{+-z-Qelh}nz>FKcT4!wsQ274zi#Kf z0F5gxf(yb{KUHtOn6c%NNXW)59IFjJ-n%Eaw*`Eni0VqqqmP;*vp(6*hjl!L?s}?B{>8_{(zbqVN8u;PTnC!h={BtW1rV zs_~-vim>106`$%WWKTc6UR73VAu~sd>&pEzX~jq1n@aGkvAlc5Fk++WmXjRG|5r7C z{va%?FI2C;;`GMDk!~}j7+)7KHKc$tC|mCemY-)_{?Gom;CJ=*ve;b#&OE;L^XekL zb?1Mnd8*GoZ|~9%Jj!i$&Rnx+mMwa-JpTF8^Y%L@?{iBuUAXg=)B5Yh^Jc7z5dO^5 z-UPa-&S&i-u8LCmw!$LAkAZiD#SdNpouZ+<;mao4SJ~NYB;=N|!j)Ms^ z=FZ)_=o(|K_sWn{DMnv3H{aCRD&v0V@yCikUAfEpFC1TL|FpL%L_y%e`Q~MdGb<}A zD=Kyra#!q%(Yt2oEx+EPGGJ|3_1=54rUfnO3(*n#{L`jZTz1LEh@9Nq+}hf?|0a4Z zeIerh)?t6&zGcgP$$dFm(sB0e*^STax^v8=pKE>%7TcO}#B#odirv%mav?OSUGSt+~u{l(Uk z{U)VH-;-r%U&>)-XR_WOzpwQBqwG^FY15+@rk`Fd^6k#whmF(UonoG+ z*v$8I;cVaKvY;(Y2g56lnuBJv=Uvx4)_yUnlt(#AwPBfV;qJR@0t2+BW_>Y=HxZjV zbLK;zAib$xpv|6h!c%u&oX**lU^J7d(ZTfeg4m4_GQ8YdqjHPC37YCJ=isc@lgM3o zGiTncSzSkyOd`%c|7=pSe7>2zy+3os$#V*eW1ZU%JbLu#*|TLcaxP_0x#g4l@7ra? z&AWDat@WK-{J#9f{Vn1zwg$wnJ)P7nE|hC$$5F}9^G5ce@QU#DNkNlyUjcg>fBp88Xx}fdj~zQ^ zQJ(bT!nT_^YodHtp8dU!N~twy0<2sM3BvVHrci zHBj3`%I-nfk2}ozC%)D^-MeZ2y{lip9Nv2DLhSy^1;3-`zxsb!{Pgw1U5URZgc-N& z{^fhK@YB%Qp|0* znzc8{>&->Sm*>u%d-O;tca`7r;FTfm(g8dD*M@O7IV?7nx^i(kYxBVfov`d*KKGsO z-#(MjUA*4u&XNL)GnEzd<19=&4nLHTm;YY1ck$xICfk;;pZ;TuW>(_nn?Am8KUTcR zpM3I4l>eRX+y2t_=Ag44gnHe?#l&jtXUt7H3pF{5HnX%S}hKegUuQ>fQiS@{p2PGl%K80W4OWnJC!n5h?7ruQM z^5WU`!ew<9rlzH8-24q9d}4mFI#s9Tq@`a^$lPBtZSnS;Yn9CxQu+7VFOuP9@ZbfN zp~p-gPjFP9|MlzsZ#QkrYXiP@=g(1T+gGyi_x$}gzE3pgv&r_hGhS#QZJ@Yo;qD%( zo!^)Jzg+rK@!p~4@Ann>eU)n0>H9JGHuHMg#+~Z-Gn(lmJg->1n_0%%usA=ze_L^G z?%DU>t>^k}zL{e*Q%9`(@WX=LcN-lN>gwuhYv*p8Stqi5ok{lomcxm^X8PVUbz3|! zShO*Y^||4Q#Y@Uid6ZWs^JO23bd?~*1JtLBY);h0}A(W9lfZ|U2G!6vV7uhiZY*KNVLZSU*$M`wuLeMN;Mg|^G(V5n_Q&erQjm(Sv-z;t8{~z#7bG|&^oBw3pudnlV z+uiuT%wEDrMV-tTpPboaEfgGR5uEoV1g?J-~4&@O)}!z>FKzA(_b z3xD~!A+0%;O7>3mTI#fL!{*JCPd|N;f9uEHyLY3wFUtMPJeg9Il(Z-_)tt|G z_Srd-E59saYGepgYEsTW`jlPVqJQK1wQFVLx+d(JaQw05Kd<%aWtGg^S245Y# zF5;=Kc}DD)X~$PhtIIi`dD?jA*|g-)_k!ys?&g`RIWjjaQD|UmNQ*a|n*74@{{ii9 zRr~+UE6RNlHC;pGwDbR8G2g%2-~WAbJFkuU+8GkAv3JOVtxpeh zj;XR;u$#}{>~C=@!(`pswHuk9IxT$g{Wq)Qg1%g%nQ3Wh5yvZ>`}M7O&z(CLq;9|M z*)h>GX~xfYED&y8vdZMb>TVaMHMJAZroEJ@{#9%@x6AVDBjcGq!qb$N6bn8-cl=;a zzSZJSyY*g&?BBin_MfV27mi$X{&`L^{qIS>JHH>j)jqfO;L@c_-Sm$#G6V>N4%amk zpY(K*%;kHH&r_@NYqG!ZuUYwe<>Vt5o^oE?zi0XL#{Dnr4|6{`?bv!a$ZwIM`u8Wy zE=v#DU;7@ue)`{EGU*Q;f93rDx;~)i#>Ir*1N;l-`Ym6=lrj0_ky$O?^7*%XoHsh? zE>|e3741G6q4Vrxh1A|SnR*jD8=EsLZ8z=S?H#@1$Xv@6C3}4Q{EAl1NjI7~bLPyQ zJ9n;KyEa+fuDe^~T6UeuUk$4XFT<^6`d(eb@x>KOmU(_+&e$k-^ksk2 zRIj6)tBzEC#GpRd$-~JxW1|2hS{qghczJ>MSic#MlTUXit z?rRi(`qbO_=_Q#N!m*z%B4XG5{@ zRPP#fhu52G!oHeFojr1drM@aQ_Q~g;GiS~;j{n`atMT~bhbbLbqTSrw3_i7VtqIfq zzp!y{?bRnoU%!4G931@l^XHWzS?THSIvK&Wa=Op1e~B$Qwm{z0(lT@NO+PVPc^UCF zQ@nhlR700K&N+O->&(kHQR|EM9e()0ey#u8YdfYb{N8l+YN+4(1^%v!1OM52XSH9v z7r?vgT>rb>{A=xtU5(Gv>UM`I7F}AU_m=hNoc%H1 zXWsvDKITo`3*qLC9A5e6eR1p0rx>j@V!oANQ1C3^oYrJ@ICElX!( zYK+QeGRe5{^80T~V_WXlrX^z0%$ajPna&E(IP%gyRF3ar#+9_qE3al*Y4o@)KK*o2 zo@A%X3xhkiZk>8slr*z+(Up` zGqABavwyXETJDJAeT$>X&2)y3;+xfVN z)6SZWzu((i7ko{tEVDEznsU{N(S-L$r1E^Hg$7nux1OvGT^W+LxiT#+EjxR)py8I1 zV?`!6_}H4~T;H*I^W`&=FD_)M|GOXNXJ7cTr}@jz4~BmKmn8=Xu*~&KH<5a|Sy@>b ze4n?^`^EJ?YW8j1XlOMx@c$CwjJn6h9xgxs<(iqHVd0xz+gIuj3uc(Im*wXA z23_5|aGz}F<_B`IIXmvY>#M!f?pIZkl{)uJS$Vl?#U*CQz95zInUU*GKa`ZyQLW0~ z7x!(l_3n9fKUzFZY9Hszz4$j>|KfSj4I(y*x3Z)zacG?VxZiiJ;FE)$|6a!{{=OLA zpZny~q2~Gt;SoIrE^6(yr$wz!3x6HEU~*vb ze9eiOVN$(q!B$~4756iaT;%d;Qea_X^iw+NKY#kPX??Ns{yY2qm|i)D{FW+_TRi_f z=YsB|i!Q&Maxc2Dvd>^{^otowb(d^gIyv2HE+1R-mycFvB6HV0fBxKZ_tpT7fY(>G zk1efr%#T>Tdi9^l2DQ`bGEFV5YtNoK#iiY_?DN8gm2A1yJ6Fj_OFs^Ye|d)K0=vc5 zi!U!k#KaugE6Ff{19YW9Xx7w2d6GUl-}b)m-?jh$&vokO<{Pvvdtdb{@#gyTrS;#9 zYvq4DZhW5lq`0p2tdITv&70Y`CY>?;@Fxd!tp2iRo|d(Bl`CT|u}JmUGe>2)ie`jt z-nTE#P*7v4m$9*Ny6E*T!!4IzF3IgU{@A48>6N9T_Nve9TE3=Enw7TnV#W{C(917P zT{h`qtzmoU+(ScVQD_-p<-lhZEa;0 z_1)C(=v0QE-CKi%eSLlB+O1nO|G~$Kpp_!^UADE;&LxLVJGWrIWcSesO|x9Hth?LZ zHYDs1v3kA3Pi?a7zclyuW2a7WJx_ATDi&v0kPNzGA~RT1RBUlg;j;h!aW{(JC2xwa zS^WBvv-&!LSieQ}b>-(d&(V37kZoNYsJ7xIgW*h{ zIZqZnN;&-UWoGk1g|imUIwp?GPjyMp_fT0<6L8_!>Z@5+sTVUhJD%0P*7sZ|PU~I* zNBiL`hJJhaR7{QLdcW*_bK}cQzoe_;^Ol((579bW_2Ag!j|xfI;YkNh&HA%%%a)M! zUZ!iULV{M-*vY@%v8?~{$Bx^^3<|8E$wX7Plg?FZ580c2_>=R#H~;Owduunv&$q5@ z&DiMi<^211JO8)+GvDK|&t|p6#>?mP|3Brrs?~bfXvfYw-yfQn{69T?RnI5T`5XsU zuh+YNv2EFdGY!)c7<4(9RtvDyPH^iHk`(JY$;X@YwQBFh43n8YX`5&MTXs!s^@Xm5 z{b$o|-@28Qs`|xi>1P>j^=`qVNrpD1+*f6!!d92&=Dxl0!gBt3eLX#^xqhAERtuVU zB`t~55o2z2_}tCp$vf9-+Vtr^Qw>+F4GRyK<#S)VP}EevRNX4{lkvOeNxzhpm9M@R zyj67V=gfODhQ~MeUYu?E`fuN_S6{xAv@c)%=rHe`)zdRfx+cXyLt-gM)1g%99@k&@ zKQzs|eNX%MdF$0P51d|ouJC2koBQuy?0tHkJ+5?XjqREO>)XbiVpq79Zjvcr+TB5;NVu>vYtFr*=DW%L-Rr7nk5*24ar|6q{rhY8qW|srf9v^_$uA72A6g>6Xknmt z`^A#AnjBxE*tj?D>)-Qn`_e6|b0&L>?~?y_DQzNxZx>m%m7Yos;_ z)j#;l)uhmJIPuz#-mRTed=fYe2=qu+?+@p8xq%V>EM#xYPQKs;a12uB*?ls@)TpZ#H}FvU}ezUAlDQ zL`U5EwBx8Uz%3FGiJ>~wNpulIyPPXjRk?Lh*YMeMxFe_;DO`m$}xqj=fYhSx||K`n= zY1cOYxP0lQN$q3KbAFF}ZY(a|9=uYdR_6Ei*g~z^&ZEnsUKlN2_~Jl{?ahYjOAHEv zphClTo&VLRmt;Cy|83v9=J~w-Dc;2~y9z!@M9mTYdxiC;{`;5zmg|4H^Rw~a>v+S6 zp3{dJk8aqq+I9MJo7JaJo1J6-_5a7LdB5$ney`8J7Pj=sC)b<&d9Uj)cZ=McShSDd zH{C!Yf^iE=x~K+xz%xQY~QxcM{SKN zA4571=$2=}sX>WmCz^$s&!7EL`(am6W}o|e`>Ro{kLIU;^LG7z-F)}|f15!UG5(j1 zGnf%K(Z6^4^{1CTm3x+5-0Bu^Lw8GP^U;dR-h=P!L3hh+-TUpd_{yDC`+vMUct*=q zx$3fH-&PCb1xv*o_zSZgbMo`OSLLv_N3ESVZ{9PTC)z7T*JWg@tE)#wduMP+b-Ebn zurqvXb+&BgV{5*eeqs5>-Me@1*x~VBeEFWq>g&W_f30F}Wccg*|5)d`y*J;M?V6U+ zS$#OY&ZT&s$Kt~^6%`WYj~O21fV%Hydsw6|Wr^s`u1TzV&}zMR{=T?x&FiOJzHwP6 zyuv_tR^18V=c)F)SN~q<|E2beFZ23cRRzg$hK8#)%sOSfnDuMG z*?jl=J^MF13l_hb{(a7qsdk0?e!sWB{r}qZQ|YzNQaw-41)XNS06L00b#_~yuHl1= zpi$8&rpL2tYv+FJF4;D1^S8$b&DswqJ~3iAu>4|1jh%eD>*ZZ1o)#TUm~c<$)u%EC z`<8Q!C3U+O>6mVLEV}p7>#v*MZM$U3wragh+Qx`WFHN-9%%3yIC4!$Jof{Nw`d9z$ zNthieH}h5f+09k^K23kB^2?n6N}}JF_grqL>uUYJ%`Y#je;vGc{*TT7%=cw%m@+~C zoW>sIF2UW0l5VY+x!aJ+6Z-q>+_z#sx0FA4b@o%u^Zk20zir;_7g5?0ca%Tx_3sz6 z*@C^Feq{^Y(Py9hM@U8}Ca2wOhUo)M5iVtAWnDvyC2gr^H)>7wI+zd;wEBC8si7sK zNv)O$7by6XFP_XTDKQc2z8d1c_}3=sl_6O*H8QC?9;VEl930lPON`4we%a-hi!N%c z=K1pIkY;=FMCCW&cxE(E8e&{`=$FIWLBv>8bm(=S}$cQ*|}&-?!(# z`uXa2b$&(h|JiXSAO5^aNOH7$u77@#T%kscS?kddy@JFm(@&RQXkD;l+rl61|6>0s zPkF9zS$^%ZKc;N5wR;aGh1@vvH1jUw`Gl&a|8G72R`)9R?)}|cW0Id-a#ruTGQTe3 zn|%E1y+1({4G*_0dbHVPOALcA^SrZXeXki`fBg9IrTK-6L$p9sjm2xYTAQxO#azuW zIeq%{oY4IlJM7HO+g0B)E|4l&x8e5NlCVVE{q;s)=85vP`^T3tTTS~>Afz4Wx^(4Y zcB8#tH-DBWo-+X`lJ_oNt| zteXA#XU&f7g+~L=L@tmJ^@dj1etR6W-PcvEO-d^Huqxy|Z~nV~--1V`H2ZAHH;?6))jJlxj4s+4 zqasweGiJq3#?qZiw{G1^y8C27UYlJR>%UpO9d8&Rh0(cXVN<&`-IuY&O?X}X|8@1d z-z(mzmrr{xetn}uyU0JA;=pe&{@$%GFTT(IucE*@YTnnL7m=%e7%$Kj>%L+Z0l7?d z-UQzE!$SRznLn(|%#Kxkh?y1YQeqWrBln#Bg0A3S<_3}VJy)_e-?T9`o$9spg-nFj zREtED+AcqfpEY(9JuYmISR3XjAi(Xk_uiWo@u6=jUY6WSF!Qw0V5Un{wv&OFUKSMu%!dw+YK-#24z@Bb+H zKRZq(o?rWon8=+87XNrMGTAPyVf~n~W%H&@N*~=f9G%sLx!D(QeEsqB-TVJ*-rxW8@_?!3&o%yum!`){dCWVQ zkYH=4d6pq+E%-JYvAqi~_8k%5yYQeyw%JCB1=(ApIP;3F=00P;pc_~#&7k79GK8zi zVY#E#+Y2Y}{ILF#|BItGX7R-fyBU_*I5+Q_fBB`)(jfQiX%3djVcos`{hP%?&pj{@X@gPaRK|J=ip?XWsTYyI`pT8WP9k3KB$D4XIT z?KXS+=FNvY3srY~bXz>}swbaTyN{2LLIWE^!!$LHrsIzzqoYr!7{Tsz3h-)b)e~8{ zP%BRQ!cr+y*`{g+3vG@Cj0~#+_!hS+E{-!yny!D2XHUWM_qFv`iods~+W*R`TzNqK z-2B3seW%4!L9_k+@h|=!ivP0z-_K85HzeJ#TXHqwRIzr}PRR?8SX9p~G7p;9wK{Ay zb0b6gx(RplrawrVeKsvDqi#ouDcej2h6}G)95>v|iCaJY-ujpMzsxVC^PMY>jgV(z zI0u?RZ;+A|>5-G4rhlH##{TyAZ{gqWeR_WP{;w%-+P9yst1GvhRQKuNI&Xecvq{V3 z|6O6dsr)#?!{bbM7_R@o!~b&YiMi2I>4Jx1^wP~{tL`}Kw%Bl@$A&CE zJzZVTZ2`)?mm{<_CiV96W`=n$d01{Y|2fNrR;Pn+%alO@w{6FluvJ&H90da2KaD6k z>UuqP&C-S9;^KkU(hTRgm@*g|f@1~$m!)kvyy!#U3FYAConITnWAA=ncl}Gr!jc!k)v%%lMyPVK-fNwEn{U^l$%Ts#e5& zdHnJ7Cii!f|GruG?)}|cpRaxg-5cH2(jO{}f84|Y0jxv4k3Ti)Svy1Sd3ffqXi!wZc+Q!SG= z&R_}O#?ZhAI$w7|-H}Zft=1mO3Amx#CD?xG`854=JZWK|`{nEJnm$eV)n@+v-mi7@ z*4Hn1eyI2E{l7lnzvsREH(kH<|6}n}|9||?d-?C&Sx^ZEs+#xxIQg#K{^I8Y_rKIU z2JNU{|9$iO7r#G9|GNL{QseY@m;5K6|0$Z6UK#7i*ne^B?65hEYeTf$-Q6Qo7d-yB z!^GYCQIzfO-MiQDgwLAXkvTczaKzf$4IlNUgPJ}J4(@>~L*``9K6}=;Q=gZYAs5t+ zb!gU{`gG^XDBnt3=gD!2rc;-D^WQ%G@ym}5hpZQU*m=7C@_fVV`Tuv!ed^!&f5G~a zo2Lr59W_b0^1p1EanaImSGyQZF1{?u&dwH{|9#H<`P0*Oy4_mkp>k-}4&P>z%x&9t zyi(52sSMD&leZm|AQ)b3NOZ4E<-3*~bo=)0OEuH@7_1nXG8h;bI3MabX*^|!n!_^p zWJ=$$9h2sEWt&KC-?mN5Z0nTQDyyz$?Z02213D+O(1ekJp+u_ts8e{)8ule~{M6t1 zGar}b*DrICh~fMh<)hqS4HrlyrgBS6>Ba9Epm5v0(KKA2k_Y1_p+? zZp$yL3UOZhTe{08c;$vXONKd&ETBVegpy38BKiHiYS^}TtPBC?kr(-z{u>Qv`mA{< z85tY9^y6%k?Q?FG6&6kuohvU=c|^+@bo!6S;)`q6uMgkjrygsn-_z36;+vx9=d&4-e_I*Tv92#vX!BgP22r;UBl>z1capLQ{p ztPJ65KRl_{ikIP*G&B;XKX8a`-4(FwcD9&KK+tL_m zAhE{6Kv?=_-gfWG-z)hyRGnz7u<2uvVqjRn%-IAwJ74SI#!Z`=Brh-&s0lbQGcb5? zFuhRQVvt>0;WU3zMM?JNn=8}{E~QsxZj9jhJez@m!Ac-q(COEMLx-4#YGPt@9JpT6ym(F^-Kq50v{U%#wCLEFIRBF?bpXjk{qBm;>l zpGx@{wirUvL6hVK-lah+|J2#@9*EGjF)~^dqNTd~@0Q%;j zzI*qHIb%&B=n}J;FTB(ypA6aKbmIAEz3JYk%x^I+=v4$o%LIWl4S5>fM-Q#sFUZx( z;yB^cx7Al)y?mK@jVCXpf`x(MMM2u;nW7GtRRv->7Irc`09T9*69noQbU*&wDYQI9 z>-h2GkuP%>27neQ{@9}6DDdprGq0sW>J7`zw;fLGRDa39z;I!K_DL6|z>oh*Y~-%L z{+gl0U;&BzC8jwJ40jcx)|M3(ZhW-sLrQUR@UOGl9Ebk=v9WJBCIm|Rb8EH=bG7!x zz4fSHn#z!o4@vYasuohmlQwRc_B3F`)Tqepp zY(JIF$iUFxCcu(dQc{wcnOR(HJo~KLSDk3YI~^XBBOQ5!EaGJvl7 zP=Y#Jz2V-?n+JJbOum?5^7-@UHJyiV-@Yx@y;L=>BW}IF+T=eBv*P&jLO^;L8cHC= zAt`_E$=-7d*jY)sTA#)XZls?O$k^rcmjffL8!@<eR{=)k`jC)-lZWTKc8R_M0_Wj|U4Vt1xgnGQ^fk^{R<*P4!yZwRYCY z6d6AE)jH>#Wff+h{lxqtLg$(gw-)G<7wDBG3<`>K7^Jq=`nO5xPV@-LxwLoh-VBpl zPM=$S)r419%hb894GLrdTLG(W4)VPC6{Iy4bOP-!=|+bIp|A3J-imKdo62F&0ouSV z2r3sC5MI`Ciiii_WuKRy-+y&U+3vlqaeZggZr{B5kmbVCAWfl8j;4lKey|-vpq2r+ zG`udpHNr+No%KR?cD8PaUgXLUD;d6PIq#YotiauUu=1DCnu}w>YmYVi56&`*(VEKC z*x{LKBOLR3zh_#nDLvEs4*`ug?jH;cVq>>rrD{le)$t*MV6 zKi<82_Z)^h<*V&mW8>3j-wN<=sIAG6Ms{C1_A=iOSUxTRlVf*yE34QHJl&tPEMTa;0Y2-(K*d z$~#V9&5wkeSXxHvh*>h4>|J;9;>BxKv0%$D+=Hal4)EC5z1z2~ql}vD`flyJdO2(B znqSf?6Fpvh{Wa~ibZ~I+akdMf>y%Bv8o?9H3=EusT2sZkQ*(3Q7O?sLU)CS7HjJhF zs`=u}FH=GE8#(VK2O`z+|DSq26M1zAY>~0vGxW3=9x!7;;^gUtYU@{br?G zDMpz_GowD1W}3`uZDsw(^PERVutjwF<(->12OG}6d;9k6*|W1R zK9w<*I(z97sId26yMBH4)~GMwa)tq#;4au*$tpFFcyi@_!Oj@nUzbdzK=YXP4RLXC zc}G881Dk%~7&xXKejCj6`B*VW^y0Ckjn{N1*5okgu3N9c!L$ovA~aqzguRv)<>cth zKfn3Y&6zW2iml!6xFzcCt5;g;4SHhTmoHyl`LI*tOcysI_Ia zwR43Xx<%JTnEIV7R(_S)n>KGw-WYK~7^IBB zAqe6>YXMN(sZsP?+UCgRmv3I$-2Al)bThJg!?_eAwq{0Ku&WtVz`b3DEzFy5&N-VF z`PDouENn|uuJ?Y2$tRCgH7-gqT6y^;n$f3&wWiw5@89|-VPk}hynO!GM<>d5*QTep z3p=b|zkYkw2}s(0%MOV~o4s-Sw{1HXwLpKa-}Wz`nw@`h{yuSnWA&k}7N@H#DLq=j!VM^HF-k_Bx z=H}PgrcPva>~K+9Ga+`)i??OFqiYvI%Q1Oy;dkK>I4!35@}7HIlp9droMAHS>C;p{ zhPmgT&-GJ>84X$r2r{~Aubo);#%oU(`%Ch)nN`e;T3eQz`&MgPj#>7`2$*NHAW^$I z2vjB-&p*HURlbkE|Mug%YOLn!$@LdAy+|=ydHwZ8Rgga!9AL_YKw&d2v_3gK{rJOz zEyuO5zWzFU_UtuZD)aO6OG~%%dc}f03J;l6DMm*h7lx%i`TDhVZP;zO^&#u8ryEK7 zG1yvL-K%Y3HAJ|K7HJ z`}AqkWcb*p$wLa(lb}H_1_oWXl_7pUJ{zXVFX_LWe!IxkZmL(R*=$?6^It$qSr%XH z_#z3mW(la9%)lVyzcOUiH&4YISHa!g>gsAy<`+I{$wo78Rm5M23wZDRg$Jzu61XqK z(6=ybwXfRb(@&)&B@3CS?s?w$TNBp=vF0jrHLG2Prz{tS*pRnaA5Jp3^zA7 zF)^`8CsVBE_8os*TwGkX`|lc~3`c>q^mNem01UeVG3Dp$DFHe5DnlNFL=1rw7&Yq_f6B}W8&k@C3tQW zLR3SV2MjaTguVXut?cN5a&SH{Dc-fwYw4%of7d)^fBCr4;lY||ZjiWZfcf`i%Bd71 zQRe%1@7~?Gabp_W1*^Gv$;pqk+Dfc)LDwNejE5GX1}{r?xhNfs`j}r;6}2|ZJl%VW z*Hh5>DnAeI-MbfDXl*!+sv{FrBs}fv{&$gGTuf}%w4axz6-<-Y5#c&~`0$N*h}xiL zaIrt*O4ipmZ*o?Ktdejzo@6-J@A@3whdTBiW@cuywn6ecLja`Fc3?@+$~|%V*?0GY z6V9v+l8}pQ%oc}e`TF@K{d9zw%n3@O|Lv>4pHp`)x?B05RV1xVoHyTjqid&jV9d4^ z(&amK*Qw}velU8pA^lqR_ShM@+iuG3`F5+hef!Tj>>m%_Y~C@ar^h=i?CbmNGwjSE zsi|&mZf<|HwS*YD;`UU0oL>KP`v0%-|EK!aJ$+yQp;;HR}|8JQ{ zQ~S~t`~Q7iU%U*YC7~UZn;V`>-~VxJ|Nr0nr_Xc#vHt(B^_%BA|MzHOd=c3u-W)n>SXTB|k>EnDW-|Ettw0;}t{|5tHo zdHv_v_y0WAum4%k{qIA&{fT`ae}LoYhAyb5vf;sHe|wPoLcJQ-uUoh8V{iVMA9uv{ z<6>fB{=D?B*IK*(V|VQpqaCQ80|Q_OKx{{N5T?`z*z8{2))j{kk@ zeEq-AK_C7e6_5Y(!reaU7r5emBMA!kh!2mBcJKf9dcU6Tkv~tT$NzhxZZ9dv(te!( z-}U;x;hGKqKtXgiziu+59<2uZXIkyAm&^D6eVgy?o%jdj^ADjGc0Zp?uKzi`UUTXB z$w8pY9T*NofWkZB=5hIYP-vcC8fszp|Ig=*{LE8)YybbguW$P^0Gt}WT=uur2ggt` zLWj^R*RNmC|NACgzW&e075$&X>;Ju4yVa?Y=- z>%BTZ)c-kN-!p5{pGQZ#<^McjU%Das&qMzDAE2m|1eH?_f5Bsgq5HmVUH|v8{ol*e zt9FTe+2HU9`FQLep~JSez^=v zQ#!U?AHw(lx*GrIXnaXsOU}dl|K8q@_zSKM&VgINE53d_F8}{cy1n+=Lmxp=_MzSW zjc0r6@A~iM_3F1ZSugDWefPcFS`%>kx&c}{!VvLL|Nkd_@6`o0U$2J$|6Kp?{QBCr z*=MEyf7`zQul)ay^5?!hpa1X6a;R^FL1h3#*pFY=_y61f|NDQv)Fboj|NTs#Uwdua zQ-8akPe2)G{{KJEFCDA@efz!<#Cd+;k=}@hN4v%C|9$KSU41!u%KxA9|L=Sl*s|&7 z{y(Sp|2dmq7wk2E|DR8%=l^-44z=zw*t%;!K^gz{{eRo0i2VQeegFS^-}h}Vn|=Ss zG4r~ApXW~xn=S^*;n0Xx2iJ6KK5t!L`*!}nm-F}idbRpe$Wu`4{`v8^|F!v#i|+D& zU%1={Rcn1 zIT*A^w_gAMFY)@1;!|uui4UqLD#CEFh-7?x{Qob@?bps>`3ov84%`1}{`}^k{oj}V z_P;Ln&w!-9dd)YGQ$DoYgNlT?s*q@6Gam z8eX0UIj>+5sL*rh29-hi|G(vfoM*{xUjOUm@^fN#|9&LjJR}}p^U$XH11Q4xf7`k~ z@D`H3#rd_bqyPVV|Nq^ZyMMOV|K7gT^MZcdo*!>EpRfD-I^McF|HQFy+cN?nEgL{* z`!OuI2+FvV=l@w^(rT%4;wD)Ag#G{J|39v;`T2DEQifms^?x4U|8w?!h}}tuMsNwc z;BNW8&vQY^&|lN#-=l8*x<8NQmn(j{zW?7>P+mUwNE#F-_J1$ipFFLR2(r;4ljQ;f z!-Bi&^J_kVvR(bZ&-1-4KdrC-`}%#|_ub!g6JI_*Z~y<#|7j<8@B2LW{f9T;qSB%i ztnGCA{Mv7`@BdjQqFVp+>Gc1<*8g8sJk$Q)kH_-=KD5{WI4nQs%g=88eFb9upxn$b z2eh4$;lk6&{&qiap06vbt$l0L`vFw2+tob>6$EqG`P&Zs65s!WwHs2BRf2Qz-hJQq zzW@6we1B2W)9L#0|3Jxa_Wqx<@Bevb9$)))>gF$>!7i@<|64>80kG0x&7ahp3^|-wC>-}=YGF*Kn4GwxA*_${<;8e(jMppS2WDv0`139{XaD~zk|wv zFU##yKY}y7g*wQ~2@T@jc%l@A8L51OiGoUtJL*l-FU)TTt^W6Ub=lTElWWD>m z|L^VnwcmH&U-|`P+Jiq}RTDu09}^o}`}67asV_h4*Z({XikmaFpfGLN>;kIj+U~}!4i|+UTzAOJ*c_F^$<55uI zQS&>ddeCbdtaB zLo=uX`Uz?RwA=rA_V=1QZcqW`ick6<{Vq zFet3ROv&)@a1o{pouD!TB+wBX6Juj*YinmGTA~g>WcF6@4sY!9^P#AL2A?IB90=3;OsZAzvt!UeT(GVl)P*5@AX^GMc%&MXv1z~ zanb1hRfp8=)^4#!U(UL+_{RRZ@f)@rK9F|(_t&pm|NK3C`0&P6U)bJm__F2xKIOT& zub40NFi1(<-#lgZ{mYjx-){M{^v;$iYPI)N6}H#gKB;xvxT`(c-S@ZshhO)uemK6m|K`sTiHWtZ9LUKl0IcI)Bh%=X5u*LSbIlz(rJ z<*A<4H{X7E`gEz>;y*KgF_KQB`I2Si;Kc(sSdOJO3N6Pw%;WeA50s zd-uNO>Em3$9v1a~jo_<^`g6QKIL03Jyl>tw=MWzgbLY;T6Qx(?_j|O5ZF~IRrIX>8 z&h5m6w_o%Ad&)dr-n;qs!{5KFm)SEr3pg-8&Ob9%PEPJzQEZ=i{=FB5c6N4l^B+F? z$6qt?if6Rz=C8r=mp?nQTwvB-TYrt?>j`l`)gKGiJra4V-mq`)UfI&p_J2L~E-V+) zZ}Kr`uP@K7Y+CHIan>z9{;Mc^P;r8Jl#0;XS{vzzP)>Gn^$hK(`>Z0FE5NUPkqiFXKz)s@8R`Z zx9xYRHpoR}dZ+gW^w&HLY2tsS<#(};DdVrH&-1IbrKPS6e{*gpE_hqDzv{Wp?ZmmZ zW#9S>nams*czIsCUt3?DnyxeN9rJ4mJv)DAwmB>pW`{;O*?wyM`(C0{^os`DJJ07= z*YdJ5elgBzZw%gZ@A=llzgp+?+*!%yV9%7XpgT4w`D(EEm%3w4LTfs#CL2z-_F*bSI zsgC?N=WUwXlixn4Z{zp%z5WyG@(!~uUHV)+Hr?B3iK0}gxSr{`D3RG)r!8KWw^!&k z(~CD(?-s;at>4%7%+G$;&ndZg_{`&1&E0!pR?w?Vw_o?|zDdo$*q$%l!Mo=|Uv=}l z%)`Ik%T~YmbZyOkMjl57UY;H5TT7LmvaP=y`h?#vJld?TzCJ(v?S*#5AM>SkjdkS} zWjnq&c61kSf6DqT;jjPtH__?k%bqRJI&F4$$De$QOSAI2_5@82_St^HX2l9k&)-{~ z?%uuoX!BM5=c(V>`Vw+YWU8t+eU2)5$a-y6JVOZEg|nvj-&OwlaDG-+{N=0L;vJVp zPww|CkNf7b?T*2^Z`x~v=lx|D@^krC6j7~{{JJdt@Q#STv!1`azP)k#_U)O?8&)N3 zUha0v#Y;{0`qeixVimQ1pUp^5^|*nnY^&b*N}WudJ@MC}oQmIU*LU2X|Al{T zy@J@eCXuE(ud0nE-*w&ZF3|pbe_pi1{}bnKZkpp#nfy)1qTGam<-&oooJp5t{@i4A z{xt_+NTMZ1M|M<9Df!pth;gU zyA5)I+h#u!pA!7wU*mc$&)fE&t8G55&+R_2M(UB9^QoYXJUk1mv+EY@SJs;-96QT$ zlZ4jKg=_y_pK|5=R%6X)tQY<@dT=gZ+4 z-U(OxbeGB5PCb~<{B-`CW7^%f;vRQjpHf# z-e-J_yMKqz+yCDG7f0W{`1W?g{iCH>7n6=hcPViNZOuDfy_vUS%m2FEm^~}E?yYUk z{xiX*VBfzBzu1#5Miy8-`PaHl;?TD{3&cO)KNs!r{KUFVy#D&~Yh#_4{a{dNV7qm5 zXUN&im9pB)q&usai(XHS&Y967YER~J-M7nJ7MEL|`EW1en)9|bf0*M#CzS>N z>j?QQUN2OeZt~{)o_6*Ne@*Rwm8rjp`xY{dO{H$dllYw%H+z;of6Bk>^Xg?L=eQSy zn>ud#|LIr3)?1N9tJzBbmR2Vmu2{ohm7DI=Ji+YrQo~%UFdfmRyNvb6a~{vUcK+O{ z2XjoTW7qI5c+21UNA1MAczN0C=PxBB9NK5Lon4z73WTn-da?}>9RJaWY(6v<*Ae2 z?ay^fnO&6I_F3X@#k!KsFUCNS?q%4 zrs%JCqra5B?RfQmGJ}8v^YO&$duNUP-v$`(O}%wRe{PM)+h%$1On#%eYjg5n1wKE? zm$OJxrv1D960iJ|-L={O7v$J4PTZ?|`=ZZx%UKzZSuT9ql<|CV{`>I1Yc?%ZDYgHb zfA?!e^|PMq{Vncm8K2jC)t}wYI?wNwWsQZXhPA>rADaW`u@cTQyBROLw#6x|p7q znZ4gE=iHnicW;mJs!w0`*m6DHEG(M)G^au@Z%V_G{a^Z*-CSmEu*6kr$EJd({Wlk{ zTy`^Va{b#A+;6n3ZnhSdaA#XvcC#jZ*L^#~wf9m|eCq772z$e7-IlMymy$c9cD~sq zS+wpl$JJ{rf1Nw{QkA#)yy*|TB)ehn>zshwpTF_0D_pzuX5y6l{jX#?crz2lzTRK( z*KIK*LQ+oKOLb>zZ@=xnjG5)af#SsX*KBM5UeYbz=s%f{;gVhISs$zC&0Ci5){0#< zhvQ97u=T9$`j08gD^hlEXz!9N-u`~dz1Jm)bD8rsP99CIPe`VFHZ#UXLYA|k@=av4fBBXup+x4@i z2H!HA{V7F%=DAY|;cJS@Zt!h>&3`KI&de1NtBU?EPtIYu`^WgzwrR)ZX3g0bIzRg7 z?QiE!8Gm?tv%|Qm`tbWTxqC~q7U(|z%)MaqeOA4=dAnLKy}6jdz517BU1Nx!(#E&V zldJPC^WDBs6DpIx`o$_!jYTgm|8(sO%TGUEa!2H9%en3O1-;%2JzF(J=l+#Dl&>z$ zmgF2Y<5zXYXWmMa-Tw%A@e`0|UjeUo0POW4<`+P|mU_ODv;CfU{f`nS&RyP9)@4L&SSbmw32 zJA2>TwZE>O@jKOFr(M0Id*Ry~A_;K}vBe5e7IjOnUWyCloc;RSjkdzy47d8eXoV|y znkVi5_r^aZE2#h6seqk_&z|irR&;Nby!*IqPTxbulG|EKb9MdCZg=b!@0iT}C4Anw z?crkHTjmr-KYmkg^Typ}`41kZ7qiwbjlY+n{Z@X5nS!5bbhN^)*fsIH)Nh@9d;8(G z-9cx=OH7qzpNqxs6r1zT^9o=2zS`#OJ&xyQ_9-R&lImda-Si&fMu=D%i_<`s5tGU$1%lM$eCV*im69(f-jd&F z_1M{(zwpW~jrN6%B~Kee;(V7HK3uYEZ|Y$S<%VsR%kGOsI>(a&=b6*e>Mq+h^oezKZr<9`@t?+ch?G^Vjn%uex;mlw51C z(c)yw_YAwfY|41~xh-YYPT6hGlRj39&*qljF1t;Cb-h7yt@iW&k~!aBofh*CC@b=O ze%pMJ53)9arP~yT2bi8uWIjqqX(T%We6_n^xb{VKgz|Vl=sMVwv>e=?@Cn zwCXy<-g>6)Uw%b*bG^PS)6L1V{^gx@d9WdD!QzMR{$D@GZRcNb+v^e=*SY-g+j5qd z%#O^Jb>Lt5(@G~s=8Q%5Di`;x={KVPG}f48W_WBb4Pl6_RM>Xx)#e5-sZ}n~ckk^; zoFnLPd*`n1+b8X=)`lwnuvSYycur$|q|?HMMpw=oy~~W7(|Yu6oU7=*|0O*93#zZZ z&CCFW$8)B_Pw&p1x_n>Yt$IV*tSQeW9d7UcetwPHip6!k>BcvY?p$<}Rcu>+`(>xe zVk_0sW3HZ>n$>jw{Fd_K{~=l0S?4{T-#)M0Aoof7)H%*iw&pJ``IT*Zc)RBf#{x#C zj0Y??tUunmm;UWoPX5f*zdSGA-Mjg|aPGl>MyKue+~9nWRTcR4RdwK3`}Nr`mbJ*I z-%P0qWw;wQiM{+FBQM{q`HeddGgNt;jSsC9leZCC89C3iDq*|bguQR4e`RKV@r$|h z8q10;uR5e&eLKecxQC%C^l|cZd0C?_y}4obUtg@@`T8=;|MMfBVAJ}-Yu9q@WDhgH zm=~DmeERa|gmtsN^R2PT<-KUf{Nlw_mJ3teSTC%eHS5hS&D+}#JAR2d{$bsR59cKh z#yqW-*1MF$aQE9cWwr~MMOG>eeN{TVx;}r!yB6nNFl8)pmbNQRfs_l&kNB<6{&#lG z+}6b1YO8;Fp3^zkR_AYapzGL{Tl-Ibn>u%H{)^Tt?Z3Y&cg@P{n)2%G*_61vNyZEAa$JOAY?H`Bj)a!*-Rc+|t+{>Rrby=a@3UdC`Y zvhtU-64Q&jY!`Tqh1_%xZd|qU4Qw0>8Yib*?rl3N%shAI)o-BG}K%Q^dBEt_KX{V(H}Ta$XeT?^Y>saom8ShDij`mPW!f2FQE zSsmwq-7d*bZ*?c0s`<6n`K-w+Nyd`DjazirT)eY+{hHg-<~{EG3v!)JY#R9N+jQ?X zvxT*tWqR>OYSy_$p3Z*9?=ijDs(XH#@d9gY|Kh+m1`T~pSJLg6t8x-dY#Pq}+m-aY z%wq3B(9EH+%BA(ww$EX_8}`xa{ytv@-P+}sYDAb`IN#-Yq1^XomZ=U0=K*&H-YuJB zkF})=JVmer?@u-Q8NruF+es#W69pKRsCl}~FIG-{-tkZ*+u^(ZLBq%YiiEri zu53T7y2-n!dGpPTFIPWJV=RgGxc(DV&HsLz9C6(vPvd5&OB>6Diw z#Cdng7lx?v1_mjKRt71F%e!-Du;hMz{o+{I|A3C>-QQB5x`o;Ht4??q`0}BvU%qqw zp*uF|dp>F0k_%Nlx{h7-{}fr~9RuzYW8Z*S@X7+dRgDM`z>`n&$FUsM}4jt z`-OAhFo@qFzyK-UEL(9Dkn>ZFU>Xos*UNvv>+ka{G9P&?%vaOG= z{$-nc{=_xA$iLU`ep^v3cVgR(onNXgm*#o-+S%DOlzAE5X5PGbie%u?Lgp8WruJM5 zZyBAM1#Mc{yrDY8p%A(|?eb%4dqoqIL+^Neyzx`#o;CH}e ziL2F4hFfvLXZt_pS$|z^x9f}Q*>7(@DESuU@@^D8|Gzi6*muSIlCu@RuVn8rvVY6J zU~XeXJ@@8=yti(ioM*PDKE-^MWMuVBW(~y#wp}+K=G9KW$XDfU>-2k%a(Z6Jm)Lh%`?Q=wa(VQZeytW=&)(O^}LDQYggTNmO3_zzi3|K4P&`& zv)9VMadpqy{55pziJOMjWxm3oR$luxzf+M_r{ar~Hc71Ivy`2h9bxId{cM-{&HfF0 zCvN?^C-Gj4^V63#zw4MXd=oF-K086|`oUo61=?-ZtjT*Y(~mw+!84-0+P(>96h?HuH>hb?e(7&P|N1m*4u+I*K8Z z<$}X{4c}?j^Dl3n=-0+uJI68q>G_X;+^6f<5HH{5?8CE47-ZX zv<6{_>I*Y~Y>mwTVDJ+{c|*izN^e_t&x^@$TR<@>tXD|=m2!J8n3 z%*d~MYBw|N`l9!Lb;mzY;tH<6oU_l-I&|q~-uE&$uTBW!z3x|bXGwZ`t}sgjgVYU; zX1?taFI7(Nef6|jQ8>obU>oDi9D`TaPW-);XK*`n!+cfq>o4wUN^hAvuY^1C#)P^r z2V-|1c)!locI}q^(pCp^Cnqg>Zsj)D!1i8H$D0~&{oR79&_<%{tpCog(YbBRQNmecNAFAYwH{ZqDU+3?9>(PdrnVg@l2?h_1=f}PzOd~f;}%}iOI1RP#O^j;VqW0US8#!<;%P0v^}%Eotzmx zVei6EU-s0VW{Bc8h~7IFlw?nuE&1izu_yM{fqCygy-ohU=-C$g2EWOROV;vK|5(kJ z@^Q|s&r0=udbuwRZckI3Z3~JG-euL*KMEANpTB-m5Zx1Hsry7jehvSE+<2#d6Sg@8 zHSF5@rF+-B?dSI$oBLjTapDwthwZ#a+O`<1&YP8Mp0R(`mn{$HD(~LfKA-Q*a=UVN zg$A|@9(j!yISxLzIlbtLDgXPbzkVhM^zMqhmHw-{Bv#CNwe}u|cLy)&PyFx3`RSJ5 zyb`rV{?q^SR*Ozu_~+~`%RPZUYmR46|94^DgwFzpKAZ}Fe?tDy{q}X|Z!zrJsWSKA zB;yDDhx#@$mP`>n_3!oZwXbIC%6X)pJzu9QvQ3~@%w_!*;d;(R-YkUTnD>ly&}T{c*Mn7i&0{ z>%Y2lcUw;T+p|`4rWf>{w!6`P`dx0Sw)kC>@U^S6&pERxAHD@hc10CcENa4w5iHR_VR4$AkZ*h%*{@%$d_B< z>vi7d7@rYY(fM=HL*FYiPp1`Jj5+j1`nFZ&r^1UtDy#dl-#VB}slS%{6>N8TU697o zHpvUQsxMhu{rF;lduBx1(AU*}vGX}|t<TVAxWUrpgN}hAoPs=Y2*F0y7 z4Gyi!W3*M??fQ==<2O^-Lk5lojka8?RoxaxzT9^r-s}3p#K?Oev>#;1P0q3ZC3`JN zM|FGpP4>GTcLJW)iyQZS(7XMYtGL2jcCNrSwr=Hb8Da(gny%5?f}IXce8t!PBf3mq z`gdErjQjhowWl`B^7?h}D06)Dq@|1xAH^i!Jp4hEH~#u-MT^4{zoSnWTwRxVWZw@> zTT^?kuth%|AAb3HRPX(zxnJDpJv6=LxV<`0J)@;5Yo6K~`H)|&X)A54`Ca(kw@sec z(bjs)8Wj49rZ@N5>dam8{;GD>+sM`V%!k+Cx@@-LUlZ5slQ(o*yn>=Ux1}A=nR`;t z=~j%S)1Bn{1i7tpQT)}bCf9jx+s63DM)s_GczmLke%H2X?)Rl->oQNo-t6Je@szq3 z7rD)Lxr2Z9j^!;oIRZ^r=q&mt<{2mKdn9k)%NvV3tO8f(=}pz2-0ObT-!7!j_1`Al zu+{d<6BqV>S^T;??{S$$3~S)}WuK0T$2wLmx%vHc7G@8FqbkM zkmNbSv7lVZW`j%B+M2z*UlbbHUVKluUecvu|C^~)T4Uqo`H|;X84B2#4Vhm2-LY#| zQXM~NzSSaq{k`g+pH!C?E?T#K{bA23_5o50@|c%SOkCl&ef#z)Yzz;0*pkf6%@et6 zHgY}Sflt{oECbK;gJx?Pd>la&+F<64CfFPfJv|Ms1y8A`|a&*^Za`;adAOXU-bCi@0)zVdy=v0yLa#I?K6IvGPf#x^6Vo2 zi>xO54+IK0Bj<`la!oe$8!fZ=XF|noA%qn0sef($` zGwJ*H?;&;7wx!F}Ei!o#%VPBBqIVJhZ{_6G;o3iSPhPz`b&s1{ zZsHHM^2xVvN2ecI&T8~BWo{nGV)eZjmh=Tm9r(tvVB_w->6e=)zU#hMBC07`;5Rp) zDI>u?FF*e+?{v-Z=Zy@%I_Axr=XBDzzUiK8naq~en^uK)eO}U9xb54A4-g(y< z+f!-0zSrvRIyLjBek>Ob6bd>dm&>jXvUj%9xFz2COHbs%O?8EbSH9=J`uA^MO7U~B z9rMf671w_3@t^p+&f_VE^LEWMpSc%g=e@hsYg1*qd*{x?U!OP5Y7ORJz+Tq&`t&N} zhHG5!Cp4d0wjx;FaeiKS@$A{3B$XT3`nnmUcJH1&&1zO+iQt{PcRx;j|9RovBY}7M zCY@zwG-=>6TRCTY%Gz&?91EaUypyWB;%<}jS5p4+{O$Q-ezpyAHze2TubyyutM0*t ztIxiu5)68K_|xuBRev=de%PtS_T2MplCyhZeRth6GxMjQWiK+~j3#B*Kb|TxdHOHw za=O=>$cv28&&!tRdvDtL|C~9a$p-D~*RS)xKlA%u_ z&CEHnSsrTjRmr%}u(R^%j~`!>Nw?mrF`F$*R$||ckDleG<~ua!8!}})*a42E@NJ7T z_q#qneJ}lX_=`Jzd^xNtK2RF(?|KuJ(sjQPc0+qulM zFV6J+yF70Hu?4$93#v9qTW#)VsG5DqW;4UCPtWSUytg#To-Dg;QQmzWlP`K^(O;7a zXI#E4dF}OHyTaG}3$||i9lu>i?#GhVZR?(Gc4goNhgBnkl;Hf2`8_=`y3vCF)ykU4D$#bYMd>wfvl;^L zuCrgeup>*4OSk6kraeC1{{LpLWxL50TwlVQ|9=01HV^Kyw{zA%d^@#1`BK^`vHTr2 zuetBLiGKAAuHU`oTg;E&W_!3?k80${?}@!8o@Umt?d{21-FkEQY;Vk(UA@9`+mRIi zE#FSbzdF6@)3bd))=b=Z_h^Sq=8qE1IlQx&(&sOZyOXv$@cMm=SJ|89nMT`v+qGFV z=QM*=wX22eUW+p?!2y4IV%zTjj|$QZ8?MbgzwYA2oXvIx&bKSR%>E>K$9eJQH2b~k z4eR#je&zqu&a>!nS;QU@mJ1HK47vaJrF{IiaR0qY_B!u6KTkH?$#~;_q!bGFMi zExvrg^4fe2D_i5a<;rhjH=9^_Eq{Ju;mzZr?(A`|f?mAje(q7Gyj$?+jx8^o)-V0C zaJ84_7yB=f8eg}1{M+U-14x3vFH>bZ7rYQILT!pkS7E4@D@ z?QNavlQn(LohL6sPwYJ9q&)52;ai7#-s$^&Pb<8(@V;qL(UXkzCG(PN--H$yuQ%DY z`^EAn|8x&n{`MuilaoSww{>%gY%nVZw@%US;Nt?XEQ-+6BIq?(qse!Pq&e{)yY zKe%t)ac$9sZ6%jpvT-bMWZ0YZxbBJg-Fsed>#U6KSTtO_a^vO9o7XKYx87U&Ch&w= zYR~qH2mkhz-fWt?d!p!FySaAvZ!zpj`yhE$Y5DOq&rZ`XZO7RzBqp_Pp1icZUq5VH z(DU>5g-h490FKzy0H0HU^D6EYHhZ+ms@V$9^jy4HK^%=s3~ zZr5GPQ00+cv7K?toRYOIen;nhoX~Ky_Q4A0Nx9P3w^eM;KlQh-jz3nW{07rY&IRK6 z(ag**+8j%){;c00%E)q|;u>Sg54q5&xaz}oUl$&I*YWoLkIvAS;d9EkAGWQPm#ULb zd0%$(_Rl>Gx8`q&l#U+bTP?^3o|{hWHX zu4=}DCDQ!+vp0vkymYydG^J^i{oKh(S5E8B5_s}v##^8DT0b>%3*%N!Re3ezoA`+X z3{mU6s$XUvi~6i=J)5cher`+Bl>coj)0aMUEZKVN{@>QViW@msj@{ZCnY;Ar|E;M@ zbwh9LyUYGlXYHk>7roEl{;j_v?ORXFjC*FMx3Nz9EL!(R`tAQK-&Pf^S?wwwx+;Tb z{=NIHvRS9*FFsaTu{%Uq&`s3AEYH8Ce){{BPT#b+RV8CnmkR#4b!dy~%v|0%!r@sy zi}Ke#(T$pS^YPZ)SdpD}dyStwTbJdvZ2#_v%iE@}bF8j=dOk2XK)%mfH2R;w-s^Fu z3sdEOfBv)8yl>vD9D8r!vg)np_!hhsKm4u9N~QR~<=Lg04RV(x@1-;3f_g?*=Vty+ z+n9LZYW@0)r!D6$kox;zWn%AKPxGgB?)%$s$!@s2@WRpFw!^lJUmoRVCotSK=r~s= zf6N%P#7>9(LbvT^uWicFr!wZKT)+3(Yp?uoLBALan}%)MZ@;PV?Dx)3xXIwRKc-i$ zu1#>+iEq6*`PRF8jy>{kd2@a9Ooyv~_pLE8*Mk7hV6BaE$H3x%U@y_WH&@ zn9^2~w52#^Rz^a)WXf+_)1w;4r_TFwsqdzL&WVdzbrZH8EZH&bvc|%; z*v#cyu2k=e+}-29@`H1}#joWnnBV>hxe)hq=?~}CB~gp5?%%6-G`$=cxiZaa_g=^9 zQ2T4Te~(=boA<_d)h17wBFSq{+&8tpIrjF4RX$`5G(c5{pvkWpF6`f%A6u8NG_LKlTGoBuzDMix1SUxd zhwmk-TkoyQO3BHMH;q^|r#?|#&gyCM>Mgc^&TZ%4x!~9BrI*YW-=C3xC+=#0>D>Eb zHx%QGCtEx*dh_sj-`~)T!oK<_zRcij1@)QMg;V91@aEt8D6!+&;R6i2mhX-zzOTP` z>8AQcf0zFHIq6%vM)&u*8~0z#+gB(PwcqPwblU&#q58#d9`Q%6=JV2Du|!h~ziCZF9tdx*uzwr0FRJ5*m`GNnD_X6`yO+K@){hE)7SSPwq?fhZk)r`!}qOu{GNp>chL>?OzMo$rK|2J*AZ2Dt%Un#@a95>+~-_BT?6;8I(&s;SJ8%9=L!q91$<8N{=ezd z@?-05edlhLy4-W=|5}Hr2Y*?OY#Q?ZDXvmu`pQ3L``@oy;{$HKzFxWhZ`A?&{ZSm> zKE0{=J%M}G{@7KOO;5kQ4gDLjU9I&@-(oFuqbEjhLSCtV30JJ1`g7;b`%`##?!Pj} zVsD}TyuM3YckVE{5y$; z`MfJSTkq`5%P(;}%dz0{(o(ITe|!J6f1JYfVteax@#%fF4`v+={(a!z*SPvbx!22V z&hM#SVOy}j-A1e7TYhvh^NVMWCJqd|GP(`l-uqbf_&?UI7j!;dCmFYYO>R9y?)&2x zXSleVKD1k#SQWzb?ZfQzv7h%|uD^MVam(L*iG|I){)cZ{G^~@%TdEyuQ}oH3ss9*+y~z!rnV#opWFJ;uh+U)!23d60+$d%Uv<@5Od z@cy{Luxsb;8!`^p>s!NwbEZn!E}yftP(s4t`yC6u#m_&zS7|6yJ7zbTAu2uPbnNbD zflJR`-M90iMA7<>_1i^EAG>odczyfu#%Fh(-?Bd1zQ`Gz_tF@@97r?*C!B+4v(E}i zzTEzL^`Tjpy3?0SFAa6snlHi@D3#)3?$?_yr6xWnl40%ol{4jcy*j#F$l><+*g1Uh zRfW+fUEcHdPu{dLJAK-dKih6qiu|6yBq{Ciz31Q}_f@CnFV*f~`6I|Iyj37s_s}tiL$*(Ah@rTRprBX7BDk zd$91=mpzkyX$pSrtn`hzc5`F?kGq$8WX`TsFS>u;Zug~oMw`k+9okv9&Q&jHYxi09 zhrM@C%%wlvY|;;`I_F(`2%22_E;TzTef83}ou*%MI2T-=e%1e?#8&|)ri=y#DV7V| zZ)AjjYnn~-st#P87qaxJ1<3cuBX4{)Uz9jimjB9nEe&~*T`w=q?PZ#4%)KDnuQB%i z2OZ`YN8>UxTffYkv(Dsw+KF5B-B(-rCPxRdV~*n!UFY8SWNKuJi5A%g;~c4k`(pW@XwCH}#gw(v7|h zxz)a3{WKc#UhA2$UnsM^=9SyO%J2EiTelA$U@iM?oiELPp*ue_`}Wdc-KPrQuf6!) z?8*2gNmKT(VoP0iSXa{an5N__d)@X&`KkNgNPT+im(X${hx|(ZwflE*f>xO%EM~Y> z_b|uW@E^;TQ1eyiekb|wS}54_kHavkUfC*Q?z5MF_T4U9{Is|3)Mp;%7u#yBmow}t zX#|y3IbqSSXNlXLlbd^Y79ZQC(={HAZ?qctdKc!{_bzlU7E~39X1lQTXQZa}qSrOQ z3z=VNyyd#j(lU2Trt3F#3+XN4%OxDj`wUWlUvfSXC;NB$^9c;MG<)ANXK1cI)xB;D z+ZR6O7u((?oz*5w<)7P?=NCe%3TqvrfBX`(YM5F3{!TH&-D{5a%NcI%tEgaD`(Abj z*Kx(~6_USYeSUdARAk+>ogvC|vAFKh8RsV5R%pok9r}C4c6r+dyB*o(UR(8Rzix7@ zF70C6QY@+Grf4?l^7?~cv>X4iYw&U|n5%dBn|Fapz5b5p47=9uj;P#ojx)BVCvNlU z)86TPj(?ST+s*$4S9|^C{c(#SO3Q7^?vsD7wDq%G@LQi#D6wff!>#?-mzYnHMoH-Y8E-2LESg?^BoP+#!R9e{Y?awnay?AWnwT5$T883fHU*ynw^)t17 z;;{@I9u@ zG+nW0=2Mp?TWe>VE)ZY8$#xCn-Tiro&oRGfdzbX|b=&#&7rIJM!+v^N6UZ`FRC?sr@M%!cVjX#d&BuTPKMxc6`m!>VyI`(5@6=iJvw^?x;I;?4AUew+U|--5$w()(g=F4$}J zM!7+*R5I)vuh;uo<`r?Gv#gcho@IJ5PyOt-ReFSjTeVMyoD!M)l>Zk?Kp^o8|51%zVV3`u41T)zVstqkBr6 z?Om-HXUQ)ATUR@0OKs%0_I#`L7b-2j&Sbq%rnJ*OEE3;jwx+nfz z@Wl#+s-?Pfw%YEw)OT~evsJx*j`q~J2Y#O4#7``IYD7jK^CWWTx9ziv<6 z>-D=O^X+9!8?MdG=lEonv7T=?=YsZ_HdDop%R1+!ZEnkc*sr+Zdh)MRXPI97T6eKW zWWmA@(oEC0-gTWH_8^CKwaxF`lE;(Pto6gLw6T4D!juv1ob|2j?cPsYm|k3Bo*%p| zJA9XUY2Cp++l+X2UVq`1RK;g4`GMLF@g@s;@fx@??3+@U(eSViy3*iV^EY7!{cCQ|bFRhjFI)P)&GFfa?cZ501R3!P^SrePI92&JprH9%mOA5? z38y!tB}8U%y@_%#X3D6ZYAJfstoh|>Gwua%^WASnE&0oSA$xcCRL0bA`}W`9joY*G z?!L*nEQ?ANuWg%%b;eWkxH|Ld2cS^``xF6P^}slTg11r& zuL=?EMY@^L@5Y-j@Bm^2IMX_{|H(_?Nw_)Dt$@TB_gQQY<`Yj@7Tf znYSiyI6v!#Lc_M@D;FAv|GHW9vb=cdWYzlQ_E28?^_%nkce4hT-m+`xJ0^FtulvoU zuz5M3Qg=TqvUvIPQc@4shN9zE@*Wxfj%RJA|6|&C*6&u2%haqm2HnMoR8cR#KYM$Tz?QU0fcHPEw?mq`lk8Uc_HCMx^E+)f*UjJ6sfm1+g@M;sh{&}%`(?lH zVYsz_XL`MJ@yBy3-X-~}O#dsSVfFjwWTo{JH%+Sdt=CO#F8Y7yuTUZk;RG@xJ?)%&Py2Ef*OS@A_NDe>*s1 zY1x5)J2qdLc>3P&DlO;#d(~>|s()1^{uEjH-}dlKN%Pd%UF*2?`s?^(-@I~BPt9Vu zYyaWByvuE|9hDn(z^#(xx`ZTaTT@%_>g!X!pZd3_#(mf0qQjd%I=;-y-JP_Fb?3(x z-4pU9>0g3pF)!0Nto62smwoP>Ti=#HHMNqPX5SJxVgGq&rWYD<6K$vO=WO3urjugt z!KXgQ?&jN)18MFtpVoic|FF3A&&{xT+fD|Q<$2ujxKX#lFEG`@iy^mK_n~Q2^3t#y zr{1s}+-A1yXvC~Ij7!)So~c7 z=cb!PUBf!=A4_^8LSn;B?*^9J{OWjd@zu*2YoEVmuK#^=!-Z9Q?ujjMw!7}%k+vmV z`p>QF@9HhGABqXrh8ir1UA43N*3WrW$2Xq+)N`=7D!cF1hP|2=YvX+r`>YBBXWrhW zE-zI&=NT(#q*&uE*HyQFn?AV*{@rhP(KnUb_?3jq)!Q$#Ze5%UT~TXM_1WiJlB zoFjd)?6E}LWcGW`+Mm_lE;x0+JxlEC>uY5**vs0sb1qnH=dbZC{QU{Zo@J31=`Qh- zvT0YkqkrFh#a5e8o&9a{i`cc@qNR8JU&zgxXPTS)b)04Gcgf&v*Vsix1R3 z5PHSHXu`2zx825NufuNEmj4nc>x$X-Uvc+B+po{g6`ItPKH53!!k-N$g=#hrtG;~- zU0M|VTjke^Y$4t*DXTu)Y|~|*S1nr4l5@ZIH^VL?k!YXFMfomSZM#ja!!~Q3TlF#2 zcf#Fxg|ax$vT3XLIC$r{G06VSN_?yMW2%{TU)1dqcg3QY!CrS?Jlo#SyCD4Qr_!+G z70l~}P0yaY@-3^G;nvOnFIG1xz72ZmVlh2^hx=>UvLFW8S3zfcDwdyIrFkY$UGMKp zx6Jm-`8{lG7p9t*FJ~?O)tJ4z+tmEXrK1_kL#-CA$u(@a#$dAK?Zg+ti|2*@@Bb{7 zCv!Oa6B}p=#ii^Q*E8FC}UaRlRf|}Fn%?0+Ry)|j-{e9rq<9>t7 zmXq=-uiCsg%k&~Ny`KMj!2YeA+x_-lOJlzw7{9k=qjb@5Fq~|{@V-NehszgqCs z9@7PLyY}Abn|e=LY|8sc=38QcnyUI&Xa3v%JwD){zgX5W^>gBlWp%rZ?el`Fx1Rmn zcS*W8m#2NZ_tI07b)DDVma06%y?{S$?Tj4Rbu+cMN6bhTztQ_D-Q+=h&4!42hS>UI zf8(22lW;+IYKUk+V$Z>id?$fm{5{KQRXe~aO-{Br1)^zjd~_V_Z$=2h11_v>Hr zFwSxVC?waOEzNwfWyj}pzoY}7%E&o`#e+ke-r zG`79#nx5Squd>GK_b-7%mxNAsPh35BuY{<##=3vM{r>hQSNP5=lPkzvfYLvPz%DY2YmHFH@n@7)cawF!6M&T?1Ep0i7fXKrmU-&@bm;ilC)+P9T% z&dxi<`#x9t2fw7tYiEwx`)9DXDK{J|USj)c);Y$8&x;S<-!n6yVqW>QQ0>?k4~h#v z!vPdAk{hc>S6n-k~Ny>W-_v6Y)YUFY&Pf1`Dc9dx3=$2T`BQvpV8)N&{pLEEsfbH&4gN;_T2@kF;=9swMMDx;y3}t2BzTBoC zu?l5}D!H~#(mqjn>b~Gj_SAOu+*9{oxRzH}XUqF+-|oy2Uvc>+g8?U_$vkoE`AdHm z-ed5aE-SHt#l|gjp0>(VgWp$voVa{h_`A*nn_b=E;o(JB^S>$Y+2GUo{_Je?8s+ZT ziCmhY*Z238-R_>eZrQo!GK=6P{u}L?!9l(!L;ugmj}tF3%u}5E_9=f(L+|lwBZ0Gh z;qm+H&c>)Tyi4joefso^=OP#R^?z82NqDbYdHZ(sZ*Jz_y_@cQjAR!&U<^J(VZ(IA z)&ByfKb^w_awr4C=z5aT^(2g-#Uu<2NGDFvB2_ee zE-Wto{OjxM?rv_-85naIUtYa)@1C8l?cS=dU6&ZZ$I{GMvU~UL>+esR!y?Q&9?5IX}I?pKNpI{ngds`S)+1 z)QgRY*;D!1?YkD2aN#RGef{_E-@nxq`?UYl^iTe_(bF1d=6G$}{NJmuW8Q+jzVEBl z&Q1*e7h{+HxJP?)-R~XSAK!Z0_wdEKb?cm#FI|>*qkDS35yKn}rVIx4PKI5Vo<4p0 z_U&5v7jFz=HZX6?nYZJ!Qmb?N$0;V$-=00|o0;R*w5@(O?}G1lWO8Aq8Z&;$oOpYS ziH`N3y{D&%CcoY8Sah&W-2QnHbHOE!1&ni4m|l4C^YeGFJji#LRdVJH$4~3TqE>1K z>F~{G(mWIXK4ay#BTDC1DmvcYf0yk-bza{#&3e80n+uOkoyqWPOUs+DH@`jn`ukI8 zsq^flXATS&ptHOEgc!fvYFhR3;ybOF3rjwI{8$*yKV`LMkWSx@CtKWB=brd~OJY}I zjcDB|t!TTcUVPcx8NbY%y*T&O{L|0p%*jqwYp^@Y_Pp}j!}ssrUAkX)^$PD>7ei(# zNRUtBSfKs#{qH%~-r^fx7y zl`Ad3-fFcd`JK7TSJi%@cDKCv`?Y^|)@-O}xv;!q)4WjmxGJ^&{{C;}31yyhX6+KJ zQ~mbki;E}|B=xB>N>@BXPth%4$=DgPtf80 zHmHf}F7sXg)cpEzsd~%H&0mU_RBv9DcjEO^;qX0Mw$w>0|onI)4}>TiGj z`t{LGm&Dgcy$CqI<>j9R8>jABYf$cYzBJt>=yFHu`pXX)zdV|EW=Fh9ywO+Q-%E1& zcow{UKJU2cr5cN~y7h;p-A%7gj%vGkck@=u_Y1LIxs9ntRvy5B%9)1;0^?xIHQr+$N zq`mPL$9G56zmlH(tSvTP|MnE8;&0nZ{Qk~;$-f}={*ou*rWVm*U$<@1%RL~j-+M_~ zT>9Q6(?|OYbMLOUnSECG@QvsQXX^*)mAqTGeEKu()Sk5C>(;HCb$#9^>ywHu(;j!p z)l835KKuReFE44KtlM_&(<5&xW!Ys%{rGiR`=@lY^k!ZEzkBPZZt&ebF_dx397oNR zuzEHJ2405aJPVe-pZ!hb?S$PXQ)15?`tm(5aC)G9Y}JQPQqo?_WUsw(f5Bm(qE>dc z@r^;WoyMy>%jK6Sv!vJOyeMX4EU{>=dpL!Sr)C@};Lwh}o56|1? zdh@KCVesFtw}oyBvEX*r%T=GV_fKAZXXC?{#kYKY&pT~VKl}Y}=+tkyty_+Ln`2sCe&Sv3t>WnF z_48vh7r#2rAi%(A!XTsDFfDLGY_yrrf{r%!!18NlKmIInKA!MNaNF(W^Yxr-->#Zw zXFGer&H3_a?p0;S7s+jw*;JGFL+5tjwY)9z4xou6Nyiz>CyRM+i_U+3su#+#78f=sCoIVyYQ(^#mQUCJYA!rw|lQ_(UsZVx+2MaX7`(IA?H5)zMS#x`z@ZR z{#~EGZ`*dje1+e)nx*PT#nLo9B?H@&IE^Q5x^MP%i?Lau_F3VcR}q>#moCrM+bjDt zyC`eZ)-5JaS1lKuyosxKMy}Iu<`)}`w;ggnE|m7lH9WP%H}&BVw|1{@6{-Fy&z++a(`(b#Yex4j zHoI?T^tUwsV@}yN9_PG7<4t>>MMYWd|F&b1=7BQyKeC&@Pv089<66n2%SQg+m;Btf zf7_*BH}lS#PtQI->#pZTN6GX{$_(U6H~6A1 zT?qbs_KnVi53f(>NCicP{d)P*Na5n2m0#ABUVB?IV|w3*uh(}3mTodk`u5@L4ll{D zlecyxzMUj%d-Y@=!{wXlpI+YLTXH#Yv4>KYM%AsEN0)Lg@>#g$LVMWM6{3@Z-}`K~ zt+B8)k3Jh_n)Gka?+m2^e}=i|0yc-oyfmEpZPuxII?MlUF;zRuyIXgKN#@mEQ_MQ+ zY~OP(Se$&)EoYl+SDeA_RpuKuR#b#VlOre3LKPcIQxAdga`$CR!f~Vs74_a^l!xtygbm{N+k~b8FwX^rm0!A4)ssI9B(5 zzw=#MD|c7*xxg>;x4yYPxv1$&wqmXK`Mq^POIaH}J2UV;P`N4ScXrFl62=QhSL&5X zJp043>r1t#^|}x8ozMQixKwxT*3$d)oEc)Jp3B?Kxe_d8x>nZp%Ji#mt-D{k&H7q$ z?QMqo>+3hSm|oKq)4dwHU*sLI*_o{1ZEJ zzhcVCYfI$Ha^{3}{&G7L*SXYfP2Hg#|L?td6JFiqb$fgJsw;^HcXv ztea-`;{S#PmJQdE3$Lm7u8LV{Djj$A_LkhWp8{7)72PyDcu(Y&_=ddI)l)D3oE_cv zFZxE0&ic*Mu5B^SE+pOX@mk&oXI|#*d%r#OR>t=~3{`I;KcC+DJkEaQC8h&E z6&u(JCTUr(KPTa7y=JMd#s24C-4EToSa+p#o3g`AkCo0j*1LJNneEycZk=2;$6|ry zE2+>hKh}5aZ-4t}_jPwjRKcSc7g@}GB+l`GrA zdf{7y*7RAP$vY}TYmePc|Csb~cAl-$?$x=LA-7c@%iNtXZQ*}0Gn><|*Dq!NuKl)6 zcJ?egcinl#fnV-?uRe5nmY30!HLi?XKIg_i-&_N^lWTu>=D+0XtGt_a%{UeuHa@#~)8@~w;_t{iSnFSIynpNY$sVo+ zZ-4Dfe!VUBX~ESqM!O4^|M%kE@j5;4ok7F4{cm-9|1W;3e7((U@vWI(dNO_~M_&k2 z(!KpA#{2iTqw6)^gj{$LJ?E6$nrE8DwwbpQQyJdY6keKkz|2H#E^l@JL&lQ78*ePw zxnM;-XUjQo*RQ&{Mw}gEKwicOF?g zH^oGyOWCO6sW?oSi% zDABKdSx5fJJSo`3SmK;)WK*?TbCJd`8BvGzR?{xoe5nlGJ9F;N^`a4Fi>J7_@Bgws zWqU$6%caZ{mlCWPQ*Za?T&XfzIxVrCv7}!2Ehm?EX>#1Jnuz@ZUbn$Md4F%hwxyqr z@b0|czjg~l!8B0MVu_;ioJ&*0eot9`F0XLq>MAqFEmN+pZhDh7@2mbiDTnrjyXVf9 z;b`h4}*jJnedyL4?=%G*p&Q=fXpe|GK;u~*6r&$TB{GGWTj zOXq8C@44y9dFcL&IXb&*YxAoL*LKbHdY)IIT($`0wM~u;x?BBT^#nKe3prT(JI)EY zS{)M~pME>{=MIyHxf~lVamSyF`Zncc-W0vAHtCxy7%jaLgwvI{QherB6_k~CfCkc@Go`ccOQnmjW-!f3Mwl#A5Sw$)p$DT zYij5z)^Cyy@^|h(`@T9p%EW5d(ag=fS3UVY{Q7lE@8HfKwa)1-m#&?=vBUSigs#_u zs}{e!t(Th2-MmvP?b7OIhFkVGejQ86Vueb&v<{g=gZrZP=h+WG# zy(H!F#UnxgpG&RIOIghHBItC%E5?#-)B3m;9R8%U&CRz<_WHSocXxWXPA#ioh|P+= zcCO*xn{ds)U%43k1i|Smt7Wp?=e=nrw*^+ZX!8p=l)wA4f+6apMyy*~8N>Xus@kWu ze#NfpF?-q@ba0E?*=Xin_6>2;|JT~iHdPEf8{BNQda|wi(izoPmR`JeE+u}No|izY zTAZ_MSeNhfjP-(9E9d^!>9Z0}r_A>*IJ5fI;u9}-@7ve6FL(>9sj|nU zw=tWozPRw;-dc_OH%diQPJdHc74zf7&WV=k#U7_O9A?5Y!p=`x^`MS?c;QciZRCr|`zR<6C-XGk~V!Hb1&-r=VWxnp$ ze$2DGwN0guVOQ>v70#Qs$#{JhOyAjA$+)GrN_+kfao%rP^DOQ=9B=Oy7A<{XRp9TX ze(qnbl=RID3ytq(Wuz}MZxfEya<+Z1_~6^|OJASg`f0a#VdY2mZ_mXYrh|*LDL<~T zEI7=Z5$*gZr^N8k?7*w(8zMuubxQxxIr8PnwdEm8r6bQ?=d{&5%*Xsfacjv(aZpYC z@9&5Awc6d~_iFF2-(tGk{K=Y7wLQ%5zaGwyV<_+g=l@1!nU|`!f37lR?m6Xu{b7cb zOV}~VZT@!*Jd_*qy0^?ZTA6*y>;AhZ`#&>fM1P!fwfAr1g&xKkvOZP|XW#8@>~6GB zUstqf+LWyGDqGvi)N)x&etvpx`ueoj?d_bi?4yl$SAAVocDPRY(VT$UVRM2R=H~iX zNq;-)RG{_h1H-L(7WOXDf3%X^Lg&wwoXWT1ALH7oQbDUOL2DpcwhPW#E9Xwwt)*R3 zcBW3;^xL-R$UVXDf6rz7GGTMr{11J*uJiA&WISLAZcrTSE4b8tG?Z_zSO2Q+Z8P)M z+MWBbeX(Hw9v#_B!Vc5p)E0BAD_kg9{Pu|MHLKmfKJ+l$a@)H!F}lJnDf8K^;EjhT zc%E9A*pfE+7xUARp7{3*|@PkNGje{YVwzRfsu=S$90&&sX7+C`mG zIIX7~V0GP0=He*{Rg*GQZTa zw6NN;6T9q~l{=dO+t1e&Uo}6sA$<%F$g{z+SthzUcYw2~@ zD`87mQ&;br;`yaalk4`Wn=^u5JKuVBYkm5nTeri$i%B0oH!X2K1ly#A>_# zte2ajyZxx_=7s-PtdD)&z5VCD`(c@vcdxoxa(EavP8 zfA2B##zMccUB12(Z;93&ZqUt%|F^(#_A`;mOfNFLG9`4|t&+d%{=MYHwS3v8wXq3S z(id75d3?|M5xgf$Yv)?gmkV9n*YD2N_R&bG57@P8uIAC)b1DA2?Yp~$T%Iqw(lPbf zueDj`i5o?d=hpX&c)|2NCzC}wuH3tx{v^4~Zo z{Oa{h(;I3gOo_Hw`>h~r9rynHgzQ$^@=yLRW0iIHKHIgu!pu6lt(NV=;;hUs&ePuP zRk(HNQJ*Wn${mY_ynUc5HAr^zR_#?A=cec89q>_ImdEl^Z)y>4uKbN!i@TQ=n~y*PYneeLBKO`*RV7VHNFz*J$6?4%gY ztmiR5*tf2_JE8Z+2iskDoJue8&b!9*V&1VO3lq!J9G1shFWtS6-N>wgPjS}$2PgJl zb1|E|>X%kxtJ437Io-CspR>9S`K>!+*7Gv@)~mR)H{WDRmPtGGuUdN1=I_zI__KXC zqYqDD7h0!#Z`<4^sXiBVSmd$d_g_cnDmJivun}}%w(vA!;MgqmCv(PB z{mrotXRWKhvYFrBYwPPdb~ZLYIOp*Tp6}mQ>s`-u ze}nPnpVdqMZ`l#G{qv@Pd1W(n*Y}8pWNKeJ{JYfhO|!;g)9Ht6c5O-PTYLLcXPNn- z5;@CbN52I38P4()x68hAN+R%Kdyp@fJdaiC1nI$q;ma{#3!!jG`Tawx} z?;gG6WB$6Ju5Ox$-?y0G>{l=3c|6^yd*kur#eY4wz9~5CI=9zPtbf%_&$bT>jaR*MbMfoFpCS%rNnZ@P zVBmT4=Isqj8veR^_#WP|?cLS+XSYpDtoWXjU~RB!THCI~?E-u%zjscxPCM^iKQ&ML zUfb`w=%rWVCe$)Ge~VO`o4$5mSkK<;`tQyx3cSwB@P>=ggrR1G%=1V&JpV-S}zweU=LhY1@rKiVNg87BJeB z|Jt*|JpW$EzE%dQ18>UM9Qs51|0E^OnHy1hs?EN>C|qoQoA|;{3=Cy`3{nS*m-k1n zls_rpz&zvbIffUG47FVx3q%=B7{Di)S6nNJTC}2mn<=A7!_Bum4RYe*;`-MoTo2B0 z-~MXK-11^A_wB1pR@g8!%vEk+`>-Z9K7N0d`@ewy>t@fM{Xy?q5v#$n;f*SBF zpL~3Syng(?J^T09S5Gk~A zuSZ4pHe&X%iJdu zy#GrHIM}y0r@Amdcq8b*d}Fg?FRUwxKL6N6Osy2*+2-n=ef zw|@Qdx_5lc8JRCEmRsb<-+-g36d8XEUH0Umsc;7cPr1ee|+pO z%Y`Uy3+uTY3pQ$ti;L&q+r#<%@5hf9|JR;b(w1lMU651xBfZjZ!ChlRqcqor=Ql z9XmMqS6R(wUC>|Qw^2S_(n0>-TDE8Q!G84{Tp9LCg6{Pd1BX|yfW!MaZjHY=7j&w% z&yQisc+=Qs+TY)Qe3$CnNQZB8&TE$4cv_uzeR^3E=Ys9}#Y`CtHzXKM8s=WA+{$uc zxsd!Dm4<6OKf6r+%dz0#4;zIByZyyoe=D|KpZ+hQn_-q&`!Rt7HVRBqY;30e zn~xtqK5c(7GnH!@1D$- zlau>mny8#>9iYXva53Lch24MOOwL^*aH#KP;|a%;_jUB7wWOy%UR%FdW{sV_*Ebcb z;LM$^tUgP3l>C4C_S61z7qUY+TbQ>iTV;RLIdMCF|8t#NE1sA>JX*wYQ#>X<{&p;{ zY1T)VmSXX^o8OG?8s22ob-Q`8VAGTRMbolZ#n+zGzCHc!hU6%akn< zDZQTaL*irgv4#AxRqNk`YF2K1{k`>H-fcdezEg)7y~>TX7Oj}C_4|QHlYOn*w+ou} z*4rlDt%z2Xay;p7eS3TI<2IoQ+x6f1pIss}d&kxA>svxn?Q{1{o3tuO>TpP3-<;{L z+{L#8->r%aF|}MT(^~wt}ued$${nYs~HSc?H z-yuGi&A;`VZ?~OZ^7(CG>&Ek~-mi1h-`psO{UN$0_u7*9fK8JFm-aFlJ$DdW?6ZIA z)cPX5^Rv7+Eu2<%&$^0fedzNm_nj@Xo?B1a8vf|f+MAjwH!E(vxOw`Nrq68d^x$ph z`npW=UT$nZ=4h|_n`wETJ8#Dux0P+vw*?40@ULHVD|bS0)-D&I;DO2 zfVoVL$tr!`rEF{$KKXBBXlK9h(m=mDZEj%UESAi>o1>@M-`@18{LH)1D2t*^i*%RE zPd}@y<)0n0?OV|aKKHlXZ_Oh%*?-#q@YmL>w@;eSzMrSvbJxS-fJVk=^=IL6MyuC# z&stp_${<@CyrNXWDrmQFwd~F9?OgNaoSwT+Z~AxCd(+x!-|kr7T4TF>DsSuMy!E?; z!mp-SP74SNvMbw^a_hy-^JmREtLiRqckhf?`7FhJ_5AGb2D*C%@@{#q&pdnb-qalC zByRQH?Kjmj3>)SJy3UD3Fkz7TW!}gYoF1+2Qy54@lw%y^s z7)!qx?VkJLa7y}<$VjG5b3ZIBd$OU7voAyC%ck!uqro|uH?dFU(|^0?=$mj;+x+eCufB}^=8*IHVT)@FU2hbgT;Jx&axSPTYPz%*{u7scz=oSugYA#)b@Ly zS@!vrxf)N-2l7s--Ig2pZTG!j+8h5ZoAYnUfqw#C+vfjUojZ5V<>}Kl&s)4@c4B%@ z+Iy*&0iZE0@2NNHKBH7J_=Yr`$8H-6cEDe$^RRDtrEH-dd8w{~n! zF6;C7_D9HpS)qZgp)A{Y$E^72>BpDe3iUny zDxy1;Yk5&nZp4<2CYw*TEjg;zH)X7aROv}CnXnyKzoBNq5L)K-hF82%Z zWxhP#pXcQ`E>$lt^jTWEpy>D;ot>9_9v-bdw{P{cEphuE^Kj3dao9~_srSic;ej(t z_T8P9{;hh4^H=|i-oMs&AMQvu(XF#z_|@!}di9T`TlxM}Z2Yu1_tGq}DfOP)u3nl~ zecbH(uUTzMvv$pXm-2M#4iEdIHxr-V-19ABQT^4+)9)5}?DKm4=URR6yZ_TxZ(+TC zXvy*eVW)%cZdTV=>srTPyT0qy(=e^#wSj(@m$%MW+g!IfX8)(sv-~sOc*ayuEQ5yN z`6Ty?nZ<2eE}6zE-`rF@*UkEwzUH(#4etU5@HKzdTg{q_m&M-j)C)X*w{PW~c)nW^ zic-7E-yK-ABK&QM_TS?|%dB(yx2tcF-Q={QZ0==Kme<}3{zqK;9IEAGeRP?K-jDsR zSJx=YZtCM*aJz28?uZ$tOQ-a8FS6ZOd2#OV58X)~BY0)HnXvxpuB;WbuQ* zndSTLPFr5A^rvCXCWhIdz+$kf^2m%1ezV1??Dto3r@vF5#!Nc9b<6X68_({&w_bGW z)tnzjM&~@Q+?sSZ@wYP1-Hy2|x4yZYouzN;Ejx8q$Nfmdooe+qJF-oG=ziX#l~t~( zTedgtYiix@Dc4p%WZV*5`qndMw_06#__pQOP4@iLDHEA%wtWB8ZU47?vzvN%}w?fS^Fn+ylS2s5O4o(?SIL%r>Fm1m3U>@n)&^{{D&!O z&#(F1T6^Dcww?9N>Zj#?OMhLMz&mx?#y$)FEob6h2J&6{`R&x|W1iu!xi|dWWzoa2 zAbZ(*J+q^J(yvn-&b_yp^KJRRNja;R&i&rU`|j(vS+R4ry_s|Wl=j9=>Kh{Jz2c+X z%LQuFqW-^e&1JakmauU`?pM97ihg%j=Q!k;iLzRp@)oHE+6`Sru4=8Q)b_1wOyZoH2bpUjelXg(zez8?YsHqX8b)C20tcHD^N<> zVR~Gc{fr*DOSYNze?N9ko_G3`n*>d&Lx$5I=-+zVjwqDlbt(=nd)ZF&lj!nOF zUU$x6s&8%Is(Mq>VLI1N`v$uy!anKjY2kr)mtJ}-bLjr-JeT`TKPE5U&a3xBJ&U;ttiyKQ1Djs$T{?a3 zuMBmcLO;i7-M9P8&+NOtepTtY@_gsKP+swv&+%RRoO@$p}N%8v3vcD_syA;=!ocBFtml^yoX0wzj!yHf# zzYC-{rN5aoeg`-IW4L7(lAAksitWV36N=M=SIwKxmm}}szP_X^ zp-gn^^x1#^U0SzaFr)wIw~j4;Hs7zcTg|X*?RAsg|E|b`BFKY5R&w_%K?WJntk&FH zY7N`$_tr$Jzp{O=(s1ofMBj=}4x46f`moRpgSV6+55Q`JUzeZ@7C8Ur&@LLdzcn%WB2@-bx&GXCgyOP?A(0& zH#!Yv(t}VXy;2r;h#q57W#ik1zLY#nnMzpUynTlUdv`GU36&h0Mm+10)-OJkG$wijoftx@#n?%_L? zc6@2-f~N=G_S-g`u&b?_HR1><*$5Lo5xt<49_`V zR;>#>+jp~d;q841Yz==EpoPNAl-|eh(m($=@@;ne`AHiN?{8!5zq|dC;v3@zyP6+! zGu3*?jSvU(y%1YF01O zFJ8CfxtN3bmsx4o=ZCsqyzg~8Ir28=$#*k!51)HJh3UXW(7?yaT&9fW*40z~zLA`7 z;s5T{lO=~undRR0Su20L%XVQ~+lz|BmIBWOBLwG)%CTkgwin!C*!AyL;i)6@WA1NA z4w^Jec?oN@^6u4Ux$(0bLZ(d$md`5LS6jwl`vhE-y$u&xy|3gA|AN=&CtjWrUZ=ig z6*R`e-YvWj+DraAyXdUq?J0L6ZH~O#Q=A6!&CNOcnWaMl_tq@wykNileq-i~ocL!g zQ_mYT#NE!mwcy_sdDnXF-2M8IziT%bn?_rEyJs$COb`Lp-&=hdYJU`za@22g`o(hS z@I0mrYlCmkC!b1O=N0$o_?s*27tZM@R*TK@USO=e+H;Lqd)c?|%lrHLmooO)t|;k9 z@=tx)zSk_r%8Q|P#qZP=x)Vw`vbMhuiPD^~;+U27HRBNNwPBL7t}nNo@>}*XAXO=W z{q4UeF_o!Nx8~;0mv!LZsmG_xl<`~8&v9vg|7-pQ;{AHMPqtWDE?=+{)U|xl{3Lc$ z^5;6&ke$2wVzce;&QxUF!aMKJ&5lq0H>)1CWSpBO?mr>-d!Mw!^mnXvr{BCku;-oc zENQQY?T@s+Mtm{Jyni6_#|ufe3)$7a(pTpHS}bwN>vr3Tmr^ICU(e6V({Id4Jhd#P z{b{d`C~v}fjs=Wwro_7W?#}qs{;*s0hWz1E@|$AKf1WmYl2NB|jg9fk!9Q(RBC{gh z!@k8kE1s}VJl1ZwzwTF6mU2FKu1|bIee^8Zu$KqjRxaJ2{7q!Z{`Bd- zC)?9rPpT7~l=gI6+)1%ZflEU+1V{z?uJ&hn<6rf3#pPMb^^2=#ysJMC%@l__7_7M5 zpPawQe)50Y;U2xc{}`;S+>7)sC2vukW9#-`#N_&=XVvYs>;D8he+#eldn>n0aLJoV zwrg)@=Y}xIUVW0YSxsK>l;tlSYipysywR15+O&7~?6ZAe^;X8VVVbQcbL7oscMpG2 z7As${yeq70-maKa@{85Aerw!qD9UFo);@#>&q{9zj#M;yYu~7_d{+SzL>;WdSf1I`lAi94_jvVXfLtd zd7O6vzx=sVoP|Cb1&Q2eXKv3}Zn`u)e&rgm@--%ono?F?*1}nf{~U~Cy(yVHb-C#( z#ns1JE>1W6ro8CW89kBPf4+fE8M%IR0>iDkmD9FO-ez`dma$61y8kaO*?c@2d?Czx z_IufFdvmjswa;g!IzKeI$b5O`irQ^&<4SnlyaTPhLzYWUUTYtCcVSn_?UP04uDr~(;QF^&W-IK!f{G_lpIlc* zZ2jlW#`Qr=paGBrT|En~+?BtYIc;8yNrUIf>hF74+NVXEF!-IExa{=vpY88moC5VG zoRxVyWn;*UbIW$$jbzGXN#@_P*6h|sm#4w0ml&@;idO)(yAj2zdk%Xay97b z$K~^_Lsytg-<)=Qlk?V+V|#=1!{<&3)IRT~c;eQloa*0Zj3xg|4OJSxz1LrwneEK< z!r3T%`@gv0dM>G~%+Gt3yI7yIUTA+JE*g1LKdp`Z0=x0_J$31CvO>=Be||fC-!>_W z<8tpfqCnZ${bKafARbfe3t_IWUGK+Puix@l)&5PKO~LXVZ^Hkni#x1;WttmY|Ehn{ z=BaTuo0s0df8|X?rlIz2nYFb?^gw~&khVc_?mrDH$s3t`+>y(Y_ZVDWb!GA0Xoj`2 z_qTkPc~)p~aq6GoZyz?>m-n{i2G;4e&s-K(o2pM56&g_lVWYUW?j6v z>auv4jmP9#%_pb6IxKN=%ilh|VO>Mv9fn^Y{;5CDoq9Y^QFnDv@7kM&(nfCCtGrxK z#VKravYMXq>z+ZZ_V0UbE)I4|vocec=jcyMKYZJqdx7=(?m)&Zmmi(HpW>Yv!jPLC zSk?DL|8Lm3Pa(6|a%Rd!nazz$@P6P!xnw(k}#tPb`(zwEQGTgjff=9u8um-LM< zovJBf{IV+U^0cqdH>4>}+!kiF>!xcoM{j5ux2bj7{tesTHb1+2?t3&tK?!I`UeD&F z`xe`XWzU5-`^(zsRw=CZTK_gSk!@OhM%1?3U;5o^r}25+KDIr|=qqE@x3{xnncVl3 zeM#89Qt^}KS^4db+7~xh|IMGj_Vcb8ftlO?f4TX5#m;H#_HwtpNI5<0TG@Q7=2>e> z)9n9F&M~w7ed?A!t3-9w`NgmIt-4+^<=5s^?X}S}qQae>k8BVGU6jMj@Ze&l>RIgy zh69qj_v}e|c=378mHfO9Hr2jY*XmfM(_3``n?bxwEgJDj~>C>lo@7`^me{WCC&q0nC)6;wR{(b87xV=?JEv>?*PoJ)TUo!M#N^t)D%oBxQ zv?e@jy>;W|yLWmb%ll4?{97#KJ1*aW69iwcFYXmN#zGJd#b*^dRslk zP5tbfTS>b;Q+U=_yS^$<(*y7Oy1%FL^R)^8r|zFp|LW$a%a?lg5 z`E9)QdFB7-$zC?rIIHkgk^wyP%)sL~e`0rc_w3oyntJNjZ>LuzE>@ZjMMsDsKMbU_JN0->lWvKFIxsbjg`Qd5fgL7FCh6(cio)eNZ z|6%J~x!*s2R7AOUP5S-2TKbutjm@4a_xi?rpRG&odfeV;$@nENJGuYdqfdek`JD{E zc*=bACEw{VG=L|a6F7d!aKC!Olri`0uV-gx$F9wa3SRQzd}c@C;?BBH`_0<&X3Ugc zCSb;X|P3S)~!_e17)q*=@EpVT@m{UKM5ha#Nwf?yKzX zefyqmV`8u{X1T!7P%PKfHveRI^4iP4KJDGMJw7h(+MZbZRKt0zJyp+X?wRm8F4E{` zR&eo;+|;Gk*Y@m7PrsXYyD?Pt@%0E@@HVX2tK#dsCVl-m!QbDX_iKs=!`=9#v-$C* zU2i347B(zph?>1alKbwr_|&<}*Cf9BJHh)*=Hd33{nF+qG9TX9zW!|G)>Ea^K0InP zVZX5H?1nnq%kvo-p0_YaF%sW~yGYhz#f zrM)g&DREi$gLb+_+)dtSMQ_#11qZLaDTC~`+N70w=Vq1CTQ>_0^@epj-Lzg`T4A;0KCDkHy?{k(ts_HD&n*KI6|+6*_u=l|HedFw}g z+e)MAW8SQnBIjjCpANWs`PPgu^}Fq}mY2VBiQVn8yKdLLpv~g5?pL{R?>H^CNP5@2 zQ>W&HZ&UbvIr7ld?{|L5Zst$AdUt~F$%9tfkC_bA?lzFHPJgo9otWB^~R8{ z*2=2NhG}L`F#qMM^;Jc>@`^~NMQY|Z!MTrezHZ*?9XCNO+wX24--XKj3BCXSd|LD8 zncAYrAm0;LKUB@Oy6R%DS>1J=?ZWC;kPvZQ822(Zdv%LUUC1Z1hH3Rhrf>Ou1&3H(uuzIX7`tupPrj|ZTOv#{v`FgrBrWw<-~`ZbABwc&QxDHx0Ye;)BJ8# zF1}6dsgrjsU%q_zZtKd$f3EKfe>`KWt5oXTDDy>l9*9cHVhoi~PLhoA-y$^|gIZY{eAen%d-TIi;R0Zzet6=E!%p zZ_b?$JA;gV`7eFne(TiceOs^e-dL5f+NH#Lvi)nj-||`cq2IJN%wOjo{_9K7ncV-T zzqfjQdpG~?`4`-omMh*YeOSMB^Q(E$o0GroF|TQ7XE<C(jUzW5l6}lv0 zJ}Yak-amn(J9yJ0`wgr8_|-amo?pEE*y}d??jLSjlFeqHI~TlddipG5v+3!z*^=Al z_-)vFRddzDZ95C>wuj6!ou9W{B|U%lMP9=zKPSAozb81d^zGLfwvOMD^h5V-t6sM` zd0R)s3rU6#KA?T>=Ne^SrcU0ZQQFm3^G`qVa$$~1NAI)v>5GJ=54uEmxV<^&mQ|-4 zH`!}WHbd;Gd5aFHYSr_`TwC`cAUcEvez#@?%=-M|zri8P_qnAj_w&A7ncV)0;nuqYtCq*#GM`qqX_@T0okDZpJDKQw zQx5#S{@=8%cjolmh@0o9XaB)-=S7|um-;d@UBuVlpSQ$ROUvi?%X3?jqMu&69JupM zPkiayoV@3oHd)W9^Sn@VUia;czw27RNHTn=0ekD4W-y8Zyf6HmQ5;mfBF5Z-`q9+7y2X|uD4`& zTfdz1ecP@p_uIZ)*?1}|EWRY$-d6YX)^4GU-*58cjo-a7H{3PZO8A;z!MS&n?pgeq zwdVQ)+icsXmP=xb>LL=BPfjn6-mNh8^UHJMoMwmo{Et7n^~E&wdfn28+ojKaG`nBC z+1l+F4@1Q^aPhUkXi0J0Gj<0vO^@Rnr_QhYQLysSrH;FjQ*QYbyyZD~SdDRu$d%KZ zz7%+^_gQ@AAH%K6nSVQL&mZ3ROS_<$;q9I^y6-mxTmKDDJG}K2cj9k`TWLXcN%t(7 zt3qR6&I@}00)wf0vGyMC@-aB4$P^rxJ)+qjcjJg%%Wn)qzP#an+(x1Lj5 zYx~r4_sV#liKf$HcRN*mD_MSX-F^r6)T>t`Dhrjrt(N`$HRZgm`CY^4gMZSGF) zL7Z>DWb@{Ymr{<~ajg4!d2YqhPv0M#ZOHhs_Zu5y$(AX(FE<7TX6o2|e`8?T&{t=y z_cTV5_l6lcw6m^H2W{Umg7V)$>Ew zYrb#W@g*R$chye-Mor%(T;xoOFH2JkKfh627{%rBZfmtB&7_{ze}nthd`O_xx6 zTfC3F_S6;jg6bj;@^)ubO*c=t{PsA@T*fVa64(9ZJ;A5?pJ&CBH+a|#G*)hyws`lxeb=rn_>$qyz;I3iwEj}2 zhik!QdD+`HmF>P@V>~mwdyYus6rVQ2RQCiL>hYkPUIkjomu3eixC(6sorLaHw zYC7}WMdlX|U*1T3IdlHG&gkDy_Rf3!if2JMtjs;9(eN&3)0_7RZ!}-e*}m_is@bZQ z+qc{ARWeMY_KD7S-sX)dO-`H0<&Q`A@p7MRsX)!Ww*w&q<6Q&;jWroFG*_6jl z(Z<>P+$AIC%{Kk|?IOpw33JmH{(Ds*ci2Lu;hbNV-quSu{om|-o>qS5+RT6JFEcP$ zD1uuB1_lk={P%9(==cA~lS@*U+f9WtuiNd-4bs}UH<|SUyYSIgPQW{KPA@pb-nhza(^>xvx$z9C&OJa2kVouzLA-_ zMW4D?GHzL0@m2jw9Ea_~xK7`iIbY8DGf3ZXIeBxz+z@Mn2EDm2&Y3OQ+!y+;;cWDE zwj-OFGj{*ay+2*2?e|UH+sE0~`>o6bZg105f_OH&` z{ag5X-s?9r{>rlPtFSQG2*X0ou4cxkD?PE``+frRT(9j(`1qM; z!Cd95zb=$L5;Hd4ZSbOp;nuU5#Kgu+Vv8c@Of~+R^83@NHi@HZ);G7`HWgsA+jct7 z*qSrS?u4C90q9=I=~lNVoU^)i&1~AYU_0+PG0`_~7;e?YKMMI2(DO1UHTv?R{=RK* zuCS!LwtjFq^`(2-vrlg_b+7L`6Sim8R^_ZyN5W3L+45JB@yo$AD}%C9_~iXu{q5KN z1o*jW@ zZ|=jmUn_%e+m;s||MR|u0oKDaFayopaNi7NPOuJt_tpC1osDl2szaYiA8k_1<(!}D z{`Ka8L(e!K#y-?7L6caykqm$L!CcvzuVbuowol*M#Tzd z28QLW;ErP(`-QTU9Y1bA&-j%nVr60MFWtl-%fEbMh{>w+eM>KIaQ^Pg|5@@}!?dJG zo%5H>vb#)t9WLD|D+A4^nBIOfZ_2gB8(v0x@$FA9O?y7+x^SNZnIoi`0`v_|5DDKWgmId*A`ocT3X+8j%AyRth}Z-*T*n3zu4gI$N4*b`OkT~xA{J6Y+-2l?8d;$V8L!wRQ)&Z z|7pH=oA!4zKiF_*`CJ24d3E`>J^9WVqF2^0)o#wZX}f#D+C8y$xBSnf{=2=)OS#nodL_NK9H)4<5wQG=? z^Cr{9DY|o*>N69ft3DMzoRV4|WM?8W-Tw0CPpSJh+-keK{eoFqxYl)U_qg}s>-Qen zWEy-b{@koyP3M_9+fMR6y?Hsx%;f8@r!HlCpKbZ%zO&52q+0jH&JU-TZ1RjRjh-HU zi`yl7|F5rG!|xVrm;1c_lf=uy@L&ljCr>!3Z^F7_W^JVXMk$62=YlAc(Dgsp9=5A@ zW@cdM>t>K*XqeIFxYS)}YMg%s%Yx-+7xEswcf(<4T9+PZK+gkYhQQ^Q=cj5j2*@$M zaFlMkd+DmNmVAo`XfFcj%07k~2l3rCpP%_YjppcQ__Bcapj~WS+^yru*Y>r=oWb}Xa+RtSj27}qWyn7L!mo;`c_E|mc*xWUhq!4Mm_ zucorJbZfgU__n-xe}3-i{u?Qqv-JA<`2Dr%ajiC08;kFK51zDi+4=jM_Ne}u{Q2JL z)82jpPN9~MmcM^;j_*N_yTHMF@2Ym+HDmyv1tk?56Juj%*LLFlzkm1Y3unyw_2I*Z zUvqcw-u-Z|)l1ENweLF~e>-b+{QUC-?Mw#Ut*>Lc=YHPTKIzMByZX~n-cR{2+Q-Jm z?ydZ+_UHB4v%Jq=SWd1I&1$-`rR2dqwYKBwEEmq-`TF(in+q)rv$QidzRc!ZATKBPr8ocHo`*8F(LsxISZ`NE zDn>W{)MK&8JO6Eupab)PVrK^41fS=-O+5DP-d#O=^Q-53H+?iP-%xa;W{si4**d=S z91PIqx+ z*n4op+da$~`#}!RUHA9Lj}uS-V3J{+e0Kv2dCM;}^Ew<=+@fK2Q70AZ5{SE#h!q?5nO2qY0$d z`R!i&<%GiLj3rO&_#7GL?%KJtP%KgAQ->2%#(lQ)jd$ujg&dOSZ`zCC-U^w<5J_h;uP$)}%;DnA}R>|F8q@88;& z64&27*Ge>h^RJziJ^X0;_3PKm%gc8O{@ncL)hgGt%}WC}w`Tl*y4c%$R-3Wt+y!4g zcrVu%`8V4<->Z6Qw;3P*g4wSloDcqbZX46Tef##MoAu?le7mwfDDuRn=NETQi=A|r z@2SH7skPUB1w_tUsM7o_c;=+NT(^6?u4ewKV#=^>`O+Je@$HMNdU)BUBFCW0Z3QSYPP&_h|t=#jEQHbbE(;t&94*7zCY35 zTFE*8(fhcnlc!%^xTR5lV&0b*!B6;CzhkX(dV98NbZPut!-xY z<5h>(+oztjjow@6Vm{@lbihlss~2{!&Wsj|zgE`!WlGAG6CS*4_TRsGId}EC;$7Kg zIwtWi&t|`xyXAlLrJ{)FNema78KfL`2hI4j?a-rR&hejLzC3xe_DKipZP`SbTIzs;MaH?gJ*Jl$hxW4ce| zcI&1|vc-J+O+vhn3oU#fr`57G`9xspnw<&ShtGcS|8zfR>y)?pb+b2}y5)4O^U_28 zr5cO=^3<=d*Q}4Y!(LnXbkQ8s@Cmh-LPECAk=d!_Is5g= zTgNv4zpyN9(!AB7;hm*&!D_r6?}9?)xA=H{_gbFYFP9Wq+`cMb`nU9}m0u0++TQHF z)hF?>TR$JFI?Yvc&buo!!wn(OGfZzDd30Trk&4K(!ni96&ZSA?mjK5#roD_5CzsbA{m&Fg+{eS!QXJGV+pvh6&u5LWn zw3f#__5PxM4_+CgwYn*?H%~oPb3Xnhrd|9tmWj!TlQfl|Nl79sSo9+iAa9^7r%?>3we) z(@cG4=G&$IwT;%~{rlo*-oiM+O9p&z?)LI7$X+*b9>Xn8AMw}zwdE#%%P!wHj5ePA z_`$=!hmY}NmCQ4h4$VY#5g>-9`;Cp^B|p5=7ogV*l48OqyEXMARTyZt5q zwL|Ca|K7Rwt>me5X@c-I_6y(Lg5O?y_k5AYq{)5DV&5vtTBjyYU-98-M2Ut{{kFis z%qffbr<^_~uyOaqdA`=a{ipMCKKEeXcrowxW$|r$zI{o3nXmHJ=j4kwSM(Y0#2>ff z-ez>?%BSgoxAwZDdulnUiw+LH?+LC&*z)_T79|xADf;3uJ6n3P5-~pcdg3Y@YOOqgoAEW zO=`>V`z8E#lCH+w#=QQG&-g@FaxRz+N}dH0f$@0^&m+h5-DI%|4atf-{_Lgm(ryRTi_m6PtkcW|Cp<@z$$ zOKPXDO@5(rYI(a;vDn>JD;2Z-Z%&xEc5R4Xj+S+>@ymq^%gxOi;`X>zF=g!j7{I<| zXGhcfAhz6mfrSS*epkD>KrHP`S^DuDhdTl+=XXC2xwrW87TaI8r#^)41Z|c-aED>n zrsBwzn|8~zHs8Ge|5jvXW|SbCjneIpoBkepfec7khe(R|D zrs%SFYE`qm!XqP`_CDtem2}v?wK4d0;+AUD&-Ir#bqRgbP(44-Mg9LK&YW3n*Y2!& zx?qvj{Yc}#JlZOIF0R{lb=Ry7TT6CrP4Uv)oKx`jb8`EfP3PvV&F!8eweDa` z-yLJS@XvJ9iJSh>jozPC-n@C1b9PJNp3jFDeAyOy%kX#S;p%|DnykAiZMtD zI55wcVJ@rPP*x|Lez|LF^&@>nE0uqo1XTk{}&$UnYHr=Z(*48+Rd4>KI>Kgy_Fo+X7CX0oB&T&3ZijiaBZ)#k_E&rMEEd|MeKEtX!Mll9ByNnh~gN4np#+Vr)U z7{ox0i^|IznKIHd5}B86_22NZ{)nwg!#3%{Wr`N;*_$)}o0s@aSrB>tQS*{ZUzOfg zEO@*8va#R&4-C6<)vLL_T@cSpE6;z+vq`ZvNBid^jdSM|&+c>RE(ukhtm|3-DB|hF zJOPL6TLLo+UC*!h68+|(Irs99G8Gxg+Mds^MxAocnl*72!!Enpi0bxLJPU5$IDxKanaTB$%K1%KQQb{Ka{gldvffSMr!Mo~L$y zo}I(Vvp>=TRJ@#Bq4GC8TWV=*t3}qb)@wQkAFheLT&!-}!?9rQblYqFhIhSK-_T|?i+0EVCf1H1pXZE4*u}ROl^Ilsd zI2SPbxH9l2B;9jixO?aI*WF)D5C5KZQt+m@`}xAEx2NQazI2pHcIbUuKHr()Zu|yk zri|#bZ9H$TzdLYC`zYTZulYN^ec!N6<>}razSVV6)m@BR+QgS`Ui|*;8Ifyd^PHI` zKAgJbf7aHM(|iA9-Fkj%i*3$_Z{N11)!p}Fda?5BhJS2{-pXB*vwrFRGgi@#-}5TX zc0-z5x5CNOZzl7L+i%%)Z7Kf@-IMRe6v_GwQ8V{-wMj0PDClU3V`L>4t#;se@Dk{4ex6G}c?Y1#lJT3BS1s|tNTll1ZtFLYn z{xyevfvL=zvpRo#3e*|DT&cPNn(l~^cF=#feD3Ak?KjK9rGkv#vK0K@x_z?C`n9E1 zC$AUF{YcyVew#|w2~Fu6n{`b)tFkVwUcA4&+~OcZRiX0IrF*N(HiftzUl(QezHjoS z{C}5r_rKlf9~H~OAOgv?nrs)0rcCOaWnX4Bo55=L`HNmVOub%9q;&^Y?Rxp*<4)EK zxval!m@}-+kN2GvUmg@T@07vq6aU^PvDJ1lmV_`n_X)3>`FGcf^q`vP$Cghnw1rO! zJex2p{puN`XdPkAS2=Aj?pT)zIry(_|IM?&`}Q0D1=U&0-jscbRz17i>%Q>%Ri$PL zYww)@vS`BVsDF073!P)`?R*pTIn-cJ`fAR7_Q6|0zB$gYt0WDym7#a(maS}hb>%m5 z-pHy~cW>cc6JwXCT;zIt@$1No(hOOU(s*tRgX~`uQ<+&`&O5oEwZ9k4vtYCR)8abD zTMkyQ%gf6zw!GLP{Qu6h2N~Ko9x{Hpaa2r=^+G%U^?g?^IJ*0O?Y~syWfV1K@lTKM zG7j>mg7-^b6Op@G(Py<~I`>TIW zyWRfp-ra{X%r7oY_jG2;h-JQIcGo!Up+t4;^i^}_iqF5dUVW_|yqwKsy-=3b|HpFf zvkgzBF8rIZR;}Tj-JNA6Y;QA;`(2a%QSJOP==Q$+khb%R4e#`CC^CLom2TLZD==&Q zlrIN6tzuU!n-@N9$zRp=_S;{$FlWqVR{hVru%Mv4{JOAhx!JtMOfNQ0O-V4$_--@n znb`-aiMqEPF8r_Bsw*mWHQ@YeP(ky&GB2C?#nIZh80M$yF-Vzu{f z|KGX2H7$SbcK;JIdoqRh&COeB!QRor-`>c5`~HqkUBW?s*~ac{2lE=%N$+OteV1mV zmUyXDHg@f=*7kLMqRX6&KS~}*<5zk0joh(&zam%HweE_TWad%o_py`h!o$l;8IJpvyvnh0 zXT5M(`{aZ)gIJ$yZu6JM7jKVME}IosENXRze}Ved!=dIJd#^4F_SOEa`}OMLDa+P+ z-Q2d*(fm%L_tw17@RUn?(|&;Rm~G9Exihyciuw^Wuedm~=z@cQiNCAsC!3=*K@U5*$Y;AFjE6@7f>tqqP0xu5mZ8y?E6IcxnV)6T4; zCvN4^i)MSbd@|uZZ`#%$-rlZ1m(^OOVcnYK&rXfow2#W|_6uD%XIXgsq_Vj#>9$9L zc@}I<{UBbSap7hKAJ2m0VUrZkCj6Sa=uOYLVx76&&vti)ZMe$@N{xTt-F%>bwn_`+ zA?Mc)U%aZhpc9o7hL7t`yUihZm#O{S8RWFDXsm>yEpch zrzPdh8|-FWo&4wL>2Kn(7q#Dp*JeK#nO=6LZ2qyjdi&qIuJ!WY&t-@JdvVXp7N!@o zzHT3p=6^KP%rc6-GT*rLr^`8%i{+&5c&TDt#xi^Dt4~eO=GXi2 zF5utUS~5FaywvN{r%y$N3qe_RvFkeae7@}jZyv)6%}eQ%#yIqv-2EcDxUa=d?-DU)e@;OVWG zKdd?Q?{(BRh5R#dJIm~L#BgL^zf-V{hhepV1GB^g>l`tM+jf(URk9@{-1p!0+x__5 zucNEK6;G@^@-C3uL>MnoQyLxin^_gbjyJvXfq>YX=~**5+QE|ZXQaF5*=dj5aLySq2n z+g>Wp@_x|4xFuI()9=b3A2#ydynp{jg;n(PrN3GocK-8R@{gG_x9t9hyXogkbEPML zX_tK&+;n;Q{!`0Ow=cWCa(^m=LIYbt7-PwmhtuXw_~ZK`@%F)!2TT{db@2YDU@gCE z_CKbxQ-AL~QTEkI+$_iIpSJD(4eDllPROl!TXs77N&R8BmOnT7D!gJ-tdDUkZ#4Mp z_vOwrKN58EFUpH7d5@t80_X z_cOO17H#J_uXe0gtWS8WOTyTlY!guE!;>eP0%v^D0+#hY(>#NWQ;sMeMj zw9{7E_DwHlmSAS|voC46#umG`pEV7(me}N2>0Polt$*+GYd70W_S~J<_u_U*_3RD0 zZEuP#%0Tyk`8me^c6~V^*vzbY**mTI_Maips)A+V6TmRDk!iAlR-O?Ll{~xUsyXlf& z#vsdU{hB-RnBO+hH;HG3Wd42ITpY28Vb{Z1YjvK?W4N_%d%EV~S-~&Q1lnGdykN#x zH#cLSo|W|Zhm2oVcwH*qI!)}p#!>Bys*zR^E8DxRAOERY_=(T7n(fP;Dv7^k2Q^hK zpD2Dz@}2R{Wu|HQpG)_)UG-U6+HHJcvC;cArGad*T8lDt|7pz5)3{o>JST_YZN0eZ z%JS#omX>qCVE!{6NbG}V@|AZ-{TIby5)oJ;M{f##+`Y8Qc8#UmPW>rNsm~ea@|{^F{ry9*Sq)>J?u}o|O}~AAx2c%*P4(8A zJ_(24e?6D)3Y(XgnZ7CdMWtAG?(SLQzIi*=&CNIYI`2ix*PwGt?>lT@VFwM->=u|8 z{>&!#@zZKsXV%?Y!{6VzcP~xc{aXKL_Xqz@A6oBqn0=}Ls|o*OYj$<)pP$=4$L_B) ze@bD2bluifwG2DrAs$Oe?E}8al&C&ku`UB@V%7^<9KN^^_#;S(0s-HG%Mb;)P+;ymNB0`x@Wz5uFvzw0fKHSM}TTK7~hyO|_nuyEoT)OW|K0c8S{8D}&!;Pg|pD8(^|K zl_3LkY}x_Kh(E4QPdh@~G?|z8@hxfI)wa}rrSw$cO@HF!-pfyYVtM`Wy!j^>j_=iQ zJG=atU!F5Bzv7%K|1~cqUv0_DQU(v1Ggz!H%<*TC4STrazv72Lz5?~fyMot9cc+Iv zUtwosGv~|1AkTS;wki$BGB=u*ov6ur1LoS)x{Ya5StvX)tXIyXO`$$=9zvHE<0 zeFGmi>$fM@Ki`m?$aCfTB@6wk8{tRnB3_CdpC2+QJ&vDqL19$MAWgg6#3GFY(xW!%ye^oRY_`@{wN&ezmDU$p%E$@zzWtv&el z>({$?=hi;CXt(@8u;+?)JEn{|0>4`&uYR?OiH&{x;WbMwN8*o9{$>9E+@$Y;Zhh*x zaJP(!aSl6Z>hzprJ%euY@>)KdHx6@;KiD$Sc(v(~k6*r&EK>DRT_`8y@VMoLcv^pd z|CD1lZ=|0tE-qgDd4cRXkxT}OCeW;Mu|W#&i&`%2VB-LJBeQ9OX=MspSD(44+ku?2 zE0QT=PD^(;_dbKe$3owI`*!Ug+tIp*>byp;!x(QcfCA{iX6f!%`URDD1Xi>&eDLu| zUd^i?JdZJ_lR*kRyT*Vq{RR;}Ai{D1!eXG>Ok~62%D?x{o;`c(dt7X+t&Poz>h))Sj|2@ATi1FQJLH|3Q?<5!) z7?i*+bN~EpZ}|GSwN;Og9z8nSJpapE{rG)r?r-|j`|tIEpcFs{oAMBIWMH)_m;n%)?a0r85kTui~boNWXxjDnEkEm_wV1obnV+2 zqRJk;eEBkW=AUdU-`zrtCe~~W3=LHfn=i{a#K*?ov@nfrePGFc!Q9;Z;*@kvdCRPy z`6i0Hbeq*0(vCAQFa-32!We9DVSW92#_U}Sj%?;#kZYo^I{97apWbzGO7$5L-OUWM zz|H`jy2jA3_$B9pqfeivN^Q`~`?-fX{OjA>8Gb!{xbRG{sd$?tVo zblv_tfU*pOA1gS4UDRQ_ATBQ6-`{_;o%fezQ98rlPft(({#_lb5xHFSbhS6P_It&K zxUZULU)D!86z%zSF)FOQygV>6HZJZJ_mg;WdylxquOpYwUzgo;VtMwbb@TO>``ewf z5B{Y0SNbQ%?+?eey3Sf_@K9NcxlmKv(qy;vF5{c|99d;P@>evi%hu$xGB7ZJ$|i;a zlRCCnOU}1vGH$8ynzGbw-n@C6BJZtBb66kMv{=1i+S`m%Gri8w^6l~ttlQOY)_B#Q zUvOL7m6buSR;6pPoZa;CMejEm-FX)KS-$N3cQ7tKe)+@FkV%2__U%Ysa-M;K!5TEn z$WUP7$Ch>Zxq1G*C7UDDSuTW!hnun2R8{TTy}SBr-#Z@@=dibm4g2=)T^n=rrkK-t zsSDqvn*stZx;%JMk*oRh;C8w099`?rvD?;2X1~0=+4T6k=GvTOXNKJD%pW`2+uPsF zTN1gaOXx$;+U~Lg_YG%v{_bDQ!oYAK2NGeAQzp(@KlNGuIgSOTy&OL;l-yHjeWEHw|`vy=cZ-w!#ypm z&WARg-oAZ%S@XZn&7aplZN4;VOZDu#O>>NF#Xq&1=u8toA$?ip?oGq}iE1AYnt#N;u*^F1%-p*VP2#ux-kG(q=ThHQ z5q$;*hHWm8^nG*2j-t1>R`M(6{J1ce1(eDzW*yq4apdmZ*k3)n+j=%_V)#1Ya!>U4 z4Ixrei(eNrZJr-jb>_jt!yLcAecM*DOe{J6`H`Dlug)v!%dQu`tbgjA#7koah68+{ z+vxe!#_SB`%f5gVboUnKOJoo;d%HsO^eD0lZKbHJu-126g@YGk*n@=}inZGY+ z=56Dx5ll;aZ!8ygGhP#HCbg~9S-tA?%E)T5MY5C6USog6z`$?=G-u6l;Np~`tFx{$ zZ{t~@uc!Bgvs7KsVfE?Lr#C!LT*&$R#O{*PZm++LUk=9ZclvG+%`3(9LgU`o^C3?= zqqhqFPMRI|{R-FaiY>0cco-Nqm_wW#d@3~CY0FK+r;D4RTKD zV%@uU@1Ez|%eCOGUaQb%$K00-Yj_z;woLmnQ}^J)_p%jTj0_A00+8Y=B{^xgPm9|A zm6D8G>b_jQ9BdY9bCDscD{%SoZ~7Mvv>L>I%{a0_;p^SIcOOaVd}S=j-1=IPu_QC7 zI816Q`?uHAwx%oYPL67r%Ds}Afgynz5_FS$Kj`V{WnH@T5EOb}AAPwU%(Gx|=3T#K z@tFw>x$>_vnKSsr!t@l2j|Z&mJ5jkhyu=BPdX#4hK-!2sEz%fR6Nm}PO<)us%#Yy58{3;EmL&i?%In}^f+ zp1*qK6(^Q@=Um@S(QvW!bddMWAnyH`{_Iwcp6|Oh_6tkZkFuJZn@hc#>&1}U?D4bN z*t>k{M#e33S!KR${&)HCdg@9H*^7bA-emo;P=-;nzmzo*h{(131 zN;;+eFsFWpQC|J=92WbOThh2c#c0_F7{|MLL zwvELW7sbTN&#V*JRMwcuz`(!*Eqb~)F5Z0VU=M>;FVoe_mxC*o%x0^uHdcyDKj&%@S66c{Jp%<%A8bC0=!B`)7Y3@HAJ$-%c z`>vqUz2P!wAvyzt45)z(S_$*@ebvuTPgj4}aAsg&cq0$Wtl$PH9rrG`JrMIuEy)q1b0 z^yBwknLE+GSXAb;WQ;7s_9%t}pFvFqi)fY$JzdLZ&FYGai`!>v#e8S+gxYQG3hrCZ zFN$krsNz5O;1$D;t4s{@L_zyJJi(j7e{Hq@-pep6@MB1DaG-QaS9^Q=GwwwGt8Sn^ zYP_1Ye*1&;j@v93rca;#{rmS##^K@Nrq5d$enn`l=WB@8g|=2KJWWp;F`6uX#H;nt z%y@zK%eV8gD@>TJX1~gs^kVu$GsZ2~iq#|48tyfpTFv|*jGN(rA1F5cgg|=ch8$X% z?O<uZ(yiOxT@5^c3|zaXkCT}F`z8%S24kj;p~bZ9er{R;c*<*%fw&G zF};|TGLu0H6od@dlt5bs=k4CT`x(QpPoF+Ld-m+A^(Xe9_kW$ADjpA7%bIUkw`Q?xV`zdxxed~ss-Lm`j#OkaQexFO@f zuk$KkdKJ@)#?W*7v$D2L6Wbv(cU$Zy!Me?h(`~G#F5EJAd-%2qyZ)Y1KD%$iyQZ*?_)H$C+4=~uUJOZJBTa@$*`b$^E3GMU!8sxt1twX65Yy8M25UwgK6n7Ggw{Cjxdv=KDsb=&9siga}?Y`%Sa%Y|{*tp1x_exb>e9X(_6JI2`XicOd%t%yqT9 z-yJw>ebzc)k!2sx@~8Ee6LU=ruibAqs5;*_|8L;NH*NbPC;DDyW4jQ<6x48&V~yIY zsG5AUmIV0yUusw9Wjt@r%9>lenoCt}dfegG%k`@#>7G89 z{`vJ$CZ6R7_RHn&y!e!vVGigd>H{Zt?B312S@8O~hHKYP?=bvxC*p+s8-q* zJAAmg&+qX1{!;FjG0D4`tybmSV053-n)*B}eX`3<`JeH7tTXU(h(o}GRTx*W5 z%!1yfDVsA7*%>r!YhCkO;eW5w&r4IBt=~+atW+(>rfh^w zr(VCkarN~sD69nRaW|gTa(sYxfXG=^GRa;7OxZ9Z`Vyz3i-V-aOtM0Du3oF?9zLp{O0Jq zzt5c#=&T1`pG!`}~bf`hGCKed}&UVfS# zx_#wx@XwNi87|ZLzAl!~IO~|RYBsOt8?j3ai|W~H%3NgG-X^Zw&R1UAY*ri5bL( z)U~2FjZ@Rv)7LB1-_-b>Jmu2z8#Aoee*1P|llF}liY@&f%dg(fzjA4QcF(TRsb2Tu zf^Q1N*|2_#1}CMT;GNp@wlZ${ygI`AjZbpZEZ3q^?u+_I+TS$jpE@*W?v;&&5v!Db zOG$IOR=-ZSeaPs$wEx-##kneWW({S_CfpXD_->EA{`tVoO=@Yj0f9L#Vx{^=a=IR4{1*ZuAPrrwde4{Cxr`;5p(JYcE0z9RpRdZ zP4}^9kZl2z@w(`t6?vUWmxkrmvg{5=v ztl0Ob?etEoSJ%I9sEq$|>f9{L$C*WEd#A>o=(gv(kZoD}G^tTX?Zh^!%%V0Z&MAm+iB9^M7s`m4`$@;$v%_NH!Gj@Y$t#@{Y! zFSdOtDSCTuj&#m<_6z4uYhAXo=Y7fVfBR6!KZaik`~G*7`9IztU?g?b)xLMTVUpCE z97%`oB3~0r7~bwVqZjt>ebCFq5a*>-G6nL#7Zgk>U{mMIsNj@lcD0JD+PY7 zo>O}x`OBT_X1Tpng*R=#dV3bbu7ySGxE6T--f*7bR^83V;p&KrVO}m%#_x_*UcY%3 zm@2KgF6%IFQY+IGxA+vVB;F8q^HEU z#cBWdeGxer$XK#+M_Y)cWue)%Elak>NIT~XILKQqYnkuGu=np;&_1CCW>E7&BzF&s z`)96s)zM9h6K6i275MS#)1`7vwHiqsbKaPo+_?A`Gvk*93|73q7eUV4j9t1tWGlyl zxmwS4*6(rrT=9Z$!SCo3huiNbW;EWYe6%!3O4K2{$44<1(8M<;S1(BkvRrt1`qG}S8fO;^o37hyFgyB$LaoR`u!F92SAE>ILAY+Q ze&DlE%bf*ZtfHnGZ!-=1W)*wKv-jWS*+)IuFC5<+dNcE%O^X1-ha5o%W(L3WW{g{E zEuwGtKP?w>xXrNW?eR}b12_8idF@v%cl(<8VN03Mz4>gnM5DsjZmG6d&k%LmF{|U+ zpOU!E^NfBQsq-l}_{FEmbKUx8uuJi5-`(C7&%&1_{MB7@sUTq09NyNsp9;%1?Q5C4 zC)By1ep1o@O%lA~FK-=NWw&!1KTkyUl4`yM*7>1-?@zt;WB2m2>X^iwq@0e z>5@g68E3+y>K{8W%&nd|m+$80sv`gDB=weUu8q!79!pC-%iR9IiSPfn%fZytk?Y{i zdR@14$qA?UKdpAZy*tb_%q+cJYpv~^Eot*g817cCe#O5)d%sP@94USFs|D=r3<><8 z2wm>ZzOnAr#rgklWd@&Xh>ufy@2h;}FUtk9&qecURHY{}7D(AnId;|Ty2jrXk;UuY zbVU6(-5vhP{G##VTV4n1Xa4O7;?qn0^yQ1l+lO^bFV6jV|KXv@&k3idZd)nX*;ekS z5G3#LJMhgh#x2J4%RQ!U&J0<3>ZIhv#S@C6cjuf-s-32L`}x|XyTj!j%C}8e%C_o% zVXoN;?b>y=+%F}!_ePg-f119n(0lcqoP{MEXZhQ5v)ANY(fd7TZQ!=Bl>N(XUNY?Z z9A;X!bwy6HMs=!o$}ZOGrnH(uR>+8N!{y}qMA@|Xwhd}rhV4)Gm-%QUS4e(-eIlmq z33{-fhoZlq>@xzA&>pSJ7#O5wo%zk02xRdJao0gwv<+{H5FLWX;ZsCom zB`4*}XxZoN+nllAyAw^w9YT-a3p zgV9_09Q?UohS;ayD?ICWOY`1CgT>vqrqyo~Sd`{y=T{zgDwsPmUO3d!*CzGx#XxIpGQDsXx_c`)|MJ7Y z&~xj5{<@ewJ$zfX`;V==zPKJ;#jtC6>y|f69Nk}6rKxA@y*k=?``^lm;x9J3yH9`i za$)Y8KN;@P$y+Ndx@Z1?cteq~YFTi6A|UsZ?;Bq z#(y{ABbyX6Z%^ZwX1nlEx9neXRKv|L2PMOouTEJae759CJlBRz(Hxh*EV{FBElXBh zS!rpg)r68uF{x6UUZv(X`kieJ(458eX3r%z%YQC=X6=&w`ynPifBPO^hS*0o-VbWjkh=Stn}Z@C9fDu&ach#V5qH_?l?WK>{qY%*|X>BRM{8~tOV^DoU`hK z^H+m@Pqqn}Qxxhyzmm02T~TxM;awTqzehf7(D_~c`I+wZ_YPLGYQNrFwcypOS6Vvy ztCy-Tj#u}bvgjIrl#RGi+w`?J|8mN2xA<>(t4TKD^!~K%0g+5!Sw*M%SR7rta9>_= z;l^9DrkjdXKWz>0U%g0P`!#1Q&&5~zj5mvQKfhUZB)B{3d}|qE*B3kKKeRe@$&ZT+grX`OHQ-!@ZPa+=GIW9Rr3=sN-sav z+PtZE?d2tFHm%y&buXjeg%iAM_*rGfBtJH0|Nv2DF1+`(2=+@Y3q{8%Ac=ne;WU`KXrP#{_ph* zg6*x-ul;B#mYU<9ncn=My}f;L&AWR{8MfDp?(Gbg*=Twr@n^942ODjl7nASYyB8M| zbHSM9uv>yL%Z1gTUA1-Z-@VJb3R)lVb#Kx6#Ri2=OD@fObZ4FL-M8E9CY$MB^2z;h zZ12Q}6WAP{_k|I_xG%~y6@+lJ2%tR&dlttXXIK@)37R+@87@c-|wEp`gXtR zm6S^FihL`LtNoMf?%JK-G4J)}pZgYWX13qPbY)Mtf8&-FS9s^F`@F(n`t<3byTsT( z{rKT=UO@W$oh8LevTT2K>MUB*TN!p8J$$%%oA_7Tz|8C~dFu5yewwd4z}c#K{BG{f zX-k7EzI1Y$1x8)<%&k+t`{ntD|J&+yyvp@f{?EKuUX=d))vK%r`{p__=q}xOc6w0$ z_3m?1)h&3VVKZg)KI>-F;GOU<`eFYI|RQ=uX64V$UU$?xC4-#TLOSMtuJ z^U2$nn%?k?pTjVVq3V^WNXq7(*|TRKy?gKf&5PAviZhI}nO+z;+)8`CoqxggHa?aM z=?P`5D^}hsip(_&S$Xr}ubWl9VQ>ALKgaD3oNU!}zmvOn3+IAzQ9S{N{-o&- zCLEj;-|A=8aBbTo%Plia8NW=k&bRi^f9-PruQ|&FBaSuypK>vNk(?3B==DZOX0~hW z)VY(v&X7=C%g$)h>)D&Z*_ZrRW9PE#g<7_^H%GcBm7QN}+l1zaB{v zzvicu%&A`BZ8!VwwN6Wx3%j|*ITo<*+O_M`{Nsx@SAguV{#Be|EY6%U*Y4;4t>y1L zCf~7=ignO+(w@Qlh3VKk+Y?hYgO}}jee$*F8MF3_J>3llRD@XMr+)oz*|zBF+^Hwo zIhy3-+gV?Hc`n5CWx|&RhQF*gavAvU@2|J7$&WU$_{nj*qr`B%zDlF*O#R0`Uh?06 z``@cjNmF_CqvOQ4f&(8e9(J4g^Mk(UwBsKvKYVp)h!Z~X%g<}kfs@{I81@xR|FiI9 z-wL^OhX%KXx@zs;8H`mw4Qn``Pu{1Pdo1?H*Qp=oY$`RWlXq!($)2ri3dW1t&iAIq<=oSGsxY&$qYDSu%bcQgAq5 zCa0wL{hjE=!+Xl_7BPJIp!c(Q^4~d*noK54Uv9fEnXm2e`pMplKW*F_rm^o^#SqI@ zQB`>0ZBj1F3;hFm%oS-LKC`mC@VKvdT@-B5IoaB(6boU4KS76&CFH*A@L-(B%=ATP z|NnoxFH63Dd3K)i>g541w@TR8{rU0x{r=jmyN;at|5M-Zj!ey)X_HRa|Nj%L{%L;w zzn`zy@Bg!JL(Rs&p_;1ck`=Z4QsU=n&exEi^pyW8|I_;PPewB}PloS(o3g?r%hluT zwEdd`FKq-Z61{y{Naw|En+U)f~J<7N#Hhd+w0@)gC;k5_`Im2I9=mTY_T>ha{acUAPd#!v@9r#y$=|o_ z`kV3RQbLK@>Vt2jSEvVx%T_>i;t0tm_ZQ2ay(_i(L3jXRec|2#Ed6p*Y)zj1MUaZ~r|DJc+ zmMbyKUh&VZxhnsy$=lfE>f8x>k}K781$dtB-Q(Cj`|VU~%b)j3PO9=gy7O3FYZnrEU`*{m5)PVaeDH0kT5 z=B;0{j%RXD4!^`-$$4BsUo~)X(JQU&?iURVZ@*9Ki?}Adp!%C+<@4j57moG(eL1t1 zY0I>BCC&09nw&XjR+rqhOgyue-P>Kf&|L4`QNyDh4L`(~J=!1nxnwQdI*na@bj|_c~*PWAF6;9+G6Vn&BZlUvlD7 zzfGb&zjwcpIP!k>&h@7!N%E$r8Y^_49jO{}+-6Qe!06 zJ7)Iy$!1EwW-T~(RpT^khOO4RwL5ZIcfPB*;=P3R#i!}hmAfW0l~@bxEzz7F#Lcv2 ziSO+OW$(Ab3$~`esN{dUZ_YHmZwX0$vO;S>mlnF-^pdz z8F1%|?{vMw`)_^--8SgkzHX83lr@?1rdtY9b~5Z$S<=aJ^5w_VPK;5r1GZ{xe(e{% zPvug`c6q*;vJ*Zoc(=rOrpSV9v1@JG#!O#)-fTI%UX7`()j9L;s?(Qd$iH2ub#g)a zJw*rhbMrd3-k4Jwu|8&<2{a#(I!epl|)eBY4t zuvc3ro|0sYQr|Rpf{5$M9lC`ks@%s6r_T2{yf5ecG0&~}7ZhLSvg|YnUdmS5J3}@r z)aY7bu=FzNtxo!7W}9~yNg2LQ?A3Z3UT%GHdARePcV@mJy%(oPSI;)&3I3N>AAfgA zJm$d)7N*3-Si8e z^Y7QwhUL9`UayobU2|#nXJg5Wimjf_nvJJ#tm}34(JK)z$n>_#oz9kUD|`>zR>}Cb zTTzkg;=eav`PLZs(4|b|n@obPMy_sJW@S>p_aW~S`#jPQFV+i{)i}L9D_(oFdwmtl@ufGvT-xK`pvSpG)Is_3mR(C{vtO&);8G%3 z{&=7HwYWp^8~%tfd$c^VGBZeSyk$S_o3+U6J~s8w+ZOJ=e!6w_u6_yIr#kyGZ69rV z<~(br!q2iln*ti9ExPdX`owKV=G=Ndv5Cy7TSDreIFZ7 zcKfBTC%2iLF{oe5Fjwzn(DJVg2PV50%-FcxvS9I^RcXs}mrqs--F10CPsUlXmeWEr zHhws5DL2zi_xyS*X#s%+;>lNfZ)>P8s>w9J`|Th*%Zmjz<(20gY(riLJ^G>?D0|@R zH!qg$lh>b}a*e%uVVk6fMQNcm>ve9XlKEG5B^XL9Kkm!F=*+~k(?b_~FYrCwljw44 z|DJ0bH73j17TXo?3N8qW>UP}AI72e^EXM_-kJ66U*Q~#N&+pZi^DbuoKh^P-4mW0 zm~XvJ(8z7J!!7SUOw&KPwtcrWRn&F3&U@wUjRjwit-X2wS@|=$dFO=|_?BOY{=WUI zkkj$jSF7IW7UV_$D&jYjjAgmIS%;MRLnhu`allwxq zaPN|HcLK%UBq`}-+b!W_JGt}Y=_tluMvshQZ=`yEx!!r6y)=E!NiD{z;2lE!R?mbt z-(G*rxBP9utx8X;Ip01T#ZPj~7u(Vst(1KJ|Id?A6SG##eRbyBxqBb^MQ5xLuWwXP zaIlxUd-v7lGQHZ3_qK|Jc=t}WRdD$IdU@KBs^ju6t9g|2C1g3D7%koZqI>GDVpG1@ z>#qLh*C*fDKFeu0gXN|a=ShaU>SDAr{4V|!syt`##lE*MPEWZr^i^>|&vTO}bJ9CJ zk}dzNoPLiruP>2Z`<&zlmhW+Uubth#^`gHD<1b#ng2@5L^DY{H>kI7c-m&GUhw3_^ z1#>%{bMs%$OLa5u<-TyP?MsJGLFbmH)Ah2kqVLxHh){BvZuRx~mMY`K+?~F=R(dkt zDp~OF+ZtJ>E&r-+@AXW|R$I;TLiV9o zRKq#dwC(Y=t;_4L@hz1-zbyJ=M%kP_XQn^#WQ_X#c41z2+!Cp*<=f*pNedqWnPB+vXTQO)x6!CV{P{xzx=YO z>V3cd%@e%LO`*wse$h!1J5S%NI%&4NO;+OZ%dd`w-qL4Zsxd~*{*ub`Q2znfHVfIj zSw9|sb2+5Sw56}-_I$DS zlbjc}&+T|@Tzs}TWRcL}&!t^k4*UO>S>CzVyP@uH^|vdWeq|gNZdGsjo7T&meS1pW zr52@Myyrxs&NZKP7k4y&m;X%Q%cKvjLC^Lus_c`Nv6L5BP`qv7Q7?PjB-h0gA4V}& z87-N~KWQ#FnQl8)9siNrCL`QR^_H{@T1fKFdbe@mmduRB%(m+KpH(Y^8v5S&e&n{- z4dUH;IU#MX=CqSl7pER7JkN1qzI*ktKdIglQtGc8ek@_IwVc6k^m&efm+~Inbnax*_VnIf zHp5BQ|G6CPt^Hoe#2+=NeDe2C$LjA91&4Iz*17K$DqZkzZ_i(!FZ!Wx^!w}-9M0=A z-`^#+(tJhTGKRM~)$R>>@kx1i4Ob^@1w= zzqY-7F7-Q)*`wxqOyRU0Mz0$f{zh&5qIk)PpX0)0#j`aN-q@5yG`tHvBE-1s`y}IY zPkI<^C5zXIE|~kdwe0uR1ux~Kz3#u7x^s_?=E=!SB{gq$#(+{-=ZEUty=T_UVP<*Z zo{*=t-x+cB=a$5WFkF7&;=gjM z^4HX`I?vr7-V0T3VzAvgxz>ouuP0ysW$fe2aXw#I7^CzQUY*VSns#W;W2XB>Y+KF+ zzGqu4?VT4=ohkR5 z<;9(@g&b8k)*KaC>~%USGq(ScZI$~G1qXfc1+~InDGRTZNUa0N%nQ%+CGyuCufEh9cP{8m#Rk=jt}2Yb4BE>%FHB~e@H?;Y z^mN<6&_$PxpQf|CFsrNH$6zabNx|VfOX=}BoJ?Ol_wRCUn0M#Dt+CpxrNy3}b%u<$ zBK2y08s@DRXUPCTeUX0(jJsUUJmr0B@FQGcLG|vsZCn?gvF(3wlY2JT!HGgeAn&gG zUiETD+OuzyYMDyj)qK9o^d)t|Lea_hel@vsUQnHQlp&A(%zO=pY<`8+GtT~$p88FM zuP}12E;q*of3XGLPiKivnYh_nV8PriFa2VcX_a$dxb@Tfe#*J~25+OTiT+C8;a>&u zncAIRgI($g+ZoT)Z2z;@BHfoWw&;1$9Ki)&FB%?C2gbs>uv{m#FNY!60jCSGb+QHeR3O0tg1O|4L!pWszeq0xRz0cR@jgVW-8a%_SN0n*IpRjh*&+WEvt(zVPGJWyZEt$mlb8W%T zs!M`0Pq#)@=^YC*3c8o+Xa6IB@mJ|q_WN`8Ctg|oZDU-qLqpv%hFmefYr$<^T;8^` z78?jGa9`^!o|7xi&XSQid(($&bM_~Oy!^KD-nn_9ayqiHJ#q&(e$aR_na$w;-AgM@ zKR@HL(vs&%Ak!9+(=R4wzZYF_S&^6NONveLv6%`E^S`WKKi9oLM{vP(`GXVnPU_dN z9N*3I;%Aj(gImKtRhEpskq@@5^f|}4O!{hoQtycs{Wtgid9nLkgI~JWl)3jlDf#BJ zzRqKe+HzNwyZUnKz1{ZZ#|+v|*-y%;HTaU^Aoemz_3`$_QqR}@+|GR=*FgPeQJv_S zbCYso4tCG;(v4wT%+8W=pFu5Ip_n_e`d?e-!qB~!c(-jgc&p6vLQ?-@C)1XF25VD( z7JW+iE_oq7qCxNI>hnx`caJbK?uu==Id6aBuHU!Pp4RK1FPQ&5;WH=+Tm9bKBO|<^ zm~F#_wNqJQ^p4ccV$j_j^DN-gbM6Z}C$KSE30~Qn&h@qoDf{+jM{RwU28MLm<^q8%f9#ReXaaR%OOSV%LazI=cbe$|7WvG zOu)BfYjnf3N#^diWW^R#dp+t&d=Zx(qQB3lY^54!Q}y&#J)YLbp^M9fdcQ5+&6=Uy zC%v<{XobK|&q}w3zL-7x{2RoSzqG%YY&c=vf=fPn=kFWb^|H07D3bi`3=f9Q>z*GJ zSdhNP+y2ja|1$0iyK<-f+G|sPxaXJG>wUI|Ywv-oz=JGXx`XbkIy~n|*cn}HW@zKm z(AR$4UwA<=IL-sg&&*VCkpH~e@v^Pilyyt=uM~bVil3y;nz8qq*1y%Ns2;a^C-!xX z-|uY~b$b{0dfoaQFh!s+`n}MC%QHV|D=F=l6Id|Uf4<0qYT0`|i7(z2Y$<=K8omC6 zUpMQ)G>P?6oHvEdH@p{HQ2OcBN6m>0szG*DYa_Lr&v9S)^?vS(^7#yFuX9*%&ggGk z66Cc&zdn!GbH1YV%H#b43)1%-QRlkwsYrb@$A!t)mU?GuJo0+(pB=@`TOUqIXriowU()5Lw)5whPTk-%5cAw z$-iXhm)DOp8QVkZ^J`uICq!GT1+C@Uul|~qQHt?bxZr|P?XDMv(>JwRblh9D>yvP; z`NfRImpV)ClzZ;?yZzRG%ZKu~hI6T}M6I_tw#TeJus6Eln%cwluXO)U`LN-a+5UT{ zOD`Byb);M{nDeyv>j#&~X3IV1URlT6x;1f%+D&cST*b*;x6~MS?LGKs+vff`b_>H# zor$q9E@qi$uQ5wz(d(kuQ=9Dq6=j(-HBbGVkmPuFFn(LWH4GK1#(=- ze4X{a^|qEn_j--LIcuBl-BNw|PPO&ivYC~-MMk?g)ExLT{>C1Ddh&={`(3sTch;Vr z<5lC!6~Rk6q6SEnnCr{Ua@`bPGw^IvMu4)8&yR4eb^d)64kE~AI`ly>G6Pp=$t65)6 zzqPI4rE_=c>lNQWh5q|k@a))Hm-j3BHFx+pXC5=17!_RXw#T&S(n>3Rhv!D2|KsF2 zZiuCQ%-B~~;?Qu7-6Ce*=9r?8x=>>ysa-GUE!(r_>jNvDyxo614_|oP@+n1n)@j+c zWx79HS4juHd$Hnl>XrL-k3xKJhfZhT(y01t8#B`u!{!s3b-x~7+T^qE)c;qFr&49l za$op&^47BzXJwhTXl}puaJqih{wZP$N(G)B@4FRw*Da^+Tj}j9{34UDU9C-Unf^`a zSnbRAR)s(L7=QK8ce%Ez<6_({?&LtuxlZ!eHQwvjclFcbCKc@XT&UHa8?S`&H zcImPCJtlFd?LMQX8L(so9bebL<8p6tp!S`}uuQO8_j z&Y9b7oc;QfqyB9YOJ0=8vU|ooO`p1py=^AZtQoSaw{Xqn@t0F_Sl+xV`P`F-OeF@d zA|}mPTW2a~utwJF`<;n(&WAi69X{sbsm79V+^j9~2Hk$G?SJ>kj7{quCUs`%5!PxpgmZ%FbNP?iAwOrQP19+c+o{*~gyFN<-EgV@W?JI! z%o;AfpS7CLyX@9J&D#C(1{RS?(r%(ggOD zir0l$YC3o)%kaMPvzn~Vec|AWP+f zymHsKV6T_DOeK23LaTn+zghdwLd{|SIs(R_@7AD7ny+;E)Hb*ywYTXU1r&dp2e=8eEF_xqjpA=*4pl zdFGmKKH+5d_WVz4*Hy zlW(gn+aCY&o1Xuv^X8lv((h~yn^x=V^*&Q#)sY7Ymnxc*m3OsFf5E!`srs?i_FfHj zD|_GWowp)ZUE;h)WoO~1r%xy6y>e#F$d%sBnz6RyXYkQoLh8>al(~y@o?US&dhNb| zQ`<@;qxBoSq#fSv-dj*&r`5rt&YinBWl6}{)QXzd)yn(My-$ie`;&j-i5in7mI@Bn zGdr(s>^3~n@=KaEBl2#|ZT6qGUnSE&MKD?kmFnzIOWqmp%fhp|?b6nhv)@cfd2%j9 zChNq`NjA0`?c1i+Y;? zoN>;RKTKCVQT_TI=h1(iq4rm_=1-fa=zaPthkt>cwbT@gpY0X5ZXZ0kM9c8zy85}F z8T(5UFLl|k@bufZb!*_$jDk-$dXDU#vE#H9Z|1(9$~a)~ zN_)=fWA{zv?%#D@TU)tnftu?o^JD+HUoV}dZ7y)GnSqyqAuwgFSHZ9Ht5Kp14D2i! z3^!yiF&vPN-1JI@;T|`W2?ImRgso2J?i#VNWH4ATFqtsC;mc%r(5v9UT*D}^fRRC= zMTSLe{}CZZDF!|TrZ4^S_WwS|^R3DH^X={I8b7}+E)8ryCMohV>=9(iXwU~4z|hlL z`%(FTzyihx48NLY{nX~2|38+&LjDrN0q0q|OeP1~n?Mfxej;k&{{R21|7nA4HrD&Q z_~8Mr7v;6$4CmTS7(U$VlVg;6aM`hejiEuh?)O{sn`w3>3qPFP`vJ7#VYZVLLxu9M zGulylP~$+NARO(`0NS<&Vlpr^=qflcLztlD31T1*!MF+B9I%rN7#J8fu(D*pWEdE3 zFo8k_#?N77gdK{&z`(Gr0pxm^+^BWnkQfb2a4;|om89}dexJ(bnEIz#k|1|`y85}S Ib4q9e0DV3oaR2}S literal 0 HcmV?d00001 diff --git a/assets/install/lockdead2.png b/assets/install/lockdead2.png new file mode 100644 index 0000000000000000000000000000000000000000..3f46c434aabbc47344a9e870766805d94505db73 GIT binary patch literal 49466 zcmeAS@N?(olHy`uVBq!ia0y~yU~gbxV6os}VqjoM-xwysz`(#+;1OBOz#w-BgclzqZ8JJlaTPi?-lAVH0QA(Oskc%7CuA-DQTcwPWk^(Dz{qpj1y>er{ z{GxPyLrY6beFGzXBO~3Slr-Jq%Dj@q3f;V7Wta&rsl~}fnFS@8`FRQ;6BCp2OG|8( zl%U2|FRSN}; z@XWlF{PJQ=kSn2jQe6^DQf-xt42(>44J>qxEJKV8txSxqOf0kwjI0a{AWD5xOA=EO zOA@gvHnlP|K~bEal9^UXP-#lCRa$;gZeoe8Qf6*qda8awUOLz|UtcTFyyB9?yyR3* z7h9!@+ycGK%oHoLB#UGVlcY3VgH#h!U6W*!RNbVcL{nWOQ`00fV@u0K^JFuaewX~@ zQcwy2>4#*7l>Fq(6f1bpStX{WCRv&#C+V6Sn5F1i8kiX9CK;Jq=%ytlnkA^Hih6WCP_?EoCu0O{j$6iXki9V z5DF#v3W(&7)1H*nqD-WaL$(F(1O+PEM=+j<%Z-o-pl>|sgDMnA7Sc!0T@bztBrx4T z(E~21t+3@IVpC#JYMNCFQh7sK$pEoGpVATrlyKl_$|@waqQob$GPS4}nh%{4)1j=K zOr*jHti~@fH`P|jKfj za`Mv^GV^p467y0Nic0gW6cjQl3yP9UaujrRVJSkvK;cotjO^6P^8BI{h1|^IWUIuS zoc!|m;?&~e%>2A~koECJsi5*ZRl)F4!%PKGpyVllgc6HNAT9$bf_f%DO(8iWKQlR1 zM$Sf`aaSDp^lT(X}Q;QYy z!C_hij!7K_a7cl4B2?~h2;F)+{C;T zJ#dK$&WVtur;j6Xf|Ve(2JIAVz(PSTZXhPO;Rt6qq_r2V6JlW7> zj~TfB*<;OU!XF@Vw8AD%M{M_9y=&1rYyZ~mk6NoXxsyjK4q@A^_urW^-t9f}>~rOs z74Ny8?o@nKwQ)k(?z{K1-xOH*EDv_Q@L?4=kUqRS zwdoDl0(*P=*~<)FVpeK&y)5~)_|MPmUft>5j3#@uAnw_{NoV`*+;9fl*=JjtV>G8- zsIlvR`sKAz^!n=?IeLZmsKAw7e_a~Ru-0no>!U(ZI$}&270!q-pMJW&RDiE&vZ-1_ z+jkXE1=~aVVVS#hNJ~c9L`|bF{2hX2B ze={dcq&4tSlGcKUxtyTZLPI_Kh1Xwy#mi1Ry_8{A_K{yR&p(Iz_rd+24~lk9;V;_H zYBu}qF0mVBySE;A5DL+#{PRKH_R0KwwRO?{HVrRJX6bCWn2|E;fht70e)a2J+VVCs ze4h?BYMtJ+YSl}5!=sNs{)jXz`SYc}zkeO87<<|#gz8nRwB>u&A1~*<_@Kva@yn83 zH*>!I{`;`t#@n*fPm7FZ+Nd`7sfrv=Xgs(ZoS+&0n@ROfswpsXjQ8AY)@28?>3c$gDLQi6?z`)><#T2|>y&NTd7#23ZvFNB z=bq)5RsYFR11CJIxlsupCV^Acf&Eiccizq0{psLxmuWG{Ml=6J72XkZw66<4`J;38 z*=5;{XP*~y^TbU8XPY0}ZRBHg#6BHl%>12SV*2%7-gbY^1@&uB{(H(fgBv(G+O_Fgyh?9ZBe z+Zn7P6JCFfV&H{)Cs1Vb%{Ac@Rj;2(3(EU5MeahONB7Y~!h99xkc9OAO6lFH{BnHl z7c){i+LT_tkezqw;_i0Wn+KS|*}36=aA@fDZKWT-{#d6d)papr%l-Ge%l^#vTkg-f zVCs#-(opB5n@Gv>wXeIfX40rFi?8Y}PQn4O<>e2;Ny z&GkD6Uqh40^6gVM&#~@5{d7}1ztE&uz4=>Bl?w8q0VLvTIM=WGhV_iiM@+tMo_Z?7 zq$~8w)fAg+^W^kDR6&wK{Z)|5USF~n`I$E9^wUp~miaO_(l)=e+VHbRuc7U_GN=q- z_?K-ov!wK;tqdR23&#`1_l_ogJi>5GZ~BKks41bLsk3)1e4V?nFu&ZL<()euNlwpw z6z4FX`9;cfZzPXPfy(NA+PiaR9TWH(A35#z+ilrG>6>o~TgM&|x|AYwuM3jq*4w2| z-*Z4E%ZTs28^}C|_ad%=)0Qsy9ND}-ZvE~}r=J#O#{F7;0t@KTchixuv#3<@OQY*yv;TL>=t6_t@5b$=m*V)wy|o%k|1C z48ajorMU9um2VFZe#(7R^78HeJw3JCZ`+zTY&)&GM-*({-U&Ir+it%Nx%(|eujHj{ z*S%>Qr>E|`nX`-O#nB|ihBk3%teK&rHc>_~Bf7^!I*?mhqn_fzs zQu$WAe*cf1mtUIPRJeFt_Q6qb{;Sw`uPybxrl!aBrR5ISL#_w6EHB@+;3N&r_Su+-CK#k=Jyq-WgMNb;Y_cZC@ca!%olT-Ot6O!b7KiSq=&rNJyWb z{$+LTySB{tp40DLzhL5fUFBHn*CS4kcifvCt5^GoF%DeqH$0c_b@Oyx(*MLh0$hq{ z@4l0_o#}<62Ul-$(eleLHy7R8^L)3QKFl-mat{5+lbydLcz%3Sw|~3uodCVn>#n_e z*g4yCn{C`KzMQ>r)rT0@yMR*RfzQ3iAEyKx6+VCLt2Q~s%|=L~CB^vU^JjYs6F&cp z>9pO$368|`;h|F*c7-2%To^QYo%VMHm9-&{y3g}2SbjNklj9-=sklyXN`3DAD%Z58 zqN^tQ#Inqim$Ij(etq5CvV42gy4O}apRiu|;01}B`3$@APi=aWCI9E=Ps`b7SuQjS zTtBxy)`GA7aPfSl9~YSS@I$PfKE?T6nRVus$5T^x#;xDY^g{hz{PD=7S!$C{_NQ|e zu06_Q_kGi;>OC1od{7Tf7InR7;w$9v+vZ=eTI$Z2veK8aYs1u19fB=q`XrfcznvT7 z`}%8@)m*#33;pgrcAZ>Up$bmO^VVldSx@@v6)4hubWwJY+3a3V$!j^sYI=`9UbV_? zaiIJ&J^lr+cbR2>FoJj@GEn65%MgaU+dXHVO^cnp>297c*Y%FC!qd0K>OGW&q#7f} z5_{Fumt}2Fyb1&J&1SFj<#@eI%;E59NK#H=dQmsaM=iE@C+mfn`m5z%D>}XRtRh%;)@z= z`?VY9`KYyZXdhiF%bmF~V$Jo}SF=p#`W=6~@rxuZ8D7rY(SB;vpWV)fpsg3Ru0 z?^#8-sZ&8E(3|q>=AogbxqOutGC6#l2Ld7KK>z0Zcb`8OZ;aqrFkk7uOi+FvLm#+y z1(iH&!d9M3SjI1P`{jGx z+FpDNS;kzT3XZ?M1~Yx^?Ck1zt@zsySJ;@j^oNTat+9L0wP5@0wG2`XbHE`VC((br z{qV!<3qC)7oD6Dy9oOzkvYMOK%XHu<#QZ}UCb!;ykNthu)Hk_f-lBD{*PSX^8^{0& zeFyz1;AR!mi=Q=dBCUZ{dseO5;>HN=y;LpKIsLWj?|Qz|PlFi#ibO4DDBy*-EkNXG z(#98A=6i1DY>}?xS{ul)qYdI7i(U8UmL2wAXv)QK9h?O&h@Y%0zr}0s9VoK;>Z;YI zUNzpSRt%6rr*`6-^5u6wY!-1foPU0|)@6v#TEHglJ8_%We|hj-IXV6OUZKxRO}Sv2 z0;fGq+k7!^N50x*&r4EELAl969PF;z!Yy|N`hxpy+i%VM z-b*IE?92=$(E8Ig(8PD~-2zaeyqmYxjqw2!ICWI1WSYywU(frYd1_P4`s=ZbUy?Qo zI51yu1*KMp{wHtSUhjfLM$yhIv!!8HOx&bXzB@L29l_~r4@8RyfCXFD?$FoNA~d#S8CAm_IE$!8OG-#xd40dC>Z zZM*O0nMg@4J-+(&uI%Cyf9vvt7+!#@qXqGk)_jI^A?5VjY-djSSdr7g@M9|2x;jZn z(pdBP@#DqovYoGN_Y{QtV}Fm^;=6g@v#+>&|x)c@=`$b$gM(FJNrg$gEEHzSUDSNl!doAz(KYnD)IwrvQK^yF+zd<5L zORV04^5)+R6C*GFFmU1Us$1yuQXScbcyK0vG52K3r;i^OJ}#(#!nozw9asceKmNF5 z_2Ugyx0h?2F4}yv)Jxi_v_f&rSoZB6C+>yON}|E6f-!fz(k`|R`2yzSkUKY#qV@&5bk zue;V|KRpi%zTlsBEvKIbz56-EbLHzQv)N~#e_ob(?D57(1_kg)^n&Hkkor=#d+W!$ zo1Z=HzQ~}U4i2Q{U5jS;Esy;zAjikPww-aobBGJCrx$1#A zwH&Kg8M!cAfb_eo)~;H0_~C`CY`Ze0oLLz5LL%?_sZDp@mVvY627X0`FVn!r#({fr zrEi^g+{}67%mG&nj%iQn7auEfrZ6m+5Anm@6r-O%e*7?P=mYg{1sT3f2Ai=DJR-Ai zHSd=kv&(E!48Op=REPVJR>>`g^zVaWGVQfC`cW46uUtXwpJZ2tn0qfSdhbubkRs;>B+5II`4_gxmV?EOn1FM@k12Mi#E?=6S--+y1sNSVU0ARHW0JjYUuUUDt4 zx3hb+8{}+o`F9|p$89k;;!Y2?nP&-N`YF&0R44^il>XhAOCHNExxK zAZL4Y?gB=b!Jgn6?_t4;Ri^|P9qPf^Ph!%lRg=sv_+FM!Vt4^*8afAo3k$9V;@z!g z7Z@(cgNx_3B^q5%i*9b^f0(ve^YkSRMhAbW0gE)2UCzA3R%Ih6t;+BMQo%4AgDcT3 zjcg77z=MAV2H>E{X69x13r_0^30;dK)`s13U_QT#wboDy+O}xa>`F45UAndL-uv&j z96qno-ml}m@Oklag*^Sz*yFkxR&)K-CSS}*af9TTgo;mQ7fNHLmEt@jr)_-p{PWME zojvu(xWb?PuW$`KqH{##P1)|l^0(ibEjui%e*%(P5O%7b(I-MsG~KMJ0<{#R)s z6Sn$liqXb%@|iYr$2a`1_##>?xcPA4`~yW^f3?bFww3Db5n8|T%IjTrGJN&+ z88`E`f7F%ya#$_NZ1&$@2fKGX1dS^~E1riZZ#&5Iu~!PLU#N3B<@8zb=w;6(<{r1j zXVWg19?qO~Y%;X`OqlS=?84=jR|GyXxh=j}w)=1R_8;ryj_`lTmfgi5gj88axL2&w z(r*fDsm=#g2LIin8}1Wq5F()fRmxdM9f;MFEu!Whg}ae_^M4_m-FKD=ga4E_DqU6v-zeDr}J$$nR&bK1Vm0dnYP?e z-1qX1lMYbTy`akVx+wqJ>)EoL6{;KOO+TF)ezpGh9o4u6nn%`NDV-ZK_xM@&`?-)- z*ntL7*NriHyB{t5Tc;%g?p;f@)< z87rNSbX(rysoH)!^GM;|J-vnQe{^|dwk9N4l{j0H%nPPvq6O!Db<9L64{J2n@ zQ9sjYX35om_3s50oA)`)d%xY_EsWwPB}S1UK;4#+&+8$**zyJIJ z)j||HzV^B_G}P!te6QPLo8#LTYsNqd z&u))h1uU@^6}j%K%lE(cd=d3SkuAk+_S3mOVXLR|2OVGq2jiZOiy2ei9NTs`uho6e zhD92Ec^*GXb&qJLUbrtSyX$Y=`k!nt^EALU%TsrGdHK>U zXlqpFKE`rz;5;bxQJcJu|6+Yzot_xCpwN2Vu!_qj%da>d&wjP5%=HL|&+^NAejcmZ zt9Sa+t0qVjr$Tn|MU9(Xx!Z5|9#39;B-?r~pVhjKWtsPEn)|8`U3@0J&7d_KT$onK z=8E^N>%UZAQ)A+rJf)(Yd*Qm*!LJs4|NYlG{X%M_-t^NcHIJ4p{K*yrt|t$8&-77i zKfF-eFG_E^o!5EmjPELU^0vDhzt|C%w)v)XoVcM&;Umw_z30!LznYc$IcNuXoVH>5 zB5w9Aw|IU{u>w_^SF=Q?ANxJ!*S52pKD((JmdwgO@D&n%Q?{+zxSHF&CRUv9-m4;u zjeJ&my=T*e_3I|{{K_!-|M8>YTtCzM4X?p@zrr*$R5jKjZ1vQD&hHnUXZ6!g=w<47>UDH8p=;o9w>(j@4`7<2Hl2ev{jS?nm2KTd{5j zH;W#yf=5KcPhAtU{MBLmex+}6`R==&k|itXf2@*pJ8%0dnaXI_z$>M-kG8eM&zFwS5i5-3eR0w^=5g+ox>K3QPRA{~ z&+!E`%=tjHu02PRtKt2rO))xRu?H_7KkgoT-L13y-~aZ@-p&8-&Drq$|6{@F^|Lq3 zuPEDnS1<1U|78!r%O;xtU)`8F3pC*-6Ba0RfcZ-4+#~*{pI*wHY#u%>^^g9MPSZp7 zNiXXD^}Elxm|_&UHmv>d!!MU7+8zE2N|SA?{(g8$Y4hp5q~N<7H*l9i@_c4ZA@l6;J4&O<&6M zFK??|c#!dj(d@Ik7OnVE1!|T3`+5Fc%k8({)&#xSX8t8>YnFZI*C{Gib&oPkR=wV} zw#x4BkK1QOSFf66cQ_W5$l88IC;d6~<#m2=_tB(|*;knFoUE|%v+I=q9`xNOL)0}e z^lH{ttL-AYc#F$--whY~JHuo9+Pm}4rY-+o^{?*0>8C-zjVc%zO&AU+)Z5STTOP}5 zcl+%%^;3-d?i+`%4h`D#vRU~<>}}CsO+hc#zqS4T`)|?CJ;A;ud!qNG?`C(4xs_ge z`^P;Sm4D%<4y#x2fDHN&68g3LGcTiw!}MjDlk{Xh|BT^Oskt5|c6{l^`|tmku3SIs z1t|1i3;iz+`cwE(acZjMd*S!nV)V}6HT_s^C)d8@Et?G}UnV3x`o8_gUhSV}wd&Re zU1a`nx5DPz9lmo{%bs-nf9)~r#+(^0$E}aFZi~>FwQQ!3TH(>D^_j}g)YnTwr_RyF-oD++Ft`9t7oL=HHX%z|E~2%wm)J8r6tMr|NlImB`@`UbA*nF z-Qi$xx=68+JH9^U-Va=c#49x!LA)~Zi_FLSjDctUYPn- zvGd=L9~s-Nt`snX8_xzjAFD(DI8D9sE;E6v;EUU=n!YCmkfy(QOk`;2*|g0&_RR|t z{u}z~j)`x~(SPL}zd%)z0nbP7t9jdl|M3*`zATw#b8`0Cv_;xGd}6F~h3;N+IsSiU zO-;=m)1H5?KFQb{*5&;vxvmfH)g(yFS{C?^r(o&Fiaqz=@BXyrZCSRq(~h9oF2}cu z{eQhFM(^>aU5P@npd@qqZP@CmcO=_DYn==j-0jWmX8QC99njo<`DxKilL@)Aj%gh9 z-QxKr!zAnUqVUyM%Xa5#FTU;Z>vZ^zKVS9ZZ;2oO|LVy6-v8pW&Oa}W?LVHp)0n4& zL5d-P;nSqOKWfkTSv&j}t=Ig2{d@l1_Y$vm{rmC5W1CWmd#iQqzueR>DMp#I(!d?s zqe&ZM^uq7!{O?$QoO{{j%$Nf}=N^4%<(qTT}3rg%&Yr)+|(bqD3 z?0dZ$-S17@*ERS0>#xer&)2C`?Z2-t*1bb`p0xArE&&EP(7^PCY}Y`Q)G9l5KAUH5 zA=93w7)9!c@#~e@1xh>559OU(ZvLr)pCJ#_&AX7D8mT6DvS{a(dgdLI*WanMn}57l zW2N{ze;(V}XZ`ARrq}FK*(aBu%4<`xF?Ro96$V>SRrg}+$BH{!gQu}wI577}uWFuM zVf#zx`Mt%ni*n3npG+w_wYShj>Sou6m!~$Zd0n+LChuQ_j+kNXulWq%@ok6os@4L> zu0P)0#<63eS=GF=Y0VmyeqIZgUw(N}z}T;BW5kWF51rj>SFO65^)-2^EMNPNN36Ab z8DFR~nlL!5uebEKQ`~p|edu#WbCK;+c09jhQ}yqU@;&2sQM>QvZN9nYf5cz4eRAvq z`q|p+_4W4k+1t%N+n09Xq_bVL;Jx4aJ0$)@@WckooPKb`tBj$_kAaur!t49z#k*ZU zo!*(kvg7LAG^3e+V!NvfAJtgMeEa=3ZF8jF^vyTdWX=LlHT?AbIDLKoQSIZ83uCW; zOn-Was_JKTK`)lXtZ_9Sa=D;>n1aw zu+I>R@1Iz>eDCp9-HoV50%Pzl6F_P?cE8nZXwXjm=^UI^R+*fC;UUh1_QbO5_mV|l3S-ZFD%$C@ zO(|#Av9sT{6^qx`&)xCCCYQB>5$s#3Uboo&i|T7?u9W6>Ja~31rFdh+7U`$8=Of}@ znjC-pv1q5w_Q%D0>NejzleU>%#CratBV6zP*3I8i)VDcf*0Hdb{yj(hUhe;>s^|Qe z-yj2GX8-Zn{fmxYuho*tTetS?owsH8na}RHbM5ul6r;+SJXY`IR$qPfWt(*F{NAHU zfuW)Ns}J2au(h1KZE8W$jl~x;cHfPg7GHcY)NJ-yKmEP^ANx6t@)!<-T4FEOpG>(V z>TrDhyE?`8+gaL)yKgbRFWX&Xy?fz`RjXF-{ImYz+p^tr&!#>8xa0hDx$lQEX6xj|=x1-YVNI zTcVm1D6)L{`T6tb8%k}ynWOR6{n3?4KA$tRAJ%9ek}%nRN4o1^&(f(pKkiq{NtiS| z1hsy?gxuy@uv#g9_gydN2iwB$)Y#cewdhVi%~<iDSM%H zGW>bjCQ?tIo{vBIro`%Py_ned_A>3GSF^Up=*?cXa#hyeIC7Zl@8l=<_i_N@PwfEa?i#q|A zP1N&FO&7oP?O=F)^ZEZje*E~cadT3*i}n2T?YHCiy?u07R7w8rp~4bvr|A9ns^9IJ zma)d?w*wQzwEg>g)vL3PZol&A;Myl|#s8f%6z_JOuYX|II{x;<`_FB;|9<)9mlx*e zfEvaw=j^S8imhg!&2jyq6B??@&p&IKp$h{uIHFf>(%Eh2ea~#s)aC6{mfK8bx&pBoV2+6bJw@LEwjG!>BB$&m`&U-F1{*d_~iqN+Thg4 zJhR!2VhM*Do|LYSz5XC;>#OvQA2Lj=w*RTze*0?aU!(0)PNrN6^{6h zg{3>b|2VDZW~#U1hqiv?F1zo{kO=tq&+pz>$D;Wx?b4^p*LmMk{l1x_%0_O!=(7D0 zzwY>Dgo_sUoVjSL@_8*sE<^R_{V&D3U3n^Qud#W*H}44}8)&%y!u|Nullhh9&jvII zhlZ9q9)EK09jnz$A3y#DkB`JJ{(P)|cKY?>?uRb+_xHFhe$o%lm2X$=oSJg^#QynH zUeq%g1c1|m*6B^FJN%iLwilJ$->D+|`uWs~DhAo(|0mU!-jI$z2D)-e%_z&Ks$>j`obzHZ>yweGbr^9zfQ(|x{t zV);46k1sT|w3cD%`Mcq56<`{aU|n%}EO$%z_G`{MrnI6gVN zVLGU9_+sV9iaS%gk6zz;DCI@hq7GNPpNm(mT7IOmkmvHtE!ych);UiiQ>25wYaRAI z_u_in34O^W$GTo|E%1NyMBubh*Ea2Z&kD_4B{)zEQWSZZGRJn*-K{$Io0p z_Wb$ti)VQ(Kj!Ze-p+8fi8)~hs7+yOI@4#}PY%m3VSys0vHxFe{QdLi&YL-MG6ucJ zA1}H3K74ko#e<_s6H_K`zPUy{^2tTsFaP$<+>;WTdC&R(k+sT?Q$5Y3wB6;ZCX3FF zi7``Tso({N~u5SMP`KzzKnkcI{>A20uuP;k}iE1C$o~%=}`|h_V zlWfcz>aL2Ih6P?<+$u5Wz47e*o|{-x_nfb>3umd_E8M-{?@@M0GM$$-Ynis|t+!?0 z_9yL_)ULfee0kjZxAwP7r^@oRzdxCCZ-OG9wcZW8p4_^i`tHe9Cj<1KW$(Tl7r${{ zPTCE-ih#-0lTUgz{nMX)_E>xkG&3%)$v0s%X^y+?=_D0je`8)<<(sd{Z@ZkmHk~+r zJx~2`b&_-Q`W^pOvnxI`{Q7e0>BS5YZAHlg|4QN|zt}#^xVdlHZH8vG1~vwXd-_jq zzYSwJTX4NB$m`FEGOmCD~RRqs=Y}J_duha3;I8; z@YeQed!4}`d-@+^?t;&H=Jrw!^)r3ce*fKf-Zty;9>2`xx35j!_uRPat zoG(>{M@vQ5=5N2fk|Ua-B{^occ(Z}LeM zy+sj+ci+`ZGidwUDt(jzycWd4zn)**;d5K|?`-G&)yw@p{);_p^6190%bDR0Gs{`} zzSrcLw+S=9Se6-AJyZ2@LFD##DF?T>UhvnitDpJX`Alq2S!igX=Fi!D4@|*r-e2B3 z7-ogX-uA4XnZkeI_Nj7(Gl!4d%$b(5`|`^#ork5%+m=Kg(Nw*+UQx3B598sZug%)7 zhJClVgQYKf0@WIOFZuO<(FSF7;3M#nA~st@Z#&#?HlXzn!8mhYFAGa z3=LHkeK%e8=-b?%bGMhVKqeu7c`%&iUjKGk=B`5rFaJ)6QO*~r@%mUAd;O&55z$|3 zem&Y__4}0F3Fb*}L?s^=e|!@XI+bU=-vtKnY^#I()4y)47kHxP-Lq3r^bNWtEX~sI zws;56Z{Ov<;w1F1DEGY zOj>vSwe{N1*<}iUb~$}^Q~GZGic;WwS7fdNtG(D7Yu)hzbW8g zSPyQgxHDzM-RR6!dN*alvzs3;%5v*dCU5&@X+?$_(0J5~#Wo(d-j*?Cv}uRsuX(tb^W|KlJJF^Q=YK!3S$h2F zMdx3FNA;$kp1x;tkK5vPtYt~vQ)A*-?utcbA7NyO2bY6WbFQd0q+Lk*y6*bxV4+Jt zYwAAdvHkRq*PFil|B+RzCaL`W7=7vK&0p)wCry8IXkw0N#pJWPx5ea7T5R{e9xKHV z1upiyZe5voPnDtS#g{o>yfRS@4wF%J>jP|d0lz-d{Ns? zvIUoZ?>Ie`cjE7zyC&JGZ2$GcV|UxFRrb#Z|>}MoRpVcGo}WMHkQA649A|ca@s$G2LZ$^?gEz zwVT<%y;uKUx5Z2RJ|Enh`f%GMy}kBKca~-5{V4wY)>c0wPdGo~dTEi~?YG|&=Z9Mq zmLK2US1|wm9P@fPfzv-S9?7!{E9*3~J(vse*~v+_&Uh?3SfHx;uzzXYZ8^cp-!IRm z6+2eu%<&E?`u*`^VOac2ZTGKJBL3I89;}@Zvg7!k``ey>y?C78D1+e#Xo=;8=#$G| zp1-TbTeV}4|C_Ly+Z87Fv^cxNS6^kF9vU4ww?w4VxYlQO_maYzOPY_SZc{pQyZip) z>VKWQXCJ4n%NJq*FR{K5?CDhgc~d~ehKRkOK~08VP1__oD^@>gW)=UQF42G7Q@ic( z!w)lx5ss<=^{QV#O~qo{r5hi1z=&ndkm_bat)!RMcQ?-%d>vGes;t4M~A zYsIrmnHZJ}J1{eR35iy^H8o?+^=w9y=CJEuH5tF;N}p5l)mrDX>-gisNgv*Q|6QFg zGi&?ydwJU{r@ouJs#*TcMBWAe;}|^IbQ@ryyh@|%XU)7Lo||~s)~;G5Tz+Qv8q?3~ zXDxflrSbjuUsK+u&)nY_WhFkn6aKh%*Sg8Q^6NDjynXWV6WaxTZHGSVVxHtPM<4cEEQyFR{Ca9W zBY0tb!#}TISM44=eo_$b8mRJh)priJ$y_(1bKlJTqOdPle`5Ukb*nkQhFAAi_+DD_ z=$D&{&=0*PI-BGy9;L*Je~dQ z?jD<;^OFVNt~GkM&Q9WcUEY)}CO_kxBm9KYy*%R~3icddwrwXmH zU&d$xEqd#pvd+HzG9*{FdD<7B9q!UEmMlNJ_Lk58$;a-L-+l4^OP_5aL*?hmSF=oa zhi$~~cdgs4RiA%D=5b`SpxWEz|L<)! z>HqgQ`f%00(vman5tn%xz$*tY#Gjm(`B1HT*+F4d-?Y4YY*z1oY`pz8@9HAOx&XQN z>%vx7Z)wh$we0nqe|!rbGdwc*G*6xRm63e=uPLjF86Jp$?bhm2(tN%9t{ z{roOcmceEssP5SRDdFk$08X|i8M5zqr8SRSo$_bRk88Zfrxs6qarXD~7=iWA>zBxW zaQyO9vj6zW)dz>p3sPy9W9!zkJy~jK4Yhp=Ut#ZLGG#s`b9T)`($4Jd^z^*vzB>ox_diMY1Z{}^|>ZV z5!YUq{^L=IyKp`|Huw4KlnJ@^91OJz4QvcAwyK!^{_`i~&hZOVQ)iYp?g+KNuk!NW zj~_eSC+5fOsmy;Qy=>R@E9J*`K96?XW_raoCuO4i&#AW23=Pqs&aDV|+FHSoJub6>OPt+?%9Kg|+hbdU$P zdfsljw$4B#{jIY^*y^jP*>;)B>-PV(IsUkCljuWUX_uJD`?aTZj{H88w)tPm1>egm zXQOTAGdKJLw_2hCMLeh8H?7{}=s#yG|HIUUxw~)2UH9L)Z0i@z>-j>H?yc%R_jUKw zd6#&s?!9`p+cZw?oJPL%qCb)hzaWE#KbQY_FFxns;W=CR6Zd>-sykcR`o3)U-uumS zPNqyM*?uF(?E3!~(MMmq&vxAY`2QEH7mLrD-%84TdY%C?T)xlymGk%Cd$sJ_^fF8S zWpAr+y!t`d-g839Ma!j*pF7jHN9gQ2_wGxN^*wbywU?5gO3!@$`6se}-=mnc&5`#u zTKV0aYzbLD;&5Me_VT0GK^v8lE}XmDUSKzWe)OGL|2w*Wd(Ho`c=D$wvya@bJXU+{ z=2rLF$9KP-o4zx~&hAO>ckeT=pML*c8+-lKe8vU#pk_tw^f$?6hvhbX(5ak1bM}*? zKhx%QAAPj0GWFhu9|aaMKP5CZ756Kw?=SDRFEVNFEAQ*9c%p9Lr+Fdoe0X{d!wXSR z2?bh6bo*^y1TR-H(sPRwcFgpIPwO{kZmHiFf90hP8(7?%^JL9K4knUVtVh9q!-FYBzkb zHsbKcN&Y+w_}dTf3|;5h`@we`qs>#6$u{3lnJIYw{lS|2wf4fJ8U8DM`XArV+kW|_ z$-fh4lV4Pv4~}X&!Y%hfff3qxeE-S!Oxf2^t9l>!@WjrpMI9IWUd}lGeD&3=zwUod7ww#LHqG~PNa)pP z7mvNV)95>IQ_TJA7WqMig`cXYUCa>iR=scgzG>=Y^BMaV#DC-ecsx0`y!YPv@+B5$ zwUb|bbBfjxTW*q;IXk18j~%jZOrl}cs(Eqye?GhAl4CYI*KGET?(_Eh+!GX^CGEez z{`%{RNS~P!zjT(rcdl>@lfL}%i@U{JvntO?yYJ@dTTI$ku}8b1?`lPDY{Bn}2Vd0g zzFl!_>ZLf2<@S>@?L!5$6E{Y@Dcc<^=W!%E$A*K!7S!;SXjsym8_k>5@otqy*RFNu zv(LWV%Tc!bZqmjXK5Dm^=Dhe)%aJU0?ryd5`$>N`Ji7VA@nqYg!j{c9-`sgF_ET-? z>Z`B9?ixH2dU5N7;mnoaCY~v=>ecMf{C9EFv(^2+zYjLO=dbYlBX}vD;e|bDq7bt3 zEdTe(T0i+eo1+B&c-$B3Zq0fjeEjE^T8{I&Z+vInI3i>FM$s|aYmP|OagI5&+w4C* z6VR^Q8Z~zwU%maLZ=V?pR}}W;KAsi!r@F>)pQygY>$$hjNh7Qfah+Jwzc+NEa=rHH zBD?wXZ%8fDR=b_Iee=yXVb+`Xeo*qSl8nE6YscH#i8+sdp3wRV8fg*V{`AK4ZQJ`w zuZGT$S#C4eFMs!|N5_vQ*{zm6ZhJ&^XN=z0TDAs9P*KI>09wTVsP1>qMb-RU)nRel z;?}?3Wft7I#P8>3_c^idqZKw`Tz^-uTIHv+)^>Gaaa{D? zn>liSLKOUrGndII7ldWa*}i>WaC=vo|2c`P7Pq*qiei3NHtkv$>&RfB0IFXTE4t8)Jb-!N3TEL73SBB zU%K(qyI&bvbycCEhTGC}rCv7DiWgl;_ zF|>i!AR6%S-^=PrxxK6G%=h1av$jU*P5*fQY+7;NuWQqsPG6~8@%q;hhF@RW^*j?x zqx1g!$X4gmoaP$@8n5=ZT=nNlQlZ_OE4L)9*o?!zuB~!Dt|`OUZgKEt&aw}Z3~k`~ zQl854rsXXe>uqm&p3RYdyR|byJ5K(;cW37AzkmLDvE-NO632pXIUE-;@hyHd ztN-EKS5IZ%8_zyFujs9cZ|ND$7VtUWm zGt-}cQ-0mD*I%tH4+c;AxN23^jhV}9RfLa=6^oRweOo5YE_wX(&;7S9{}Iyf=+;ZC z-xzUZ;&D;Ie5ES3260dYFVVILwA3)1VekF-?|0q4v3up~UD}RzQnlM$7i_+nv;Fqm zIL2Lf^VBDI?$C8hu$wP0yZ!R)kUyW7`|NmK=yaxt=l5p6ZJD#4IJ)X|F78*I)Tdf| zWA>Nd&zT)}Bv-HVgX8-rG#lC_ib^*)Tzc4VAgNDu}dO({cjyBj8+6Q>9D-V0#E?*oD zUM;ayyY zci-GMX^F`ysQ-7l@9`A5wWX_9-O4d@-|h3}`|n-r z?icvoe)}~~)Iq&ByJ}PL{fkO3EL!D{&n(yKFTXs29kM+2z=SEOGne=+FF*S9k>kFr zY5k8sT0DC_g{R7B=ALM_xzoSTlXlRbetO;ZSLanHmpA22KluInbJs^@3M`QJmVpX* zpWM0ypp|~rdrm6Yt8J3$Kfe0vs|>cick@=Ss@iU2_|mL6k6|v)r?qnGG5YK7tUIP3 zzx4b4^X8e8W%aN1vO`)+2M$~*y(?;S^m_di&!R?mvs{T@x0C08$!+U9{&@SW);-#; zvt{QS33}T8UMscgj@M>obRvHlA?)89c4(-o@XibXD`UZ~p!C`l0)88Kry%S^dwR9ME88o*drx z>Ti{BX{`OG^PYPiUgY`p`0?Yr^YotNPW0Dt^$)r$_wM%0ntcmnncp%VZ}Oby^i?aA z9X#m9<8$xww`X5>zF)a&)jF9Eet&u076%4h{`Gb7{VeB063w(5Ka@&;u6gaNoavgGgU-KO08+V`A4IhSeQkA;=&ZR>eC@287> zns;J3k89+#-FNdGBHyMMoh*;P^KT+gw>1O91#M8F|8S;{+DW^X(pc$5+N!mF?`~~h zxN23+^SwV_uD<%p*XqwR#xI>;PaB5CR_588ztuVYX-ci;D4>5(yQbe%-m5 zvyA!8)Jbz+znk^(=#i_XcTIQ3Z+to1r|=TT(ydWz`}&+?bUYdEo-g{e_`Kpeo~Miq za-em11~w=6WqB#&F9MGunB3YI&s%gmNtHhiv~JJj(TVaW*~cGd?C#t%x7>br=$34S z{392yivO;)+QPu#44Uzfn72q{693EjJ1nJlrp(`7%|3m(Nn*s>u=RguD84VPs}g>` zB>rsO{`YUE3bBJ04rLt?)bC4u{7@LOPQAhL)Z@U=3D>=~(&aB$|9H{XQpmHBEpEq6 zr+-tP9#OEnr?NAsYE&nuA7s{AQ_0GGUQEfEy zP1$ahf;)NJ|GrTu6gJ%BDg91(_rxQ!kNBvr4f!SGaQxtLsT0yo`xDa(7!nFV^?0+1 zRPUscqKy$9i`Gqf?_6=}TX}fa>hj5IC)VFBQaty1%CGx>5*_ZHuHJm}OU;*CrW5Sj zGuRcymK?KYaIgo}A#5vkPG8NsD(dmoKJxW`o82`&i{EaOESY2@$JZX7dt_qBg8zG8 zr(KUZazbV96!wj=>2sVwbLHD!>)iVCvo-r6W5YtwP!Lbhz37Df_qms>o4$qr-;W;^ zKKt*^IKGFWY;WBDCo#u8OHF6~tlnC_^-14pl}f+Q4MyLhW8WA`bstqa_vLf_(OVtA z8*ZgDEI1GHlXK|x(oNoRHP;1VHBUOoUuOF?-~Qp_5-Zwm-{f5d ze?Bjlv3TkJvC8$r+Y|HU9FBARxz(y%+44Yp^D#iTJ zjCbuzAMzVW^-fCsAIfv?zFHj zBz9wd&ENMIKG%IxdU5!n0Q+aAewj}zY&#$PkNe=MS{i;kgMlFr+>}YUpQ=Fgu$`>dK~-@l7xYWG&XepQk3TZ92J$|kXG4`dI@uc}J%zN1MW zH#qjmi`eT~&Ujj6`DLH>$&C7%nj@3^xGvS39P+F3l;>-oo;j13;X*p7^hwkPZIx27 zm1MbaUAq6c=iS1Z*AvgmJW5yPd~-inqfK?adH#95n_{2buhz$2_iUDuy~M~M=fJ?r z@PXxM{hcRkCr!F>H*fhFB{W{W8ygM4mi&#FFpJN@r=w^48NEPdwiJ zahAnyi{mMJw=SRmo^vP14CGICQ1Z0#1I>4?zyA7fUA=`&+3veVJLmYQg{NKkxhyv~ z?fW+7xX`QpVycE}hOE!iE-b#Nky$GA{-)S-yJveIv8(24JW62OC7Q@nB_K~+fRCQ{yeyKEb+@ZPGDDz-hH!%yxpO9 zQa10~W3gS=tUl$MJ^X_lEWSki)7;j&`dEXw6UkCT$tKZ?Sv%>#C>^r8Cc@ZC-y`<)7;P zt_|y6R~%l)Zft*#m!ScC0>GWv+m03c?>}dqef>|z65cNYn@>dZ{?0M;HhXQo-SXr` zzYF|*rjtGS58vwA@YZi~`OSYDd-|_69DluAZx{RY)y$Bg(*w1#zPkBB4&k9ww>0KO zKiW5Y3G?BjXFc5(U(DL-m2}_z*xy2flfk`r^UN2l<+$DGJL&I!_17=LS~lNYqrI?i z{r=~{k_-*UL50kn!078cZ@>LFb=N-MVxePub9djCm|XKj|8`rR(M*}z+s9S*8!rF+ z(-xI) zY!kkp-@ETn)q>{vDYL}+z5h&HviW#;@cZLD6_=ju%5^sEs9e8FYroGfKNUawm5lyr z|L00CW@fMfooe#{w92w-uivCoX3EhzV%O6Xb9o`Vg!W&3@SM3Qb#m9@-Gav&=HE{E z^~iLZ%*nd_@Bi=Fe%|lXI<@-g_Vs^nE-7@MmvOsM09t;OPki6-eedSCYoi!JgSMZ3 zw&gDH?^IiV@@fCH@b}+;uetGs40Z_&JwwRKmb@~tILKT2mfJG+_jNyHnEuLrF3ZqR463&B@+7i4>+ami$zo}nZyx>m=HiDh&(2HKg-%Odvvl@$$;t+^BmQ=(0>%|vLVmtrYh!-v z!^H3byz||>%uA{4^Ov9Vg>N}LpSncfjP>(RoA>oalj9Cl{_bc`y>N2RajQ4a_sqX! z`}oLdmAK+C!7tVCPI5AQ&;eym>D8;W^m}^W-_sQKkrJ-2tMgla*?eZx9*rMutcP+h z&0W4C_y6SGYV$VE*;VwR?B4Hdt;&7N*S+53eyVPN|MfXVPtrvl_a|CQF+fIT?*xHX z3LCxGDo9#W*0_YXB>L@dwbuEMKU(Pf>`QDc=&7`O9KZ1S-&YHgqb8@z)n+rxvK!Cz z`SfMyUG)!No=PQGKT>WlOLi;QVrXaw4Y1w`x@_Y4<>$|zJ7e_TPiGQ$6?{KG#NP}t5)@uorzd~J^ks|T+h;dZ=YY! z$N-g_9w0Bzw%nzCH*fpya_4)?GAETCD2?6!M`zAGhF@W# z%-*-R=KF1ngTlKFYo;EFljqtV{YrN2fn4tg?*-Y9?{}l{;rYGfIKP#(`<@wf zR>rIiJ84?6|J!Q@$bQf}Zj=6OJNbBLEURAdwA4u-k8Y3K_s5v+=aeuW^Bm^8S=$d; z->Tjf%V~ao!Q{<-^M5p`%e%9u8_hiO$vSG`o~X6!cKReG>^6EaW7e|F9D5Fi4+$V| zOJ{tS^O>~uZ(aTVz3lr>b8qBtKYTj80W{Yc_2Bo`#(z?ODpoJHx2=1Wwz;!&$HS@< z@-{Z*@`o(8Ez9iNrjZ$KA1{Bl-)-^D95H)6wMU=(Bfc407@E$?XJD`aEth!^^_DHe z^UaS3=QevXRUh84b$fB)7Qqkq!&YBio3{L|ON|%PzWeX_ zvFSe|J-5E(J$y~BE7*E98zxS9$ekara zpZ+W|?IlUpQ!Eb6?m2wF{bJEv!9-W9htZ1>%~{rADAh?VW`U4JHR z^U0J&Q6IicJo84y|yk= zN&Qi%!aw_qSrur;>yn?2Yk#=iGDltphJN)1wubU6Wt=a(j_-?FX6CEhc5drg^G{Oe zk0yP5kh1oz%bb?Ag=f}VDR0c!?Ps%ZUWwYw^Ut@>UG_)o_iu)>-LW!bi8r z`Sa)dUcOWMpDSe!MDp&qYRAm5#|9Kwa~Em&z8_M-hR@Z+0wQ6HT$KAu^ZYwI zbDtGgo%>hnvC-xI#qW{~4RL}F%m;33o-W!MGcRuGkB=V>=b!)j=*R68qm#4qbIfL^ zKi%_lTFLrbt&1~fEjf9t#L9P<%Ki75j(gH|K&vCdG7F@gx9?r(zvtH^UWwc4p4+W< zZ#!MglO_`<^Q6;%bDhljtgXBDy)|V3ZzFBk9t=7V!9v^k*8A_impi)lc^}%hzU$WW zwmp+is$_nyJ#4Ybp4+-|lTh}KRjc;6{Ho*Ux#jinYF24p*zLSPiFyOQ0~PHNr6<=s zmGwy48E5(Ug*CQ=8_T zO-uiplPg`=(fjYGzk93A!TWjJLql!vp|tvhmU_8!Hv#x<`85N98}BsyJWqyyCybt-E>R_Fo>|*%_Pv`l}UN z{6k}g1E90S4$Rg%y(x3n*Q&ku-}AR0)_i#>Z+mssid*cDKmN%0-21ZRR{I9Kmxlz! zx{sc=3C!rOpDg)PD_5@9%~QOOJ?H!lvw%L)O*eD&Ud;QW+>`hD#g4AWcf(eP{@MK6 zsV_KtcEukpzLmPgeYX$Q*!6GUwduys<7v%>`#vh$9AshuA1qf9A79${_~Vb&S2jM+ zRh_5jXaBP3LSN9H2a(nM|0a|_tZ=yT>xA*y+1B-IZ*McOnYnL=fL!s{qowAv&z`$G z=ff<8iv9QV|KF$){x9kL{jcMdwSDUM*7nYO?BjZ#0kVGK&-DxwFRLft5|j5n*8-iD zwx`l*eUDsX>La>pCZ1=epMJ{yr1|HwYC}!? zZDKvFb4&s=)ju9QE`Rw8lVM48ifpkU^S|$MoeT_nK&#?E*mr?;{d?BFI9w(2r68rx z?EZ_y?nxH&_Het`zuKxltz4=z|L+TvOM0JDwB#dM{{CHYOQLG`-ME|5zdr8VoF@&b zYCc@+x^kQEbcRXP+OW#$ozq{+*8B=u`P!__vi_*W$DcL- zzH>f1`lesM>7QMEVb0~3Tka}sInR1A_uZb`Z})l4`#YD3;lO>C3k-X@&4T~!dma~i z-S_gDe>2WM@6LY&>UQi=h!b0%Z}0ujZeq!tmnlX!-+%Y~@MZDJcc;5eCttbICb2HU z;IGVNoB6W8j!l~Wb!Xmor8m)nU%nsio-g-({tm&lVXGrz-+pVb?VR^GVcYH8J6ey$ zRy~nq0G+SWARaDqG{YpTc+S(Joi}sJcHezi@Z-m0R8i}df|WJiQrpLi!3i( zot>{t_fScWAjnj z1-Z^&p5=aI1RodEa6M4OH8iyQs8WBzyDuldye+eyfBrVt!ReBh_Uv?&j@efxSTZMe zPV&8)WP!IEKCis<{yX#ALxRt@#;w=aOFZ}6eY?MS)$Loqk9Tg7|Lw7jzxU#dzsLXd zZ@d5ZzV7?|yY6w%Wn|bfk3p&-{6d(myvqiZQFG3pDRq4Qm5{o+x_t$LUoJ9z*k)6vv3zp*!;VO~M>cA) zNso+rtPfvY{XS#$OvbI&{mpNNF%u_quf-Rnojzo9FnYZh!pRFyG5O zyA-O7W~v-aos%3Ix_;+-Jf&*IWt%8=TA2j&n2G;{8XZH?!}Q)Pis=xzARBZ zw|%u-%?{Uh3=BMT8Kf*8f3K0hvNS(?6KEGq>GE8*{1tas7wj-Bxy@er!gs>?(vs?3 zjHPKmcBM?JJMKK^xWxbHt0m9JHU1+urW=`wvfB$N)af!eU+T&$P`q zi+0B7h+TeZQukck`SX`l%b7l(&aL%K`1SE)A$YG#-uB!7HvUZh>;A{PMs=U)`p)os zS`YGWJ8$>3WHWzIX=C1z^G?Um{qs+onZF`zns3a0*S;tDQ^2pt`kjg4uVi_-tl_%Bw+ajL` z$g4d0Y_UdHwZBZn(%h%N`q0H`_iN?m+c@9P+rIwRYFWtGnS0&dcpb6&|7Ozho$NAh;c+UUyqDS1>y)kt# zN+tRGpuq=FYgOU0iSPCGkL2a$^>2QiIxqY3a~s89aqD(O=-iqnZXUBbSHf1R_tmbx z@AvbzPtR@q@$;u-y_sLS#>xP>{JlPcCD)s`zc1f!arxoBzez9E_GXvuzN;{=`$@FR zw&IfhoB7tM-#^dtO)C@l>&yV2Wm5QUYjgizZoyqA$z7MT=iA%aO*{RR`Bu!4-}R~& zbA7+C8kWR(edKHISoqlDbM>JM-a7tk8fCv^KI@fg`=p@wUUk#$w|aVk_EG=u-Trp} zf){_V(>{{vDoY%D2gcO@E>n8mg-JTR~3ch>z;|MUS#}{Sdju z>-V``V53J8&u=relYA|O?JplPGBbQoW4Yk4+-70M;bn}a+^H|z76-;n`w{x{$DMB+ zsgZtalb;qzPCvhs_2Nf&x!@hOy(&+nssz7iz7>yqyi9!ggem;>H8o%CQ~a+z{Cag? z?!=0^t;d4ihsu9gtoqPyBMZZU%^V9F{Yqoyb)VeH+g`W)DdVSQjQ6V}ebgq~J!y_N z{Iavwa^E*~nf~K{d8|J39V)ymks(-eyGD8cOWvyY2jxGpb6yV-uut3c=#iHlbKzf; zr?3BHPx(k5D(B0VymnpK>V2)-?yp{W z{_Tm4aqFvZOH^IBnL0gqRz45dEqbpLMMyINu0JG+z%Z{u&qnxC{d z_hTJ{6hlKgC^q(=mD9DzeR=5MUfH|CYkcQdNB6`}O9h>L{A-*u6sFV&&!^4YU;k3s6iA71{nWwkFPl#5nE|=WBb|zMX8ZyzMJpno$p%s{rBGztGA&oQ@%S$gdI(l$tu$O``*3q zY?jZv&$;Vv9cJe&ym8W9=~49d+7N-$k28#4Y~%YC*{|_wdCAAGH*=mfdoh5Qw7vM# zYWCCSefE}`rT^U)U#!|&w>QP$T(;Tlw`IF8CxcEacv^IGe$b1>yfVLL#+KcE{YmI| z_}TY;b`LsLZyjE4T_{>2``K13ZclWa*1s=2RSTxRVPF8QbN{e=GgHR?`$hbqGz`Q^*rg^yETfBp6HtwrCo75DXd_gwv`9_w&3NC4M@seS$aMmib<`DHm{C95^r5Z~5hWY&+bgf3FK$U0$(HOxR@h*|s2-xi+6W z)*ml_ZyWac=btItEOWhI?Cy(>`CVvm^2kjk35JGwV0+TkKhD>axf2~4`g2>9{?7x8 zbxtqKEZcoI@~y?Z8IJQO#eOqB+`IUc{S(2>A2zsg`J2o2PYzT0tJ!pJe$TO|9~u_? z$$0a7vF!1=^MsC8%jI%zid#R`o|)kSJ5$Dj&)@(2IsDS@)#=#j@te-ycs=Ci&}e)sHk-amcYo{vX@UhMEQpM7?7l#~44@Gl!2 zYkETMwr%`#?`@u0hti83A9e>_k7z7BY4eGzm(g;m`0?uu>%vyQPJS_?X~xQb!V;N7?pEKQ=GFBmAhU=0gSp zgM$+TZ^^%P)^q*Nb1k^dWRkmJXWiSUf6d?RJs+{Y?a`F1kEG^zr&SO`FpnnWE5cT{_y$I4!1vb%ZhH;^7lRx`m106`grql zK-YrL0-I$I*qK<@UCXtM~?*y!5?YA0uwKWc5|8f7|Bzs4ccX zm7lcbaZ#Un|Ma={imciW#UEh+&)mMaVsdsT=pe`M8{^ka`F_9R{HrTwPoma_EsvSx ze{#X&<43Q2+0S8>m+d*>`eeW3{!_}E>hc6jKKYoaz1u1M?&z()sl{Q|ee%rG%LVFf z^zKRgKP&(7eWAL|_HDm*Mo(g50G$)(u-s{U@=o^e&3(zIyBEx_F1EN8rs4Kg^RD-= zXBmQDg6&!b+^1dz%CC{PXf+&c}O>^iQ^92A>SKAUHHMR??+r@AkbGl3V_4bYGveOg+o~&HS9J zKlXn9q%6-NtJ@T}Hq4*1^7c8Q%7Z)peT`2#tFn4E?`!#(nE5pZN&D}A|FAOs_V&N` z3`_QWF5BHJy%T+WN|~x#uV6M(<)^_%eq<>IG<~n!(C*-=pnG^I4xURnC2!wmI8D07r+xUrcgX$peEAr4I}SsIpO>m4-c)b-@AkiZU+>{=?hTofevN?cJ|6^y)7fGk}-sSRK_r6YH8TFE8(TYza5Jxc<&{dV9~``nBf&D$q)m z$|a)HpVZjZN7T$0ceLMk)AdtgUs=JdWgEBDbue}&o;?26(Dj1*?|hyY&4Tf)7YonM zo9%ME`*Hu8>#tvyta>F0DKl=aKjkT9G5`GTO`P-7pBs5Hzc5oZaoKORRNOsgEq{09 z=OYI1_&48tllZ;;hhz6qCCQmztKJGr@9#?Ve6~?`7rV{X6StRt+4?8-1{L-pMuFQ*;Y z`HBBlHpAT6K5Fj9FWjfeT`!$mBGC8y@L{9-DaKdbr+wu6GO4H1Cd#Jn{oxMziC^wZ zd?{Y}sQ<_AA{)8mPQ4fVsvqQ-&HgX=UoO6L{qdtp-6KTxwl)`OHO27 z{_w=(-K~F%-p0?FVxKKsa&7BO8}E$&Ry&R-JmYtKJmHK20|QSJgVc*D;`_F)wV&MJ zx$kh~q_dCs+MBnQ?D})^LOAzab{qMwNbg_jceXOS@icvUF8wcdf_X@%_IJ6*GuO{Q zUQ)=&z_3oefz9ga!ozvnrF-2#r`4N;Y&{h@sp{(W+gWe!^-Wu|?KXqm1G!BRI+G6X z2wpsIn`~L!zZ}=Os%_et7yn)Dc)ZQtL~Y}1eTCdg28IL&mJ1HgGSp^-tl;FZh@CB= z=5Ia4D$ZbDrSXez&OG1kK<5n}?$~|Ywrj!XPtU90&;EX>UiOK0*5;dc3S5t}sJ8yG zOJrtXU{-2iGpY=4xtI|$Ej37Nd(_$`HglBTi|@Ic$9my;mteGxnCI;lv-Z8;56I~@ z?W=sLl`#jm^nlyB+H}_4pVqgHR zSanDJVDHFHt7QDAx#-iRwG%vzT z`u$`RzMy|Ke?J`K{hyIN{oBnaruG`^$`S6;bO_&jJG?vnw?NU}J@;4l-;Oul;F&*p zTgukVS=HN5o$OwaFTr)(>g4J9kJqJ!#we$0(U;HcWawuUb%Oym0zRDPtM?ufwIQ&+9p z^)K#6-PyRwg6h$eZru}OU|@4+;7#%CWc@thSDXC0=Uc<0!abx`XKaj!aJ_zFcaY68 z4y*pQ{7d@#?yCBKe_oyad(M+yi==h>`+h#}*Z%gqHZ(Mik%58Dg@IRwlWCH}^1m`A z|7MnNT|GyMf5Gjj>cu5zKODO{Ym0A%gW#8o&m^wbM?HFx*M4e#zQyd5>lViIo9StX z`kC#&Dk#SQUMQOaK87w<^KjZ`&C{QzT$k`HdiCPH?)}~m1r}SXyY79Jc;v1!@#)m> zT^2un*8H2Xmhb0t|Lo~stLCO(*!bj}?z;Tl)9!zDWMyCgO`1KZ5W661xMlt<`=_RE zlVao?vVT@h&bGX1{qEPYy~|JR4y>=Kxl&qtcD6cab5J~2o81)i>Vcqje3wj=fk@AIbZXHTcyZGE?E#j?wpoAy45+-or@?!()) z4>mnzWMHtF&LCx>bd&!TXi#jXOs|`JJagxg`lc%{+mci!zrAZV`|Mu(^%u&r&RI9c z2sD}dPEJ{HD((F$ozq8?3Qd~(TFqyl{lxYC$zhZJ$oUKm2W&xk=2O8=UEj0u%C=9Y zq^dR4HEhxeUwyS$+b91Xr;1*bf@Rq#{Z-)xwA4bfDT8H0R>9&)$`}imu0U{Vc%Kdd)cII;vHM27ZEc< zLyvx%eKzgm`E|Rz!@u-1Jz+mmQyQy2u~6pT%i{vYyCQVv-M%qv{pyOnaq?#u+%A(b z%)YOGa*t)j@A9*$(jiO?4F2j3Y<(VfVt>I0SKVT;;#^sqH!FBrDV!M0JPv_`I zdC&A2-*$G`*)TAGw%_--+9$1pS+(h5igkhw|EWr z=c>K?%2#II5lHfzT*tj!-ucq@g?BFn+;aXV|0j%L@DXKAmDjp;8B zW2^OAxaGMU1A{>ZQwG>g{BQEN-!^OTyH#S75N&*J?&WQHd#|?NJUKsc%iK7>`t27p zu88K@EjwQLU)&+6;m-^`nUDWI|Fn6@Qgo_$bxQY@Z|_omA58C@*niqgv&eqpyYmbT zADCD!94Pd?T=LZA_uo1bskxVy9X9yp=;LxG+~-Bo#)$RTXP;F|OShW4ZSs#h%)1{7 zc@=r?PTF?tap9%b$A;H)?r}buvXJFq`~|mb`u8v}B)nj`u%~Z* zmtW`Mv!HW9r#uIp%=K8}^V6c6qCxfxmg=a-DTjt0^*Oqx);H{SbLrNoqub|Iyq$CD z<VDUTy>CnAI<3jN&HpWN=G9W!>+e(F zTHNx}Sr-PWuJu1@=l$us6;`tC>6~1Ztdu;}W1kBwN=hShn@>wGYrm5(w_9rSG4c7) znKR0(ZoVx`*Ij5cYl}kkNp8pn%4XMiPNf;^p5S=cqCpRw!TxP zU*MCv00YB;0FDKft?_xwFTc#&{`*gVe}Dhis=s%N&WRgK_3pBBlVy&(zLlX$ApBI0 znYYn`8T)MB@7^Ba5$mnN_j^s#9h-A`zmG)-oorrud`sg$^|ycjeyv&k`n=lwGdmI< zd%dgu-}$r4`b=l+!sOIrJioe`85rW48D<^qzMuJDuPNJn-( z!GE{>=`k@gUVpXf2Mq%y&#Px(VCYwDNW1Y!{L0Uof3MeX`slj<;5`G=7hJ1u_3f(E z54TZrx=!x6 znEA9N|J&Fn)c)gMy0$HE_QiVf%d+v;ze_SO#Pu-DI{07i_SMT_Y=zFQfhxbJ9^IZa z=d-wn@I1R_&^Scx0XsXpSG(%2J)QGLM&fw=HLX*pt8GOxRdW~I{_85g&0_L7gUvVJ zytkifziz|%CklC98xJJ09!t^v-_beGN6m2aGd`F#Y_mn~ZTrjeN2_{r;W_IZ(0=%= zBim%VA}iL}^u9e=BU^i}@SR=D$wgP$c1_)GTX|z~#}et%@X)$ThI?{-@{8ENd_OI| zn2~`&-;?3&gZe^Wtsl3n+zl`L9ObX0m zzUy@>-eyyv=kLgAPZpl&XVaOd$H2hA)4?$7AZV@O{|nnX{C`#MP4V9Tw=O>PD(`Id zg8rA*OaC9cyu0AeHf0x~-Pz1{Pg!f)Z>sbwYX7-A^;Cw*t6dMb=$mb3U|{&G*pT+2 z&un|F-t<{}<3O7abk?8M{vF_cGWEJg{X9vT*tGP$(f2Bz+?gl0ewW#=4g3%7>y4hK zY)T5PSs&qlty7whfx+QE$AU`M#~&;9-!E4c&#he-xa+wckR0U)+Ec~R_yacXAyUy&$G9b{(JRgvi#@%6;ccg4aY%ty<2vb;gTzin|uP zJ!zU`HL1=kcm2=$zTB{vJDH%46RbS)ZB5a+@JZjhdh=E13LmLCUmC{z;(4B|qOp zdCr%vx1NHk_5Lycem1DQt*udgdGQ_B^L0x%=}f-+3X~CZt3Um)PLI7F%g=M`XV+ri zZQ55purn|$Xa|*IPnw^c*Lq%~TG@W>Z{2*B3wDD4T`FHz`NRYj{F-u4^JHtyLB*}P z3;N4SD?W=}3Js89{`bJf{C=0gv}~RJKWek4&ffxNzL&R8*c(1c>ErQoP0L-Pi8bbx z3pU-%xs%Jl!0^kB;q2=Z(Y!Kz?4FmWek$7)tGxgA+Y-wc&)01AEuGwS`Ny@#&-L_g z?t3s{k|2kj^hEXxn{U23__%n>!un4&hjN&}lU1{(8_o2Y)bi!dEzi0W-od+>UMz2! zQFHS3wbiRm$=|lwx6tvQ%F8A>?u~yYO}NXq^yCklr`syGEUdqjbu!qEfuTW8$l-I) zCq0=-7qp-L-dP&C{(9Tr$WLu-yYK4h&D>M@tHi4IPvZTu={wCXzKfdQe)!?pa*eah zFP2{sdCsjc(@S*7Ts)G)sJnitop-#pMQ%cduG?PRn}=*VnRr`}}?H zElk=PWxJHS;QG0W>858-{Px;k{QE&2+l5N$Y4g5xF*1PnsmBF`hI+o7W4G|SM6X-= zR8=`X_LUceL8Dg=_48+yeLolHT3zVz`RAWDU*k`*UiW``dPYu*jr?C+y~EtM_}6pY zHx3*O;K8G~fS?P@1K$1G=?g}%x1wJ&ek{IhM5xXD?Mdj@;n z=FQy8yTHHx&etPepd{HR1M8Loz(W=qu=un)1_oGXB1F{l&n*Fvp4E zY_^wONZn1ov@M_3@!5&r-@aO5WzOG;n$Nes^}pHvVg8o(uc;e6 zwEWK1mycd9tf^DK9>K}LkRZTvVb8KXR|@yv*PgyRBKG=n_6z5A=hqZ_a^Ky*Ty1~K zw%c!mC*8DYU6Of>)qm2XubvBb-hO-R@ki-(lh+0Od&%4FSM%uUWN?;OYj~FWbn9f_ z%My!DhlG}%YJar#cHOQef@kjs2aC8~vaH>I-+t+#Ejp){^p?)KyYuVLT?KPWU5{U% zKktOP>ubAAMg|504yKH_YoMJ82EQ*dOuwx9byEHF=KKi%Tk@V8e!RY-^0#ch#nhjZ zmvB!yZgZjLu(k7LliKPJAMRe%li6qkiPm(cjJPn+E d7pi%3E{QJWua(YFz4&(h z!K66DziZZ+7KWUx>dv2At@yk#OXWVQ{~-flt1if{<46Z0ld*-&ze0;4^-D( z`=|El?yI^tG3pKPp8vZ4wyfUY_mc6i&gtxiz{Ydk}4H4T7Db*J`dY=EPT?8_np5zpZOZ=ad=LS zdS6~$U?kN$$+KVeO1t-t+F75nE&o^T4g1H#z;L0MDI@M?hKZM5cKyNj??0bMWWMe9 z3S#^syj-)=Z$sSrdfo-Q*G+$(HnH+@&*6s!dDRmvCN8l*U$?(LZ2!dLr{`b#x?IBM zn!}m{?KsTd|($lB?DA{$0(wy7fo>S}DI> zhBkZW+1}L9pHrRV{`>Qh@??{HiZ^}OzBQ%%UzgJ871K9#?BUHOqwC42LFy~B1=|6RnFob-$>_%reOHfFzF4BJglKiAu~YSk{Oxb5=& zGyInOUOsXIb~XFlyj$s;S&G83{l-@MVd zVZQeM)$`rt-2dI$`Z)1Z^6munT^7@qaJ%n$_^{x{`|r6+->$x=`stq9`MHG*3=DB? z46{HBc5=)vw?5wX>CP#>7TcMNi_1m!B-}sbe#-uAL7w+_;pmy$=V~NH#2Iz@+MT*E zUzURr(z;%+e=}8EXS%oI>77YOlJ4}qbI4dQFT+HtbnA>4v*!NEJbRh>#gdgCzYSjA zQ3cHe>B-m|y@*%-y)gc0rE(7cb5O<1$!M}(|NPo5TKgQLwPv%I?Y*_{4R5d8;&spU zUyv*LG?bVmP zP}^(Ws#i_+Ukxg!zxwg3Xs3;~nQZ@Y_wASe{9c~3{dUBE!?44>8J|Br-{!ren}dO& zVYYz7XEC?Mftxbt72PeCeapCZ^S8@aOKTl)R;$0CzBqM` z%a)IuADusDaeM<$_SWrp=TA;k`<2hYz);}KlyUFSMLiiQvH7VcQcp`4Grd^uJprT~xAwobeP(izqo^eV1L#(+J>8phCeJw87rk7&D`{iIlj!Yl z%XZss$$nw=&tluM%tt!YPCwm{74C0;TqWfU^NV$C;(s|8Jbv)`-_dkif2&m6`Jn=` z$Hi8!-YzZbr#5*>dnc%b0A1jFc6Uaynrl61O2l2;jlbR5zWT&5qmIrvz3GOJW{_2&GYJ?s9wEZ(vdg$#Xp-nR#ETX`f)HY z95~Clpi5$-CVhPTBl(;8?6cZW^WNU8ie)Sb zdT&34!RmgP3E$StS(o*nOY}auyH3!36X;OqP?__^-?e(=ZRPrtUrmmB&ux{#%)kJ; z%Iw~W3LC#|=c3n!O`5*g?@joH+YbBJy^d$TcKG23ui68TU6O3$H(dG5VCA;n{`m}( zoq5jRHg_%fT;Bb(FtxvLfA%8zoi`pGKYAy3`|UqE=W^%sGB7YK7jXFOc50JP(9U~h zy)UK)|H|J|c)Mulo9KD7OWf)59>daZoR4j++H1i>~>tdz}NMXUDslJOxyK)O*xm}(yYa1aVs8W^1H%q>Mw9odFAXl7KeHt~sbJE% zL-udVcJJd&3wru1$@hSM->uIKyYg%ICOb_&{qv5}i#_gtt}obXdi3M`jfd9jcjVpQ zlPfCweg4lHx%R-&(AnQ~&>k zy`5K=8{aou#HF5p@nha(u}2BlUVly6*fIaovP&O@-Tw;)-}&cVW4KRxeWvsCACI5Q z`TSWkBl4^{s5}#9G|5+gdFbQEj|;i8rb|q#S-kDv^QoSluj}^PXP@6SPy6&HZSP)5 zpKZ}HVGMuIbGlww9)IyC+wA?o~eAN^g34sLXs(&+WGocAZ_e|499|&d*2f zt?sGx-S_2Z0Pke_T=vQ6-qoz7+{f2{s(pKo*GgWW|3dW*gD0m>zKVKMxp|^Z!@I8VZI4j7ln#n)Uxu@{HBTG8KXh^XF+p3y znLd+p-i4ojx+$EoWK;UxvfZ`w8LV#R6q`tuo-NAXJ>^ONlyg-ALd)-8-Sy;%m~C!$ z-^-F+aqAy{-RryP@qtG^rS}*Z7#=XPT-Y;rkC0ja^Lv#S#JZ2}RJ@+H`KAA=-(id; zaVKJ~mtL3m`IgyZf8%_*@p2Kz`4V%VcR%?uS8M+_=AQEC_19}xclK=+RR82<3v%NN zV@8wr8tpooefqYieD_>EnfqHsmsM^s?Z|!o$(Q54 zdV`*2!dlB2?{vx)_4B#yh_X6X1 zW>4?fw{XuN%eK|4GoA1Mn(3o9S*4+FX&;OD_M&sfzwGz}Wp0=4_7%EuG^y~BahpWT z67J(Kk6wv2pI>(T&=1W*kHRyC!G_Pw*Z2JUqnwtzH|}`qiid0r3=HR$8lL%vhE6@Q ztox|b+=SN|KZ~Q!RW9H1?%8C!BcJYZt1y<-*lK>rpOv;C*6Y@CFVD!2b^Gl%%Gsaa zl>dXX)8g5W$c;M5Hy+R19Jl`Q+5Mkha4Wt1=6}@s$VdI@rzIv-d=A%o%g(@%(7|$H z&&rD#TW;pCZLGdmtm^qU+`fIu{F7N*U->i4eY4?v662TDbgM75QvG6%$FppnihPRY zO+IVxTYNh-_K)CkvE>5A;@7W~SoJ1%F!xno%-eqZ{r6mhzuOPXf1I_0=W+j$jYmyy zZ@cwDgcsD<6L9#vtS`-HdTCXyA^0|wJ%23YCikSQ4?4Za@Tj)wzkNCS2mdU3@jrOx zV%H0W@6^k#gSLeiPZw@}qkVp9?~>?T1KCIWOnxf+E%`hBhgXeloPhph3uXp}3!r*2 z{F300&!3CUX7By^19XxK%RjC9y!dNVqn`1~%e{HD_9xr(O=-%8Q%`Xs-TyY(=g7^qVXL1UJXy8Z?&-}So%idG zi}t@f#K^$Fu-=j3Y_xaLuIe09GlkGl)u#^=H%8R(`bAFj+~4#syl}|RQ%xCsZB9!!#sa} z?*H^*+q6CZe+%q$>+W3qNM{mgxlF0AdkkOf&fGn>8=|IcnVqi2U9tIQ$G{C{yk7M3xID zueE;snpnC76q}oun%UX?QuDlAkoySKS9M{^xECdN^=lUM-ge1ex7b>(eOj~r^G%r? z`~KJF{qa8EYwX_7dN=)~@aNFEB1_`0S?-$uNM`b?KV>p~^8)`Jc~oGr=iy&aFr8Cv zcy{+`E_>Wc{STU-I=1;vu77JY!NmCGdAk1_OYLX&w_b~C+L+-$tVpZQ7c8GoH7 zKc}DOd+Zq)7(iDJ?b%(!yjQsT=)RtlDU(d@XZ#NNW2NxZU|rbic`3U+=SisllPaz) zWcZu(^r8FwWpgI2>OcPY2{YsSGSG-=12@Nl%JNFDugTl@UN@8K-SzFoZ>ipO^O)b- zwOrp~UC|SsRa|p((z~unkNs8uUU(estn>Bkk_9PV>C^Mw6F))-uncUGq|QpWIed_`&vNXzkL|OfQzS+1|_A7{T*V>qPfKf1Rej z*131&t1iWX3Xdvp2HyXAlYOd=@@@I{S*Nh6G`3uIbNs=l_pABq!b3wZ`R>k~Wj7}? za$2nFMtxzmZC782vs{P`Ke)hMO)U44%(E#h<>lqqU!1wn8`S;O$_y6pdwF0&`tFZw?NWBTSBLI*W0<=| z_uZ@x@ppZ;QoWOuUKDKES8X&?CDx+qQvoYzpv#ki_y4r*{Sq0>cY{nMztFf&MlRsy*GOe~Z>$^?EzpcwF z_eI{%+b&&|SP`@TB&*yft!I0<-ES{A7AwNQz)+{!&{ltXb$PsL!m3qT`Mwvz>gUVZ z^&Nk_&SJN{^vzzk#sB1=OzpOOx$=^zgZj*`+;28t&)Zz-D_HXBcy$JgS{``YE^0zirol z9(BD?Dc*NBZ811sf^H!FpKc=cwruyj_T}a_H-$GT(Ylo_zGbmw)`Eb{}`^2G9nR%ZZ=_1Uk{LU^LO0es`5L?!UV<^;iE`w@T~fhC7od=$(vytk7CW`j2~x_wBJN5_t4u`Q^;;Z@=~~e0y|ea^$p= z$J%Ufp4017d}(3$rSlx~i~Z-{W%y4D&$7Fmw|&NU+xMp?-fr|d^m@9cC_4i~gS3#t z;rgeyFXwK*?HF#c?XO|qvh#(ru9s{+d-=?~5~IxRFJD)B)txnZSH<=rn_;f`vWkuG zp8x-&dC7lW)1IF``$Au4zq!W2z`(FwwV~~Q7I(|!+GB0EWi9;Hu6w;?-*0V&zUi@& zi@xrk>^bK_j#>59Wx~(dF8t(cS%3YO#rtpf?3!Qhx|FT?+>^m=FIch&u9MQBeR$7{KqocPwj7J!NlpC;)0p~l~gkPEnhHa{m<(ewg0{g zy?qt(Z>v}R+TZ86|3H$@e$E9C>!1AY;oT_f2)elMNye`~;0=8FMP-%V?ek1_fR3k0 z>twFI^uhFBIxFZH!=n!lul;piziSDL-G2>-7++8Je(@I~pkN34Z(_a8es$fR^Hy_D zrc82qb>G`A|LVhE8O_~xDYGi~zjrjZ^OIZjXYN}0yNv}GYR?OMKAu=(erON(aqfNz z1_p*0HwIpNQ{TxZ=@J3%O~TppZ=b!KH+$AoUcIVIY`gx?R*ieMhT&Ih^N+>LE@xiX z@-0(7Gk^UHaGht*vEbqIJ@#*kcFG)af8)Qt_T8#4d)(sUZcR2kW9}`J*HaP3@Hfv| z;9ta2Pu=28D-$l6MvLR~@ziK|Hm)*rcvZ)c0I1 z+Igm2`A@Y#2{>0@=3MYl{G|Jv|9MFlwAHWKZBIQ>-Yfpu@Q+-xUE!KfW*3-ym~p1a#*jF$>09vN-Hx11L%&2B?Exa`o7^&AcVE?bL6p*RgizzWuy+^U*!LCH}_>Y~;SzZ$472%J`*! z+quanRZiZI-^cjnd+LPuZad=E*V`1II{p0j{S}~wfSelx@BZvr%d}^|PTW-z_O@8& zPjb;!iNpW4H~Lity!rlH@!H0D5sY))R~S0#-)H#s`>F8ZNpIY4uzj~*H){#EyTm)S zX`tYaX3F?+x57rwOZtVGopsdjKQqor-~DdcwXEBDYg0;q;@^YT~Hl#PvW=$d!^uHAQTMJ*!#^z>f3N-ac6MzMziR&$`BqKZ(*4kV*&OqW z*T6CMPtd`6`nL71lP=iqb$(Z26Q?)bGw$1+FF#*Md|Sd>BJ(82ta_=2Stjqt&||+R zon4<_W4`lX=|cg?Zab7R(DKfm^hoQw2}J@>!Y?UxS|@3U!`cmDaurkdAB*V|pp*NEqND?Io8 zYel_dOSs+Fmua(tCiMgyoR{xu{TO`9Vf)3zpxwWeYwN0tZcXd>w&$wzz1HM{#vGxA z+ZaoFDldJrQhWOHZR$MjlT&W5)48AgRN~B%Z1_%)d(HNQ7#vh1u-04M|5*qL0q#IGQAwJn#GciqB_E z@+aJV=k}xY?eqQ!xti&q+EY%*!Fk!LRZl*D<=5`f?MgD5Ip@X~OTLPY5ns~3Z&taT z%Ux7`sa5%;O#4>RL^;q2VG^I8OgvCxb=6eq{EOQ%|FxH$-(4W#&%nTNZw`Z$(aGnp zZ|l5gyciTY&G)j3{OA9Hg_g6=R)rp%^ z+@1Dr-lq7c{hPb(Rn`9*PP+Wkq>@kMepdFe&%Qd3Q*HM&6ZZ1 z^tP_~_SyMXa889+1RQNMxSUk$8sG593ug+`F`J$aR8$Vd~rEk9ZW!uZo_a6o9Zn_(1 zdQ!I6%~Lb`w%@}4o%NSWtZ&u@{QSILJnf&)qt%6Fm(rhA`+-K`-n%jI9#<{A_x1NS zQCCB$-n7j(L0#}H)4CT~Tc!GsGkftomf3AJ^NZGBo24AP{#$d^UIPm@(c_Nay|^a$DdZeh`r3V>+Q~sH*@^*XB1e-q;0ergsXK4xv`<~(SQ=>|+E8m*@&2+AUinRt%!{Bk(q8aC(dwzWvnY-Y2 z+4+xcAKA}q)%4jLy)e4Ehqq+?E9c}npAQu7zWc3G@6nA(U3d4NKl-hC`I>u+T`#0Y zs%`zes{k}yKab@?!K6LBUplYu&fWdIxH|8McKPnRC04RkKU3!XF54}8>RDaogNoGG zQ>(it`gj#?ZQGIKA>Qp8$8tCBF4%|z(Ww1A|e^I$NZvIy5I}2{-{judZ zsh4ZGXYZ=Rwo(?`b_;$hj(hZA@|yUcpHo+@@=E#}p;g%UJl5itpRAh@14F}hrG~c2 zPde{qZGFY1q~AC1woh5dZ(g+|nO#bE&Gx^(dhuCf^6jhJ=fBLow>8H1-Odi@ij|7xa5tb5`Z@>@VP^ZMn_=X61pAwS4h^IZRFXYAi zH}7#eZ`J;TdO!7YZSUOF?^D-T&66(tQm|9)uHU}*v(P zopga)Mz^U?bY4xA(zQ#S)zg?57!G6$I2>N-wm9&T;11qCP{_=aUcd2Xg5LR$)i)MA zc#+p)n{#Aheycj$-eVV!>AY2!fV6t1F-ZAM-QIuW{rB5%zcs!1x%&Ar?Od}NCuT<- z*8)S5w=AD0DDc)zk^9Cr}%QKqHd6)6~I`^XI zck{&G|2$-CUMG9(XU#p+9(j5B`@1v0Kc6vs*-7a_@X3+$?fRF?WbxGTN6+QS=6&vZ zp)huR*y=>xB4`J8&MKYL(X1Cfs{Q_3XE%R;=$AjKMl*TVIUdwZJ-YkuyO+KpeP;Is z9PYcsosd`F6Qc)dQrELwDCk@36`tKbX{bf0O zD*xMKPn&YLPayqQvqi*6mS=>>5d-pv(umda^O=QfadM8!6UHrWB(U-|t zkL=#}Pk*!Ehi!C?7u(%+mx8sv+>RAyy>OksB93Kljd`A0*9A}n3WG|lDa&>(dR~0B zbgqfUi(H#qX8&z}X*~K^dSUTJ4Ys#m(p6SpJr%U)UGfafcYR%>P+i$c!o^Sux*-z8t-rF+%+mkv)cig$TNtGOK}8+|XmRE3w=U;nKk3QX<_BCbYqnEu&YSgY-DdgxxX`OYqpl2h-%`!qTp^XJ zwafG34W`aKc=*`{P%B5ym4SEuiA`%>@A}Q0aq;t9C0&_=v$(nJlJ5KSA2#uQsG`zU zb@(zzwgu1O@XOC{3u~Xgr1)p&hMgZ*Ybx(v3@(=bGclUftXs9pI(gp*YC6we>{O6c`$UkbMb$IFi`}%92tA%Y^_qzJog2Ve&|J+!t zweWEBl+>TSQ4)XoJ8P_1a>YSyHhp1-!?Ag5xnr--^;;e-v{yt+w%`5n`Esq(MYEPI zo%-f?-Ba76^2Hav`y8*2asN5lUc9b$`|aMx73br5mX~B!9$w$B{&<0%R}F{Nr*kc0 zpl;2*c??qf6i#olIiFvCLATZGu)&XrzjGfgUOfGD>R(gA@82E&+j0H9n($Z5_WrRC z?{jMAEnE3|*HU%0Uo}5G-~Ik4?R?>}h1O#>28IWFITt)Uy-DZx+cIy<2R7$RW22YO zU!U@$>c_iZ&X=OuYOUtJ>uEd8`SQ1&%p{xh_J6O}x}1Oh`R6~$+nKWtU22W*S+eLM zC-(w*jhq+eZ3_;sZ#lbFkb!|=k0GN;jeG3%Q@nDER;@bWTlG5s;g5pZ-TRH3_o?Sk{#|Yf@CU?T*ot*3!`EdQ@Ohlgaa~YVW;Sv-J1(fXv+Y zW9glr-!hh8Ub$-3?ceer89#qeFF9%x_M}!*7c?O8Cmm$kCLL?J{)sN0Tgv}?9gDWO zwe9W&d-e05Kb-G8Q?lIne6hvk)X0B!wel}pXDsu4_w&QyKfQ`C&dP%F@ed(JlbYb$ z+q^fvH1W+^@IHK6>Ymo*=vuYPdFH;wcJudJ?f)a3$XLGn?*8ZR4&Tx{`$S9I|6#TB zh2xI{GeJ$R_g)OV_d`NMm#|d{Z-2hlW#04UmtWdOS>zqM*8aT4Ms9zh_FZ$f`M>x5 zUvc+`bD)U#!+*ISu4&f(xYl0#|5Y`Aw9OMx^`H)NMxe+lk_I57*8>M&Ud(ZzDo3HoX%yUtATRx9tdu~xNXc=9; zCj;+&k@>ghE?c=uYjw$T|7Z)dy)(AE^{sn-$o@&Y;TPR1I~hLjxzhjtU7lzV@?xgP zAKt0k!S3GR!oYi9d}l$d^{|(9xwrLP zmqzdJ`f%>?m&0p*uJ2kDq1DB?`mRZD^K_5MX%qcDGC*Sl5A2;7cEajftnT?M zHM$Zd&a~Tw&3o=`m|?MK_uX@XzE7l`FGTGGRSNb@89yd2(m410bI=@-eM?&(*M02# z!e=X<6{J)F-y0^0Ps?Xukskuf33bk;#_dp{{{0>+*tE|J|!B zm8r#lU&ui{_RrrsdCh4bLEUhMe18UB`>Q5rgASBvmu_|WetOfJ0t=UC&ZT1Y`JU77 zDO=7zZzVtJ*DHaN9}hohUjt3+Y*%b(o3GWSRCM*m%MzgvwVtupCpyG)9}hp;?R)5A zsoney|Gx7(w$IPGeN7S6fyo68?SONkcj2X{MTX~psD3>6Xv39FJJ)ydytJP0FOc8$ z|Fz=xbqt^etTO{I{{@q?ms&D^{L0%tdFDO+pxM&#~U~U;84BHRsLGJ-;Navc1|U^_RcJrFf|(zV+&0 zZJ>ck_Ky3X&CVBJHVJ#_{mF*E``Y)v7JbuCKdrHQ|GnDs-*)lOC04F#UsC7#3;4Y^ z;3;RjunQc8(o7i@JsxNCE|kvgdB6Hlm#Ayt|Db70r6$i`^W-^(GPQ$rtx&RQ0!rEu-rhcn@whaVO^7bvN?xZ?G#MT`s#8%minDrW3j zH{HlCeDBAoiCr@aGFa!HzteI0X;C_N`zvsoZeWm-Q>!}}asT@!mAIuET}$tLuG+gT zH@kD5^1b7K-&f_m)nH&?$e9aLCZ`*#Cmt!Ze$w-wmv$?w<<4KT?)8b*rEQl%>DHJj zqhiUn-04gi#mn{tOiNvU`DDdEsV9|kVt>x9=GY6GJ3nxZbHT%jO0Mh&KUSRid`IhJ z&Bxd8&pqEf`KQlBYsLQtJk9=o3=9k#GC@Y^oL1W0``BVyYUb36lPB-I|L)CLVlgx5 zT>7ccHbxWvxpTW;HVNZlU}$(N&oo$N_kZ_OD(^5O}h2Jzb84t zl|#;S1}V8Ut5z))>wEoG%llEQdhyG5yDR4%F4w(i{Is&pZvK1D1+_&?3=9pv!VZU< zkJ`tqzc@9#Q)J5P%8JetbC>@A_oT%flmKsNFq+sz?8zyg_k7p7wL<5oKmTdK3sitUMC9!L&9Q~3m+;bu4{h%^;YTJCH>F4OYB;bD=lPXPCxGsIhGAB z8EiQgJpB0R?Ybz7imMyn{I)Yn)^4cV_aVrj@9}cRFJG%l>p_LGv}!}!@zbF8)6#>- zGG}cm_%I1%(6qj%KWoB1eVF9iY4YvQyArFL3JeSk+dLR}J+GA7p8tHw;Bno4^W0OD zk8VDfDDh;re&DpHm!3|j-%}VGI`t_N14BYF%Y_Lpk<%u=KFVYKsU~vT*4*794)J>8 zXARchntu3Ufj@UU#Lr5MCMpwCZ+@)k*;240sONb%&ok@E`XW2Gh1A+GFfc@`H?)P! zS{BK*;PCbG-E&nRojkQEhRf=C<+TqVv?}Mx_aFCXezC#*Vd&8!P_ooz%J5jK(dDsq zwHRMmsaoso^`Y0l+JfrQi?2a56t|Tc+CuVlWhQDLeYI7;cC$ny6ga_BQD0yRTJmclq5r4vEa^d`})06ez^6$eiWhz97~W zv?k~o#{$KLn{=kL`Q?Xq?fll8-qnAzE#K2DeuYNY<(FSx3T*iX$`IRJ8F)GGz7vby z)m1PreJQ(5utiSnbzRvLpMUDytaju!=6pWK-CY6<3=L}q9Gr_Hr^)iQpO~5y8XCED`_0!= z&u@NSx$g>R@!q(p-0K}9r%k*k_ZBo}oYT!9HE-d%*Gnh5t-LSIaeMmn%FxiW`VZ~H ztmjJ2i@5*Y+ug9{bYRTk!mcmhYI3eUEZ7jqz`(F(K7-UeMWeE+?1u$QZ%w1t5!)J|9E*dN30Yl1H*w|oC_XGZqj+ZD^K(5 z=geQe+Mw3npTf=epBCMG|6QA>`0?efk1eNT%U_yny@|SUb3fl|zQY^NeHT@7|5&tB;#hp=kEcu5DS`5zHp_(%Dj&O#9@<_r ztFAk5^V|Bf#fQbe|NhH$KYYciEX@YK_;S8*rSqR3f0U4Knz!tv=rWM6<}gUjQ~5XZ z*N3m$a(Ny1-`qCOZ@K8Z%*bi=B5i-<9I~4u`!|SxRD4nJ;o46%&=7fzfWzU>F01&P z_Pwv2Rag9I>Z#W`TR8kPHLva2E0`1=uCzy?WqNA`_i+QBs9**Lh6rOu6C3||&!2y` zELu9l|8jodliJo&K9Tm~9aq?r7nS86`WYz|{{M!N^J|cMW->_4%i4b1)hl-Qy2*cY z{gzxzntR>b?H)&={Igqkj9F@Jk$7#LQoHnc78+9J>L*y5MT-)BeIZy(-%ZQJt5 zX|6_RKj>yYTXkf0bzZpOE-TQ0$Wc_eVZLj*ck|oJCTrI!D%KS~ z`dM?$b)QzEwcqmK8jh;%w-t%Fhp-ZlOEwSqSZ>DavxN2|Q^=oT{_FEK6 zu&Ed1-rCm7?|9pkfq@~+n}PSd*!=W8F?#Ei?#x-FF>T$~-L1{5vmTz9`m6W86JlUs_~*{RdwzOqK$U zuvO6EFn7(ZLmRgpW2@V-JbQQCCXKG8k~PQkw;o#8`&dG#ytfUsv1X^l??;WpEr$W{`?gKE26<`?!fOC^w#c zn|Zx-qT-80iLgtTWl2iNeb{5aslb=`C za8#+@mXbUm?yx>4_WEZVc+qh9^pi?C$+S7oD^)LVs`0Ghu(FWh)7SseXMUh1-?AdR z?ry{?|3XpFq8V+KhPLS^H?7H><+1qn&zd;TRD<|i*Z$VYOE&RY-`n;!Tliiy!`?3{ ztQWMm-+rsao-;3<_Y)}Dwlhe@t<>l`Ver_**Y|S7QuEu_Zs)eF*L}1jl#_eG_UZ$A z)4iWGl*Xn{1!W0NMw304mS5gfd;hn|U$O05GiOx#|pGv8lck%cTP|K%o1gdO-v0h4+gGhp zw~=K0V$GSJCec>kZ{MzO_uPV!fx)4LLF(Gm%Ze|y<@TE7g+xw!{`qJ9V!!2=h4oZK z9QIG%FgrA~b+YmK&tIp1a1t~#+%uzMEvQ5Dl;y$(z3u#0+@GbKe_k9YB9;Ym)U0Pk zJNNu?I`qM3*E(T`{gXdz67UPZaqaNK4Y%K}S~baznSo&g8&gKa+#dp8Cg-nyyz!IG z{rBHL8ol^%_k*$L_6UZ*>o(O#a4|42ggG(ruKt`E`N4pvZNdGD`uP{OE^1DS47<+x(dGVxT_$ zW;uq3PJOgKJyLAuAu-V6a)y4ThPJ7zR%OW?_i%N-Y!a5aJ5OB5?bJT|O%FEd1poQE z@BQ?D89%1|tO9vfk>$dMppV&)dRFc`F801`_m9?=hYVk8|9{B*UQl%CXXLN$R zFm=q2y>ZY(_OrVN=u9~YuIH8ezT7)@_`evaD-o~O&=$J-wN;RC4#zLsDXBX{IzA@O zdww_X`wGh!6%2Q`t@Q;hyOINi)wJi8_rH5T-uT%j+q;7QSy#U9>)p_wds~lJtzP2z#&xgd^Qt1Jd7I0(Ig9Sgwg%1rwF@{L zX1in6^#8xs`Rub0kGyI?=Fd0%gozG!#6o;afkC^$5jGH$f#oIbVb z&in7R_via9Km72+XF0ZOD>b^7UYgo|#<4yA<*vM!9}gdXR+$GH25bPiXj)3-wEs#~ zb@{G=GX2M0Bujq$-1mOEoN>+Rm!R+fIb?&IYv7;VKYlC5%2dwdKm6gkJ9quN0t=1> zj0_A7?t%`?Yp%Tgbn^e-GvUt{bT8Twqvy@|C2#v?P$3FRZH(7euUhr_=bucrze_D& ze3)_BY$v5E!M1_WW_e$QM-JCZoZQk?!b|*}HQzN5_L8&W{x@nkILAqXri@XynnRi$N;k?IxYyL2R-!o6mjT^ZxhJc>a2&KMky) z>J#h(#_c@6=IQl){wZ^ELHDAFstK>ZR$0ir+kXbMn*2d9Q$|DXk4rLNg5*nn{0ahf zTkgIsV*)kU9yGFCV3=L_U*?NNpYP>A6V=-P+sg2H?>F+jyj=7WC>_KrHL%^7q;vY! zu6@SMdAGlP=h>yvb^58$%-La(G(U|&Dk1sZ{ATcg=OT@~{af$9Uw{4eCI0sLSN4Mv zs0~O(bsi|I&QH5={q@%xJM;ZMmzUIoGqf6`$$_xDH;)RQ+3!-f;C=O9Y0z4=!<-8k zx4rsj_rm}2OM7rvnE{l}Hze|(T;RX_@>+E%P}pr`xxjF{>~*uywG_q`n9 z#=yX!z{+THz*^(hXbZ9T?%rA zke~zeo_?LvvzAG=J)CFNS19v(SJ`(^XKg|sgVckyDUhb~^wX)DZG7?e^UwQU_LvWf z-6bp+81gmFe_oc^cl@zM-)Ecn|APO17wv3WA0Db&3+gHb2|FGH4d|+^yH*^a5~H0#>cQF6|MOWvAvMnp9Ha~mLg2_@V3;HTF0L3Rv@n1?%+R0$ zE<+d?R6y4rfqcpd&KwL3p5Wxlz~BM8A&h}x)Ch*rumEM>(R9I}Fq%h3%L@kTmYpB# XjkJ9x8%_PO6`aXj{an^LB{Ts5xM=s2 literal 0 HcmV?d00001 diff --git a/assets/install/meson.build b/assets/install/meson.build new file mode 100644 index 00000000..19b49638 --- /dev/null +++ b/assets/install/meson.build @@ -0,0 +1,6 @@ +globber = run_command('sh', '-c', 'find -type f -not -name "*.build"', check: true) +files = globber.stdout().strip().split('\n') + +foreach file : files + install_data(file, install_dir: join_paths(get_option('datadir'), 'hypr'), install_tag: 'runtime') +endforeach diff --git a/assets/wall0.png b/assets/install/wall0.png similarity index 100% rename from assets/wall0.png rename to assets/install/wall0.png diff --git a/assets/wall1.png b/assets/install/wall1.png similarity index 100% rename from assets/wall1.png rename to assets/install/wall1.png diff --git a/assets/wall2.png b/assets/install/wall2.png similarity index 100% rename from assets/wall2.png rename to assets/install/wall2.png diff --git a/assets/meson.build b/assets/meson.build index 47de3d02..0648037a 100644 --- a/assets/meson.build +++ b/assets/meson.build @@ -1,7 +1,2 @@ -wallpapers = ['0', '1', '2'] - -foreach type : wallpapers - install_data(f'wall@type@.png', install_dir: join_paths(get_option('datadir'), 'hypr'), install_tag: 'runtime') -endforeach - install_data('hyprland-portals.conf', install_dir: join_paths(get_option('datadir'), 'xdg-desktop-portal'), install_tag: 'runtime') +subdir('install') diff --git a/src/managers/SessionLockManager.cpp b/src/managers/SessionLockManager.cpp index 81e22889..7267b8f2 100644 --- a/src/managers/SessionLockManager.cpp +++ b/src/managers/SessionLockManager.cpp @@ -4,6 +4,7 @@ #include "../protocols/FractionalScale.hpp" #include "../protocols/SessionLock.hpp" #include +#include SSessionLockSurface::SSessionLockSurface(SP surface_) : surface(surface_) { pWlrSurface = surface->surface(); @@ -166,3 +167,7 @@ void CSessionLockManager::removeSessionLockSurface(SSessionLockSurface* pSLS) { bool CSessionLockManager::isSessionLockPresent() { return m_pSessionLock && !m_pSessionLock->vSessionLockSurfaces.empty(); } + +bool CSessionLockManager::anySessionLockSurfacesPresent() { + return m_pSessionLock && std::ranges::any_of(m_pSessionLock->vSessionLockSurfaces, [](const auto& surf) { return surf->mapped; }); +} diff --git a/src/managers/SessionLockManager.hpp b/src/managers/SessionLockManager.hpp index b01ee288..9b3b882c 100644 --- a/src/managers/SessionLockManager.hpp +++ b/src/managers/SessionLockManager.hpp @@ -55,6 +55,7 @@ class CSessionLockManager { bool isSessionLocked(); bool isSessionLockPresent(); bool isSurfaceSessionLock(SP); + bool anySessionLockSurfacesPresent(); void removeSessionLockSurface(SSessionLockSurface*); diff --git a/src/render/OpenGL.cpp b/src/render/OpenGL.cpp index 67c11c23..91849701 100644 --- a/src/render/OpenGL.cpp +++ b/src/render/OpenGL.cpp @@ -338,6 +338,8 @@ CHyprOpenGLImpl::CHyprOpenGLImpl() { initDRMFormats(); + initAssets(); + static auto P = g_pHookSystem->hookDynamic("preRender", [&](void* self, SCallbackInfo& info, std::any data) { preRender(std::any_cast(data)); }); RASSERT(eglMakeCurrent(m_pEglDisplay, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT), "Couldn't unset current EGL!"); @@ -2614,14 +2616,17 @@ void CHyprOpenGLImpl::renderSplash(cairo_t* const CAIRO, cairo_surface_t* const cairo_surface_flush(CAIROSURFACE); } -void CHyprOpenGLImpl::createBackgroundTexture(const std::string& texPath) { - const auto CAIROSURFACE = cairo_image_surface_create_from_png(texPath.c_str()); - const auto CAIROFORMAT = cairo_image_surface_get_format(CAIROSURFACE); +SP CHyprOpenGLImpl::loadAsset(const std::string& file) { + const auto CAIROSURFACE = cairo_image_surface_create_from_png(file.c_str()); - m_pBackgroundTexture = makeShared(); + if (!CAIROSURFACE) + return nullptr; - m_pBackgroundTexture->allocate(); - m_pBackgroundTexture->m_vSize = {cairo_image_surface_get_width(CAIROSURFACE), cairo_image_surface_get_height(CAIROSURFACE)}; + const auto CAIROFORMAT = cairo_image_surface_get_format(CAIROSURFACE); + auto tex = makeShared(); + + tex->allocate(); + tex->m_vSize = {cairo_image_surface_get_width(CAIROSURFACE), cairo_image_surface_get_height(CAIROSURFACE)}; const GLint glIFormat = CAIROFORMAT == CAIRO_FORMAT_RGB96F ? #ifdef GLES2 @@ -2634,7 +2639,7 @@ void CHyprOpenGLImpl::createBackgroundTexture(const std::string& texPath) { const GLint glType = CAIROFORMAT == CAIRO_FORMAT_RGB96F ? GL_FLOAT : GL_UNSIGNED_BYTE; const auto DATA = cairo_image_surface_get_data(CAIROSURFACE); - glBindTexture(GL_TEXTURE_2D, m_pBackgroundTexture->m_iTexID); + glBindTexture(GL_TEXTURE_2D, tex->m_iTexID); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); #ifndef GLES2 @@ -2643,9 +2648,105 @@ void CHyprOpenGLImpl::createBackgroundTexture(const std::string& texPath) { glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_B, GL_RED); } #endif - glTexImage2D(GL_TEXTURE_2D, 0, glIFormat, m_pBackgroundTexture->m_vSize.x, m_pBackgroundTexture->m_vSize.y, 0, glFormat, glType, DATA); + glTexImage2D(GL_TEXTURE_2D, 0, glIFormat, tex->m_vSize.x, tex->m_vSize.y, 0, glFormat, glType, DATA); cairo_surface_destroy(CAIROSURFACE); + + return tex; +} + +SP CHyprOpenGLImpl::renderText(const std::string& text, CColor col, int pt, bool italic) { + SP tex = makeShared(); + + static auto FONT = CConfigValue("misc:font_family"); + + const auto FONTFAMILY = *FONT; + const auto FONTSIZE = pt; + const auto COLOR = col; + + auto CAIROSURFACE = cairo_image_surface_create(CAIRO_FORMAT_ARGB32, 1920, 1080 /* arbitrary, just for size */); + auto CAIRO = cairo_create(CAIROSURFACE); + + PangoLayout* layoutText = pango_cairo_create_layout(CAIRO); + PangoFontDescription* pangoFD = pango_font_description_new(); + + pango_font_description_set_family_static(pangoFD, FONTFAMILY.c_str()); + pango_font_description_set_absolute_size(pangoFD, FONTSIZE * PANGO_SCALE); + pango_font_description_set_style(pangoFD, italic ? PANGO_STYLE_ITALIC : PANGO_STYLE_NORMAL); + pango_font_description_set_weight(pangoFD, PANGO_WEIGHT_NORMAL); + pango_layout_set_font_description(layoutText, pangoFD); + + cairo_set_source_rgba(CAIRO, COLOR.r, COLOR.g, COLOR.b, COLOR.a); + + int textW = 0, textH = 0; + pango_layout_set_text(layoutText, text.c_str(), -1); + pango_layout_get_size(layoutText, &textW, &textH); + textW /= PANGO_SCALE; + textH /= PANGO_SCALE; + + pango_font_description_free(pangoFD); + g_object_unref(layoutText); + cairo_destroy(CAIRO); + cairo_surface_destroy(CAIROSURFACE); + + CAIROSURFACE = cairo_image_surface_create(CAIRO_FORMAT_ARGB32, textW, textH); + CAIRO = cairo_create(CAIROSURFACE); + + layoutText = pango_cairo_create_layout(CAIRO); + pangoFD = pango_font_description_new(); + + pango_font_description_set_family_static(pangoFD, FONTFAMILY.c_str()); + pango_font_description_set_absolute_size(pangoFD, FONTSIZE * PANGO_SCALE); + pango_font_description_set_style(pangoFD, italic ? PANGO_STYLE_ITALIC : PANGO_STYLE_NORMAL); + pango_font_description_set_weight(pangoFD, PANGO_WEIGHT_NORMAL); + pango_layout_set_font_description(layoutText, pangoFD); + pango_layout_set_text(layoutText, text.c_str(), -1); + + cairo_set_source_rgba(CAIRO, COLOR.r, COLOR.g, COLOR.b, COLOR.a); + + cairo_move_to(CAIRO, 0, 0); + pango_cairo_show_layout(CAIRO, layoutText); + + pango_font_description_free(pangoFD); + g_object_unref(layoutText); + + cairo_surface_flush(CAIROSURFACE); + + tex->allocate(); + tex->m_vSize = {cairo_image_surface_get_width(CAIROSURFACE), cairo_image_surface_get_height(CAIROSURFACE)}; + + const auto DATA = cairo_image_surface_get_data(CAIROSURFACE); + glBindTexture(GL_TEXTURE_2D, tex->m_iTexID); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); +#ifndef GLES2 + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_R, GL_BLUE); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_B, GL_RED); +#endif + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, tex->m_vSize.x, tex->m_vSize.y, 0, GL_RGBA, GL_UNSIGNED_BYTE, DATA); + + cairo_destroy(CAIRO); + cairo_surface_destroy(CAIROSURFACE); + + return tex; +} + +void CHyprOpenGLImpl::initAssets() { + std::string assetsPath = ""; +#ifndef DATAROOTDIR + assetsPath = "/usr/share/hypr/"; +#else + assetsPath = std::format("{}{}", DATAROOTDIR, "/hypr/"); +#endif + + m_pLockDeadTexture = loadAsset(assetsPath + "lockdead.png"); + m_pLockDead2Texture = loadAsset(assetsPath + "lockdead2.png"); + + m_pLockTtyTextTexture = renderText(std::format("Running on tty {}", + g_pCompositor->m_pAqBackend->hasSession() && g_pCompositor->m_pAqBackend->session->vt > 0 ? + std::to_string(g_pCompositor->m_pAqBackend->session->vt) : + "unknown"), + CColor{0.9F, 0.9F, 0.9F, 0.7F}, 20, true); } void CHyprOpenGLImpl::createBGTextureForMonitor(CMonitor* pMonitor) { @@ -2694,7 +2795,7 @@ void CHyprOpenGLImpl::createBGTextureForMonitor(CMonitor* pMonitor) { return; // the texture will be empty, oh well. We'll clear with a solid color anyways. } - createBackgroundTexture(texPath); + m_pBackgroundTexture = loadAsset(texPath); } // create a new one with cairo diff --git a/src/render/OpenGL.hpp b/src/render/OpenGL.hpp index f405cb7c..06078a00 100644 --- a/src/render/OpenGL.hpp +++ b/src/render/OpenGL.hpp @@ -277,7 +277,7 @@ class CHyprOpenGLImpl { CShader m_sFinalScreenShader; CTimer m_tGlobalTimer; - SP m_pBackgroundTexture; + SP m_pBackgroundTexture, m_pLockDeadTexture, m_pLockDead2Texture, m_pLockTtyTextTexture; void logShaderError(const GLuint&, bool program = false); GLuint createProgram(const std::string&, const std::string&, bool dynamic = false); @@ -287,7 +287,9 @@ class CHyprOpenGLImpl { void initDRMFormats(); void initEGL(bool gbm); EGLDeviceEXT eglDeviceFromDRMFD(int drmFD); - void createBackgroundTexture(const std::string& path); + SP loadAsset(const std::string& file); + SP renderText(const std::string& text, CColor col, int pt, bool italic = false); + void initAssets(); // std::optional> getModsForFormat(EGLint format); diff --git a/src/render/Renderer.cpp b/src/render/Renderer.cpp index 33679731..2854a973 100644 --- a/src/render/Renderer.cpp +++ b/src/render/Renderer.cpp @@ -839,9 +839,7 @@ void CHyprRenderer::renderAllClientsForWorkspace(CMonitor* pMonitor, PHLWORKSPAC if (g_pSessionLockManager->isSessionLocked() && !g_pSessionLockManager->isSessionLockPresent()) { // locked with no exclusive, draw only red - CBox boxe = {0, 0, INT16_MAX, INT16_MAX}; - const float A = g_pSessionLockManager->getRedScreenAlphaForMonitor(pMonitor->ID); - g_pHyprOpenGL->renderRect(&boxe, CColor(1.0, 0.2, 0.2, A)); + renderSessionLockMissing(pMonitor); return; } @@ -1001,27 +999,50 @@ void CHyprRenderer::renderLockscreen(CMonitor* pMonitor, timespec* now, const CB if (g_pSessionLockManager->isSessionLocked()) { Vector2D translate = {geometry.x, geometry.y}; - float scale = (float)geometry.width / pMonitor->vecPixelSize.x; const auto PSLS = g_pSessionLockManager->getSessionLockSurfaceForMonitor(pMonitor->ID); - if (!PSLS) { - // locked with no surface, fill with red - const auto ALPHA = g_pSessionLockManager->getRedScreenAlphaForMonitor(pMonitor->ID); - - CBox monbox = {translate.x, translate.y, pMonitor->vecTransformedSize.x * scale, pMonitor->vecTransformedSize.y * scale}; - g_pHyprOpenGL->renderRect(&monbox, CColor(1.0, 0.2, 0.2, ALPHA)); - - if (ALPHA < 1.f) /* animate */ - damageMonitor(pMonitor); - else - g_pSessionLockManager->onLockscreenRenderedOnMonitor(pMonitor->ID); - } else { + if (!PSLS) + renderSessionLockMissing(pMonitor); + else { renderSessionLockSurface(PSLS, pMonitor, now); g_pSessionLockManager->onLockscreenRenderedOnMonitor(pMonitor->ID); } } } +void CHyprRenderer::renderSessionLockMissing(CMonitor* pMonitor) { + const auto ALPHA = g_pSessionLockManager->getRedScreenAlphaForMonitor(pMonitor->ID); + + CBox monbox = {{}, pMonitor->vecPixelSize}; + + const bool ANY_PRESENT = g_pSessionLockManager->anySessionLockSurfacesPresent(); + + if (ANY_PRESENT) { + // render image2, without instructions. Lock still "alive", unless texture dead + if (g_pHyprOpenGL->m_pLockDead2Texture) + g_pHyprOpenGL->renderTexture(g_pHyprOpenGL->m_pLockDead2Texture, &monbox, ALPHA); + else + g_pHyprOpenGL->renderRect(&monbox, CColor(1.0, 0.2, 0.2, ALPHA)); + } else { + // render image, with instructions. Lock is gone. + if (g_pHyprOpenGL->m_pLockDeadTexture) { + g_pHyprOpenGL->renderTexture(g_pHyprOpenGL->m_pLockDeadTexture, &monbox, ALPHA); + + // also render text for the tty number + if (g_pHyprOpenGL->m_pLockTtyTextTexture) { + CBox texbox = {{}, g_pHyprOpenGL->m_pLockTtyTextTexture->m_vSize}; + g_pHyprOpenGL->renderTexture(g_pHyprOpenGL->m_pLockTtyTextTexture, &texbox, 1.F); + } + } else + g_pHyprOpenGL->renderRect(&monbox, CColor(1.0, 0.2, 0.2, ALPHA)); + } + + if (ALPHA < 1.f) /* animate */ + damageMonitor(pMonitor); + else + g_pSessionLockManager->onLockscreenRenderedOnMonitor(pMonitor->ID); +} + void CHyprRenderer::calculateUVForSurface(PHLWINDOW pWindow, SP pSurface, bool main, const Vector2D& projSize, bool fixMisalignedFSV1) { if (!pWindow || !pWindow->m_bIsX11) { Vector2D uvTL; diff --git a/src/render/Renderer.hpp b/src/render/Renderer.hpp index 0b16efea..d00c0a17 100644 --- a/src/render/Renderer.hpp +++ b/src/render/Renderer.hpp @@ -123,6 +123,7 @@ class CHyprRenderer { void renderWorkspace(CMonitor* pMonitor, PHLWORKSPACE pWorkspace, timespec* now, const CBox& geometry); void sendFrameEventsToWorkspace(CMonitor* pMonitor, PHLWORKSPACE pWorkspace, timespec* now); // sends frame displayed events but doesn't actually render anything void renderAllClientsForWorkspace(CMonitor* pMonitor, PHLWORKSPACE pWorkspace, timespec* now, const Vector2D& translate = {0, 0}, const float& scale = 1.f); + void renderSessionLockMissing(CMonitor* pMonitor); bool commitPendingAndDoExplicitSync(CMonitor* pMonitor); From ef33198e8f9fa874b3ad2e2775f8474af62d7fee Mon Sep 17 00:00:00 2001 From: Mihai Fufezan Date: Fri, 30 Aug 2024 14:10:46 +0300 Subject: [PATCH 0340/2181] flake.lock: update aquamarine and hyprutils --- flake.lock | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/flake.lock b/flake.lock index 219cc08b..b26cd5e3 100644 --- a/flake.lock +++ b/flake.lock @@ -16,11 +16,11 @@ ] }, "locked": { - "lastModified": 1724850097, - "narHash": "sha256-3BHxvFb3NJzch1X8puRMkVZujOoarQ1llu3ZcwuvsKU=", + "lastModified": 1725016199, + "narHash": "sha256-2TMk7F2a27ZtOUW/bftkDyZKp3OQ71E5XnfKSUT8HZQ=", "owner": "hyprwm", "repo": "aquamarine", - "rev": "23c7925dd31e79e8c06086ace3edb129a070ac01", + "rev": "cff00196f0fcf734a2bf164eb0dfdb6e58c5c906", "type": "github" }, "original": { @@ -116,11 +116,11 @@ ] }, "locked": { - "lastModified": 1724863980, - "narHash": "sha256-7Ke9wFRYPUIXwm5ZndGHkWBKj6BsFTkSEXUNXQRHE54=", + "lastModified": 1724966483, + "narHash": "sha256-WXDgKIbzjYKczxSZOsJplCS1i1yrTUpsDPuJV/xpYLo=", "owner": "hyprwm", "repo": "hyprutils", - "rev": "aadf9a27dddd2272ca354ba5a22a0c2d1f919039", + "rev": "8976e3f6a5357da953a09511d0c7f6a890fb6ec2", "type": "github" }, "original": { From 259dcd838eef8d6eb2f88f2c0935e32bf7985ebd Mon Sep 17 00:00:00 2001 From: trianta <56975502+Trimutex@users.noreply.github.com> Date: Fri, 30 Aug 2024 07:04:09 -0500 Subject: [PATCH 0341/2181] xwayland: update overrideRedirect on map and configure (#7575) --- src/xwayland/XWM.cpp | 15 ++++++++++++++- src/xwayland/XWM.hpp | 1 + 2 files changed, 15 insertions(+), 1 deletion(-) diff --git a/src/xwayland/XWM.cpp b/src/xwayland/XWM.cpp index 5ad146e4..b5762762 100644 --- a/src/xwayland/XWM.cpp +++ b/src/xwayland/XWM.cpp @@ -81,6 +81,7 @@ void CXWM::handleConfigureNotify(xcb_configure_notify_event_t* e) { return; XSURF->geometry = {e->x, e->y, e->width, e->height}; + updateOverrideRedirect(XSURF, e->override_redirect); XSURF->events.setGeometry.emit(); } @@ -115,7 +116,12 @@ void CXWM::handleMapRequest(xcb_map_request_event_t* e) { void CXWM::handleMapNotify(xcb_map_notify_event_t* e) { const auto XSURF = windowForXID(e->window); - if (!XSURF || XSURF->overrideRedirect) + if (!XSURF) + return; + + updateOverrideRedirect(XSURF, e->override_redirect); + + if (XSURF->overrideRedirect) return; XSURF->setWithdrawn(false); @@ -1044,6 +1050,13 @@ bool CXWM::isWMWindow(xcb_window_t w) { return w == wmWindow || w == clipboard.window; } +void CXWM::updateOverrideRedirect(SP surf, bool overrideRedirect) { + if (!surf || surf->overrideRedirect == overrideRedirect) + return; + + surf->overrideRedirect = overrideRedirect; +} + void CXWM::initSelection() { clipboard.window = xcb_generate_id(connection); uint32_t mask[1] = {XCB_EVENT_MASK_SUBSTRUCTURE_NOTIFY | XCB_EVENT_MASK_PROPERTY_CHANGE}; diff --git a/src/xwayland/XWM.hpp b/src/xwayland/XWM.hpp index 4f6f3f7c..7d6b63ed 100644 --- a/src/xwayland/XWM.hpp +++ b/src/xwayland/XWM.hpp @@ -82,6 +82,7 @@ class CXWM { void focusWindow(SP surf); void activateSurface(SP surf, bool activate); bool isWMWindow(xcb_window_t w); + void updateOverrideRedirect(SP surf, bool overrideRedirect); void sendWMMessage(SP surf, xcb_client_message_data_t* data, uint32_t mask); From 25e72949a1cc2368425ed81712a394cb277f514f Mon Sep 17 00:00:00 2001 From: Vaxry Date: Fri, 30 Aug 2024 14:12:23 +0200 Subject: [PATCH 0342/2181] window/xwayland: minor property cleanup fixes #6921 --- src/Compositor.cpp | 14 +++++++------- src/desktop/Window.cpp | 13 ++++++++++--- src/desktop/Window.hpp | 4 ++-- src/events/Windows.cpp | 8 ++++---- src/helpers/Monitor.cpp | 2 +- src/layout/IHyprLayout.cpp | 14 +++++++------- src/managers/AnimationManager.cpp | 2 +- src/managers/XWaylandManager.cpp | 11 ++++------- src/managers/input/InputManager.cpp | 4 ++-- 9 files changed, 38 insertions(+), 34 deletions(-) diff --git a/src/Compositor.cpp b/src/Compositor.cpp index cacbeece..7ae3070d 100644 --- a/src/Compositor.cpp +++ b/src/Compositor.cpp @@ -791,7 +791,7 @@ PHLWINDOW CCompositor::vectorToWindowUnified(const Vector2D& pos, uint8_t proper if (properties & ALLOW_FLOATING) { for (auto const& w : m_vWindows | std::views::reverse) { const auto BB = w->getWindowBoxUnified(properties); - CBox box = BB.copy().expand(w->m_iX11Type != 2 ? BORDER_GRAB_AREA : 0); + CBox box = BB.copy().expand(!w->isX11OverrideRedirect() ? BORDER_GRAB_AREA : 0); if (w->m_bIsFloating && w->m_bIsMapped && !w->isHidden() && !w->m_bX11ShouldntFocus && w->m_bPinned && !w->m_sWindowData.noFocus.valueOrDefault() && w != pIgnoreWindow) { if (box.containsPoint(g_pPointerManager->position())) @@ -821,16 +821,16 @@ PHLWINDOW CCompositor::vectorToWindowUnified(const Vector2D& pos, uint8_t proper BB.x + BB.width <= PWINDOWMONITOR->vecPosition.x + PWINDOWMONITOR->vecSize.x && BB.y + BB.height <= PWINDOWMONITOR->vecPosition.y + PWINDOWMONITOR->vecSize.y) continue; - CBox box = BB.copy().expand(w->m_iX11Type != 2 ? BORDER_GRAB_AREA : 0); + CBox box = BB.copy().expand(!w->isX11OverrideRedirect() ? BORDER_GRAB_AREA : 0); if (w->m_bIsFloating && w->m_bIsMapped && isWorkspaceVisible(w->m_pWorkspace) && !w->isHidden() && !w->m_bPinned && !w->m_sWindowData.noFocus.valueOrDefault() && w != pIgnoreWindow && (!aboveFullscreen || w->m_bCreatedOverFullscreen)) { // OR windows should add focus to parent - if (w->m_bX11ShouldntFocus && w->m_iX11Type != 2) + if (w->m_bX11ShouldntFocus && !w->isX11OverrideRedirect()) continue; if (box.containsPoint(g_pPointerManager->position())) { - if (w->m_bIsX11 && w->m_iX11Type == 2 && !w->m_pXWaylandSurface->wantsFocus()) { + if (w->m_bIsX11 && w->isX11OverrideRedirect() && !w->m_pXWaylandSurface->wantsFocus()) { // Override Redirect return g_pCompositor->m_pLastWindow.lock(); // we kinda trick everything here. // TODO: this is wrong, we should focus the parent, but idk how to get it considering it's nullptr in most cases. @@ -997,7 +997,7 @@ void CCompositor::focusWindow(PHLWINDOW pWindow, SP pSurface return; } - if (pWindow && pWindow->m_bIsX11 && pWindow->m_iX11Type == 2 && !pWindow->m_pXWaylandSurface->wantsFocus()) + if (pWindow && pWindow->m_bIsX11 && pWindow->isX11OverrideRedirect() && !pWindow->m_pXWaylandSurface->wantsFocus()) return; g_pLayoutManager->getCurrentLayout()->bringWindowToTop(pWindow); @@ -1071,7 +1071,7 @@ void CCompositor::focusWindow(PHLWINDOW pWindow, SP pSurface updateWindowAnimatedDecorationValues(PLASTWINDOW); - if (!pWindow->m_bIsX11 || pWindow->m_iX11Type == 1) + if (!pWindow->m_bIsX11 || !pWindow->isX11OverrideRedirect()) g_pXWaylandManager->activateWindow(PLASTWINDOW, false); } @@ -1928,7 +1928,7 @@ void CCompositor::updateWindowAnimatedDecorationValues(PHLWINDOW pWindow) { } // shadow - if (pWindow->m_iX11Type != 2 && !pWindow->m_bX11DoesntWantBorders) { + if (!pWindow->isX11OverrideRedirect() && !pWindow->m_bX11DoesntWantBorders) { if (pWindow == m_pLastWindow) { pWindow->m_cRealShadowColor = CColor(*PSHADOWCOL); } else { diff --git a/src/desktop/Window.cpp b/src/desktop/Window.cpp index a4ba366a..7623d45e 100644 --- a/src/desktop/Window.cpp +++ b/src/desktop/Window.cpp @@ -19,9 +19,8 @@ using namespace Hyprutils::String; PHLWINDOW CWindow::create(SP surface) { PHLWINDOW pWindow = SP(new CWindow(surface)); - pWindow->m_pSelf = pWindow; - pWindow->m_bIsX11 = true; - pWindow->m_iX11Type = surface->overrideRedirect ? 2 : 1; + pWindow->m_pSelf = pWindow; + pWindow->m_bIsX11 = true; pWindow->m_vRealPosition.create(g_pConfigManager->getAnimationPropertyConfig("windowsIn"), pWindow, AVARDAMAGE_ENTIRE); pWindow->m_vRealSize.create(g_pConfigManager->getAnimationPropertyConfig("windowsIn"), pWindow, AVARDAMAGE_ENTIRE); @@ -1571,3 +1570,11 @@ void CWindow::unsetWindowData(eOverridePriority priority) { element.second(m_pSelf.lock())->unset(priority); } } + +bool CWindow::isX11OverrideRedirect() { + return m_pXWaylandSurface && m_pXWaylandSurface->overrideRedirect; +} + +bool CWindow::isModal() { + return (m_pXWaylandSurface && m_pXWaylandSurface->modal); +} diff --git a/src/desktop/Window.hpp b/src/desktop/Window.hpp index bdc275bf..7197ba26 100644 --- a/src/desktop/Window.hpp +++ b/src/desktop/Window.hpp @@ -288,8 +288,6 @@ class CWindow { // XWayland stuff bool m_bIsX11 = false; PHLWINDOWREF m_pX11Parent; - uint64_t m_iX11Type = 0; - bool m_bIsModal = false; bool m_bX11DoesntWantBorders = false; bool m_bX11ShouldntFocus = false; float m_fX11SurfaceScaledBy = 1.f; @@ -468,6 +466,8 @@ class CWindow { void warpCursor(); PHLWINDOW getSwallower(); void unsetWindowData(eOverridePriority priority); + bool isX11OverrideRedirect(); + bool isModal(); // listeners void onAck(uint32_t serial); diff --git a/src/events/Windows.cpp b/src/events/Windows.cpp index cd000223..034920a2 100644 --- a/src/events/Windows.cpp +++ b/src/events/Windows.cpp @@ -120,7 +120,7 @@ void Events::listener_mapWindow(void* owner, void* data) { PWINDOW->m_bRequestsFloat = true; } - PWINDOW->m_bX11ShouldntFocus = PWINDOW->m_bX11ShouldntFocus || (PWINDOW->m_bIsX11 && PWINDOW->m_iX11Type == 2 && !PWINDOW->m_pXWaylandSurface->wantsFocus()); + PWINDOW->m_bX11ShouldntFocus = PWINDOW->m_bX11ShouldntFocus || (PWINDOW->m_bIsX11 && PWINDOW->isX11OverrideRedirect() && !PWINDOW->m_pXWaylandSurface->wantsFocus()); if (PWORKSPACE->m_bDefaultFloating) PWINDOW->m_bIsFloating = true; @@ -477,7 +477,7 @@ void Events::listener_mapWindow(void* owner, void* data) { } if (!PWINDOW->m_sWindowData.noFocus.valueOrDefault() && !PWINDOW->m_bNoInitialFocus && - (PWINDOW->m_iX11Type != 2 || (PWINDOW->m_bIsX11 && PWINDOW->m_pXWaylandSurface->wantsFocus())) && !workspaceSilent && (!PFORCEFOCUS || PFORCEFOCUS == PWINDOW) && + (!PWINDOW->isX11OverrideRedirect() || (PWINDOW->m_bIsX11 && PWINDOW->m_pXWaylandSurface->wantsFocus())) && !workspaceSilent && (!PFORCEFOCUS || PFORCEFOCUS == PWINDOW) && !g_pInputManager->isConstrained()) { g_pCompositor->focusWindow(PWINDOW); PWINDOW->m_fActiveInactiveAlpha.setValueAndWarp(*PACTIVEALPHA); @@ -577,7 +577,7 @@ void Events::listener_mapWindow(void* owner, void* data) { g_pCompositor->updateWorkspaceWindows(PWINDOW->workspaceID()); - if (PMONITOR && PWINDOW->m_iX11Type == 2) + if (PMONITOR && PWINDOW->isX11OverrideRedirect()) PWINDOW->m_fX11SurfaceScaledBy = PMONITOR->scale; } @@ -816,7 +816,7 @@ void Events::listener_activateX11(void* owner, void* data) { Debug::log(LOG, "X11 Activate request for window {}", PWINDOW); - if (PWINDOW->m_iX11Type == 2) { + if (PWINDOW->isX11OverrideRedirect()) { Debug::log(LOG, "Unmanaged X11 {} requests activate", PWINDOW); diff --git a/src/helpers/Monitor.cpp b/src/helpers/Monitor.cpp index 2b8404ee..8af0bc62 100644 --- a/src/helpers/Monitor.cpp +++ b/src/helpers/Monitor.cpp @@ -721,7 +721,7 @@ void CMonitor::setSpecialWorkspace(const PHLWORKSPACE& pWorkspace) { w->setAnimationsToMove(); const auto MIDDLE = w->middle(); - if (w->m_bIsFloating && !VECINRECT(MIDDLE, vecPosition.x, vecPosition.y, vecPosition.x + vecSize.x, vecPosition.y + vecSize.y) && w->m_iX11Type != 2) { + if (w->m_bIsFloating && !VECINRECT(MIDDLE, vecPosition.x, vecPosition.y, vecPosition.x + vecSize.x, vecPosition.y + vecSize.y) && !w->isX11OverrideRedirect()) { // if it's floating and the middle isnt on the current mon, move it to the center const auto PMONFROMMIDDLE = g_pCompositor->getMonitorFromVector(MIDDLE); Vector2D pos = w->m_vRealPosition.goal(); diff --git a/src/layout/IHyprLayout.cpp b/src/layout/IHyprLayout.cpp index f6339beb..c5a5373c 100644 --- a/src/layout/IHyprLayout.cpp +++ b/src/layout/IHyprLayout.cpp @@ -104,7 +104,7 @@ void IHyprLayout::onWindowCreatedFloating(PHLWINDOW pWindow) { pWindow->m_vRealSize = PWINDOWSURFACE->current.size; if ((desiredGeometry.width <= 1 || desiredGeometry.height <= 1) && pWindow->m_bIsX11 && - pWindow->m_iX11Type == 2) { // XDG windows should be fine. TODO: check for weird atoms? + pWindow->isX11OverrideRedirect()) { // XDG windows should be fine. TODO: check for weird atoms? pWindow->setHidden(true); return; } @@ -113,7 +113,7 @@ void IHyprLayout::onWindowCreatedFloating(PHLWINDOW pWindow) { if (pWindow->m_vRealSize.goal().x <= 5 || pWindow->m_vRealSize.goal().y <= 5) pWindow->m_vRealSize = PMONITOR->vecSize / 2.f; - if (pWindow->m_bIsX11 && pWindow->m_iX11Type == 2) { + if (pWindow->m_bIsX11 && pWindow->isX11OverrideRedirect()) { if (pWindow->m_pXWaylandSurface->geometry.x != 0 && pWindow->m_pXWaylandSurface->geometry.y != 0) pWindow->m_vRealPosition = g_pXWaylandManager->xwaylandToWaylandCoords(pWindow->m_pXWaylandSurface->geometry.pos()); @@ -163,12 +163,12 @@ void IHyprLayout::onWindowCreatedFloating(PHLWINDOW pWindow) { if (*PXWLFORCESCALEZERO && pWindow->m_bIsX11) pWindow->m_vRealSize = pWindow->m_vRealSize.goal() / PMONITOR->scale; - if (pWindow->m_bX11DoesntWantBorders || (pWindow->m_bIsX11 && pWindow->m_iX11Type == 2)) { + if (pWindow->m_bX11DoesntWantBorders || (pWindow->m_bIsX11 && pWindow->isX11OverrideRedirect())) { pWindow->m_vRealPosition.warp(); pWindow->m_vRealSize.warp(); } - if (pWindow->m_iX11Type != 2) { + if (!pWindow->isX11OverrideRedirect()) { g_pXWaylandManager->setWindowSize(pWindow, pWindow->m_vRealSize.goal()); g_pCompositor->changeWindowZOrder(pWindow, true); @@ -592,7 +592,7 @@ PHLWINDOW IHyprLayout::getNextWindowCandidate(PHLWINDOW pWindow) { // find whether there is a floating window below this one for (auto const& w : g_pCompositor->m_vWindows) { - if (w->m_bIsMapped && !w->isHidden() && w->m_bIsFloating && w->m_iX11Type != 2 && w->m_pWorkspace == pWindow->m_pWorkspace && !w->m_bX11ShouldntFocus && + if (w->m_bIsMapped && !w->isHidden() && w->m_bIsFloating && !w->isX11OverrideRedirect() && w->m_pWorkspace == pWindow->m_pWorkspace && !w->m_bX11ShouldntFocus && !w->m_sWindowData.noFocus.valueOrDefault() && w != pWindow) { if (VECINRECT((pWindow->m_vSize / 2.f + pWindow->m_vPosition), w->m_vPosition.x, w->m_vPosition.y, w->m_vPosition.x + w->m_vSize.x, w->m_vPosition.y + w->m_vSize.y)) { @@ -612,7 +612,7 @@ PHLWINDOW IHyprLayout::getNextWindowCandidate(PHLWINDOW pWindow) { // if not, floating window for (auto const& w : g_pCompositor->m_vWindows) { - if (w->m_bIsMapped && !w->isHidden() && w->m_bIsFloating && w->m_iX11Type != 2 && w->m_pWorkspace == pWindow->m_pWorkspace && !w->m_bX11ShouldntFocus && + if (w->m_bIsMapped && !w->isHidden() && w->m_bIsFloating && !w->isX11OverrideRedirect() && w->m_pWorkspace == pWindow->m_pWorkspace && !w->m_bX11ShouldntFocus && !w->m_sWindowData.noFocus.valueOrDefault() && w != pWindow) return w; } @@ -631,7 +631,7 @@ PHLWINDOW IHyprLayout::getNextWindowCandidate(PHLWINDOW pWindow) { pWindowCandidate = g_pCompositor->getFirstWindowOnWorkspace(pWindow->workspaceID()); if (!pWindowCandidate || pWindow == pWindowCandidate || !pWindowCandidate->m_bIsMapped || pWindowCandidate->isHidden() || pWindowCandidate->m_bX11ShouldntFocus || - pWindowCandidate->m_iX11Type == 2 || pWindowCandidate->m_iMonitorID != g_pCompositor->m_pLastMonitor->ID) + pWindowCandidate->isX11OverrideRedirect() || pWindowCandidate->m_iMonitorID != g_pCompositor->m_pLastMonitor->ID) return nullptr; return pWindowCandidate; diff --git a/src/managers/AnimationManager.cpp b/src/managers/AnimationManager.cpp index e2fe7089..092d9721 100644 --- a/src/managers/AnimationManager.cpp +++ b/src/managers/AnimationManager.cpp @@ -194,7 +194,7 @@ void CAnimationManager::tick() { default: UNREACHABLE(); } // set size and pos if valid, but only if damage policy entire (dont if border for example) - if (validMapped(PWINDOW) && av->m_eDamagePolicy == AVARDAMAGE_ENTIRE && PWINDOW->m_iX11Type != 2) + if (validMapped(PWINDOW) && av->m_eDamagePolicy == AVARDAMAGE_ENTIRE && !PWINDOW->isX11OverrideRedirect()) g_pXWaylandManager->setWindowSize(PWINDOW, PWINDOW->m_vRealSize.goal()); // check if we did not finish animating. If so, trigger onAnimationEnd. diff --git a/src/managers/XWaylandManager.cpp b/src/managers/XWaylandManager.cpp index b37e796b..144343f8 100644 --- a/src/managers/XWaylandManager.cpp +++ b/src/managers/XWaylandManager.cpp @@ -59,7 +59,7 @@ void CHyprXWaylandManager::activateWindow(PHLWINDOW pWindow, bool activate) { if (activate) { pWindow->m_pXWaylandSurface->setMinimized(false); - if (pWindow->m_iX11Type != 2) + if (!pWindow->isX11OverrideRedirect()) pWindow->m_pXWaylandSurface->restackToTop(); } @@ -80,7 +80,7 @@ void CHyprXWaylandManager::getGeometryForWindow(PHLWINDOW pWindow, CBox* pbox) { if (pWindow->m_bIsX11) { const auto SIZEHINTS = pWindow->m_pXWaylandSurface->sizeHints.get(); - if (SIZEHINTS && pWindow->m_iX11Type != 2) { + if (SIZEHINTS && !pWindow->isX11OverrideRedirect()) { // WM_SIZE_HINTS' x,y,w,h is deprecated it seems. // Source: https://x.org/releases/X11R7.6/doc/xorg-docs/specs/ICCCM/icccm.html#wm_normal_hints_property pbox->x = pWindow->m_pXWaylandSurface->geometry.x; @@ -160,10 +160,8 @@ bool CHyprXWaylandManager::shouldBeFloated(PHLWINDOW pWindow, bool pending) { return true; } - if (pWindow->m_pXWaylandSurface->modal) { - pWindow->m_bIsModal = true; + if (pWindow->isModal()) return true; - } if (pWindow->m_pXWaylandSurface->transient) return true; @@ -203,9 +201,8 @@ void CHyprXWaylandManager::checkBorders(PHLWINDOW pWindow) { } } - if (pWindow->m_iX11Type == 2) { + if (pWindow->isX11OverrideRedirect()) pWindow->m_bX11DoesntWantBorders = true; - } } void CHyprXWaylandManager::setWindowFullscreen(PHLWINDOW pWindow, bool fullscreen) { diff --git a/src/managers/input/InputManager.cpp b/src/managers/input/InputManager.cpp index 6b04c13f..78c9e437 100644 --- a/src/managers/input/InputManager.cpp +++ b/src/managers/input/InputManager.cpp @@ -675,7 +675,7 @@ void CInputManager::processMouseDownNormal(const IPointer::SButtonEvent& e) { // clicking on border triggers resize // TODO detect click on LS properly - if (*PRESIZEONBORDER && !m_bLastFocusOnLS && e.state == WL_POINTER_BUTTON_STATE_PRESSED && (!w || w->m_iX11Type != 2)) { + if (*PRESIZEONBORDER && !m_bLastFocusOnLS && e.state == WL_POINTER_BUTTON_STATE_PRESSED && (!w || !w->isX11OverrideRedirect())) { if (w && !w->isFullscreen()) { const CBox real = {w->m_vRealPosition.value().x, w->m_vRealPosition.value().y, w->m_vRealSize.value().x, w->m_vRealSize.value().y}; const CBox grab = {real.x - BORDER_GRAB_AREA, real.y - BORDER_GRAB_AREA, real.width + 2 * BORDER_GRAB_AREA, real.height + 2 * BORDER_GRAB_AREA}; @@ -1688,7 +1688,7 @@ void CInputManager::setCursorIconOnBorder(PHLWINDOW w) { } // ignore X11 OR windows, they shouldn't be touched - if (w->m_bIsX11 && w->m_iX11Type == 2) + if (w->m_bIsX11 && w->isX11OverrideRedirect()) return; static auto PEXTENDBORDERGRAB = CConfigValue("general:extend_border_grab_area"); From 242e06b24212b61e7afbdf5cf4adae8886a28abd Mon Sep 17 00:00:00 2001 From: darkwater Date: Fri, 30 Aug 2024 15:06:49 +0200 Subject: [PATCH 0343/2181] keybinds: release mods after sendshortcut (#7581) --- src/managers/KeybindManager.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/managers/KeybindManager.cpp b/src/managers/KeybindManager.cpp index df3f2572..72799f1d 100644 --- a/src/managers/KeybindManager.cpp +++ b/src/managers/KeybindManager.cpp @@ -2349,6 +2349,8 @@ SDispatchResult CKeybindManager::sendshortcut(std::string args) { } } + g_pSeatManager->sendKeyboardMods(0, 0, 0, 0); + if (!PWINDOW) return {}; From 1c9d56998dbf3a9b61e13573e9e91d149fe65969 Mon Sep 17 00:00:00 2001 From: Vaxry Date: Fri, 30 Aug 2024 15:18:12 +0200 Subject: [PATCH 0344/2181] xdg-dialog: implement new protocol --- CMakeLists.txt | 1 + protocols/meson.build | 1 + src/Compositor.cpp | 17 ++++-- src/managers/ProtocolManager.cpp | 2 + src/protocols/XDGDialog.cpp | 88 ++++++++++++++++++++++++++++++++ src/protocols/XDGDialog.hpp | 57 +++++++++++++++++++++ src/protocols/XDGShell.cpp | 18 ++++++- src/protocols/XDGShell.hpp | 8 ++- src/render/OpenGL.cpp | 5 +- 9 files changed, 187 insertions(+), 10 deletions(-) create mode 100644 src/protocols/XDGDialog.cpp create mode 100644 src/protocols/XDGDialog.hpp diff --git a/CMakeLists.txt b/CMakeLists.txt index 84a856b8..dba14813 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -315,6 +315,7 @@ protocolnew("stable/viewporter" "viewporter" false) protocolnew("stable/linux-dmabuf" "linux-dmabuf-v1" false) protocolnew("staging/drm-lease" "drm-lease-v1" false) protocolnew("staging/linux-drm-syncobj" "linux-drm-syncobj-v1" false) +protocolnew("staging/xdg-dialog" "xdg-dialog-v1" false) protocolwayland() diff --git a/protocols/meson.build b/protocols/meson.build index 5b807914..de650230 100644 --- a/protocols/meson.build +++ b/protocols/meson.build @@ -60,6 +60,7 @@ new_protocols = [ [wl_protocol_dir, 'stable/linux-dmabuf/linux-dmabuf-v1.xml'], [wl_protocol_dir, 'staging/drm-lease/drm-lease-v1.xml'], [wl_protocol_dir, 'staging/linux-drm-syncobj/linux-drm-syncobj-v1.xml'], + [wl_protocol_dir, 'staging/xdg-dialog/xdg-dialog-v1.xml'], ] wl_protos_src = [] diff --git a/src/Compositor.cpp b/src/Compositor.cpp index 7ae3070d..eac75bd4 100644 --- a/src/Compositor.cpp +++ b/src/Compositor.cpp @@ -1888,6 +1888,8 @@ void CCompositor::updateWindowAnimatedDecorationValues(PHLWINDOW pWindow) { pWindow->m_fBorderFadeAnimationProgress = 1.f; }; + const bool IS_SHADOWED_BY_MODAL = pWindow->m_pXDGSurface && pWindow->m_pXDGSurface->toplevel && pWindow->m_pXDGSurface->toplevel->anyChildModal(); + // border const auto RENDERDATA = g_pLayoutManager->getCurrentLayout()->requestRenderHints(pWindow); if (RENDERDATA.isBorderGradient) @@ -1921,11 +1923,16 @@ void CCompositor::updateWindowAnimatedDecorationValues(PHLWINDOW pWindow) { } // dim - if (pWindow == m_pLastWindow.lock() || pWindow->m_sWindowData.noDim.valueOrDefault() || !*PDIMENABLED) { - pWindow->m_fDimPercent = 0; - } else { - pWindow->m_fDimPercent = *PDIMSTRENGTH; - } + float goalDim = 1.F; + if (pWindow == m_pLastWindow.lock() || pWindow->m_sWindowData.noDim.valueOrDefault() || !*PDIMENABLED) + goalDim = 0; + else + goalDim = *PDIMSTRENGTH; + + if (IS_SHADOWED_BY_MODAL) + goalDim += (1.F - goalDim) / 2.F; + + pWindow->m_fDimPercent = goalDim; // shadow if (!pWindow->isX11OverrideRedirect() && !pWindow->m_bX11DoesntWantBorders) { diff --git a/src/managers/ProtocolManager.cpp b/src/managers/ProtocolManager.cpp index bace4451..2c421abe 100644 --- a/src/managers/ProtocolManager.cpp +++ b/src/managers/ProtocolManager.cpp @@ -43,6 +43,7 @@ #include "../protocols/ToplevelExport.hpp" #include "../protocols/TextInputV1.hpp" #include "../protocols/GlobalShortcuts.hpp" +#include "../protocols/XDGDialog.hpp" #include "../protocols/core/Seat.hpp" #include "../protocols/core/DataDevice.hpp" @@ -150,6 +151,7 @@ CProtocolManager::CProtocolManager() { PROTO::screencopy = std::make_unique(&zwlr_screencopy_manager_v1_interface, 3, "Screencopy"); PROTO::toplevelExport = std::make_unique(&hyprland_toplevel_export_manager_v1_interface, 2, "ToplevelExport"); PROTO::globalShortcuts = std::make_unique(&hyprland_global_shortcuts_manager_v1_interface, 1, "GlobalShortcuts"); + PROTO::xdgDialog = std::make_unique(&xdg_dialog_v1_interface, 1, "XDGDialog"); for (auto const& b : g_pCompositor->m_pAqBackend->getImplementations()) { if (b->type() != Aquamarine::AQ_BACKEND_DRM) diff --git a/src/protocols/XDGDialog.cpp b/src/protocols/XDGDialog.cpp new file mode 100644 index 00000000..237cf3f3 --- /dev/null +++ b/src/protocols/XDGDialog.cpp @@ -0,0 +1,88 @@ +#include "XDGDialog.hpp" +#include "XDGShell.hpp" +#include "../desktop/WLSurface.hpp" +#include "../Compositor.hpp" +#include + +CXDGDialogV1Resource::CXDGDialogV1Resource(SP resource_, SP toplevel_) : resource(resource_), toplevel(toplevel_) { + if (!good()) + return; + + resource->setDestroy([this](CXdgDialogV1* r) { PROTO::xdgDialog->destroyResource(this); }); + resource->setOnDestroy([this](CXdgDialogV1* r) { PROTO::xdgDialog->destroyResource(this); }); + + resource->setSetModal([this](CXdgDialogV1* r) { + modal = true; + updateWindow(); + }); + + resource->setUnsetModal([this](CXdgDialogV1* r) { + modal = false; + updateWindow(); + }); +} + +void CXDGDialogV1Resource::updateWindow() { + if (!toplevel || !toplevel->parent || !toplevel->parent->owner) + return; + + auto HLSurface = CWLSurface::fromResource(toplevel->parent->owner->surface.lock()); + if (!HLSurface || !HLSurface->getWindow()) + return; + + g_pCompositor->updateWindowAnimatedDecorationValues(HLSurface->getWindow()); +} + +bool CXDGDialogV1Resource::good() { + return resource->resource(); +} + +CXDGWmDialogManagerResource::CXDGWmDialogManagerResource(SP resource_) : resource(resource_) { + if (!good()) + return; + + resource->setDestroy([this](CXdgWmDialogV1* r) { PROTO::xdgDialog->destroyResource(this); }); + resource->setOnDestroy([this](CXdgWmDialogV1* r) { PROTO::xdgDialog->destroyResource(this); }); + + resource->setGetXdgDialog([this](CXdgWmDialogV1* r, uint32_t id, wl_resource* toplevel) { + auto tl = CXDGToplevelResource::fromResource(toplevel); + if (!tl) { + r->error(-1, "Toplevel inert"); + return; + } + + const auto RESOURCE = PROTO::xdgDialog->m_vDialogs.emplace_back(makeShared(makeShared(r->client(), r->version(), id), tl)); + + if (!RESOURCE->good()) { + r->noMemory(); + return; + } + + tl->dialog = RESOURCE; + }); +} + +bool CXDGWmDialogManagerResource::good() { + return resource->resource(); +} + +CXDGDialogProtocol::CXDGDialogProtocol(const wl_interface* iface, const int& ver, const std::string& name) : IWaylandProtocol(iface, ver, name) { + ; +} + +void CXDGDialogProtocol::bindManager(wl_client* client, void* data, uint32_t ver, uint32_t id) { + const auto RESOURCE = m_vManagers.emplace_back(makeShared(makeShared(client, ver, id))); + + if (!RESOURCE->good()) { + wl_client_post_no_memory(client); + return; + } +} + +void CXDGDialogProtocol::destroyResource(CXDGWmDialogManagerResource* res) { + std::erase_if(m_vManagers, [&](const auto& other) { return other.get() == res; }); +} + +void CXDGDialogProtocol::destroyResource(CXDGDialogV1Resource* res) { + std::erase_if(m_vDialogs, [&](const auto& other) { return other.get() == res; }); +} diff --git a/src/protocols/XDGDialog.hpp b/src/protocols/XDGDialog.hpp new file mode 100644 index 00000000..a635bfac --- /dev/null +++ b/src/protocols/XDGDialog.hpp @@ -0,0 +1,57 @@ +#pragma once + +#include +#include +#include +#include "WaylandProtocol.hpp" +#include "xdg-dialog-v1.hpp" + +class CXDGToplevelResource; + +class CXDGDialogV1Resource { + public: + CXDGDialogV1Resource(SP resource_, SP toplevel_); + + bool good(); + + bool modal = false; + + private: + SP resource; + WP toplevel; + + void updateWindow(); +}; + +class CXDGWmDialogManagerResource { + public: + CXDGWmDialogManagerResource(SP resource_); + + bool good(); + + private: + SP resource; +}; + +class CXDGDialogProtocol : public IWaylandProtocol { + public: + CXDGDialogProtocol(const wl_interface* iface, const int& ver, const std::string& name); + + virtual void bindManager(wl_client* client, void* data, uint32_t ver, uint32_t id); + + private: + void onManagerResourceDestroy(wl_resource* res); + void destroyResource(CXDGWmDialogManagerResource* res); + void destroyResource(CXDGDialogV1Resource* res); + + // + std::vector> m_vManagers; + std::vector> m_vDialogs; + + friend class CXDGWmDialogManagerResource; + friend class CXDGDialogV1Resource; +}; + +namespace PROTO { + inline UP xdgDialog; +}; diff --git a/src/protocols/XDGShell.cpp b/src/protocols/XDGShell.cpp index 39a511c3..25d8b1ba 100644 --- a/src/protocols/XDGShell.cpp +++ b/src/protocols/XDGShell.cpp @@ -1,10 +1,12 @@ #include "XDGShell.hpp" +#include "XDGDialog.hpp" #include #include "../Compositor.hpp" #include "../managers/SeatManager.hpp" #include "core/Seat.hpp" #include "core/Compositor.hpp" #include +#include void SXDGPositionerState::setAnchor(xdgPositionerAnchor edges) { anchor.setTop(edges == XDG_POSITIONER_ANCHOR_TOP || edges == XDG_POSITIONER_ANCHOR_TOP_LEFT || edges == XDG_POSITIONER_ANCHOR_TOP_RIGHT); @@ -207,15 +209,25 @@ CXDGToplevelResource::CXDGToplevelResource(SP resource_, SPsetSetParent([this](CXdgToplevel* r, wl_resource* parentR) { + auto oldParent = parent; + + if (parent) + std::erase(parent->children, self); + auto newp = parentR ? CXDGToplevelResource::fromResource(parentR) : nullptr; parent = newp; - LOGM(LOG, "Toplevel {:x} sets parent to {:x}", (uintptr_t)this, (uintptr_t)newp.get()); + if (parent) + parent->children.emplace_back(self); + + LOGM(LOG, "Toplevel {:x} sets parent to {:x}{}", (uintptr_t)this, (uintptr_t)newp.get(), (oldParent ? std::format(" (was {:x})", (uintptr_t)oldParent.get()) : "")); }); } CXDGToplevelResource::~CXDGToplevelResource() { events.destroy.emit(); + if (parent) + std::erase_if(parent->children, [this](const auto& other) { return !other || other.get() == this; }); } SP CXDGToplevelResource::fromResource(wl_resource* res) { @@ -227,6 +239,10 @@ bool CXDGToplevelResource::good() { return resource->resource(); } +bool CXDGToplevelResource::anyChildModal() { + return std::ranges::any_of(children, [](const auto& child) { return child && child->dialog && child->dialog->modal; }); +} + uint32_t CXDGToplevelResource::setSize(const Vector2D& size) { pendingApply.size = size; applyState(); diff --git a/src/protocols/XDGShell.hpp b/src/protocols/XDGShell.hpp index 81d10613..9c766c20 100644 --- a/src/protocols/XDGShell.hpp +++ b/src/protocols/XDGShell.hpp @@ -18,6 +18,7 @@ class CXDGToplevelResource; class CXDGPopupResource; class CSeatGrab; class CWLSurfaceResource; +class CXDGDialogV1Resource; struct SXDGPositionerState { Vector2D requestedSize; @@ -134,7 +135,12 @@ class CXDGToplevelResource { Vector2D maxSize = {1337420, 694200}; } pending, current; - WP parent; + WP parent; + WP dialog; + + bool anyChildModal(); + + std::vector> children; private: SP resource; diff --git a/src/render/OpenGL.cpp b/src/render/OpenGL.cpp index 91849701..74d3d3cd 100644 --- a/src/render/OpenGL.cpp +++ b/src/render/OpenGL.cpp @@ -1378,8 +1378,7 @@ void CHyprOpenGLImpl::renderTextureInternalWithDamage(SP tex, CBox* pB CBox newBox = *pBox; m_RenderData.renderModif.applyToBox(newBox); - static auto PDIMINACTIVE = CConfigValue("decoration:dim_inactive"); - static auto PDT = CConfigValue("debug:damage_tracking"); + static auto PDT = CConfigValue("debug:damage_tracking"); // get the needed transform for this texture const bool TRANSFORMS_MATCH = wlTransformToHyprutils(m_RenderData.pMonitor->transform) == tex->m_eTransform; // FIXME: combine them properly!!! @@ -1493,7 +1492,7 @@ void CHyprOpenGLImpl::renderTextureInternalWithDamage(SP tex, CBox* pB glUniform2f(shader->fullSize, FULLSIZE.x, FULLSIZE.y); glUniform1f(shader->radius, round); - if (allowDim && m_pCurrentWindow.lock() && *PDIMINACTIVE) { + if (allowDim && m_pCurrentWindow.lock()) { glUniform1i(shader->applyTint, 1); const auto DIM = m_pCurrentWindow->m_fDimPercent.value(); glUniform3f(shader->tint, 1.f - DIM, 1.f - DIM, 1.f - DIM); From fd8d8e122ed9cf49f3f84d4d264f1b810c355a07 Mon Sep 17 00:00:00 2001 From: Vaxry Date: Fri, 30 Aug 2024 15:26:00 +0200 Subject: [PATCH 0345/2181] keybinds: fixup misused kb state fixes #7369 --- src/managers/KeybindManager.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/managers/KeybindManager.cpp b/src/managers/KeybindManager.cpp index 72799f1d..7ee5ae7e 100644 --- a/src/managers/KeybindManager.cpp +++ b/src/managers/KeybindManager.cpp @@ -372,7 +372,7 @@ bool CKeybindManager::onKeyEvent(std::any event, SP pKeyboard) { const auto KEYCODE = e.keycode + 8; // Because to xkbcommon it's +8 from libinput - const xkb_keysym_t keysym = xkb_state_key_get_one_sym(pKeyboard->resolveBindsBySym ? pKeyboard->xkbStaticState : m_pXKBTranslationState, KEYCODE); + const xkb_keysym_t keysym = xkb_state_key_get_one_sym(pKeyboard->resolveBindsBySym ? pKeyboard->xkbState : m_pXKBTranslationState, KEYCODE); const xkb_keysym_t internalKeysym = xkb_state_key_get_one_sym(pKeyboard->xkbState, KEYCODE); if (handleInternalKeybinds(internalKeysym)) From fbd63543930417f3cefe36bdb9f2cdd20fc3693a Mon Sep 17 00:00:00 2001 From: Vaxry Date: Fri, 30 Aug 2024 15:50:25 +0200 Subject: [PATCH 0346/2181] presentation-feedback: minor fixups --- src/helpers/Monitor.cpp | 4 ++-- src/protocols/PresentationTime.cpp | 12 +++++++----- src/protocols/PresentationTime.hpp | 8 +++++--- src/protocols/core/Compositor.cpp | 2 +- src/protocols/core/Compositor.hpp | 2 +- src/render/Renderer.cpp | 4 ++-- 6 files changed, 18 insertions(+), 14 deletions(-) diff --git a/src/helpers/Monitor.cpp b/src/helpers/Monitor.cpp index 8af0bc62..685009fd 100644 --- a/src/helpers/Monitor.cpp +++ b/src/helpers/Monitor.cpp @@ -47,7 +47,7 @@ void CMonitor::onConnect(bool noRule) { listeners.presented = output->events.present.registerListener([this](std::any d) { auto E = std::any_cast(d); - PROTO::presentation->onPresented(this, E.when, E.refresh, E.seq, E.flags); + PROTO::presentation->onPresented(self.lock(), E.when, E.refresh, E.seq, E.flags); }); listeners.destroy = output->events.destroy.registerListener([this](std::any d) { @@ -861,7 +861,7 @@ bool CMonitor::attemptDirectScanout() { timespec now; clock_gettime(CLOCK_MONOTONIC, &now); - PSURFACE->presentFeedback(&now, this); + PSURFACE->presentFeedback(&now, self.lock()); output->state->addDamage(CBox{{}, vecPixelSize}); output->state->resetExplicitFences(); diff --git a/src/protocols/PresentationTime.cpp b/src/protocols/PresentationTime.cpp index b1108042..e1ff52cd 100644 --- a/src/protocols/PresentationTime.cpp +++ b/src/protocols/PresentationTime.cpp @@ -14,7 +14,7 @@ void CQueuedPresentationData::setPresentationType(bool zeroCopy_) { zeroCopy = zeroCopy_; } -void CQueuedPresentationData::attachMonitor(CMonitor* pMonitor_) { +void CQueuedPresentationData::attachMonitor(SP pMonitor_) { pMonitor = pMonitor_; } @@ -67,12 +67,14 @@ void CPresentationFeedback::sendQueued(SP data, timespe (uint32_t)(seq & 0xFFFFFFFF), (wpPresentationFeedbackKind)flags); else resource->sendDiscarded(); + + done = true; } CPresentationProtocol::CPresentationProtocol(const wl_interface* iface, const int& ver, const std::string& name) : IWaylandProtocol(iface, ver, name) { static auto P = g_pHookSystem->hookDynamic("monitorRemoved", [this](void* self, SCallbackInfo& info, std::any param) { const auto PMONITOR = std::any_cast(param); - std::erase_if(m_vQueue, [PMONITOR](const auto& other) { return !other->surface || other->pMonitor == PMONITOR; }); + std::erase_if(m_vQueue, [PMONITOR](const auto& other) { return !other->surface || other->pMonitor.get() == PMONITOR; }); }); } @@ -105,7 +107,7 @@ void CPresentationProtocol::onGetFeedback(CWpPresentation* pMgr, wl_resource* su } } -void CPresentationProtocol::onPresented(CMonitor* pMonitor, timespec* when, uint32_t untilRefreshNs, uint64_t seq, uint32_t reportedFlags) { +void CPresentationProtocol::onPresented(SP pMonitor, timespec* when, uint32_t untilRefreshNs, uint64_t seq, uint32_t reportedFlags) { timespec now; timespec* presentedAt = when; if (!presentedAt) { @@ -119,7 +121,7 @@ void CPresentationProtocol::onPresented(CMonitor* pMonitor, timespec* when, uint continue; for (auto const& data : m_vQueue) { - if (!data->surface || data->surface != feedback->surface) + if (!data->surface || data->surface != feedback->surface || (data->pMonitor && data->pMonitor != pMonitor)) continue; feedback->sendQueued(data, when, untilRefreshNs, seq, reportedFlags); @@ -129,7 +131,7 @@ void CPresentationProtocol::onPresented(CMonitor* pMonitor, timespec* when, uint } std::erase_if(m_vFeedbacks, [](const auto& other) { return !other->surface || other->done; }); - std::erase_if(m_vQueue, [pMonitor](const auto& other) { return !other->surface || other->pMonitor == pMonitor || !other->pMonitor; }); + std::erase_if(m_vQueue, [pMonitor](const auto& other) { return !other->surface || other->pMonitor == pMonitor || !other->pMonitor || other->done; }); } void CPresentationProtocol::queueData(SP data) { diff --git a/src/protocols/PresentationTime.hpp b/src/protocols/PresentationTime.hpp index 2c6ce3e9..06c71c9a 100644 --- a/src/protocols/PresentationTime.hpp +++ b/src/protocols/PresentationTime.hpp @@ -14,15 +14,17 @@ class CQueuedPresentationData { CQueuedPresentationData(SP surf); void setPresentationType(bool zeroCopy); - void attachMonitor(CMonitor* pMonitor); + void attachMonitor(SP pMonitor); void presented(); void discarded(); + bool done = false; + private: bool wasPresented = false; bool zeroCopy = false; - CMonitor* pMonitor = nullptr; + WP pMonitor; WP surface; DYNLISTENER(destroySurface); @@ -53,7 +55,7 @@ class CPresentationProtocol : public IWaylandProtocol { virtual void bindManager(wl_client* client, void* data, uint32_t ver, uint32_t id); - void onPresented(CMonitor* pMonitor, timespec* when, uint32_t untilRefreshNs, uint64_t seq, uint32_t reportedFlags); + void onPresented(SP pMonitor, timespec* when, uint32_t untilRefreshNs, uint64_t seq, uint32_t reportedFlags); void queueData(SP data); private: diff --git a/src/protocols/core/Compositor.cpp b/src/protocols/core/Compositor.cpp index f7f6dcda..37a4bdf1 100644 --- a/src/protocols/core/Compositor.cpp +++ b/src/protocols/core/Compositor.cpp @@ -509,7 +509,7 @@ void CWLSurfaceResource::updateCursorShm() { memcpy(shmData.data(), pixelData, bufLen); } -void CWLSurfaceResource::presentFeedback(timespec* when, CMonitor* pMonitor) { +void CWLSurfaceResource::presentFeedback(timespec* when, SP pMonitor) { frame(when); auto FEEDBACK = makeShared(self.lock()); FEEDBACK->attachMonitor(pMonitor); diff --git a/src/protocols/core/Compositor.hpp b/src/protocols/core/Compositor.hpp index a3245399..dc1c851f 100644 --- a/src/protocols/core/Compositor.hpp +++ b/src/protocols/core/Compositor.hpp @@ -124,7 +124,7 @@ class CWLSurfaceResource { void breadthfirst(std::function, const Vector2D&, void*)> fn, void* data); CRegion accumulateCurrentBufferDamage(); - void presentFeedback(timespec* when, CMonitor* pMonitor); + void presentFeedback(timespec* when, SP pMonitor); void lockPendingState(); void unlockPendingState(); diff --git a/src/render/Renderer.cpp b/src/render/Renderer.cpp index 2854a973..420f8d4c 100644 --- a/src/render/Renderer.cpp +++ b/src/render/Renderer.cpp @@ -185,7 +185,7 @@ static void renderSurface(SP surface, int x, int y, void* da if (windowBox.width <= 1 || windowBox.height <= 1) { if (!g_pHyprRenderer->m_bBlockSurfaceFeedback) { Debug::log(TRACE, "presentFeedback for invisible surface"); - surface->presentFeedback(RDATA->when, RDATA->pMonitor); + surface->presentFeedback(RDATA->when, RDATA->pMonitor->self.lock()); } return; // invisible @@ -240,7 +240,7 @@ static void renderSurface(SP surface, int x, int y, void* da } if (!g_pHyprRenderer->m_bBlockSurfaceFeedback) - surface->presentFeedback(RDATA->when, RDATA->pMonitor); + surface->presentFeedback(RDATA->when, RDATA->pMonitor->self.lock()); g_pHyprOpenGL->blend(true); From c5fd5771814958ad274ea9abb961fff621a35b9c Mon Sep 17 00:00:00 2001 From: Vaxry <43317083+vaxerski@users.noreply.github.com> Date: Fri, 30 Aug 2024 17:37:52 +0200 Subject: [PATCH 0347/2181] config: Add a window rule to render while unfocused (#7582) --- src/config/ConfigDescriptions.hpp | 6 +++ src/config/ConfigManager.cpp | 3 +- src/desktop/Window.cpp | 5 +++ src/desktop/Window.hpp | 1 + src/managers/eventLoop/EventLoopTimer.cpp | 4 ++ src/managers/eventLoop/EventLoopTimer.hpp | 1 + src/render/Renderer.cpp | 50 +++++++++++++++++++++++ src/render/Renderer.hpp | 4 ++ 8 files changed, 73 insertions(+), 1 deletion(-) diff --git a/src/config/ConfigDescriptions.hpp b/src/config/ConfigDescriptions.hpp index 73b995ae..73f3c9a3 100644 --- a/src/config/ConfigDescriptions.hpp +++ b/src/config/ConfigDescriptions.hpp @@ -1037,6 +1037,12 @@ inline static const std::vector CONFIG_OPTIONS = { .type = CONFIG_OPTION_BOOL, .data = SConfigOptionDescription::SBoolData{true}, }, + SConfigOptionDescription{ + .value = "misc:render_unfocused_fps", + .description = "the maximum limit for renderunfocused windows' fps in the background", + .type = CONFIG_OPTION_INT, + .data = SConfigOptionDescription::SRangeData{15, 1, 120}, + }, /* * binds: diff --git a/src/config/ConfigManager.cpp b/src/config/ConfigManager.cpp index f402958b..5940a6fe 100644 --- a/src/config/ConfigManager.cpp +++ b/src/config/ConfigManager.cpp @@ -357,6 +357,7 @@ CConfigManager::CConfigManager() { m_pConfig->addConfigValue("misc:exit_window_retains_fullscreen", Hyprlang::INT{0}); m_pConfig->addConfigValue("misc:initial_workspace_tracking", Hyprlang::INT{1}); m_pConfig->addConfigValue("misc:middle_click_paste", Hyprlang::INT{1}); + m_pConfig->addConfigValue("misc:render_unfocused_fps", Hyprlang::INT{15}); m_pConfig->addConfigValue("group:insert_after_current", Hyprlang::INT{1}); m_pConfig->addConfigValue("group:focus_removed_window", Hyprlang::INT{1}); @@ -2155,7 +2156,7 @@ std::optional CConfigManager::handleUnbind(const std::string& comma bool windowRuleValid(const std::string& RULE) { static const auto rules = std::unordered_set{ - "float", "fullscreen", "maximize", "noinitialfocus", "pin", "stayfocused", "tile", + "float", "fullscreen", "maximize", "noinitialfocus", "pin", "stayfocused", "tile", "renderunfocused", }; static const auto rulesPrefix = std::vector{ "animation", "bordercolor", "bordersize", "center", "fullscreenstate", "group", "idleinhibit", "maxsize", "minsize", "monitor", diff --git a/src/desktop/Window.cpp b/src/desktop/Window.cpp index 7623d45e..a9e389a6 100644 --- a/src/desktop/Window.cpp +++ b/src/desktop/Window.cpp @@ -757,6 +757,9 @@ void CWindow::applyDynamicRule(const SWindowRule& r) { if (m_sGroupData.pNextWindow.expired()) setHidden(false); } catch (std::exception& e) { Debug::log(ERR, "minsize rule \"{}\" failed with: {}", r.szRule, e.what()); } + } else if (r.szRule == "renderunfocused") { + m_sWindowData.renderUnfocused = CWindowOverridableVar(true, priority); + g_pHyprRenderer->addWindowToRenderUnfocused(m_pSelf.lock()); } } @@ -774,6 +777,8 @@ void CWindow::updateDynamicRules() { m_sWindowData.activeBorderColor.unset(PRIORITY_WINDOW_RULE); m_sWindowData.inactiveBorderColor.unset(PRIORITY_WINDOW_RULE); + m_sWindowData.renderUnfocused.unset(PRIORITY_WINDOW_RULE); + m_eIdleInhibitMode = IDLEINHIBIT_NONE; m_tags.removeDynamicTags(); diff --git a/src/desktop/Window.hpp b/src/desktop/Window.hpp index 7197ba26..d14248c5 100644 --- a/src/desktop/Window.hpp +++ b/src/desktop/Window.hpp @@ -174,6 +174,7 @@ struct SWindowData { CWindowOverridableVar syncFullscreen = true; CWindowOverridableVar tearing = false; CWindowOverridableVar xray = false; + CWindowOverridableVar renderUnfocused = false; CWindowOverridableVar rounding; CWindowOverridableVar borderSize; diff --git a/src/managers/eventLoop/EventLoopTimer.cpp b/src/managers/eventLoop/EventLoopTimer.cpp index d3cfdf8d..b8943b7c 100644 --- a/src/managers/eventLoop/EventLoopTimer.cpp +++ b/src/managers/eventLoop/EventLoopTimer.cpp @@ -49,3 +49,7 @@ float CEventLoopTimer::leftUs() { return std::chrono::duration_cast(*expires - std::chrono::steady_clock::now()).count(); } + +bool CEventLoopTimer::armed() { + return expires.has_value(); +} diff --git a/src/managers/eventLoop/EventLoopTimer.hpp b/src/managers/eventLoop/EventLoopTimer.hpp index ad7d3986..e5a8c5e3 100644 --- a/src/managers/eventLoop/EventLoopTimer.hpp +++ b/src/managers/eventLoop/EventLoopTimer.hpp @@ -16,6 +16,7 @@ class CEventLoopTimer { void cancel(); bool passed(); + bool armed(); float leftUs(); diff --git a/src/render/Renderer.cpp b/src/render/Renderer.cpp index 420f8d4c..c5866e4a 100644 --- a/src/render/Renderer.cpp +++ b/src/render/Renderer.cpp @@ -97,6 +97,44 @@ CHyprRenderer::CHyprRenderer() { m_pCursorTicker = wl_event_loop_add_timer(g_pCompositor->m_sWLEventLoop, cursorTicker, nullptr); wl_event_source_timer_update(m_pCursorTicker, 500); + + m_tRenderUnfocusedTimer = makeShared( + std::nullopt, + [this](SP self, void* data) { + static auto PFPS = CConfigValue("misc:render_unfocused_fps"); + + if (m_vRenderUnfocused.empty()) + return; + + timespec now; + clock_gettime(CLOCK_MONOTONIC, &now); + + bool dirty = false; + for (auto& w : m_vRenderUnfocused) { + if (!w) { + dirty = true; + continue; + } + + if (!w->m_pWLSurface || !w->m_pWLSurface->resource() || shouldRenderWindow(w.lock())) + continue; + + w->m_pWLSurface->resource()->frame(&now); + auto FEEDBACK = makeShared(w->m_pWLSurface->resource()); + FEEDBACK->attachMonitor(g_pCompositor->m_pLastMonitor.lock()); + FEEDBACK->discarded(); + PROTO::presentation->queueData(FEEDBACK); + } + + if (dirty) + std::erase_if(m_vRenderUnfocused, [](const auto& e) { return !e || !e->m_sWindowData.renderUnfocused.valueOr(false); }); + + if (!m_vRenderUnfocused.empty()) + m_tRenderUnfocusedTimer->updateTimeout(std::chrono::milliseconds(1000 / *PFPS)); + }, + nullptr); + + g_pEventLoopManager->addTimer(m_tRenderUnfocusedTimer); } CHyprRenderer::~CHyprRenderer() { @@ -2800,3 +2838,15 @@ SExplicitSyncSettings CHyprRenderer::getExplicitSyncSettings() { return settings; } + +void CHyprRenderer::addWindowToRenderUnfocused(PHLWINDOW window) { + static auto PFPS = CConfigValue("misc:render_unfocused_fps"); + + if (std::find(m_vRenderUnfocused.begin(), m_vRenderUnfocused.end(), window) != m_vRenderUnfocused.end()) + return; + + m_vRenderUnfocused.emplace_back(window); + + if (!m_tRenderUnfocusedTimer->armed()) + m_tRenderUnfocusedTimer->updateTimeout(std::chrono::milliseconds(1000 / *PFPS)); +} diff --git a/src/render/Renderer.hpp b/src/render/Renderer.hpp index d00c0a17..b730d589 100644 --- a/src/render/Renderer.hpp +++ b/src/render/Renderer.hpp @@ -13,6 +13,7 @@ class CWorkspace; class CWindow; class CInputPopup; class IHLBuffer; +class CEventLoopTimer; // TODO: add fuller damage tracking for updating only parts of a window enum DAMAGETRACKINGMODES { @@ -78,6 +79,7 @@ class CHyprRenderer { void makeEGLCurrent(); void unsetEGL(); SExplicitSyncSettings getExplicitSyncSettings(); + void addWindowToRenderUnfocused(PHLWINDOW window); // if RENDER_MODE_NORMAL, provided damage will be written to. // otherwise, it will be the one used. @@ -143,6 +145,8 @@ class CHyprRenderer { SP getOrCreateRenderbuffer(SP buffer, uint32_t fmt); std::vector> m_vRenderbuffers; + std::vector m_vRenderUnfocused; + SP m_tRenderUnfocusedTimer; friend class CHyprOpenGLImpl; friend class CToplevelExportFrame; From 76b82fdde7d3f38cb70db0bec3318a7fb6c27a0c Mon Sep 17 00:00:00 2001 From: Jan Beich Date: Sat, 31 Aug 2024 09:01:02 +0000 Subject: [PATCH 0348/2181] meson: explicitly specify path for find(1) (#7590) assets/install/meson.build:1:10: ERROR: Command `/bin/sh -c 'find -type f -not -name "*.build"'` failed with status 1. --- assets/install/meson.build | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/assets/install/meson.build b/assets/install/meson.build index 19b49638..1d4fb917 100644 --- a/assets/install/meson.build +++ b/assets/install/meson.build @@ -1,4 +1,4 @@ -globber = run_command('sh', '-c', 'find -type f -not -name "*.build"', check: true) +globber = run_command('sh', '-c', 'find . -type f -not -name "*.build"', check: true) files = globber.stdout().strip().split('\n') foreach file : files From 838ed87d6ffae0dbdc8a3ecaac2c8be006f6d053 Mon Sep 17 00:00:00 2001 From: Ikalco <73481042+ikalco@users.noreply.github.com> Date: Sat, 31 Aug 2024 08:07:52 -0500 Subject: [PATCH 0349/2181] renderer: minor direct scanout fixes (#7594) --- src/helpers/Monitor.cpp | 15 +++++++++++++++ src/helpers/Monitor.hpp | 3 ++- src/render/Renderer.cpp | 9 ++++++--- 3 files changed, 23 insertions(+), 4 deletions(-) diff --git a/src/helpers/Monitor.cpp b/src/helpers/Monitor.cpp index 685009fd..5b01d651 100644 --- a/src/helpers/Monitor.cpp +++ b/src/helpers/Monitor.cpp @@ -832,6 +832,21 @@ bool CMonitor::attemptDirectScanout() { // FIXME: make sure the buffer actually follows the available scanout dmabuf formats // and comes from the appropriate device. This may implode on multi-gpu!! + + const auto params = PSURFACE->current.buffer->buffer->dmabuf(); + // scanout buffer isn't dmabuf, so no scanout + if (!params.success) + return false; + + // entering into scanout, so save monitor format + if (lastScanout.expired()) + prevDrmFormat = drmFormat; + + if (drmFormat != params.format) { + output->state->setFormat(params.format); + drmFormat = params.format; + } + output->state->setBuffer(PSURFACE->current.buffer->buffer.lock()); output->state->setPresentationMode(tearingState.activelyTearing ? Aquamarine::eOutputPresentationMode::AQ_OUTPUT_PRESENTATION_IMMEDIATE : Aquamarine::eOutputPresentationMode::AQ_OUTPUT_PRESENTATION_VSYNC); diff --git a/src/helpers/Monitor.hpp b/src/helpers/Monitor.hpp index 01a5d28d..203cac90 100644 --- a/src/helpers/Monitor.hpp +++ b/src/helpers/Monitor.hpp @@ -100,7 +100,8 @@ class CMonitor { std::optional forceSize; SP currentMode; SP cursorSwapchain; - uint32_t drmFormat = DRM_FORMAT_INVALID; + uint32_t drmFormat = DRM_FORMAT_INVALID; + uint32_t prevDrmFormat = DRM_FORMAT_INVALID; bool dpmsStatus = true; bool vrrActive = false; // this can be TRUE even if VRR is not active in the case that this display does not support it. diff --git a/src/render/Renderer.cpp b/src/render/Renderer.cpp index c5866e4a..27fde129 100644 --- a/src/render/Renderer.cpp +++ b/src/render/Renderer.cpp @@ -1277,7 +1277,8 @@ void CHyprRenderer::renderMonitor(CMonitor* pMonitor) { pMonitor->lastScanout.reset(); // reset DRM format, make sure it's the one we want. - pMonitor->output->state->setFormat(pMonitor->drmFormat); + pMonitor->output->state->setFormat(pMonitor->prevDrmFormat); + pMonitor->drmFormat = pMonitor->prevDrmFormat; } } @@ -1978,7 +1979,8 @@ bool CHyprRenderer::applyMonitorRule(CMonitor* pMonitor, SMonitorRule* pMonitorR pMonitor->currentMode = nullptr; pMonitor->output->state->setFormat(DRM_FORMAT_XRGB8888); - pMonitor->drmFormat = DRM_FORMAT_XRGB8888; + pMonitor->prevDrmFormat = pMonitor->drmFormat; + pMonitor->drmFormat = DRM_FORMAT_XRGB8888; pMonitor->output->state->resetExplicitFences(); bool autoScale = false; @@ -2219,7 +2221,8 @@ bool CHyprRenderer::applyMonitorRule(CMonitor* pMonitor, SMonitorRule* pMonitorR for (auto const& fmt : formats[(int)!RULE->enable10bit]) { pMonitor->output->state->setFormat(fmt.second); - pMonitor->drmFormat = fmt.second; + pMonitor->prevDrmFormat = pMonitor->drmFormat; + pMonitor->drmFormat = fmt.second; if (!pMonitor->state.test()) { Debug::log(ERR, "output {} failed basic test on format {}", pMonitor->szName, fmt.first); From 10d7219807dd726d231e8df53a357018f5526432 Mon Sep 17 00:00:00 2001 From: NotAShelf Date: Sat, 31 Aug 2024 13:51:19 +0300 Subject: [PATCH 0350/2181] CI: clarify Nix CI jobs; disable on forked repositories --- .github/workflows/nix-build.yml | 4 +++- .github/workflows/nix-ci.yml | 4 ++-- .github/workflows/nix-update-inputs.yml | 3 ++- 3 files changed, 7 insertions(+), 4 deletions(-) diff --git a/.github/workflows/nix-build.yml b/.github/workflows/nix-build.yml index d0234498..ed0c2ae1 100644 --- a/.github/workflows/nix-build.yml +++ b/.github/workflows/nix-build.yml @@ -1,3 +1,5 @@ +name: Nix (Build) + on: workflow_call: secrets: @@ -25,6 +27,6 @@ jobs: - uses: cachix/cachix-action@v15 with: name: hyprland - authToken: '${{ secrets.CACHIX_AUTH_TOKEN }}' + authToken: "${{ secrets.CACHIX_AUTH_TOKEN }}" - run: nix build '.?submodules=1#${{ matrix.package }}' -L --extra-substituters "https://hyprland.cachix.org" diff --git a/.github/workflows/nix-ci.yml b/.github/workflows/nix-ci.yml index b25ed9aa..2f35337d 100644 --- a/.github/workflows/nix-ci.yml +++ b/.github/workflows/nix-ci.yml @@ -1,10 +1,10 @@ -name: Nix +name: Nix (CI) on: [push, pull_request, workflow_dispatch] jobs: update-inputs: - if: github.event_name == 'push' || github.event_name == 'workflow_dispatch' + if: (github.event_name == 'push' || github.event_name == 'workflow_dispatch') uses: ./.github/workflows/nix-update-inputs.yml secrets: inherit diff --git a/.github/workflows/nix-update-inputs.yml b/.github/workflows/nix-update-inputs.yml index 000900d9..a8f68f3b 100644 --- a/.github/workflows/nix-update-inputs.yml +++ b/.github/workflows/nix-update-inputs.yml @@ -1,4 +1,4 @@ -name: Nix +name: Nix (Update Inputs) on: workflow_call: @@ -8,6 +8,7 @@ on: jobs: update: + if: github.repository == 'hyprwm/Hyprland' name: inputs runs-on: ubuntu-latest steps: From cf6a1716ae719f9c59b1d175ca84a79015fab8e1 Mon Sep 17 00:00:00 2001 From: Vaxry Date: Sat, 31 Aug 2024 18:32:57 +0200 Subject: [PATCH 0351/2181] syncobj: wait for deadline instead of available avoids slow apps from lagging the desktop --- src/protocols/DRMSyncobj.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/protocols/DRMSyncobj.cpp b/src/protocols/DRMSyncobj.cpp index 4993f1a4..e0c90a3b 100644 --- a/src/protocols/DRMSyncobj.cpp +++ b/src/protocols/DRMSyncobj.cpp @@ -58,8 +58,8 @@ CDRMSyncobjSurfaceResource::CDRMSyncobjSurfaceResource(SPtimeline->check(pending.acquirePoint, DRM_SYNCOBJ_WAIT_FLAGS_WAIT_AVAILABLE); + // wait for the buffer to be released by the gpu before sending a commit to avoid lagging the desktop + auto materialized = pending.acquireTimeline->timeline->check(pending.acquirePoint, DRM_SYNCOBJ_WAIT_FLAGS_WAIT_DEADLINE); if (!materialized.has_value()) { LOGM(ERR, "Failed to check the acquire timeline"); resource->noMemory(); @@ -70,7 +70,7 @@ CDRMSyncobjSurfaceResource::CDRMSyncobjSurfaceResource(SPlockPendingState(); - pending.acquireTimeline->timeline->addWaiter([this]() { surface->unlockPendingState(); }, pending.acquirePoint, DRM_SYNCOBJ_WAIT_FLAGS_WAIT_AVAILABLE); + pending.acquireTimeline->timeline->addWaiter([this]() { surface->unlockPendingState(); }, pending.acquirePoint, DRM_SYNCOBJ_WAIT_FLAGS_WAIT_DEADLINE); }); listeners.surfaceCommit = surface->events.roleCommit.registerListener([this](std::any d) { From 1ac2fc3f7e538e47a5cb8fdef60d701987fe63ed Mon Sep 17 00:00:00 2001 From: Ikalco <73481042+ikalco@users.noreply.github.com> Date: Sat, 31 Aug 2024 14:07:23 -0500 Subject: [PATCH 0352/2181] protocols: destroy new xdgDialog protocol at right time (#7600) --- src/managers/ProtocolManager.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/src/managers/ProtocolManager.cpp b/src/managers/ProtocolManager.cpp index 2c421abe..6b6d5acf 100644 --- a/src/managers/ProtocolManager.cpp +++ b/src/managers/ProtocolManager.cpp @@ -221,6 +221,7 @@ CProtocolManager::~CProtocolManager() { PROTO::screencopy.reset(); PROTO::toplevelExport.reset(); PROTO::globalShortcuts.reset(); + PROTO::xdgDialog.reset(); PROTO::lease.reset(); PROTO::sync.reset(); From cac59fefecaefe34be45e65713d54676444f88a2 Mon Sep 17 00:00:00 2001 From: TheMical <85638851+TheMical@users.noreply.github.com> Date: Sat, 31 Aug 2024 15:43:02 -0400 Subject: [PATCH 0353/2181] data-device: Fix selection mismatch when wlr resets primary selection (#7598) --- src/protocols/DataDeviceWlr.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/protocols/DataDeviceWlr.cpp b/src/protocols/DataDeviceWlr.cpp index d2d06644..69e28772 100644 --- a/src/protocols/DataDeviceWlr.cpp +++ b/src/protocols/DataDeviceWlr.cpp @@ -133,7 +133,7 @@ CWLRDataDevice::CWLRDataDevice(SP resource_) : resourc auto source = sourceR ? CWLRDataSource::fromResource(sourceR) : CSharedPointer{}; if (!source) { LOGM(LOG, "wlr reset primary selection received"); - g_pSeatManager->setCurrentSelection(nullptr); + g_pSeatManager->setCurrentPrimarySelection(nullptr); return; } From a6315b0af4e417cf396649d9c5792d3c5420b713 Mon Sep 17 00:00:00 2001 From: Ikalco <73481042+ikalco@users.noreply.github.com> Date: Sat, 31 Aug 2024 14:55:08 -0500 Subject: [PATCH 0354/2181] core: fix crash on monitor removed with gammaControl (#7601) * fix crash on monitor removed with gammaControl * Update GammaControl.cpp --- src/protocols/GammaControl.cpp | 14 +++++++------- src/protocols/GammaControl.hpp | 2 +- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/src/protocols/GammaControl.cpp b/src/protocols/GammaControl.cpp index cb75a202..d7992981 100644 --- a/src/protocols/GammaControl.cpp +++ b/src/protocols/GammaControl.cpp @@ -17,7 +17,7 @@ CGammaControl::CGammaControl(SP resource_, wl_resource* out return; } - pMonitor = OUTPUTRES->monitor.get(); + pMonitor = OUTPUTRES->monitor; if (!pMonitor) { LOGM(ERR, "No CMonitor"); @@ -103,7 +103,7 @@ CGammaControl::CGammaControl(SP resource_, wl_resource* out resource->sendGammaSize(gammaSize); listeners.monitorDestroy = pMonitor->events.destroy.registerListener([this](std::any) { this->onMonitorDestroy(); }); - listeners.monitorDisconnect = pMonitor->events.destroy.registerListener([this](std::any) { this->onMonitorDestroy(); }); + listeners.monitorDisconnect = pMonitor->events.disconnect.registerListener([this](std::any) { this->onMonitorDestroy(); }); } CGammaControl::~CGammaControl() { @@ -119,7 +119,7 @@ bool CGammaControl::good() { } void CGammaControl::applyToMonitor() { - if (!pMonitor) + if (!pMonitor || !pMonitor->output) return; // ?? LOGM(LOG, "setting to monitor {}", pMonitor->szName); @@ -136,16 +136,16 @@ void CGammaControl::applyToMonitor() { pMonitor->output->state->setGammaLut({}); } - g_pHyprRenderer->damageMonitor(pMonitor); + g_pHyprRenderer->damageMonitor(pMonitor.get()); } CMonitor* CGammaControl::getMonitor() { - return pMonitor; + return pMonitor ? pMonitor.get() : nullptr; } void CGammaControl::onMonitorDestroy() { + LOGM(LOG, "Destroying gamma control for {}", pMonitor->szName); resource->sendFailed(); - pMonitor = nullptr; } CGammaControlProtocol::CGammaControlProtocol(const wl_interface* iface, const int& ver, const std::string& name) : IWaylandProtocol(iface, ver, name) { @@ -187,4 +187,4 @@ void CGammaControlProtocol::applyGammaToState(CMonitor* pMonitor) { g->applyToMonitor(); break; } -} \ No newline at end of file +} diff --git a/src/protocols/GammaControl.hpp b/src/protocols/GammaControl.hpp index 963eea5c..bbdc0139 100644 --- a/src/protocols/GammaControl.hpp +++ b/src/protocols/GammaControl.hpp @@ -20,7 +20,7 @@ class CGammaControl { private: SP resource; - CMonitor* pMonitor = nullptr; + WP pMonitor; size_t gammaSize = 0; bool gammaTableSet = false; std::vector gammaTable; // [r,g,b]+ From 4af9410dc2d0e241276a0797d3f3d276310d956e Mon Sep 17 00:00:00 2001 From: Tom Englund Date: Sun, 1 Sep 2024 12:04:28 +0200 Subject: [PATCH 0355/2181] xwm: read atom name from xcb (#7546) expand the debug trace logging by actually reading the atom name from xcb if not found in HYPRATOMS, will also print the proper atom for xcb internal ones and not just the HYPRATOMS ones. --- src/xwayland/XWM.cpp | 34 ++++++++++++++++++++++++---------- src/xwayland/XWM.hpp | 1 + 2 files changed, 25 insertions(+), 10 deletions(-) diff --git a/src/xwayland/XWM.cpp b/src/xwayland/XWM.cpp index b5762762..cb4d8f4d 100644 --- a/src/xwayland/XWM.cpp +++ b/src/xwayland/XWM.cpp @@ -158,18 +158,32 @@ static bool lookupParentExists(SP XSURF, SP return false; } +std::string CXWM::getAtomName(uint32_t atom) { + for (auto const& ha : HYPRATOMS) { + if (ha.second != atom) + continue; + + return ha.first; + } + + // Get the name of the atom + auto const atom_name_cookie = xcb_get_atom_name(connection, atom); + auto* atom_name_reply = xcb_get_atom_name_reply(connection, atom_name_cookie, NULL); + + if (!atom_name_reply) + return "Unknown"; + + auto const name_len = xcb_get_atom_name_name_length(atom_name_reply); + auto* name = xcb_get_atom_name_name(atom_name_reply); + free(atom_name_reply); + + return {name, name_len}; +} + void CXWM::readProp(SP XSURF, uint32_t atom, xcb_get_property_reply_t* reply) { std::string propName; - if (Debug::trace) { - propName = std::format("{}?", atom); - for (auto const& ha : HYPRATOMS) { - if (ha.second != atom) - continue; - - propName = ha.first; - break; - } - } + if (Debug::trace) + propName = getAtomName(atom); if (atom == XCB_ATOM_WM_CLASS) { size_t len = xcb_get_property_value_length(reply); diff --git a/src/xwayland/XWM.hpp b/src/xwayland/XWM.hpp index 7d6b63ed..59695720 100644 --- a/src/xwayland/XWM.hpp +++ b/src/xwayland/XWM.hpp @@ -119,6 +119,7 @@ class CXWM { std::string mimeFromAtom(xcb_atom_t atom); void setClipboardToWayland(SXSelection& sel); void getTransferData(SXSelection& sel); + std::string getAtomName(uint32_t atom); void readProp(SP XSURF, uint32_t atom, xcb_get_property_reply_t* reply); // From 5b1375141bd77c26023fb4a8dc087272be82849a Mon Sep 17 00:00:00 2001 From: Mihai Fufezan Date: Sun, 1 Sep 2024 17:18:50 +0300 Subject: [PATCH 0356/2181] flake.lock: update --- flake.lock | 18 +++++++++--------- nix/default.nix | 7 +++++-- 2 files changed, 14 insertions(+), 11 deletions(-) diff --git a/flake.lock b/flake.lock index b26cd5e3..a3f905d8 100644 --- a/flake.lock +++ b/flake.lock @@ -16,11 +16,11 @@ ] }, "locked": { - "lastModified": 1725016199, - "narHash": "sha256-2TMk7F2a27ZtOUW/bftkDyZKp3OQ71E5XnfKSUT8HZQ=", + "lastModified": 1725199881, + "narHash": "sha256-jsmipf/u1GFZE5tBUkr56CHMN6VpUWCAjfLIhvQijU0=", "owner": "hyprwm", "repo": "aquamarine", - "rev": "cff00196f0fcf734a2bf164eb0dfdb6e58c5c906", + "rev": "f8a687dd29ff019657498f1bd14da2fbbf0e604b", "type": "github" }, "original": { @@ -93,11 +93,11 @@ ] }, "locked": { - "lastModified": 1724174162, - "narHash": "sha256-fOOBLwil6M9QWMCiSULwjMQzrXhHXUnEqmjHX5ZHeVI=", + "lastModified": 1725188252, + "narHash": "sha256-yBH8c4GDaEAtBrh+BqIlrx5vp6gG/Gu8fQQK63KAQgs=", "owner": "hyprwm", "repo": "hyprlang", - "rev": "16e5c9465f04477d8a3dd48a0a26bf437986336c", + "rev": "c12ab785ce1982f82594aff03b3104c598186ddd", "type": "github" }, "original": { @@ -154,11 +154,11 @@ }, "nixpkgs": { "locked": { - "lastModified": 1724819573, - "narHash": "sha256-GnR7/ibgIH1vhoy8cYdmXE6iyZqKqFxQSVkFgosBh6w=", + "lastModified": 1725103162, + "narHash": "sha256-Ym04C5+qovuQDYL/rKWSR+WESseQBbNAe5DsXNx5trY=", "owner": "NixOS", "repo": "nixpkgs", - "rev": "71e91c409d1e654808b2621f28a327acfdad8dc2", + "rev": "12228ff1752d7b7624a54e9c1af4b222b3c1073b", "type": "github" }, "original": { diff --git a/nix/default.nix b/nix/default.nix index 64796a90..6a4979f1 100644 --- a/nix/default.nix +++ b/nix/default.nix @@ -89,6 +89,10 @@ assert lib.assertMsg (!hidpiXWayland) "The option `hidpiXWayland` has been remov DIRTY = lib.optionalString (commit == "") "dirty"; HASH = commit; + depsBuildBuild = [ + pkg-config + ]; + nativeBuildInputs = [ hyprwayland-scanner jq @@ -97,8 +101,7 @@ assert lib.assertMsg (!hidpiXWayland) "The option `hidpiXWayland` has been remov ninja pkg-config python3 # for udis86 - # re-add after https://github.com/NixOS/nixpkgs/pull/214906 hits nixos-unstable - # wayland-scanner + wayland-scanner ]; outputs = [ From 4b5b8a763073593ac48af3bdcf04cf65b219120b Mon Sep 17 00:00:00 2001 From: Mihai Fufezan Date: Sun, 1 Sep 2024 18:14:14 +0300 Subject: [PATCH 0357/2181] flake.lock: update xdph --- flake.lock | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/flake.lock b/flake.lock index a3f905d8..5921488e 100644 --- a/flake.lock +++ b/flake.lock @@ -209,11 +209,11 @@ ] }, "locked": { - "lastModified": 1724073926, - "narHash": "sha256-nWlUL43jOFHf+KW6Hqrx+W/r1XdXuDyb0wC/SrHsOu4=", + "lastModified": 1725203619, + "narHash": "sha256-Am4gwnu5q+6GFKQ3NnEkXeZYKIZ9rv9mRLk+DYqX9Zs=", "owner": "hyprwm", "repo": "xdg-desktop-portal-hyprland", - "rev": "a08ecbbf33598924e93542f737fc6169a26b481e", + "rev": "8e5ca2a299e95a3bdcdb84cfbe08f31b0690ecd5", "type": "github" }, "original": { From 7a24e564f43d4c24abf2ec4e5351007df2f8926c Mon Sep 17 00:00:00 2001 From: Mihai Fufezan Date: Sun, 1 Sep 2024 19:37:25 +0300 Subject: [PATCH 0358/2181] flake.lock: update xdph again --- flake.lock | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/flake.lock b/flake.lock index 5921488e..99a544e2 100644 --- a/flake.lock +++ b/flake.lock @@ -209,11 +209,11 @@ ] }, "locked": { - "lastModified": 1725203619, - "narHash": "sha256-Am4gwnu5q+6GFKQ3NnEkXeZYKIZ9rv9mRLk+DYqX9Zs=", + "lastModified": 1725203932, + "narHash": "sha256-VLULC/OnI+6R9KEP2OIGk+uLJJsfRlaLouZ5gyFd2+Y=", "owner": "hyprwm", "repo": "xdg-desktop-portal-hyprland", - "rev": "8e5ca2a299e95a3bdcdb84cfbe08f31b0690ecd5", + "rev": "2425e8f541525fa7409d9f26a8ffaf92a3767251", "type": "github" }, "original": { From 8bbeee20414bc0e20992076632d7d44ede443a1c Mon Sep 17 00:00:00 2001 From: Sungyoon Cho Date: Mon, 2 Sep 2024 01:44:33 +0900 Subject: [PATCH 0359/2181] textinput: send deactivate to ime on destory ti (#7614) --- src/managers/input/TextInput.cpp | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/src/managers/input/TextInput.cpp b/src/managers/input/TextInput.cpp index 5bff9fed..711935a7 100644 --- a/src/managers/input/TextInput.cpp +++ b/src/managers/input/TextInput.cpp @@ -23,9 +23,7 @@ void CTextInput::initCallbacks() { listeners.disable = INPUT->events.disable.registerListener([this](std::any p) { onDisabled(); }); listeners.commit = INPUT->events.onCommit.registerListener([this](std::any p) { onCommit(); }); listeners.destroy = INPUT->events.destroy.registerListener([this](std::any p) { - const auto INPUT = pV3Input.lock(); - if (INPUT && INPUT->current.enabled && focusedSurface()) - g_pInputManager->m_sIMERelay.deactivateIME(this); + g_pInputManager->m_sIMERelay.deactivateIME(this); g_pInputManager->m_sIMERelay.removeTextInput(this); }); } else { @@ -40,6 +38,7 @@ void CTextInput::initCallbacks() { listeners.destroy = INPUT->events.destroy.registerListener([this](std::any p) { listeners.surfaceUnmap.reset(); listeners.surfaceDestroy.reset(); + g_pInputManager->m_sIMERelay.deactivateIME(this); g_pInputManager->m_sIMERelay.removeTextInput(this); }); } @@ -192,7 +191,7 @@ wl_client* CTextInput::client() { } void CTextInput::commitStateToIME(SP ime) { - if (isV3()) { + if (isV3() && !pV3Input.expired()) { const auto INPUT = pV3Input.lock(); if (INPUT->current.surrounding.updated) @@ -202,7 +201,7 @@ void CTextInput::commitStateToIME(SP ime) { if (INPUT->current.contentType.updated) ime->textContentType(INPUT->current.contentType.hint, INPUT->current.contentType.purpose); - } else { + } else if (!pV1Input.expired()) { const auto INPUT = pV1Input.lock(); if (INPUT->pendingSurrounding.isPending) From 6934e7aa2b300bc4565855a4092fb34de8a9a8d2 Mon Sep 17 00:00:00 2001 From: Sungyoon Cho Date: Mon, 2 Sep 2024 04:33:31 +0900 Subject: [PATCH 0360/2181] textinput: don't deactivate ime if another ti is focused (#7617) --- src/managers/input/TextInput.cpp | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/managers/input/TextInput.cpp b/src/managers/input/TextInput.cpp index 711935a7..de14f1ab 100644 --- a/src/managers/input/TextInput.cpp +++ b/src/managers/input/TextInput.cpp @@ -23,8 +23,9 @@ void CTextInput::initCallbacks() { listeners.disable = INPUT->events.disable.registerListener([this](std::any p) { onDisabled(); }); listeners.commit = INPUT->events.onCommit.registerListener([this](std::any p) { onCommit(); }); listeners.destroy = INPUT->events.destroy.registerListener([this](std::any p) { - g_pInputManager->m_sIMERelay.deactivateIME(this); g_pInputManager->m_sIMERelay.removeTextInput(this); + if (!g_pInputManager->m_sIMERelay.getFocusedTextInput()) + g_pInputManager->m_sIMERelay.deactivateIME(this); }); } else { const auto INPUT = pV1Input.lock(); @@ -38,8 +39,9 @@ void CTextInput::initCallbacks() { listeners.destroy = INPUT->events.destroy.registerListener([this](std::any p) { listeners.surfaceUnmap.reset(); listeners.surfaceDestroy.reset(); - g_pInputManager->m_sIMERelay.deactivateIME(this); g_pInputManager->m_sIMERelay.removeTextInput(this); + if (!g_pInputManager->m_sIMERelay.getFocusedTextInput()) + g_pInputManager->m_sIMERelay.deactivateIME(this); }); } } From f7249bd3317e79b9cb1564f2497df510f7a166bb Mon Sep 17 00:00:00 2001 From: Jan Beich Date: Mon, 2 Sep 2024 14:51:56 +0200 Subject: [PATCH 0361/2181] CMake: drop duplicate -luuid after 5262292abc56 --- CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index dba14813..ef3f4021 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -266,7 +266,7 @@ function(protocolWayland) endfunction() target_link_libraries(Hyprland OpenGL::EGL OpenGL::GL Threads::Threads - libudis86 uuid) + libudis86) protocolnew("subprojects/hyprland-protocols/protocols" "hyprland-global-shortcuts-v1" true) From fa39df4731e200fab031f01757ded9920a1d473d Mon Sep 17 00:00:00 2001 From: Jan Beich Date: Mon, 2 Sep 2024 15:05:39 +0200 Subject: [PATCH 0362/2181] CMake: drop unused deps after 016da234d0e8 Found via LDFLAGS += -Wl,--as-needed (default in Meson). Some dependencies are only used by aquamarine. --- CMakeLists.txt | 10 ---------- 1 file changed, 10 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index ef3f4021..d8424d91 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -99,8 +99,6 @@ pkg_check_modules( xkbcommon uuid wayland-server - wayland-client - wayland-cursor wayland-protocols cairo pango @@ -109,11 +107,6 @@ pkg_check_modules( xcursor libdrm libinput - hwdata - libseat - libdisplay-info - libliftoff - libudev gbm gio-2.0 hyprlang>=0.3.2 @@ -200,14 +193,11 @@ else() REQUIRED IMPORTED_TARGET xcb - xwayland - xcb-util xcb-render xcb-xfixes xcb-icccm xcb-composite xcb-res - xcb-ewmh xcb-errors) target_link_libraries(Hyprland PkgConfig::xdeps) endif() From 8f9887b0c9443d6c2559feeec411daecb9780a97 Mon Sep 17 00:00:00 2001 From: Mihai Fufezan Date: Mon, 2 Sep 2024 23:09:44 +0300 Subject: [PATCH 0363/2181] Nix: remove unused dependencies --- nix/default.nix | 32 ++++++++------------------------ 1 file changed, 8 insertions(+), 24 deletions(-) diff --git a/nix/default.nix b/nix/default.nix index 6a4979f1..e1a348b0 100644 --- a/nix/default.nix +++ b/nix/default.nix @@ -9,33 +9,22 @@ aquamarine, binutils, cairo, - expat, - fribidi, git, - hwdata, hyprcursor, hyprlang, hyprutils, hyprwayland-scanner, jq, libGL, - libdatrie, - libdisplay-info, libdrm, libexecinfo, libinput, - libliftoff, - libselinux, - libsepol, - libthai, - libuuid, libxkbcommon, + libuuid, mesa, pango, pciutils, - pcre2, python3, - seatd, systemd, tomlplusplus, wayland, @@ -114,29 +103,25 @@ assert lib.assertMsg (!hidpiXWayland) "The option `hidpiXWayland` has been remov [ aquamarine cairo - expat - fribidi + # expat + # fribidi git - hwdata hyprcursor hyprlang hyprutils - libdatrie - libdisplay-info + # libdatrie libdrm libGL libinput - libliftoff - libselinux - libsepol - libthai + # libselinux + # libsepol + # libthai libuuid libxkbcommon mesa pango pciutils - pcre2 - seatd + # pcre2 tomlplusplus wayland wayland-protocols @@ -146,7 +131,6 @@ assert lib.assertMsg (!hidpiXWayland) "The option `hidpiXWayland` has been remov (lib.optionals enableXWayland [ xorg.libxcb xorg.libXdmcp - xorg.xcbutil xorg.xcbutilerrors xorg.xcbutilrenderutil xorg.xcbutilwm From 9b54342baa27d8de0460e1103ec4c3cc65592ed8 Mon Sep 17 00:00:00 2001 From: vaxerski Date: Tue, 3 Sep 2024 14:47:34 +0200 Subject: [PATCH 0364/2181] Revert "syncobj: wait for deadline instead of available" This reverts commit cf6a1716ae719f9c59b1d175ca84a79015fab8e1. Fixes #7628 --- src/protocols/DRMSyncobj.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/protocols/DRMSyncobj.cpp b/src/protocols/DRMSyncobj.cpp index e0c90a3b..4993f1a4 100644 --- a/src/protocols/DRMSyncobj.cpp +++ b/src/protocols/DRMSyncobj.cpp @@ -58,8 +58,8 @@ CDRMSyncobjSurfaceResource::CDRMSyncobjSurfaceResource(SPtimeline->check(pending.acquirePoint, DRM_SYNCOBJ_WAIT_FLAGS_WAIT_DEADLINE); + // wait for the acquire timeline to materialize + auto materialized = pending.acquireTimeline->timeline->check(pending.acquirePoint, DRM_SYNCOBJ_WAIT_FLAGS_WAIT_AVAILABLE); if (!materialized.has_value()) { LOGM(ERR, "Failed to check the acquire timeline"); resource->noMemory(); @@ -70,7 +70,7 @@ CDRMSyncobjSurfaceResource::CDRMSyncobjSurfaceResource(SPlockPendingState(); - pending.acquireTimeline->timeline->addWaiter([this]() { surface->unlockPendingState(); }, pending.acquirePoint, DRM_SYNCOBJ_WAIT_FLAGS_WAIT_DEADLINE); + pending.acquireTimeline->timeline->addWaiter([this]() { surface->unlockPendingState(); }, pending.acquirePoint, DRM_SYNCOBJ_WAIT_FLAGS_WAIT_AVAILABLE); }); listeners.surfaceCommit = surface->events.roleCommit.registerListener([this](std::any d) { From ea10592ad3c861ff2ce73ad7785bcb5a45a9e400 Mon Sep 17 00:00:00 2001 From: Maximilian Seidler <78690852+PaideiaDilemma@users.noreply.github.com> Date: Wed, 4 Sep 2024 10:23:29 +0000 Subject: [PATCH 0365/2181] input: don't emit idle activity when calling simulateMouseMovement (#7649) --- src/managers/input/InputManager.cpp | 6 +++--- src/managers/input/InputManager.hpp | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/managers/input/InputManager.cpp b/src/managers/input/InputManager.cpp index 78c9e437..d7ccc5e4 100644 --- a/src/managers/input/InputManager.cpp +++ b/src/managers/input/InputManager.cpp @@ -111,7 +111,7 @@ void CInputManager::simulateMouseMovement() { timespec now; clock_gettime(CLOCK_MONOTONIC, &now); m_vLastCursorPosFloored = m_vLastCursorPosFloored - Vector2D(1, 1); // hack: force the mouseMoveUnified to report without making this a refocus. - mouseMoveUnified(now.tv_sec * 1000 + now.tv_nsec / 10000000); + mouseMoveUnified(now.tv_sec * 1000 + now.tv_nsec / 10000000, false, true); } void CInputManager::sendMotionEventsToFocused() { @@ -132,7 +132,7 @@ void CInputManager::sendMotionEventsToFocused() { g_pSeatManager->setPointerFocus(g_pCompositor->m_pLastFocus.lock(), LOCAL); } -void CInputManager::mouseMoveUnified(uint32_t time, bool refocus) { +void CInputManager::mouseMoveUnified(uint32_t time, bool refocus, bool silent) { static auto PFOLLOWMOUSE = CConfigValue("input:follow_mouse"); static auto PMOUSEREFOCUS = CConfigValue("input:mouse_refocus"); static auto PMOUSEDPMS = CConfigValue("misc:mouse_move_enables_dpms"); @@ -171,7 +171,7 @@ void CInputManager::mouseMoveUnified(uint32_t time, bool refocus) { EMIT_HOOK_EVENT_CANCELLABLE("mouseMove", MOUSECOORDSFLOORED); - if (time) + if (time && !silent) PROTO::idle->onActivity(); m_vLastCursorPosFloored = MOUSECOORDSFLOORED; diff --git a/src/managers/input/InputManager.hpp b/src/managers/input/InputManager.hpp index ebf00b2d..70e4d40f 100644 --- a/src/managers/input/InputManager.hpp +++ b/src/managers/input/InputManager.hpp @@ -237,7 +237,7 @@ class CInputManager { uint32_t m_uiCapabilities = 0; - void mouseMoveUnified(uint32_t, bool refocus = false); + void mouseMoveUnified(uint32_t, bool refocus = false, bool silent = false); SP ensureTabletToolPresent(SP); From 027140b7315efe3cd2e7b78fa608bd36da839894 Mon Sep 17 00:00:00 2001 From: Maximilian Seidler <78690852+PaideiaDilemma@users.noreply.github.com> Date: Wed, 4 Sep 2024 15:59:00 +0000 Subject: [PATCH 0366/2181] sessionLock: ensure sls focus in some edge cases (#7647) * input: return early in mouseMoveUnified when the session is locked * sessionLock: make make a commit an opportunity to focus session lock surfaces * compositor: allow resetting focus when session is locked * input: remove redundant PMONITOR checks PMONITOR is checked above * input: check isSessionLocked earlier in mouseMoveUnified A bit of reordering, so that we don't call some stuff that is irrelevant when the session is locked --- src/Compositor.cpp | 2 +- src/managers/SessionLockManager.cpp | 3 ++ src/managers/input/InputManager.cpp | 56 ++++++++++++++--------------- 3 files changed, 32 insertions(+), 29 deletions(-) diff --git a/src/Compositor.cpp b/src/Compositor.cpp index eac75bd4..ba9ff96b 100644 --- a/src/Compositor.cpp +++ b/src/Compositor.cpp @@ -1117,7 +1117,7 @@ void CCompositor::focusSurface(SP pSurface, PHLWINDOW pWindo if (g_pSeatManager->state.keyboardFocus == pSurface || (pWindowOwner && g_pSeatManager->state.keyboardFocus == pWindowOwner->m_pWLSurface->resource())) return; // Don't focus when already focused on this. - if (g_pSessionLockManager->isSessionLocked() && !g_pSessionLockManager->isSurfaceSessionLock(pSurface)) + if (g_pSessionLockManager->isSessionLocked() && pSurface && !g_pSessionLockManager->isSurfaceSessionLock(pSurface)) return; if (g_pSeatManager->seatGrab && !g_pSeatManager->seatGrab->accepts(pSurface)) { diff --git a/src/managers/SessionLockManager.cpp b/src/managers/SessionLockManager.cpp index 7267b8f2..260a3992 100644 --- a/src/managers/SessionLockManager.cpp +++ b/src/managers/SessionLockManager.cpp @@ -30,6 +30,9 @@ SSessionLockSurface::SSessionLockSurface(SP surface_) : sur listeners.commit = surface_->events.commit.registerListener([this](std::any data) { const auto PMONITOR = g_pCompositor->getMonitorFromID(iMonitorID); + if (mapped && pWlrSurface != g_pCompositor->m_pLastFocus) + g_pInputManager->simulateMouseMovement(); + if (PMONITOR) g_pHyprRenderer->damageMonitor(PMONITOR); }); diff --git a/src/managers/input/InputManager.cpp b/src/managers/input/InputManager.cpp index d7ccc5e4..cdf7d615 100644 --- a/src/managers/input/InputManager.cpp +++ b/src/managers/input/InputManager.cpp @@ -153,7 +153,6 @@ void CInputManager::mouseMoveUnified(uint32_t time, bool refocus, bool silent) { Vector2D surfacePos = Vector2D(-1337, -1337); PHLWINDOW pFoundWindow; PHLLS pFoundLayerSurface; - SSessionLockSurface* pSessionLock = nullptr; if (!g_pCompositor->m_bReadyToProcess || g_pCompositor->m_bIsShuttingDown || g_pCompositor->m_bUnsafeState) return; @@ -190,17 +189,6 @@ void CInputManager::mouseMoveUnified(uint32_t time, bool refocus, bool silent) { if (!PMONITOR->solitaryClient.lock() && g_pHyprRenderer->shouldRenderCursor() && g_pPointerManager->softwareLockedFor(PMONITOR->self.lock()) && !skipFrameSchedule) g_pCompositor->scheduleFrameForMonitor(PMONITOR, Aquamarine::IOutput::AQ_SCHEDULE_CURSOR_MOVE); - PHLWINDOW forcedFocus = m_pForcedFocus.lock(); - - if (!forcedFocus) - forcedFocus = g_pCompositor->getForceFocus(); - - if (forcedFocus) { - pFoundWindow = forcedFocus; - surfacePos = pFoundWindow->m_vRealPosition.value(); - foundSurface = pFoundWindow->m_pWLSurface->resource(); - } - // constraints if (!g_pSeatManager->mouse.expired() && isConstrained()) { const auto SURF = CWLSurface::fromResource(g_pCompositor->m_pLastFocus.lock()); @@ -227,6 +215,33 @@ void CInputManager::mouseMoveUnified(uint32_t time, bool refocus, bool silent) { Debug::log(ERR, "BUG THIS: Null SURF/CONSTRAINT in mouse refocus. Ignoring constraints. {:x} {:x}", (uintptr_t)SURF.get(), (uintptr_t)CONSTRAINT.get()); } + if (PMONITOR != g_pCompositor->m_pLastMonitor.get() && (*PMOUSEFOCUSMON || refocus) && m_pForcedFocus.expired()) + g_pCompositor->setActiveMonitor(PMONITOR); + + if (g_pSessionLockManager->isSessionLocked()) { + const auto PSESSIONLOCKSURFACE = g_pSessionLockManager->getSessionLockSurfaceForMonitor(PMONITOR->ID); + surfacePos = PMONITOR->vecPosition; + + foundSurface = PSESSIONLOCKSURFACE ? PSESSIONLOCKSURFACE->surface->surface() : nullptr; + g_pCompositor->focusSurface(foundSurface); + + const auto SURFACELOCAL = mouseCoords - surfacePos; + g_pSeatManager->setPointerFocus(foundSurface, SURFACELOCAL); + g_pSeatManager->sendPointerMotion(time, SURFACELOCAL); + return; + } + + PHLWINDOW forcedFocus = m_pForcedFocus.lock(); + + if (!forcedFocus) + forcedFocus = g_pCompositor->getForceFocus(); + + if (forcedFocus) { + pFoundWindow = forcedFocus; + surfacePos = pFoundWindow->m_vRealPosition.value(); + foundSurface = pFoundWindow->m_pWLSurface->resource(); + } + // if we are holding a pointer button, // and we're not dnd-ing, don't refocus. Keep focus on last surface. if (!PROTO::data->dndActive() && !m_lCurrentlyHeldButtons.empty() && g_pCompositor->m_pLastFocus && g_pSeatManager->state.pointerFocus && !m_bHardInput) { @@ -258,19 +273,6 @@ void CInputManager::mouseMoveUnified(uint32_t time, bool refocus, bool silent) { g_pLayoutManager->getCurrentLayout()->onMouseMove(getMouseCoordsInternal()); - if (PMONITOR && PMONITOR != g_pCompositor->m_pLastMonitor.get() && (*PMOUSEFOCUSMON || refocus) && m_pForcedFocus.expired()) - g_pCompositor->setActiveMonitor(PMONITOR); - - if (g_pSessionLockManager->isSessionLocked()) { - pSessionLock = PMONITOR ? g_pSessionLockManager->getSessionLockSurfaceForMonitor(PMONITOR->ID) : nullptr; - - if (!pSessionLock) - return; - - foundSurface = pSessionLock->surface->surface(); - surfacePos = PMONITOR->vecPosition; - } - if (!foundSurface) foundSurface = g_pCompositor->vectorToLayerPopupSurface(mouseCoords, PMONITOR, &surfaceCoords, &pFoundLayerSurface); @@ -460,9 +462,7 @@ void CInputManager::mouseMoveUnified(uint32_t time, bool refocus, bool silent) { restoreCursorIconToApp(); } - if (pSessionLock != nullptr) - g_pCompositor->focusSurface(foundSurface); - else if (pFoundWindow) { + if (pFoundWindow) { // change cursor icon if hovering over border if (*PRESIZEONBORDER && *PRESIZECURSORICON) { if (!pFoundWindow->isFullscreen() && !pFoundWindow->hasPopupAt(mouseCoords)) { From bd6d6e7f3378c08fe48c179ba4ec3517fe10ae3f Mon Sep 17 00:00:00 2001 From: trianta <56975502+Trimutex@users.noreply.github.com> Date: Thu, 5 Sep 2024 11:26:46 -0500 Subject: [PATCH 0367/2181] xwayland: add option to enable/disable xwayland (#7633) * config: add xwayland enabled option to config * xwayland: use DISPLAY env variable for enable/disable of new launches * xwayland: close X11 windows when turning of XWayland * clang: format fix * config: add better description for xwayland:enabled * xwayland: close X11 windows on disable without crashes * xwayland: better method of informing CXWayland if xwayland enabled * xwayland: prevent closing non-xwayland windows on disable * misc: loop formatting --- src/Compositor.cpp | 2 +- src/Compositor.hpp | 1 + src/config/ConfigDescriptions.hpp | 6 ++++++ src/config/ConfigManager.cpp | 25 +++++++++++++++++++++++++ src/xwayland/Server.cpp | 3 ++- src/xwayland/XWM.cpp | 4 ++++ src/xwayland/XWayland.cpp | 9 +++++++-- src/xwayland/XWayland.hpp | 4 ++-- 8 files changed, 48 insertions(+), 6 deletions(-) diff --git a/src/Compositor.cpp b/src/Compositor.cpp index ba9ff96b..da659654 100644 --- a/src/Compositor.cpp +++ b/src/Compositor.cpp @@ -615,7 +615,7 @@ void CCompositor::initManagers(eManagersInitStage stage) { g_pCursorManager = std::make_unique(); Debug::log(LOG, "Starting XWayland"); - g_pXWayland = std::make_unique(); + g_pXWayland = std::make_unique(g_pCompositor->m_bEnableXwayland); } break; default: UNREACHABLE(); } diff --git a/src/Compositor.hpp b/src/Compositor.hpp index bb986f5e..f17d86e5 100644 --- a/src/Compositor.hpp +++ b/src/Compositor.hpp @@ -92,6 +92,7 @@ class CCompositor { CMonitor* m_pUnsafeOutput = nullptr; // fallback output for the unsafe state bool m_bIsShuttingDown = false; bool m_bDesktopEnvSet = false; + bool m_bEnableXwayland = true; // ------------------------------------------------- // diff --git a/src/config/ConfigDescriptions.hpp b/src/config/ConfigDescriptions.hpp index 73f3c9a3..00ebde6a 100644 --- a/src/config/ConfigDescriptions.hpp +++ b/src/config/ConfigDescriptions.hpp @@ -1115,6 +1115,12 @@ inline static const std::vector CONFIG_OPTIONS = { * xwayland: */ + SConfigOptionDescription{ + .value = "xwayland:enabled", + .description = "allow running applications using X11", + .type = CONFIG_OPTION_BOOL, + .data = SConfigOptionDescription::SBoolData{true}, + }, SConfigOptionDescription{ .value = "xwayland:use_nearest_neighbor", .description = "uses the nearest neighbor filtering for xwayland apps, making them pixelated rather than blurry", diff --git a/src/config/ConfigManager.cpp b/src/config/ConfigManager.cpp index 5940a6fe..740dbbdf 100644 --- a/src/config/ConfigManager.cpp +++ b/src/config/ConfigManager.cpp @@ -6,6 +6,7 @@ #include "config/ConfigValue.hpp" #include "helpers/varlist/VarList.hpp" #include "../protocols/LayerShell.hpp" +#include "../xwayland/XWayland.hpp" #include #include @@ -523,6 +524,7 @@ CConfigManager::CConfigManager() { m_pConfig->addConfigValue("gestures:workspace_swipe_touch", Hyprlang::INT{0}); m_pConfig->addConfigValue("gestures:workspace_swipe_touch_invert", Hyprlang::INT{0}); + m_pConfig->addConfigValue("xwayland:enabled", Hyprlang::INT{1}); m_pConfig->addConfigValue("xwayland:use_nearest_neighbor", Hyprlang::INT{1}); m_pConfig->addConfigValue("xwayland:force_zero_scaling", Hyprlang::INT{0}); @@ -860,6 +862,29 @@ void CConfigManager::postConfigReload(const Hyprlang::CParseResult& result) { ensureVRR(); } +#ifndef NO_XWAYLAND + const auto PENABLEXWAYLAND = std::any_cast(m_pConfig->getConfigValue("xwayland:enabled")); + // enable/disable xwayland usage + if (!isFirstLaunch) { + bool prevEnabledXwayland = g_pCompositor->m_bEnableXwayland; + if (PENABLEXWAYLAND != prevEnabledXwayland) { + g_pCompositor->m_bEnableXwayland = PENABLEXWAYLAND; + if (PENABLEXWAYLAND) { + Debug::log(LOG, "xwayland has been enabled"); + } else { + Debug::log(LOG, "xwayland has been disabled, cleaning up..."); + for (auto& w : g_pCompositor->m_vWindows) { + if (w->m_pXDGSurface || !w->m_bIsX11) + continue; + g_pCompositor->closeWindow(w); + } + } + g_pXWayland = std::make_unique(g_pCompositor->m_bEnableXwayland); + } + } else + g_pCompositor->m_bEnableXwayland = PENABLEXWAYLAND; +#endif + if (!isFirstLaunch && !g_pCompositor->m_bUnsafeState) refreshGroupBarGradients(); diff --git a/src/xwayland/Server.cpp b/src/xwayland/Server.cpp index 200bec70..f3bf5768 100644 --- a/src/xwayland/Server.cpp +++ b/src/xwayland/Server.cpp @@ -432,7 +432,8 @@ int CXWaylandServer::ready(int fd, uint32_t mask) { pipeSource = nullptr; // start the wm - g_pXWayland->pWM = std::make_unique(); + if (!g_pXWayland->pWM) + g_pXWayland->pWM = std::make_unique(); g_pCursorManager->setXWaylandCursor(); diff --git a/src/xwayland/XWM.cpp b/src/xwayland/XWM.cpp index cb4d8f4d..e8e2258a 100644 --- a/src/xwayland/XWM.cpp +++ b/src/xwayland/XWM.cpp @@ -890,6 +890,10 @@ CXWM::~CXWM() { if (eventSource) wl_event_source_remove(eventSource); + + for (auto const& sr : surfaces) { + sr->events.destroy.emit(); + } } void CXWM::setActiveWindow(xcb_window_t window) { diff --git a/src/xwayland/XWayland.cpp b/src/xwayland/XWayland.cpp index 8d45fa63..8cdb1fca 100644 --- a/src/xwayland/XWayland.cpp +++ b/src/xwayland/XWayland.cpp @@ -1,12 +1,17 @@ #include "XWayland.hpp" #include "../debug/Log.hpp" -CXWayland::CXWayland() { +CXWayland::CXWayland(const bool enabled) { #ifndef NO_XWAYLAND Debug::log(LOG, "Starting up the XWayland server"); pServer = std::make_unique(); + if (!enabled) { + unsetenv("DISPLAY"); + return; + } + if (!pServer->create()) { Debug::log(ERR, "XWayland failed to start: it will not work."); return; @@ -25,4 +30,4 @@ void CXWayland::setCursor(unsigned char* pixData, uint32_t stride, const Vector2 pWM->setCursor(pixData, stride, size, hotspot); #endif -} \ No newline at end of file +} diff --git a/src/xwayland/XWayland.hpp b/src/xwayland/XWayland.hpp index 40c0ba65..96253d19 100644 --- a/src/xwayland/XWayland.hpp +++ b/src/xwayland/XWayland.hpp @@ -17,7 +17,7 @@ class CXWM; class CXWayland { public: - CXWayland(); + CXWayland(const bool enabled); #ifndef NO_XWAYLAND std::unique_ptr pServer; @@ -126,4 +126,4 @@ inline std::unordered_map HYPRATOMS = { HYPRATOM("DELETE"), HYPRATOM("TEXT"), HYPRATOM("INCR"), -}; \ No newline at end of file +}; From 4a42c5ed20a6852e5e51c0f3893024f3b5c03500 Mon Sep 17 00:00:00 2001 From: Parola Marco Date: Thu, 5 Sep 2024 18:29:33 +0200 Subject: [PATCH 0368/2181] config: Add a variable to prevent groups from merging after being dragged (#7650) * config: Add a variable to prevent groups from merging after being dragged * Fixed code style for [f777f028] --- src/config/ConfigDescriptions.hpp | 6 ++++++ src/config/ConfigManager.cpp | 1 + src/desktop/Window.cpp | 6 +++++- 3 files changed, 12 insertions(+), 1 deletion(-) diff --git a/src/config/ConfigDescriptions.hpp b/src/config/ConfigDescriptions.hpp index 00ebde6a..44b5ee4a 100644 --- a/src/config/ConfigDescriptions.hpp +++ b/src/config/ConfigDescriptions.hpp @@ -742,6 +742,12 @@ inline static const std::vector CONFIG_OPTIONS = { .type = CONFIG_OPTION_BOOL, .data = SConfigOptionDescription::SBoolData{true}, }, + SConfigOptionDescription{ + .value = "group:merge_groups_on_drag", + .description = "whether window groups can be dragged into other groups", + .type = CONFIG_OPTION_BOOL, + .data = SConfigOptionDescription::SBoolData{true}, + }, SConfigOptionDescription{ .value = "general:col.border_active", .description = "border color for inactive windows", diff --git a/src/config/ConfigManager.cpp b/src/config/ConfigManager.cpp index 740dbbdf..b16b7747 100644 --- a/src/config/ConfigManager.cpp +++ b/src/config/ConfigManager.cpp @@ -362,6 +362,7 @@ CConfigManager::CConfigManager() { m_pConfig->addConfigValue("group:insert_after_current", Hyprlang::INT{1}); m_pConfig->addConfigValue("group:focus_removed_window", Hyprlang::INT{1}); + m_pConfig->addConfigValue("group:merge_groups_on_drag", Hyprlang::INT{1}); m_pConfig->addConfigValue("group:groupbar:enabled", Hyprlang::INT{1}); m_pConfig->addConfigValue("group:groupbar:font_family", {STRVAL_EMPTY}); m_pConfig->addConfigValue("group:groupbar:font_size", Hyprlang::INT{8}); diff --git a/src/desktop/Window.cpp b/src/desktop/Window.cpp index a9e389a6..cc5b48af 100644 --- a/src/desktop/Window.cpp +++ b/src/desktop/Window.cpp @@ -951,12 +951,16 @@ int CWindow::getGroupSize() { } bool CWindow::canBeGroupedInto(PHLWINDOW pWindow) { + static auto ALLOWGROUPMERGE = CConfigValue("group:merge_groups_on_drag"); + bool isGroup = m_sGroupData.pNextWindow; + bool disallowDragIntoGroup = g_pInputManager->m_bWasDraggingWindow && isGroup && !bool(*ALLOWGROUPMERGE); return !g_pKeybindManager->m_bGroupsLocked // global group lock disengaged && ((m_eGroupRules & GROUP_INVADE && m_bFirstMap) // window ignore local group locks, or || (!pWindow->getGroupHead()->m_sGroupData.locked // target unlocked && !(m_sGroupData.pNextWindow.lock() && getGroupHead()->m_sGroupData.locked))) // source unlocked or isn't group && !m_sGroupData.deny // source is not denied entry - && !(m_eGroupRules & GROUP_BARRED && m_bFirstMap); // group rule doesn't prevent adding window + && !(m_eGroupRules & GROUP_BARRED && m_bFirstMap) // group rule doesn't prevent adding window + && !disallowDragIntoGroup; // config allows groups to be merged } PHLWINDOW CWindow::getGroupWindowByIndex(int index) { From c80457be02e7b75b590e025708fad38d84c99026 Mon Sep 17 00:00:00 2001 From: Mihai Fufezan Date: Sun, 21 Jul 2024 20:54:57 +0300 Subject: [PATCH 0369/2181] nix: add COMMITS var --- nix/default.nix | 3 ++- nix/overlays.nix | 1 + 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/nix/default.nix b/nix/default.nix index e1a348b0..1c6a0113 100644 --- a/nix/default.nix +++ b/nix/default.nix @@ -39,6 +39,7 @@ wrapRuntimeDeps ? true, version ? "git", commit, + revCount, date, # deprecated flags enableNvidiaPatches ? false, @@ -73,7 +74,7 @@ assert lib.assertMsg (!hidpiXWayland) "The option `hidpiXWayland` has been remov sed -i "s#@PREFIX@/##g" hyprland.pc.in ''; - COMMITS = commit; + COMMITS = revCount; DATE = date; DIRTY = lib.optionalString (commit == "") "dirty"; HASH = commit; diff --git a/nix/overlays.nix b/nix/overlays.nix index 36206f46..d6e078fa 100644 --- a/nix/overlays.nix +++ b/nix/overlays.nix @@ -34,6 +34,7 @@ in { stdenv = final.gcc14Stdenv; version = "${version}+date=${date}_${self.shortRev or "dirty"}"; commit = self.rev or ""; + revCount = self.sourceInfo.revCount or ""; inherit date; }; hyprland-unwrapped = final.hyprland.override {wrapRuntimeDeps = false;}; From 727f1b54cd1ba48774092a5d54acc0e55f3ffe0f Mon Sep 17 00:00:00 2001 From: Sungyoon Cho Date: Fri, 6 Sep 2024 04:04:23 +0900 Subject: [PATCH 0370/2181] textinput: fix ime activation in some edge cases (#7660) * textinput: clear ti3 state when focused surface gets destroyed * textinput: send enter to newly created ti in focus --- src/managers/input/TextInput.cpp | 46 +++++++++++++++++++++++--------- src/protocols/TextInputV3.cpp | 13 +++++---- 2 files changed, 40 insertions(+), 19 deletions(-) diff --git a/src/managers/input/TextInput.cpp b/src/managers/input/TextInput.cpp index de14f1ab..4c2e326a 100644 --- a/src/managers/input/TextInput.cpp +++ b/src/managers/input/TextInput.cpp @@ -23,10 +23,15 @@ void CTextInput::initCallbacks() { listeners.disable = INPUT->events.disable.registerListener([this](std::any p) { onDisabled(); }); listeners.commit = INPUT->events.onCommit.registerListener([this](std::any p) { onCommit(); }); listeners.destroy = INPUT->events.destroy.registerListener([this](std::any p) { + listeners.surfaceUnmap.reset(); + listeners.surfaceDestroy.reset(); g_pInputManager->m_sIMERelay.removeTextInput(this); if (!g_pInputManager->m_sIMERelay.getFocusedTextInput()) g_pInputManager->m_sIMERelay.deactivateIME(this); }); + + if (!g_pCompositor->m_pLastFocus.expired() && g_pCompositor->m_pLastFocus->client() == INPUT->client()) + enter(g_pCompositor->m_pLastFocus.lock()); } else { const auto INPUT = pV1Input.lock(); @@ -72,15 +77,19 @@ void CTextInput::onDisabled() { return; } - if (!focusedSurface()) - return; - if (!isV3()) leave(); listeners.surfaceUnmap.reset(); listeners.surfaceDestroy.reset(); + if (!focusedSurface()) + return; + + const auto PFOCUSEDTI = g_pInputManager->m_sIMERelay.getFocusedTextInput(); + if (!PFOCUSEDTI || PFOCUSEDTI != this) + return; + g_pInputManager->m_sIMERelay.deactivateIME(this); } @@ -104,12 +113,12 @@ void CTextInput::setFocusedSurface(SP pSurface) { pFocusedSurface = pSurface; - listeners.surfaceUnmap.reset(); - listeners.surfaceDestroy.reset(); - if (!pSurface) return; + listeners.surfaceUnmap.reset(); + listeners.surfaceDestroy.reset(); + listeners.surfaceUnmap = pSurface->events.unmap.registerListener([this](std::any d) { Debug::log(LOG, "Unmap TI owner1"); @@ -118,6 +127,12 @@ void CTextInput::setFocusedSurface(SP pSurface) { pFocusedSurface.reset(); listeners.surfaceUnmap.reset(); listeners.surfaceDestroy.reset(); + + if (isV3() && !pV3Input.expired() && pV3Input->current.enabled) + pV3Input->current.enabled = false; + + if (!g_pInputManager->m_sIMERelay.getFocusedTextInput()) + g_pInputManager->m_sIMERelay.deactivateIME(this); }); listeners.surfaceDestroy = pSurface->events.destroy.registerListener([this](std::any d) { @@ -128,6 +143,12 @@ void CTextInput::setFocusedSurface(SP pSurface) { pFocusedSurface.reset(); listeners.surfaceUnmap.reset(); listeners.surfaceDestroy.reset(); + + if (isV3() && !pV3Input.expired() && pV3Input->current.enabled) + pV3Input->current.enabled = false; + + if (!g_pInputManager->m_sIMERelay.getFocusedTextInput()) + g_pInputManager->m_sIMERelay.deactivateIME(this); }); } @@ -142,10 +163,8 @@ void CTextInput::enter(SP pSurface) { if (pSurface == focusedSurface()) return; - if (focusedSurface()) { + if (focusedSurface()) leave(); - setFocusedSurface(nullptr); - } enterLocks++; if (enterLocks != 1) { @@ -173,11 +192,14 @@ void CTextInput::leave() { enterLocks = 0; } - if (isV3() && focusedSurface()) + if (isV3()) { pV3Input->leave(focusedSurface()); - else if (focusedSurface() && pV1Input) { + if (pV3Input->current.enabled) { + pV3Input->current.enabled = false; + onDisabled(); + } + } else pV1Input->leave(); - } setFocusedSurface(nullptr); diff --git a/src/protocols/TextInputV3.cpp b/src/protocols/TextInputV3.cpp index 99d799f3..42dc659e 100644 --- a/src/protocols/TextInputV3.cpp +++ b/src/protocols/TextInputV3.cpp @@ -24,10 +24,9 @@ CTextInputV3::CTextInputV3(SP resource_) : resource(resource_) current = pending; serial++; - if (wasEnabled && !current.enabled) { - current.reset(); + if (wasEnabled && !current.enabled) events.disable.emit(); - } else if (!wasEnabled && current.enabled) + else if (!wasEnabled && current.enabled) events.enable.emit(); else events.onCommit.emit(); @@ -53,12 +52,12 @@ CTextInputV3::CTextInputV3(SP resource_) : resource(resource_) pending.box.cursorBox = {x, y, w, h}; }); - resource->setEnable([this](CZwpTextInputV3* r) { pending.enabled = true; }); - - resource->setDisable([this](CZwpTextInputV3* r) { - pending.enabled = false; + resource->setEnable([this](CZwpTextInputV3* r) { pending.reset(); + pending.enabled = true; }); + + resource->setDisable([this](CZwpTextInputV3* r) { pending.enabled = false; }); } CTextInputV3::~CTextInputV3() { From 0fad7a0bb03d4181901952a0df620d42ab6bbe4d Mon Sep 17 00:00:00 2001 From: Sungyoon Cho Date: Fri, 6 Sep 2024 08:54:01 +0900 Subject: [PATCH 0371/2181] workspacerules: fix on-created-empty window focus (#7657) --- src/desktop/Workspace.cpp | 2 +- src/managers/KeybindManager.cpp | 32 ++++++++++++++++++++------------ src/managers/KeybindManager.hpp | 3 ++- 3 files changed, 23 insertions(+), 14 deletions(-) diff --git a/src/desktop/Workspace.cpp b/src/desktop/Workspace.cpp index 35fc5727..2d92659c 100644 --- a/src/desktop/Workspace.cpp +++ b/src/desktop/Workspace.cpp @@ -51,7 +51,7 @@ void CWorkspace::init(PHLWORKSPACE self) { if (self->m_bWasCreatedEmpty) if (auto cmd = WORKSPACERULE.onCreatedEmptyRunCmd) - g_pKeybindManager->spawn(*cmd); + g_pKeybindManager->spawnWithRules(*cmd, self); g_pEventManager->postEvent({"createworkspace", m_szName}); g_pEventManager->postEvent({"createworkspacev2", std::format("{},{}", m_iID, m_szName)}); diff --git a/src/managers/KeybindManager.cpp b/src/managers/KeybindManager.cpp index 7ee5ae7e..2db9f375 100644 --- a/src/managers/KeybindManager.cpp +++ b/src/managers/KeybindManager.cpp @@ -34,7 +34,7 @@ using namespace Hyprutils::String; #include #endif -static std::vector> getHyprlandLaunchEnv() { +static std::vector> getHyprlandLaunchEnv(PHLWORKSPACE pInitialWorkspace) { static auto PINITIALWSTRACKING = CConfigValue("misc:initial_workspace_tracking"); if (!*PINITIALWSTRACKING || g_pConfigManager->isLaunchingExecOnce) @@ -46,11 +46,15 @@ static std::vector> getHyprlandLaunchEnv() { std::vector> result; - result.push_back(std::make_pair<>( - "HL_INITIAL_WORKSPACE_TOKEN", - g_pTokenManager->registerNewToken( - SInitialWorkspaceToken{{}, PMONITOR->activeSpecialWorkspace ? PMONITOR->activeSpecialWorkspace->getConfigName() : PMONITOR->activeWorkspace->getConfigName()}, - std::chrono::months(1337)))); + if (!pInitialWorkspace) { + if (PMONITOR->activeSpecialWorkspace) + pInitialWorkspace = PMONITOR->activeSpecialWorkspace; + else + pInitialWorkspace = PMONITOR->activeWorkspace; + } + + result.push_back(std::make_pair<>("HL_INITIAL_WORKSPACE_TOKEN", + g_pTokenManager->registerNewToken(SInitialWorkspaceToken{{}, pInitialWorkspace->getConfigName()}, std::chrono::months(1337)))); return result; } @@ -846,8 +850,12 @@ bool CKeybindManager::handleInternalKeybinds(xkb_keysym_t keysym) { } // Dispatchers - SDispatchResult CKeybindManager::spawn(std::string args) { + const uint64_t PROC = spawnWithRules(args, nullptr); + return {.success = PROC > 0, .error = std::format("Failed to start process {}", args)}; +} + +uint64_t CKeybindManager::spawnWithRules(std::string args, PHLWORKSPACE pInitialWorkspace) { args = trim(args); @@ -859,7 +867,7 @@ SDispatchResult CKeybindManager::spawn(std::string args) { args = args.substr(args.find_first_of(']') + 1); } - const uint64_t PROC = spawnRawProc(args); + const uint64_t PROC = spawnRawProc(args, pInitialWorkspace); if (!RULES.empty()) { const auto RULESLIST = CVarList(RULES, 0, ';'); @@ -871,18 +879,18 @@ SDispatchResult CKeybindManager::spawn(std::string args) { Debug::log(LOG, "Applied {} rule arguments for exec.", RULESLIST.size()); } - return {.success = PROC > 0, .error = std::format("Failed to start process {}", args)}; + return PROC; } SDispatchResult CKeybindManager::spawnRaw(std::string args) { - const uint64_t PROC = spawnRawProc(args); + const uint64_t PROC = spawnRawProc(args, nullptr); return {.success = PROC > 0, .error = std::format("Failed to start process {}", args)}; } -uint64_t CKeybindManager::spawnRawProc(std::string args) { +uint64_t CKeybindManager::spawnRawProc(std::string args, PHLWORKSPACE pInitialWorkspace) { Debug::log(LOG, "Executing {}", args); - const auto HLENV = getHyprlandLaunchEnv(); + const auto HLENV = getHyprlandLaunchEnv(pInitialWorkspace); int socket[2]; if (pipe(socket) != 0) { diff --git a/src/managers/KeybindManager.hpp b/src/managers/KeybindManager.hpp index d1f26c2c..bf3b049f 100644 --- a/src/managers/KeybindManager.hpp +++ b/src/managers/KeybindManager.hpp @@ -149,7 +149,8 @@ class CKeybindManager { static void moveWindowOutOfGroup(PHLWINDOW pWindow, const std::string& dir = ""); static void moveWindowIntoGroup(PHLWINDOW pWindow, PHLWINDOW pWindowInDirection); static void switchToWindow(PHLWINDOW PWINDOWTOCHANGETO); - static uint64_t spawnRawProc(std::string); + static uint64_t spawnRawProc(std::string, PHLWORKSPACE pInitialWorkspace); + static uint64_t spawnWithRules(std::string, PHLWORKSPACE pInitialWorkspace); // -------------- Dispatchers -------------- // static SDispatchResult killActive(std::string); From 4988e00b1d72edb8ca8e87eecdbed8c2ecc6a7dc Mon Sep 17 00:00:00 2001 From: Maximilian Seidler <78690852+PaideiaDilemma@users.noreply.github.com> Date: Thu, 5 Sep 2024 23:58:57 +0000 Subject: [PATCH 0372/2181] input: move idle notify to input handlers (#7659) * Revert "input: don't emit idle activity when calling simulateMouseMovement (#7649)" This reverts commit ea10592ad3c861ff2ce73ad7785bcb5a45a9e400. * input: move idle notify calls to input event listeners * input: don't post idle activity when keyboard is not enabled --- src/managers/PointerManager.cpp | 39 +++++++++++++++++++++++++++++ src/managers/input/InputManager.cpp | 19 ++++++-------- src/managers/input/InputManager.hpp | 2 +- src/managers/input/Tablets.cpp | 9 ------- src/managers/input/Touch.cpp | 3 --- 5 files changed, 48 insertions(+), 24 deletions(-) diff --git a/src/managers/PointerManager.cpp b/src/managers/PointerManager.cpp index f0f74428..ce9ea4a4 100644 --- a/src/managers/PointerManager.cpp +++ b/src/managers/PointerManager.cpp @@ -3,6 +3,7 @@ #include "../config/ConfigValue.hpp" #include "../protocols/PointerGestures.hpp" #include "../protocols/FractionalScale.hpp" +#include "../protocols/IdleNotify.hpp" #include "../protocols/core/Compositor.hpp" #include "../protocols/core/Seat.hpp" #include "eventLoop/EventLoopManager.hpp" @@ -833,24 +834,32 @@ void CPointerManager::attachPointer(SP pointer) { auto E = std::any_cast(e); g_pInputManager->onMouseMoved(E); + + PROTO::idle->onActivity(); }); listener->motionAbsolute = pointer->pointerEvents.motionAbsolute.registerListener([this] (std::any e) { auto E = std::any_cast(e); g_pInputManager->onMouseWarp(E); + + PROTO::idle->onActivity(); }); listener->button = pointer->pointerEvents.button.registerListener([this] (std::any e) { auto E = std::any_cast(e); g_pInputManager->onMouseButton(E); + + PROTO::idle->onActivity(); }); listener->axis = pointer->pointerEvents.axis.registerListener([this] (std::any e) { auto E = std::any_cast(e); g_pInputManager->onMouseWheel(E); + + PROTO::idle->onActivity(); }); listener->frame = pointer->pointerEvents.frame.registerListener([this] (std::any e) { @@ -861,48 +870,64 @@ void CPointerManager::attachPointer(SP pointer) { auto E = std::any_cast(e); g_pInputManager->onSwipeBegin(E); + + PROTO::idle->onActivity(); }); listener->swipeEnd = pointer->pointerEvents.swipeEnd.registerListener([this] (std::any e) { auto E = std::any_cast(e); g_pInputManager->onSwipeEnd(E); + + PROTO::idle->onActivity(); }); listener->swipeUpdate = pointer->pointerEvents.swipeUpdate.registerListener([this] (std::any e) { auto E = std::any_cast(e); g_pInputManager->onSwipeUpdate(E); + + PROTO::idle->onActivity(); }); listener->pinchBegin = pointer->pointerEvents.pinchBegin.registerListener([this] (std::any e) { auto E = std::any_cast(e); PROTO::pointerGestures->pinchBegin(E.timeMs, E.fingers); + + PROTO::idle->onActivity(); }); listener->pinchEnd = pointer->pointerEvents.pinchEnd.registerListener([this] (std::any e) { auto E = std::any_cast(e); PROTO::pointerGestures->pinchEnd(E.timeMs, E.cancelled); + + PROTO::idle->onActivity(); }); listener->pinchUpdate = pointer->pointerEvents.pinchUpdate.registerListener([this] (std::any e) { auto E = std::any_cast(e); PROTO::pointerGestures->pinchUpdate(E.timeMs, E.delta, E.scale, E.rotation); + + PROTO::idle->onActivity(); }); listener->holdBegin = pointer->pointerEvents.holdBegin.registerListener([this] (std::any e) { auto E = std::any_cast(e); PROTO::pointerGestures->holdBegin(E.timeMs, E.fingers); + + PROTO::idle->onActivity(); }); listener->holdEnd = pointer->pointerEvents.holdEnd.registerListener([this] (std::any e) { auto E = std::any_cast(e); PROTO::pointerGestures->holdEnd(E.timeMs, E.cancelled); + + PROTO::idle->onActivity(); }); // clang-format on @@ -926,18 +951,24 @@ void CPointerManager::attachTouch(SP touch) { auto E = std::any_cast(e); g_pInputManager->onTouchDown(E); + + PROTO::idle->onActivity(); }); listener->up = touch->touchEvents.up.registerListener([this] (std::any e) { auto E = std::any_cast(e); g_pInputManager->onTouchUp(E); + + PROTO::idle->onActivity(); }); listener->motion = touch->touchEvents.motion.registerListener([this] (std::any e) { auto E = std::any_cast(e); g_pInputManager->onTouchMove(E); + + PROTO::idle->onActivity(); }); listener->cancel = touch->touchEvents.cancel.registerListener([this] (std::any e) { @@ -969,24 +1000,32 @@ void CPointerManager::attachTablet(SP tablet) { auto E = std::any_cast(e); g_pInputManager->onTabletAxis(E); + + PROTO::idle->onActivity(); }); listener->proximity = tablet->tabletEvents.proximity.registerListener([this] (std::any e) { auto E = std::any_cast(e); g_pInputManager->onTabletProximity(E); + + PROTO::idle->onActivity(); }); listener->tip = tablet->tabletEvents.tip.registerListener([this] (std::any e) { auto E = std::any_cast(e); g_pInputManager->onTabletTip(E); + + PROTO::idle->onActivity(); }); listener->button = tablet->tabletEvents.button.registerListener([this] (std::any e) { auto E = std::any_cast(e); g_pInputManager->onTabletButton(E); + + PROTO::idle->onActivity(); }); // clang-format on diff --git a/src/managers/input/InputManager.cpp b/src/managers/input/InputManager.cpp index cdf7d615..66ca4eb2 100644 --- a/src/managers/input/InputManager.cpp +++ b/src/managers/input/InputManager.cpp @@ -111,7 +111,7 @@ void CInputManager::simulateMouseMovement() { timespec now; clock_gettime(CLOCK_MONOTONIC, &now); m_vLastCursorPosFloored = m_vLastCursorPosFloored - Vector2D(1, 1); // hack: force the mouseMoveUnified to report without making this a refocus. - mouseMoveUnified(now.tv_sec * 1000 + now.tv_nsec / 10000000, false, true); + mouseMoveUnified(now.tv_sec * 1000 + now.tv_nsec / 10000000); } void CInputManager::sendMotionEventsToFocused() { @@ -132,7 +132,7 @@ void CInputManager::sendMotionEventsToFocused() { g_pSeatManager->setPointerFocus(g_pCompositor->m_pLastFocus.lock(), LOCAL); } -void CInputManager::mouseMoveUnified(uint32_t time, bool refocus, bool silent) { +void CInputManager::mouseMoveUnified(uint32_t time, bool refocus) { static auto PFOLLOWMOUSE = CConfigValue("input:follow_mouse"); static auto PMOUSEREFOCUS = CConfigValue("input:mouse_refocus"); static auto PMOUSEDPMS = CConfigValue("misc:mouse_move_enables_dpms"); @@ -170,9 +170,6 @@ void CInputManager::mouseMoveUnified(uint32_t time, bool refocus, bool silent) { EMIT_HOOK_EVENT_CANCELLABLE("mouseMove", MOUSECOORDSFLOORED); - if (time && !silent) - PROTO::idle->onActivity(); - m_vLastCursorPosFloored = MOUSECOORDSFLOORED; const auto PMONITOR = g_pCompositor->getMonitorFromCursor(); @@ -531,8 +528,6 @@ void CInputManager::mouseMoveUnified(uint32_t time, bool refocus, bool silent) { void CInputManager::onMouseButton(IPointer::SButtonEvent e) { EMIT_HOOK_EVENT_CANCELLABLE("mouseButton", e); - PROTO::idle->onActivity(); - m_tmrLastCursorMovement.reset(); if (e.state == WL_POINTER_BUTTON_STATE_PRESSED) { @@ -767,8 +762,6 @@ void CInputManager::onMouseWheel(IPointer::SAxisEvent e) { bool passEvent = g_pKeybindManager->onAxisEvent(e); - PROTO::idle->onActivity(); - if (!passEvent) return; @@ -883,6 +876,9 @@ void CInputManager::setupKeyboard(SP keeb) { auto PKEEB = ((IKeyboard*)owner)->self.lock(); onKeyboardKey(data, PKEEB); + + if (PKEEB->enabled) + PROTO::idle->onActivity(); }, keeb.get()); @@ -891,6 +887,9 @@ void CInputManager::setupKeyboard(SP keeb) { auto PKEEB = ((IKeyboard*)owner)->self.lock(); onKeyboardMod(PKEEB); + + if (PKEEB->enabled) + PROTO::idle->onActivity(); }, keeb.get()); @@ -1292,8 +1291,6 @@ void CInputManager::onKeyboardKey(std::any event, SP pKeyboard) { auto e = std::any_cast(event); - PROTO::idle->onActivity(); - if (passEvent) { const auto IME = m_sIMERelay.m_pIME.lock(); diff --git a/src/managers/input/InputManager.hpp b/src/managers/input/InputManager.hpp index 70e4d40f..ebf00b2d 100644 --- a/src/managers/input/InputManager.hpp +++ b/src/managers/input/InputManager.hpp @@ -237,7 +237,7 @@ class CInputManager { uint32_t m_uiCapabilities = 0; - void mouseMoveUnified(uint32_t, bool refocus = false, bool silent = false); + void mouseMoveUnified(uint32_t, bool refocus = false); SP ensureTabletToolPresent(SP); diff --git a/src/managers/input/Tablets.cpp b/src/managers/input/Tablets.cpp index f33937e8..9f80726e 100644 --- a/src/managers/input/Tablets.cpp +++ b/src/managers/input/Tablets.cpp @@ -1,6 +1,5 @@ #include "InputManager.hpp" #include "../../Compositor.hpp" -#include "../../protocols/IdleNotify.hpp" #include "../../protocols/Tablet.hpp" #include "../../devices/Tablet.hpp" #include "../../managers/PointerManager.hpp" @@ -155,8 +154,6 @@ void CInputManager::onTabletAxis(CTablet::SAxisEvent e) { if (e.updatedAxes & (CTablet::eTabletToolAxes::HID_TABLET_TOOL_AXIS_TILT_X | CTablet::eTabletToolAxes::HID_TABLET_TOOL_AXIS_TILT_Y)) PROTO::tablet->tilt(PTOOL, PTOOL->tilt); - - PROTO::idle->onActivity(); } void CInputManager::onTabletTip(CTablet::STipEvent e) { @@ -171,8 +168,6 @@ void CInputManager::onTabletTip(CTablet::STipEvent e) { PROTO::tablet->up(PTOOL); PTOOL->isDown = e.in; - - PROTO::idle->onActivity(); } void CInputManager::onTabletButton(CTablet::SButtonEvent e) { @@ -184,8 +179,6 @@ void CInputManager::onTabletButton(CTablet::SButtonEvent e) { PTOOL->buttonsDown.push_back(e.button); else std::erase(PTOOL->buttonsDown, e.button); - - PROTO::idle->onActivity(); } void CInputManager::onTabletProximity(CTablet::SProximityEvent e) { @@ -201,8 +194,6 @@ void CInputManager::onTabletProximity(CTablet::SProximityEvent e) { simulateMouseMovement(); refocusTablet(PTAB, PTOOL); } - - PROTO::idle->onActivity(); } void CInputManager::newTablet(SP pDevice) { diff --git a/src/managers/input/Touch.cpp b/src/managers/input/Touch.cpp index 40af4b1e..9b03168e 100644 --- a/src/managers/input/Touch.cpp +++ b/src/managers/input/Touch.cpp @@ -1,7 +1,6 @@ #include "InputManager.hpp" #include "../../Compositor.hpp" #include "../../config/ConfigValue.hpp" -#include "../../protocols/IdleNotify.hpp" #include "../../devices/ITouch.hpp" #include "../SeatManager.hpp" @@ -78,8 +77,6 @@ void CInputManager::onTouchDown(ITouch::SDownEvent e) { return; // oops, nothing found. g_pSeatManager->sendTouchDown(m_sTouchData.touchFocusSurface.lock(), e.timeMs, e.touchID, local); - - PROTO::idle->onActivity(); } void CInputManager::onTouchUp(ITouch::SUpEvent e) { From b0fca6eaf00a2c5061f499c76ec8d60772b6a719 Mon Sep 17 00:00:00 2001 From: outfoxxed Date: Thu, 5 Sep 2024 17:03:12 -0700 Subject: [PATCH 0373/2181] input: kb focus mouse focused window if unset (#7666) Normally it shouldn't be possible to have mouse focus with no kb focus, but it does happen, and when it does this makes it considerably less annoying. --- src/managers/input/InputManager.cpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/managers/input/InputManager.cpp b/src/managers/input/InputManager.cpp index 66ca4eb2..f1035c82 100644 --- a/src/managers/input/InputManager.cpp +++ b/src/managers/input/InputManager.cpp @@ -505,6 +505,9 @@ void CInputManager::mouseMoveUnified(uint32_t time, bool refocus) { } } + if (g_pSeatManager->state.keyboardFocus == nullptr) + g_pCompositor->focusWindow(pFoundWindow, foundSurface); + m_bLastFocusOnLS = false; } else { if (*PRESIZEONBORDER && *PRESIZECURSORICON && m_eBorderIconDirection != BORDERICON_NONE) { From 0500213086f8402ccbdb2acb4748dbc6d22e21f6 Mon Sep 17 00:00:00 2001 From: outfoxxed Date: Fri, 6 Sep 2024 17:06:55 -0700 Subject: [PATCH 0374/2181] input: try to refocus a focusable window when seat grabs are reset (#7669) --- src/desktop/Popup.cpp | 7 +++++++ src/desktop/Popup.hpp | 23 ++++++++++++----------- src/managers/SeatManager.cpp | 31 +++++++++++++++++++++++++++++++ 3 files changed, 50 insertions(+), 11 deletions(-) diff --git a/src/desktop/Popup.cpp b/src/desktop/Popup.cpp index a4952ef7..9e254fa6 100644 --- a/src/desktop/Popup.cpp +++ b/src/desktop/Popup.cpp @@ -202,6 +202,13 @@ void CPopup::reposition() { m_pResource->applyPositioning(box, COORDS); } +SP CPopup::getT1Owner() { + if (m_pWindowOwner) + return m_pWindowOwner->m_pWLSurface; + else + return m_pLayerOwner->surface; +} + Vector2D CPopup::coordsRelativeToParent() { Vector2D offset; diff --git a/src/desktop/Popup.hpp b/src/desktop/Popup.hpp index eea3fb84..04996612 100644 --- a/src/desktop/Popup.hpp +++ b/src/desktop/Popup.hpp @@ -18,21 +18,22 @@ class CPopup { ~CPopup(); - Vector2D coordsRelativeToParent(); - Vector2D coordsGlobal(); + SP getT1Owner(); + Vector2D coordsRelativeToParent(); + Vector2D coordsGlobal(); - Vector2D size(); + Vector2D size(); - void onNewPopup(SP popup); - void onDestroy(); - void onMap(); - void onUnmap(); - void onCommit(bool ignoreSiblings = false); - void onReposition(); + void onNewPopup(SP popup); + void onDestroy(); + void onMap(); + void onUnmap(); + void onCommit(bool ignoreSiblings = false); + void onReposition(); - void recheckTree(); + void recheckTree(); - bool visible(); + bool visible(); // will also loop over this node void breadthfirst(std::function fn, void* data); diff --git a/src/managers/SeatManager.cpp b/src/managers/SeatManager.cpp index 3e4063f4..b40d6cad 100644 --- a/src/managers/SeatManager.cpp +++ b/src/managers/SeatManager.cpp @@ -6,6 +6,7 @@ #include "../protocols/core/Compositor.hpp" #include "../Compositor.hpp" #include "../devices/IKeyboard.hpp" +#include "wlr-layer-shell-unstable-v1.hpp" #include #include @@ -584,6 +585,36 @@ void CSeatManager::setGrab(SP grab) { auto oldGrab = seatGrab; seatGrab.reset(); g_pInputManager->refocus(); + + auto currentFocus = state.keyboardFocus.lock(); + auto refocus = !currentFocus; + + SP surf; + PHLLS layer; + + if (!refocus) { + surf = CWLSurface::fromResource(currentFocus); + layer = surf->getLayer(); + } + + if (!refocus && !layer) { + auto popup = surf->getPopup(); + if (popup) { + auto parent = popup->getT1Owner(); + layer = parent->getLayer(); + } + } + + if (!refocus && layer) + refocus = layer->interactivity == ZWLR_LAYER_SURFACE_V1_KEYBOARD_INTERACTIVITY_NONE; + + if (refocus) { + auto candidate = g_pCompositor->m_pLastWindow.lock(); + + if (candidate) + g_pCompositor->focusWindow(candidate); + } + if (oldGrab->onEnd) oldGrab->onEnd(); } From 5ca48231287d67e75a3f21dbdbc47d6dc65752c4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Darth=20=C5=A0=C4=8C!?= Date: Sat, 7 Sep 2024 17:14:23 +0200 Subject: [PATCH 0375/2181] config: Added default button mapping for xf86 keys (#7672) * Added default button mapping for laptop multimedia keys for volume and brightness * Added default button mapping for laptop multimedia keys for volume and brightness into example config --- example/hyprland.conf | 8 ++++++++ src/config/defaultConfig.hpp | 7 +++++++ 2 files changed, 15 insertions(+) diff --git a/example/hyprland.conf b/example/hyprland.conf index d55d25fd..76e5bcdb 100644 --- a/example/hyprland.conf +++ b/example/hyprland.conf @@ -228,6 +228,14 @@ bind = $mainMod, mouse_up, workspace, e-1 bindm = $mainMod, mouse:272, movewindow bindm = $mainMod, mouse:273, resizewindow +# Laptop multimedia keys for volume and LCD brightness +bindel = ,XF86AudioRaiseVolume, exec, wpctl set-volume @DEFAULT_AUDIO_SINK@ 5%+ +bindel = ,XF86AudioLowerVolume, exec, wpctl set-volume @DEFAULT_AUDIO_SINK@ 5%- +bindel = ,XF86AudioMute, exec, wpctl set-mute @DEFAULT_AUDIO_SINK@ toggle +bindel = ,XF86AudioMicMute, exec, wpctl set-mute @DEFAULT_AUDIO_SOURCE@ toggle +bindel = ,XF86MonBrightnessUp, exec, brightnessctl s 10%+ +bindel = ,XF86MonBrightnessDown, exec, brightnessctl s 10%- + ############################## ### WINDOWS AND WORKSPACES ### diff --git a/src/config/defaultConfig.hpp b/src/config/defaultConfig.hpp index 59265fee..b8d215d1 100644 --- a/src/config/defaultConfig.hpp +++ b/src/config/defaultConfig.hpp @@ -241,6 +241,13 @@ bind = $mainMod, mouse_up, workspace, e-1 bindm = $mainMod, mouse:272, movewindow bindm = $mainMod, mouse:273, resizewindow +# Laptop multimedia keys for volume and LCD brightness +bindel = ,XF86AudioRaiseVolume, exec, wpctl set-volume @DEFAULT_AUDIO_SINK@ 5%+ +bindel = ,XF86AudioLowerVolume, exec, wpctl set-volume @DEFAULT_AUDIO_SINK@ 5%- +bindel = ,XF86AudioMute, exec, wpctl set-mute @DEFAULT_AUDIO_SINK@ toggle +bindel = ,XF86AudioMicMute, exec, wpctl set-mute @DEFAULT_AUDIO_SOURCE@ toggle +bindel = ,XF86MonBrightnessUp, exec, brightnessctl s 10%+ +bindel = ,XF86MonBrightnessDown, exec, brightnessctl s 10%- ############################## ### WINDOWS AND WORKSPACES ### From 70add904c40924a761059e4009a8c0f1e43d76a3 Mon Sep 17 00:00:00 2001 From: trianta <56975502+Trimutex@users.noreply.github.com> Date: Sat, 7 Sep 2024 14:54:33 -0500 Subject: [PATCH 0376/2181] config: add exec-shutdown for running commands on shutdown (#7683) * config: add exec-shutdown for running commands on shutdown * compositor: delay stopping until after exec-shutdown --- src/Compositor.hpp | 1 + src/config/ConfigManager.cpp | 42 +++++++++++++++++++++++++++++++++ src/config/ConfigManager.hpp | 3 +++ src/managers/KeybindManager.cpp | 5 ++++ 4 files changed, 51 insertions(+) diff --git a/src/Compositor.hpp b/src/Compositor.hpp index f17d86e5..a57450f1 100644 --- a/src/Compositor.hpp +++ b/src/Compositor.hpp @@ -91,6 +91,7 @@ class CCompositor { bool m_bNextIsUnsafe = false; CMonitor* m_pUnsafeOutput = nullptr; // fallback output for the unsafe state bool m_bIsShuttingDown = false; + bool m_bFinalRequests = false; bool m_bDesktopEnvSet = false; bool m_bEnableXwayland = true; diff --git a/src/config/ConfigManager.cpp b/src/config/ConfigManager.cpp index b16b7747..852994a7 100644 --- a/src/config/ConfigManager.cpp +++ b/src/config/ConfigManager.cpp @@ -141,6 +141,18 @@ static Hyprlang::CParseResult handleExecOnce(const char* c, const char* v) { return result; } +static Hyprlang::CParseResult handleExecShutdown(const char* c, const char* v) { + const std::string VALUE = v; + const std::string COMMAND = c; + + const auto RESULT = g_pConfigManager->handleExecShutdown(COMMAND, VALUE); + + Hyprlang::CParseResult result; + if (RESULT.has_value()) + result.setError(RESULT.value().c_str()); + return result; +} + static Hyprlang::CParseResult handleMonitor(const char* c, const char* v) { const std::string VALUE = v; const std::string COMMAND = c; @@ -609,6 +621,7 @@ CConfigManager::CConfigManager() { // keywords m_pConfig->registerHandler(&::handleRawExec, "exec", {false}); m_pConfig->registerHandler(&::handleExecOnce, "exec-once", {false}); + m_pConfig->registerHandler(&::handleExecShutdown, "exec-shutdown", {false}); m_pConfig->registerHandler(&::handleMonitor, "monitor", {false}); m_pConfig->registerHandler(&::handleBind, "bind", {true}); m_pConfig->registerHandler(&::handleUnbind, "unbind", {false}); @@ -801,6 +814,7 @@ std::optional CConfigManager::resetHLConfig() { m_vDeclaredPlugins.clear(); m_dLayerRules.clear(); m_vFailedPluginConfigValues.clear(); + finalExecRequests.clear(); // paths configPaths.clear(); @@ -1398,6 +1412,24 @@ void CConfigManager::dispatchExecOnce() { g_pCompositor->performUserChecks(); } +void CConfigManager::dispatchExecShutdown() { + if (finalExecRequests.empty()) { + g_pCompositor->m_bFinalRequests = false; + return; + } + + g_pCompositor->m_bFinalRequests = true; + + for (auto const& c : finalExecRequests) { + handleExecShutdown("", c); + } + + finalExecRequests.clear(); + + // Actually exit now + handleExecShutdown("", "hyprctl dispatch exit"); +} + void CConfigManager::appendMonitorRule(const SMonitorRule& r) { m_dMonitorRules.emplace_back(r); } @@ -1700,6 +1732,16 @@ std::optional CConfigManager::handleExecOnce(const std::string& com return {}; } +std::optional CConfigManager::handleExecShutdown(const std::string& command, const std::string& args) { + if (g_pCompositor->m_bFinalRequests) { + g_pKeybindManager->spawn(args); + return {}; + } + + finalExecRequests.push_back(args); + return {}; +} + static bool parseModeLine(const std::string& modeline, drmModeModeInfo& mode) { auto args = CVarList(modeline, 0, 's'); diff --git a/src/config/ConfigManager.hpp b/src/config/ConfigManager.hpp index 4d087753..da450e39 100644 --- a/src/config/ConfigManager.hpp +++ b/src/config/ConfigManager.hpp @@ -192,6 +192,7 @@ class CConfigManager { // no-op when done. void dispatchExecOnce(); + void dispatchExecShutdown(); void performMonitorReload(); void appendMonitorRule(const SMonitorRule&); @@ -213,6 +214,7 @@ class CConfigManager { // keywords std::optional handleRawExec(const std::string&, const std::string&); std::optional handleExecOnce(const std::string&, const std::string&); + std::optional handleExecShutdown(const std::string&, const std::string&); std::optional handleMonitor(const std::string&, const std::string&); std::optional handleBind(const std::string&, const std::string&); std::optional handleUnbind(const std::string&, const std::string&); @@ -289,6 +291,7 @@ class CConfigManager { bool firstExecDispatched = false; bool m_bManualCrashInitiated = false; std::deque firstExecRequests; + std::deque finalExecRequests; std::vector> m_vFailedPluginConfigValues; // for plugin values of unloaded plugins std::string m_szConfigErrors = ""; diff --git a/src/managers/KeybindManager.cpp b/src/managers/KeybindManager.cpp index 2db9f375..2f593d74 100644 --- a/src/managers/KeybindManager.cpp +++ b/src/managers/KeybindManager.cpp @@ -1781,6 +1781,11 @@ SDispatchResult CKeybindManager::renameWorkspace(std::string args) { } SDispatchResult CKeybindManager::exitHyprland(std::string argz) { + g_pConfigManager->dispatchExecShutdown(); + + if (g_pCompositor->m_bFinalRequests) + return {}; // Exiting deferred until requests complete + g_pCompositor->stopCompositor(); return {}; } From 312411fc7073143a8bf1fc3ba23ef403b7d15eee Mon Sep 17 00:00:00 2001 From: Vaxry Date: Sun, 8 Sep 2024 00:46:16 +0100 Subject: [PATCH 0377/2181] windows: support size with pseudo tiled fixes #7690 --- src/events/Windows.cpp | 35 ++++++++++++++++++++++++++++++++--- 1 file changed, 32 insertions(+), 3 deletions(-) diff --git a/src/events/Windows.cpp b/src/events/Windows.cpp index 034920a2..544483b1 100644 --- a/src/events/Windows.cpp +++ b/src/events/Windows.cpp @@ -344,7 +344,8 @@ void Events::listener_mapWindow(void* owner, void* data) { Debug::log(LOG, "Rule size, applying to {}", PWINDOW); - PWINDOW->m_vRealSize = Vector2D(SIZEX, SIZEY); + PWINDOW->m_vRealSize = Vector2D(SIZEX, SIZEY); + PWINDOW->m_vPseudoSize = PWINDOW->m_vRealSize.goal(); g_pXWaylandManager->setWindowSize(PWINDOW, PWINDOW->m_vRealSize.goal()); PWINDOW->setHidden(false); @@ -449,8 +450,36 @@ void Events::listener_mapWindow(void* owner, void* data) { } else { g_pLayoutManager->getCurrentLayout()->onWindowCreated(PWINDOW); - // Set the pseudo size here too so that it doesnt end up being 0x0 - PWINDOW->m_vPseudoSize = PWINDOW->m_vRealSize.goal() - Vector2D(10, 10); + bool setPseudo = false; + + for (auto const& r : PWINDOW->m_vMatchedRules) { + if (r.szRule.starts_with("size")) { + try { + const auto VALUE = r.szRule.substr(r.szRule.find(' ') + 1); + const auto SIZEXSTR = VALUE.substr(0, VALUE.find(' ')); + const auto SIZEYSTR = VALUE.substr(VALUE.find(' ') + 1); + + const auto MAXSIZE = g_pXWaylandManager->getMaxSizeForWindow(PWINDOW); + + const auto SIZEX = SIZEXSTR == "max" ? + std::clamp(MAXSIZE.x, 20.0, PMONITOR->vecSize.x) : + (!SIZEXSTR.contains('%') ? std::stoi(SIZEXSTR) : std::stof(SIZEXSTR.substr(0, SIZEXSTR.length() - 1)) * 0.01 * PMONITOR->vecSize.x); + const auto SIZEY = SIZEYSTR == "max" ? + std::clamp(MAXSIZE.y, 20.0, PMONITOR->vecSize.y) : + (!SIZEYSTR.contains('%') ? std::stoi(SIZEYSTR) : std::stof(SIZEYSTR.substr(0, SIZEYSTR.length() - 1)) * 0.01 * PMONITOR->vecSize.y); + + Debug::log(LOG, "Rule size (tiled), applying to {}", PWINDOW); + + setPseudo = true; + PWINDOW->m_vPseudoSize = Vector2D(SIZEX, SIZEY); + + PWINDOW->setHidden(false); + } catch (...) { Debug::log(LOG, "Rule size failed, rule: {} -> {}", r.szRule, r.szValue); } + } + } + + if (!setPseudo) + PWINDOW->m_vPseudoSize = PWINDOW->m_vRealSize.goal() - Vector2D(10, 10); } const auto PFOCUSEDWINDOWPREV = g_pCompositor->m_pLastWindow.lock(); From 0f594732b063a90d44df8c5d402d658f27471dfe Mon Sep 17 00:00:00 2001 From: Vaxry Date: Sun, 8 Sep 2024 17:48:21 +0100 Subject: [PATCH 0378/2181] props: bump version to 0.43.0 --- VERSION | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/VERSION b/VERSION index 787ffc30..8298bb08 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -0.42.0 +0.43.0 From 07a21fdfa9e4d3827457dc3f08a4910703fedd35 Mon Sep 17 00:00:00 2001 From: diniamo <55629891+diniamo@users.noreply.github.com> Date: Sun, 8 Sep 2024 20:20:45 +0200 Subject: [PATCH 0379/2181] github(nix-build): switch to better nix installer, attempt at fixing hash mismatch (#7701) * github(nix-build): switch to DeterminateSystems/nix-installer-action * github(nix-build): switch to a direct git reference instead of cloning * github(nix-ci): attempt to fix CI for pull requests --- .github/workflows/nix-build.yml | 11 +++-------- .github/workflows/nix-ci.yml | 3 +-- 2 files changed, 4 insertions(+), 10 deletions(-) diff --git a/.github/workflows/nix-build.yml b/.github/workflows/nix-build.yml index ed0c2ae1..50823629 100644 --- a/.github/workflows/nix-build.yml +++ b/.github/workflows/nix-build.yml @@ -16,17 +16,12 @@ jobs: runs-on: ubuntu-latest steps: - - name: Clone repository - uses: actions/checkout@v4 - with: - ref: ${{ github.ref }} - submodules: recursive - - - uses: cachix/install-nix-action@v27 + - uses: DeterminateSystems/nix-installer-action@main - uses: DeterminateSystems/magic-nix-cache-action@main + - uses: cachix/cachix-action@v15 with: name: hyprland authToken: "${{ secrets.CACHIX_AUTH_TOKEN }}" - - run: nix build '.?submodules=1#${{ matrix.package }}' -L --extra-substituters "https://hyprland.cachix.org" + - run: nix build 'git+https://github.com/hyprwm/Hyprland?ref=${{ github.ref }}&submodules=1#${{ matrix.package }}' -L --extra-substituters "https://hyprland.cachix.org" diff --git a/.github/workflows/nix-ci.yml b/.github/workflows/nix-ci.yml index 2f35337d..75c19790 100644 --- a/.github/workflows/nix-ci.yml +++ b/.github/workflows/nix-ci.yml @@ -9,7 +9,6 @@ jobs: secrets: inherit build: - if: (github.event_name != 'pull_request' || github.event.pull_request.head.repo.fork) && !contains(needs.*.result, 'failure') - needs: update-inputs + if: (github.event_name != 'pull_request' || github.event.pull_request.head.repo.fork) uses: ./.github/workflows/nix-build.yml secrets: inherit From 05b48d48d9074041fd7987c36f04bdc1dafa575c Mon Sep 17 00:00:00 2001 From: Davide Conti Date: Sun, 8 Sep 2024 20:36:33 +0200 Subject: [PATCH 0380/2181] config: Limit max volume to 100% --- example/hyprland.conf | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/example/hyprland.conf b/example/hyprland.conf index 76e5bcdb..1179a274 100644 --- a/example/hyprland.conf +++ b/example/hyprland.conf @@ -229,7 +229,7 @@ bindm = $mainMod, mouse:272, movewindow bindm = $mainMod, mouse:273, resizewindow # Laptop multimedia keys for volume and LCD brightness -bindel = ,XF86AudioRaiseVolume, exec, wpctl set-volume @DEFAULT_AUDIO_SINK@ 5%+ +bindel = ,XF86AudioRaiseVolume, exec, wpctl set-volume -l 1 @DEFAULT_AUDIO_SINK@ 5%+ bindel = ,XF86AudioLowerVolume, exec, wpctl set-volume @DEFAULT_AUDIO_SINK@ 5%- bindel = ,XF86AudioMute, exec, wpctl set-mute @DEFAULT_AUDIO_SINK@ toggle bindel = ,XF86AudioMicMute, exec, wpctl set-mute @DEFAULT_AUDIO_SOURCE@ toggle From 6179b17903647d7659749f9f7c79bb9aff97a806 Mon Sep 17 00:00:00 2001 From: Aqa-Ib Date: Sun, 8 Sep 2024 22:12:01 +0200 Subject: [PATCH 0381/2181] github: improve issue template (#7699) * github: improve issue template Require to check that you have searched through open and closed issues before committing. * fix yaml syntax * clarify text * validation * revert validation * markdown * done --- .github/ISSUE_TEMPLATE/bug.yml | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/.github/ISSUE_TEMPLATE/bug.yml b/.github/ISSUE_TEMPLATE/bug.yml index e3e97bef..7d402904 100644 --- a/.github/ISSUE_TEMPLATE/bug.yml +++ b/.github/ISSUE_TEMPLATE/bug.yml @@ -2,12 +2,13 @@ name: Bug Report description: Something is not working right labels: ["bug"] body: - - type: markdown + - type: checkboxes attributes: - value: | - ## Before opening a new issue, please take a moment to search through the current open and closed issues to check if it already exists. - - --- + label: Already reported ? * + description: Before opening a new bug report, please take a moment to search through the current open and closed issues to check if it already exists. + options: + - label: I have searched the existing open and closed issues. + required: true - type: dropdown id: type From 7c4c402bd7f24241c096d809cc80408a469f15cb Mon Sep 17 00:00:00 2001 From: Richard Ayotte Date: Sun, 8 Sep 2024 17:04:07 -0400 Subject: [PATCH 0382/2181] config: include XF86Audio* key bindings to default cfg (#7695) --- example/hyprland.conf | 13 +++++++++---- src/config/defaultConfig.hpp | 14 ++++++++++---- 2 files changed, 19 insertions(+), 8 deletions(-) diff --git a/example/hyprland.conf b/example/hyprland.conf index 1179a274..4adc2d40 100644 --- a/example/hyprland.conf +++ b/example/hyprland.conf @@ -59,7 +59,7 @@ env = HYPRCURSOR_SIZE,24 # Refer to https://wiki.hyprland.org/Configuring/Variables/ # https://wiki.hyprland.org/Configuring/Variables/#general -general { +general { gaps_in = 5 gaps_out = 20 @@ -70,7 +70,7 @@ general { col.inactive_border = rgba(595959aa) # Set to true enable resizing windows by clicking and dragging on borders and gaps - resize_on_border = false + resize_on_border = false # Please see https://wiki.hyprland.org/Configuring/Tearing/ before you turn this on allow_tearing = false @@ -96,7 +96,7 @@ decoration { enabled = true size = 3 passes = 1 - + vibrancy = 0.1696 } } @@ -129,7 +129,7 @@ master { } # https://wiki.hyprland.org/Configuring/Variables/#misc -misc { +misc { force_default_wallpaper = -1 # Set to 0 or 1 to disable the anime mascot wallpapers disable_hyprland_logo = false # If true disables the random hyprland logo / anime girl background. :( } @@ -236,6 +236,11 @@ bindel = ,XF86AudioMicMute, exec, wpctl set-mute @DEFAULT_AUDIO_SOURCE@ toggle bindel = ,XF86MonBrightnessUp, exec, brightnessctl s 10%+ bindel = ,XF86MonBrightnessDown, exec, brightnessctl s 10%- +# Requires playerctl +bindl = , XF86AudioNext, exec, playerctl next +bindl = , XF86AudioPause, exec, playerctl play-pause +bindl = , XF86AudioPlay, exec, playerctl play-pause +bindl = , XF86AudioPrev, exec, playerctl previous ############################## ### WINDOWS AND WORKSPACES ### diff --git a/src/config/defaultConfig.hpp b/src/config/defaultConfig.hpp index b8d215d1..5843caa3 100644 --- a/src/config/defaultConfig.hpp +++ b/src/config/defaultConfig.hpp @@ -72,7 +72,7 @@ env = HYPRCURSOR_SIZE,24 # Refer to https://wiki.hyprland.org/Configuring/Variables/ # https://wiki.hyprland.org/Configuring/Variables/#general -general { +general { gaps_in = 5 gaps_out = 20 @@ -83,7 +83,7 @@ general { col.inactive_border = rgba(595959aa) # Set to true enable resizing windows by clicking and dragging on borders and gaps - resize_on_border = false + resize_on_border = false # Please see https://wiki.hyprland.org/Configuring/Tearing/ before you turn this on allow_tearing = false @@ -109,7 +109,7 @@ decoration { enabled = true size = 3 passes = 1 - + vibrancy = 0.1696 } } @@ -142,7 +142,7 @@ master { } # https://wiki.hyprland.org/Configuring/Variables/#misc -misc { +misc { force_default_wallpaper = -1 # Set to 0 or 1 to disable the anime mascot wallpapers disable_hyprland_logo = false # If true disables the random hyprland logo / anime girl background. :( } @@ -249,6 +249,12 @@ bindel = ,XF86AudioMicMute, exec, wpctl set-mute @DEFAULT_AUDIO_SOURCE@ toggle bindel = ,XF86MonBrightnessUp, exec, brightnessctl s 10%+ bindel = ,XF86MonBrightnessDown, exec, brightnessctl s 10%- +# Requires playerctl +bindl = , XF86AudioNext, exec, playerctl next +bindl = , XF86AudioPause, exec, playerctl play-pause +bindl = , XF86AudioPlay, exec, playerctl play-pause +bindl = , XF86AudioPrev, exec, playerctl previous + ############################## ### WINDOWS AND WORKSPACES ### ############################## From e1448732b3a463fc3aafc162d456a3db593253c8 Mon Sep 17 00:00:00 2001 From: Sungyoon Cho Date: Mon, 9 Sep 2024 17:58:44 +0900 Subject: [PATCH 0383/2181] tiv1: fix deleting first character (#7716) --- src/managers/input/TextInput.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/managers/input/TextInput.cpp b/src/managers/input/TextInput.cpp index 4c2e326a..d488f173 100644 --- a/src/managers/input/TextInput.cpp +++ b/src/managers/input/TextInput.cpp @@ -264,7 +264,7 @@ void CTextInput::updateIMEState(SP ime) { INPUT->preeditStyling(0, std::string(ime->current.preeditString.string).length(), ZWP_TEXT_INPUT_V1_PREEDIT_STYLE_HIGHLIGHT); INPUT->preeditString(pV1Input->serial, ime->current.preeditString.string.c_str(), ""); } else { - INPUT->preeditCursor(ime->current.preeditString.begin); + INPUT->preeditCursor(0); INPUT->preeditStyling(0, 0, ZWP_TEXT_INPUT_V1_PREEDIT_STYLE_HIGHLIGHT); INPUT->preeditString(pV1Input->serial, "", ""); } From 43e1415e715bb6c6c4ea722ba839210938ac2b07 Mon Sep 17 00:00:00 2001 From: davc0n Date: Mon, 9 Sep 2024 11:01:26 +0200 Subject: [PATCH 0384/2181] assets: Remove execute permission from lockdead.png (#7715) --- assets/install/lockdead.png | Bin 1 file changed, 0 insertions(+), 0 deletions(-) mode change 100755 => 100644 assets/install/lockdead.png diff --git a/assets/install/lockdead.png b/assets/install/lockdead.png old mode 100755 new mode 100644 From 04421063af2941c6e27e6dca2bdc2c387778a3a5 Mon Sep 17 00:00:00 2001 From: darkwater Date: Mon, 9 Sep 2024 11:10:08 +0200 Subject: [PATCH 0385/2181] config: add order rule for layers (#7697) --- src/config/ConfigManager.cpp | 2 +- src/desktop/LayerSurface.cpp | 5 +++++ src/desktop/LayerSurface.hpp | 1 + src/render/Renderer.cpp | 4 ++++ 4 files changed, 11 insertions(+), 1 deletion(-) diff --git a/src/config/ConfigManager.cpp b/src/config/ConfigManager.cpp index 852994a7..57cd2350 100644 --- a/src/config/ConfigManager.cpp +++ b/src/config/ConfigManager.cpp @@ -2239,7 +2239,7 @@ bool windowRuleValid(const std::string& RULE) { bool layerRuleValid(const std::string& RULE) { static const auto rules = std::unordered_set{"noanim", "blur", "blurpopups", "dimaround"}; - static const auto rulesPrefix = std::vector{"ignorealpha", "ignorezero", "xray", "animation"}; + static const auto rulesPrefix = std::vector{"ignorealpha", "ignorezero", "xray", "animation", "order"}; return rules.contains(RULE) || std::any_of(rulesPrefix.begin(), rulesPrefix.end(), [&RULE](auto prefix) { return RULE.starts_with(prefix); }); } diff --git a/src/desktop/LayerSurface.cpp b/src/desktop/LayerSurface.cpp index 155a2605..0e7e71b6 100644 --- a/src/desktop/LayerSurface.cpp +++ b/src/desktop/LayerSurface.cpp @@ -394,6 +394,11 @@ void CLayerSurface::applyRules() { } else if (rule.rule.starts_with("animation")) { CVarList vars{rule.rule, 2, 's'}; animationStyle = vars[1]; + } else if (rule.rule.starts_with("order")) { + CVarList vars{rule.rule, 2, 's'}; + try { + order = std::stoi(vars[1]); + } catch (...) { Debug::log(ERR, "Invalid value passed to order"); } } } } diff --git a/src/desktop/LayerSurface.hpp b/src/desktop/LayerSurface.hpp index 84935b34..e0f17039 100644 --- a/src/desktop/LayerSurface.hpp +++ b/src/desktop/LayerSurface.hpp @@ -55,6 +55,7 @@ class CLayerSurface { bool ignoreAlpha = false; float ignoreAlphaValue = 0.f; bool dimAround = false; + int64_t order = 0; std::optional animationStyle; diff --git a/src/render/Renderer.cpp b/src/render/Renderer.cpp index 27fde129..08bf76cb 100644 --- a/src/render/Renderer.cpp +++ b/src/render/Renderer.cpp @@ -1742,6 +1742,10 @@ void CHyprRenderer::arrangeLayersForMonitor(const MONITORID& monitor) { CBox usableArea = {PMONITOR->vecPosition.x, PMONITOR->vecPosition.y, PMONITOR->vecSize.x, PMONITOR->vecSize.y}; + for (auto& la : PMONITOR->m_aLayerSurfaceLayers) { + std::stable_sort(la.begin(), la.end(), [](const PHLLSREF& a, const PHLLSREF& b) { return a->order > b->order; }); + } + for (auto const& la : PMONITOR->m_aLayerSurfaceLayers) arrangeLayerArray(PMONITOR, la, true, &usableArea); From 9609b04ff9e63d16f9b2b9ecfdc732c2c7ebbf2f Mon Sep 17 00:00:00 2001 From: justmessingaround <69480361+DemonKingSwarn@users.noreply.github.com> Date: Mon, 9 Sep 2024 20:49:17 +0530 Subject: [PATCH 0386/2181] man: Fixed the man page to show the new information (#7713) * Update Hyprland.1.rst * Update Hyprland.1 --- docs/Hyprland.1 | 4 ++-- docs/Hyprland.1.rst | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/docs/Hyprland.1 b/docs/Hyprland.1 index 92061da2..465671e1 100644 --- a/docs/Hyprland.1 +++ b/docs/Hyprland.1 @@ -10,8 +10,8 @@ Hyprland - Dynamic tiling Wayland compositor \f[B]Hyprland\f[R] [\f[I]arg [...]\f[R]]. .SH DESCRIPTION .PP -\f[B]Hyprland\f[R] is a dynamic tiling Wayland compositor based on -wlroots that doesn\[aq]t sacrifice on its looks. +\f[B]Hyprland\f[R] is an independent, highly customizable, +dynamic tiling Wayland compositor that doesn\[aq]t sacrifice on its looks. .PP You can launch Hyprland by either going into a TTY and executing \f[B]Hyprland\f[R], or with a login manager. diff --git a/docs/Hyprland.1.rst b/docs/Hyprland.1.rst index c73b4343..e10d9c6a 100644 --- a/docs/Hyprland.1.rst +++ b/docs/Hyprland.1.rst @@ -14,8 +14,8 @@ SYNOPSIS DESCRIPTION =========== -**Hyprland** is a dynamic tiling Wayland compositor based on -wlroots that doesn't sacrifice on its looks. +**Hyprland** is an independent, highly customizable, +dynamic tiling Wayland compositor that doesn't sacrifice on its looks. You can launch Hyprland by either going into a TTY and executing **Hyprland**, or with a login manager. From 85da1a17d831e2b5db9c1c1e4ce6427d63563562 Mon Sep 17 00:00:00 2001 From: vaxerski Date: Mon, 9 Sep 2024 15:19:44 +0000 Subject: [PATCH 0387/2181] [gha] build man pages --- docs/Hyprland.1 | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/Hyprland.1 b/docs/Hyprland.1 index 465671e1..2d6e1444 100644 --- a/docs/Hyprland.1 +++ b/docs/Hyprland.1 @@ -10,8 +10,8 @@ Hyprland - Dynamic tiling Wayland compositor \f[B]Hyprland\f[R] [\f[I]arg [...]\f[R]]. .SH DESCRIPTION .PP -\f[B]Hyprland\f[R] is an independent, highly customizable, -dynamic tiling Wayland compositor that doesn\[aq]t sacrifice on its looks. +\f[B]Hyprland\f[R] is an independent, highly customizable, dynamic +tiling Wayland compositor that doesn\[aq]t sacrifice on its looks. .PP You can launch Hyprland by either going into a TTY and executing \f[B]Hyprland\f[R], or with a login manager. From 8237d7e1a4994f70636b2e91584775308f24a584 Mon Sep 17 00:00:00 2001 From: Maximilian Seidler <78690852+PaideiaDilemma@users.noreply.github.com> Date: Mon, 9 Sep 2024 20:29:00 +0000 Subject: [PATCH 0388/2181] input: move dmps activation to input listeners (#7721) --- src/managers/KeybindManager.hpp | 1 + src/managers/PointerManager.cpp | 30 +++++++++++++++++++++++++++++ src/managers/input/InputManager.cpp | 21 +++++++++----------- 3 files changed, 40 insertions(+), 12 deletions(-) diff --git a/src/managers/KeybindManager.hpp b/src/managers/KeybindManager.hpp index bf3b049f..096cd4f9 100644 --- a/src/managers/KeybindManager.hpp +++ b/src/managers/KeybindManager.hpp @@ -221,6 +221,7 @@ class CKeybindManager { friend class CInputManager; friend class CConfigManager; friend class CWorkspace; + friend class CPointerManager; }; inline std::unique_ptr g_pKeybindManager; diff --git a/src/managers/PointerManager.cpp b/src/managers/PointerManager.cpp index ce9ea4a4..e48c77d5 100644 --- a/src/managers/PointerManager.cpp +++ b/src/managers/PointerManager.cpp @@ -821,6 +821,9 @@ void CPointerManager::attachPointer(SP pointer) { if (!pointer) return; + static auto PMOUSEDPMS = CConfigValue("misc:mouse_move_enables_dpms"); + + // auto listener = pointerListeners.emplace_back(makeShared()); listener->pointer = pointer; @@ -836,6 +839,9 @@ void CPointerManager::attachPointer(SP pointer) { g_pInputManager->onMouseMoved(E); PROTO::idle->onActivity(); + + if (!g_pCompositor->m_bDPMSStateON && *PMOUSEDPMS) + g_pKeybindManager->dpms("on"); }); listener->motionAbsolute = pointer->pointerEvents.motionAbsolute.registerListener([this] (std::any e) { @@ -844,6 +850,9 @@ void CPointerManager::attachPointer(SP pointer) { g_pInputManager->onMouseWarp(E); PROTO::idle->onActivity(); + + if (!g_pCompositor->m_bDPMSStateON && *PMOUSEDPMS) + g_pKeybindManager->dpms("on"); }); listener->button = pointer->pointerEvents.button.registerListener([this] (std::any e) { @@ -872,6 +881,9 @@ void CPointerManager::attachPointer(SP pointer) { g_pInputManager->onSwipeBegin(E); PROTO::idle->onActivity(); + + if (!g_pCompositor->m_bDPMSStateON && *PMOUSEDPMS) + g_pKeybindManager->dpms("on"); }); listener->swipeEnd = pointer->pointerEvents.swipeEnd.registerListener([this] (std::any e) { @@ -896,6 +908,9 @@ void CPointerManager::attachPointer(SP pointer) { PROTO::pointerGestures->pinchBegin(E.timeMs, E.fingers); PROTO::idle->onActivity(); + + if (!g_pCompositor->m_bDPMSStateON && *PMOUSEDPMS) + g_pKeybindManager->dpms("on"); }); listener->pinchEnd = pointer->pointerEvents.pinchEnd.registerListener([this] (std::any e) { @@ -938,6 +953,9 @@ void CPointerManager::attachTouch(SP touch) { if (!touch) return; + static auto PMOUSEDPMS = CConfigValue("misc:mouse_move_enables_dpms"); + + // auto listener = touchListeners.emplace_back(makeShared()); listener->touch = touch; @@ -953,6 +971,9 @@ void CPointerManager::attachTouch(SP touch) { g_pInputManager->onTouchDown(E); PROTO::idle->onActivity(); + + if (!g_pCompositor->m_bDPMSStateON && *PMOUSEDPMS) + g_pKeybindManager->dpms("on"); }); listener->up = touch->touchEvents.up.registerListener([this] (std::any e) { @@ -987,6 +1008,9 @@ void CPointerManager::attachTablet(SP tablet) { if (!tablet) return; + static auto PMOUSEDPMS = CConfigValue("misc:mouse_move_enables_dpms"); + + // auto listener = tabletListeners.emplace_back(makeShared()); listener->tablet = tablet; @@ -1002,6 +1026,9 @@ void CPointerManager::attachTablet(SP tablet) { g_pInputManager->onTabletAxis(E); PROTO::idle->onActivity(); + + if (!g_pCompositor->m_bDPMSStateON && *PMOUSEDPMS) + g_pKeybindManager->dpms("on"); }); listener->proximity = tablet->tabletEvents.proximity.registerListener([this] (std::any e) { @@ -1018,6 +1045,9 @@ void CPointerManager::attachTablet(SP tablet) { g_pInputManager->onTabletTip(E); PROTO::idle->onActivity(); + + if (!g_pCompositor->m_bDPMSStateON && *PMOUSEDPMS) + g_pKeybindManager->dpms("on"); }); listener->button = tablet->tabletEvents.button.registerListener([this] (std::any e) { diff --git a/src/managers/input/InputManager.cpp b/src/managers/input/InputManager.cpp index f1035c82..03c72919 100644 --- a/src/managers/input/InputManager.cpp +++ b/src/managers/input/InputManager.cpp @@ -28,6 +28,7 @@ #include "../../managers/PointerManager.hpp" #include "../../managers/SeatManager.hpp" +#include "../../managers/KeybindManager.hpp" #include @@ -135,7 +136,6 @@ void CInputManager::sendMotionEventsToFocused() { void CInputManager::mouseMoveUnified(uint32_t time, bool refocus) { static auto PFOLLOWMOUSE = CConfigValue("input:follow_mouse"); static auto PMOUSEREFOCUS = CConfigValue("input:mouse_refocus"); - static auto PMOUSEDPMS = CConfigValue("misc:mouse_move_enables_dpms"); static auto PFOLLOWONDND = CConfigValue("misc:always_follow_on_dnd"); static auto PFLOATBEHAVIOR = CConfigValue("input:float_switch_override_focus"); static auto PMOUSEFOCUSMON = CConfigValue("misc:mouse_move_focuses_monitor"); @@ -157,11 +157,6 @@ void CInputManager::mouseMoveUnified(uint32_t time, bool refocus) { if (!g_pCompositor->m_bReadyToProcess || g_pCompositor->m_bIsShuttingDown || g_pCompositor->m_bUnsafeState) return; - if (!g_pCompositor->m_bDPMSStateON && *PMOUSEDPMS) { - // enable dpms - g_pKeybindManager->dpms("on"); - } - Vector2D mouseCoords = getMouseCoordsInternal(); const auto MOUSECOORDSFLOORED = mouseCoords.floor(); @@ -854,6 +849,8 @@ void CInputManager::newVirtualKeyboard(SP keyboard) } void CInputManager::setupKeyboard(SP keeb) { + static auto PDPMS = CConfigValue("misc:key_press_enables_dpms"); + m_vHIDs.push_back(keeb); try { @@ -882,6 +879,9 @@ void CInputManager::setupKeyboard(SP keeb) { if (PKEEB->enabled) PROTO::idle->onActivity(); + + if (PKEEB->enabled && *PDPMS && !g_pCompositor->m_bDPMSStateON) + g_pKeybindManager->dpms("on"); }, keeb.get()); @@ -893,6 +893,9 @@ void CInputManager::setupKeyboard(SP keeb) { if (PKEEB->enabled) PROTO::idle->onActivity(); + + if (PKEEB->enabled && *PDPMS && !g_pCompositor->m_bDPMSStateON) + g_pKeybindManager->dpms("on"); }, keeb.get()); @@ -1284,12 +1287,6 @@ void CInputManager::onKeyboardKey(std::any event, SP pKeyboard) { const auto EMAP = std::unordered_map{{"keyboard", pKeyboard}, {"event", event}}; EMIT_HOOK_EVENT_CANCELLABLE("keyPress", EMAP); - static auto PDPMS = CConfigValue("misc:key_press_enables_dpms"); - if (*PDPMS && !g_pCompositor->m_bDPMSStateON) { - // enable dpms - g_pKeybindManager->dpms("on"); - } - bool passEvent = DISALLOWACTION || g_pKeybindManager->onKeyEvent(event, pKeyboard); auto e = std::any_cast(event); From c67b257e51133a2aaeec050fc4d283e2eaea6375 Mon Sep 17 00:00:00 2001 From: davc0n Date: Tue, 10 Sep 2024 12:06:37 +0200 Subject: [PATCH 0389/2181] build: Set cmake_minimum_required to version 3.30 (#7709) * build: Set cmake_minimum_required to version 3.30 * Nix: add patch for CMake min ver --------- Co-authored-by: Mihai Fufezan --- CMakeLists.txt | 2 +- nix/cmake-version.patch | 10 ++++++++++ nix/default.nix | 2 ++ 3 files changed, 13 insertions(+), 1 deletion(-) create mode 100644 nix/cmake-version.patch diff --git a/CMakeLists.txt b/CMakeLists.txt index d8424d91..6fdf98db 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,4 +1,4 @@ -cmake_minimum_required(VERSION 3.27) +cmake_minimum_required(VERSION 3.30) # Get version file(READ "${CMAKE_SOURCE_DIR}/VERSION" VER_RAW) diff --git a/nix/cmake-version.patch b/nix/cmake-version.patch new file mode 100644 index 00000000..ccc9c738 --- /dev/null +++ b/nix/cmake-version.patch @@ -0,0 +1,10 @@ +diff --git a/CMakeLists.txt b/CMakeLists.txt +index 6fdf98db..d8424d91 100644 +--- a/CMakeLists.txt ++++ b/CMakeLists.txt +@@ -1,4 +1,4 @@ +-cmake_minimum_required(VERSION 3.30) ++cmake_minimum_required(VERSION 3.27) + + # Get version + file(READ "${CMAKE_SOURCE_DIR}/VERSION" VER_RAW) diff --git a/nix/default.nix b/nix/default.nix index 1c6a0113..985a4cbb 100644 --- a/nix/default.nix +++ b/nix/default.nix @@ -64,6 +64,8 @@ assert lib.assertMsg (!hidpiXWayland) "The option `hidpiXWayland` has been remov patches = [ # forces GCC to use -std=c++26 ./stdcxx.patch + # Nix does not have CMake 3.30 yet, so override the minimum version + ./cmake-version.patch ]; postPatch = '' From 13f90bb87a697866f1bbbacd1473d04f33ec2aa7 Mon Sep 17 00:00:00 2001 From: Alexandre Acebedo Date: Sun, 8 Sep 2024 20:54:12 +0200 Subject: [PATCH 0390/2181] update xdph commit in flake.lock --- flake.lock | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/flake.lock b/flake.lock index 99a544e2..239ec219 100644 --- a/flake.lock +++ b/flake.lock @@ -209,11 +209,11 @@ ] }, "locked": { - "lastModified": 1725203932, - "narHash": "sha256-VLULC/OnI+6R9KEP2OIGk+uLJJsfRlaLouZ5gyFd2+Y=", + "lastModified": 1725228143, + "narHash": "sha256-kbSiPA5oXiz1+1eVoRslMi5wylHD6SDT8dS9eZAxXAM=", "owner": "hyprwm", "repo": "xdg-desktop-portal-hyprland", - "rev": "2425e8f541525fa7409d9f26a8ffaf92a3767251", + "rev": "11e15b437e7efc39e452f36e15a183225d6bfa39", "type": "github" }, "original": { From 155d44016d0cb11332c454db73d59030cdbd7b13 Mon Sep 17 00:00:00 2001 From: Sungyoon Cho Date: Tue, 10 Sep 2024 22:49:10 +0900 Subject: [PATCH 0391/2181] textinput: handle IME resetting (#7731) --- src/managers/input/InputMethodRelay.cpp | 10 ++++++---- src/managers/input/InputMethodRelay.hpp | 4 ++-- src/managers/input/TextInput.cpp | 24 +++++++++++++++++------- src/managers/input/TextInput.hpp | 2 ++ src/protocols/TextInputV1.cpp | 1 + src/protocols/TextInputV1.hpp | 1 + src/protocols/TextInputV3.cpp | 19 ++++++++++++++----- src/protocols/TextInputV3.hpp | 7 ++++++- 8 files changed, 49 insertions(+), 19 deletions(-) diff --git a/src/managers/input/InputMethodRelay.cpp b/src/managers/input/InputMethodRelay.cpp index 1608e123..5ef7f331 100644 --- a/src/managers/input/InputMethodRelay.cpp +++ b/src/managers/input/InputMethodRelay.cpp @@ -106,20 +106,22 @@ void CInputMethodRelay::updateAllPopups() { } } -void CInputMethodRelay::activateIME(CTextInput* pInput) { +void CInputMethodRelay::activateIME(CTextInput* pInput, bool shouldCommit) { if (m_pIME.expired()) return; m_pIME->activate(); - commitIMEState(pInput); + if (shouldCommit) + commitIMEState(pInput); } -void CInputMethodRelay::deactivateIME(CTextInput* pInput) { +void CInputMethodRelay::deactivateIME(CTextInput* pInput, bool shouldCommit) { if (m_pIME.expired()) return; m_pIME->deactivate(); - commitIMEState(pInput); + if (shouldCommit) + commitIMEState(pInput); } void CInputMethodRelay::commitIMEState(CTextInput* pInput) { diff --git a/src/managers/input/InputMethodRelay.hpp b/src/managers/input/InputMethodRelay.hpp index 5ecc11a2..3d706563 100644 --- a/src/managers/input/InputMethodRelay.hpp +++ b/src/managers/input/InputMethodRelay.hpp @@ -21,8 +21,8 @@ class CInputMethodRelay { void onNewTextInput(WP tiv3); void onNewTextInput(WP pTIV1); - void activateIME(CTextInput* pInput); - void deactivateIME(CTextInput* pInput); + void activateIME(CTextInput* pInput, bool shouldCommit = true); + void deactivateIME(CTextInput* pInput, bool shouldCommit = true); void commitIMEState(CTextInput* pInput); void removeTextInput(CTextInput* pInput); diff --git a/src/managers/input/TextInput.cpp b/src/managers/input/TextInput.cpp index d488f173..2769fad0 100644 --- a/src/managers/input/TextInput.cpp +++ b/src/managers/input/TextInput.cpp @@ -22,6 +22,7 @@ void CTextInput::initCallbacks() { listeners.enable = INPUT->events.enable.registerListener([this](std::any p) { onEnabled(); }); listeners.disable = INPUT->events.disable.registerListener([this](std::any p) { onDisabled(); }); listeners.commit = INPUT->events.onCommit.registerListener([this](std::any p) { onCommit(); }); + listeners.reset = INPUT->events.reset.registerListener([this](std::any p) { onReset(); }); listeners.destroy = INPUT->events.destroy.registerListener([this](std::any p) { listeners.surfaceUnmap.reset(); listeners.surfaceDestroy.reset(); @@ -41,6 +42,7 @@ void CTextInput::initCallbacks() { }); listeners.disable = INPUT->events.disable.registerListener([this](std::any p) { onDisabled(); }); listeners.commit = INPUT->events.onCommit.registerListener([this](std::any p) { onCommit(); }); + listeners.reset = INPUT->events.reset.registerListener([this](std::any p) { onReset(); }); listeners.destroy = INPUT->events.destroy.registerListener([this](std::any p) { listeners.surfaceUnmap.reset(); listeners.surfaceDestroy.reset(); @@ -93,13 +95,21 @@ void CTextInput::onDisabled() { g_pInputManager->m_sIMERelay.deactivateIME(this); } +void CTextInput::onReset() { + if (g_pInputManager->m_sIMERelay.m_pIME.expired()) + return; + + g_pInputManager->m_sIMERelay.deactivateIME(this, false); + g_pInputManager->m_sIMERelay.activateIME(this); +} + void CTextInput::onCommit() { if (g_pInputManager->m_sIMERelay.m_pIME.expired()) { // Debug::log(WARN, "Committing TextInput on no IME!"); return; } - if (!(isV3() ? pV3Input->current.enabled : pV1Input->active)) { + if (!(isV3() ? pV3Input->current.enabled.value : pV1Input->active)) { Debug::log(WARN, "Disabled TextInput commit?"); return; } @@ -128,8 +138,8 @@ void CTextInput::setFocusedSurface(SP pSurface) { listeners.surfaceUnmap.reset(); listeners.surfaceDestroy.reset(); - if (isV3() && !pV3Input.expired() && pV3Input->current.enabled) - pV3Input->current.enabled = false; + if (isV3() && !pV3Input.expired() && pV3Input->current.enabled.value) + pV3Input->current.enabled.value = false; if (!g_pInputManager->m_sIMERelay.getFocusedTextInput()) g_pInputManager->m_sIMERelay.deactivateIME(this); @@ -144,8 +154,8 @@ void CTextInput::setFocusedSurface(SP pSurface) { listeners.surfaceUnmap.reset(); listeners.surfaceDestroy.reset(); - if (isV3() && !pV3Input.expired() && pV3Input->current.enabled) - pV3Input->current.enabled = false; + if (isV3() && !pV3Input.expired() && pV3Input->current.enabled.value) + pV3Input->current.enabled.value = false; if (!g_pInputManager->m_sIMERelay.getFocusedTextInput()) g_pInputManager->m_sIMERelay.deactivateIME(this); @@ -194,8 +204,8 @@ void CTextInput::leave() { if (isV3()) { pV3Input->leave(focusedSurface()); - if (pV3Input->current.enabled) { - pV3Input->current.enabled = false; + if (pV3Input->current.enabled.value) { + pV3Input->current.enabled.value = false; onDisabled(); } } else diff --git a/src/managers/input/TextInput.hpp b/src/managers/input/TextInput.hpp index 0f69866e..f920adc7 100644 --- a/src/managers/input/TextInput.hpp +++ b/src/managers/input/TextInput.hpp @@ -29,6 +29,7 @@ class CTextInput { void onEnabled(SP surfV1 = nullptr); void onDisabled(); void onCommit(); + void onReset(); bool hasCursorRectangle(); CBox cursorBox(); @@ -47,6 +48,7 @@ class CTextInput { struct { CHyprSignalListener enable; CHyprSignalListener disable; + CHyprSignalListener reset; CHyprSignalListener commit; CHyprSignalListener destroy; CHyprSignalListener surfaceUnmap; diff --git a/src/protocols/TextInputV1.cpp b/src/protocols/TextInputV1.cpp index f25f5aca..dad74b53 100644 --- a/src/protocols/TextInputV1.cpp +++ b/src/protocols/TextInputV1.cpp @@ -31,6 +31,7 @@ CTextInputV1::CTextInputV1(SP resource_) : resource(resource_) resource->setReset([this](CZwpTextInputV1* pMgr) { pendingSurrounding.isPending = false; pendingContentType.isPending = false; + events.reset.emit(); }); resource->setSetSurroundingText( diff --git a/src/protocols/TextInputV1.hpp b/src/protocols/TextInputV1.hpp index c85a1f31..9bee452c 100644 --- a/src/protocols/TextInputV1.hpp +++ b/src/protocols/TextInputV1.hpp @@ -37,6 +37,7 @@ class CTextInputV1 { CSignal onCommit; CSignal enable; CSignal disable; + CSignal reset; CSignal destroy; } events; diff --git a/src/protocols/TextInputV3.cpp b/src/protocols/TextInputV3.cpp index 42dc659e..30374104 100644 --- a/src/protocols/TextInputV3.cpp +++ b/src/protocols/TextInputV3.cpp @@ -19,17 +19,22 @@ CTextInputV3::CTextInputV3(SP resource_) : resource(resource_) resource->setOnDestroy([this](CZwpTextInputV3* r) { PROTO::textInputV3->destroyTextInput(this); }); resource->setCommit([this](CZwpTextInputV3* r) { - bool wasEnabled = current.enabled; + bool wasEnabled = current.enabled.value; current = pending; serial++; - if (wasEnabled && !current.enabled) + if (wasEnabled && !current.enabled.value) events.disable.emit(); - else if (!wasEnabled && current.enabled) + else if (!wasEnabled && current.enabled.value) events.enable.emit(); + else if (current.enabled.value && current.enabled.isEnablePending && current.enabled.isDisablePending) + events.reset.emit(); else events.onCommit.emit(); + + pending.enabled.isEnablePending = false; + pending.enabled.isDisablePending = false; }); resource->setSetSurroundingText([this](CZwpTextInputV3* r, const char* text, int32_t cursor, int32_t anchor) { @@ -54,10 +59,14 @@ CTextInputV3::CTextInputV3(SP resource_) : resource(resource_) resource->setEnable([this](CZwpTextInputV3* r) { pending.reset(); - pending.enabled = true; + pending.enabled.value = true; + pending.enabled.isEnablePending = true; }); - resource->setDisable([this](CZwpTextInputV3* r) { pending.enabled = false; }); + resource->setDisable([this](CZwpTextInputV3* r) { + pending.enabled.value = false; + pending.enabled.isDisablePending = true; + }); } CTextInputV3::~CTextInputV3() { diff --git a/src/protocols/TextInputV3.hpp b/src/protocols/TextInputV3.hpp index 9f6284dc..ba8b75e6 100644 --- a/src/protocols/TextInputV3.hpp +++ b/src/protocols/TextInputV3.hpp @@ -31,6 +31,7 @@ class CTextInputV3 { CSignal onCommit; CSignal enable; CSignal disable; + CSignal reset; CSignal destroy; } events; @@ -53,7 +54,11 @@ class CTextInputV3 { CBox cursorBox; } box; - bool enabled = false; + struct { + bool isEnablePending = false; + bool isDisablePending = false; + bool value = false; + } enabled; zwpTextInputV3ChangeCause cause = ZWP_TEXT_INPUT_V3_CHANGE_CAUSE_INPUT_METHOD; From 518399a95bada8bad8a4c29514da9962ce442307 Mon Sep 17 00:00:00 2001 From: Vaxry Date: Wed, 11 Sep 2024 09:30:21 +0100 Subject: [PATCH 0392/2181] pointermgr: avoid derefing null outputs --- src/managers/PointerManager.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/managers/PointerManager.cpp b/src/managers/PointerManager.cpp index e48c77d5..6b2a40f5 100644 --- a/src/managers/PointerManager.cpp +++ b/src/managers/PointerManager.cpp @@ -675,7 +675,7 @@ void CPointerManager::damageIfSoftware() { static auto PNOHW = CConfigValue("cursor:no_hardware_cursors"); for (auto const& mw : monitorStates) { - if (mw->monitor.expired()) + if (mw->monitor.expired() || !mw->monitor->output) continue; if ((mw->softwareLocks > 0 || mw->hardwareFailed || *PNOHW) && b.overlaps({mw->monitor->vecPosition, mw->monitor->vecSize})) { @@ -789,7 +789,7 @@ void CPointerManager::warpAbsolute(Vector2D abs, SP dev) { void CPointerManager::onMonitorLayoutChange() { currentMonitorLayout.monitorBoxes.clear(); for (auto const& m : g_pCompositor->m_vMonitors) { - if (m->isMirror() || !m->m_bEnabled) + if (m->isMirror() || !m->m_bEnabled || !m->output) continue; currentMonitorLayout.monitorBoxes.emplace_back(CBox{m->vecPosition, m->vecSize}); From 7a8c013edcbc59804a98fffa0436efcb268e1cda Mon Sep 17 00:00:00 2001 From: Mihai Fufezan Date: Wed, 11 Sep 2024 18:50:59 +0300 Subject: [PATCH 0393/2181] Meson: fix protocols, clean up --- protocols/meson.build | 147 ++++++++++++++++++++---------------------- 1 file changed, 70 insertions(+), 77 deletions(-) diff --git a/protocols/meson.build b/protocols/meson.build index de650230..d686bacd 100644 --- a/protocols/meson.build +++ b/protocols/meson.build @@ -1,77 +1,75 @@ -wayland_protos = dependency('wayland-protocols', +wayland_protos = dependency( + 'wayland-protocols', version: '>=1.32', fallback: 'wayland-protocols', default_options: ['tests=false'], ) -hyprland_protos = dependency('hyprland-protocols', +hyprland_protos = dependency( + 'hyprland-protocols', version: '>=0.2', - fallback: 'hyprland-protocols', + fallback: 'hyprland-protocols', ) -wl_protocol_dir = wayland_protos.get_variable('pkgdatadir') -hl_protocol_dir = hyprland_protos.get_variable('pkgdatadir') +wayland_protocol_dir = wayland_protos.get_variable('pkgdatadir') +hyprland_protocol_dir = hyprland_protos.get_variable('pkgdatadir') -hyprwayland_scanner_dep = dependency('hyprwayland-scanner', version: '>=0.3.8', native: true) +hyprwayland_scanner_dep = dependency('hyprwayland-scanner', version: '>=0.3.10', native: true) hyprwayland_scanner = find_program( hyprwayland_scanner_dep.get_variable('hyprwayland_scanner'), native: true, ) -new_protocols = [ - ['wlr-gamma-control-unstable-v1.xml'], - ['wlr-foreign-toplevel-management-unstable-v1.xml'], - ['wlr-output-power-management-unstable-v1.xml'], - ['input-method-unstable-v2.xml'], - ['virtual-keyboard-unstable-v1.xml'], - ['wlr-virtual-pointer-unstable-v1.xml'], - ['wlr-output-management-unstable-v1.xml'], - ['kde-server-decoration.xml'], - ['wlr-layer-shell-unstable-v1.xml'], - ['wayland-drm.xml'], - ['wlr-data-control-unstable-v1.xml'], - ['wlr-screencopy-unstable-v1.xml'], - [hl_protocol_dir, 'protocols/hyprland-global-shortcuts-v1.xml'], - [hl_protocol_dir, 'protocols/hyprland-toplevel-export-v1.xml'], - [hl_protocol_dir, 'protocols/hyprland-focus-grab-v1.xml'], - [wl_protocol_dir, 'staging/tearing-control/tearing-control-v1.xml'], - [wl_protocol_dir, 'staging/fractional-scale/fractional-scale-v1.xml'], - [wl_protocol_dir, 'unstable/xdg-output/xdg-output-unstable-v1.xml'], - [wl_protocol_dir, 'staging/cursor-shape/cursor-shape-v1.xml'], - [wl_protocol_dir, 'unstable/idle-inhibit/idle-inhibit-unstable-v1.xml'], - [wl_protocol_dir, 'unstable/relative-pointer/relative-pointer-unstable-v1.xml'], - [wl_protocol_dir, 'unstable/xdg-decoration/xdg-decoration-unstable-v1.xml'], - [wl_protocol_dir, 'staging/alpha-modifier/alpha-modifier-v1.xml'], - [wl_protocol_dir, 'staging/ext-foreign-toplevel-list/ext-foreign-toplevel-list-v1.xml'], - [wl_protocol_dir, 'unstable/pointer-gestures/pointer-gestures-unstable-v1.xml'], - [wl_protocol_dir, 'unstable/keyboard-shortcuts-inhibit/keyboard-shortcuts-inhibit-unstable-v1.xml'], - [wl_protocol_dir, 'unstable/text-input/text-input-unstable-v3.xml'], - [wl_protocol_dir, 'unstable/text-input/text-input-unstable-v1.xml'], - [wl_protocol_dir, 'unstable/pointer-constraints/pointer-constraints-unstable-v1.xml'], - [wl_protocol_dir, 'staging/xdg-activation/xdg-activation-v1.xml'], - [wl_protocol_dir, 'staging/ext-idle-notify/ext-idle-notify-v1.xml'], - [wl_protocol_dir, 'staging/ext-session-lock/ext-session-lock-v1.xml'], - [wl_protocol_dir, 'stable/tablet/tablet-v2.xml'], - [wl_protocol_dir, 'stable/presentation-time/presentation-time.xml'], - [wl_protocol_dir, 'stable/xdg-shell/xdg-shell.xml'], - [wl_protocol_dir, 'unstable/primary-selection/primary-selection-unstable-v1.xml'], - [wl_protocol_dir, 'staging/xwayland-shell/xwayland-shell-v1.xml'], - [wl_protocol_dir, 'stable/viewporter/viewporter.xml'], - [wl_protocol_dir, 'stable/linux-dmabuf/linux-dmabuf-v1.xml'], - [wl_protocol_dir, 'staging/drm-lease/drm-lease-v1.xml'], - [wl_protocol_dir, 'staging/linux-drm-syncobj/linux-drm-syncobj-v1.xml'], - [wl_protocol_dir, 'staging/xdg-dialog/xdg-dialog-v1.xml'], +protocols = [ + 'wlr-gamma-control-unstable-v1.xml', + 'wlr-foreign-toplevel-management-unstable-v1.xml', + 'wlr-output-power-management-unstable-v1.xml', + 'input-method-unstable-v2.xml', + 'virtual-keyboard-unstable-v1.xml', + 'wlr-virtual-pointer-unstable-v1.xml', + 'wlr-output-management-unstable-v1.xml', + 'kde-server-decoration.xml', + 'wlr-layer-shell-unstable-v1.xml', + 'wayland-drm.xml', + 'wlr-data-control-unstable-v1.xml', + 'wlr-screencopy-unstable-v1.xml', + hyprland_protocol_dir / 'protocols/hyprland-global-shortcuts-v1.xml', + hyprland_protocol_dir / 'protocols/hyprland-toplevel-export-v1.xml', + hyprland_protocol_dir / 'protocols/hyprland-focus-grab-v1.xml', + wayland_protocol_dir / 'staging/tearing-control/tearing-control-v1.xml', + wayland_protocol_dir / 'staging/fractional-scale/fractional-scale-v1.xml', + wayland_protocol_dir / 'unstable/xdg-output/xdg-output-unstable-v1.xml', + wayland_protocol_dir / 'staging/cursor-shape/cursor-shape-v1.xml', + wayland_protocol_dir / 'unstable/idle-inhibit/idle-inhibit-unstable-v1.xml', + wayland_protocol_dir / 'unstable/relative-pointer/relative-pointer-unstable-v1.xml', + wayland_protocol_dir / 'unstable/xdg-decoration/xdg-decoration-unstable-v1.xml', + wayland_protocol_dir / 'staging/alpha-modifier/alpha-modifier-v1.xml', + wayland_protocol_dir / 'staging/ext-foreign-toplevel-list/ext-foreign-toplevel-list-v1.xml', + wayland_protocol_dir / 'unstable/pointer-gestures/pointer-gestures-unstable-v1.xml', + wayland_protocol_dir / 'unstable/keyboard-shortcuts-inhibit/keyboard-shortcuts-inhibit-unstable-v1.xml', + wayland_protocol_dir / 'unstable/text-input/text-input-unstable-v3.xml', + wayland_protocol_dir / 'unstable/text-input/text-input-unstable-v1.xml', + wayland_protocol_dir / 'unstable/pointer-constraints/pointer-constraints-unstable-v1.xml', + wayland_protocol_dir / 'staging/xdg-activation/xdg-activation-v1.xml', + wayland_protocol_dir / 'staging/ext-idle-notify/ext-idle-notify-v1.xml', + wayland_protocol_dir / 'staging/ext-session-lock/ext-session-lock-v1.xml', + wayland_protocol_dir / 'stable/tablet/tablet-v2.xml', + wayland_protocol_dir / 'stable/presentation-time/presentation-time.xml', + wayland_protocol_dir / 'stable/xdg-shell/xdg-shell.xml', + wayland_protocol_dir / 'unstable/primary-selection/primary-selection-unstable-v1.xml', + wayland_protocol_dir / 'staging/xwayland-shell/xwayland-shell-v1.xml', + wayland_protocol_dir / 'stable/viewporter/viewporter.xml', + wayland_protocol_dir / 'stable/linux-dmabuf/linux-dmabuf-v1.xml', + wayland_protocol_dir / 'staging/drm-lease/drm-lease-v1.xml', + wayland_protocol_dir / 'staging/linux-drm-syncobj/linux-drm-syncobj-v1.xml', + wayland_protocol_dir / 'staging/xdg-dialog/xdg-dialog-v1.xml', ] -wl_protos_src = [] -wl_protos_headers = [] - -new_wl_protos = [] -foreach p : new_protocols - xml = join_paths(p) - new_wl_protos += custom_target( - xml.underscorify(), - input: xml, +wl_protocols = [] +foreach protocol : protocols + wl_protocols += custom_target( + protocol.underscorify(), + input: protocol, install: true, install_dir: [false, join_paths(get_option('includedir'), 'hyprland/protocols')], output: ['@BASENAME@.cpp', '@BASENAME@.hpp'], @@ -79,31 +77,26 @@ foreach p : new_protocols ) endforeach -wayland_server_dep = dependency('wayland-server', version: '>=1.20.0') -wayland_server_dir = wayland_server_dep.get_variable('pkgdatadir') +# wayland.xml generation +wayland_scanner = dependency('wayland-scanner') +wayland_scanner_datadir = wayland_scanner.get_variable('pkgdatadir') -wl_server_protos = [ - wayland_server_dir / 'wayland.xml' -] -wl_server_protos_gen = [] -foreach p : wl_server_protos - wl_server_protos_gen += custom_target( - p.underscorify(), - input: p, - install: true, - install_dir: [false, join_paths(get_option('includedir'), 'hyprland/protocols')], - output: ['@BASENAME@.cpp', '@BASENAME@.hpp'], - command: [hyprwayland_scanner, '--wayland-enums', '@INPUT@', '@OUTDIR@'], - ) -endforeach +wayland_xml = wayland_scanner_datadir / 'wayland.xml' +wayland_protocol = custom_target( + wayland_xml.underscorify(), + input: wayland_xml, + install: true, + install_dir: [false, join_paths(get_option('includedir'), 'hyprland/protocols')], + output: ['@BASENAME@.cpp', '@BASENAME@.hpp'], + command: [hyprwayland_scanner, '--wayland-enums', '@INPUT@', '@OUTDIR@'], +) lib_server_protos = static_library( 'server_protos', - wl_protos_src + wl_protos_headers + new_wl_protos + wl_server_protos_gen, - dependencies: wayland_server_dep.partial_dependency(compile_args: true), + wl_protocols + wayland_protocol, ) server_protos = declare_dependency( link_with: lib_server_protos, - sources: wl_protos_headers + new_wl_protos, + sources: wl_protocols + wayland_protocol, ) From e01da1fd7a50ab0baeaba074f2a14c826b05bf1c Mon Sep 17 00:00:00 2001 From: Mihai Fufezan Date: Wed, 11 Sep 2024 19:00:47 +0300 Subject: [PATCH 0394/2181] Meson: format --- assets/install/meson.build | 6 +++++- assets/meson.build | 7 ++++++- docs/meson.build | 4 ++-- example/meson.build | 12 ++++++++++-- hyprctl/meson.build | 26 +++++++++++++++++++++----- hyprpm/src/meson.build | 28 ++++++++++++++++++++++------ meson.build | 26 +++++++++++++++++--------- src/meson.build | 6 ++++-- 8 files changed, 87 insertions(+), 28 deletions(-) diff --git a/assets/install/meson.build b/assets/install/meson.build index 1d4fb917..45076469 100644 --- a/assets/install/meson.build +++ b/assets/install/meson.build @@ -2,5 +2,9 @@ globber = run_command('sh', '-c', 'find . -type f -not -name "*.build"', check: files = globber.stdout().strip().split('\n') foreach file : files - install_data(file, install_dir: join_paths(get_option('datadir'), 'hypr'), install_tag: 'runtime') + install_data( + file, + install_dir: join_paths(get_option('datadir'), 'hypr'), + install_tag: 'runtime', + ) endforeach diff --git a/assets/meson.build b/assets/meson.build index 0648037a..2a28121d 100644 --- a/assets/meson.build +++ b/assets/meson.build @@ -1,2 +1,7 @@ -install_data('hyprland-portals.conf', install_dir: join_paths(get_option('datadir'), 'xdg-desktop-portal'), install_tag: 'runtime') +install_data( + 'hyprland-portals.conf', + install_dir: join_paths(get_option('datadir'), 'xdg-desktop-portal'), + install_tag: 'runtime', +) + subdir('install') diff --git a/docs/meson.build b/docs/meson.build index a5d7e737..6ff51d1a 100644 --- a/docs/meson.build +++ b/docs/meson.build @@ -1,2 +1,2 @@ -install_man ('Hyprland.1') -install_man ('hyprctl.1') +install_man('Hyprland.1') +install_man('hyprctl.1') diff --git a/example/meson.build b/example/meson.build index 2fb3a35e..a338644e 100644 --- a/example/meson.build +++ b/example/meson.build @@ -1,2 +1,10 @@ -install_data('hyprland.conf', install_dir: join_paths(get_option('datadir'), 'hypr'), install_tag: 'runtime') -install_data('hyprland.desktop', install_dir: join_paths(get_option('datadir'), 'wayland-sessions'), install_tag: 'runtime') +install_data( + 'hyprland.conf', + install_dir: join_paths(get_option('datadir'), 'hypr'), + install_tag: 'runtime', +) +install_data( + 'hyprland.desktop', + install_dir: join_paths(get_option('datadir'), 'wayland-sessions'), + install_tag: 'runtime', +) diff --git a/hyprctl/meson.build b/hyprctl/meson.build index 5488845f..455f5739 100644 --- a/hyprctl/meson.build +++ b/hyprctl/meson.build @@ -1,10 +1,26 @@ -executable('hyprctl', 'main.cpp', +executable( + 'hyprctl', + 'main.cpp', dependencies: [ dependency('hyprutils', version: '>= 0.1.1'), ], - install: true + install: true, ) -install_data('hyprctl.bash', install_dir: join_paths(get_option('datadir'), 'bash-completion/completions'), install_tag: 'runtime', rename: 'hyprctl') -install_data('hyprctl.fish', install_dir: join_paths(get_option('datadir'), 'fish/vendor_completions.d'), install_tag: 'runtime') -install_data('hyprctl.zsh', install_dir: join_paths(get_option('datadir'), 'zsh/site-functions'), install_tag: 'runtime', rename: '_hyprctl') +install_data( + 'hyprctl.bash', + install_dir: join_paths(get_option('datadir'), 'bash-completion/completions'), + install_tag: 'runtime', + rename: 'hyprctl', +) +install_data( + 'hyprctl.fish', + install_dir: join_paths(get_option('datadir'), 'fish/vendor_completions.d'), + install_tag: 'runtime', +) +install_data( + 'hyprctl.zsh', + install_dir: join_paths(get_option('datadir'), 'zsh/site-functions'), + install_tag: 'runtime', + rename: '_hyprctl', +) diff --git a/hyprpm/src/meson.build b/hyprpm/src/meson.build index e2c512a5..2ef6c323 100644 --- a/hyprpm/src/meson.build +++ b/hyprpm/src/meson.build @@ -1,15 +1,31 @@ globber = run_command('sh', '-c', 'find . -name "*.cpp" | sort', check: true) src = globber.stdout().strip().split('\n') -executable('hyprpm', src, +executable( + 'hyprpm', + src, dependencies: [ dependency('hyprutils', version: '>= 0.1.1'), dependency('threads'), - dependency('tomlplusplus') + dependency('tomlplusplus'), ], - install : true + install: true, ) -install_data('../hyprpm.bash', install_dir: join_paths(get_option('datadir'), 'bash-completion/completions'), install_tag: 'runtime', rename: 'hyprpm') -install_data('../hyprpm.fish', install_dir: join_paths(get_option('datadir'), 'fish/vendor_completions.d'), install_tag: 'runtime') -install_data('../hyprpm.zsh', install_dir: join_paths(get_option('datadir'), 'zsh/site-functions'), install_tag: 'runtime', rename: '_hyprpm') +install_data( + '../hyprpm.bash', + install_dir: join_paths(get_option('datadir'), 'bash-completion/completions'), + install_tag: 'runtime', + rename: 'hyprpm', +) +install_data( + '../hyprpm.fish', + install_dir: join_paths(get_option('datadir'), 'fish/vendor_completions.d'), + install_tag: 'runtime', +) +install_data( + '../hyprpm.zsh', + install_dir: join_paths(get_option('datadir'), 'zsh/site-functions'), + install_tag: 'runtime', + rename: '_hyprpm', +) diff --git a/meson.build b/meson.build index 6a9b7ac5..123c31ae 100644 --- a/meson.build +++ b/meson.build @@ -1,13 +1,17 @@ -project('Hyprland', 'cpp', 'c', - version : run_command('cat', join_paths(meson.source_root(), 'VERSION'), check: true).stdout().strip(), - default_options : [ +project( + 'Hyprland', + 'cpp', + 'c', + version: run_command('cat', join_paths(meson.project_source_root(), 'VERSION'), check: true).stdout().strip(), + default_options: [ 'warning_level=2', 'default_library=static', 'optimization=3', 'buildtype=release', 'debug=false', 'cpp_std=c++26', - ]) + ], +) datarootdir = '-DDATAROOTDIR="' + get_option('prefix') / get_option('datadir') + '"' add_project_arguments( @@ -16,10 +20,10 @@ add_project_arguments( '-Wno-unused-value', '-Wno-missing-field-initializers', '-Wno-narrowing', - '-Wno-pointer-arith', - datarootdir, + '-Wno-pointer-arith', datarootdir, ], - language: 'cpp') + language: 'cpp', +) cpp_compiler = meson.get_compiler('cpp') if cpp_compiler.check_header('execinfo.h') @@ -34,7 +38,7 @@ xcb_render_dep = dependency('xcb-render', required: get_option('xwayland')) xcb_res_dep = dependency('xcb-res', required: get_option('xwayland')) xcb_xfixes_dep = dependency('xcb-xfixes', required: get_option('xwayland')) -gio_dep = dependency('gio-2.0', required:true) +gio_dep = dependency('gio-2.0', required: true) cmake = import('cmake') udis = cmake.subproject('udis86') @@ -47,6 +51,7 @@ endif backtrace_dep = cpp_compiler.find_library('execinfo', required: false) epoll_dep = dependency('epoll-shim', required: false) # timerfd on BSDs +# Handle options if get_option('systemd').enabled() add_project_arguments('-DUSES_SYSTEMD', language: 'cpp') endif @@ -59,8 +64,10 @@ if get_option('buildtype') == 'debug' add_project_arguments('-DHYPRLAND_DEBUG', language: 'cpp') endif -version_h = run_command('sh', '-c', 'scripts/generateVersion.sh', check: true) +# Generate hyprland version and populate version.h +run_command('sh', '-c', 'scripts/generateVersion.sh', check: true) +# Install headers globber = run_command('find', 'src', '-name', '*.h*', check: true) headers = globber.stdout().strip().split('\n') foreach file : headers @@ -75,6 +82,7 @@ subdir('assets') subdir('example') subdir('docs') +# Generate hyprland.pc pkg_install_dir = join_paths(get_option('datadir'), 'pkgconfig') import('pkgconfig').generate( diff --git a/src/meson.build b/src/meson.build index 475ecc24..3821bd60 100644 --- a/src/meson.build +++ b/src/meson.build @@ -1,7 +1,9 @@ globber = run_command('sh', '-c', 'find . -name "*.cpp" | sort', check: true) src = globber.stdout().strip().split('\n') -executable('Hyprland', src, +executable( + 'Hyprland', + src, link_args: '-rdynamic', cpp_pch: 'pch/pch.hpp', dependencies: [ @@ -38,5 +40,5 @@ executable('Hyprland', src, dependency('pangocairo'), dependency('uuid'), ], - install : true + install: true, ) From 8b9e385943d1a9fd0f8c6070fa1eae507ae26145 Mon Sep 17 00:00:00 2001 From: fufexan Date: Wed, 11 Sep 2024 16:10:51 +0000 Subject: [PATCH 0395/2181] [gha] Nix: update inputs --- flake.lock | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/flake.lock b/flake.lock index 239ec219..55dc6939 100644 --- a/flake.lock +++ b/flake.lock @@ -16,11 +16,11 @@ ] }, "locked": { - "lastModified": 1725199881, - "narHash": "sha256-jsmipf/u1GFZE5tBUkr56CHMN6VpUWCAjfLIhvQijU0=", + "lastModified": 1725753098, + "narHash": "sha256-/NO/h/qD/eJXAQr/fHA4mdDgYsNT9thHQ+oT6KPi2ac=", "owner": "hyprwm", "repo": "aquamarine", - "rev": "f8a687dd29ff019657498f1bd14da2fbbf0e604b", + "rev": "e4a13203112a036fc7f437d391c7810f3dd5ab52", "type": "github" }, "original": { @@ -93,11 +93,11 @@ ] }, "locked": { - "lastModified": 1725188252, - "narHash": "sha256-yBH8c4GDaEAtBrh+BqIlrx5vp6gG/Gu8fQQK63KAQgs=", + "lastModified": 1725997860, + "narHash": "sha256-d/rZ/fHR5l1n7PeyLw0StWMNLXVU9c4HFyfskw568so=", "owner": "hyprwm", "repo": "hyprlang", - "rev": "c12ab785ce1982f82594aff03b3104c598186ddd", + "rev": "dfeb5811dd6485490cce18d6cc1e38a055eea876", "type": "github" }, "original": { @@ -154,11 +154,11 @@ }, "nixpkgs": { "locked": { - "lastModified": 1725103162, - "narHash": "sha256-Ym04C5+qovuQDYL/rKWSR+WESseQBbNAe5DsXNx5trY=", + "lastModified": 1725983898, + "narHash": "sha256-4b3A9zPpxAxLnkF9MawJNHDtOOl6ruL0r6Og1TEDGCE=", "owner": "NixOS", "repo": "nixpkgs", - "rev": "12228ff1752d7b7624a54e9c1af4b222b3c1073b", + "rev": "1355a0cbfeac61d785b7183c0caaec1f97361b43", "type": "github" }, "original": { @@ -209,11 +209,11 @@ ] }, "locked": { - "lastModified": 1725228143, - "narHash": "sha256-kbSiPA5oXiz1+1eVoRslMi5wylHD6SDT8dS9eZAxXAM=", + "lastModified": 1726046979, + "narHash": "sha256-6SEsjurq9cdTkITA6d49ncAJe4O/8CgRG5/F//s6Xh8=", "owner": "hyprwm", "repo": "xdg-desktop-portal-hyprland", - "rev": "11e15b437e7efc39e452f36e15a183225d6bfa39", + "rev": "e695669fd8e1d1be9eaae40f35e00f8bd8b64c18", "type": "github" }, "original": { From 73b9756b8d7ee06fc1c9f072f2a41f2dd1aeb2c9 Mon Sep 17 00:00:00 2001 From: trianta <56975502+Trimutex@users.noreply.github.com> Date: Thu, 12 Sep 2024 04:15:01 -0500 Subject: [PATCH 0396/2181] xwayland: remove extra x11 deactivation (#7755) --- src/managers/XWaylandManager.cpp | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/src/managers/XWaylandManager.cpp b/src/managers/XWaylandManager.cpp index 144343f8..fad7e451 100644 --- a/src/managers/XWaylandManager.cpp +++ b/src/managers/XWaylandManager.cpp @@ -46,11 +46,8 @@ void CHyprXWaylandManager::activateSurface(SP pSurface, bool PWINDOW->m_pXWaylandSurface->restackToTop(); } PWINDOW->m_pXWaylandSurface->activate(activate); - } else if (!PWINDOW->m_bIsX11 && PWINDOW->m_pXDGSurface) { + } else if (!PWINDOW->m_bIsX11 && PWINDOW->m_pXDGSurface) PWINDOW->m_pXDGSurface->toplevel->setActive(activate); - if (g_pCompositor->m_pLastFocus && g_pCompositor->m_pLastWindow && g_pCompositor->m_pLastWindow->m_bIsX11) - activateSurface(g_pCompositor->m_pLastFocus.lock(), false); - } } void CHyprXWaylandManager::activateWindow(PHLWINDOW pWindow, bool activate) { From 118be4dea048df88fd21b84580fe62950c868c8f Mon Sep 17 00:00:00 2001 From: Sungyoon Cho Date: Fri, 13 Sep 2024 01:41:24 +0900 Subject: [PATCH 0397/2181] textinput: fix tiv3 leave (#7761) --- src/managers/input/TextInput.cpp | 24 ++++++++++++++---------- 1 file changed, 14 insertions(+), 10 deletions(-) diff --git a/src/managers/input/TextInput.cpp b/src/managers/input/TextInput.cpp index 2769fad0..e601ad9a 100644 --- a/src/managers/input/TextInput.cpp +++ b/src/managers/input/TextInput.cpp @@ -138,8 +138,12 @@ void CTextInput::setFocusedSurface(SP pSurface) { listeners.surfaceUnmap.reset(); listeners.surfaceDestroy.reset(); - if (isV3() && !pV3Input.expired() && pV3Input->current.enabled.value) - pV3Input->current.enabled.value = false; + if (isV3() && !pV3Input.expired() && pV3Input->current.enabled.value) { + pV3Input->pending.enabled.value = false; + pV3Input->pending.enabled.isDisablePending = false; + pV3Input->pending.enabled.isEnablePending = false; + pV3Input->current.enabled.value = false; + } if (!g_pInputManager->m_sIMERelay.getFocusedTextInput()) g_pInputManager->m_sIMERelay.deactivateIME(this); @@ -154,8 +158,12 @@ void CTextInput::setFocusedSurface(SP pSurface) { listeners.surfaceUnmap.reset(); listeners.surfaceDestroy.reset(); - if (isV3() && !pV3Input.expired() && pV3Input->current.enabled.value) - pV3Input->current.enabled.value = false; + if (isV3() && !pV3Input.expired() && pV3Input->current.enabled.value) { + pV3Input->pending.enabled.value = false; + pV3Input->pending.enabled.isDisablePending = false; + pV3Input->pending.enabled.isEnablePending = false; + pV3Input->current.enabled.value = false; + } if (!g_pInputManager->m_sIMERelay.getFocusedTextInput()) g_pInputManager->m_sIMERelay.deactivateIME(this); @@ -202,13 +210,9 @@ void CTextInput::leave() { enterLocks = 0; } - if (isV3()) { + if (isV3()) pV3Input->leave(focusedSurface()); - if (pV3Input->current.enabled.value) { - pV3Input->current.enabled.value = false; - onDisabled(); - } - } else + else pV1Input->leave(); setFocusedSurface(nullptr); From d505b3366533b71d57156469c926e8b2b75afb89 Mon Sep 17 00:00:00 2001 From: diniamo Date: Fri, 13 Sep 2024 16:21:33 +0200 Subject: [PATCH 0398/2181] nix: use meson --- nix/default.nix | 2 ++ 1 file changed, 2 insertions(+) diff --git a/nix/default.nix b/nix/default.nix index 985a4cbb..d3c7dd5f 100644 --- a/nix/default.nix +++ b/nix/default.nix @@ -4,6 +4,7 @@ pkg-config, pkgconf, makeWrapper, + meson, cmake, ninja, aquamarine, @@ -89,6 +90,7 @@ assert lib.assertMsg (!hidpiXWayland) "The option `hidpiXWayland` has been remov hyprwayland-scanner jq makeWrapper + meson cmake ninja pkg-config From c35ed8363f321bb9925bc5e6f5ff03a903593802 Mon Sep 17 00:00:00 2001 From: diniamo Date: Fri, 13 Sep 2024 17:29:41 +0200 Subject: [PATCH 0399/2181] nix: adapt cmake options --- nix/cmake-version.patch | 10 ---------- nix/default.nix | 21 +++++++-------------- nix/stdcxx.patch | 12 ------------ 3 files changed, 7 insertions(+), 36 deletions(-) delete mode 100644 nix/cmake-version.patch delete mode 100644 nix/stdcxx.patch diff --git a/nix/cmake-version.patch b/nix/cmake-version.patch deleted file mode 100644 index ccc9c738..00000000 --- a/nix/cmake-version.patch +++ /dev/null @@ -1,10 +0,0 @@ -diff --git a/CMakeLists.txt b/CMakeLists.txt -index 6fdf98db..d8424d91 100644 ---- a/CMakeLists.txt -+++ b/CMakeLists.txt -@@ -1,4 +1,4 @@ --cmake_minimum_required(VERSION 3.30) -+cmake_minimum_required(VERSION 3.27) - - # Get version - file(READ "${CMAKE_SOURCE_DIR}/VERSION" VER_RAW) diff --git a/nix/default.nix b/nix/default.nix index d3c7dd5f..8d912fe6 100644 --- a/nix/default.nix +++ b/nix/default.nix @@ -62,13 +62,6 @@ assert lib.assertMsg (!hidpiXWayland) "The option `hidpiXWayland` has been remov src = lib.cleanSource ../.; }; - patches = [ - # forces GCC to use -std=c++26 - ./stdcxx.patch - # Nix does not have CMake 3.30 yet, so override the minimum version - ./cmake-version.patch - ]; - postPatch = '' # Fix hardcoded paths to /usr installation sed -i "s#/usr#$out#" src/render/OpenGL.cpp @@ -144,18 +137,18 @@ assert lib.assertMsg (!hidpiXWayland) "The option `hidpiXWayland` has been remov (lib.optionals withSystemd [systemd]) ]; - cmakeBuildType = + mesonBuildType = if debug - then "Debug" - else "RelWithDebInfo"; + then "debug" + else "release"; # we want as much debug info as possible dontStrip = debug; - cmakeFlags = [ - (lib.cmakeBool "NO_XWAYLAND" (!enableXWayland)) - (lib.cmakeBool "LEGACY_RENDERER" legacyRenderer) - (lib.cmakeBool "NO_SYSTEMD" (!withSystemd)) + mesonFlags = [ + (lib.mesonEnable "xwayland" enableXWayland) + (lib.mesonEnable "legacy_renderer" legacyRenderer) + (lib.mesonEnable "systemd" withSystemd) ]; postInstall = '' diff --git a/nix/stdcxx.patch b/nix/stdcxx.patch deleted file mode 100644 index 032e494d..00000000 --- a/nix/stdcxx.patch +++ /dev/null @@ -1,12 +0,0 @@ -diff --git a/CMakeLists.txt b/CMakeLists.txt -index cfbd431f..73e8e0c2 100644 ---- a/CMakeLists.txt -+++ b/CMakeLists.txt -@@ -64,6 +64,7 @@ endif() - include_directories(. "src/" "subprojects/udis86/" "protocols/") - set(CMAKE_CXX_STANDARD 26) - add_compile_options( -+ -std=c++26 - -Wall - -Wextra - -Wno-unused-parameter From d35e70a8c6599bb058cf86eb87c783ce1cf72471 Mon Sep 17 00:00:00 2001 From: Vaxry Date: Fri, 13 Sep 2024 17:56:39 +0100 Subject: [PATCH 0400/2181] cmake: drop ninja dep --- Makefile | 24 ++++++++++-------------- 1 file changed, 10 insertions(+), 14 deletions(-) diff --git a/Makefile b/Makefile index bc7b750b..59efc0ef 100644 --- a/Makefile +++ b/Makefile @@ -1,28 +1,24 @@ PREFIX = /usr/local legacyrenderer: - cmake --no-warn-unused-cli -DCMAKE_BUILD_TYPE:STRING=Release -DCMAKE_INSTALL_PREFIX:STRING=${PREFIX} -DLEGACY_RENDERER:BOOL=true -S . -B ./build -G Ninja - cmake --build ./build --config Release --target all - chmod -R 777 ./build + cmake --no-warn-unused-cli -DCMAKE_BUILD_TYPE:STRING=Release -DCMAKE_INSTALL_PREFIX:STRING=${PREFIX} -DLEGACY_RENDERER:BOOL=true -S . -B ./buildZ + cmake --build ./build --config Release --target all -j`nproc 2>/dev/null || getconf NPROCESSORS_CONF` legacyrendererdebug: - cmake --no-warn-unused-cli -DCMAKE_BUILD_TYPE:STRING=Debug -DCMAKE_INSTALL_PREFIX:STRING=${PREFIX} -DLEGACY_RENDERER:BOOL=true -S . -B ./build -G Ninja - cmake --build ./build --config Release --target all - chmod -R 777 ./build + cmake --no-warn-unused-cli -DCMAKE_BUILD_TYPE:STRING=Debug -DCMAKE_INSTALL_PREFIX:STRING=${PREFIX} -DLEGACY_RENDERER:BOOL=true -S . -B ./build + cmake --build ./build --config Release --target all -j`nproc 2>/dev/null || getconf NPROCESSORS_CONF` release: - cmake --no-warn-unused-cli -DCMAKE_BUILD_TYPE:STRING=Release -DCMAKE_INSTALL_PREFIX:STRING=${PREFIX} -S . -B ./build -G Ninja - cmake --build ./build --config Release --target all - chmod -R 777 ./build + cmake --no-warn-unused-cli -DCMAKE_BUILD_TYPE:STRING=Release -DCMAKE_INSTALL_PREFIX:STRING=${PREFIX} -S . -B ./build + cmake --build ./build --config Release --target all -j`nproc 2>/dev/null || getconf NPROCESSORS_CONF` debug: - cmake --no-warn-unused-cli -DCMAKE_BUILD_TYPE:STRING=Debug -DCMAKE_INSTALL_PREFIX:STRING=${PREFIX} -S . -B ./build -G Ninja - cmake --build ./build --config Debug --target all - chmod -R 777 ./build + cmake --no-warn-unused-cli -DCMAKE_BUILD_TYPE:STRING=Debug -DCMAKE_INSTALL_PREFIX:STRING=${PREFIX} -S . -B ./build + cmake --build ./build --config Debug --target all -j`nproc 2>/dev/null || getconf NPROCESSORS_CONF` nopch: - cmake --no-warn-unused-cli -DCMAKE_BUILD_TYPE:STRING=Release -DCMAKE_INSTALL_PREFIX:STRING=${PREFIX} -DCMAKE_DISABLE_PRECOMPILE_HEADERS=ON -S . -B ./build -G Ninja - cmake --build ./build --config Release --target all + cmake --no-warn-unused-cli -DCMAKE_BUILD_TYPE:STRING=Release -DCMAKE_INSTALL_PREFIX:STRING=${PREFIX} -DCMAKE_DISABLE_PRECOMPILE_HEADERS=ON -S . -B ./build + cmake --build ./build --config Release --target all -j`nproc 2>/dev/null || getconf NPROCESSORS_CONF` clear: rm -rf build From 5ee4b19691f413072f6877940ed709774333f84b Mon Sep 17 00:00:00 2001 From: Vaxry Date: Sat, 14 Sep 2024 23:35:45 +0100 Subject: [PATCH 0401/2181] data-device: send clock time in motion events remove hack --- src/protocols/core/DataDevice.cpp | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/protocols/core/DataDevice.cpp b/src/protocols/core/DataDevice.cpp index 8c1a48d8..43a63949 100644 --- a/src/protocols/core/DataDevice.cpp +++ b/src/protocols/core/DataDevice.cpp @@ -513,7 +513,10 @@ void CWLDataDeviceProtocol::initiateDrag(WP currentSource if (!box.has_value()) return; - dnd.focusedDevice->sendMotion(0 /* this is a hack */, V - box->pos()); + timespec timeNow; + clock_gettime(CLOCK_MONOTONIC, &timeNow); + + dnd.focusedDevice->sendMotion(timeNow.tv_sec * 1000 + timeNow.tv_nsec / 1000000, V - box->pos()); LOGM(LOG, "Drag motion {}", V - box->pos()); } }); From 4dbdb556fe441506ec5cf129c65b14e514dbcc5a Mon Sep 17 00:00:00 2001 From: Vaxry Date: Sat, 14 Sep 2024 23:36:06 +0100 Subject: [PATCH 0402/2181] data-device: don't send default action of move gtk doesn't like it? --- src/protocols/core/DataDevice.cpp | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/src/protocols/core/DataDevice.cpp b/src/protocols/core/DataDevice.cpp index 43a63949..eac80a83 100644 --- a/src/protocols/core/DataDevice.cpp +++ b/src/protocols/core/DataDevice.cpp @@ -82,10 +82,8 @@ void CWLDataOfferResource::sendData() { if (!source) return; - if (resource->version() >= 3) { + if (resource->version() >= 3) resource->sendSourceActions(7); - resource->sendAction(WL_DATA_DEVICE_MANAGER_DND_ACTION_MOVE); - } for (auto const& m : source->mimes()) { LOGM(LOG, " | offer {:x} supports mime {}", (uintptr_t)this, m); From e74efd87e5aa38f9cf84cb3848ee1ab26e5e4bcb Mon Sep 17 00:00:00 2001 From: Ikalco <73481042+ikalco@users.noreply.github.com> Date: Sat, 14 Sep 2024 17:37:18 -0500 Subject: [PATCH 0403/2181] internal: fix initial cursor warping (#7793) --- src/Compositor.cpp | 34 ++++++++++++++++++++++++++++ src/managers/PointerManager.cpp | 40 +-------------------------------- src/managers/PointerManager.hpp | 1 - 3 files changed, 35 insertions(+), 40 deletions(-) diff --git a/src/Compositor.cpp b/src/Compositor.cpp index da659654..8e1b11b0 100644 --- a/src/Compositor.cpp +++ b/src/Compositor.cpp @@ -2943,6 +2943,38 @@ PHLWINDOW CCompositor::windowForCPointer(CWindow* pWindow) { return {}; } +static void checkDefaultCursorWarp(SP monitor) { + static auto PCURSORMONITOR = CConfigValue("cursor:default_monitor"); + static bool cursorDefaultDone = false; + static bool firstLaunch = true; + + const auto POS = monitor->middle(); + + // by default, cursor should be set to first monitor detected + // this is needed as a default if the monitor given in config above doesn't exist + if (firstLaunch) { + firstLaunch = false; + g_pCompositor->warpCursorTo(POS, true); + g_pInputManager->refocus(); + return; + } + + if (!cursorDefaultDone && *PCURSORMONITOR != STRVAL_EMPTY) { + if (*PCURSORMONITOR == monitor->szName) { + cursorDefaultDone = true; + g_pCompositor->warpCursorTo(POS, true); + g_pInputManager->refocus(); + return; + } + } + + // modechange happend check if cursor is on that monitor and warp it to middle to not place it out of bounds if resolution changed. + if (g_pCompositor->getMonitorFromCursor() == monitor.get()) { + g_pCompositor->warpCursorTo(POS, true); + g_pInputManager->refocus(); + } +} + void CCompositor::onNewMonitor(SP output) { // add it to real auto PNEWMONITOR = g_pCompositor->m_vRealMonitors.emplace_back(makeShared(output)); @@ -2977,6 +3009,8 @@ void CCompositor::onNewMonitor(SP output) { g_pConfigManager->m_bWantsMonitorReload = true; g_pCompositor->scheduleFrameForMonitor(PNEWMONITOR.get(), IOutput::AQ_SCHEDULE_NEW_MONITOR); + checkDefaultCursorWarp(PNEWMONITOR); + for (auto const& w : g_pCompositor->m_vWindows) { if (w->m_iMonitorID == PNEWMONITOR->ID) { w->m_iLastSurfaceMonitorID = MONITOR_INVALID; diff --git a/src/managers/PointerManager.cpp b/src/managers/PointerManager.cpp index 6b2a40f5..5a192e13 100644 --- a/src/managers/PointerManager.cpp +++ b/src/managers/PointerManager.cpp @@ -18,13 +18,7 @@ CPointerManager::CPointerManager() { onMonitorLayoutChange(); PMONITOR->events.modeChanged.registerStaticListener( - [this, PMONITOR](void* owner, std::any data) { - g_pEventLoopManager->doLater([this, PMONITOR]() { - onMonitorLayoutChange(); - checkDefaultCursorWarp(PMONITOR, PMONITOR->output->name); - }); - }, - nullptr); + [this, PMONITOR](void* owner, std::any data) { g_pEventLoopManager->doLater([this, PMONITOR]() { onMonitorLayoutChange(); }); }, nullptr); PMONITOR->events.disconnect.registerStaticListener( [this, PMONITOR](void* owner, std::any data) { g_pEventLoopManager->doLater([this, PMONITOR]() { onMonitorLayoutChange(); }); }, nullptr); PMONITOR->events.destroy.registerStaticListener( @@ -44,38 +38,6 @@ CPointerManager::CPointerManager() { }); } -void CPointerManager::checkDefaultCursorWarp(SP monitor, std::string monitorName) { - static auto PCURSORMONITOR = CConfigValue("cursor:default_monitor"); - static bool cursorDefaultDone = false; - static bool firstLaunch = true; - - const auto POS = monitor->middle(); - - // by default, cursor should be set to first monitor detected - // this is needed as a default if the monitor given in config above doesn't exist - if (firstLaunch) { - firstLaunch = false; - g_pCompositor->warpCursorTo(POS, true); - g_pInputManager->refocus(); - return; - } - - if (!cursorDefaultDone && *PCURSORMONITOR != STRVAL_EMPTY) { - if (*PCURSORMONITOR == monitorName) { - cursorDefaultDone = true; - g_pCompositor->warpCursorTo(POS, true); - g_pInputManager->refocus(); - return; - } - } - - // modechange happend check if cursor is on that monitor and warp it to middle to not place it out of bounds if resolution changed. - if (g_pCompositor->getMonitorFromCursor() == monitor.get()) { - g_pCompositor->warpCursorTo(POS, true); - g_pInputManager->refocus(); - } -} - void CPointerManager::lockSoftwareAll() { for (auto const& state : monitorStates) state->softwareLocks++; diff --git a/src/managers/PointerManager.hpp b/src/managers/PointerManager.hpp index 082855b5..4a4c4f61 100644 --- a/src/managers/PointerManager.hpp +++ b/src/managers/PointerManager.hpp @@ -26,7 +26,6 @@ class CPointerManager { public: CPointerManager(); - void checkDefaultCursorWarp(SP monitor, std::string monitorName); void attachPointer(SP pointer); void attachTouch(SP touch); void attachTablet(SP tablet); From eb97d949aa31b900d9735bcb8ead47acddc1f339 Mon Sep 17 00:00:00 2001 From: Sungyoon Cho Date: Mon, 16 Sep 2024 01:31:38 +0900 Subject: [PATCH 0404/2181] textinput: don't reset if ti isn't enabled (#7798) --- src/managers/input/TextInput.cpp | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/src/managers/input/TextInput.cpp b/src/managers/input/TextInput.cpp index e601ad9a..f7a6a350 100644 --- a/src/managers/input/TextInput.cpp +++ b/src/managers/input/TextInput.cpp @@ -99,6 +99,13 @@ void CTextInput::onReset() { if (g_pInputManager->m_sIMERelay.m_pIME.expired()) return; + if (!focusedSurface()) + return; + + const auto PFOCUSEDTI = g_pInputManager->m_sIMERelay.getFocusedTextInput(); + if (!PFOCUSEDTI || PFOCUSEDTI != this) + return; + g_pInputManager->m_sIMERelay.deactivateIME(this, false); g_pInputManager->m_sIMERelay.activateIME(this); } From e87758529e9d2dc70f318346c66a9d895d4503ce Mon Sep 17 00:00:00 2001 From: AlvinaNancy <152092635+AlvinaNancy@users.noreply.github.com> Date: Sun, 15 Sep 2024 17:25:06 +0000 Subject: [PATCH 0405/2181] internal: Fix change group current fullscreen state query (#7802) --- src/desktop/Window.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/desktop/Window.cpp b/src/desktop/Window.cpp index cc5b48af..feced807 100644 --- a/src/desktop/Window.cpp +++ b/src/desktop/Window.cpp @@ -991,7 +991,7 @@ void CWindow::setGroupCurrent(PHLWINDOW pWindow) { const auto PCURRENT = getGroupCurrent(); const bool FULLSCREEN = PCURRENT->isFullscreen(); const auto WORKSPACE = PCURRENT->m_pWorkspace; - const auto MODE = PCURRENT->m_sFullscreenState.client; + const auto MODE = PCURRENT->m_sFullscreenState.internal; const auto PWINDOWSIZE = PCURRENT->m_vRealSize.goal(); const auto PWINDOWPOS = PCURRENT->m_vRealPosition.goal(); From 9e356562446f44c471ae38a80506a9df039305d6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Leiser=20Fern=C3=A1ndez=20Gallo?= Date: Sun, 15 Sep 2024 22:03:42 +0200 Subject: [PATCH 0406/2181] internal: Delay monitor events/hooks (#7797) * Delay monitor messages * Format --- src/helpers/Monitor.cpp | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/src/helpers/Monitor.cpp b/src/helpers/Monitor.cpp index 5b01d651..708a5cc8 100644 --- a/src/helpers/Monitor.cpp +++ b/src/helpers/Monitor.cpp @@ -192,10 +192,6 @@ void CMonitor::onConnect(bool noRule) { if (!activeMonitorRule.mirrorOf.empty()) setMirror(activeMonitorRule.mirrorOf); - g_pEventManager->postEvent(SHyprIPCEvent{"monitoradded", szName}); - g_pEventManager->postEvent(SHyprIPCEvent{"monitoraddedv2", std::format("{},{},{}", ID, szName, szShortDescription)}); - EMIT_HOOK_EVENT("monitorAdded", this); - if (!g_pCompositor->m_pLastMonitor) // set the last monitor if it isnt set yet g_pCompositor->setActiveMonitor(this); @@ -224,6 +220,10 @@ void CMonitor::onConnect(bool noRule) { PROTO::gamma->applyGammaToState(this); events.connect.emit(); + + g_pEventManager->postEvent(SHyprIPCEvent{"monitoradded", szName}); + g_pEventManager->postEvent(SHyprIPCEvent{"monitoraddedv2", std::format("{},{},{}", ID, szName, szShortDescription)}); + EMIT_HOOK_EVENT("monitorAdded", this); } void CMonitor::onDisconnect(bool destroy) { @@ -281,9 +281,6 @@ void CMonitor::onDisconnect(bool destroy) { Debug::log(LOG, "Removed monitor {}!", szName); - g_pEventManager->postEvent(SHyprIPCEvent{"monitorremoved", szName}); - EMIT_HOOK_EVENT("monitorRemoved", this); - if (!BACKUPMON) { Debug::log(WARN, "Unplugged last monitor, entering an unsafe state. Good luck my friend."); g_pCompositor->enterUnsafeState(); @@ -342,6 +339,9 @@ void CMonitor::onDisconnect(bool destroy) { g_pHyprRenderer->m_pMostHzMonitor = pMonitorMostHz; } std::erase_if(g_pCompositor->m_vMonitors, [&](SP& el) { return el.get() == this; }); + + g_pEventManager->postEvent(SHyprIPCEvent{"monitorremoved", szName}); + EMIT_HOOK_EVENT("monitorRemoved", this); } void CMonitor::addDamage(const pixman_region32_t* rg) { From e72ae6b25fe019404df31e783ae980f80d3eaa3c Mon Sep 17 00:00:00 2001 From: vaxerski Date: Tue, 17 Sep 2024 11:24:54 +0100 Subject: [PATCH 0407/2181] hyprctl: allow parsing empty value fixes #7821 --- src/debug/HyprCtl.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/debug/HyprCtl.cpp b/src/debug/HyprCtl.cpp index 683665be..3d4d8092 100644 --- a/src/debug/HyprCtl.cpp +++ b/src/debug/HyprCtl.cpp @@ -987,9 +987,9 @@ std::string dispatchKeyword(eHyprCtlOutputFormat format, std::string in) { const auto COMMAND = in.substr(0, secondSpacePos); const auto VALUE = in.substr(secondSpacePos + 1); - // If either COMMAND or VALUE is empty, handle accordingly - if (COMMAND.empty() || VALUE.empty()) - return "Invalid input: command or value is empty"; + // If COMMAND is empty, handle accordingly + if (COMMAND.empty()) + return "Invalid input: command is empty"; std::string retval = g_pConfigManager->parseKeyword(COMMAND, VALUE); From 581f6659f8541476da82ebd819a564780b3a969e Mon Sep 17 00:00:00 2001 From: vaxerski Date: Tue, 17 Sep 2024 12:55:48 +0100 Subject: [PATCH 0408/2181] data-device: conform to reported source actions fixes #7815 --- src/protocols/core/DataDevice.cpp | 21 ++++++++++++++++++--- src/protocols/core/DataDevice.hpp | 3 ++- src/protocols/types/DataDevice.cpp | 4 ++++ src/protocols/types/DataDevice.hpp | 1 + 4 files changed, 25 insertions(+), 4 deletions(-) diff --git a/src/protocols/core/DataDevice.cpp b/src/protocols/core/DataDevice.cpp index eac80a83..5644f243 100644 --- a/src/protocols/core/DataDevice.cpp +++ b/src/protocols/core/DataDevice.cpp @@ -82,8 +82,19 @@ void CWLDataOfferResource::sendData() { if (!source) return; - if (resource->version() >= 3) - resource->sendSourceActions(7); + const auto SOURCEACTIONS = source->actions(); + + if (resource->version() >= 3 && SOURCEACTIONS > 0) { + resource->sendSourceActions(SOURCEACTIONS); + if (SOURCEACTIONS & WL_DATA_DEVICE_MANAGER_DND_ACTION_MOVE) + resource->sendAction(WL_DATA_DEVICE_MANAGER_DND_ACTION_MOVE); + else if (SOURCEACTIONS & WL_DATA_DEVICE_MANAGER_DND_ACTION_COPY) + resource->sendAction(WL_DATA_DEVICE_MANAGER_DND_ACTION_COPY); + else { + LOGM(ERR, "Client bug? dnd source has no action move or copy. Sending move, f this."); + resource->sendAction(WL_DATA_DEVICE_MANAGER_DND_ACTION_MOVE); + } + } for (auto const& m : source->mimes()) { LOGM(LOG, " | offer {:x} supports mime {}", (uintptr_t)this, m); @@ -111,7 +122,7 @@ CWLDataSourceResource::CWLDataSourceResource(SP resource_, SPsetOffer([this](CWlDataSource* r, const char* mime) { mimeTypes.push_back(mime); }); resource->setSetActions([this](CWlDataSource* r, uint32_t a) { LOGM(LOG, "DataSource {:x} actions {}", (uintptr_t)this, a); - actions = (wl_data_device_manager_dnd_action)a; + supportedActions = a; }); } @@ -193,6 +204,10 @@ void CWLDataSourceResource::sendDndAction(wl_data_device_manager_dnd_action a) { resource->sendAction(a); } +uint32_t CWLDataSourceResource::actions() { + return supportedActions; +} + CWLDataDeviceResource::CWLDataDeviceResource(SP resource_) : resource(resource_) { if (!good()) return; diff --git a/src/protocols/core/DataDevice.hpp b/src/protocols/core/DataDevice.hpp index 8aaf46be..50e9ac61 100644 --- a/src/protocols/core/DataDevice.hpp +++ b/src/protocols/core/DataDevice.hpp @@ -65,6 +65,7 @@ class CWLDataSourceResource : public IDataSource { virtual bool dndDone(); virtual void error(uint32_t code, const std::string& msg); virtual void sendDndFinished(); + virtual uint32_t actions(); // wl_data_device_manager.dnd_action void sendDndDropPerformed(); void sendDndAction(wl_data_device_manager_dnd_action a); @@ -78,7 +79,7 @@ class CWLDataSourceResource : public IDataSource { WP self; std::vector mimeTypes; - uint32_t actions = 0; + uint32_t supportedActions = 0; private: SP resource; diff --git a/src/protocols/types/DataDevice.cpp b/src/protocols/types/DataDevice.cpp index e95f1c76..36a7a157 100644 --- a/src/protocols/types/DataDevice.cpp +++ b/src/protocols/types/DataDevice.cpp @@ -23,3 +23,7 @@ eDataSourceType IDataSource::type() { void IDataSource::sendDndFinished() { ; } + +uint32_t IDataSource::actions() { + return 7; // all +} diff --git a/src/protocols/types/DataDevice.hpp b/src/protocols/types/DataDevice.hpp index f6757e1c..a62cc35e 100644 --- a/src/protocols/types/DataDevice.hpp +++ b/src/protocols/types/DataDevice.hpp @@ -26,6 +26,7 @@ class IDataSource { virtual void markUsed(); virtual void error(uint32_t code, const std::string& msg) = 0; virtual eDataSourceType type(); + virtual uint32_t actions(); // wl_data_device_manager.dnd_action struct { CSignal destroy; From 3c9716acfd00c6ea1b7bcd1dc63f97b51cc09998 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andr=C3=A9=20Silva?= <123550+andresilva@users.noreply.github.com> Date: Tue, 17 Sep 2024 14:37:20 +0100 Subject: [PATCH 0409/2181] gammactrl: fix potential crash on monitor removed (#7828) --- src/protocols/GammaControl.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/protocols/GammaControl.cpp b/src/protocols/GammaControl.cpp index d7992981..077d6e2f 100644 --- a/src/protocols/GammaControl.cpp +++ b/src/protocols/GammaControl.cpp @@ -19,7 +19,7 @@ CGammaControl::CGammaControl(SP resource_, wl_resource* out pMonitor = OUTPUTRES->monitor; - if (!pMonitor) { + if (!pMonitor || !pMonitor->output) { LOGM(ERR, "No CMonitor"); resource->sendFailed(); return; From 0564b46a5e9afbf2fb51a7198452342e43ba4637 Mon Sep 17 00:00:00 2001 From: Aqa-Ib Date: Wed, 18 Sep 2024 12:05:17 +0200 Subject: [PATCH 0410/2181] dispatchers: allow moveintogroup when floating (#7818) This allows to use the moveintogroup dispatcher when windows are floating. I don't know why was this disabled in the first place though. Cheers! --- src/managers/KeybindManager.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/managers/KeybindManager.cpp b/src/managers/KeybindManager.cpp index 2f593d74..dd35bc19 100644 --- a/src/managers/KeybindManager.cpp +++ b/src/managers/KeybindManager.cpp @@ -2730,7 +2730,7 @@ SDispatchResult CKeybindManager::moveIntoGroup(std::string args) { const auto PWINDOW = g_pCompositor->m_pLastWindow.lock(); - if (!PWINDOW || PWINDOW->m_bIsFloating || PWINDOW->m_sGroupData.deny) + if (!PWINDOW || PWINDOW->m_sGroupData.deny) return {}; auto PWINDOWINDIR = g_pCompositor->getWindowInDirection(PWINDOW, arg); From 883d01084c52fdc5da0e6bfff7fd0f5cf0f62352 Mon Sep 17 00:00:00 2001 From: vaxerski Date: Wed, 18 Sep 2024 11:22:07 +0100 Subject: [PATCH 0411/2181] userchecks: add an xdg_current_desktop check ref https://github.com/hyprwm/xdg-desktop-portal-hyprland/issues/251 if the XDG_CURRENT_DESKTOP is externally managed (e.g. DE, DM, etc) Hyprland will not overwrite it. In those cases, if that's undesired, portals and other apps depending on it might break. --- src/Compositor.cpp | 12 +++++++++++- src/config/ConfigDescriptions.hpp | 6 ++++++ src/config/ConfigManager.cpp | 1 + 3 files changed, 18 insertions(+), 1 deletion(-) diff --git a/src/Compositor.cpp b/src/Compositor.cpp index 8e1b11b0..232ba4a6 100644 --- a/src/Compositor.cpp +++ b/src/Compositor.cpp @@ -2696,7 +2696,17 @@ WORKSPACEID CCompositor::getNewSpecialID() { } void CCompositor::performUserChecks() { - ; // intentional + static auto PNOCHECKXDG = CConfigValue("misc:disable_xdg_env_checks"); + + if (!*PNOCHECKXDG) { + const auto CURRENT_DESKTOP_ENV = getenv("XDG_CURRENT_DESKTOP"); + if (!CURRENT_DESKTOP_ENV || std::string{CURRENT_DESKTOP_ENV} != "Hyprland") { + g_pHyprNotificationOverlay->addNotification( + std::format("Your XDG_CURRENT_DESKTOP environment seems to be managed externally, and the current value is {}.\nThis might cause issues unless it's intentional.", + CURRENT_DESKTOP_ENV ? CURRENT_DESKTOP_ENV : "unset"), + CColor{}, 15000, ICON_WARNING); + } + } } void CCompositor::moveWindowToWorkspaceSafe(PHLWINDOW pWindow, PHLWORKSPACE pWorkspace) { diff --git a/src/config/ConfigDescriptions.hpp b/src/config/ConfigDescriptions.hpp index 44b5ee4a..84ac1a41 100644 --- a/src/config/ConfigDescriptions.hpp +++ b/src/config/ConfigDescriptions.hpp @@ -1049,6 +1049,12 @@ inline static const std::vector CONFIG_OPTIONS = { .type = CONFIG_OPTION_INT, .data = SConfigOptionDescription::SRangeData{15, 1, 120}, }, + SConfigOptionDescription{ + .value = "misc:disable_xdg_env_checks", + .description = "disable the warning if XDG environment is externally managed", + .type = CONFIG_OPTION_BOOL, + .data = SConfigOptionDescription::SBoolData{false}, + }, /* * binds: diff --git a/src/config/ConfigManager.cpp b/src/config/ConfigManager.cpp index 57cd2350..27e8fdb0 100644 --- a/src/config/ConfigManager.cpp +++ b/src/config/ConfigManager.cpp @@ -371,6 +371,7 @@ CConfigManager::CConfigManager() { m_pConfig->addConfigValue("misc:initial_workspace_tracking", Hyprlang::INT{1}); m_pConfig->addConfigValue("misc:middle_click_paste", Hyprlang::INT{1}); m_pConfig->addConfigValue("misc:render_unfocused_fps", Hyprlang::INT{15}); + m_pConfig->addConfigValue("misc:disable_xdg_env_checks", Hyprlang::INT{0}); m_pConfig->addConfigValue("group:insert_after_current", Hyprlang::INT{1}); m_pConfig->addConfigValue("group:focus_removed_window", Hyprlang::INT{1}); From d936eb437b5d33cda21e1502a96dc7d83446aca5 Mon Sep 17 00:00:00 2001 From: Mihai Fufezan Date: Wed, 18 Sep 2024 17:26:51 +0300 Subject: [PATCH 0412/2181] flake.lock: update aquamarine --- flake.lock | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/flake.lock b/flake.lock index 55dc6939..35974921 100644 --- a/flake.lock +++ b/flake.lock @@ -16,11 +16,11 @@ ] }, "locked": { - "lastModified": 1725753098, - "narHash": "sha256-/NO/h/qD/eJXAQr/fHA4mdDgYsNT9thHQ+oT6KPi2ac=", + "lastModified": 1726665257, + "narHash": "sha256-rEzEZtd3iyVo5RJ1OGujOlnywNf3gsrOnjAn1NLciD4=", "owner": "hyprwm", "repo": "aquamarine", - "rev": "e4a13203112a036fc7f437d391c7810f3dd5ab52", + "rev": "752d0fbd141fabb5a1e7f865199b80e6e76f8d8e", "type": "github" }, "original": { From 6b6554adb8c2fba5d89554af6fc467dcd15cedc0 Mon Sep 17 00:00:00 2001 From: Mihai Fufezan Date: Sat, 14 Sep 2024 00:06:43 +0300 Subject: [PATCH 0413/2181] flake.nix: inherit stdenv from package Means we no longer have to change the base stdenv in two places. --- flake.nix | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/flake.nix b/flake.nix index 9e1e3ab4..ef914627 100644 --- a/flake.nix +++ b/flake.nix @@ -95,13 +95,9 @@ devShells = eachSystem (system: { default = pkgsFor.${system}.mkShell.override { - stdenv = pkgsFor.${system}.gcc14Stdenv; + inherit (self.packages.${system}.default) stdenv; } { name = "hyprland-shell"; - nativeBuildInputs = with pkgsFor.${system}; [ - expat - libxml2 - ]; hardeningDisable = ["fortify"]; inputsFrom = [pkgsFor.${system}.hyprland]; packages = [pkgsFor.${system}.clang-tools]; From cbc0ff6ec0670e904758069c3844b05086bb15d3 Mon Sep 17 00:00:00 2001 From: Mihai Fufezan Date: Wed, 18 Sep 2024 18:54:00 +0300 Subject: [PATCH 0414/2181] Nix: disable PCH --- nix/default.nix | 1 + 1 file changed, 1 insertion(+) diff --git a/nix/default.nix b/nix/default.nix index 8d912fe6..b167a4df 100644 --- a/nix/default.nix +++ b/nix/default.nix @@ -149,6 +149,7 @@ assert lib.assertMsg (!hidpiXWayland) "The option `hidpiXWayland` has been remov (lib.mesonEnable "xwayland" enableXWayland) (lib.mesonEnable "legacy_renderer" legacyRenderer) (lib.mesonEnable "systemd" withSystemd) + (lib.mesonEnable "b_pch" false) ]; postInstall = '' From b248d59713d99a8338d25f4765fd2f564069f98b Mon Sep 17 00:00:00 2001 From: Mihai Fufezan Date: Wed, 18 Sep 2024 19:43:56 +0300 Subject: [PATCH 0415/2181] Nix: fix meson PCH flag --- nix/default.nix | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/nix/default.nix b/nix/default.nix index b167a4df..11e18e6c 100644 --- a/nix/default.nix +++ b/nix/default.nix @@ -149,7 +149,7 @@ assert lib.assertMsg (!hidpiXWayland) "The option `hidpiXWayland` has been remov (lib.mesonEnable "xwayland" enableXWayland) (lib.mesonEnable "legacy_renderer" legacyRenderer) (lib.mesonEnable "systemd" withSystemd) - (lib.mesonEnable "b_pch" false) + "-Db_pch=false" ]; postInstall = '' From 94140e886ea8c4ac34478d290c212f0f5454ab2e Mon Sep 17 00:00:00 2001 From: Jasson Date: Wed, 18 Sep 2024 13:12:26 -0400 Subject: [PATCH 0416/2181] xwayland: Some readability improvements (#7807) * Readability improvements xwayland server * Made requested changes * removed braces * fix * Ok this time is fixed * Formatting --- src/xwayland/Server.cpp | 194 ++++++++++++++++++++++------------------ 1 file changed, 105 insertions(+), 89 deletions(-) diff --git a/src/xwayland/Server.cpp b/src/xwayland/Server.cpp index f3bf5768..97caf9e3 100644 --- a/src/xwayland/Server.cpp +++ b/src/xwayland/Server.cpp @@ -1,105 +1,115 @@ +#include #ifndef NO_XWAYLAND -#include "Server.hpp" -#include "../defines.hpp" -#include "../Compositor.hpp" -#include "../managers/CursorManager.hpp" -#include "XWayland.hpp" - +#include +#include #include #include +#include +#include #include #include #include -#include #include -#include -#include -#include #include #include +#include #include -#include +#include +#include +#include -// TODO: cleanup -static bool set_cloexec(int fd, bool cloexec) { +#include "Server.hpp" +#include "XWayland.hpp" +#include "debug/Log.hpp" +#include "../defines.hpp" +#include "../Compositor.hpp" +#include "../managers/CursorManager.hpp" + +// Constants +constexpr int SOCKET_DIR_PERMISSIONS = 0755; +constexpr int SOCKET_BACKLOG = 1; +constexpr int MAX_SOCKET_RETRIES = 32; +constexpr int LOCK_FILE_MODE = 044; + +static bool setCloseOnExec(int fd, bool cloexec) { int flags = fcntl(fd, F_GETFD); if (flags == -1) { Debug::log(ERR, "fcntl failed"); return false; } - if (cloexec) { + + if (cloexec) flags = flags | FD_CLOEXEC; - } else { + else flags = flags & ~FD_CLOEXEC; - } + if (fcntl(fd, F_SETFD, flags) == -1) { Debug::log(ERR, "fcntl failed"); return false; } + return true; } -static int openSocket(struct sockaddr_un* addr, size_t path_size) { - int fd, rc; - socklen_t size = offsetof(struct sockaddr_un, sun_path) + path_size + 1; +void cleanUpSocket(int fd, const char* path) { + close(fd); + if (path[0]) + unlink(path); +} - fd = socket(AF_UNIX, SOCK_STREAM, 0); +static int createSocket(struct sockaddr_un* addr, size_t path_size) { + socklen_t size = offsetof(struct sockaddr_un, sun_path) + path_size + 1; + int fd = socket(AF_UNIX, SOCK_STREAM, 0); if (fd < 0) { - Debug::log(ERR, "failed to create socket {}{}", addr->sun_path[0] ? addr->sun_path[0] : '@', addr->sun_path + 1); + Debug::log(ERR, "Failed to create socket {}{}", addr->sun_path[0] ? addr->sun_path[0] : '@', addr->sun_path + 1); return -1; } - if (!set_cloexec(fd, true)) { + + if (!setCloseOnExec(fd, true)) { close(fd); return -1; } - if (addr->sun_path[0]) { + if (addr->sun_path[0]) unlink(addr->sun_path); - } + if (bind(fd, (struct sockaddr*)addr, size) < 0) { - rc = errno; - Debug::log(ERR, "failed to bind socket {}{}", addr->sun_path[0] ? addr->sun_path[0] : '@', addr->sun_path + 1); - goto cleanup; + Debug::log(ERR, "Failed to bind socket {}{}", addr->sun_path[0] ? addr->sun_path[0] : '@', addr->sun_path + 1); + cleanUpSocket(fd, addr->sun_path); + return -1; } - if (listen(fd, 1) < 0) { - rc = errno; - Debug::log(ERR, "failed to listen to socket {}{}", addr->sun_path[0] ? addr->sun_path[0] : '@', addr->sun_path + 1); - goto cleanup; + + if (listen(fd, SOCKET_BACKLOG) < 0) { + Debug::log(ERR, "Failed to listen to socket {}{}", addr->sun_path[0] ? addr->sun_path[0] : '@', addr->sun_path + 1); + cleanUpSocket(fd, addr->sun_path); + return -1; } return fd; - -cleanup: - close(fd); - if (addr->sun_path[0]) { - unlink(addr->sun_path); - } - errno = rc; - return -1; } static bool checkPermissionsForSocketDir(void) { struct stat buf; if (lstat("/tmp/.X11-unix", &buf)) { - Debug::log(ERR, "Failed statting X11 socket dir"); + Debug::log(ERR, "Failed to stat X11 socket dir"); return false; } if (!(buf.st_mode & S_IFDIR)) { - Debug::log(ERR, "X11 socket dir is not a dir"); + Debug::log(ERR, "X11 socket dir is not a directory"); return false; } if (!((buf.st_uid == 0) || (buf.st_uid == getuid()))) { - Debug::log(ERR, "X11 socket dir is not ours"); + Debug::log(ERR, "X11 socket dir is not owned by root or current user"); return false; } if (!(buf.st_mode & S_ISVTX)) { if ((buf.st_mode & (S_IWGRP | S_IWOTH))) { - Debug::log(ERR, "X11 socket dir is sticky by others"); + Debug::log(ERR, "X11 socket dir is writable by others"); return false; } } @@ -107,38 +117,51 @@ static bool checkPermissionsForSocketDir(void) { return true; } -static bool openSockets(std::array& sockets, int display) { - auto ret = mkdir("/tmp/.X11-unix", 755); - - if (ret != 0) { - if (errno == EEXIST) { - if (!checkPermissionsForSocketDir()) - return false; - } else { - Debug::log(ERR, "XWayland: couldn't create socket dir"); +static bool ensureSocketDirExists() { + if (mkdir("/tmp/.X11-unix", SOCKET_DIR_PERMISSIONS) != 0) { + if (errno == EEXIST) + return checkPermissionsForSocketDir(); + else { + Debug::log(ERR, "XWayland: Couldn't create socket dir"); return false; } } - std::string path; + return true; +} + +static std::string getSocketPath(int display, bool isLinux) { + if (isLinux) + return std::format("/tmp/.X11-unix{}", display); + + return std::format("/tmp/.X11-unix{}_", display); +} + +static bool openSockets(std::array& sockets, int display) { + if (!ensureSocketDirExists()) + return false; + sockaddr_un addr = {.sun_family = AF_UNIX}; + std::string path; #ifdef __linux__ // cursed... addr.sun_path[0] = 0; - path = std::format("/tmp/.X11-unix/X{}", display); + path = getSocketPath(display, true); strncpy(addr.sun_path + 1, path.c_str(), path.length() + 1); #else - path = std::format("/tmp/.X11-unix/X{}_", display); + path = getSocketPath(display, false); strncpy(addr.sun_path, path.c_str(), path.length() + 1); #endif - sockets[0] = openSocket(&addr, path.length()); + + sockets[0] = createSocket(&addr, path.length()); if (sockets[0] < 0) return false; - path = std::format("/tmp/.X11-unix/X{}", display); + path = getSocketPath(display, true); strncpy(addr.sun_path, path.c_str(), path.length() + 1); - sockets[1] = openSocket(&addr, path.length()); + + sockets[1] = createSocket(&addr, path.length()); if (sockets[1] < 0) { close(sockets[0]); sockets[0] = -1; @@ -160,39 +183,37 @@ static int xwaylandReady(int fd, uint32_t mask, void* data) { static bool safeRemove(const std::string& path) { try { return std::filesystem::remove(path); - } catch (std::exception& e) { Debug::log(ERR, "[XWayland] failed to remove {}", path); } - + } catch (const std::exception& e) { Debug::log(ERR, "[XWayland] Failed to remove {}", path); } return false; } bool CXWaylandServer::tryOpenSockets() { - for (size_t i = 0; i <= 32; ++i) { - auto LOCK = std::format("/tmp/.X{}-lock", i); + for (size_t i = 0; i <= MAX_SOCKET_RETRIES; ++i) { + std::string lockPath = std::format("/tmp/.X{}-lock", i); - if (int fd = open(LOCK.c_str(), O_WRONLY | O_CREAT | O_EXCL | O_CLOEXEC, 0444); fd >= 0) { + int fd = open(lockPath.c_str(), O_WRONLY | O_CREAT | O_EXCL | O_CLOEXEC, LOCK_FILE_MODE); + if (fd >= 0) { // we managed to open the lock if (!openSockets(xFDs, i)) { - safeRemove(LOCK); + safeRemove(lockPath); close(fd); continue; } - const auto PIDSTR = std::format("{}", getpid()); - - if (write(fd, PIDSTR.c_str(), PIDSTR.length()) != (long)PIDSTR.length()) { - safeRemove(LOCK); + const std::string pidStr = std::to_string(getpid()); + if (write(fd, pidStr.c_str(), pidStr.length()) != (long)pidStr.length()) { + safeRemove(lockPath); close(fd); continue; } close(fd); - display = i; displayName = std::format(":{}", display); break; } - int fd = open(LOCK.c_str(), O_RDONLY | O_CLOEXEC); + fd = open(lockPath.c_str(), O_RDONLY | O_CLOEXEC); if (fd < 0) continue; @@ -201,21 +222,20 @@ bool CXWaylandServer::tryOpenSockets() { read(fd, pidstr, sizeof(pidstr) - 1); close(fd); - uint64_t pid = 0; + int32_t pid = 0; try { pid = std::stoi(std::string{pidstr, 11}); } catch (...) { continue; } if (kill(pid, 0) != 0 && errno == ESRCH) { - if (!safeRemove(LOCK)) + if (!safeRemove(lockPath)) continue; - i--; } } if (display < 0) { - Debug::log(ERR, "Failed to find a suitable socket for xwayland"); + Debug::log(ERR, "Failed to find a suitable socket for XWayland"); return false; } @@ -232,19 +252,17 @@ CXWaylandServer::~CXWaylandServer() { if (display < 0) return; - if (xFDs[0]) - close(xFDs[0]); - if (xFDs[1]) - close(xFDs[1]); + close(xFDs[0]); + close(xFDs[1]); - auto LOCK = std::format("/tmp/.X{}-lock", display); - safeRemove(LOCK); + std::string lockPath = std::format("/tmp/.X{}-lock", display); + safeRemove(lockPath); std::string path; #ifdef __linux__ - path = std::format("/tmp/.X11-unix/X{}", display); + path = getSocketPath(display, true); #else - path = std::format("/tmp/.X11-unix/X{}_", display); + path = getSocketPath(display, false); #endif safeRemove(path); } @@ -256,7 +274,6 @@ void CXWaylandServer::die() { if (xFDReadEvents[0]) { wl_event_source_remove(xFDReadEvents[0]); wl_event_source_remove(xFDReadEvents[1]); - xFDReadEvents = {nullptr, nullptr}; } @@ -298,7 +315,7 @@ bool CXWaylandServer::create() { } void CXWaylandServer::runXWayland(int notifyFD) { - if (!set_cloexec(xFDs[0], false) || !set_cloexec(xFDs[1], false) || !set_cloexec(waylandFDs[1], false) || !set_cloexec(xwmFDs[1], false)) { + if (!setCloseOnExec(xFDs[0], false) || !setCloseOnExec(xFDs[1], false) || !setCloseOnExec(waylandFDs[1], false) || !setCloseOnExec(xwmFDs[1], false)) { Debug::log(ERR, "Failed to unset cloexec on fds"); _exit(EXIT_FAILURE); } @@ -325,7 +342,7 @@ bool CXWaylandServer::start() { return false; } - if (!set_cloexec(waylandFDs[0], true) || !set_cloexec(waylandFDs[1], true)) { + if (!setCloseOnExec(waylandFDs[0], true) || !setCloseOnExec(waylandFDs[1], true)) { Debug::log(ERR, "set_cloexec failed (1)"); die(); return false; @@ -337,7 +354,7 @@ bool CXWaylandServer::start() { return false; } - if (!set_cloexec(xwmFDs[0], true) || !set_cloexec(xwmFDs[1], true)) { + if (!setCloseOnExec(xwmFDs[0], true) || !setCloseOnExec(xwmFDs[1], true)) { Debug::log(ERR, "set_cloexec failed (2)"); die(); return false; @@ -359,7 +376,7 @@ bool CXWaylandServer::start() { return false; } - if (!set_cloexec(notify[0], true)) { + if (!setCloseOnExec(notify[0], true)) { Debug::log(ERR, "set_cloexec failed (3)"); close(notify[0]); close(notify[1]); @@ -382,9 +399,8 @@ bool CXWaylandServer::start() { if (pid < 0) { Debug::log(ERR, "second fork failed"); _exit(1); - } else if (pid == 0) { + } else if (pid == 0) runXWayland(notify[1]); - } _exit(0); } From e6cf643f5ab1c1545fb858ab1fd9d7538ef9e0f3 Mon Sep 17 00:00:00 2001 From: Vaxry <43317083+vaxerski@users.noreply.github.com> Date: Wed, 18 Sep 2024 18:47:53 +0100 Subject: [PATCH 0417/2181] pointermgr: Hide hardware cursor on leave (#7806) --- src/managers/PointerManager.cpp | 31 +++++++++++++++++++++++++++++-- 1 file changed, 29 insertions(+), 2 deletions(-) diff --git a/src/managers/PointerManager.cpp b/src/managers/PointerManager.cpp index 5a192e13..3dcee431 100644 --- a/src/managers/PointerManager.cpp +++ b/src/managers/PointerManager.cpp @@ -208,9 +208,8 @@ void CPointerManager::recheckEnteredOutputs() { // if we are using hw cursors, prevent // the cursor from being stuck at the last point. - // if we are leaving it, move it to narnia. if (!s->hardwareFailed && (s->monitor->output->getBackend()->capabilities() & Aquamarine::IBackendImplementation::eBackendCapabilities::AQ_BACKEND_CAPABILITY_POINTER)) - s->monitor->output->moveCursor({-1337, -420}); + setHWCursorBuffer(s, nullptr); if (!currentCursorImage.surface) continue; @@ -269,6 +268,8 @@ void CPointerManager::resetCursorImage(bool apply) { void CPointerManager::updateCursorBackend() { static auto PNOHW = CConfigValue("cursor:no_hardware_cursors"); + const auto CURSORBOX = getCursorBoxGlobal(); + for (auto const& m : g_pCompositor->m_vMonitors) { auto state = stateFor(m); @@ -277,6 +278,15 @@ void CPointerManager::updateCursorBackend() { continue; } + auto CROSSES = !m->logicalBox().intersection(CURSORBOX).empty(); + + if (!CROSSES) { + if (state->cursorFrontBuffer) + setHWCursorBuffer(state, nullptr); + + continue; + } + if (state->softwareLocks > 0 || *PNOHW || !attemptHardwareCursor(state)) { Debug::log(TRACE, "Output {} rejected hardware cursors, falling back to sw", m->szName); state->box = getCursorBoxLogicalForMonitor(state->monitor.lock()); @@ -297,17 +307,34 @@ void CPointerManager::onCursorMoved() { if (!hasCursor()) return; + const auto CURSORBOX = getCursorBoxGlobal(); + bool recalc = false; + for (auto const& m : g_pCompositor->m_vMonitors) { auto state = stateFor(m); state->box = getCursorBoxLogicalForMonitor(state->monitor.lock()); + auto CROSSES = !m->logicalBox().intersection(CURSORBOX).empty(); + + if (!CROSSES && state->cursorFrontBuffer) { + Debug::log(TRACE, "onCursorMoved for output {}: cursor left the viewport, removing it from the backend", m->szName); + setHWCursorBuffer(state, nullptr); + continue; + } else if (CROSSES && !state->cursorFrontBuffer) { + Debug::log(TRACE, "onCursorMoved for output {}: cursor entered the output, but no front buffer, forcing recalc", m->szName); + recalc = true; + } + if (state->hardwareFailed || !state->entered) continue; const auto CURSORPOS = getCursorPosForMonitor(m); m->output->moveCursor(CURSORPOS); } + + if (recalc) + updateCursorBackend(); } bool CPointerManager::attemptHardwareCursor(SP state) { From 1bc05b1f9fd55f2a7371082e6914622e4584ed54 Mon Sep 17 00:00:00 2001 From: Arisa Snowbell Date: Thu, 19 Sep 2024 12:08:02 +0200 Subject: [PATCH 0418/2181] xwayland: use proper path for the XWayland sockets (#7852) fixes #7849 --- src/xwayland/Server.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/xwayland/Server.cpp b/src/xwayland/Server.cpp index 97caf9e3..5ad9ff23 100644 --- a/src/xwayland/Server.cpp +++ b/src/xwayland/Server.cpp @@ -132,9 +132,9 @@ static bool ensureSocketDirExists() { static std::string getSocketPath(int display, bool isLinux) { if (isLinux) - return std::format("/tmp/.X11-unix{}", display); + return std::format("/tmp/.X11-unix/X{}", display); - return std::format("/tmp/.X11-unix{}_", display); + return std::format("/tmp/.X11-unix/X{}_", display); } static bool openSockets(std::array& sockets, int display) { From 71963972bff15acccd9abd0dfd3e70504609b7cc Mon Sep 17 00:00:00 2001 From: vaxerski Date: Thu, 19 Sep 2024 11:25:58 +0100 Subject: [PATCH 0419/2181] args: add --version to binary args --- src/main.cpp | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/src/main.cpp b/src/main.cpp index 820a248c..525ad4ff 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -4,6 +4,9 @@ #include "config/ConfigManager.hpp" #include "init/initHelpers.hpp" +#include +using namespace Hyprutils::String; + #include #include #include @@ -20,6 +23,7 @@ void help() { std::cout << " --socket NAME - Sets the Wayland socket name (for Wayland socket handover)\n"; std::cout << " --wayland-fd FD - Sets the Wayland socket fd (for Wayland socket handover)\n"; std::cout << " --i-am-really-stupid - Omits root user privileges check (why would you do that?)\n"; + std::cout << " --version -v - Print this binary's version\n"; } int main(int argc, char** argv) { @@ -109,6 +113,24 @@ int main(int argc, char** argv) { } else if (it->compare("-h") == 0 || it->compare("--help") == 0) { help(); + return 0; + } else if (it->compare("-v") == 0 || it->compare("--version") == 0) { + auto commitMsg = trim(GIT_COMMIT_MESSAGE); + std::replace(commitMsg.begin(), commitMsg.end(), '#', ' '); + std::string result = "Hyprland, built from branch " + std::string(GIT_BRANCH) + " at commit " + GIT_COMMIT_HASH + " " + GIT_DIRTY + " (" + commitMsg + + ").\nDate: " + GIT_COMMIT_DATE + "\nTag: " + GIT_TAG + ", commits: " + GIT_COMMITS + "\n\nflags: (if any)\n"; + +#ifdef LEGACY_RENDERER + result += "legacyrenderer\n"; +#endif +#ifndef ISDEBUG + result += "debug\n"; +#endif +#ifdef NO_XWAYLAND + result += "no xwayland\n"; +#endif + + std::cout << result; return 0; } else { std::cerr << "[ ERROR ] Unknown option '" << it->c_str() << "'!\n"; From 92df6b0dce1b81b130c2b0e46d206c8c3dbb2971 Mon Sep 17 00:00:00 2001 From: vaxerski Date: Thu, 19 Sep 2024 11:39:54 +0100 Subject: [PATCH 0420/2181] version: log build aquamarine version log the built against aq version, might be useful when it's mismatched to identify the problem --- CMakeLists.txt | 7 +++++-- src/debug/HyprCtl.cpp | 7 +++++-- src/main.cpp | 3 ++- 3 files changed, 12 insertions(+), 5 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 6fdf98db..b6ac8efc 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -91,11 +91,14 @@ find_package(OpenGL REQUIRED COMPONENTS ${GLES_VERSION}) pkg_check_modules(hyprctl_deps REQUIRED IMPORTED_TARGET hyprutils>=0.2.1) +pkg_check_modules(aquamarine_dep REQUIRED IMPORTED_TARGET aquamarine) + +add_compile_definitions(AQUAMARINE_VERSION="${aquamarine_dep_VERSION}") + pkg_check_modules( deps REQUIRED IMPORTED_TARGET - aquamarine xkbcommon uuid wayland-server @@ -220,7 +223,7 @@ target_precompile_headers(Hyprland PRIVATE message(STATUS "Setting link libraries") -target_link_libraries(Hyprland rt PkgConfig::deps) +target_link_libraries(Hyprland rt PkgConfig::aquamarine_dep PkgConfig::deps) # used by `make installheaders`, to ensure the headers are generated add_custom_target(generate-protocol-headers) diff --git a/src/debug/HyprCtl.cpp b/src/debug/HyprCtl.cpp index 3d4d8092..9faefe26 100644 --- a/src/debug/HyprCtl.cpp +++ b/src/debug/HyprCtl.cpp @@ -858,7 +858,8 @@ std::string versionRequest(eHyprCtlOutputFormat format, std::string request) { if (format == eHyprCtlOutputFormat::FORMAT_NORMAL) { std::string result = "Hyprland, built from branch " + std::string(GIT_BRANCH) + " at commit " + GIT_COMMIT_HASH + " " + GIT_DIRTY + " (" + commitMsg + - ").\nDate: " + GIT_COMMIT_DATE + "\nTag: " + GIT_TAG + ", commits: " + GIT_COMMITS + "\n\nflags: (if any)\n"; + ").\nDate: " + GIT_COMMIT_DATE + "\nTag: " + GIT_TAG + ", commits: " + GIT_COMMITS + std::string{"\nbuilt against aquamarine "} + AQUAMARINE_VERSION + "\n" + + "\n\nflags: (if any)\n"; #ifdef LEGACY_RENDERER result += "legacyrenderer\n"; @@ -881,8 +882,10 @@ std::string versionRequest(eHyprCtlOutputFormat format, std::string request) { "commit_date": "{}", "tag": "{}", "commits": "{}", + "buildAquamarine": "{}", "flags": [)#", - GIT_BRANCH, GIT_COMMIT_HASH, (strcmp(GIT_DIRTY, "dirty") == 0 ? "true" : "false"), escapeJSONStrings(commitMsg), GIT_COMMIT_DATE, GIT_TAG, GIT_COMMITS); + GIT_BRANCH, GIT_COMMIT_HASH, (strcmp(GIT_DIRTY, "dirty") == 0 ? "true" : "false"), escapeJSONStrings(commitMsg), GIT_COMMIT_DATE, GIT_TAG, GIT_COMMITS, + AQUAMARINE_VERSION); #ifdef LEGACY_RENDERER result += "\"legacyrenderer\","; diff --git a/src/main.cpp b/src/main.cpp index 525ad4ff..ba6fe505 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -118,7 +118,8 @@ int main(int argc, char** argv) { auto commitMsg = trim(GIT_COMMIT_MESSAGE); std::replace(commitMsg.begin(), commitMsg.end(), '#', ' '); std::string result = "Hyprland, built from branch " + std::string(GIT_BRANCH) + " at commit " + GIT_COMMIT_HASH + " " + GIT_DIRTY + " (" + commitMsg + - ").\nDate: " + GIT_COMMIT_DATE + "\nTag: " + GIT_TAG + ", commits: " + GIT_COMMITS + "\n\nflags: (if any)\n"; + ").\nDate: " + GIT_COMMIT_DATE + "\nTag: " + GIT_TAG + ", commits: " + GIT_COMMITS + std::string{"\nbuilt against aquamarine "} + AQUAMARINE_VERSION + "\n" + + "\n\nflags: (if any)\n"; #ifdef LEGACY_RENDERER result += "legacyrenderer\n"; From dfa1bd0cd48253a446fbe455a46f0f4d23368c02 Mon Sep 17 00:00:00 2001 From: Mihai Fufezan Date: Thu, 19 Sep 2024 13:48:31 +0000 Subject: [PATCH 0421/2181] Meson: pass AQUAMARINE_VERSION argument --- meson.build | 3 +++ src/meson.build | 2 +- 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/meson.build b/meson.build index 123c31ae..9449c241 100644 --- a/meson.build +++ b/meson.build @@ -30,6 +30,9 @@ if cpp_compiler.check_header('execinfo.h') add_project_arguments('-DHAS_EXECINFO', language: 'cpp') endif +aquamarine = dependency('aquamarine') +add_project_arguments(['-DAQUAMARINE_VERSION="@0@"'.format(aquamarine.version())], language: 'cpp') + xcb_dep = dependency('xcb', required: get_option('xwayland')) xcb_composite_dep = dependency('xcb-composite', required: get_option('xwayland')) xcb_errors_dep = dependency('xcb-errors', required: get_option('xwayland')) diff --git a/src/meson.build b/src/meson.build index 3821bd60..928cd5a7 100644 --- a/src/meson.build +++ b/src/meson.build @@ -8,7 +8,7 @@ executable( cpp_pch: 'pch/pch.hpp', dependencies: [ server_protos, - dependency('aquamarine'), + aquamarine, dependency('gbm'), dependency('xcursor'), dependency('wayland-server'), From 9856378384539e35cd943604e6a4d696a9d25447 Mon Sep 17 00:00:00 2001 From: Mihai Fufezan Date: Thu, 19 Sep 2024 18:53:34 +0300 Subject: [PATCH 0422/2181] Nix: use mold linker --- nix/default.nix | 237 +++++++++++++++++++++++++----------------------- 1 file changed, 122 insertions(+), 115 deletions(-) diff --git a/nix/default.nix b/nix/default.nix index 11e18e6c..3d621db6 100644 --- a/nix/default.nix +++ b/nix/default.nix @@ -1,6 +1,7 @@ { lib, stdenv, + stdenvAdapters, pkg-config, pkgconf, makeWrapper, @@ -46,130 +47,136 @@ enableNvidiaPatches ? false, nvidiaPatches ? false, hidpiXWayland ? false, -}: -assert lib.assertMsg (!nvidiaPatches) "The option `nvidiaPatches` has been removed."; -assert lib.assertMsg (!enableNvidiaPatches) "The option `enableNvidiaPatches` has been removed."; -assert lib.assertMsg (!hidpiXWayland) "The option `hidpiXWayland` has been removed. Please refer https://wiki.hyprland.org/Configuring/XWayland"; - stdenv.mkDerivation { - pname = "hyprland${lib.optionalString debug "-debug"}"; - inherit version; +}: let + adapters = lib.flatten [ + stdenvAdapters.useMoldLinker + ]; - src = lib.cleanSourceWith { - filter = name: type: let - baseName = baseNameOf (toString name); - in - ! (lib.hasSuffix ".nix" baseName); - src = lib.cleanSource ../.; - }; + customStdenv = builtins.foldl' (acc: adapter: adapter acc) stdenv adapters; +in + assert lib.assertMsg (!nvidiaPatches) "The option `nvidiaPatches` has been removed."; + assert lib.assertMsg (!enableNvidiaPatches) "The option `enableNvidiaPatches` has been removed."; + assert lib.assertMsg (!hidpiXWayland) "The option `hidpiXWayland` has been removed. Please refer https://wiki.hyprland.org/Configuring/XWayland"; + customStdenv.mkDerivation { + pname = "hyprland${lib.optionalString debug "-debug"}"; + inherit version; - postPatch = '' - # Fix hardcoded paths to /usr installation - sed -i "s#/usr#$out#" src/render/OpenGL.cpp + src = lib.cleanSourceWith { + filter = name: type: let + baseName = baseNameOf (toString name); + in + ! (lib.hasSuffix ".nix" baseName); + src = lib.cleanSource ../.; + }; - # Remove extra @PREFIX@ to fix pkg-config paths - sed -i "s#@PREFIX@/##g" hyprland.pc.in - ''; + postPatch = '' + # Fix hardcoded paths to /usr installation + sed -i "s#/usr#$out#" src/render/OpenGL.cpp - COMMITS = revCount; - DATE = date; - DIRTY = lib.optionalString (commit == "") "dirty"; - HASH = commit; + # Remove extra @PREFIX@ to fix pkg-config paths + sed -i "s#@PREFIX@/##g" hyprland.pc.in + ''; - depsBuildBuild = [ - pkg-config - ]; + COMMITS = revCount; + DATE = date; + DIRTY = lib.optionalString (commit == "") "dirty"; + HASH = commit; - nativeBuildInputs = [ - hyprwayland-scanner - jq - makeWrapper - meson - cmake - ninja - pkg-config - python3 # for udis86 - wayland-scanner - ]; + depsBuildBuild = [ + pkg-config + ]; - outputs = [ - "out" - "man" - "dev" - ]; + nativeBuildInputs = [ + hyprwayland-scanner + jq + makeWrapper + meson + cmake + ninja + pkg-config + python3 # for udis86 + wayland-scanner + ]; - buildInputs = lib.concatLists [ - [ - aquamarine - cairo - # expat - # fribidi - git - hyprcursor - hyprlang - hyprutils - # libdatrie - libdrm - libGL - libinput - # libselinux - # libsepol - # libthai - libuuid - libxkbcommon - mesa - pango - pciutils - # pcre2 - tomlplusplus - wayland - wayland-protocols - xorg.libXcursor - ] - (lib.optionals stdenv.hostPlatform.isMusl [libexecinfo]) - (lib.optionals enableXWayland [ - xorg.libxcb - xorg.libXdmcp - xorg.xcbutilerrors - xorg.xcbutilrenderutil - xorg.xcbutilwm - xwayland - ]) - (lib.optionals withSystemd [systemd]) - ]; + outputs = [ + "out" + "man" + "dev" + ]; - mesonBuildType = - if debug - then "debug" - else "release"; - - # we want as much debug info as possible - dontStrip = debug; - - mesonFlags = [ - (lib.mesonEnable "xwayland" enableXWayland) - (lib.mesonEnable "legacy_renderer" legacyRenderer) - (lib.mesonEnable "systemd" withSystemd) - "-Db_pch=false" - ]; - - postInstall = '' - ${lib.optionalString wrapRuntimeDeps '' - wrapProgram $out/bin/Hyprland \ - --suffix PATH : ${lib.makeBinPath [ - binutils + buildInputs = lib.concatLists [ + [ + aquamarine + cairo + # expat + # fribidi + git + hyprcursor + hyprlang + hyprutils + # libdatrie + libdrm + libGL + libinput + # libselinux + # libsepol + # libthai + libuuid + libxkbcommon + mesa + pango pciutils - pkgconf - ]} - ''} - ''; + # pcre2 + tomlplusplus + wayland + wayland-protocols + xorg.libXcursor + ] + (lib.optionals stdenv.hostPlatform.isMusl [libexecinfo]) + (lib.optionals enableXWayland [ + xorg.libxcb + xorg.libXdmcp + xorg.xcbutilerrors + xorg.xcbutilrenderutil + xorg.xcbutilwm + xwayland + ]) + (lib.optionals withSystemd [systemd]) + ]; - passthru.providedSessions = ["hyprland"]; + mesonBuildType = + if debug + then "debug" + else "release"; - meta = { - homepage = "https://github.com/hyprwm/Hyprland"; - description = "Dynamic tiling Wayland compositor that doesn't sacrifice on its looks"; - license = lib.licenses.bsd3; - platforms = lib.platforms.linux; - mainProgram = "Hyprland"; - }; - } + # we want as much debug info as possible + dontStrip = debug; + + mesonFlags = [ + (lib.mesonEnable "xwayland" enableXWayland) + (lib.mesonEnable "legacy_renderer" legacyRenderer) + (lib.mesonEnable "systemd" withSystemd) + "-Db_pch=false" + ]; + + postInstall = '' + ${lib.optionalString wrapRuntimeDeps '' + wrapProgram $out/bin/Hyprland \ + --suffix PATH : ${lib.makeBinPath [ + binutils + pciutils + pkgconf + ]} + ''} + ''; + + passthru.providedSessions = ["hyprland"]; + + meta = { + homepage = "https://github.com/hyprwm/Hyprland"; + description = "Dynamic tiling Wayland compositor that doesn't sacrifice on its looks"; + license = lib.licenses.bsd3; + platforms = lib.platforms.linux; + mainProgram = "Hyprland"; + }; + } From 9e98fb0167f8bc6c5eb4510a65b42aaa3b743421 Mon Sep 17 00:00:00 2001 From: Vaxry Date: Fri, 20 Sep 2024 10:47:34 +0100 Subject: [PATCH 0423/2181] dmabuffer: attempt importing failed dmabufs as implicit don't ask me why, vulkan doesn't like this. funny note, broken on wlroots :P fixes #7037 --- src/protocols/types/DMABuffer.cpp | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/src/protocols/types/DMABuffer.cpp b/src/protocols/types/DMABuffer.cpp index 63a26c76..a8c7248e 100644 --- a/src/protocols/types/DMABuffer.cpp +++ b/src/protocols/types/DMABuffer.cpp @@ -16,8 +16,15 @@ CDMABuffer::CDMABuffer(uint32_t id, wl_client* client, Aquamarine::SDMABUFAttrs auto eglImage = g_pHyprOpenGL->createEGLImage(attrs); - if (!eglImage) - return; + if (!eglImage) { + Debug::log(ERR, "CDMABuffer: failed to import EGLImage, retrying as implicit"); + attrs.modifier = DRM_FORMAT_MOD_INVALID; + eglImage = g_pHyprOpenGL->createEGLImage(attrs); + if (!eglImage) { + Debug::log(ERR, "CDMABuffer: failed to import EGLImage"); + return; + } + } texture = makeShared(attrs, eglImage); // texture takes ownership of the eglImage opaque = FormatUtils::isFormatOpaque(attrs.format); From 4414cd07e257a57362e73d1f6efe1df692ae3762 Mon Sep 17 00:00:00 2001 From: Jasson Date: Fri, 20 Sep 2024 07:32:04 -0400 Subject: [PATCH 0424/2181] xwm: Minor cleanup, add wrappers for basic types (#7856) --- src/xwayland/XDataSource.cpp | 2 +- src/xwayland/XSurface.cpp | 13 ++++---- src/xwayland/XWM.cpp | 37 +++++++++------------ src/xwayland/XWM.hpp | 62 ++++++++++++++++++++++++++++++------ 4 files changed, 74 insertions(+), 40 deletions(-) diff --git a/src/xwayland/XDataSource.cpp b/src/xwayland/XDataSource.cpp index f4059ee1..c6495435 100644 --- a/src/xwayland/XDataSource.cpp +++ b/src/xwayland/XDataSource.cpp @@ -1,8 +1,8 @@ #ifndef NO_XWAYLAND -#include "XDataSource.hpp" #include "XWayland.hpp" #include "../defines.hpp" +#include "XDataSource.hpp" #include diff --git a/src/xwayland/XSurface.cpp b/src/xwayland/XSurface.cpp index 02fe2b3b..e734c153 100644 --- a/src/xwayland/XSurface.cpp +++ b/src/xwayland/XSurface.cpp @@ -5,8 +5,8 @@ #ifndef NO_XWAYLAND -#include "../Compositor.hpp" #include +#include "../Compositor.hpp" CXWaylandSurface::CXWaylandSurface(uint32_t xID_, CBox geometry_, bool OR) : xID(xID_), geometry(geometry_), overrideRedirect(OR) { xcb_res_query_client_ids_cookie_t client_id_cookie = {0}; @@ -196,12 +196,11 @@ void CXWaylandSurface::restackToTop() { xcb_configure_window(g_pXWayland->pWM->connection, xID, XCB_CONFIG_WINDOW_STACK_MODE, values); - for (auto it = g_pXWayland->pWM->mappedSurfacesStacking.begin(); it != g_pXWayland->pWM->mappedSurfacesStacking.end(); ++it) { - if (*it == self) { - std::rotate(it, it + 1, g_pXWayland->pWM->mappedSurfacesStacking.end()); - break; - } - } + auto& stack = g_pXWayland->pWM->mappedSurfacesStacking; + auto it = std::find(stack.begin(), stack.end(), self); + + if (it != stack.end()) + std::rotate(it, it + 1, stack.end()); g_pXWayland->pWM->updateClientList(); diff --git a/src/xwayland/XWM.cpp b/src/xwayland/XWM.cpp index e8e2258a..dcb22eae 100644 --- a/src/xwayland/XWM.cpp +++ b/src/xwayland/XWM.cpp @@ -1,20 +1,21 @@ #include "helpers/math/Math.hpp" +#include #ifndef NO_XWAYLAND +#include +#include +#include +#include +#include +#include + #include "XWayland.hpp" #include "../defines.hpp" -#include #include "../Compositor.hpp" +#include "../protocols/core/Seat.hpp" +#include "../managers/SeatManager.hpp" #include "../protocols/XWaylandShell.hpp" #include "../protocols/core/Compositor.hpp" -#include "../managers/SeatManager.hpp" -#include "../protocols/core/Seat.hpp" -#include -#include -#include -#include - -#include #define XCB_EVENT_RESPONSE_TYPE_MASK 0x7f #define INCR_CHUNK_SIZE (64 * 1024) @@ -830,15 +831,15 @@ void CXWM::getRenderFormat() { free(reply); } -CXWM::CXWM() { - connection = xcb_connect_to_fd(g_pXWayland->pServer->xwmFDs[0], nullptr); +CXWM::CXWM() : connection(g_pXWayland->pServer->xwmFDs[0]) { - if (int ret = xcb_connection_has_error(connection); ret) { - Debug::log(ERR, "[xwm] Couldn't start, error {}", ret); + if (connection.hasError()) { + Debug::log(ERR, "[xwm] Couldn't start, error {}", connection.hasError()); return; } - if (xcb_errors_context_new(connection, &errors)) { + CXCBErrorContext xcbErrCtx(connection); + if (!xcbErrCtx.isValid()) { Debug::log(ERR, "[xwm] Couldn't allocate errors context"); return; } @@ -867,10 +868,7 @@ CXWM::CXWM() { }; xcb_change_property(connection, XCB_PROP_MODE_REPLACE, screen->root, HYPRATOMS["_NET_SUPPORTED"], XCB_ATOM_ATOM, 32, sizeof(supported) / sizeof(*supported), supported); - xcb_flush(connection); - setActiveWindow(XCB_WINDOW_NONE); - initSelection(); listeners.newWLSurface = PROTO::compositor->events.newSurface.registerListener([this](std::any d) { onNewSurface(std::any_cast>(d)); }); @@ -882,11 +880,6 @@ CXWM::CXWM() { } CXWM::~CXWM() { - if (errors) - xcb_errors_context_free(errors); - - if (connection) - xcb_disconnect(connection); if (eventSource) wl_event_source_remove(eventSource); diff --git a/src/xwayland/XWM.hpp b/src/xwayland/XWM.hpp index 59695720..ba00dd8d 100644 --- a/src/xwayland/XWM.hpp +++ b/src/xwayland/XWM.hpp @@ -1,17 +1,16 @@ #pragma once -#include "../helpers/signal/Signal.hpp" -#include "../helpers/memory/Memory.hpp" -#include "../helpers/WLListener.hpp" #include "../macros.hpp" - #include "XDataSource.hpp" +#include "../helpers/WLListener.hpp" +#include "../helpers/memory/Memory.hpp" +#include "../helpers/signal/Signal.hpp" #include -#include -#include -#include #include +#include +#include +#include struct wl_event_source; class CXWaylandSurfaceResource; @@ -58,6 +57,49 @@ struct SXSelection { std::unique_ptr transfer; }; +class CXCBConnection { + public: + CXCBConnection(int fd) { + connection = xcb_connect_to_fd(fd, nullptr); + } + + ~CXCBConnection() { + if (connection) + xcb_disconnect(connection); + } + + bool hasError() const { + return xcb_connection_has_error(connection); + } + + operator xcb_connection_t*() const { + return connection; + } + + private: + xcb_connection_t* connection = nullptr; +}; + +class CXCBErrorContext { + public: + explicit CXCBErrorContext(xcb_connection_t* connection) { + if (xcb_errors_context_new(connection, &errors) != 0) + errors = nullptr; + } + + ~CXCBErrorContext() { + if (errors) + xcb_errors_context_free(errors); + } + + bool isValid() const { + return errors != nullptr; + } + + private: + xcb_errors_context_t* errors = nullptr; +}; + class CXWM { public: CXWM(); @@ -123,9 +165,9 @@ class CXWM { void readProp(SP XSURF, uint32_t atom, xcb_get_property_reply_t* reply); // - xcb_connection_t* connection = nullptr; - xcb_errors_context_t* errors = nullptr; - xcb_screen_t* screen = nullptr; + CXCBConnection connection; + xcb_errors_context_t* errors = nullptr; + xcb_screen_t* screen = nullptr; xcb_window_t wmWindow; From 278583b8a1ab66272a4c437ed1acd7936a6a5c36 Mon Sep 17 00:00:00 2001 From: Mihai Fufezan Date: Fri, 20 Sep 2024 20:16:13 +0300 Subject: [PATCH 0425/2181] flake.lock: update --- flake.lock | 24 +++++++++++++++--------- flake.nix | 2 ++ 2 files changed, 17 insertions(+), 9 deletions(-) diff --git a/flake.lock b/flake.lock index 35974921..608c5bbb 100644 --- a/flake.lock +++ b/flake.lock @@ -139,11 +139,11 @@ ] }, "locked": { - "lastModified": 1721324119, - "narHash": "sha256-SOOqIT27/X792+vsLSeFdrNTF+OSRp5qXv6Te+fb2Qg=", + "lastModified": 1726840673, + "narHash": "sha256-HIPEXyRRVZoqD6U+lFS1B0tsIU7p83FaB9m7KT/x6mQ=", "owner": "hyprwm", "repo": "hyprwayland-scanner", - "rev": "a048a6cb015340bd82f97c1f40a4b595ca85cc30", + "rev": "b68dab23fc922eae99306988133ee80a40b39ca5", "type": "github" }, "original": { @@ -154,11 +154,11 @@ }, "nixpkgs": { "locked": { - "lastModified": 1725983898, - "narHash": "sha256-4b3A9zPpxAxLnkF9MawJNHDtOOl6ruL0r6Og1TEDGCE=", + "lastModified": 1726755586, + "narHash": "sha256-PmUr/2GQGvFTIJ6/Tvsins7Q43KTMvMFhvG6oaYK+Wk=", "owner": "NixOS", "repo": "nixpkgs", - "rev": "1355a0cbfeac61d785b7183c0caaec1f97361b43", + "rev": "c04d5652cfa9742b1d519688f65d1bbccea9eb7e", "type": "github" }, "original": { @@ -201,6 +201,12 @@ "hyprlang": [ "hyprlang" ], + "hyprutils": [ + "hyprutils" + ], + "hyprwayland-scanner": [ + "hyprwayland-scanner" + ], "nixpkgs": [ "nixpkgs" ], @@ -209,11 +215,11 @@ ] }, "locked": { - "lastModified": 1726046979, - "narHash": "sha256-6SEsjurq9cdTkITA6d49ncAJe4O/8CgRG5/F//s6Xh8=", + "lastModified": 1726851729, + "narHash": "sha256-1z0esr5lBeUMlrPZ9gZmqZT8oTQekxJi53HAW4cH0Ms=", "owner": "hyprwm", "repo": "xdg-desktop-portal-hyprland", - "rev": "e695669fd8e1d1be9eaae40f35e00f8bd8b64c18", + "rev": "73b8c4f1150040644cf678aa8bbf2cec48a433cf", "type": "github" }, "original": { diff --git a/flake.nix b/flake.nix index ef914627..ef48b2d1 100644 --- a/flake.nix +++ b/flake.nix @@ -46,6 +46,8 @@ inputs.nixpkgs.follows = "nixpkgs"; inputs.systems.follows = "systems"; inputs.hyprlang.follows = "hyprlang"; + inputs.hyprutils.follows = "hyprutils"; + inputs.hyprwayland-scanner.follows = "hyprwayland-scanner"; }; }; From db0b764a5ac22e752d8557cc1e1e5a42ac58c7e4 Mon Sep 17 00:00:00 2001 From: Vaxry Date: Fri, 20 Sep 2024 22:56:10 +0100 Subject: [PATCH 0426/2181] shm: send a static list of shm formats fixes #7733 --- src/protocols/core/Shm.cpp | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/src/protocols/core/Shm.cpp b/src/protocols/core/Shm.cpp index b09326bd..a8c98bb0 100644 --- a/src/protocols/core/Shm.cpp +++ b/src/protocols/core/Shm.cpp @@ -193,11 +193,8 @@ void CWLSHMProtocol::bindManager(wl_client* client, void* data, uint32_t ver, ui DRM_FORMAT_XBGR8888, DRM_FORMAT_ABGR8888, DRM_FORMAT_XRGB2101010, DRM_FORMAT_ARGB2101010, DRM_FORMAT_XBGR2101010, DRM_FORMAT_ABGR2101010, }; - for (auto const& fmt : g_pHyprOpenGL->getDRMFormats()) { - if (std::find(supportedShmFourccFormats.begin(), supportedShmFourccFormats.end(), fmt.drmFormat) == supportedShmFourccFormats.end()) - continue; - - shmFormats.push_back(fmt.drmFormat); + for (auto const& fmt : supportedShmFourccFormats) { + shmFormats.push_back(fmt); } } From 9232bc2c00a57b99ac876b43fdfedfa25c2de774 Mon Sep 17 00:00:00 2001 From: Vaxry Date: Sat, 21 Sep 2024 00:33:48 +0100 Subject: [PATCH 0427/2181] internal: move to hyprutils' scopeguard bumps hyprutils dep to 0.2.2 --- CMakeLists.txt | 2 +- flake.lock | 6 +++--- src/helpers/Monitor.cpp | 3 ++- src/helpers/ScopeGuard.cpp | 10 ---------- src/helpers/ScopeGuard.hpp | 13 ------------- src/render/Renderer.cpp | 4 +++- 6 files changed, 9 insertions(+), 29 deletions(-) delete mode 100644 src/helpers/ScopeGuard.cpp delete mode 100644 src/helpers/ScopeGuard.hpp diff --git a/CMakeLists.txt b/CMakeLists.txt index b6ac8efc..e1718b2d 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -114,7 +114,7 @@ pkg_check_modules( gio-2.0 hyprlang>=0.3.2 hyprcursor>=0.1.7 - hyprutils>=0.2.1) + hyprutils>=0.2.2) find_package(hyprwayland-scanner 0.3.10 REQUIRED) diff --git a/flake.lock b/flake.lock index 608c5bbb..024bcf50 100644 --- a/flake.lock +++ b/flake.lock @@ -116,11 +116,11 @@ ] }, "locked": { - "lastModified": 1724966483, - "narHash": "sha256-WXDgKIbzjYKczxSZOsJplCS1i1yrTUpsDPuJV/xpYLo=", + "lastModified": 1726874949, + "narHash": "sha256-PNnIpwGqpTvMU3N2r0wMQwK1E+t4Bb5fbJwblQvr+80=", "owner": "hyprwm", "repo": "hyprutils", - "rev": "8976e3f6a5357da953a09511d0c7f6a890fb6ec2", + "rev": "d97af4f6bd068c03a518b597675e598f57ea2291", "type": "github" }, "original": { diff --git a/src/helpers/Monitor.cpp b/src/helpers/Monitor.cpp index 708a5cc8..223a3f94 100644 --- a/src/helpers/Monitor.cpp +++ b/src/helpers/Monitor.cpp @@ -2,7 +2,6 @@ #include "MiscFunctions.hpp" #include "math/Math.hpp" #include "sync/SyncReleaser.hpp" -#include "ScopeGuard.hpp" #include "../Compositor.hpp" #include "../config/ConfigValue.hpp" #include "../protocols/GammaControl.hpp" @@ -17,7 +16,9 @@ #include "sync/SyncTimeline.hpp" #include #include +#include using namespace Hyprutils::String; +using namespace Hyprutils::Utils; int ratHandler(void* data) { g_pHyprRenderer->renderMonitor((CMonitor*)data); diff --git a/src/helpers/ScopeGuard.cpp b/src/helpers/ScopeGuard.cpp deleted file mode 100644 index 319255cd..00000000 --- a/src/helpers/ScopeGuard.cpp +++ /dev/null @@ -1,10 +0,0 @@ -#include "ScopeGuard.hpp" - -CScopeGuard::CScopeGuard(const std::function& fn_) : fn(fn_) { - ; -} - -CScopeGuard::~CScopeGuard() { - if (fn) - fn(); -} diff --git a/src/helpers/ScopeGuard.hpp b/src/helpers/ScopeGuard.hpp deleted file mode 100644 index 8a1468eb..00000000 --- a/src/helpers/ScopeGuard.hpp +++ /dev/null @@ -1,13 +0,0 @@ -#pragma once - -#include - -// calls a function when it goes out of scope -class CScopeGuard { - public: - CScopeGuard(const std::function& fn_); - ~CScopeGuard(); - - private: - std::function fn; -}; diff --git a/src/render/Renderer.cpp b/src/render/Renderer.cpp index 08bf76cb..417a3ff8 100644 --- a/src/render/Renderer.cpp +++ b/src/render/Renderer.cpp @@ -1,7 +1,6 @@ #include "Renderer.hpp" #include "../Compositor.hpp" #include "../helpers/math/Math.hpp" -#include "../helpers/ScopeGuard.hpp" #include "../helpers/sync/SyncReleaser.hpp" #include #include @@ -23,6 +22,9 @@ #include "../helpers/sync/SyncTimeline.hpp" #include "debug/Log.hpp" +#include +using namespace Hyprutils::Utils; + extern "C" { #include } From 8579066c7a1ceb745499ea4e11d5d420b1387ec0 Mon Sep 17 00:00:00 2001 From: Mihai Fufezan Date: Sat, 21 Sep 2024 14:27:13 +0300 Subject: [PATCH 0428/2181] Nix: clean up derivation --- nix/default.nix | 58 +++++++++++++++++++++++++------------------------ 1 file changed, 30 insertions(+), 28 deletions(-) diff --git a/nix/default.nix b/nix/default.nix index 3d621db6..40675d9a 100644 --- a/nix/default.nix +++ b/nix/default.nix @@ -48,25 +48,32 @@ nvidiaPatches ? false, hidpiXWayland ? false, }: let - adapters = lib.flatten [ + inherit (builtins) baseNameOf foldl'; + inherit (lib.asserts) assertMsg; + inherit (lib.attrsets) mapAttrsToList; + inherit (lib.lists) flatten concatLists optional optionals; + inherit (lib.sources) cleanSourceWith cleanSource; + inherit (lib.strings) hasSuffix makeBinPath optionalString mesonBool mesonEnable; + + adapters = flatten [ stdenvAdapters.useMoldLinker ]; - customStdenv = builtins.foldl' (acc: adapter: adapter acc) stdenv adapters; + customStdenv = foldl' (acc: adapter: adapter acc) stdenv adapters; in - assert lib.assertMsg (!nvidiaPatches) "The option `nvidiaPatches` has been removed."; - assert lib.assertMsg (!enableNvidiaPatches) "The option `enableNvidiaPatches` has been removed."; - assert lib.assertMsg (!hidpiXWayland) "The option `hidpiXWayland` has been removed. Please refer https://wiki.hyprland.org/Configuring/XWayland"; + assert assertMsg (!nvidiaPatches) "The option `nvidiaPatches` has been removed."; + assert assertMsg (!enableNvidiaPatches) "The option `enableNvidiaPatches` has been removed."; + assert assertMsg (!hidpiXWayland) "The option `hidpiXWayland` has been removed. Please refer https://wiki.hyprland.org/Configuring/XWayland"; customStdenv.mkDerivation { - pname = "hyprland${lib.optionalString debug "-debug"}"; + pname = "hyprland${optionalString debug "-debug"}"; inherit version; - src = lib.cleanSourceWith { + src = cleanSourceWith { filter = name: type: let baseName = baseNameOf (toString name); in - ! (lib.hasSuffix ".nix" baseName); - src = lib.cleanSource ../.; + ! (hasSuffix ".nix" baseName); + src = cleanSource ../.; }; postPatch = '' @@ -79,7 +86,7 @@ in COMMITS = revCount; DATE = date; - DIRTY = lib.optionalString (commit == "") "dirty"; + DIRTY = optionalString (commit == "") "dirty"; HASH = commit; depsBuildBuild = [ @@ -104,36 +111,29 @@ in "dev" ]; - buildInputs = lib.concatLists [ + buildInputs = concatLists [ [ aquamarine cairo - # expat - # fribidi git hyprcursor hyprlang hyprutils - # libdatrie libdrm libGL libinput - # libselinux - # libsepol - # libthai libuuid libxkbcommon mesa pango pciutils - # pcre2 tomlplusplus wayland wayland-protocols xorg.libXcursor ] - (lib.optionals stdenv.hostPlatform.isMusl [libexecinfo]) - (lib.optionals enableXWayland [ + (optionals customStdenv.hostPlatform.isMusl [libexecinfo]) + (optionals enableXWayland [ xorg.libxcb xorg.libXdmcp xorg.xcbutilerrors @@ -141,7 +141,7 @@ in xorg.xcbutilwm xwayland ]) - (lib.optionals withSystemd [systemd]) + (optional withSystemd systemd) ]; mesonBuildType = @@ -152,17 +152,19 @@ in # we want as much debug info as possible dontStrip = debug; - mesonFlags = [ - (lib.mesonEnable "xwayland" enableXWayland) - (lib.mesonEnable "legacy_renderer" legacyRenderer) - (lib.mesonEnable "systemd" withSystemd) - "-Db_pch=false" + mesonFlags = flatten [ + (mapAttrsToList mesonEnable { + "xwayland" = enableXWayland; + "legacy_renderer" = legacyRenderer; + "systemd" = withSystemd; + }) + (mesonBool "b_pch" false) ]; postInstall = '' - ${lib.optionalString wrapRuntimeDeps '' + ${optionalString wrapRuntimeDeps '' wrapProgram $out/bin/Hyprland \ - --suffix PATH : ${lib.makeBinPath [ + --suffix PATH : ${makeBinPath [ binutils pciutils pkgconf From e5ff19ac0f2c8d53a0c847d06a17676e636d6447 Mon Sep 17 00:00:00 2001 From: diniamo Date: Sat, 21 Sep 2024 16:52:11 +0200 Subject: [PATCH 0429/2181] flake: update xdph --- flake.lock | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/flake.lock b/flake.lock index 024bcf50..76351cc9 100644 --- a/flake.lock +++ b/flake.lock @@ -215,11 +215,11 @@ ] }, "locked": { - "lastModified": 1726851729, - "narHash": "sha256-1z0esr5lBeUMlrPZ9gZmqZT8oTQekxJi53HAW4cH0Ms=", + "lastModified": 1726933538, + "narHash": "sha256-xTqnMoJsEojuvqJLuM+U7EZ7q71efaj3pbvjutq4TXc=", "owner": "hyprwm", "repo": "xdg-desktop-portal-hyprland", - "rev": "73b8c4f1150040644cf678aa8bbf2cec48a433cf", + "rev": "4880c50146d0c2a3152d2b02f79253810c330c11", "type": "github" }, "original": { From 508bde1f61b1264c9621b937657088f09f318ce0 Mon Sep 17 00:00:00 2001 From: Artur Manuel Date: Mon, 23 Sep 2024 16:40:19 +0100 Subject: [PATCH 0430/2181] core: add HYPRLAND_CONFIG environment variable (#7851) --- src/config/ConfigManager.cpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/config/ConfigManager.cpp b/src/config/ConfigManager.cpp index 27e8fdb0..21a3a21e 100644 --- a/src/config/ConfigManager.cpp +++ b/src/config/ConfigManager.cpp @@ -683,6 +683,10 @@ std::string CConfigManager::getMainConfigPath() { if (!g_pCompositor->explicitConfigPath.empty()) return g_pCompositor->explicitConfigPath; + if (const auto CFG_ENV = getenv("HYPRLAND_CONFIG"); CFG_ENV) + return CFG_ENV; + Debug::log(TRACE, "Seems as if HYPRLAND_CONFIG isn't set, let's see what we can do with HOME."); + static const auto paths = Hyprutils::Path::findConfig(ISDEBUG ? "hyprlandd" : "hyprland"); if (paths.first.has_value()) { return paths.first.value(); From f79497087bdea3ea2706606362ba99cfe7a956a0 Mon Sep 17 00:00:00 2001 From: Vaxry Date: Mon, 23 Sep 2024 17:59:35 +0100 Subject: [PATCH 0431/2181] internal: nuke wlsignal and related old semi-wrappers for wl_signal, they are no longer used --- src/defines.hpp | 1 - src/desktop/Subsurface.cpp | 8 +--- src/desktop/Subsurface.hpp | 4 -- src/devices/IKeyboard.hpp | 1 - src/devices/IPointer.hpp | 1 - src/devices/ITouch.hpp | 1 - src/devices/Tablet.hpp | 1 - src/helpers/WLListener.cpp | 62 ------------------------- src/helpers/WLListener.hpp | 39 ---------------- src/managers/SeatManager.hpp | 1 - src/managers/input/InputMethodPopup.hpp | 1 - src/managers/input/TextInput.hpp | 1 - src/protocols/FocusGrab.hpp | 3 -- src/protocols/PresentationTime.hpp | 2 - src/render/Renderbuffer.hpp | 1 - src/xwayland/XSurface.hpp | 1 - src/xwayland/XWM.hpp | 1 - 17 files changed, 1 insertion(+), 128 deletions(-) delete mode 100644 src/helpers/WLListener.cpp delete mode 100644 src/helpers/WLListener.hpp diff --git a/src/defines.hpp b/src/defines.hpp index 0b2c0e0c..41ee4502 100644 --- a/src/defines.hpp +++ b/src/defines.hpp @@ -1,6 +1,5 @@ #include "includes.hpp" #include "debug/Log.hpp" -#include "helpers/WLListener.hpp" #include "helpers/Color.hpp" #include "macros.hpp" #include "desktop/DesktopTypes.hpp" diff --git a/src/desktop/Subsurface.cpp b/src/desktop/Subsurface.cpp index 64dd7cf5..893411bd 100644 --- a/src/desktop/Subsurface.cpp +++ b/src/desktop/Subsurface.cpp @@ -30,13 +30,7 @@ CSubsurface::CSubsurface(SP pSubsurface, CPopup* pOwner) } CSubsurface::~CSubsurface() { - hyprListener_newSubsurface.removeCallback(); - - if (!m_pSubsurface) - return; - - hyprListener_commitSubsurface.removeCallback(); - hyprListener_destroySubsurface.removeCallback(); + ; } void CSubsurface::initSignals() { diff --git a/src/desktop/Subsurface.hpp b/src/desktop/Subsurface.hpp index 101f4f19..7829c489 100644 --- a/src/desktop/Subsurface.hpp +++ b/src/desktop/Subsurface.hpp @@ -35,10 +35,6 @@ class CSubsurface { void recheckDamageForSubsurfaces(); private: - DYNLISTENER(destroySubsurface); - DYNLISTENER(commitSubsurface); - DYNLISTENER(newSubsurface); - struct { CHyprSignalListener destroySubsurface; CHyprSignalListener commitSubsurface; diff --git a/src/devices/IKeyboard.hpp b/src/devices/IKeyboard.hpp index ad8eaf7e..759b2f58 100644 --- a/src/devices/IKeyboard.hpp +++ b/src/devices/IKeyboard.hpp @@ -1,7 +1,6 @@ #pragma once #include "IHID.hpp" -#include "../helpers/WLListener.hpp" #include "../macros.hpp" #include "../helpers/math/Math.hpp" diff --git a/src/devices/IPointer.hpp b/src/devices/IPointer.hpp index 760ec8dc..f38ef55a 100644 --- a/src/devices/IPointer.hpp +++ b/src/devices/IPointer.hpp @@ -1,7 +1,6 @@ #pragma once #include "IHID.hpp" -#include "../helpers/WLListener.hpp" #include "../macros.hpp" #include "../helpers/math/Math.hpp" diff --git a/src/devices/ITouch.hpp b/src/devices/ITouch.hpp index cb8a6e90..bf969b2f 100644 --- a/src/devices/ITouch.hpp +++ b/src/devices/ITouch.hpp @@ -1,7 +1,6 @@ #pragma once #include "IHID.hpp" -#include "../helpers/WLListener.hpp" #include "../macros.hpp" #include "../helpers/math/Math.hpp" diff --git a/src/devices/Tablet.hpp b/src/devices/Tablet.hpp index 0efbe796..01901721 100644 --- a/src/devices/Tablet.hpp +++ b/src/devices/Tablet.hpp @@ -1,7 +1,6 @@ #pragma once #include "IHID.hpp" -#include "../helpers/WLListener.hpp" #include "../macros.hpp" #include "../helpers/math/Math.hpp" #include "../helpers/math/Math.hpp" diff --git a/src/helpers/WLListener.cpp b/src/helpers/WLListener.cpp deleted file mode 100644 index 2ea5c0b6..00000000 --- a/src/helpers/WLListener.cpp +++ /dev/null @@ -1,62 +0,0 @@ -#include "WLListener.hpp" -#include "MiscFunctions.hpp" -#include -#include "../debug/Log.hpp" -#include "Watchdog.hpp" - -void handleWrapped(wl_listener* listener, void* data) { - CHyprWLListener::SWrapper* pWrap = wl_container_of(listener, pWrap, m_sListener); - - if (g_pWatchdog) - g_pWatchdog->startWatching(); - - try { - pWrap->m_pSelf->emit(data); - } catch (std::exception& e) { Debug::log(ERR, "Listener {} threw or timed out and was killed by Watchdog!!! This is bad. what(): {}", (uintptr_t)listener, e.what()); } - - if (g_pWatchdog) - g_pWatchdog->endWatching(); -} - -CHyprWLListener::CHyprWLListener(wl_signal* pSignal, std::function const& callback, void* pOwner) { - initCallback(pSignal, callback, pOwner); -} - -CHyprWLListener::CHyprWLListener() { - m_swWrapper.m_pSelf = this; - m_swWrapper.m_sListener.notify = &handleWrapped; - wl_list_init(&m_swWrapper.m_sListener.link); -} - -CHyprWLListener::~CHyprWLListener() { - removeCallback(); -} - -void CHyprWLListener::removeCallback() { - if (isConnected()) { - Debug::log(LOG, "Callback {:x} -> {:x}, {} removed.", (uintptr_t)&m_pCallback, (uintptr_t)&m_pOwner, m_szAuthor); - wl_list_remove(&m_swWrapper.m_sListener.link); - wl_list_init(&m_swWrapper.m_sListener.link); - } -} - -bool CHyprWLListener::isConnected() { - return !wl_list_empty(&m_swWrapper.m_sListener.link); -} - -void CHyprWLListener::initCallback(wl_signal* pSignal, std::function const& callback, void* pOwner, std::string author) { - if (isConnected()) { - Debug::log(ERR, "Tried to connect a listener twice?!"); - return; - } - - m_pOwner = pOwner; - m_pCallback = callback; - m_szAuthor = author; - - addWLSignal(pSignal, &m_swWrapper.m_sListener, pOwner, m_szAuthor); -} - -void CHyprWLListener::emit(void* data) { - m_pCallback(m_pOwner, data); -} diff --git a/src/helpers/WLListener.hpp b/src/helpers/WLListener.hpp deleted file mode 100644 index 621458e6..00000000 --- a/src/helpers/WLListener.hpp +++ /dev/null @@ -1,39 +0,0 @@ -#pragma once - -#include -#include -#include - -class CHyprWLListener { - public: - CHyprWLListener(wl_signal*, std::function const&, void* owner); - CHyprWLListener(); - ~CHyprWLListener(); - - CHyprWLListener(const CHyprWLListener&) = delete; - CHyprWLListener(CHyprWLListener&&) = delete; - CHyprWLListener& operator=(const CHyprWLListener&) = delete; - CHyprWLListener& operator=(CHyprWLListener&&) = delete; - - void initCallback(wl_signal*, std::function const&, void* owner, std::string author = ""); - - void removeCallback(); - - bool isConnected(); - - struct SWrapper { - wl_listener m_sListener; - CHyprWLListener* m_pSelf; - }; - - void emit(void*); - - private: - SWrapper m_swWrapper; - - void* m_pOwner = nullptr; - - std::function m_pCallback = nullptr; - - std::string m_szAuthor = ""; -}; \ No newline at end of file diff --git a/src/managers/SeatManager.hpp b/src/managers/SeatManager.hpp index 43ebe8b5..5cc7eee0 100644 --- a/src/managers/SeatManager.hpp +++ b/src/managers/SeatManager.hpp @@ -2,7 +2,6 @@ #include #include -#include "../helpers/WLListener.hpp" #include "../macros.hpp" #include "../helpers/signal/Signal.hpp" #include "../helpers/math/Math.hpp" diff --git a/src/managers/input/InputMethodPopup.hpp b/src/managers/input/InputMethodPopup.hpp index f8e4b962..53c11cff 100644 --- a/src/managers/input/InputMethodPopup.hpp +++ b/src/managers/input/InputMethodPopup.hpp @@ -1,6 +1,5 @@ #pragma once -#include "../../helpers/WLListener.hpp" #include "../../desktop/WLSurface.hpp" #include "../../macros.hpp" #include "../../helpers/math/Math.hpp" diff --git a/src/managers/input/TextInput.hpp b/src/managers/input/TextInput.hpp index f920adc7..3cf07006 100644 --- a/src/managers/input/TextInput.hpp +++ b/src/managers/input/TextInput.hpp @@ -1,6 +1,5 @@ #pragma once -#include "../../helpers/WLListener.hpp" #include "../../macros.hpp" #include "../../helpers/math/Math.hpp" #include "../../helpers/signal/Signal.hpp" diff --git a/src/protocols/FocusGrab.hpp b/src/protocols/FocusGrab.hpp index a2d545c5..6fe8780f 100644 --- a/src/protocols/FocusGrab.hpp +++ b/src/protocols/FocusGrab.hpp @@ -53,9 +53,6 @@ class CFocusGrab { bool m_bGrabActive = false; - DYNLISTENER(pointerGrabStarted); - DYNLISTENER(keyboardGrabStarted); - DYNLISTENER(touchGrabStarted); friend class CFocusGrabSurfaceState; }; diff --git a/src/protocols/PresentationTime.hpp b/src/protocols/PresentationTime.hpp index 06c71c9a..421bb838 100644 --- a/src/protocols/PresentationTime.hpp +++ b/src/protocols/PresentationTime.hpp @@ -27,8 +27,6 @@ class CQueuedPresentationData { WP pMonitor; WP surface; - DYNLISTENER(destroySurface); - friend class CPresentationFeedback; friend class CPresentationProtocol; }; diff --git a/src/render/Renderbuffer.hpp b/src/render/Renderbuffer.hpp index e6bfa909..ff06bd5a 100644 --- a/src/render/Renderbuffer.hpp +++ b/src/render/Renderbuffer.hpp @@ -2,7 +2,6 @@ #include "../helpers/signal/Signal.hpp" #include "../helpers/memory/Memory.hpp" -#include "../helpers/WLListener.hpp" #include "Framebuffer.hpp" #include diff --git a/src/xwayland/XSurface.hpp b/src/xwayland/XSurface.hpp index 61eee984..7584354e 100644 --- a/src/xwayland/XSurface.hpp +++ b/src/xwayland/XSurface.hpp @@ -1,6 +1,5 @@ #pragma once -#include "../helpers/WLListener.hpp" #include "../helpers/signal/Signal.hpp" #include "../helpers/memory/Memory.hpp" #include "../helpers/math/Math.hpp" diff --git a/src/xwayland/XWM.hpp b/src/xwayland/XWM.hpp index ba00dd8d..37c61416 100644 --- a/src/xwayland/XWM.hpp +++ b/src/xwayland/XWM.hpp @@ -2,7 +2,6 @@ #include "../macros.hpp" #include "XDataSource.hpp" -#include "../helpers/WLListener.hpp" #include "../helpers/memory/Memory.hpp" #include "../helpers/signal/Signal.hpp" From 6c78b03bb7810e074d21d5c41f088bd317c28906 Mon Sep 17 00:00:00 2001 From: diniamo Date: Mon, 23 Sep 2024 18:52:30 +0200 Subject: [PATCH 0432/2181] flake: update xdph --- flake.lock | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/flake.lock b/flake.lock index 76351cc9..68bb0ed2 100644 --- a/flake.lock +++ b/flake.lock @@ -215,11 +215,11 @@ ] }, "locked": { - "lastModified": 1726933538, - "narHash": "sha256-xTqnMoJsEojuvqJLuM+U7EZ7q71efaj3pbvjutq4TXc=", + "lastModified": 1727109343, + "narHash": "sha256-1PFckA8Im7wMSl26okwOKqBZeCFLD3LvZZFaxswDhbY=", "owner": "hyprwm", "repo": "xdg-desktop-portal-hyprland", - "rev": "4880c50146d0c2a3152d2b02f79253810c330c11", + "rev": "4adb6c4c41ee5014bfe608123bfeddb26e5f5cea", "type": "github" }, "original": { From d279d7c4c6fe27c1944d8e9b51c4730612c8a9ae Mon Sep 17 00:00:00 2001 From: Vaxry Date: Tue, 24 Sep 2024 00:49:29 +0100 Subject: [PATCH 0433/2181] eventloop: dispatch pending in session on start fixes #7855 #7391 --- src/managers/eventLoop/EventLoopManager.cpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/managers/eventLoop/EventLoopManager.cpp b/src/managers/eventLoop/EventLoopManager.cpp index e9b0fa3e..081268c3 100644 --- a/src/managers/eventLoop/EventLoopManager.cpp +++ b/src/managers/eventLoop/EventLoopManager.cpp @@ -50,6 +50,10 @@ void CEventLoopManager::enterLoop() { m_sWayland.aqEventSources.emplace_back(wl_event_loop_add_fd(m_sWayland.loop, fd->fd, WL_EVENT_READABLE, aquamarineFDWrite, fd.get())); } + // if we have a session, dispatch it to get the pending input devices + if (g_pCompositor->m_pAqBackend->hasSession()) + g_pCompositor->m_pAqBackend->session->dispatchPendingEventsAsync(); + wl_display_run(m_sWayland.display); Debug::log(LOG, "Kicked off the event loop! :("); From 0a211f29f5952322925b9f982cbf9b0326d45f0f Mon Sep 17 00:00:00 2001 From: Vaxry Date: Tue, 24 Sep 2024 01:19:05 +0100 Subject: [PATCH 0434/2181] hyprctl: add defaultName to workspacerules fixes #7886 --- src/debug/HyprCtl.cpp | 67 ++++++++++++++++++++++--------------------- 1 file changed, 35 insertions(+), 32 deletions(-) diff --git a/src/debug/HyprCtl.cpp b/src/debug/HyprCtl.cpp index 9faefe26..4de9143d 100644 --- a/src/debug/HyprCtl.cpp +++ b/src/debug/HyprCtl.cpp @@ -320,45 +320,48 @@ std::string CHyprCtl::getWorkspaceData(PHLWORKSPACE w, eHyprCtlOutputFormat form static std::string getWorkspaceRuleData(const SWorkspaceRule& r, eHyprCtlOutputFormat format) { const auto boolToString = [](const bool b) -> std::string { return b ? "true" : "false"; }; if (format == eHyprCtlOutputFormat::FORMAT_JSON) { - const std::string monitor = r.monitor.empty() ? "" : std::format(",\n \"monitor\": \"{}\"", escapeJSONStrings(r.monitor)); - const std::string default_ = (bool)(r.isDefault) ? std::format(",\n \"default\": {}", boolToString(r.isDefault)) : ""; - const std::string persistent = (bool)(r.isPersistent) ? std::format(",\n \"persistent\": {}", boolToString(r.isPersistent)) : ""; - const std::string gapsIn = (bool)(r.gapsIn) ? - std::format(",\n \"gapsIn\": [{}, {}, {}, {}]", r.gapsIn.value().top, r.gapsIn.value().right, r.gapsIn.value().bottom, r.gapsIn.value().left) : + const std::string monitor = r.monitor.empty() ? "" : std::format(",\n \"monitor\": \"{}\"", escapeJSONStrings(r.monitor)); + const std::string default_ = (bool)(r.isDefault) ? std::format(",\n \"default\": {}", boolToString(r.isDefault)) : ""; + const std::string persistent = (bool)(r.isPersistent) ? std::format(",\n \"persistent\": {}", boolToString(r.isPersistent)) : ""; + const std::string gapsIn = (bool)(r.gapsIn) ? + std::format(",\n \"gapsIn\": [{}, {}, {}, {}]", r.gapsIn.value().top, r.gapsIn.value().right, r.gapsIn.value().bottom, r.gapsIn.value().left) : + ""; + const std::string gapsOut = (bool)(r.gapsOut) ? + std::format(",\n \"gapsOut\": [{}, {}, {}, {}]", r.gapsOut.value().top, r.gapsOut.value().right, r.gapsOut.value().bottom, r.gapsOut.value().left) : ""; - const std::string gapsOut = (bool)(r.gapsOut) ? - std::format(",\n \"gapsOut\": [{}, {}, {}, {}]", r.gapsOut.value().top, r.gapsOut.value().right, r.gapsOut.value().bottom, r.gapsOut.value().left) : - ""; - const std::string borderSize = (bool)(r.borderSize) ? std::format(",\n \"borderSize\": {}", r.borderSize.value()) : ""; - const std::string border = (bool)(r.noBorder) ? std::format(",\n \"border\": {}", boolToString(!r.noBorder.value())) : ""; - const std::string rounding = (bool)(r.noRounding) ? std::format(",\n \"rounding\": {}", boolToString(!r.noRounding.value())) : ""; - const std::string decorate = (bool)(r.decorate) ? std::format(",\n \"decorate\": {}", boolToString(r.decorate.value())) : ""; - const std::string shadow = (bool)(r.noShadow) ? std::format(",\n \"shadow\": {}", boolToString(!r.noShadow.value())) : ""; + const std::string borderSize = (bool)(r.borderSize) ? std::format(",\n \"borderSize\": {}", r.borderSize.value()) : ""; + const std::string border = (bool)(r.noBorder) ? std::format(",\n \"border\": {}", boolToString(!r.noBorder.value())) : ""; + const std::string rounding = (bool)(r.noRounding) ? std::format(",\n \"rounding\": {}", boolToString(!r.noRounding.value())) : ""; + const std::string decorate = (bool)(r.decorate) ? std::format(",\n \"decorate\": {}", boolToString(r.decorate.value())) : ""; + const std::string shadow = (bool)(r.noShadow) ? std::format(",\n \"shadow\": {}", boolToString(!r.noShadow.value())) : ""; + const std::string defaultName = r.defaultName.has_value() ? std::format(",\n \"defaultName\": \"{}\"", escapeJSONStrings(r.defaultName.value())) : ""; - std::string result = std::format(R"#({{ - "workspaceString": "{}"{}{}{}{}{}{}{}{} + std::string result = + std::format(R"#({{ + "workspaceString": "{}"{}{}{}{}{}{}{}{}{}{}{} }})#", - escapeJSONStrings(r.workspaceString), monitor, default_, persistent, gapsIn, gapsOut, borderSize, border, rounding, decorate, shadow); + escapeJSONStrings(r.workspaceString), monitor, default_, persistent, gapsIn, gapsOut, borderSize, border, rounding, decorate, shadow, defaultName); return result; } else { - const std::string monitor = std::format("\tmonitor: {}\n", r.monitor.empty() ? "" : escapeJSONStrings(r.monitor)); - const std::string default_ = std::format("\tdefault: {}\n", (bool)(r.isDefault) ? boolToString(r.isDefault) : ""); - const std::string persistent = std::format("\tpersistent: {}\n", (bool)(r.isPersistent) ? boolToString(r.isPersistent) : ""); - const std::string gapsIn = (bool)(r.gapsIn) ? std::format("\tgapsIn: {} {} {} {}\n", std::to_string(r.gapsIn.value().top), std::to_string(r.gapsIn.value().right), - std::to_string(r.gapsIn.value().bottom), std::to_string(r.gapsIn.value().left)) : - std::format("\tgapsIn: \n"); - const std::string gapsOut = (bool)(r.gapsOut) ? std::format("\tgapsOut: {} {} {} {}\n", std::to_string(r.gapsOut.value().top), std::to_string(r.gapsOut.value().right), - std::to_string(r.gapsOut.value().bottom), std::to_string(r.gapsOut.value().left)) : - std::format("\tgapsOut: \n"); - const std::string borderSize = std::format("\tborderSize: {}\n", (bool)(r.borderSize) ? std::to_string(r.borderSize.value()) : ""); - const std::string border = std::format("\tborder: {}\n", (bool)(r.noBorder) ? boolToString(!r.noBorder.value()) : ""); - const std::string rounding = std::format("\trounding: {}\n", (bool)(r.noRounding) ? boolToString(!r.noRounding.value()) : ""); - const std::string decorate = std::format("\tdecorate: {}\n", (bool)(r.decorate) ? boolToString(r.decorate.value()) : ""); - const std::string shadow = std::format("\tshadow: {}\n", (bool)(r.noShadow) ? boolToString(!r.noShadow.value()) : ""); + const std::string monitor = std::format("\tmonitor: {}\n", r.monitor.empty() ? "" : escapeJSONStrings(r.monitor)); + const std::string default_ = std::format("\tdefault: {}\n", (bool)(r.isDefault) ? boolToString(r.isDefault) : ""); + const std::string persistent = std::format("\tpersistent: {}\n", (bool)(r.isPersistent) ? boolToString(r.isPersistent) : ""); + const std::string gapsIn = (bool)(r.gapsIn) ? std::format("\tgapsIn: {} {} {} {}\n", std::to_string(r.gapsIn.value().top), std::to_string(r.gapsIn.value().right), + std::to_string(r.gapsIn.value().bottom), std::to_string(r.gapsIn.value().left)) : + std::format("\tgapsIn: \n"); + const std::string gapsOut = (bool)(r.gapsOut) ? std::format("\tgapsOut: {} {} {} {}\n", std::to_string(r.gapsOut.value().top), std::to_string(r.gapsOut.value().right), + std::to_string(r.gapsOut.value().bottom), std::to_string(r.gapsOut.value().left)) : + std::format("\tgapsOut: \n"); + const std::string borderSize = std::format("\tborderSize: {}\n", (bool)(r.borderSize) ? std::to_string(r.borderSize.value()) : ""); + const std::string border = std::format("\tborder: {}\n", (bool)(r.noBorder) ? boolToString(!r.noBorder.value()) : ""); + const std::string rounding = std::format("\trounding: {}\n", (bool)(r.noRounding) ? boolToString(!r.noRounding.value()) : ""); + const std::string decorate = std::format("\tdecorate: {}\n", (bool)(r.decorate) ? boolToString(r.decorate.value()) : ""); + const std::string shadow = std::format("\tshadow: {}\n", (bool)(r.noShadow) ? boolToString(!r.noShadow.value()) : ""); + const std::string defaultName = std::format("\tdefaultName: {}\n", r.defaultName.value_or("")); - std::string result = std::format("Workspace rule {}:\n{}{}{}{}{}{}{}{}{}{}\n", escapeJSONStrings(r.workspaceString), monitor, default_, persistent, gapsIn, gapsOut, - borderSize, border, rounding, decorate, shadow); + std::string result = std::format("Workspace rule {}:\n{}{}{}{}{}{}{}{}{}{}{}\n", escapeJSONStrings(r.workspaceString), monitor, default_, persistent, gapsIn, gapsOut, + borderSize, border, rounding, decorate, shadow, defaultName); return result; } From 00c862686354d139a53222d41a1c80d698a50c43 Mon Sep 17 00:00:00 2001 From: vaxerski Date: Tue, 24 Sep 2024 11:25:05 +0100 Subject: [PATCH 0435/2181] hyprctl: add submap request fixes #7898 --- src/debug/HyprCtl.cpp | 9 +++++++++ src/managers/KeybindManager.cpp | 4 ++++ src/managers/KeybindManager.hpp | 1 + 3 files changed, 14 insertions(+) diff --git a/src/debug/HyprCtl.cpp b/src/debug/HyprCtl.cpp index 4de9143d..87e071d7 100644 --- a/src/debug/HyprCtl.cpp +++ b/src/debug/HyprCtl.cpp @@ -1627,6 +1627,14 @@ std::string getDescriptions(eHyprCtlOutputFormat format, std::string request) { return json; } +std::string submapRequest(eHyprCtlOutputFormat format, std::string request) { + std::string submap = g_pKeybindManager->getCurrentSubmap(); + if (submap.empty()) + submap = "default"; + + return format == FORMAT_JSON ? std::format("{{\"{}\"}}\n", escapeJSONStrings(submap)) : (submap + "\n"); +} + CHyprCtl::CHyprCtl() { registerCommand(SHyprCtlCommand{"workspaces", true, workspacesRequest}); registerCommand(SHyprCtlCommand{"workspacerules", true, workspaceRulesRequest}); @@ -1648,6 +1656,7 @@ CHyprCtl::CHyprCtl() { registerCommand(SHyprCtlCommand{"configerrors", true, configErrorsRequest}); registerCommand(SHyprCtlCommand{"locked", true, getIsLocked}); registerCommand(SHyprCtlCommand{"descriptions", true, getDescriptions}); + registerCommand(SHyprCtlCommand{"submap", true, submapRequest}); registerCommand(SHyprCtlCommand{"monitors", false, monitorsRequest}); registerCommand(SHyprCtlCommand{"reload", false, reloadRequest}); diff --git a/src/managers/KeybindManager.cpp b/src/managers/KeybindManager.cpp index dd35bc19..02e2f5e7 100644 --- a/src/managers/KeybindManager.cpp +++ b/src/managers/KeybindManager.cpp @@ -594,6 +594,10 @@ eMultiKeyCase CKeybindManager::mkBindMatches(const SKeybind keybind) { return mkKeysymSetMatches(keybind.sMkKeys, m_sMkKeys); } +std::string CKeybindManager::getCurrentSubmap() { + return m_szCurrentSelectedSubmap; +} + SDispatchResult CKeybindManager::handleKeybinds(const uint32_t modmask, const SPressedKeyWithMods& key, bool pressed) { static auto PDISABLEINHIBIT = CConfigValue("binds:disable_keybind_grabbing"); bool found = false; diff --git a/src/managers/KeybindManager.hpp b/src/managers/KeybindManager.hpp index 096cd4f9..c81ca86f 100644 --- a/src/managers/KeybindManager.hpp +++ b/src/managers/KeybindManager.hpp @@ -96,6 +96,7 @@ class CKeybindManager { uint32_t keycodeToModifier(xkb_keycode_t); void clearKeybinds(); void shadowKeybinds(const xkb_keysym_t& doesntHave = 0, const uint32_t doesntHaveCode = 0); + std::string getCurrentSubmap(); std::unordered_map> m_mDispatchers; From 8f5188269b7d58a90c569fd150435b4330dff7df Mon Sep 17 00:00:00 2001 From: vaxerski Date: Wed, 25 Sep 2024 09:59:18 +0100 Subject: [PATCH 0436/2181] hyprctl: add solitary field to hyprctl monitors --- src/debug/HyprCtl.cpp | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/src/debug/HyprCtl.cpp b/src/debug/HyprCtl.cpp index 87e071d7..178e9ba8 100644 --- a/src/debug/HyprCtl.cpp +++ b/src/debug/HyprCtl.cpp @@ -103,6 +103,7 @@ std::string CHyprCtl::getMonitorData(Hyprutils::Memory::CSharedPointer "focused": {}, "dpmsStatus": {}, "vrr": {}, + "solitary": "{:x}", "activelyTearing": {}, "disabled": {}, "currentFormat": "{}", @@ -114,19 +115,20 @@ std::string CHyprCtl::getMonitorData(Hyprutils::Memory::CSharedPointer m->activeWorkspaceID(), (!m->activeWorkspace ? "" : escapeJSONStrings(m->activeWorkspace->m_szName)), m->activeSpecialWorkspaceID(), escapeJSONStrings(m->activeSpecialWorkspace ? m->activeSpecialWorkspace->m_szName : ""), (int)m->vecReservedTopLeft.x, (int)m->vecReservedTopLeft.y, (int)m->vecReservedBottomRight.x, (int)m->vecReservedBottomRight.y, m->scale, (int)m->transform, (m == g_pCompositor->m_pLastMonitor ? "true" : "false"), - (m->dpmsStatus ? "true" : "false"), (m->output->state->state().adaptiveSync ? "true" : "false"), (m->tearingState.activelyTearing ? "true" : "false"), - (m->m_bEnabled ? "false" : "true"), formatToString(m->output->state->state().drmFormat), availableModesForOutput(m.get(), format)); + (m->dpmsStatus ? "true" : "false"), (m->output->state->state().adaptiveSync ? "true" : "false"), (uint64_t)m->solitaryClient.get(), + (m->tearingState.activelyTearing ? "true" : "false"), (m->m_bEnabled ? "false" : "true"), formatToString(m->output->state->state().drmFormat), + availableModesForOutput(m.get(), format)); } else { result += std::format("Monitor {} (ID {}):\n\t{}x{}@{:.5f} at {}x{}\n\tdescription: {}\n\tmake: {}\n\tmodel: {}\n\tserial: {}\n\tactive workspace: {} ({})\n\t" "special workspace: {} ({})\n\treserved: {} {} {} {}\n\tscale: {:.2f}\n\ttransform: {}\n\tfocused: {}\n\t" - "dpmsStatus: {}\n\tvrr: {}\n\tactivelyTearing: {}\n\tdisabled: {}\n\tcurrentFormat: {}\n\tavailableModes: {}\n\n", + "dpmsStatus: {}\n\tvrr: {}\n\tsolitary: {:x}\n\tactivelyTearing: {}\n\tdisabled: {}\n\tcurrentFormat: {}\n\tavailableModes: {}\n\n", m->szName, m->ID, (int)m->vecPixelSize.x, (int)m->vecPixelSize.y, m->refreshRate, (int)m->vecPosition.x, (int)m->vecPosition.y, m->szShortDescription, m->output->make, m->output->model, m->output->serial, m->activeWorkspaceID(), (!m->activeWorkspace ? "" : m->activeWorkspace->m_szName), m->activeSpecialWorkspaceID(), (m->activeSpecialWorkspace ? m->activeSpecialWorkspace->m_szName : ""), (int)m->vecReservedTopLeft.x, (int)m->vecReservedTopLeft.y, (int)m->vecReservedBottomRight.x, (int)m->vecReservedBottomRight.y, m->scale, (int)m->transform, - (m == g_pCompositor->m_pLastMonitor ? "yes" : "no"), (int)m->dpmsStatus, m->output->state->state().adaptiveSync, m->tearingState.activelyTearing, - !m->m_bEnabled, formatToString(m->output->state->state().drmFormat), availableModesForOutput(m.get(), format)); + (m == g_pCompositor->m_pLastMonitor ? "yes" : "no"), (int)m->dpmsStatus, m->output->state->state().adaptiveSync, (uint64_t)m->solitaryClient.get(), + m->tearingState.activelyTearing, !m->m_bEnabled, formatToString(m->output->state->state().drmFormat), availableModesForOutput(m.get(), format)); } return result; From 2320b2241c0713b8d81e8f467cb99bd4179ad23b Mon Sep 17 00:00:00 2001 From: Vaxry <43317083+vaxerski@users.noreply.github.com> Date: Wed, 25 Sep 2024 10:01:13 +0100 Subject: [PATCH 0437/2181] Internal: move to Mat3x3 from hyprutils (#7902) * Meson: require hyprutils >= 0.2.3 * flake.lock: update hyprutils --------- Co-authored-by: Mihai Fufezan --- CMakeLists.txt | 2 +- flake.lock | 6 +- src/helpers/MiscFunctions.cpp | 21 ----- src/helpers/MiscFunctions.hpp | 1 - src/helpers/Monitor.cpp | 9 +-- src/helpers/Monitor.hpp | 2 +- src/helpers/math/Math.cpp | 120 ---------------------------- src/helpers/math/Math.hpp | 10 +-- src/meson.build | 2 +- src/render/OpenGL.cpp | 142 ++++++++++++++-------------------- src/render/OpenGL.hpp | 46 +++++------ 11 files changed, 93 insertions(+), 268 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index e1718b2d..8055271e 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -114,7 +114,7 @@ pkg_check_modules( gio-2.0 hyprlang>=0.3.2 hyprcursor>=0.1.7 - hyprutils>=0.2.2) + hyprutils>=0.2.3) find_package(hyprwayland-scanner 0.3.10 REQUIRED) diff --git a/flake.lock b/flake.lock index 68bb0ed2..a1f0d88d 100644 --- a/flake.lock +++ b/flake.lock @@ -116,11 +116,11 @@ ] }, "locked": { - "lastModified": 1726874949, - "narHash": "sha256-PNnIpwGqpTvMU3N2r0wMQwK1E+t4Bb5fbJwblQvr+80=", + "lastModified": 1727219120, + "narHash": "sha256-wmT+JpnDk6EjgASU2VGfS0nnu6oKA4Cw25o5fzpDD/Q=", "owner": "hyprwm", "repo": "hyprutils", - "rev": "d97af4f6bd068c03a518b597675e598f57ea2291", + "rev": "db956287d3aa194dda91d05c8eb286de2a569edf", "type": "github" }, "original": { diff --git a/src/helpers/MiscFunctions.cpp b/src/helpers/MiscFunctions.cpp index b9970399..20c79a2b 100644 --- a/src/helpers/MiscFunctions.cpp +++ b/src/helpers/MiscFunctions.cpp @@ -628,27 +628,6 @@ void logSystemInfo() { Debug::log(NONE, "{}", execAndGet("cat /etc/os-release")); } -void matrixProjection(float mat[9], int w, int h, wl_output_transform tr) { - memset(mat, 0, sizeof(*mat) * 9); - - const float* t = transforms[tr]; - float x = 2.0f / w; - float y = 2.0f / h; - - // Rotation + reflection - mat[0] = x * t[0]; - mat[1] = x * t[1]; - mat[3] = y * t[3]; - mat[4] = y * t[4]; - - // Translation - mat[2] = -copysign(1.0f, mat[0] + mat[1]); - mat[5] = -copysign(1.0f, mat[3] + mat[4]); - - // Identity - mat[8] = 1.0f; -} - int64_t getPPIDof(int64_t pid) { #if defined(KERN_PROC_PID) int mib[] = { diff --git a/src/helpers/MiscFunctions.hpp b/src/helpers/MiscFunctions.hpp index 8b2ea0d1..f696fc5d 100644 --- a/src/helpers/MiscFunctions.hpp +++ b/src/helpers/MiscFunctions.hpp @@ -34,7 +34,6 @@ int64_t getPPIDof(int64_t pid); int64_t configStringToInt(const std::string&); Vector2D configStringToVector2D(const std::string&); std::optional getPlusMinusKeywordResult(std::string in, float relative); -void matrixProjection(float mat[9], int w, int h, wl_output_transform tr); double normalizeAngleRad(double ang); std::vector getBacktrace(); void throwError(const std::string& err); diff --git a/src/helpers/Monitor.cpp b/src/helpers/Monitor.cpp index 223a3f94..a2d4c504 100644 --- a/src/helpers/Monitor.cpp +++ b/src/helpers/Monitor.cpp @@ -772,12 +772,9 @@ Vector2D CMonitor::middle() { } void CMonitor::updateMatrix() { - matrixIdentity(projMatrix.data()); - if (transform != WL_OUTPUT_TRANSFORM_NORMAL) { - matrixTranslate(projMatrix.data(), vecPixelSize.x / 2.0, vecPixelSize.y / 2.0); - matrixTransform(projMatrix.data(), wlTransformToHyprutils(transform)); - matrixTranslate(projMatrix.data(), -vecTransformedSize.x / 2.0, -vecTransformedSize.y / 2.0); - } + projMatrix = Mat3x3::identity(); + if (transform != WL_OUTPUT_TRANSFORM_NORMAL) + projMatrix.translate(vecPixelSize / 2.0).transform(wlTransformToHyprutils(transform)).translate(-vecTransformedSize / 2.0); } WORKSPACEID CMonitor::activeWorkspaceID() { diff --git a/src/helpers/Monitor.hpp b/src/helpers/Monitor.hpp index 203cac90..97d9f8ab 100644 --- a/src/helpers/Monitor.hpp +++ b/src/helpers/Monitor.hpp @@ -96,7 +96,7 @@ class CMonitor { bool scheduledRecalc = false; wl_output_transform transform = WL_OUTPUT_TRANSFORM_NORMAL; float xwaylandScale = 1.f; - std::array projMatrix = {0}; + Mat3x3 projMatrix; std::optional forceSize; SP currentMode; SP cursorSwapchain; diff --git a/src/helpers/math/Math.cpp b/src/helpers/math/Math.cpp index fccfd636..d111690e 100644 --- a/src/helpers/math/Math.cpp +++ b/src/helpers/math/Math.cpp @@ -1,6 +1,4 @@ #include "Math.hpp" -#include -#include Hyprutils::Math::eTransform wlTransformToHyprutils(wl_output_transform t) { switch (t) { @@ -17,124 +15,6 @@ Hyprutils::Math::eTransform wlTransformToHyprutils(wl_output_transform t) { return Hyprutils::Math::eTransform::HYPRUTILS_TRANSFORM_NORMAL; } -void matrixIdentity(float mat[9]) { - static const float identity[9] = { - 1.0f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f, 1.0f, - }; - memcpy(mat, identity, sizeof(identity)); -} - -void matrixMultiply(float mat[9], const float a[9], const float b[9]) { - float product[9]; - - product[0] = a[0] * b[0] + a[1] * b[3] + a[2] * b[6]; - product[1] = a[0] * b[1] + a[1] * b[4] + a[2] * b[7]; - product[2] = a[0] * b[2] + a[1] * b[5] + a[2] * b[8]; - - product[3] = a[3] * b[0] + a[4] * b[3] + a[5] * b[6]; - product[4] = a[3] * b[1] + a[4] * b[4] + a[5] * b[7]; - product[5] = a[3] * b[2] + a[4] * b[5] + a[5] * b[8]; - - product[6] = a[6] * b[0] + a[7] * b[3] + a[8] * b[6]; - product[7] = a[6] * b[1] + a[7] * b[4] + a[8] * b[7]; - product[8] = a[6] * b[2] + a[7] * b[5] + a[8] * b[8]; - - memcpy(mat, product, sizeof(product)); -} - -void matrixTranspose(float mat[9], const float a[9]) { - float transposition[9] = { - a[0], a[3], a[6], a[1], a[4], a[7], a[2], a[5], a[8], - }; - memcpy(mat, transposition, sizeof(transposition)); -} - -void matrixTranslate(float mat[9], float x, float y) { - float translate[9] = { - 1.0f, 0.0f, x, 0.0f, 1.0f, y, 0.0f, 0.0f, 1.0f, - }; - matrixMultiply(mat, mat, translate); -} - -void matrixScale(float mat[9], float x, float y) { - float scale[9] = { - x, 0.0f, 0.0f, 0.0f, y, 0.0f, 0.0f, 0.0f, 1.0f, - }; - matrixMultiply(mat, mat, scale); -} - -void matrixRotate(float mat[9], float rad) { - float rotate[9] = { - cos(rad), -sin(rad), 0.0f, sin(rad), cos(rad), 0.0f, 0.0f, 0.0f, 1.0f, - }; - matrixMultiply(mat, mat, rotate); -} - -const std::unordered_map>& getTransforms() { - static std::unordered_map> transforms = { - {HYPRUTILS_TRANSFORM_NORMAL, {1.0f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f, 1.0f}}, - {HYPRUTILS_TRANSFORM_90, {0.0f, 1.0f, 0.0f, -1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f}}, - {HYPRUTILS_TRANSFORM_180, {-1.0f, 0.0f, 0.0f, 0.0f, -1.0f, 0.0f, 0.0f, 0.0f, 1.0f}}, - {HYPRUTILS_TRANSFORM_270, {0.0f, -1.0f, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f}}, - {HYPRUTILS_TRANSFORM_FLIPPED, {-1.0f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f, 1.0f}}, - {HYPRUTILS_TRANSFORM_FLIPPED_90, {0.0f, 1.0f, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f}}, - {HYPRUTILS_TRANSFORM_FLIPPED_180, {1.0f, 0.0f, 0.0f, 0.0f, -1.0f, 0.0f, 0.0f, 0.0f, 1.0f}}, - {HYPRUTILS_TRANSFORM_FLIPPED_270, {0.0f, -1.0f, 0.0f, -1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f}}, - }; - return transforms; -} - -void matrixTransform(float mat[9], eTransform transform) { - matrixMultiply(mat, mat, getTransforms().at(transform).data()); -} - -void matrixProjection(float mat[9], int width, int height, eTransform transform) { - memset(mat, 0, sizeof(*mat) * 9); - - const float* t = getTransforms().at(transform).data(); - float x = 2.0f / width; - float y = 2.0f / height; - - // Rotation + reflection - mat[0] = x * t[0]; - mat[1] = x * t[1]; - mat[3] = y * -t[3]; - mat[4] = y * -t[4]; - - // Translation - mat[2] = -copysign(1.0f, mat[0] + mat[1]); - mat[5] = -copysign(1.0f, mat[3] + mat[4]); - - // Identity - mat[8] = 1.0f; -} - -void projectBox(float mat[9], CBox& box, eTransform transform, float rotation, const float projection[9]) { - double x = box.x; - double y = box.y; - double width = box.width; - double height = box.height; - - matrixIdentity(mat); - matrixTranslate(mat, x, y); - - if (rotation != 0) { - matrixTranslate(mat, width / 2, height / 2); - matrixRotate(mat, rotation); - matrixTranslate(mat, -width / 2, -height / 2); - } - - matrixScale(mat, width, height); - - if (transform != HYPRUTILS_TRANSFORM_NORMAL) { - matrixTranslate(mat, 0.5, 0.5); - matrixTransform(mat, transform); - matrixTranslate(mat, -0.5, -0.5); - } - - matrixMultiply(mat, projection, mat); -} - wl_output_transform invertTransform(wl_output_transform tr) { if ((tr & WL_OUTPUT_TRANSFORM_90) && !(tr & WL_OUTPUT_TRANSFORM_FLIPPED)) tr = (wl_output_transform)(tr ^ (int)WL_OUTPUT_TRANSFORM_180); diff --git a/src/helpers/math/Math.hpp b/src/helpers/math/Math.hpp index f57cef93..9b73a20f 100644 --- a/src/helpers/math/Math.hpp +++ b/src/helpers/math/Math.hpp @@ -4,17 +4,9 @@ // includes box and vector as well #include +#include using namespace Hyprutils::Math; eTransform wlTransformToHyprutils(wl_output_transform t); -void projectBox(float mat[9], CBox& box, eTransform transform, float rotation, const float projection[9]); -void matrixProjection(float mat[9], int width, int height, eTransform transform); -void matrixTransform(float mat[9], eTransform transform); -void matrixRotate(float mat[9], float rad); -void matrixScale(float mat[9], float x, float y); -void matrixTranslate(float mat[9], float x, float y); -void matrixTranspose(float mat[9], const float a[9]); -void matrixMultiply(float mat[9], const float a[9], const float b[9]); -void matrixIdentity(float mat[9]); wl_output_transform invertTransform(wl_output_transform tr); diff --git a/src/meson.build b/src/meson.build index 928cd5a7..da46c38c 100644 --- a/src/meson.build +++ b/src/meson.build @@ -16,7 +16,7 @@ executable( dependency('cairo'), dependency('hyprcursor', version: '>=0.1.7'), dependency('hyprlang', version: '>= 0.3.2'), - dependency('hyprutils', version: '>= 0.2.1'), + dependency('hyprutils', version: '>= 0.2.3'), dependency('libdrm'), dependency('egl'), dependency('xkbcommon'), diff --git a/src/render/OpenGL.cpp b/src/render/OpenGL.cpp index 74d3d3cd..ff3d52e4 100644 --- a/src/render/OpenGL.cpp +++ b/src/render/OpenGL.cpp @@ -755,14 +755,12 @@ void CHyprOpenGLImpl::beginSimple(CMonitor* pMonitor, const CRegion& damage, SP< glViewport(0, 0, pMonitor->vecPixelSize.x, pMonitor->vecPixelSize.y); - matrixProjection(m_RenderData.projection, pMonitor->vecPixelSize.x, pMonitor->vecPixelSize.y, WL_OUTPUT_TRANSFORM_NORMAL); + m_RenderData.projection = Mat3x3::outputProjection(pMonitor->vecPixelSize, HYPRUTILS_TRANSFORM_NORMAL); - matrixIdentity(m_RenderData.monitorProjection.data()); + m_RenderData.monitorProjection = Mat3x3::identity(); if (pMonitor->transform != WL_OUTPUT_TRANSFORM_NORMAL) { const Vector2D tfmd = pMonitor->transform % 2 == 1 ? Vector2D{FBO->m_vSize.y, FBO->m_vSize.x} : FBO->m_vSize; - matrixTranslate(m_RenderData.monitorProjection.data(), FBO->m_vSize.x / 2.0, FBO->m_vSize.y / 2.0); - matrixTransform(m_RenderData.monitorProjection.data(), wlTransformToHyprutils(pMonitor->transform)); - matrixTranslate(m_RenderData.monitorProjection.data(), -tfmd.x / 2.0, -tfmd.y / 2.0); + m_RenderData.monitorProjection.translate(FBO->m_vSize / 2.0).transform(wlTransformToHyprutils(pMonitor->transform)).translate(-tfmd / 2.0); } m_RenderData.pCurrentMonData = &m_mMonitorRenderResources[pMonitor]; @@ -809,7 +807,7 @@ void CHyprOpenGLImpl::begin(CMonitor* pMonitor, const CRegion& damage_, CFramebu glViewport(0, 0, pMonitor->vecPixelSize.x, pMonitor->vecPixelSize.y); - matrixProjection(m_RenderData.projection, pMonitor->vecPixelSize.x, pMonitor->vecPixelSize.y, WL_OUTPUT_TRANSFORM_NORMAL); + m_RenderData.projection = Mat3x3::outputProjection(pMonitor->vecPixelSize, HYPRUTILS_TRANSFORM_NORMAL); m_RenderData.monitorProjection = pMonitor->projMatrix; @@ -1289,20 +1287,17 @@ void CHyprOpenGLImpl::renderRectWithDamage(CBox* box, const CColor& col, CRegion box = &newBox; - float matrix[9]; - projectBox(matrix, newBox, wlTransformToHyprutils(invertTransform(!m_bEndFrame ? WL_OUTPUT_TRANSFORM_NORMAL : m_RenderData.pMonitor->transform)), newBox.rot, - m_RenderData.monitorProjection.data()); - - float glMatrix[9]; - matrixMultiply(glMatrix, m_RenderData.projection, matrix); + Mat3x3 matrix = m_RenderData.monitorProjection.projectBox( + newBox, wlTransformToHyprutils(invertTransform(!m_bEndFrame ? WL_OUTPUT_TRANSFORM_NORMAL : m_RenderData.pMonitor->transform)), newBox.rot); + Mat3x3 glMatrix = m_RenderData.projection.copy().multiply(matrix); glUseProgram(m_RenderData.pCurrentMonData->m_shQUAD.program); #ifndef GLES2 - glUniformMatrix3fv(m_RenderData.pCurrentMonData->m_shQUAD.proj, 1, GL_TRUE, glMatrix); + glUniformMatrix3fv(m_RenderData.pCurrentMonData->m_shQUAD.proj, 1, GL_TRUE, glMatrix.getMatrix().data()); #else - matrixTranspose(glMatrix, glMatrix); - glUniformMatrix3fv(m_RenderData.pCurrentMonData->m_shQUAD.proj, 1, GL_FALSE, glMatrix); + glMatrix.transpose(); + glUniformMatrix3fv(m_RenderData.pCurrentMonData->m_shQUAD.proj, 1, GL_FALSE, glMatrix.getMatrix().data()); #endif // premultiply the color as well as we don't work with straight alpha @@ -1386,11 +1381,10 @@ void CHyprOpenGLImpl::renderTextureInternalWithDamage(SP tex, CBox* pB if (m_bEndFrame || TRANSFORMS_MATCH) TRANSFORM = wlTransformToHyprutils(invertTransform(m_RenderData.pMonitor->transform)); - float matrix[9]; - projectBox(matrix, newBox, TRANSFORM, newBox.rot, m_RenderData.monitorProjection.data()); + Mat3x3 matrix = m_RenderData.monitorProjection.projectBox(newBox, TRANSFORM, newBox.rot); + Mat3x3 glMatrix = m_RenderData.projection.copy().multiply(matrix); - float glMatrix[9]; - matrixMultiply(glMatrix, m_RenderData.projection, matrix); + Debug::log(LOG, "internal:\nmat: {},\nglmat: {}", matrix.toString(), glMatrix.toString()); if (waitTimeline != nullptr) { if (!waitForTimelinePoint(waitTimeline, waitPoint)) { @@ -1442,10 +1436,10 @@ void CHyprOpenGLImpl::renderTextureInternalWithDamage(SP tex, CBox* pB glUseProgram(shader->program); #ifndef GLES2 - glUniformMatrix3fv(shader->proj, 1, GL_TRUE, glMatrix); + glUniformMatrix3fv(shader->proj, 1, GL_TRUE, glMatrix.getMatrix().data()); #else - matrixTranspose(glMatrix, glMatrix); - glUniformMatrix3fv(shader->proj, 1, GL_FALSE, glMatrix); + glMatrix.transpose(); + glUniformMatrix3fv(shader->proj, 1, GL_FALSE, glMatrix.getMatrix().data()); #endif glUniform1i(shader->tex, 0); @@ -1556,13 +1550,10 @@ void CHyprOpenGLImpl::renderTexturePrimitive(SP tex, CBox* pBox) { // get transform const auto TRANSFORM = wlTransformToHyprutils(invertTransform(!m_bEndFrame ? WL_OUTPUT_TRANSFORM_NORMAL : m_RenderData.pMonitor->transform)); - float matrix[9]; - projectBox(matrix, newBox, TRANSFORM, newBox.rot, m_RenderData.monitorProjection.data()); + Mat3x3 matrix = m_RenderData.monitorProjection.projectBox(newBox, TRANSFORM, newBox.rot); + Mat3x3 glMatrix = m_RenderData.projection.copy().multiply(matrix); - float glMatrix[9]; - matrixMultiply(glMatrix, m_RenderData.projection, matrix); - - CShader* shader = &m_RenderData.pCurrentMonData->m_shPASSTHRURGBA; + CShader* shader = &m_RenderData.pCurrentMonData->m_shPASSTHRURGBA; glActiveTexture(GL_TEXTURE0); glBindTexture(tex->m_iTarget, tex->m_iTexID); @@ -1570,10 +1561,10 @@ void CHyprOpenGLImpl::renderTexturePrimitive(SP tex, CBox* pBox) { glUseProgram(shader->program); #ifndef GLES2 - glUniformMatrix3fv(shader->proj, 1, GL_TRUE, glMatrix); + glUniformMatrix3fv(shader->proj, 1, GL_TRUE, glMatrix.getMatrix().data()); #else - matrixTranspose(glMatrix, glMatrix); - glUniformMatrix3fv(shader->proj, 1, GL_FALSE, glMatrix); + glMatrix.transpose(); + glUniformMatrix3fv(shader->proj, 1, GL_FALSE, glMatrix.getMatrix().data()); #endif glUniform1i(shader->tex, 0); @@ -1610,21 +1601,18 @@ void CHyprOpenGLImpl::renderTextureMatte(SP tex, CBox* pBox, CFramebuf // get transform const auto TRANSFORM = wlTransformToHyprutils(invertTransform(!m_bEndFrame ? WL_OUTPUT_TRANSFORM_NORMAL : m_RenderData.pMonitor->transform)); - float matrix[9]; - projectBox(matrix, newBox, TRANSFORM, newBox.rot, m_RenderData.monitorProjection.data()); + Mat3x3 matrix = m_RenderData.monitorProjection.projectBox(newBox, TRANSFORM, newBox.rot); + Mat3x3 glMatrix = m_RenderData.projection.copy().multiply(matrix); - float glMatrix[9]; - matrixMultiply(glMatrix, m_RenderData.projection, matrix); - - CShader* shader = &m_RenderData.pCurrentMonData->m_shMATTE; + CShader* shader = &m_RenderData.pCurrentMonData->m_shMATTE; glUseProgram(shader->program); #ifndef GLES2 - glUniformMatrix3fv(shader->proj, 1, GL_TRUE, glMatrix); + glUniformMatrix3fv(shader->proj, 1, GL_TRUE, glMatrix.getMatrix().data()); #else - matrixTranspose(glMatrix, glMatrix); - glUniformMatrix3fv(shader->proj, 1, GL_FALSE, glMatrix); + glMatrix.transpose(); + glUniformMatrix3fv(shader->proj, 1, GL_FALSE, glMatrix.getMatrix().data()); #endif glUniform1i(shader->tex, 0); glUniform1i(shader->alphaMatte, 1); @@ -1667,13 +1655,10 @@ CFramebuffer* CHyprOpenGLImpl::blurMainFramebufferWithDamage(float a, CRegion* o glDisable(GL_STENCIL_TEST); // get transforms for the full monitor - const auto TRANSFORM = wlTransformToHyprutils(invertTransform(m_RenderData.pMonitor->transform)); - float matrix[9]; + const auto TRANSFORM = wlTransformToHyprutils(invertTransform(m_RenderData.pMonitor->transform)); CBox MONITORBOX = {0, 0, m_RenderData.pMonitor->vecTransformedSize.x, m_RenderData.pMonitor->vecTransformedSize.y}; - projectBox(matrix, MONITORBOX, TRANSFORM, 0, m_RenderData.monitorProjection.data()); - - float glMatrix[9]; - matrixMultiply(glMatrix, m_RenderData.projection, matrix); + Mat3x3 matrix = m_RenderData.monitorProjection.projectBox(MONITORBOX, TRANSFORM); + Mat3x3 glMatrix = m_RenderData.projection.copy().multiply(matrix); // get the config settings static auto PBLURSIZE = CConfigValue("decoration:blur:size"); @@ -1710,10 +1695,10 @@ CFramebuffer* CHyprOpenGLImpl::blurMainFramebufferWithDamage(float a, CRegion* o glUseProgram(m_RenderData.pCurrentMonData->m_shBLURPREPARE.program); #ifndef GLES2 - glUniformMatrix3fv(m_RenderData.pCurrentMonData->m_shBLURPREPARE.proj, 1, GL_TRUE, glMatrix); + glUniformMatrix3fv(m_RenderData.pCurrentMonData->m_shBLURPREPARE.proj, 1, GL_TRUE, glMatrix.getMatrix().data()); #else - matrixTranspose(glMatrix, glMatrix); - glUniformMatrix3fv(m_RenderData.pCurrentMonData->m_shBLURPREPARE.proj, 1, GL_FALSE, glMatrix); + glMatrix.transpose(); + glUniformMatrix3fv(m_RenderData.pCurrentMonData->m_shBLURPREPARE.proj, 1, GL_FALSE, glMatrix.getMatrix().data()); #endif glUniform1f(m_RenderData.pCurrentMonData->m_shBLURPREPARE.contrast, *PBLURCONTRAST); glUniform1f(m_RenderData.pCurrentMonData->m_shBLURPREPARE.brightness, *PBLURBRIGHTNESS); @@ -1755,10 +1740,10 @@ CFramebuffer* CHyprOpenGLImpl::blurMainFramebufferWithDamage(float a, CRegion* o // prep two shaders #ifndef GLES2 - glUniformMatrix3fv(pShader->proj, 1, GL_TRUE, glMatrix); + glUniformMatrix3fv(pShader->proj, 1, GL_TRUE, glMatrix.getMatrix().data()); #else - matrixTranspose(glMatrix, glMatrix); - glUniformMatrix3fv(pShader->proj, 1, GL_FALSE, glMatrix); + glMatrix.transpose(); + glUniformMatrix3fv(pShader->proj, 1, GL_FALSE, glMatrix.getMatrix().data()); #endif glUniform1f(pShader->radius, *PBLURSIZE * a); // this makes the blursize change with a if (pShader == &m_RenderData.pCurrentMonData->m_shBLUR1) { @@ -1832,10 +1817,10 @@ CFramebuffer* CHyprOpenGLImpl::blurMainFramebufferWithDamage(float a, CRegion* o glUseProgram(m_RenderData.pCurrentMonData->m_shBLURFINISH.program); #ifndef GLES2 - glUniformMatrix3fv(m_RenderData.pCurrentMonData->m_shBLURFINISH.proj, 1, GL_TRUE, glMatrix); + glUniformMatrix3fv(m_RenderData.pCurrentMonData->m_shBLURFINISH.proj, 1, GL_TRUE, glMatrix.getMatrix().data()); #else - matrixTranspose(glMatrix, glMatrix); - glUniformMatrix3fv(m_RenderData.pCurrentMonData->m_shBLURFINISH.proj, 1, GL_FALSE, glMatrix); + glMatrix.transpose(); + glUniformMatrix3fv(m_RenderData.pCurrentMonData->m_shBLURFINISH.proj, 1, GL_FALSE, glMatrix.getMatrix().data()); #endif glUniform1f(m_RenderData.pCurrentMonData->m_shBLURFINISH.noise, *PBLURNOISE); glUniform1f(m_RenderData.pCurrentMonData->m_shBLURFINISH.brightness, *PBLURBRIGHTNESS); @@ -2165,12 +2150,9 @@ void CHyprOpenGLImpl::renderBorder(CBox* box, const CGradientValueData& grad, in round += round == 0 ? 0 : scaledBorderSize; - float matrix[9]; - projectBox(matrix, newBox, wlTransformToHyprutils(invertTransform(!m_bEndFrame ? WL_OUTPUT_TRANSFORM_NORMAL : m_RenderData.pMonitor->transform)), newBox.rot, - m_RenderData.monitorProjection.data()); - - float glMatrix[9]; - matrixMultiply(glMatrix, m_RenderData.projection, matrix); + Mat3x3 matrix = m_RenderData.monitorProjection.projectBox( + newBox, wlTransformToHyprutils(invertTransform(!m_bEndFrame ? WL_OUTPUT_TRANSFORM_NORMAL : m_RenderData.pMonitor->transform)), newBox.rot); + Mat3x3 glMatrix = m_RenderData.projection.copy().multiply(matrix); const auto BLEND = m_bBlend; blend(true); @@ -2178,10 +2160,10 @@ void CHyprOpenGLImpl::renderBorder(CBox* box, const CGradientValueData& grad, in glUseProgram(m_RenderData.pCurrentMonData->m_shBORDER1.program); #ifndef GLES2 - glUniformMatrix3fv(m_RenderData.pCurrentMonData->m_shBORDER1.proj, 1, GL_TRUE, glMatrix); + glUniformMatrix3fv(m_RenderData.pCurrentMonData->m_shBORDER1.proj, 1, GL_TRUE, glMatrix.getMatrix().data()); #else - matrixTranspose(glMatrix, glMatrix); - glUniformMatrix3fv(m_RenderData.pCurrentMonData->m_shBORDER1.proj, 1, GL_FALSE, glMatrix); + glMatrix.transpose(); + glUniformMatrix3fv(m_RenderData.pCurrentMonData->m_shBORDER1.proj, 1, GL_FALSE, glMatrix.getMatrix().data()); #endif static_assert(sizeof(CColor) == 4 * sizeof(float)); // otherwise the line below this will fail @@ -2471,22 +2453,19 @@ void CHyprOpenGLImpl::renderRoundedShadow(CBox* box, int round, int range, const const auto col = color; - float matrix[9]; - projectBox(matrix, newBox, wlTransformToHyprutils(invertTransform(!m_bEndFrame ? WL_OUTPUT_TRANSFORM_NORMAL : m_RenderData.pMonitor->transform)), newBox.rot, - m_RenderData.monitorProjection.data()); - - float glMatrix[9]; - matrixMultiply(glMatrix, m_RenderData.projection, matrix); + Mat3x3 matrix = m_RenderData.monitorProjection.projectBox( + newBox, wlTransformToHyprutils(invertTransform(!m_bEndFrame ? WL_OUTPUT_TRANSFORM_NORMAL : m_RenderData.pMonitor->transform)), newBox.rot); + Mat3x3 glMatrix = m_RenderData.projection.copy().multiply(matrix); glEnable(GL_BLEND); glUseProgram(m_RenderData.pCurrentMonData->m_shSHADOW.program); #ifndef GLES2 - glUniformMatrix3fv(m_RenderData.pCurrentMonData->m_shSHADOW.proj, 1, GL_TRUE, glMatrix); + glUniformMatrix3fv(m_RenderData.pCurrentMonData->m_shSHADOW.proj, 1, GL_TRUE, glMatrix.getMatrix().data()); #else - matrixTranspose(glMatrix, glMatrix); - glUniformMatrix3fv(m_RenderData.pCurrentMonData->m_shSHADOW.proj, 1, GL_FALSE, glMatrix); + glMatrix.transpose(); + glUniformMatrix3fv(m_RenderData.pCurrentMonData->m_shSHADOW.proj, 1, GL_FALSE, glMatrix.getMatrix().data()); #endif glUniform4f(m_RenderData.pCurrentMonData->m_shSHADOW.color, col.r, col.g, col.b, col.a * a); @@ -2565,11 +2544,11 @@ void CHyprOpenGLImpl::renderMirrored() { return; // replace monitor projection to undo the mirrored monitor's projection - matrixIdentity(m_RenderData.monitorProjection.data()); - matrixTranslate(m_RenderData.monitorProjection.data(), monitor->vecPixelSize.x / 2.0, monitor->vecPixelSize.y / 2.0); - matrixTransform(m_RenderData.monitorProjection.data(), wlTransformToHyprutils(monitor->transform)); - matrixTransform(m_RenderData.monitorProjection.data(), wlTransformToHyprutils(invertTransform(mirrored->transform))); - matrixTranslate(m_RenderData.monitorProjection.data(), -monitor->vecTransformedSize.x / 2.0, -monitor->vecTransformedSize.y / 2.0); + m_RenderData.monitorProjection = Mat3x3::identity() + .translate(monitor->vecPixelSize / 2.0) + .transform(wlTransformToHyprutils(monitor->transform)) + .transform(wlTransformToHyprutils(invertTransform(mirrored->transform))) + .translate(-monitor->vecTransformedSize / 2.0); // clear stuff outside of mirrored area (e.g. when changing to mirrored) clear(CColor(0, 0, 0, 0)); @@ -2920,16 +2899,15 @@ void CHyprOpenGLImpl::destroyMonitorResources(CMonitor* pMonitor) { } void CHyprOpenGLImpl::saveMatrix() { - memcpy(m_RenderData.savedProjection, m_RenderData.projection, 9 * sizeof(float)); + m_RenderData.savedProjection = m_RenderData.projection; } void CHyprOpenGLImpl::setMatrixScaleTranslate(const Vector2D& translate, const float& scale) { - matrixScale(m_RenderData.projection, scale, scale); - matrixTranslate(m_RenderData.projection, translate.x, translate.y); + m_RenderData.projection.scale(scale).translate(translate); } void CHyprOpenGLImpl::restoreMatrix() { - memcpy(m_RenderData.projection, m_RenderData.savedProjection, 9 * sizeof(float)); + m_RenderData.projection = m_RenderData.savedProjection; } void CHyprOpenGLImpl::bindOffMain() { diff --git a/src/render/OpenGL.hpp b/src/render/OpenGL.hpp index 06078a00..0d1c267b 100644 --- a/src/render/OpenGL.hpp +++ b/src/render/OpenGL.hpp @@ -94,35 +94,35 @@ struct SMonitorRenderData { }; struct SCurrentRenderData { - CMonitor* pMonitor = nullptr; - PHLWORKSPACE pWorkspace = nullptr; - float projection[9]; - float savedProjection[9]; - std::array monitorProjection; + CMonitor* pMonitor = nullptr; + PHLWORKSPACE pWorkspace = nullptr; + Mat3x3 projection; + Mat3x3 savedProjection; + Mat3x3 monitorProjection; - SMonitorRenderData* pCurrentMonData = nullptr; - CFramebuffer* currentFB = nullptr; // current rendering to - CFramebuffer* mainFB = nullptr; // main to render to - CFramebuffer* outFB = nullptr; // out to render to (if offloaded, etc) + SMonitorRenderData* pCurrentMonData = nullptr; + CFramebuffer* currentFB = nullptr; // current rendering to + CFramebuffer* mainFB = nullptr; // main to render to + CFramebuffer* outFB = nullptr; // out to render to (if offloaded, etc) - CRegion damage; - CRegion finalDamage; // damage used for funal off -> main + CRegion damage; + CRegion finalDamage; // damage used for funal off -> main - SRenderModifData renderModif; - float mouseZoomFactor = 1.f; - bool mouseZoomUseMouse = true; // true by default - bool useNearestNeighbor = false; - bool forceIntrospection = false; // cleaned in ::end() - bool blockScreenShader = false; - bool simplePass = false; + SRenderModifData renderModif; + float mouseZoomFactor = 1.f; + bool mouseZoomUseMouse = true; // true by default + bool useNearestNeighbor = false; + bool forceIntrospection = false; // cleaned in ::end() + bool blockScreenShader = false; + bool simplePass = false; - Vector2D primarySurfaceUVTopLeft = Vector2D(-1, -1); - Vector2D primarySurfaceUVBottomRight = Vector2D(-1, -1); + Vector2D primarySurfaceUVTopLeft = Vector2D(-1, -1); + Vector2D primarySurfaceUVBottomRight = Vector2D(-1, -1); - CBox clipBox = {}; // scaled coordinates + CBox clipBox = {}; // scaled coordinates - uint32_t discardMode = DISCARD_OPAQUE; - float discardOpacity = 0.f; + uint32_t discardMode = DISCARD_OPAQUE; + float discardOpacity = 0.f; }; class CEGLSync { From 2a052c69f36a71fb473262f57039b8ac81518ad3 Mon Sep 17 00:00:00 2001 From: vaxerski Date: Wed, 25 Sep 2024 10:36:43 +0100 Subject: [PATCH 0438/2181] core: add a --systeminfo parameter to gather systeminfo without running --- src/debug/HyprCtl.cpp | 11 +++++++---- src/debug/HyprCtl.hpp | 3 +++ src/main.cpp | 5 +++++ 3 files changed, 15 insertions(+), 4 deletions(-) diff --git a/src/debug/HyprCtl.cpp b/src/debug/HyprCtl.cpp index 178e9ba8..0229a803 100644 --- a/src/debug/HyprCtl.cpp +++ b/src/debug/HyprCtl.cpp @@ -943,11 +943,14 @@ std::string systemInfoRequest(eHyprCtlOutputFormat format, std::string request) result += "os-release: " + execAndGet("cat /etc/os-release") + "\n\n"; result += "plugins:\n"; - for (auto const& pl : g_pPluginSystem->getAllPlugins()) { - result += std::format(" {} by {} ver {}\n", pl->name, pl->author, pl->version); - } + if (g_pPluginSystem) { + for (auto const& pl : g_pPluginSystem->getAllPlugins()) { + result += std::format(" {} by {} ver {}\n", pl->name, pl->author, pl->version); + } + } else + result += "\tunknown: not runtime\n"; - if (g_pHyprCtl->m_sCurrentRequestParams.sysInfoConfig) { + if (g_pHyprCtl && g_pHyprCtl->m_sCurrentRequestParams.sysInfoConfig) { result += "\n======Config-Start======\n"; result += g_pConfigManager->getConfigString(); result += "\n======Config-End========\n"; diff --git a/src/debug/HyprCtl.hpp b/src/debug/HyprCtl.hpp index cbacd7cb..d68bf14f 100644 --- a/src/debug/HyprCtl.hpp +++ b/src/debug/HyprCtl.hpp @@ -5,6 +5,9 @@ #include "../helpers/MiscFunctions.hpp" #include +// exposed for main.cpp +std::string systemInfoRequest(eHyprCtlOutputFormat format, std::string request); + class CHyprCtl { public: CHyprCtl(); diff --git a/src/main.cpp b/src/main.cpp index ba6fe505..279e1ce1 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -3,6 +3,7 @@ #include "Compositor.hpp" #include "config/ConfigManager.hpp" #include "init/initHelpers.hpp" +#include "debug/HyprCtl.hpp" #include using namespace Hyprutils::String; @@ -133,6 +134,10 @@ int main(int argc, char** argv) { std::cout << result; return 0; + } else if (it->compare("--systeminfo") == 0) { + const auto SYSINFO = systemInfoRequest(eHyprCtlOutputFormat::FORMAT_NORMAL, ""); + std::cout << SYSINFO << "\n"; + return 0; } else { std::cerr << "[ ERROR ] Unknown option '" << it->c_str() << "'!\n"; help(); From 8b86ee8bf08eaf8b57d0a7f12af876216323cc3d Mon Sep 17 00:00:00 2001 From: vaxerski Date: Wed, 25 Sep 2024 10:37:58 +0100 Subject: [PATCH 0439/2181] github: encourage usage of --systeminfo if Hyprland won't launch --- .github/ISSUE_TEMPLATE/bug.yml | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/.github/ISSUE_TEMPLATE/bug.yml b/.github/ISSUE_TEMPLATE/bug.yml index 7d402904..ce6d9d3e 100644 --- a/.github/ISSUE_TEMPLATE/bug.yml +++ b/.github/ISSUE_TEMPLATE/bug.yml @@ -29,10 +29,10 @@ body: attributes: label: System Info and Version description: | - Paste the output of `hyprctl systeminfo -c` here (If you are on a - version that shows you help menu, omit the `-c` and attach config files - to the issue). If you have configs outside of the main config shown - here, please attach. + Paste the output of `hyprctl systeminfo -c` here. If you can't + launch Hyprland, paste the output of `Hyprland --systeminfo`. + If `Hyprland --systeminfo` errors out (added in 0.44.0), find + and paste the Hyprland version manually. value: "
System/Version info From 49713fab045f7bd41466ddedd83ad5cb81142853 Mon Sep 17 00:00:00 2001 From: Vaxry Date: Wed, 25 Sep 2024 23:15:36 +0100 Subject: [PATCH 0440/2181] pointermgr: avoid hogging CMonitor refs --- src/managers/PointerManager.cpp | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/src/managers/PointerManager.cpp b/src/managers/PointerManager.cpp index 3dcee431..736b629c 100644 --- a/src/managers/PointerManager.cpp +++ b/src/managers/PointerManager.cpp @@ -17,10 +17,8 @@ CPointerManager::CPointerManager() { onMonitorLayoutChange(); - PMONITOR->events.modeChanged.registerStaticListener( - [this, PMONITOR](void* owner, std::any data) { g_pEventLoopManager->doLater([this, PMONITOR]() { onMonitorLayoutChange(); }); }, nullptr); - PMONITOR->events.disconnect.registerStaticListener( - [this, PMONITOR](void* owner, std::any data) { g_pEventLoopManager->doLater([this, PMONITOR]() { onMonitorLayoutChange(); }); }, nullptr); + PMONITOR->events.modeChanged.registerStaticListener([this](void* owner, std::any data) { g_pEventLoopManager->doLater([this]() { onMonitorLayoutChange(); }); }, nullptr); + PMONITOR->events.disconnect.registerStaticListener([this](void* owner, std::any data) { g_pEventLoopManager->doLater([this]() { onMonitorLayoutChange(); }); }, nullptr); PMONITOR->events.destroy.registerStaticListener( [this](void* owner, std::any data) { if (g_pCompositor && !g_pCompositor->m_bIsShuttingDown) From 22746b304614b313a78d740f4536e809a4df90e2 Mon Sep 17 00:00:00 2001 From: Vaxry Date: Wed, 25 Sep 2024 23:38:11 +0100 Subject: [PATCH 0441/2181] hyprctl: use the getMonitorData helper everywhere --- src/debug/HyprCtl.cpp | 11 +---------- 1 file changed, 1 insertion(+), 10 deletions(-) diff --git a/src/debug/HyprCtl.cpp b/src/debug/HyprCtl.cpp index 0229a803..d9274727 100644 --- a/src/debug/HyprCtl.cpp +++ b/src/debug/HyprCtl.cpp @@ -160,16 +160,7 @@ std::string monitorsRequest(eHyprCtlOutputFormat format, std::string request) { if (!m->output || m->ID == -1) continue; - result += std::format( - "Monitor {} (ID {}):\n\t{}x{}@{:.5f} at {}x{}\n\tdescription: {}\n\tmake: {}\n\tmodel: {}\n\tserial: {}\n\tactive workspace: {} ({})\n\t" - "special workspace: {} ({})\n\treserved: {} {} {} {}\n\tscale: {:.2f}\n\ttransform: {}\n\tfocused: {}\n\t" - "dpmsStatus: {}\n\tvrr: {}\n\tactivelyTearing: {}\n\tdisabled: {}\n\tcurrentFormat: A {} H {}\n\tavailableModes: {}\n\n", - m->szName, m->ID, (int)m->vecPixelSize.x, (int)m->vecPixelSize.y, m->refreshRate, (int)m->vecPosition.x, (int)m->vecPosition.y, m->szShortDescription, - m->output->make, m->output->model, m->output->serial, m->activeWorkspaceID(), (!m->activeWorkspace ? "" : m->activeWorkspace->m_szName), - m->activeSpecialWorkspaceID(), (m->activeSpecialWorkspace ? m->activeSpecialWorkspace->m_szName : ""), (int)m->vecReservedTopLeft.x, (int)m->vecReservedTopLeft.y, - (int)m->vecReservedBottomRight.x, (int)m->vecReservedBottomRight.y, m->scale, (int)m->transform, (m == g_pCompositor->m_pLastMonitor ? "yes" : "no"), - (int)m->dpmsStatus, (int)(m->output->state ? m->output->state->state().adaptiveSync : false), m->tearingState.activelyTearing, !m->m_bEnabled, - formatToString(m->output->state->state().drmFormat), formatToString(m->drmFormat), availableModesForOutput(m.get(), format)); + result += CHyprCtl::getMonitorData(m, format); } } From b1ad2d806634edff656cb5ddc9850ae2c73324e8 Mon Sep 17 00:00:00 2001 From: Kamikadze <40305144+Kam1k4dze@users.noreply.github.com> Date: Thu, 26 Sep 2024 04:08:50 +0500 Subject: [PATCH 0442/2181] dispatchers: fixup dpms toggle (#7875) now toggles every monitor individually --- src/managers/KeybindManager.cpp | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/src/managers/KeybindManager.cpp b/src/managers/KeybindManager.cpp index 02e2f5e7..48c4517a 100644 --- a/src/managers/KeybindManager.cpp +++ b/src/managers/KeybindManager.cpp @@ -2403,9 +2403,7 @@ SDispatchResult CKeybindManager::dpms(std::string arg) { bool enable = arg.starts_with("on"); std::string port = ""; - if (arg.starts_with("toggle")) - enable = !std::any_of(g_pCompositor->m_vMonitors.begin(), g_pCompositor->m_vMonitors.end(), [&](const auto& other) { return !other->dpmsStatus; }); // enable if any is off - + bool isToggle = arg.starts_with("toggle"); if (arg.find_first_of(' ') != std::string::npos) port = arg.substr(arg.find_first_of(' ') + 1); @@ -2414,6 +2412,9 @@ SDispatchResult CKeybindManager::dpms(std::string arg) { if (!port.empty() && m->szName != port) continue; + if (isToggle) + enable = !m->dpmsStatus; + m->output->state->resetExplicitFences(); m->output->state->setEnabled(enable); From caaa9b11e4763ed0367f81bf97ceaad5175806fc Mon Sep 17 00:00:00 2001 From: Vaxry <43317083+vaxerski@users.noreply.github.com> Date: Thu, 26 Sep 2024 11:10:53 +0100 Subject: [PATCH 0443/2181] wlr-output-configuration: Improve output configuration (#7571) --- src/config/ConfigManager.cpp | 66 ++++++++++++++--- src/config/ConfigManager.hpp | 2 +- src/helpers/Monitor.cpp | 4 +- src/managers/KeybindManager.cpp | 2 +- src/protocols/OutputManagement.cpp | 115 +++++++++++++++++++---------- src/protocols/OutputManagement.hpp | 69 +++++++++++------ 6 files changed, 181 insertions(+), 77 deletions(-) diff --git a/src/config/ConfigManager.cpp b/src/config/ConfigManager.cpp index 21a3a21e..ab5905c2 100644 --- a/src/config/ConfigManager.cpp +++ b/src/config/ConfigManager.cpp @@ -7,6 +7,7 @@ #include "helpers/varlist/VarList.hpp" #include "../protocols/LayerShell.hpp" #include "../xwayland/XWayland.hpp" +#include "../protocols/OutputManagement.hpp" #include #include @@ -1079,28 +1080,69 @@ std::string CConfigManager::getDeviceString(const std::string& dev, const std::s return VAL; } -SMonitorRule CConfigManager::getMonitorRuleFor(const CMonitor& PMONITOR) { +SMonitorRule CConfigManager::getMonitorRuleFor(const SP PMONITOR) { + auto applyWlrOutputConfig = [PMONITOR](SMonitorRule rule) -> SMonitorRule { + const auto CONFIG = PROTO::outputManagement->getOutputStateFor(PMONITOR); + + if (!CONFIG) + return rule; + + Debug::log(LOG, "CConfigManager::getMonitorRuleFor: found a wlr_output_manager override for {}", PMONITOR->szName); + + Debug::log(LOG, " > overriding enabled: {} -> {}", !rule.disabled, !CONFIG->enabled); + rule.disabled = !CONFIG->enabled; + + if ((CONFIG->committedProperties & OUTPUT_HEAD_COMMITTED_MODE) || (CONFIG->committedProperties & OUTPUT_HEAD_COMMITTED_CUSTOM_MODE)) { + Debug::log(LOG, " > overriding mode: {:.0f}x{:.0f}@{:.2f}Hz -> {:.0f}x{:.0f}@{:.2f}Hz", rule.resolution.x, rule.resolution.y, rule.refreshRate, CONFIG->resolution.x, + CONFIG->resolution.y, CONFIG->refresh / 1000.F); + rule.resolution = CONFIG->resolution; + rule.refreshRate = CONFIG->refresh / 1000.F; + } + + if (CONFIG->committedProperties & OUTPUT_HEAD_COMMITTED_POSITION) { + Debug::log(LOG, " > overriding offset: {:.0f}, {:.0f} -> {:.0f}, {:.0f}", rule.offset.x, rule.offset.y, CONFIG->position.x, CONFIG->position.y); + rule.offset = CONFIG->position; + } + + if (CONFIG->committedProperties & OUTPUT_HEAD_COMMITTED_TRANSFORM) { + Debug::log(LOG, " > overriding transform: {} -> {}", (uint8_t)rule.transform, (uint8_t)CONFIG->transform); + rule.transform = CONFIG->transform; + } + + if (CONFIG->committedProperties & OUTPUT_HEAD_COMMITTED_SCALE) { + Debug::log(LOG, " > overriding scale: {} -> {}", (uint8_t)rule.scale, (uint8_t)CONFIG->scale); + rule.scale = CONFIG->scale; + } + + if (CONFIG->committedProperties & OUTPUT_HEAD_COMMITTED_ADAPTIVE_SYNC) { + Debug::log(LOG, " > overriding vrr: {} -> {}", rule.vrr.value_or(0), CONFIG->adaptiveSync); + rule.vrr = (int)CONFIG->adaptiveSync; + } + + return rule; + }; + for (auto const& r : m_dMonitorRules | std::views::reverse) { - if (PMONITOR.matchesStaticSelector(r.name)) { - return r; + if (PMONITOR->matchesStaticSelector(r.name)) { + return applyWlrOutputConfig(r); } } - Debug::log(WARN, "No rule found for {}, trying to use the first.", PMONITOR.szName); + Debug::log(WARN, "No rule found for {}, trying to use the first.", PMONITOR->szName); for (auto const& r : m_dMonitorRules) { if (r.name.empty()) { - return r; + return applyWlrOutputConfig(r); } } Debug::log(WARN, "No rules configured. Using the default hardcoded one."); - return SMonitorRule{.autoDir = eAutoDirs::DIR_AUTO_RIGHT, - .name = "", - .resolution = Vector2D(0, 0), - .offset = Vector2D(-INT32_MAX, -INT32_MAX), - .scale = -1}; // 0, 0 is preferred and -1, -1 is auto + return applyWlrOutputConfig(SMonitorRule{.autoDir = eAutoDirs::DIR_AUTO_RIGHT, + .name = "", + .resolution = Vector2D(0, 0), + .offset = Vector2D(-INT32_MAX, -INT32_MAX), + .scale = -1}); // 0, 0 is preferred and -1, -1 is auto } SWorkspaceRule CConfigManager::getWorkspaceRuleFor(PHLWORKSPACE pWorkspace) { @@ -1459,7 +1501,7 @@ void CConfigManager::performMonitorReload() { if (!m->output || m->isUnsafeFallback) continue; - auto rule = getMonitorRuleFor(*m); + auto rule = getMonitorRuleFor(m); if (!g_pHyprRenderer->applyMonitorRule(m.get(), &rule)) { overAgain = true; @@ -1516,7 +1558,7 @@ void CConfigManager::ensureMonitorStatus() { if (!rm->output || rm->isUnsafeFallback) continue; - auto rule = getMonitorRuleFor(*rm); + auto rule = getMonitorRuleFor(rm); if (rule.disabled == rm->m_bEnabled) g_pHyprRenderer->applyMonitorRule(rm.get(), &rule); diff --git a/src/config/ConfigManager.hpp b/src/config/ConfigManager.hpp index da450e39..2134acf4 100644 --- a/src/config/ConfigManager.hpp +++ b/src/config/ConfigManager.hpp @@ -169,7 +169,7 @@ class CConfigManager { static std::string getMainConfigPath(); const std::string getConfigString(); - SMonitorRule getMonitorRuleFor(const CMonitor&); + SMonitorRule getMonitorRuleFor(const SP); SWorkspaceRule getWorkspaceRuleFor(PHLWORKSPACE workspace); std::string getDefaultWorkspaceFor(const std::string&); diff --git a/src/helpers/Monitor.cpp b/src/helpers/Monitor.cpp index a2d4c504..a9569699 100644 --- a/src/helpers/Monitor.cpp +++ b/src/helpers/Monitor.cpp @@ -114,7 +114,7 @@ void CMonitor::onConnect(bool noRule) { createdByUser = true; // should be true. WL and Headless backends should be addable / removable // get monitor rule that matches - SMonitorRule monitorRule = g_pConfigManager->getMonitorRuleFor(*this); + SMonitorRule monitorRule = g_pConfigManager->getMonitorRuleFor(self.lock()); // if it's disabled, disable and ignore if (monitorRule.disabled) { @@ -489,7 +489,7 @@ void CMonitor::setMirror(const std::string& mirrorOf) { pMirrorOf = nullptr; // set rule - const auto RULE = g_pConfigManager->getMonitorRuleFor(*this); + const auto RULE = g_pConfigManager->getMonitorRuleFor(self.lock()); vecPosition = RULE.offset; diff --git a/src/managers/KeybindManager.cpp b/src/managers/KeybindManager.cpp index 48c4517a..cd47bf71 100644 --- a/src/managers/KeybindManager.cpp +++ b/src/managers/KeybindManager.cpp @@ -1943,7 +1943,7 @@ SDispatchResult CKeybindManager::forceRendererReload(std::string args) { if (!m->output) continue; - auto rule = g_pConfigManager->getMonitorRuleFor(*m); + auto rule = g_pConfigManager->getMonitorRuleFor(m); if (!g_pHyprRenderer->applyMonitorRule(m.get(), &rule, true)) { overAgain = true; break; diff --git a/src/protocols/OutputManagement.cpp b/src/protocols/OutputManagement.cpp index 09552b19..dcc7a62d 100644 --- a/src/protocols/OutputManagement.cpp +++ b/src/protocols/OutputManagement.cpp @@ -307,10 +307,15 @@ COutputConfiguration::COutputConfiguration(SP resour LOGM(LOG, "disableHead on {}", PMONITOR->szName); - PMONITOR->activeMonitorRule.disabled = true; - if (!g_pConfigManager->replaceMonitorRule(PMONITOR->activeMonitorRule)) - g_pConfigManager->appendMonitorRule(PMONITOR->activeMonitorRule); - g_pHyprRenderer->applyMonitorRule(PMONITOR, &PMONITOR->activeMonitorRule, false); + SWlrManagerSavedOutputState newState; + if (owner->monitorStates.contains(PMONITOR->szName)) + newState = owner->monitorStates.at(PMONITOR->szName); + + newState.enabled = false; + + g_pConfigManager->m_bWantsMonitorReload = true; + + owner->monitorStates[PMONITOR->szName] = newState; }); resource->setTest([this](CZwlrOutputConfigurationV1* r) { @@ -346,6 +351,11 @@ bool COutputConfiguration::applyTestConfiguration(bool test) { LOGM(LOG, "Applying configuration"); + if (!owner) { + LOGM(ERR, "applyTestConfiguration: no owner?!"); + return false; + } + for (auto const& headw : heads) { auto head = headw.lock(); @@ -357,41 +367,59 @@ bool COutputConfiguration::applyTestConfiguration(bool test) { if (!PMONITOR) continue; - LOGM(LOG, "Applying config for monitor {}", PMONITOR->szName); + LOGM(LOG, "Saving config for monitor {}", PMONITOR->szName); - SMonitorRule newRule = PMONITOR->activeMonitorRule; - newRule.name = PMONITOR->szName; - newRule.disabled = false; + SWlrManagerSavedOutputState newState; + if (owner->monitorStates.contains(PMONITOR->szName)) + newState = owner->monitorStates.at(PMONITOR->szName); - if (head->committedProperties & COutputConfigurationHead::eCommittedProperties::OUTPUT_HEAD_COMMITTED_MODE) { - newRule.resolution = head->state.mode->getMode()->pixelSize; - newRule.refreshRate = head->state.mode->getMode()->refreshRate / 1000.F; - } else if (head->committedProperties & COutputConfigurationHead::eCommittedProperties::OUTPUT_HEAD_COMMITTED_CUSTOM_MODE) { - newRule.resolution = head->state.customMode.size; - newRule.refreshRate = head->state.customMode.refresh / 1000.F; + newState.enabled = true; + + if (head->state.committedProperties & eWlrOutputCommittedProperties::OUTPUT_HEAD_COMMITTED_MODE) { + newState.resolution = head->state.mode->getMode()->pixelSize; + newState.refresh = head->state.mode->getMode()->refreshRate; + newState.committedProperties |= eWlrOutputCommittedProperties::OUTPUT_HEAD_COMMITTED_MODE; + LOGM(LOG, " > Mode: {:.0f}x{:.0f}@{}mHz", newState.resolution.x, newState.resolution.y, newState.refresh); + } else if (head->state.committedProperties & eWlrOutputCommittedProperties::OUTPUT_HEAD_COMMITTED_CUSTOM_MODE) { + newState.resolution = head->state.customMode.size; + newState.refresh = head->state.customMode.refresh; + newState.committedProperties |= eWlrOutputCommittedProperties::OUTPUT_HEAD_COMMITTED_CUSTOM_MODE; + LOGM(LOG, " > Custom mode: {:.0f}x{:.0f}@{}mHz", newState.resolution.x, newState.resolution.y, newState.refresh); } - if (head->committedProperties & COutputConfigurationHead::eCommittedProperties::OUTPUT_HEAD_COMMITTED_POSITION) - newRule.offset = head->state.position; + if (head->state.committedProperties & eWlrOutputCommittedProperties::OUTPUT_HEAD_COMMITTED_POSITION) { + newState.position = head->state.position; + newState.committedProperties |= eWlrOutputCommittedProperties::OUTPUT_HEAD_COMMITTED_POSITION; + LOGM(LOG, " > Position: {:.0f}, {:.0f}", head->state.position.x, head->state.position.y); + } - if (head->committedProperties & COutputConfigurationHead::eCommittedProperties::OUTPUT_HEAD_COMMITTED_ADAPTIVE_SYNC) - newRule.vrr = head->state.adaptiveSync; + if (head->state.committedProperties & eWlrOutputCommittedProperties::OUTPUT_HEAD_COMMITTED_ADAPTIVE_SYNC) { + newState.adaptiveSync = head->state.adaptiveSync; + newState.committedProperties |= eWlrOutputCommittedProperties::OUTPUT_HEAD_COMMITTED_ADAPTIVE_SYNC; + LOGM(LOG, " > vrr: {}", newState.adaptiveSync); + } - if (head->committedProperties & COutputConfigurationHead::eCommittedProperties::OUTPUT_HEAD_COMMITTED_SCALE) - newRule.scale = head->state.scale; + if (head->state.committedProperties & eWlrOutputCommittedProperties::OUTPUT_HEAD_COMMITTED_SCALE) { + newState.scale = head->state.scale; + newState.committedProperties |= eWlrOutputCommittedProperties::OUTPUT_HEAD_COMMITTED_SCALE; + LOGM(LOG, " > scale: {:.2f}", newState.scale); + } - if (head->committedProperties & COutputConfigurationHead::eCommittedProperties::OUTPUT_HEAD_COMMITTED_TRANSFORM) - newRule.transform = head->state.transform; + if (head->state.committedProperties & eWlrOutputCommittedProperties::OUTPUT_HEAD_COMMITTED_TRANSFORM) { + newState.transform = head->state.transform; + newState.committedProperties |= eWlrOutputCommittedProperties::OUTPUT_HEAD_COMMITTED_TRANSFORM; + LOGM(LOG, " > transform: {}", (uint8_t)newState.transform); + } // reset properties for next set. - head->committedProperties = 0; + head->state.committedProperties = 0; - if (!g_pConfigManager->replaceMonitorRule(newRule)) - g_pConfigManager->appendMonitorRule(newRule); g_pConfigManager->m_bWantsMonitorReload = true; + + owner->monitorStates[PMONITOR->szName] = newState; } - LOGM(LOG, "Applied configuration"); + LOGM(LOG, "Saved configuration"); return true; } @@ -417,12 +445,12 @@ COutputConfigurationHead::COutputConfigurationHead(SPerror(ZWLR_OUTPUT_CONFIGURATION_HEAD_V1_ERROR_ALREADY_SET, "Property already set"); return; } - committedProperties |= OUTPUT_HEAD_COMMITTED_MODE; + state.committedProperties |= OUTPUT_HEAD_COMMITTED_MODE; state.mode = MODE; LOGM(LOG, " | configHead for {}: set mode to {}x{}@{}", pMonitor->szName, MODE->getMode()->pixelSize.x, MODE->getMode()->pixelSize.y, MODE->getMode()->refreshRate); @@ -434,7 +462,7 @@ COutputConfigurationHead::COutputConfigurationHead(SPerror(ZWLR_OUTPUT_CONFIGURATION_HEAD_V1_ERROR_ALREADY_SET, "Property already set"); return; } @@ -444,7 +472,7 @@ COutputConfigurationHead::COutputConfigurationHead(SPszName, w, h, refresh); @@ -456,12 +484,12 @@ COutputConfigurationHead::COutputConfigurationHead(SPerror(ZWLR_OUTPUT_CONFIGURATION_HEAD_V1_ERROR_ALREADY_SET, "Property already set"); return; } - committedProperties |= OUTPUT_HEAD_COMMITTED_POSITION; + state.committedProperties |= OUTPUT_HEAD_COMMITTED_POSITION; state.position = {x, y}; LOGM(LOG, " | configHead for {}: set pos to {}, {}", pMonitor->szName, x, y); @@ -473,7 +501,7 @@ COutputConfigurationHead::COutputConfigurationHead(SPerror(ZWLR_OUTPUT_CONFIGURATION_HEAD_V1_ERROR_ALREADY_SET, "Property already set"); return; } @@ -483,7 +511,7 @@ COutputConfigurationHead::COutputConfigurationHead(SPszName, transform); @@ -495,7 +523,7 @@ COutputConfigurationHead::COutputConfigurationHead(SPerror(ZWLR_OUTPUT_CONFIGURATION_HEAD_V1_ERROR_ALREADY_SET, "Property already set"); return; } @@ -507,7 +535,7 @@ COutputConfigurationHead::COutputConfigurationHead(SPszName, scale); @@ -519,7 +547,7 @@ COutputConfigurationHead::COutputConfigurationHead(SPerror(ZWLR_OUTPUT_CONFIGURATION_HEAD_V1_ERROR_ALREADY_SET, "Property already set"); return; } @@ -529,7 +557,7 @@ COutputConfigurationHead::COutputConfigurationHead(SPszName, as); @@ -601,3 +629,14 @@ SP COutputManagementProtocol::modeFromResource(wl_resource* r) { return nullptr; } + +SP COutputManagementProtocol::getOutputStateFor(SP pMonitor) { + for (auto const& m : m_vManagers) { + if (!m->monitorStates.contains(pMonitor->szName)) + continue; + + return makeShared(m->monitorStates.at(pMonitor->szName)); + } + + return nullptr; +} diff --git a/src/protocols/OutputManagement.hpp b/src/protocols/OutputManagement.hpp index 36478d0b..f4a84475 100644 --- a/src/protocols/OutputManagement.hpp +++ b/src/protocols/OutputManagement.hpp @@ -3,6 +3,7 @@ #include #include #include +#include #include "WaylandProtocol.hpp" #include "wlr-output-management-unstable-v1.hpp" #include "../helpers/signal/Signal.hpp" @@ -13,6 +14,43 @@ class CMonitor; class COutputHead; class COutputMode; +struct SMonitorRule; + +enum eWlrOutputCommittedProperties : uint32_t { + OUTPUT_HEAD_COMMITTED_MODE = (1 << 0), + OUTPUT_HEAD_COMMITTED_CUSTOM_MODE = (1 << 1), + OUTPUT_HEAD_COMMITTED_POSITION = (1 << 2), + OUTPUT_HEAD_COMMITTED_TRANSFORM = (1 << 3), + OUTPUT_HEAD_COMMITTED_SCALE = (1 << 4), + OUTPUT_HEAD_COMMITTED_ADAPTIVE_SYNC = (1 << 5), +}; + +struct SWlrManagerOutputState { + uint32_t committedProperties = 0; + + WP mode; + struct { + Vector2D size; + uint32_t refresh = 0; + } customMode; + Vector2D position; + wl_output_transform transform = WL_OUTPUT_TRANSFORM_NORMAL; + float scale = 1.F; + bool adaptiveSync = false; + bool enabled = true; +}; + +struct SWlrManagerSavedOutputState { + uint32_t committedProperties = 0; + Vector2D resolution; + uint32_t refresh = 0; + Vector2D position; + wl_output_transform transform = WL_OUTPUT_TRANSFORM_NORMAL; + float scale = 1.F; + bool adaptiveSync = false; + bool enabled = true; +}; + class COutputManager { public: COutputManager(SP resource_); @@ -21,6 +59,9 @@ class COutputManager { void ensureMonitorSent(CMonitor* pMonitor); void sendDone(); + // holds the states for this manager. + std::unordered_map monitorStates; + private: SP resource; bool stopped = false; @@ -80,30 +121,9 @@ class COutputConfigurationHead { public: COutputConfigurationHead(SP resource_, CMonitor* pMonitor_); - bool good(); + bool good(); - enum eCommittedProperties : uint32_t { - OUTPUT_HEAD_COMMITTED_MODE = (1 << 0), - OUTPUT_HEAD_COMMITTED_CUSTOM_MODE = (1 << 1), - OUTPUT_HEAD_COMMITTED_POSITION = (1 << 2), - OUTPUT_HEAD_COMMITTED_TRANSFORM = (1 << 3), - OUTPUT_HEAD_COMMITTED_SCALE = (1 << 4), - OUTPUT_HEAD_COMMITTED_ADAPTIVE_SYNC = (1 << 5), - }; - - uint32_t committedProperties = 0; - - struct { - WP mode; - struct { - Vector2D size; - uint32_t refresh = 0; - } customMode; - Vector2D position; - wl_output_transform transform = WL_OUTPUT_TRANSFORM_NORMAL; - float scale = 1.F; - bool adaptiveSync = false; - } state; + SWlrManagerOutputState state; private: SP resource; @@ -136,6 +156,9 @@ class COutputManagementProtocol : public IWaylandProtocol { virtual void bindManager(wl_client* client, void* data, uint32_t ver, uint32_t id); + // doesn't have to return one + SP getOutputStateFor(SP pMonitor); + private: void destroyResource(COutputManager* resource); void destroyResource(COutputHead* resource); From 32a8caf7e7a0609629eb08c91de9f9b23a10c455 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=B6rg=20Thalheim?= Date: Thu, 6 Jun 2024 10:07:53 +0200 Subject: [PATCH 0444/2181] Nix: also test cross build --- flake.nix | 10 ++++++++++ nix/default.nix | 2 +- 2 files changed, 11 insertions(+), 1 deletion(-) diff --git a/flake.nix b/flake.nix index ef48b2d1..eca45675 100644 --- a/flake.nix +++ b/flake.nix @@ -67,6 +67,15 @@ hyprland-extras ]; }); + pkgsCrossFor = eachSystem (system: crossSystem: + import nixpkgs { + localSystem = system; + crossSystem = crossSystem; + overlays = with self.overlays; [ + hyprland-packages + hyprland-extras + ]; + }); in { overlays = import ./nix/overlays.nix {inherit self lib inputs;}; @@ -92,6 +101,7 @@ xdg-desktop-portal-hyprland ; + hyprland-cross = (pkgsCrossFor.${system} "aarch64-linux").hyprland; }); devShells = eachSystem (system: { diff --git a/nix/default.nix b/nix/default.nix index 40675d9a..be7394e4 100644 --- a/nix/default.nix +++ b/nix/default.nix @@ -102,7 +102,6 @@ in ninja pkg-config python3 # for udis86 - wayland-scanner ]; outputs = [ @@ -130,6 +129,7 @@ in tomlplusplus wayland wayland-protocols + wayland-scanner xorg.libXcursor ] (optionals customStdenv.hostPlatform.isMusl [libexecinfo]) From 7b56ce6521e5ad3b0a2dab6f79a045e79c7aeb82 Mon Sep 17 00:00:00 2001 From: Mihai Fufezan Date: Tue, 11 Jun 2024 18:49:12 +0300 Subject: [PATCH 0445/2181] CI/Nix: add cross build --- .github/workflows/nix-build.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/nix-build.yml b/.github/workflows/nix-build.yml index 50823629..6351216f 100644 --- a/.github/workflows/nix-build.yml +++ b/.github/workflows/nix-build.yml @@ -12,6 +12,7 @@ jobs: matrix: package: - hyprland + - hyprland-cross - xdg-desktop-portal-hyprland runs-on: ubuntu-latest From 77f2a01304f33a2dc7c9002ca9fb20a7653e6ae1 Mon Sep 17 00:00:00 2001 From: Mihai Fufezan Date: Thu, 26 Sep 2024 16:52:02 +0300 Subject: [PATCH 0446/2181] flake.lock: update nixpkgs --- flake.lock | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/flake.lock b/flake.lock index a1f0d88d..4ebdc734 100644 --- a/flake.lock +++ b/flake.lock @@ -154,11 +154,11 @@ }, "nixpkgs": { "locked": { - "lastModified": 1726755586, - "narHash": "sha256-PmUr/2GQGvFTIJ6/Tvsins7Q43KTMvMFhvG6oaYK+Wk=", + "lastModified": 1727122398, + "narHash": "sha256-o8VBeCWHBxGd4kVMceIayf5GApqTavJbTa44Xcg5Rrk=", "owner": "NixOS", "repo": "nixpkgs", - "rev": "c04d5652cfa9742b1d519688f65d1bbccea9eb7e", + "rev": "30439d93eb8b19861ccbe3e581abf97bdc91b093", "type": "github" }, "original": { From 14942bca60cc7d85e8238a151bd444112601ebe6 Mon Sep 17 00:00:00 2001 From: Mihai Fufezan Date: Sun, 22 Sep 2024 21:19:09 +0300 Subject: [PATCH 0447/2181] Nix: re-add hyprland-protocols --- flake.lock | 26 +++++++++++++++++++++++++- flake.nix | 6 ++++++ nix/default.nix | 2 ++ nix/overlays.nix | 1 + 4 files changed, 34 insertions(+), 1 deletion(-) diff --git a/flake.lock b/flake.lock index 4ebdc734..7e0f093e 100644 --- a/flake.lock +++ b/flake.lock @@ -56,6 +56,29 @@ } }, "hyprland-protocols": { + "inputs": { + "nixpkgs": [ + "nixpkgs" + ], + "systems": [ + "systems" + ] + }, + "locked": { + "lastModified": 1721326555, + "narHash": "sha256-zCu4R0CSHEactW9JqYki26gy8h9f6rHmSwj4XJmlHgg=", + "owner": "hyprwm", + "repo": "hyprland-protocols", + "rev": "5a11232266bf1a1f5952d5b179c3f4b2facaaa84", + "type": "github" + }, + "original": { + "owner": "hyprwm", + "repo": "hyprland-protocols", + "type": "github" + } + }, + "hyprland-protocols_2": { "inputs": { "nixpkgs": [ "xdph", @@ -172,6 +195,7 @@ "inputs": { "aquamarine": "aquamarine", "hyprcursor": "hyprcursor", + "hyprland-protocols": "hyprland-protocols", "hyprlang": "hyprlang", "hyprutils": "hyprutils", "hyprwayland-scanner": "hyprwayland-scanner", @@ -197,7 +221,7 @@ }, "xdph": { "inputs": { - "hyprland-protocols": "hyprland-protocols", + "hyprland-protocols": "hyprland-protocols_2", "hyprlang": [ "hyprlang" ], diff --git a/flake.nix b/flake.nix index eca45675..ee5af6a1 100644 --- a/flake.nix +++ b/flake.nix @@ -22,6 +22,12 @@ inputs.hyprlang.follows = "hyprlang"; }; + hyprland-protocols = { + url = "github:hyprwm/hyprland-protocols"; + inputs.nixpkgs.follows = "nixpkgs"; + inputs.systems.follows = "systems"; + }; + hyprlang = { url = "github:hyprwm/hyprlang"; inputs.nixpkgs.follows = "nixpkgs"; diff --git a/nix/default.nix b/nix/default.nix index be7394e4..85a3105d 100644 --- a/nix/default.nix +++ b/nix/default.nix @@ -13,6 +13,7 @@ cairo, git, hyprcursor, + hyprland-protocols, hyprlang, hyprutils, hyprwayland-scanner, @@ -116,6 +117,7 @@ in cairo git hyprcursor + hyprland-protocols hyprlang hyprutils libdrm diff --git a/nix/overlays.nix b/nix/overlays.nix index d6e078fa..71b5f59f 100644 --- a/nix/overlays.nix +++ b/nix/overlays.nix @@ -22,6 +22,7 @@ in { # Dependencies inputs.aquamarine.overlays.default inputs.hyprcursor.overlays.default + inputs.hyprland-protocols.overlays.default inputs.hyprlang.overlays.default inputs.hyprutils.overlays.default inputs.hyprwayland-scanner.overlays.default From 27211c71e92e1bacf111d8a815e958f80969ce6e Mon Sep 17 00:00:00 2001 From: Mihai Fufezan Date: Sun, 22 Sep 2024 21:20:35 +0300 Subject: [PATCH 0448/2181] Meson: try to find udis86 through pkgconfig, fallback to subproject Only the fork provides a .pc file, so there's no risk of linking the wrong lib version. If pkg-config can't find it (most cases), fall back to using the subproject through the wrap file. --- meson.build | 4 ---- nix/default.nix | 8 ++------ nix/overlays.nix | 17 +++++++++++++++++ src/meson.build | 6 +++++- subprojects/udis86.wrap | 5 +++++ 5 files changed, 29 insertions(+), 11 deletions(-) create mode 100644 subprojects/udis86.wrap diff --git a/meson.build b/meson.build index 9449c241..42ed519d 100644 --- a/meson.build +++ b/meson.build @@ -43,10 +43,6 @@ xcb_xfixes_dep = dependency('xcb-xfixes', required: get_option('xwayland')) gio_dep = dependency('gio-2.0', required: true) -cmake = import('cmake') -udis = cmake.subproject('udis86') -udis86 = udis.dependency('libudis86') - if not xcb_dep.found() add_project_arguments('-DNO_XWAYLAND', language: 'cpp') endif diff --git a/nix/default.nix b/nix/default.nix index 85a3105d..df270f28 100644 --- a/nix/default.nix +++ b/nix/default.nix @@ -6,7 +6,6 @@ pkgconf, makeWrapper, meson, - cmake, ninja, aquamarine, binutils, @@ -17,7 +16,6 @@ hyprlang, hyprutils, hyprwayland-scanner, - jq, libGL, libdrm, libexecinfo, @@ -27,9 +25,9 @@ mesa, pango, pciutils, - python3, systemd, tomlplusplus, + udis86-hyprland, wayland, wayland-protocols, wayland-scanner, @@ -96,13 +94,10 @@ in nativeBuildInputs = [ hyprwayland-scanner - jq makeWrapper meson - cmake ninja pkg-config - python3 # for udis86 ]; outputs = [ @@ -129,6 +124,7 @@ in pango pciutils tomlplusplus + udis86-hyprland wayland wayland-protocols wayland-scanner diff --git a/nix/overlays.nix b/nix/overlays.nix index 71b5f59f..2b2788e7 100644 --- a/nix/overlays.nix +++ b/nix/overlays.nix @@ -26,6 +26,7 @@ in { inputs.hyprlang.overlays.default inputs.hyprutils.overlays.default inputs.hyprwayland-scanner.overlays.default + self.overlays.udis86 # Hyprland packages themselves (final: prev: let @@ -64,4 +65,20 @@ in { hyprland-extras = lib.composeManyExtensions [ inputs.xdph.overlays.xdg-desktop-portal-hyprland ]; + + # udis86 from nixpkgs is too old, and also does not provide a .pc file + # this version is the one used in the git submodule, and allows us to + # fetch the source without '?submodules=1' + udis86 = final: prev: { + udis86-hyprland = prev.udis86.overrideAttrs (self: super: { + src = final.fetchFromGitHub { + owner = "canihavesomecoffee"; + repo = "udis86"; + rev = "5336633af70f3917760a6d441ff02d93477b0c86"; + hash = "sha256-HifdUQPGsKQKQprByeIznvRLONdOXeolOsU5nkwIv3g="; + }; + + patches = []; + }); + }; } diff --git a/src/meson.build b/src/meson.build index da46c38c..7c71a735 100644 --- a/src/meson.build +++ b/src/meson.build @@ -31,7 +31,11 @@ executable( backtrace_dep, epoll_dep, gio_dep, - udis86, + + # Try to find canihavesomecoffee's udis86 using pkgconfig + # vmt/udis86 does not provide a .pc file and won't be detected this way + # Falls back to using the subproject through udis86.wrap + dependency('udis86'), dependency('pixman-1'), dependency('gl', 'opengl'), diff --git a/subprojects/udis86.wrap b/subprojects/udis86.wrap new file mode 100644 index 00000000..dfb63984 --- /dev/null +++ b/subprojects/udis86.wrap @@ -0,0 +1,5 @@ +[wrap-file] +method = cmake + +[provide] +udis86 = libudis86_dep From 89d945aabe632387f113ac500bfee573d51cc4f7 Mon Sep 17 00:00:00 2001 From: Mihai Fufezan Date: Sun, 22 Sep 2024 18:00:02 +0300 Subject: [PATCH 0449/2181] CMake: use hyprland-protocols from pkg-config, fallback to subproject protocolnew: fix external path, which may not be in $CMAKE_SOURCE_DIR --- CMakeLists.txt | 22 +++++++++++++++------- 1 file changed, 15 insertions(+), 7 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 8055271e..08eb93cf 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -230,7 +230,7 @@ add_custom_target(generate-protocol-headers) function(protocolnew protoPath protoName external) if(external) - set(path ${CMAKE_SOURCE_DIR}/${protoPath}) + set(path ${protoPath}) else() set(path ${WAYLAND_PROTOCOLS_DIR}/${protoPath}) endif() @@ -261,11 +261,20 @@ endfunction() target_link_libraries(Hyprland OpenGL::EGL OpenGL::GL Threads::Threads libudis86) -protocolnew("subprojects/hyprland-protocols/protocols" - "hyprland-global-shortcuts-v1" true) +pkg_check_modules(hyprland_protocols_dep hyprland-protocols>=0.2.0) +if(hyprland_protocols_dep_FOUND) + pkg_get_variable(HYPRLAND_PROTOCOLS hyprland-protocols pkgdatadir) + message(STATUS "hyprland-protocols dependency set to ${HYPRLAND_PROTOCOLS}") +else() + set(HYPRLAND_PROTOCOLS "subprojects/hyprland-protocols") + message(STATUS "hyprland-protocols subproject set to ${HYPRLAND_PROTOCOLS}") +endif() + +protocolnew("${HYPRLAND_PROTOCOLS}/protocols" "hyprland-global-shortcuts-v1" + true) protocolnew("unstable/text-input" "text-input-unstable-v1" false) -protocolnew("subprojects/hyprland-protocols/protocols" - "hyprland-toplevel-export-v1" true) +protocolnew("${HYPRLAND_PROTOCOLS}/protocols" "hyprland-toplevel-export-v1" + true) protocolnew("protocols" "wlr-screencopy-unstable-v1" true) protocolnew("protocols" "wlr-gamma-control-unstable-v1" true) protocolnew("protocols" "wlr-foreign-toplevel-management-unstable-v1" true) @@ -276,8 +285,7 @@ protocolnew("protocols" "input-method-unstable-v2" true) protocolnew("protocols" "wlr-output-management-unstable-v1" true) protocolnew("protocols" "kde-server-decoration" true) protocolnew("protocols" "wlr-data-control-unstable-v1" true) -protocolnew("subprojects/hyprland-protocols/protocols" "hyprland-focus-grab-v1" - true) +protocolnew("${HYPRLAND_PROTOCOLS}/protocols" "hyprland-focus-grab-v1" true) protocolnew("protocols" "wlr-layer-shell-unstable-v1" true) protocolnew("protocols" "wayland-drm" true) protocolnew("staging/tearing-control" "tearing-control-v1" false) From be96787ed086f751455cf713739296b5c6e3a235 Mon Sep 17 00:00:00 2001 From: Mihai Fufezan Date: Sun, 22 Sep 2024 18:01:44 +0300 Subject: [PATCH 0450/2181] CMake: use udis86 from pkg-config, fallback to subproject Only canihavesomecoffee's fork (the one the subproject uses) provides a .pc file, so we either find the correct version or we use the subproject. --- CMakeLists.txt | 27 ++++++++++++++++++++------- 1 file changed, 20 insertions(+), 7 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 08eb93cf..8115d01c 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -25,8 +25,18 @@ message(STATUS "Gathering git info") execute_process(COMMAND ./scripts/generateVersion.sh WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}) -# udis -add_subdirectory("subprojects/udis86") +find_package(PkgConfig REQUIRED) + +# Try to find canihavesomecoffee's udis86 using pkgconfig vmd/udis86 does not +# provide a .pc file and won't be detected this way +pkg_check_modules(udis_dep IMPORTED_TARGET udis86>=1.7.2) + +# Fallback to subproject +if(NOT udis_dep_FOUND) + add_subdirectory("subprojects/udis86") + include_directories("subprojects/udis86") + message(STATUS "udis86 dependency not found, falling back to subproject") +endif() if(CMAKE_BUILD_TYPE) string(TOLOWER ${CMAKE_BUILD_TYPE} BUILDTYPE_LOWER) @@ -47,8 +57,6 @@ else() set(BUILDTYPE_LOWER "release") endif() -find_package(PkgConfig REQUIRED) - pkg_get_variable(WAYLAND_PROTOCOLS_DIR wayland-protocols pkgdatadir) message(STATUS "Found wayland-protocols at ${WAYLAND_PROTOCOLS_DIR}") pkg_get_variable(WAYLAND_SCANNER_PKGDATA_DIR wayland-scanner pkgdatadir) @@ -63,7 +71,8 @@ else() message(STATUS "Configuring Hyprland in Release with CMake") endif() -include_directories(. "src/" "subprojects/udis86/" "protocols/") +include_directories(. "src/" "protocols/") + set(CMAKE_CXX_STANDARD 26) add_compile_options( -Wall @@ -224,6 +233,11 @@ target_precompile_headers(Hyprland PRIVATE message(STATUS "Setting link libraries") target_link_libraries(Hyprland rt PkgConfig::aquamarine_dep PkgConfig::deps) +if(udis_dep_FOUND) + target_link_libraries(Hyprland PkgConfig::udis_dep) +else() + target_link_libraries(Hyprland libudis86) +endif() # used by `make installheaders`, to ensure the headers are generated add_custom_target(generate-protocol-headers) @@ -258,8 +272,7 @@ function(protocolWayland) PRIVATE ${CMAKE_SOURCE_DIR}/protocols/wayland.hpp) endfunction() -target_link_libraries(Hyprland OpenGL::EGL OpenGL::GL Threads::Threads - libudis86) +target_link_libraries(Hyprland OpenGL::EGL OpenGL::GL Threads::Threads) pkg_check_modules(hyprland_protocols_dep hyprland-protocols>=0.2.0) if(hyprland_protocols_dep_FOUND) From f75f8efb1be227e586cc0ba2ce6153ce56e04314 Mon Sep 17 00:00:00 2001 From: Mihai Fufezan Date: Sun, 22 Sep 2024 20:53:34 +0300 Subject: [PATCH 0451/2181] Meson: add tracy dependency --- meson.build | 6 ++++++ meson_options.txt | 1 + nix/default.nix | 7 +++++-- src/meson.build | 1 + subprojects/tracy.wrap | 1 + 5 files changed, 14 insertions(+), 2 deletions(-) create mode 100644 subprojects/tracy.wrap diff --git a/meson.build b/meson.build index 42ed519d..3545f46a 100644 --- a/meson.build +++ b/meson.build @@ -73,6 +73,12 @@ foreach file : headers install_headers(file, subdir: 'hyprland', preserve_path: true) endforeach +tracy = dependency('tracy', static: true, required: get_option('tracy_enable')) + +if get_option('tracy_enable') and get_option('buildtype') != 'debugoptimized' + warning('Profiling builds should set -- buildtype = debugoptimized') +endif + subdir('protocols') subdir('src') subdir('hyprctl') diff --git a/meson_options.txt b/meson_options.txt index 16a34a54..d8c9d5e6 100644 --- a/meson_options.txt +++ b/meson_options.txt @@ -1,3 +1,4 @@ option('xwayland', type: 'feature', value: 'auto', description: 'Enable support for X11 applications') option('systemd', type: 'feature', value: 'auto', description: 'Enable systemd integration') option('legacy_renderer', type: 'feature', value: 'disabled', description: 'Enable legacy renderer') +option('tracy_enable', type: 'boolean', value: false , description: 'Enable profiling') diff --git a/nix/default.nix b/nix/default.nix index df270f28..6f086ccc 100644 --- a/nix/default.nix +++ b/nix/default.nix @@ -144,7 +144,7 @@ in mesonBuildType = if debug - then "debug" + then "debugoptimized" else "release"; # we want as much debug info as possible @@ -156,7 +156,10 @@ in "legacy_renderer" = legacyRenderer; "systemd" = withSystemd; }) - (mesonBool "b_pch" false) + (mapAttrsToList mesonBool { + "b_pch" = false; + "tracy_enable" = false; + }) ]; postInstall = '' diff --git a/src/meson.build b/src/meson.build index 7c71a735..2dbe2f44 100644 --- a/src/meson.build +++ b/src/meson.build @@ -31,6 +31,7 @@ executable( backtrace_dep, epoll_dep, gio_dep, + tracy, # Try to find canihavesomecoffee's udis86 using pkgconfig # vmt/udis86 does not provide a .pc file and won't be detected this way diff --git a/subprojects/tracy.wrap b/subprojects/tracy.wrap new file mode 100644 index 00000000..11b21787 --- /dev/null +++ b/subprojects/tracy.wrap @@ -0,0 +1 @@ +[wrap-file] From b2143a98e2719012f8c36211a066f8ebccc950b8 Mon Sep 17 00:00:00 2001 From: Mihai Fufezan Date: Thu, 26 Sep 2024 23:00:20 +0300 Subject: [PATCH 0452/2181] CI/Nix: no longer build with submodules --- .github/workflows/nix-build.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/nix-build.yml b/.github/workflows/nix-build.yml index 6351216f..73adb497 100644 --- a/.github/workflows/nix-build.yml +++ b/.github/workflows/nix-build.yml @@ -25,4 +25,4 @@ jobs: name: hyprland authToken: "${{ secrets.CACHIX_AUTH_TOKEN }}" - - run: nix build 'git+https://github.com/hyprwm/Hyprland?ref=${{ github.ref }}&submodules=1#${{ matrix.package }}' -L --extra-substituters "https://hyprland.cachix.org" + - run: nix build 'git+https://github.com/hyprwm/Hyprland?ref=${{ github.ref }}#${{ matrix.package }}' -L --extra-substituters "https://hyprland.cachix.org" From e20aef7d53fcde1470e8d7672e6a03d814fca97f Mon Sep 17 00:00:00 2001 From: Vaxry Date: Thu, 26 Sep 2024 22:34:33 +0100 Subject: [PATCH 0453/2181] opengl: remove debug log --- src/render/OpenGL.cpp | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/render/OpenGL.cpp b/src/render/OpenGL.cpp index ff3d52e4..4f22d6aa 100644 --- a/src/render/OpenGL.cpp +++ b/src/render/OpenGL.cpp @@ -1384,8 +1384,6 @@ void CHyprOpenGLImpl::renderTextureInternalWithDamage(SP tex, CBox* pB Mat3x3 matrix = m_RenderData.monitorProjection.projectBox(newBox, TRANSFORM, newBox.rot); Mat3x3 glMatrix = m_RenderData.projection.copy().multiply(matrix); - Debug::log(LOG, "internal:\nmat: {},\nglmat: {}", matrix.toString(), glMatrix.toString()); - if (waitTimeline != nullptr) { if (!waitForTimelinePoint(waitTimeline, waitPoint)) { Debug::log(ERR, "renderTextureInternalWithDamage: failed to wait for explicit sync point {}", waitPoint); From 58669fef77ac17ea205ce3570f48e17de736111f Mon Sep 17 00:00:00 2001 From: Mihai Fufezan Date: Fri, 27 Sep 2024 18:35:29 +0300 Subject: [PATCH 0454/2181] flake.lock: update --- flake.lock | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/flake.lock b/flake.lock index 7e0f093e..5adaa350 100644 --- a/flake.lock +++ b/flake.lock @@ -16,11 +16,11 @@ ] }, "locked": { - "lastModified": 1726665257, - "narHash": "sha256-rEzEZtd3iyVo5RJ1OGujOlnywNf3gsrOnjAn1NLciD4=", + "lastModified": 1727261104, + "narHash": "sha256-rxDI7WrxIRV9it9mDCHcLa7xQykf1JloXnoXr5xQ8zI=", "owner": "hyprwm", "repo": "aquamarine", - "rev": "752d0fbd141fabb5a1e7f865199b80e6e76f8d8e", + "rev": "b82fdaff917582a9d568969e15e61b398c71e990", "type": "github" }, "original": { @@ -65,11 +65,11 @@ ] }, "locked": { - "lastModified": 1721326555, - "narHash": "sha256-zCu4R0CSHEactW9JqYki26gy8h9f6rHmSwj4XJmlHgg=", + "lastModified": 1727451107, + "narHash": "sha256-qV9savtHwmZUa0eJE294WYJjKPGB2+bJhwByFShsVyo=", "owner": "hyprwm", "repo": "hyprland-protocols", - "rev": "5a11232266bf1a1f5952d5b179c3f4b2facaaa84", + "rev": "6b3261ee13a6d2b99de79a31d352f6996e35bde3", "type": "github" }, "original": { @@ -139,11 +139,11 @@ ] }, "locked": { - "lastModified": 1727219120, - "narHash": "sha256-wmT+JpnDk6EjgASU2VGfS0nnu6oKA4Cw25o5fzpDD/Q=", + "lastModified": 1727300645, + "narHash": "sha256-OvAtVLaSRPnbXzOwlR1fVqCXR7i+ICRX3aPMCdIiv+c=", "owner": "hyprwm", "repo": "hyprutils", - "rev": "db956287d3aa194dda91d05c8eb286de2a569edf", + "rev": "3f5293432b6dc6a99f26aca2eba3876d2660665c", "type": "github" }, "original": { @@ -162,11 +162,11 @@ ] }, "locked": { - "lastModified": 1726840673, - "narHash": "sha256-HIPEXyRRVZoqD6U+lFS1B0tsIU7p83FaB9m7KT/x6mQ=", + "lastModified": 1726874836, + "narHash": "sha256-VKR0sf0PSNCB0wPHVKSAn41mCNVCnegWmgkrneKDhHM=", "owner": "hyprwm", "repo": "hyprwayland-scanner", - "rev": "b68dab23fc922eae99306988133ee80a40b39ca5", + "rev": "500c81a9e1a76760371049a8d99e008ea77aa59e", "type": "github" }, "original": { From 2cf6e7862a844ad96aa060d63f6774df7e2234a6 Mon Sep 17 00:00:00 2001 From: Mike Will Date: Fri, 27 Sep 2024 20:49:40 -0400 Subject: [PATCH 0455/2181] dwindle: add config option `split_bias` (#7920) If `default_split_ratio` is greater than 1.0, `split_bias` will give the bigger half to a specific window: 0 - positional (default) 1 - current window 2 - opening window --- src/config/ConfigManager.cpp | 1 + src/layout/DwindleLayout.cpp | 8 +++++++- 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/src/config/ConfigManager.cpp b/src/config/ConfigManager.cpp index ab5905c2..ad6e1871 100644 --- a/src/config/ConfigManager.cpp +++ b/src/config/ConfigManager.cpp @@ -446,6 +446,7 @@ CConfigManager::CConfigManager() { m_pConfig->addConfigValue("dwindle:no_gaps_when_only", Hyprlang::INT{0}); m_pConfig->addConfigValue("dwindle:use_active_for_splits", Hyprlang::INT{1}); m_pConfig->addConfigValue("dwindle:default_split_ratio", {1.f}); + m_pConfig->addConfigValue("dwindle:split_bias", Hyprlang::INT{0}); m_pConfig->addConfigValue("dwindle:smart_split", Hyprlang::INT{0}); m_pConfig->addConfigValue("dwindle:smart_resizing", Hyprlang::INT{1}); diff --git a/src/layout/DwindleLayout.cpp b/src/layout/DwindleLayout.cpp index c936d59c..69b044b4 100644 --- a/src/layout/DwindleLayout.cpp +++ b/src/layout/DwindleLayout.cpp @@ -1,7 +1,7 @@ #include "DwindleLayout.hpp" -#include "../render/decorations/CHyprGroupBarDecoration.hpp" #include "../Compositor.hpp" #include "../config/ConfigValue.hpp" +#include "../render/decorations/CHyprGroupBarDecoration.hpp" void SDwindleNodeData::recalcSizePosRecursive(bool force, bool horizontalOverride, bool verticalOverride) { if (children[0]) { @@ -459,6 +459,12 @@ void CHyprDwindleLayout::onWindowCreatedTiling(PHLWINDOW pWindow, eDirection dir } } + // split in favor of a specific window + const auto first = NEWPARENT->children[0]; + static auto PSPLITBIAS = CConfigValue("dwindle:split_bias"); + if ((*PSPLITBIAS == 1 && first == PNODE) || (*PSPLITBIAS == 2 && first == OPENINGON)) + NEWPARENT->splitRatio = 2.f - NEWPARENT->splitRatio; + // and update the previous parent if it exists if (OPENINGON->pParent) { if (OPENINGON->pParent->children[0] == OPENINGON) { From 6f313de952311282e82461a342c74ea702d9f13a Mon Sep 17 00:00:00 2001 From: bivsk <141476105+bivsk@users.noreply.github.com> Date: Sat, 28 Sep 2024 08:46:31 -0400 Subject: [PATCH 0456/2181] core: Fix Musl builds (#7934) Musl does not include the internal type `__time_t`. Use `time_t` instead. --- src/protocols/PresentationTime.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/protocols/PresentationTime.cpp b/src/protocols/PresentationTime.cpp index e1ff52cd..71f74cd5 100644 --- a/src/protocols/PresentationTime.cpp +++ b/src/protocols/PresentationTime.cpp @@ -58,8 +58,8 @@ void CPresentationFeedback::sendQueued(SP data, timespe if (reportedFlags & Aquamarine::IOutput::AQ_OUTPUT_PRESENT_HW_COMPLETION) flags |= WP_PRESENTATION_FEEDBACK_KIND_HW_COMPLETION; - __time_t tv_sec = 0; - if (sizeof(__time_t) > 4) + time_t tv_sec = 0; + if (sizeof(time_t) > 4) tv_sec = when->tv_sec >> 32; if (data->wasPresented) From d73c14751ad40fd54d93baac2226f550142b0e74 Mon Sep 17 00:00:00 2001 From: Mihai Fufezan Date: Sat, 28 Sep 2024 21:53:08 +0300 Subject: [PATCH 0457/2181] CI/Nix: git+https -> github --- .github/workflows/nix-build.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/nix-build.yml b/.github/workflows/nix-build.yml index 73adb497..d1f47ee4 100644 --- a/.github/workflows/nix-build.yml +++ b/.github/workflows/nix-build.yml @@ -25,4 +25,4 @@ jobs: name: hyprland authToken: "${{ secrets.CACHIX_AUTH_TOKEN }}" - - run: nix build 'git+https://github.com/hyprwm/Hyprland?ref=${{ github.ref }}#${{ matrix.package }}' -L --extra-substituters "https://hyprland.cachix.org" + - run: nix build 'github:hyprwm/Hyprland?ref=${{ github.ref }}#${{ matrix.package }}' -L --extra-substituters "https://hyprland.cachix.org" From 9e418671e12549156d0735a6b23732f66d5647c7 Mon Sep 17 00:00:00 2001 From: Mike Will Date: Sun, 29 Sep 2024 09:42:10 -0400 Subject: [PATCH 0458/2181] config: add descriptions for dwindle and master layout options (#7933) --- src/config/ConfigDescriptions.hpp | 160 ++++++++++++++++++++++++++++++ 1 file changed, 160 insertions(+) diff --git a/src/config/ConfigDescriptions.hpp b/src/config/ConfigDescriptions.hpp index 84ac1a41..3a91a808 100644 --- a/src/config/ConfigDescriptions.hpp +++ b/src/config/ConfigDescriptions.hpp @@ -1372,4 +1372,164 @@ inline static const std::vector CONFIG_OPTIONS = { .type = CONFIG_OPTION_BOOL, .data = SConfigOptionDescription::SBoolData{true}, }, + + /* + * dwindle: + */ + + SConfigOptionDescription{ + .value = "dwindle:pseudotile", + .description = "enable pseudotiling. Pseudotiled windows retain their floating size when tiled.", + .type = CONFIG_OPTION_BOOL, + .data = SConfigOptionDescription::SBoolData{false}, + }, + SConfigOptionDescription{ + .value = "dwindle:force_split", + .description = "0 -> split follows mouse, 1 -> always split to the left (new = left or top) 2 -> always split to the right (new = right or bottom)", + .type = CONFIG_OPTION_CHOICE, + .data = SConfigOptionDescription::SChoiceData{0, "follow mouse,left or top,right or bottom"}, + }, + SConfigOptionDescription{ + .value = "dwindle:preserve_split", + .description = "if enabled, the split (side/top) will not change regardless of what happens to the container.", + .type = CONFIG_OPTION_BOOL, + .data = SConfigOptionDescription::SBoolData{false}, + }, + SConfigOptionDescription{ + .value = "dwindle:smart_split", + .description = "if enabled, allows a more precise control over the window split direction based on the cursor's position. The window is conceptually divided into four " + "triangles, and cursor's triangle determines the split direction. This feature also turns on preserve_split.", + .type = CONFIG_OPTION_BOOL, + .data = SConfigOptionDescription::SBoolData{false}, + }, + SConfigOptionDescription{ + .value = "dwindle:smart_resizing", + .description = + "if enabled, resizing direction will be determined by the mouse's position on the window (nearest to which corner). Else, it is based on the window's tiling position.", + .type = CONFIG_OPTION_BOOL, + .data = SConfigOptionDescription::SBoolData{true}, + }, + SConfigOptionDescription{ + .value = "dwindle:permanent_direction_override", + .description = "if enabled, makes the preselect direction persist until either this mode is turned off, another direction is specified, or a non-direction is specified " + "(anything other than l,r,u/t,d/b)", + .type = CONFIG_OPTION_BOOL, + .data = SConfigOptionDescription::SBoolData{false}, + }, + SConfigOptionDescription{ + .value = "dwindle:special_scale_factor", + .description = "specifies the scale factor of windows on the special workspace [0 - 1]", + .type = CONFIG_OPTION_FLOAT, + .data = SConfigOptionDescription::SFloatData{1, 0, 1}, + }, + SConfigOptionDescription{ + .value = "dwindle:split_width_multiplier", + .description = "specifies the auto-split width multiplier", + .type = CONFIG_OPTION_FLOAT, + .data = SConfigOptionDescription::SFloatData{1, 0.1, 3}, + }, + SConfigOptionDescription{ + .value = "dwindle:no_gaps_when_only", + .description = "whether to apply gaps when there is only one window on a workspace, aka. smart gaps. (default: disabled - 0) no border - 1, with border - 2 [0/1/2]", + .type = CONFIG_OPTION_CHOICE, + .data = SConfigOptionDescription::SChoiceData{0, "disabled,no border,with border"}, + }, + SConfigOptionDescription{ + .value = "dwindle:use_active_for_splits", + .description = "whether to prefer the active window or the mouse position for splits", + .type = CONFIG_OPTION_BOOL, + .data = SConfigOptionDescription::SBoolData{true}, + }, + SConfigOptionDescription{ + .value = "dwindle:default_split_ratio", + .description = "the default split ratio on window open. 1 means even 50/50 split. [0.1 - 1.9]", + .type = CONFIG_OPTION_FLOAT, + .data = SConfigOptionDescription::SFloatData{1, 0.1, 1.9}, + }, + SConfigOptionDescription{ + .value = "dwindle:split_bias", + .description = "specifies which window will receive the larger half of a split. positional - 0, current window - 1, opening window - 2 [0/1/2]", + .type = CONFIG_OPTION_CHOICE, + .data = SConfigOptionDescription::SChoiceData{0, "positional,current,opening"}, + }, + + /* + * master: + */ + + SConfigOptionDescription{ + .value = "master:allow_small_split", + .description = "enable adding additional master windows in a horizontal split style", + .type = CONFIG_OPTION_BOOL, + .data = SConfigOptionDescription::SBoolData{false}, + }, + SConfigOptionDescription{ + .value = "master:special_scale_factor", + .description = "the scale of the special workspace windows. [0.0 - 1.0]", + .type = CONFIG_OPTION_FLOAT, + .data = SConfigOptionDescription::SFloatData{1, 0, 1}, + }, + SConfigOptionDescription{ + .value = "master:mfact", + .description = + "the size as a percentage of the master window, for example `mfact = 0.70` would mean 70% of the screen will be the master window, and 30% the slave [0.0 - 1.0]", + .type = CONFIG_OPTION_FLOAT, + .data = SConfigOptionDescription::SFloatData{0.55, 0, 1}, + }, + SConfigOptionDescription{ + .value = "master:new_status", + .description = "`master`: new window becomes master; `slave`: new windows are added to slave stack; `inherit`: inherit from focused window", + .type = CONFIG_OPTION_STRING_SHORT, + .data = SConfigOptionDescription::SStringData{"slave"}, + }, + SConfigOptionDescription{ + .value = "master:new_on_top", + .description = "whether a newly open window should be on the top of the stack", + .type = CONFIG_OPTION_BOOL, + .data = SConfigOptionDescription::SBoolData{false}, + }, + SConfigOptionDescription{ + .value = "master:new_on_active", + .description = "`before`, `after`: place new window relative to the focused window; `none`: place new window according to the value of `new_on_top`. ", + .type = CONFIG_OPTION_STRING_SHORT, + .data = SConfigOptionDescription::SStringData{"none"}, + }, + SConfigOptionDescription{ + .value = "master:no_gaps_when_only", + .description = "whether to apply gaps when there is only one window on a workspace, aka. smart gaps. (default: disabled - 0) no border - 1, with border - 2 [0/1/2]", + .type = CONFIG_OPTION_CHOICE, + .data = SConfigOptionDescription::SChoiceData{0, "disabled,no border,with border"}, + }, + SConfigOptionDescription{ + .value = "master:orientation", + .description = "default placement of the master area, can be left, right, top, bottom or center", + .type = CONFIG_OPTION_STRING_SHORT, + .data = SConfigOptionDescription::SStringData{"left"}, + }, + SConfigOptionDescription{ + .value = "master:inherit_fullscreen", + .description = "inherit fullscreen status when cycling/swapping to another window (e.g. monocle layout)", + .type = CONFIG_OPTION_BOOL, + .data = SConfigOptionDescription::SBoolData{true}, + }, + SConfigOptionDescription{ + .value = "master:always_center_master", + .description = "when using orientation=center, keep the master window centered, even when it is the only window in the workspace.", + .type = CONFIG_OPTION_BOOL, + .data = SConfigOptionDescription::SBoolData{false}, + }, + SConfigOptionDescription{ + .value = "master:smart_resizing", + .description = + "if enabled, resizing direction will be determined by the mouse's position on the window (nearest to which corner). Else, it is based on the window's tiling position.", + .type = CONFIG_OPTION_BOOL, + .data = SConfigOptionDescription::SBoolData{true}, + }, + SConfigOptionDescription{ + .value = "master:drop_at_cursor", + .description = "when enabled, dragging and dropping windows will put them at the cursor position. Otherwise, when dropped at the stack side, they will go to the " + "top/bottom of the stack depending on new_on_top.", + .type = CONFIG_OPTION_BOOL, + .data = SConfigOptionDescription::SBoolData{true}, + }, }; From 4b00cba319dc44294567d06df7c378cf5e4e5338 Mon Sep 17 00:00:00 2001 From: Luke Chen <3363954+LukeXuan@users.noreply.github.com> Date: Sun, 29 Sep 2024 09:47:59 -0400 Subject: [PATCH 0459/2181] dwindle: add movetoroot method to layout messages (#7903) --- src/layout/DwindleLayout.cpp | 42 ++++++++++++++++++++++++++++++++++++ src/layout/DwindleLayout.hpp | 1 + 2 files changed, 43 insertions(+) diff --git a/src/layout/DwindleLayout.cpp b/src/layout/DwindleLayout.cpp index 69b044b4..ed47fa44 100644 --- a/src/layout/DwindleLayout.cpp +++ b/src/layout/DwindleLayout.cpp @@ -998,6 +998,10 @@ std::any CHyprDwindleLayout::layoutMessage(SLayoutMessageHeader header, std::str toggleSplit(header.pWindow); } else if (ARGS[0] == "swapsplit") { swapSplit(header.pWindow); + } else if (ARGS[0] == "movetoroot") { + const auto WINDOW = ARGS[1].empty() ? header.pWindow : g_pCompositor->getWindowByRegex(ARGS[1]); + const auto STABLE = ARGS[2].empty() || ARGS[2] != "unstable"; + moveToRoot(WINDOW, STABLE); } else if (ARGS[0] == "preselect") { std::string direction = ARGS[1]; @@ -1065,6 +1069,44 @@ void CHyprDwindleLayout::swapSplit(PHLWINDOW pWindow) { PNODE->pParent->recalcSizePosRecursive(); } +// goal: maximize the chosen window within current dwindle layout +// impl: swap the selected window with the other sub-tree below root +void CHyprDwindleLayout::moveToRoot(PHLWINDOW pWindow, bool stable) { + const auto PNODE = getNodeFromWindow(pWindow); + + if (!PNODE || !PNODE->pParent) + return; + + if (pWindow->isFullscreen()) + return; + + // already at root + if (!PNODE->pParent->pParent) + return; + + auto& pNode = PNODE->pParent->children[0] == PNODE ? PNODE->pParent->children[0] : PNODE->pParent->children[1]; + + // instead of [getMasterNodeOnWorkspace], we walk back to root since we need + // to know which children of root is our ancestor + auto pAncestor = PNODE, pRoot = PNODE->pParent; + while (pRoot->pParent) { + pAncestor = pRoot; + pRoot = pRoot->pParent; + } + + auto& pSwap = pRoot->children[0] == pAncestor ? pRoot->children[1] : pRoot->children[0]; + std::swap(pNode, pSwap); + std::swap(pNode->pParent, pSwap->pParent); + + // [stable] in that the focused window occupies same side of screen + if (stable) + std::swap(pRoot->children[0], pRoot->children[1]); + + // if the workspace is visible, recalculate layout + if (g_pCompositor->isWorkspaceVisible(pWindow->m_pWorkspace)) + pRoot->recalcSizePosRecursive(); +} + void CHyprDwindleLayout::replaceWindowDataWith(PHLWINDOW from, PHLWINDOW to) { const auto PNODE = getNodeFromWindow(from); diff --git a/src/layout/DwindleLayout.hpp b/src/layout/DwindleLayout.hpp index bbd511c2..953ba3a2 100644 --- a/src/layout/DwindleLayout.hpp +++ b/src/layout/DwindleLayout.hpp @@ -87,6 +87,7 @@ class CHyprDwindleLayout : public IHyprLayout { void toggleSplit(PHLWINDOW); void swapSplit(PHLWINDOW); + void moveToRoot(PHLWINDOW, bool stable = true); eDirection overrideDirection = DIRECTION_DEFAULT; From 6649255d54f45a7e2fedd9b4be85fe5d11229c04 Mon Sep 17 00:00:00 2001 From: Gliczy <129636582+Gliczy@users.noreply.github.com> Date: Sun, 29 Sep 2024 15:45:19 +0200 Subject: [PATCH 0460/2181] flake.lock: update --- flake.lock | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/flake.lock b/flake.lock index 5adaa350..2579dd11 100644 --- a/flake.lock +++ b/flake.lock @@ -42,11 +42,11 @@ ] }, "locked": { - "lastModified": 1722623071, - "narHash": "sha256-sLADpVgebpCBFXkA1FlCXtvEPu1tdEsTfqK1hfeHySE=", + "lastModified": 1727532803, + "narHash": "sha256-ZaZ7h7PY8mQc4vtGmVqWLAq9CAO02gHMyNR5yY8zDmM=", "owner": "hyprwm", "repo": "hyprcursor", - "rev": "912d56025f03d41b1ad29510c423757b4379eb1c", + "rev": "b98726e431d4d3ed58bd58bee1047cdb81cec69f", "type": "github" }, "original": { @@ -177,11 +177,11 @@ }, "nixpkgs": { "locked": { - "lastModified": 1727122398, - "narHash": "sha256-o8VBeCWHBxGd4kVMceIayf5GApqTavJbTa44Xcg5Rrk=", + "lastModified": 1727348695, + "narHash": "sha256-J+PeFKSDV+pHL7ukkfpVzCOO7mBSrrpJ3svwBFABbhI=", "owner": "NixOS", "repo": "nixpkgs", - "rev": "30439d93eb8b19861ccbe3e581abf97bdc91b093", + "rev": "1925c603f17fc89f4c8f6bf6f631a802ad85d784", "type": "github" }, "original": { @@ -239,11 +239,11 @@ ] }, "locked": { - "lastModified": 1727109343, - "narHash": "sha256-1PFckA8Im7wMSl26okwOKqBZeCFLD3LvZZFaxswDhbY=", + "lastModified": 1727524473, + "narHash": "sha256-1DGktDtSWIJpnDbVoj/qpvJSH5zg6JbOfuh6xqZMap0=", "owner": "hyprwm", "repo": "xdg-desktop-portal-hyprland", - "rev": "4adb6c4c41ee5014bfe608123bfeddb26e5f5cea", + "rev": "7e500e679ede40e79cf2d89b5f5fa3e34923bd26", "type": "github" }, "original": { From 488efab63654a643d76df4997cd932d6fddd8faf Mon Sep 17 00:00:00 2001 From: Vaxry Date: Mon, 30 Sep 2024 00:57:51 +0100 Subject: [PATCH 0461/2181] single-pixel-buffer: new protocol impl fixes #6624 --- CMakeLists.txt | 1 + src/helpers/Color.hpp | 3 +- src/managers/ProtocolManager.cpp | 2 + src/protocols/SinglePixel.cpp | 125 +++++++++++++++++++++++++++++++ src/protocols/SinglePixel.hpp | 79 +++++++++++++++++++ 5 files changed, 209 insertions(+), 1 deletion(-) create mode 100644 src/protocols/SinglePixel.cpp create mode 100644 src/protocols/SinglePixel.hpp diff --git a/CMakeLists.txt b/CMakeLists.txt index 8115d01c..ee9cd2e2 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -330,6 +330,7 @@ protocolnew("stable/linux-dmabuf" "linux-dmabuf-v1" false) protocolnew("staging/drm-lease" "drm-lease-v1" false) protocolnew("staging/linux-drm-syncobj" "linux-drm-syncobj-v1" false) protocolnew("staging/xdg-dialog" "xdg-dialog-v1" false) +protocolnew("staging/single-pixel-buffer" "single-pixel-buffer-v1" false) protocolwayland() diff --git a/src/helpers/Color.hpp b/src/helpers/Color.hpp index 8abfe748..32ed39ee 100644 --- a/src/helpers/Color.hpp +++ b/src/helpers/Color.hpp @@ -8,8 +8,9 @@ class CColor { CColor(float r, float g, float b, float a); CColor(uint64_t); - float r = 0, g = 0, b = 0, a = 1.f; + float r = 0, g = 0, b = 0, a = 1.f; + // AR32 uint32_t getAsHex() const; CColor operator-(const CColor& c2) const { diff --git a/src/managers/ProtocolManager.cpp b/src/managers/ProtocolManager.cpp index 6b6d5acf..8bcc857a 100644 --- a/src/managers/ProtocolManager.cpp +++ b/src/managers/ProtocolManager.cpp @@ -44,6 +44,7 @@ #include "../protocols/TextInputV1.hpp" #include "../protocols/GlobalShortcuts.hpp" #include "../protocols/XDGDialog.hpp" +#include "../protocols/SinglePixel.hpp" #include "../protocols/core/Seat.hpp" #include "../protocols/core/DataDevice.hpp" @@ -152,6 +153,7 @@ CProtocolManager::CProtocolManager() { PROTO::toplevelExport = std::make_unique(&hyprland_toplevel_export_manager_v1_interface, 2, "ToplevelExport"); PROTO::globalShortcuts = std::make_unique(&hyprland_global_shortcuts_manager_v1_interface, 1, "GlobalShortcuts"); PROTO::xdgDialog = std::make_unique(&xdg_dialog_v1_interface, 1, "XDGDialog"); + PROTO::singlePixel = std::make_unique(&wp_single_pixel_buffer_manager_v1_interface, 1, "SinglePixel"); for (auto const& b : g_pCompositor->m_pAqBackend->getImplementations()) { if (b->type() != Aquamarine::AQ_BACKEND_DRM) diff --git a/src/protocols/SinglePixel.cpp b/src/protocols/SinglePixel.cpp new file mode 100644 index 00000000..7dd3748f --- /dev/null +++ b/src/protocols/SinglePixel.cpp @@ -0,0 +1,125 @@ +#include "SinglePixel.hpp" +#include + +CSinglePixelBuffer::CSinglePixelBuffer(uint32_t id, wl_client* client, CColor col_) { + LOGM(LOG, "New single-pixel buffer with color 0x{:x}", col_.getAsHex()); + + color = col_.getAsHex(); + + g_pHyprRenderer->makeEGLCurrent(); + + opaque = col_.a >= 1.F; + + texture = makeShared(DRM_FORMAT_ARGB8888, (uint8_t*)&color, 4, Vector2D{1, 1}); + + resource = CWLBufferResource::create(makeShared(client, 1, id)); + + success = texture->m_iTexID; + + if (!success) + Debug::log(ERR, "Failed creating a single pixel texture: null texture id"); +} + +CSinglePixelBuffer::~CSinglePixelBuffer() { + ; +} + +Aquamarine::eBufferCapability CSinglePixelBuffer::caps() { + return Aquamarine::eBufferCapability::BUFFER_CAPABILITY_DATAPTR; +} + +Aquamarine::eBufferType CSinglePixelBuffer::type() { + return Aquamarine::eBufferType::BUFFER_TYPE_SHM; +} + +bool CSinglePixelBuffer::isSynchronous() { + return true; +} + +void CSinglePixelBuffer::update(const CRegion& damage) { + ; +} + +Aquamarine::SDMABUFAttrs CSinglePixelBuffer::dmabuf() { + return {.success = false}; +} + +std::tuple CSinglePixelBuffer::beginDataPtr(uint32_t flags) { + return {(uint8_t*)&color, DRM_FORMAT_ARGB8888, 4}; +} + +void CSinglePixelBuffer::endDataPtr() { + ; +} + +bool CSinglePixelBuffer::good() { + return resource->good(); +} + +CSinglePixelBufferResource::CSinglePixelBufferResource(uint32_t id, wl_client* client, CColor color) { + buffer = makeShared(id, client, color); + + if (!buffer->good()) + return; + + buffer->resource->buffer = buffer; + + listeners.bufferResourceDestroy = buffer->events.destroy.registerListener([this](std::any d) { + listeners.bufferResourceDestroy.reset(); + PROTO::singlePixel->destroyResource(this); + }); +} + +CSinglePixelBufferResource::~CSinglePixelBufferResource() { + ; +} + +bool CSinglePixelBufferResource::good() { + return buffer->good(); +} + +CSinglePixelBufferManagerResource::CSinglePixelBufferManagerResource(SP resource_) : resource(resource_) { + if (!good()) + return; + + resource->setDestroy([this](CWpSinglePixelBufferManagerV1* r) { PROTO::singlePixel->destroyResource(this); }); + resource->setOnDestroy([this](CWpSinglePixelBufferManagerV1* r) { PROTO::singlePixel->destroyResource(this); }); + + resource->setCreateU32RgbaBuffer([this](CWpSinglePixelBufferManagerV1* res, uint32_t id, uint32_t r, uint32_t g, uint32_t b, uint32_t a) { + CColor color{r / (float)std::numeric_limits::max(), g / (float)std::numeric_limits::max(), b / (float)std::numeric_limits::max(), + a / (float)std::numeric_limits::max()}; + const auto RESOURCE = PROTO::singlePixel->m_vBuffers.emplace_back(makeShared(id, resource->client(), color)); + + if (!RESOURCE->good()) { + res->noMemory(); + PROTO::singlePixel->m_vBuffers.pop_back(); + return; + } + }); +} + +bool CSinglePixelBufferManagerResource::good() { + return resource->resource(); +} + +CSinglePixelProtocol::CSinglePixelProtocol(const wl_interface* iface, const int& ver, const std::string& name) : IWaylandProtocol(iface, ver, name) { + ; +} + +void CSinglePixelProtocol::bindManager(wl_client* client, void* data, uint32_t ver, uint32_t id) { + const auto RESOURCE = m_vManagers.emplace_back(makeShared(makeShared(client, ver, id))); + + if (!RESOURCE->good()) { + wl_client_post_no_memory(client); + m_vManagers.pop_back(); + return; + } +} + +void CSinglePixelProtocol::destroyResource(CSinglePixelBufferManagerResource* res) { + std::erase_if(m_vManagers, [&](const auto& other) { return other.get() == res; }); +} + +void CSinglePixelProtocol::destroyResource(CSinglePixelBufferResource* surf) { + std::erase_if(m_vBuffers, [&](const auto& other) { return other.get() == surf; }); +} diff --git a/src/protocols/SinglePixel.hpp b/src/protocols/SinglePixel.hpp new file mode 100644 index 00000000..ab74825c --- /dev/null +++ b/src/protocols/SinglePixel.hpp @@ -0,0 +1,79 @@ +#pragma once + +#include +#include +#include +#include "WaylandProtocol.hpp" +#include "single-pixel-buffer-v1.hpp" +#include "types/Buffer.hpp" + +class CSinglePixelBuffer : public IHLBuffer { + public: + CSinglePixelBuffer(uint32_t id, wl_client* client, CColor col); + virtual ~CSinglePixelBuffer(); + + virtual Aquamarine::eBufferCapability caps(); + virtual Aquamarine::eBufferType type(); + virtual bool isSynchronous(); + virtual void update(const CRegion& damage); + virtual Aquamarine::SDMABUFAttrs dmabuf(); + virtual std::tuple beginDataPtr(uint32_t flags); + virtual void endDataPtr(); + // + bool good(); + bool success = false; + + private: + uint32_t color = 0x00000000; + + struct { + CHyprSignalListener resourceDestroy; + } listeners; +}; + +class CSinglePixelBufferResource { + public: + CSinglePixelBufferResource(uint32_t id, wl_client* client, CColor color); + ~CSinglePixelBufferResource(); + + bool good(); + + private: + SP buffer; + + struct { + CHyprSignalListener bufferResourceDestroy; + } listeners; +}; + +class CSinglePixelBufferManagerResource { + public: + CSinglePixelBufferManagerResource(SP resource_); + + bool good(); + + private: + SP resource; +}; + +class CSinglePixelProtocol : public IWaylandProtocol { + public: + CSinglePixelProtocol(const wl_interface* iface, const int& ver, const std::string& name); + + virtual void bindManager(wl_client* client, void* data, uint32_t ver, uint32_t id); + + private: + void destroyResource(CSinglePixelBufferManagerResource* resource); + void destroyResource(CSinglePixelBufferResource* resource); + + // + std::vector> m_vManagers; + std::vector> m_vBuffers; + + friend class CSinglePixelBufferManagerResource; + friend class CSinglePixelBufferResource; +}; + +namespace PROTO { + inline UP singlePixel; +}; \ No newline at end of file From 968f6a6013409a6e6eab1545b28cd5e0cc49ce87 Mon Sep 17 00:00:00 2001 From: Trianta <56975502+Trimutex@users.noreply.github.com> Date: Sun, 29 Sep 2024 23:52:58 -0500 Subject: [PATCH 0462/2181] meson: fix arch build with new protocol --- protocols/meson.build | 1 + 1 file changed, 1 insertion(+) diff --git a/protocols/meson.build b/protocols/meson.build index d686bacd..6990b5a7 100644 --- a/protocols/meson.build +++ b/protocols/meson.build @@ -63,6 +63,7 @@ protocols = [ wayland_protocol_dir / 'staging/drm-lease/drm-lease-v1.xml', wayland_protocol_dir / 'staging/linux-drm-syncobj/linux-drm-syncobj-v1.xml', wayland_protocol_dir / 'staging/xdg-dialog/xdg-dialog-v1.xml', + wayland_protocol_dir / 'staging/single-pixel-buffer/single-pixel-buffer-v1.xml', ] wl_protocols = [] From f6387536f62454f82039b42f641cd8c44153ad47 Mon Sep 17 00:00:00 2001 From: Trianta <56975502+Trimutex@users.noreply.github.com> Date: Mon, 30 Sep 2024 00:15:25 -0500 Subject: [PATCH 0463/2181] protocol: fix missing include --- src/protocols/SinglePixel.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/src/protocols/SinglePixel.cpp b/src/protocols/SinglePixel.cpp index 7dd3748f..0595cce5 100644 --- a/src/protocols/SinglePixel.cpp +++ b/src/protocols/SinglePixel.cpp @@ -1,5 +1,6 @@ #include "SinglePixel.hpp" #include +#include "render/Renderer.hpp" CSinglePixelBuffer::CSinglePixelBuffer(uint32_t id, wl_client* client, CColor col_) { LOGM(LOG, "New single-pixel buffer with color 0x{:x}", col_.getAsHex()); From 3ddb16bd5bb7146d125a7d68e4e9f3b54c381a20 Mon Sep 17 00:00:00 2001 From: Vaxry Date: Mon, 30 Sep 2024 17:25:39 +0100 Subject: [PATCH 0464/2181] compositor/wayland: up the max buffer size to avoid disconnects when app hangs --- CMakeLists.txt | 2 +- src/Compositor.cpp | 4 +++ src/helpers/ByteOperations.hpp | 52 ++++++++++++++++++++++++++++++++++ 3 files changed, 57 insertions(+), 1 deletion(-) create mode 100644 src/helpers/ByteOperations.hpp diff --git a/CMakeLists.txt b/CMakeLists.txt index ee9cd2e2..3440af4a 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -110,7 +110,7 @@ pkg_check_modules( IMPORTED_TARGET xkbcommon uuid - wayland-server + wayland-server>=1.22.90 wayland-protocols cairo pango diff --git a/src/Compositor.cpp b/src/Compositor.cpp index 232ba4a6..25d73db0 100644 --- a/src/Compositor.cpp +++ b/src/Compositor.cpp @@ -28,6 +28,7 @@ #include "desktop/LayerSurface.hpp" #include "render/Renderer.hpp" #include "xwayland/XWayland.hpp" +#include "helpers/ByteOperations.hpp" #include #include @@ -229,6 +230,9 @@ void CCompositor::initServer(std::string socketName, int socketFd) { if (envEnabled("HYPRLAND_TRACE")) Debug::trace = true; + // set the buffer size to 1MB to avoid disconnects due to an app hanging for a short while + wl_display_set_default_max_buffer_size(m_sWLDisplay, 1_MB); + Aquamarine::SBackendOptions options; options.logFunction = aqLog; diff --git a/src/helpers/ByteOperations.hpp b/src/helpers/ByteOperations.hpp new file mode 100644 index 00000000..6d9507ff --- /dev/null +++ b/src/helpers/ByteOperations.hpp @@ -0,0 +1,52 @@ +#pragma once + +#define ULL unsigned long long +#define LD long double + +constexpr ULL operator""_kB(const ULL BYTES) { + return BYTES * 1024; +} +constexpr ULL operator""_MB(const ULL BYTES) { + return BYTES * 1024 * 1024; +} +constexpr ULL operator""_GB(const ULL BYTES) { + return BYTES * 1024 * 1024 * 1024; +} +constexpr ULL operator""_TB(const ULL BYTES) { + return BYTES * 1024 * 1024 * 1024 * 1024; +} +constexpr LD operator""_kB(const LD BYTES) { + return BYTES * 1024; +} +constexpr LD operator""_MB(const LD BYTES) { + return BYTES * 1024 * 1024; +} +constexpr LD operator""_GB(const LD BYTES) { + return BYTES * 1024 * 1024 * 1024; +} +constexpr LD operator""_TB(const LD BYTES) { + return BYTES * 1024 * 1024 * 1024 * 1024; +} + +template +using __acceptable_byte_operation_type = typename std::enable_if::value || std::is_trivially_constructible::value>::type; + +template > +constexpr X kBtoBytes(const X kB) { + return kB * 1024; +} +template > +constexpr X MBtoBytes(const X MB) { + return MB * 1024 * 1024; +} +template > +constexpr X GBtoBytes(const X GB) { + return GB * 1024 * 1024 * 1024; +} +template > +constexpr X TBtoBytes(const X TB) { + return TB * 1024 * 1024 * 1024 * 1024; +} + +#undef ULL +#undef LD \ No newline at end of file From 68fd32c81013541f237e2046779185b41db1538e Mon Sep 17 00:00:00 2001 From: Vaxry Date: Mon, 30 Sep 2024 17:27:10 +0100 Subject: [PATCH 0465/2181] byteoperations: add missing header --- src/helpers/ByteOperations.hpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/helpers/ByteOperations.hpp b/src/helpers/ByteOperations.hpp index 6d9507ff..13e98500 100644 --- a/src/helpers/ByteOperations.hpp +++ b/src/helpers/ByteOperations.hpp @@ -1,5 +1,7 @@ #pragma once +#include + #define ULL unsigned long long #define LD long double From 6bd339714160505ab1c4aade659eca6fe426fea5 Mon Sep 17 00:00:00 2001 From: Vaxry Date: Mon, 30 Sep 2024 17:40:38 +0100 Subject: [PATCH 0466/2181] wlr-output-management: accept 0 refresh rates fixes #7879 --- src/protocols/OutputManagement.cpp | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/src/protocols/OutputManagement.cpp b/src/protocols/OutputManagement.cpp index dcc7a62d..3fd0cf6c 100644 --- a/src/protocols/OutputManagement.cpp +++ b/src/protocols/OutputManagement.cpp @@ -467,11 +467,16 @@ COutputConfigurationHead::COutputConfigurationHead(SPerror(ZWLR_OUTPUT_CONFIGURATION_HEAD_V1_ERROR_INVALID_CUSTOM_MODE, "Invalid mode"); return; } + if (refresh == 0) { + LOGM(LOG, " | configHead for {}: refreshRate 0, using old refresh rate of {:.2f}Hz", pMonitor->szName, pMonitor->refreshRate); + refresh = std::round(pMonitor->refreshRate * 1000.F); + } + state.committedProperties |= OUTPUT_HEAD_COMMITTED_CUSTOM_MODE; state.customMode = {{w, h}, (uint32_t)refresh}; From 5c6c300abfea2539ffad9bcbf857325eec5ab765 Mon Sep 17 00:00:00 2001 From: Vaxry Date: Mon, 30 Sep 2024 17:42:36 +0100 Subject: [PATCH 0467/2181] wayland/output: send geometry in updateState --- src/protocols/core/Output.cpp | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/protocols/core/Output.cpp b/src/protocols/core/Output.cpp index 394dc8e2..7b88e0a8 100644 --- a/src/protocols/core/Output.cpp +++ b/src/protocols/core/Output.cpp @@ -21,8 +21,6 @@ CWLOutputResource::CWLOutputResource(SP resource_, SP pMoni PROTO::outputs.at(monitor->szName)->destroyResource(this); }); - resource->sendGeometry(0, 0, monitor->output->physicalSize.x, monitor->output->physicalSize.y, (wl_output_subpixel)monitor->output->subpixel, monitor->output->make.c_str(), - monitor->output->model.c_str(), monitor->transform); if (resource->version() >= 4) { resource->sendName(monitor->szName.c_str()); resource->sendDescription(monitor->szDescription.c_str()); @@ -57,6 +55,9 @@ void CWLOutputResource::updateState() { resource->sendMode((wl_output_mode)(WL_OUTPUT_MODE_CURRENT), monitor->vecPixelSize.x, monitor->vecPixelSize.y, monitor->refreshRate * 1000.0); + resource->sendGeometry(0, 0, monitor->output->physicalSize.x, monitor->output->physicalSize.y, (wl_output_subpixel)monitor->output->subpixel, monitor->output->make.c_str(), + monitor->output->model.c_str(), monitor->transform); + if (resource->version() >= 2) resource->sendDone(); } From e2426942e5716a742ea353d2a1de7d7760fbbb41 Mon Sep 17 00:00:00 2001 From: Aqa-Ib Date: Wed, 2 Oct 2024 11:22:19 +0200 Subject: [PATCH 0468/2181] layout: add auto_group to control default grouping (#7883) --- src/config/ConfigDescriptions.hpp | 6 +++ src/config/ConfigManager.cpp | 1 + src/events/Windows.cpp | 2 +- src/layout/DwindleLayout.cpp | 21 +-------- src/layout/IHyprLayout.cpp | 73 ++++++++++++++++++++++++------- src/layout/IHyprLayout.hpp | 1 + src/layout/MasterLayout.cpp | 20 --------- 7 files changed, 68 insertions(+), 56 deletions(-) diff --git a/src/config/ConfigDescriptions.hpp b/src/config/ConfigDescriptions.hpp index 3a91a808..385d4e59 100644 --- a/src/config/ConfigDescriptions.hpp +++ b/src/config/ConfigDescriptions.hpp @@ -772,6 +772,12 @@ inline static const std::vector CONFIG_OPTIONS = { .type = CONFIG_OPTION_GRADIENT, .data = SConfigOptionDescription::SGradientData{"0x66775500"}, }, + SConfigOptionDescription{ + .value = "group:auto_group", + .description = "automatically group new windows", + .type = CONFIG_OPTION_BOOL, + .data = SConfigOptionDescription::SBoolData{true}, + }, /* * group:groupbar: diff --git a/src/config/ConfigManager.cpp b/src/config/ConfigManager.cpp index ad6e1871..2ce07ff0 100644 --- a/src/config/ConfigManager.cpp +++ b/src/config/ConfigManager.cpp @@ -377,6 +377,7 @@ CConfigManager::CConfigManager() { m_pConfig->addConfigValue("group:insert_after_current", Hyprlang::INT{1}); m_pConfig->addConfigValue("group:focus_removed_window", Hyprlang::INT{1}); m_pConfig->addConfigValue("group:merge_groups_on_drag", Hyprlang::INT{1}); + m_pConfig->addConfigValue("group:auto_group", Hyprlang::INT{1}); m_pConfig->addConfigValue("group:groupbar:enabled", Hyprlang::INT{1}); m_pConfig->addConfigValue("group:groupbar:font_family", {STRVAL_EMPTY}); m_pConfig->addConfigValue("group:groupbar:font_size", Hyprlang::INT{8}); diff --git a/src/events/Windows.cpp b/src/events/Windows.cpp index 544483b1..1c2c7cfa 100644 --- a/src/events/Windows.cpp +++ b/src/events/Windows.cpp @@ -322,7 +322,7 @@ void Events::listener_mapWindow(void* owner, void* data) { PWINDOW->updateWindowData(); if (PWINDOW->m_bIsFloating) { - g_pLayoutManager->getCurrentLayout()->onWindowCreatedFloating(PWINDOW); + g_pLayoutManager->getCurrentLayout()->onWindowCreated(PWINDOW); PWINDOW->m_bCreatedOverFullscreen = true; // size and move rules diff --git a/src/layout/DwindleLayout.cpp b/src/layout/DwindleLayout.cpp index ed47fa44..04cbf21d 100644 --- a/src/layout/DwindleLayout.cpp +++ b/src/layout/DwindleLayout.cpp @@ -340,26 +340,7 @@ void CHyprDwindleLayout::onWindowCreatedTiling(PHLWINDOW pWindow, eDirection dir return; } - // if it's a group, add the window - if (OPENINGON->pWindow->m_sGroupData.pNextWindow.lock() // target is group - && pWindow->canBeGroupedInto(OPENINGON->pWindow.lock()) && !m_vOverrideFocalPoint) { // we are not moving window - m_lDwindleNodesData.remove(*PNODE); - - static auto USECURRPOS = CConfigValue("group:insert_after_current"); - (*USECURRPOS ? OPENINGON->pWindow.lock() : OPENINGON->pWindow->getGroupTail())->insertWindowToGroup(pWindow); - - OPENINGON->pWindow->setGroupCurrent(pWindow); - pWindow->applyGroupRules(); - pWindow->updateWindowDecos(); - recalculateWindow(pWindow); - - if (!pWindow->getDecorationByType(DECORATION_GROUPBAR)) - pWindow->addWindowDeco(std::make_unique(pWindow)); - - return; - } - - // If it's not, get the node under our cursor + // get the node under our cursor m_lDwindleNodesData.push_back(SDwindleNodeData()); const auto NEWPARENT = &m_lDwindleNodesData.back(); diff --git a/src/layout/IHyprLayout.cpp b/src/layout/IHyprLayout.cpp index c5a5373c..0fb78d02 100644 --- a/src/layout/IHyprLayout.cpp +++ b/src/layout/IHyprLayout.cpp @@ -9,23 +9,25 @@ #include "../xwayland/XSurface.hpp" void IHyprLayout::onWindowCreated(PHLWINDOW pWindow, eDirection direction) { - if (pWindow->m_bIsFloating) { + CBox desiredGeometry = {}; + g_pXWaylandManager->getGeometryForWindow(pWindow, &desiredGeometry); + + if (desiredGeometry.width <= 5 || desiredGeometry.height <= 5) { + const auto PMONITOR = g_pCompositor->getMonitorFromID(pWindow->m_iMonitorID); + pWindow->m_vLastFloatingSize = PMONITOR->vecSize / 2.f; + } else + pWindow->m_vLastFloatingSize = Vector2D(desiredGeometry.width, desiredGeometry.height); + + pWindow->m_vPseudoSize = pWindow->m_vLastFloatingSize; + + bool autoGrouped = IHyprLayout::onWindowCreatedAutoGroup(pWindow); + if (autoGrouped) + return; + + if (pWindow->m_bIsFloating) onWindowCreatedFloating(pWindow); - } else { - CBox desiredGeometry = {}; - g_pXWaylandManager->getGeometryForWindow(pWindow, &desiredGeometry); - - if (desiredGeometry.width <= 5 || desiredGeometry.height <= 5) { - const auto PMONITOR = g_pCompositor->getMonitorFromID(pWindow->m_iMonitorID); - pWindow->m_vLastFloatingSize = PMONITOR->vecSize / 2.f; - } else { - pWindow->m_vLastFloatingSize = Vector2D(desiredGeometry.width, desiredGeometry.height); - } - - pWindow->m_vPseudoSize = pWindow->m_vLastFloatingSize; - + else onWindowCreatedTiling(pWindow, direction); - } } void IHyprLayout::onWindowRemoved(PHLWINDOW pWindow) { @@ -178,6 +180,47 @@ void IHyprLayout::onWindowCreatedFloating(PHLWINDOW pWindow) { } } +bool IHyprLayout::onWindowCreatedAutoGroup(PHLWINDOW pWindow) { + static auto AUTOGROUP = CConfigValue("group:auto_group"); + if ((*AUTOGROUP || g_pInputManager->m_bWasDraggingWindow) // check if auto_group is enabled, or, if the user is manually dragging the window into the group. + && g_pCompositor->m_pLastWindow.lock() // check if a focused window exists. + && g_pCompositor->m_pLastWindow != pWindow // fixes a freeze when activating togglefloat to transform a floating group into a tiled group. + && g_pCompositor->m_pLastWindow->m_pWorkspace == + pWindow + ->m_pWorkspace // fix for multimonitor: when there is a focused group in monitor 1 and monitor 2 is empty, this enables adding the first window of monitor 2 when using the mouse to focus it. + && g_pCompositor->m_pLastWindow->m_sGroupData.pNextWindow.lock() // check if the focused window is a group + && pWindow->canBeGroupedInto(g_pCompositor->m_pLastWindow.lock()) // check if the new window can be grouped into the focused group + && !g_pXWaylandManager->shouldBeFloated(pWindow)) { // don't group XWayland windows that should be floated. + + switch (pWindow->m_bIsFloating) { + case false: + if (g_pCompositor->m_pLastWindow->m_bIsFloating) + pWindow->m_bIsFloating = true; + break; + + case true: + if (!g_pCompositor->m_pLastWindow->m_bIsFloating) + pWindow->m_bIsFloating = false; + break; + } + + static auto USECURRPOS = CConfigValue("group:insert_after_current"); + (*USECURRPOS ? g_pCompositor->m_pLastWindow : g_pCompositor->m_pLastWindow->getGroupTail())->insertWindowToGroup(pWindow); + + g_pCompositor->m_pLastWindow->setGroupCurrent(pWindow); + pWindow->applyGroupRules(); + pWindow->updateWindowDecos(); + recalculateWindow(pWindow); + + if (!pWindow->getDecorationByType(DECORATION_GROUPBAR)) + pWindow->addWindowDeco(std::make_unique(pWindow)); + + return true; + } + + return false; +} + void IHyprLayout::onBeginDragWindow() { const auto DRAGGINGWINDOW = g_pInputManager->currentlyDraggedWindow.lock(); diff --git a/src/layout/IHyprLayout.hpp b/src/layout/IHyprLayout.hpp index 7e0d5704..f9e2de0d 100644 --- a/src/layout/IHyprLayout.hpp +++ b/src/layout/IHyprLayout.hpp @@ -47,6 +47,7 @@ class IHyprLayout { virtual void onWindowCreated(PHLWINDOW, eDirection direction = DIRECTION_DEFAULT); virtual void onWindowCreatedTiling(PHLWINDOW, eDirection direction = DIRECTION_DEFAULT) = 0; virtual void onWindowCreatedFloating(PHLWINDOW); + virtual bool onWindowCreatedAutoGroup(PHLWINDOW); /* Return tiled status diff --git a/src/layout/MasterLayout.cpp b/src/layout/MasterLayout.cpp index 8fa324b0..04a6ea29 100644 --- a/src/layout/MasterLayout.cpp +++ b/src/layout/MasterLayout.cpp @@ -116,26 +116,6 @@ void CHyprMasterLayout::onWindowCreatedTiling(PHLWINDOW pWindow, eDirection dire return; } - // if it's a group, add the window - if (OPENINGON && OPENINGON != PNODE && OPENINGON->pWindow->m_sGroupData.pNextWindow.lock() // target is group - && pWindow->canBeGroupedInto(OPENINGON->pWindow.lock())) { - - m_lMasterNodesData.remove(*PNODE); - - static auto USECURRPOS = CConfigValue("group:insert_after_current"); - (*USECURRPOS ? OPENINGON->pWindow.lock() : OPENINGON->pWindow->getGroupTail())->insertWindowToGroup(pWindow); - - OPENINGON->pWindow->setGroupCurrent(pWindow); - pWindow->applyGroupRules(); - pWindow->updateWindowDecos(); - recalculateWindow(pWindow); - - if (!pWindow->getDecorationByType(DECORATION_GROUPBAR)) - pWindow->addWindowDeco(std::make_unique(pWindow)); - - return; - } - pWindow->applyGroupRules(); static auto PDROPATCURSOR = CConfigValue("master:drop_at_cursor"); From de68e065fe861d7ca01eca267df4c305bc6e73c2 Mon Sep 17 00:00:00 2001 From: Aqa-Ib Date: Wed, 2 Oct 2024 22:25:25 +0200 Subject: [PATCH 0469/2181] layout: fix dragging a window into a group after e242694 (#7976) --- src/layout/IHyprLayout.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/layout/IHyprLayout.cpp b/src/layout/IHyprLayout.cpp index 0fb78d02..4b5c9d4f 100644 --- a/src/layout/IHyprLayout.cpp +++ b/src/layout/IHyprLayout.cpp @@ -552,10 +552,10 @@ void IHyprLayout::changeWindowFloatingMode(PHLWINDOW pWindow) { pWindow->m_vLastFloatingSize = PSAVEDSIZE; - // move to narnia because we don't wanna find our own node. onWindowCreatedTiling should apply the coords back. + // move to narnia because we don't wanna find our own node. onWindowCreated should apply the coords back. pWindow->m_vPosition = Vector2D(-999999, -999999); - onWindowCreatedTiling(pWindow); + onWindowCreated(pWindow); pWindow->m_vRealPosition.setValue(PSAVEDPOS); pWindow->m_vRealSize.setValue(PSAVEDSIZE); From aed529f695bc62f5fa45dc94c545275ebb49bc48 Mon Sep 17 00:00:00 2001 From: Maximilian Seidler <78690852+PaideiaDilemma@users.noreply.github.com> Date: Thu, 3 Oct 2024 22:00:44 +0000 Subject: [PATCH 0470/2181] renderer: fix uvBR calculation (#7975) --- src/render/Renderer.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/render/Renderer.cpp b/src/render/Renderer.cpp index 417a3ff8..b081fd81 100644 --- a/src/render/Renderer.cpp +++ b/src/render/Renderer.cpp @@ -1134,7 +1134,7 @@ void CHyprRenderer::calculateUVForSurface(PHLWINDOW pWindow, SPcurrent.size.y; const auto TOADDTL = Vector2D(XPERC * (uvBR.x - uvTL.x), YPERC * (uvBR.y - uvTL.y)); - uvBR = uvBR - Vector2D(1.0 - WPERC * (uvBR.x - uvTL.x), 1.0 - HPERC * (uvBR.y - uvTL.y)); + uvBR = uvBR - Vector2D((1.0 - WPERC) * (uvBR.x - uvTL.x), (1.0 - HPERC) * (uvBR.y - uvTL.y)); uvTL = uvTL + TOADDTL; // TODO: make this passed to the func. Might break in the future. From 1ed925b69c2854a3f345cbeb7dca29a6286ca926 Mon Sep 17 00:00:00 2001 From: Theo Paris Date: Fri, 4 Oct 2024 01:41:27 -0700 Subject: [PATCH 0471/2181] internal: fix missing include directive (#7984) This should fix building with clang. --- src/helpers/SdDaemon.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/src/helpers/SdDaemon.cpp b/src/helpers/SdDaemon.cpp index 48c23e6b..80944794 100644 --- a/src/helpers/SdDaemon.cpp +++ b/src/helpers/SdDaemon.cpp @@ -8,6 +8,7 @@ #include #include #include +#include #include namespace Systemd { From 8e237b006fa7dd348a58c85f1aa46a8a835533c2 Mon Sep 17 00:00:00 2001 From: Vaxry Date: Sat, 5 Oct 2024 00:43:59 +0100 Subject: [PATCH 0472/2181] xdg-output: minor cleanups --- src/protocols/XDGOutput.cpp | 32 ++++++++++++++------------------ src/protocols/XDGOutput.hpp | 6 +++--- 2 files changed, 17 insertions(+), 21 deletions(-) diff --git a/src/protocols/XDGOutput.cpp b/src/protocols/XDGOutput.cpp index 5d620667..0cdadd43 100644 --- a/src/protocols/XDGOutput.cpp +++ b/src/protocols/XDGOutput.cpp @@ -29,29 +29,20 @@ void CXDGOutputProtocol::bindManager(wl_client* client, void* data, uint32_t ver return; } - RESOURCE->setDestroy([this](CZxdgOutputManagerV1* res) { this->onManagerResourceDestroy(res->resource()); }); - RESOURCE->setOnDestroy([this](CZxdgOutputManagerV1* res) { this->onManagerResourceDestroy(res->resource()); }); - RESOURCE->setGetXdgOutput([this](CZxdgOutputManagerV1* mgr, uint32_t id, wl_resource* output) { this->onManagerGetXDGOutput(mgr, id, output); }); + RESOURCE->setDestroy([this](CZxdgOutputManagerV1* res) { onManagerResourceDestroy(res->resource()); }); + RESOURCE->setOnDestroy([this](CZxdgOutputManagerV1* res) { onManagerResourceDestroy(res->resource()); }); + RESOURCE->setGetXdgOutput([this](CZxdgOutputManagerV1* mgr, uint32_t id, wl_resource* output) { onManagerGetXDGOutput(mgr, id, output); }); } CXDGOutputProtocol::CXDGOutputProtocol(const wl_interface* iface, const int& ver, const std::string& name) : IWaylandProtocol(iface, ver, name) { static auto P = g_pHookSystem->hookDynamic("monitorLayoutChanged", [this](void* self, SCallbackInfo& info, std::any param) { this->updateAllOutputs(); }); static auto P2 = g_pHookSystem->hookDynamic("configReloaded", [this](void* self, SCallbackInfo& info, std::any param) { this->updateAllOutputs(); }); - static auto P3 = g_pHookSystem->hookDynamic("monitorRemoved", [this](void* self, SCallbackInfo& info, std::any param) { - const auto PMONITOR = std::any_cast(param); - for (auto const& o : m_vXDGOutputs) { - if (o->monitor == PMONITOR) - o->monitor = nullptr; - } - }); } void CXDGOutputProtocol::onManagerGetXDGOutput(CZxdgOutputManagerV1* mgr, uint32_t id, wl_resource* outputResource) { - const auto OUTPUT = CWLOutputResource::fromResource(outputResource); - - const auto PMONITOR = OUTPUT->monitor.get(); - - const auto CLIENT = mgr->client(); + const auto OUTPUT = CWLOutputResource::fromResource(outputResource); + const auto PMONITOR = OUTPUT->monitor.lock(); + const auto CLIENT = mgr->client(); CXDGOutput* pXDGOutput = m_vXDGOutputs.emplace_back(std::make_unique(makeShared(CLIENT, mgr->version(), id), PMONITOR)).get(); #ifndef NO_XWAYLAND @@ -66,8 +57,12 @@ void CXDGOutputProtocol::onManagerGetXDGOutput(CZxdgOutputManagerV1* mgr, uint32 return; } - if (!PMONITOR) + if (!PMONITOR) { + LOGM(ERR, "New xdg_output from client {:x} ({}) has no CMonitor?!", (uintptr_t)CLIENT, pXDGOutput->isXWayland ? "xwayland" : "not xwayland"); return; + } + + LOGM(LOG, "New xdg_output for {}: client {:x} ({})", PMONITOR->szName, (uintptr_t)CLIENT, pXDGOutput->isXWayland ? "xwayland" : "not xwayland"); const auto XDGVER = pXDGOutput->resource->version(); @@ -84,8 +79,9 @@ void CXDGOutputProtocol::onManagerGetXDGOutput(CZxdgOutputManagerV1* mgr, uint32 } void CXDGOutputProtocol::updateAllOutputs() { - for (auto const& o : m_vXDGOutputs) { + LOGM(LOG, "updating all xdg_output heads"); + for (auto const& o : m_vXDGOutputs) { if (!o->monitor) continue; @@ -97,7 +93,7 @@ void CXDGOutputProtocol::updateAllOutputs() { // -CXDGOutput::CXDGOutput(SP resource_, CMonitor* monitor_) : monitor(monitor_), resource(resource_) { +CXDGOutput::CXDGOutput(SP resource_, SP monitor_) : monitor(monitor_), resource(resource_) { if (!resource->resource()) return; diff --git a/src/protocols/XDGOutput.hpp b/src/protocols/XDGOutput.hpp index 73e7d53e..15d86cc7 100644 --- a/src/protocols/XDGOutput.hpp +++ b/src/protocols/XDGOutput.hpp @@ -9,12 +9,12 @@ class CXDGOutputProtocol; class CXDGOutput { public: - CXDGOutput(SP resource, CMonitor* monitor_); + CXDGOutput(SP resource, SP monitor_); void sendDetails(); private: - CMonitor* monitor = nullptr; + WP monitor; SP resource; std::optional overridePosition; @@ -30,12 +30,12 @@ class CXDGOutputProtocol : public IWaylandProtocol { CXDGOutputProtocol(const wl_interface* iface, const int& ver, const std::string& name); virtual void bindManager(wl_client* client, void* data, uint32_t ver, uint32_t id); + void updateAllOutputs(); private: void onManagerResourceDestroy(wl_resource* res); void onOutputResourceDestroy(wl_resource* res); void onManagerGetXDGOutput(CZxdgOutputManagerV1* mgr, uint32_t id, wl_resource* outputResource); - void updateAllOutputs(); // std::vector> m_vManagerResources; From 3a5052a714e2a6a2b002dddcac1204960b298f8b Mon Sep 17 00:00:00 2001 From: Vaxry Date: Sat, 5 Oct 2024 00:44:16 +0100 Subject: [PATCH 0473/2181] compositor: update all xdg outputs on arrange --- src/Compositor.cpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/Compositor.cpp b/src/Compositor.cpp index 25d73db0..b4d10c88 100644 --- a/src/Compositor.cpp +++ b/src/Compositor.cpp @@ -23,6 +23,7 @@ #include "protocols/PointerConstraints.hpp" #include "protocols/LayerShell.hpp" #include "protocols/XDGShell.hpp" +#include "protocols/XDGOutput.hpp" #include "protocols/core/Compositor.hpp" #include "protocols/core/Subcompositor.hpp" #include "desktop/LayerSurface.hpp" @@ -2869,6 +2870,8 @@ void CCompositor::arrangeMonitors() { else m->xwaylandScale = 1.f; } + + PROTO::xdgOutput->updateAllOutputs(); } void CCompositor::enterUnsafeState() { From a815b14bf1b69b92f82bd09f6845fbdbb2fbe516 Mon Sep 17 00:00:00 2001 From: Vaxry Date: Sat, 5 Oct 2024 00:44:30 +0100 Subject: [PATCH 0474/2181] monitor: cleanup and modernize scheduleDone --- src/helpers/Monitor.cpp | 25 ++++++++++++++----------- src/helpers/Monitor.hpp | 6 +++--- 2 files changed, 17 insertions(+), 14 deletions(-) diff --git a/src/helpers/Monitor.cpp b/src/helpers/Monitor.cpp index a9569699..03a1d92b 100644 --- a/src/helpers/Monitor.cpp +++ b/src/helpers/Monitor.cpp @@ -12,6 +12,7 @@ #include "../protocols/DRMSyncobj.hpp" #include "../protocols/core/Output.hpp" #include "../managers/PointerManager.hpp" +#include "../managers/eventLoop/EventLoopManager.hpp" #include "../protocols/core/Compositor.hpp" #include "sync/SyncTimeline.hpp" #include @@ -789,20 +790,22 @@ CBox CMonitor::logicalBox() { return {vecPosition, vecSize}; } -static void onDoneSource(void* data) { - auto pMonitor = (CMonitor*)data; - - if (!PROTO::outputs.contains(pMonitor->szName)) - return; - - PROTO::outputs.at(pMonitor->szName)->sendDone(); -} - void CMonitor::scheduleDone() { - if (doneSource) + if (doneScheduled) return; - doneSource = wl_event_loop_add_idle(g_pCompositor->m_sWLEventLoop, ::onDoneSource, this); + doneScheduled = true; + + g_pEventLoopManager->doLater([M = self] { + if (!M) // if M is gone, we got destroyed, doesn't matter. + return; + + if (!PROTO::outputs.contains(M->szName)) + return; + + PROTO::outputs.at(M->szName)->sendDone(); + M->doneScheduled = false; + }); } bool CMonitor::attemptDirectScanout() { diff --git a/src/helpers/Monitor.hpp b/src/helpers/Monitor.hpp index 97d9f8ab..2a2edab6 100644 --- a/src/helpers/Monitor.hpp +++ b/src/helpers/Monitor.hpp @@ -190,10 +190,10 @@ class CMonitor { } private: - void setupDefaultWS(const SMonitorRule&); - WORKSPACEID findAvailableDefaultWS(); + void setupDefaultWS(const SMonitorRule&); + WORKSPACEID findAvailableDefaultWS(); - wl_event_source* doneSource = nullptr; + bool doneScheduled = false; struct { CHyprSignalListener frame; From 595eb89f6e16df0e19916e3c02bf5ceac5a61c57 Mon Sep 17 00:00:00 2001 From: Vaxry <43317083+vaxerski@users.noreply.github.com> Date: Sat, 5 Oct 2024 00:52:53 +0100 Subject: [PATCH 0475/2181] renderer: Fix resize artifacts (stretching, bumps) (#7499) --- src/desktop/WLSurface.cpp | 2 +- src/render/OpenGL.cpp | 3 +++ src/render/Renderer.cpp | 42 +++++++++++++++++++++++---------------- src/render/Renderer.hpp | 33 +++++++++++++++--------------- 4 files changed, 46 insertions(+), 34 deletions(-) diff --git a/src/desktop/WLSurface.cpp b/src/desktop/WLSurface.cpp index 45050e35..5e88f507 100644 --- a/src/desktop/WLSurface.cpp +++ b/src/desktop/WLSurface.cpp @@ -62,7 +62,7 @@ bool CWLSurface::small() const { const auto O = m_pWindowOwner.lock(); - return O->m_vReportedSize.x > m_pResource->current.bufferSize.x + 1 || O->m_vReportedSize.y > m_pResource->current.bufferSize.y + 1; + return O->m_vReportedSize.x > m_pResource->current.size.x + 1 || O->m_vReportedSize.y > m_pResource->current.size.y + 1; } Vector2D CWLSurface::correctSmallVec() const { diff --git a/src/render/OpenGL.cpp b/src/render/OpenGL.cpp index 4f22d6aa..a16c2d62 100644 --- a/src/render/OpenGL.cpp +++ b/src/render/OpenGL.cpp @@ -1423,6 +1423,9 @@ void CHyprOpenGLImpl::renderTextureInternalWithDamage(SP tex, CBox* pB glActiveTexture(GL_TEXTURE0); glBindTexture(tex->m_iTarget, tex->m_iTexID); + glTexParameteri(tex->m_iTarget, GL_TEXTURE_WRAP_S, 0x2900 /* GL_CLAMP */); + glTexParameteri(tex->m_iTarget, GL_TEXTURE_WRAP_T, 0x2900); + if (m_RenderData.useNearestNeighbor) { glTexParameteri(tex->m_iTarget, GL_TEXTURE_MAG_FILTER, GL_NEAREST); glTexParameteri(tex->m_iTarget, GL_TEXTURE_MIN_FILTER, GL_NEAREST); diff --git a/src/render/Renderer.cpp b/src/render/Renderer.cpp index b081fd81..310d45af 100644 --- a/src/render/Renderer.cpp +++ b/src/render/Renderer.cpp @@ -150,7 +150,7 @@ static void renderSurface(SP surface, int x, int y, void* da const auto& TEXTURE = surface->current.texture; const auto RDATA = (SRenderData*)data; - const auto INTERACTIVERESIZEINPROGRESS = RDATA->pWindow && g_pInputManager->currentlyDraggedWindow.lock() == RDATA->pWindow && g_pInputManager->dragMode == MBIND_RESIZE; + const auto INTERACTIVERESIZEINPROGRESS = RDATA->pWindow && g_pInputManager->currentlyDraggedWindow && g_pInputManager->dragMode == MBIND_RESIZE; // this is bad, probably has been logged elsewhere. Means the texture failed // uploading to the GPU. @@ -180,6 +180,7 @@ static void renderSurface(SP surface, int x, int y, void* da // however, if surface buffer w / h < box, we need to adjust them const auto PWINDOW = PSURFACE ? PSURFACE->getWindow() : nullptr; + // center the surface if it's smaller than the viewport we assign it if (PSURFACE && !PSURFACE->m_bFillIgnoreSmall && PSURFACE->small() /* guarantees PWINDOW */) { const auto CORRECT = PSURFACE->correctSmallVec(); const auto SIZE = PSURFACE->getViewporterCorrectedSize(); @@ -195,17 +196,6 @@ static void renderSurface(SP surface, int x, int y, void* da } } - if (!INTERACTIVERESIZEINPROGRESS && PSURFACE && PWINDOW && PWINDOW->m_vRealSize.goal().floor() > PWINDOW->m_vReportedSize && PWINDOW->m_vReportedSize > Vector2D{1, 1}) { - Vector2D size = - Vector2D{windowBox.w * (PWINDOW->m_vReportedSize.x / PWINDOW->m_vRealSize.value().x), windowBox.h * (PWINDOW->m_vReportedSize.y / PWINDOW->m_vRealSize.value().y)}; - Vector2D correct = Vector2D{windowBox.w, windowBox.h} - size; - - windowBox.translate(correct / 2.0); - - windowBox.w = size.x; - windowBox.h = size.y; - } - } else { // here we clamp to 2, these might be some tiny specks windowBox = {(int)outputX + RDATA->x + x, (int)outputY + RDATA->y + y, std::max((float)surface->current.size.x, 2.F), std::max((float)surface->current.size.y, 2.F)}; if (RDATA->pWindow && RDATA->pWindow->m_vRealSize.isBeingAnimated() && RDATA->surface && RDATA->surface != surface && RDATA->squishOversized /* subsurface */) { @@ -231,6 +221,8 @@ static void renderSurface(SP surface, int x, int y, void* da return; // invisible } + const auto PROJSIZEUNSCALED = windowBox.size(); + windowBox.scale(RDATA->pMonitor->scale); windowBox.round(); @@ -239,7 +231,7 @@ static void renderSurface(SP surface, int x, int y, void* da DELTALESSTHAN(windowBox.height, surface->current.bufferSize.y, 3) /* off by one-or-two */ && (!RDATA->pWindow || (!RDATA->pWindow->m_vRealSize.isBeingAnimated() && !INTERACTIVERESIZEINPROGRESS)) /* not window or not animated/resizing */; - g_pHyprRenderer->calculateUVForSurface(RDATA->pWindow, surface, RDATA->surface == surface, windowBox.size(), MISALIGNEDFSV1); + g_pHyprRenderer->calculateUVForSurface(RDATA->pWindow, surface, RDATA->pMonitor->self.lock(), RDATA->surface == surface, windowBox.size(), PROJSIZEUNSCALED, MISALIGNEDFSV1); // check for fractional scale surfaces misaligning the buffer size // in those cases it's better to just force nearest neighbor @@ -1083,7 +1075,8 @@ void CHyprRenderer::renderSessionLockMissing(CMonitor* pMonitor) { g_pSessionLockManager->onLockscreenRenderedOnMonitor(pMonitor->ID); } -void CHyprRenderer::calculateUVForSurface(PHLWINDOW pWindow, SP pSurface, bool main, const Vector2D& projSize, bool fixMisalignedFSV1) { +void CHyprRenderer::calculateUVForSurface(PHLWINDOW pWindow, SP pSurface, SP pMonitor, bool main, const Vector2D& projSize, + const Vector2D& projSizeUnscaled, bool fixMisalignedFSV1) { if (!pWindow || !pWindow->m_bIsX11) { Vector2D uvTL; Vector2D uvBR = Vector2D(1, 1); @@ -1112,6 +1105,22 @@ void CHyprRenderer::calculateUVForSurface(PHLWINDOW pWindow, SPscale); + const bool SCALE_UNAWARE = MONITOR_WL_SCALE != pSurface->current.scale && !pSurface->current.viewport.hasDestination; + const auto EXPECTED_SIZE = + ((pSurface->current.viewport.hasDestination ? pSurface->current.viewport.destination : pSurface->current.bufferSize / pSurface->current.scale) * pMonitor->scale) + .round(); + if (!SCALE_UNAWARE && (EXPECTED_SIZE.x < projSize.x || EXPECTED_SIZE.y < projSize.y)) { + // this will not work with shm AFAIK, idk why. + // NOTE: this math is wrong if we have a source... or geom updates later, but I don't think we can do much + const auto FIX = projSize / EXPECTED_SIZE; + uvBR = uvBR * FIX; + } + g_pHyprOpenGL->m_RenderData.primarySurfaceUVTopLeft = uvTL; g_pHyprOpenGL->m_RenderData.primarySurfaceUVBottomRight = uvBR; @@ -1127,7 +1136,7 @@ void CHyprRenderer::calculateUVForSurface(PHLWINDOW pWindow, SPm_pXDGSurface->current.geometry; // ignore X and Y, adjust uv - if (geom.x != 0 || geom.y != 0 || geom.width > pWindow->m_vRealSize.value().x || geom.height > pWindow->m_vRealSize.value().y) { + if (geom.x != 0 || geom.y != 0 || geom.width > projSizeUnscaled.x || geom.height > projSizeUnscaled.y) { const auto XPERC = (double)geom.x / (double)pSurface->current.size.x; const auto YPERC = (double)geom.y / (double)pSurface->current.size.y; const auto WPERC = (double)(geom.x + geom.width) / (double)pSurface->current.size.x; @@ -1137,8 +1146,7 @@ void CHyprRenderer::calculateUVForSurface(PHLWINDOW pWindow, SPm_vRealSize.value(); + auto maxSize = projSizeUnscaled; if (pWindow->m_pWLSurface->small() && !pWindow->m_pWLSurface->m_bFillIgnoreSmall) maxSize = pWindow->m_pWLSurface->getViewporterCorrectedSize(); diff --git a/src/render/Renderer.hpp b/src/render/Renderer.hpp index b730d589..7d1ae4b1 100644 --- a/src/render/Renderer.hpp +++ b/src/render/Renderer.hpp @@ -49,22 +49,23 @@ class CHyprRenderer { CHyprRenderer(); ~CHyprRenderer(); - void renderMonitor(CMonitor* pMonitor); - void arrangeLayersForMonitor(const MONITORID&); - void damageSurface(SP, double, double, double scale = 1.0); - void damageWindow(PHLWINDOW, bool forceFull = false); - void damageBox(CBox*, bool skipFrameSchedule = false); - void damageBox(const int& x, const int& y, const int& w, const int& h); - void damageRegion(const CRegion&); - void damageMonitor(CMonitor*); - void damageMirrorsWith(CMonitor*, const CRegion&); - bool applyMonitorRule(CMonitor*, SMonitorRule*, bool force = false); - bool shouldRenderWindow(PHLWINDOW, CMonitor*); - bool shouldRenderWindow(PHLWINDOW); - void ensureCursorRenderingMode(); - bool shouldRenderCursor(); - void setCursorHidden(bool hide); - void calculateUVForSurface(PHLWINDOW, SP, bool main = false, const Vector2D& projSize = {}, bool fixMisalignedFSV1 = false); + void renderMonitor(CMonitor* pMonitor); + void arrangeLayersForMonitor(const MONITORID&); + void damageSurface(SP, double, double, double scale = 1.0); + void damageWindow(PHLWINDOW, bool forceFull = false); + void damageBox(CBox*, bool skipFrameSchedule = false); + void damageBox(const int& x, const int& y, const int& w, const int& h); + void damageRegion(const CRegion&); + void damageMonitor(CMonitor*); + void damageMirrorsWith(CMonitor*, const CRegion&); + bool applyMonitorRule(CMonitor*, SMonitorRule*, bool force = false); + bool shouldRenderWindow(PHLWINDOW, CMonitor*); + bool shouldRenderWindow(PHLWINDOW); + void ensureCursorRenderingMode(); + bool shouldRenderCursor(); + void setCursorHidden(bool hide); + void calculateUVForSurface(PHLWINDOW, SP, SP pMonitor, bool main = false, const Vector2D& projSize = {}, const Vector2D& projSizeUnscaled = {}, + bool fixMisalignedFSV1 = false); std::tuple getRenderTimes(CMonitor* pMonitor); // avg max min void renderLockscreen(CMonitor* pMonitor, timespec* now, const CBox& geometry); void setOccludedForBackLayers(CRegion& region, PHLWORKSPACE pWorkspace); From 46bf87c8d1f053284a266d5f0b470073a48a92f6 Mon Sep 17 00:00:00 2001 From: Vaxry Date: Sat, 5 Oct 2024 14:37:12 +0100 Subject: [PATCH 0476/2181] monitor: use a scope guard for disconnect events --- src/helpers/Monitor.cpp | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/src/helpers/Monitor.cpp b/src/helpers/Monitor.cpp index 03a1d92b..f105ea66 100644 --- a/src/helpers/Monitor.cpp +++ b/src/helpers/Monitor.cpp @@ -229,6 +229,12 @@ void CMonitor::onConnect(bool noRule) { } void CMonitor::onDisconnect(bool destroy) { + CScopeGuard x = {[this]() { + if (g_pCompositor->m_bIsShuttingDown) + return; + g_pEventManager->postEvent(SHyprIPCEvent{"monitorremoved", szName}); + EMIT_HOOK_EVENT("monitorRemoved", this); + }}; if (renderTimer) { wl_event_source_remove(renderTimer); @@ -341,9 +347,6 @@ void CMonitor::onDisconnect(bool destroy) { g_pHyprRenderer->m_pMostHzMonitor = pMonitorMostHz; } std::erase_if(g_pCompositor->m_vMonitors, [&](SP& el) { return el.get() == this; }); - - g_pEventManager->postEvent(SHyprIPCEvent{"monitorremoved", szName}); - EMIT_HOOK_EVENT("monitorRemoved", this); } void CMonitor::addDamage(const pixman_region32_t* rg) { From 6fbfeefc7119ff86411b765aa26b4bffbaa825ec Mon Sep 17 00:00:00 2001 From: Vaxry Date: Sat, 5 Oct 2024 14:40:03 +0100 Subject: [PATCH 0477/2181] protocolmgr: don't expose the fallback output --- src/managers/ProtocolManager.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/managers/ProtocolManager.cpp b/src/managers/ProtocolManager.cpp index 8bcc857a..157fa76c 100644 --- a/src/managers/ProtocolManager.cpp +++ b/src/managers/ProtocolManager.cpp @@ -86,7 +86,8 @@ CProtocolManager::CProtocolManager() { // ignore mirrored outputs. I don't think this will ever be hit as mirrors are applied after // this event is emitted iirc. - if (M->isMirror()) + // also ignore the fallback + if (M->isMirror() || M == g_pCompositor->m_pUnsafeOutput) return; if (PROTO::outputs.contains(M->szName)) From 52c09196219313aec2ec1d3d543669bff834d746 Mon Sep 17 00:00:00 2001 From: Vaxry Date: Sat, 5 Oct 2024 14:41:44 +0100 Subject: [PATCH 0478/2181] monitor: arrange monitors on connect and disconnect --- src/helpers/Monitor.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/helpers/Monitor.cpp b/src/helpers/Monitor.cpp index f105ea66..c6cef41f 100644 --- a/src/helpers/Monitor.cpp +++ b/src/helpers/Monitor.cpp @@ -36,6 +36,7 @@ CMonitor::~CMonitor() { } void CMonitor::onConnect(bool noRule) { + CScopeGuard x = {[]() { g_pCompositor->arrangeMonitors(); }}; if (output->supportsExplicit) { inTimeline = CSyncTimeline::create(output->getBackend()->drmFD()); @@ -234,6 +235,7 @@ void CMonitor::onDisconnect(bool destroy) { return; g_pEventManager->postEvent(SHyprIPCEvent{"monitorremoved", szName}); EMIT_HOOK_EVENT("monitorRemoved", this); + g_pCompositor->arrangeMonitors(); }}; if (renderTimer) { From 3ca699debffbb97085888835a33f20d0c542128d Mon Sep 17 00:00:00 2001 From: Vaxry Date: Sat, 5 Oct 2024 14:57:18 +0100 Subject: [PATCH 0479/2181] opengl: use GL_CLAMP_TO_EDGE instead of GL_CLAMP avoid error spam on select hw --- src/render/OpenGL.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/render/OpenGL.cpp b/src/render/OpenGL.cpp index a16c2d62..833e2ccb 100644 --- a/src/render/OpenGL.cpp +++ b/src/render/OpenGL.cpp @@ -1423,8 +1423,8 @@ void CHyprOpenGLImpl::renderTextureInternalWithDamage(SP tex, CBox* pB glActiveTexture(GL_TEXTURE0); glBindTexture(tex->m_iTarget, tex->m_iTexID); - glTexParameteri(tex->m_iTarget, GL_TEXTURE_WRAP_S, 0x2900 /* GL_CLAMP */); - glTexParameteri(tex->m_iTarget, GL_TEXTURE_WRAP_T, 0x2900); + glTexParameteri(tex->m_iTarget, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); + glTexParameteri(tex->m_iTarget, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); if (m_RenderData.useNearestNeighbor) { glTexParameteri(tex->m_iTarget, GL_TEXTURE_MAG_FILTER, GL_NEAREST); From 0ec6072a290051a03ab66cfb9bc616b2f5540e64 Mon Sep 17 00:00:00 2001 From: Vaxry Date: Sat, 5 Oct 2024 16:36:57 +0100 Subject: [PATCH 0480/2181] single-pixel: set buffer size to 1,1 --- src/protocols/SinglePixel.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/protocols/SinglePixel.cpp b/src/protocols/SinglePixel.cpp index 0595cce5..d800539d 100644 --- a/src/protocols/SinglePixel.cpp +++ b/src/protocols/SinglePixel.cpp @@ -17,6 +17,8 @@ CSinglePixelBuffer::CSinglePixelBuffer(uint32_t id, wl_client* client, CColor co success = texture->m_iTexID; + size = {1, 1}; + if (!success) Debug::log(ERR, "Failed creating a single pixel texture: null texture id"); } From 0c7a7e2d569eeed9d6025f3eef4ea0690d90845d Mon Sep 17 00:00:00 2001 From: Vaxry Date: Sun, 6 Oct 2024 12:04:13 +0100 Subject: [PATCH 0481/2181] version: bump to 0.44.0 --- VERSION | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/VERSION b/VERSION index 8298bb08..a8ab6c96 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -0.43.0 +0.44.0 From da86aac0f5c5c3604351961b901f62cdf7186a10 Mon Sep 17 00:00:00 2001 From: Vaxry Date: Sun, 6 Oct 2024 14:07:07 +0100 Subject: [PATCH 0482/2181] security-context: implement protocol fixes #7318 --- CMakeLists.txt | 1 + protocols/meson.build | 1 + src/Compositor.cpp | 12 ++ src/managers/ProtocolManager.cpp | 55 ++++++++ src/managers/ProtocolManager.hpp | 2 + src/protocols/SecurityContext.cpp | 214 ++++++++++++++++++++++++++++++ src/protocols/SecurityContext.hpp | 83 ++++++++++++ src/protocols/TextInputV1.hpp | 2 +- src/protocols/WaylandProtocol.cpp | 4 + src/protocols/WaylandProtocol.hpp | 1 + 10 files changed, 374 insertions(+), 1 deletion(-) create mode 100644 src/protocols/SecurityContext.cpp create mode 100644 src/protocols/SecurityContext.hpp diff --git a/CMakeLists.txt b/CMakeLists.txt index 3440af4a..1bac29ab 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -331,6 +331,7 @@ protocolnew("staging/drm-lease" "drm-lease-v1" false) protocolnew("staging/linux-drm-syncobj" "linux-drm-syncobj-v1" false) protocolnew("staging/xdg-dialog" "xdg-dialog-v1" false) protocolnew("staging/single-pixel-buffer" "single-pixel-buffer-v1" false) +protocolnew("staging/security-context" "security-context-v1" false) protocolwayland() diff --git a/protocols/meson.build b/protocols/meson.build index 6990b5a7..3fa2ef2f 100644 --- a/protocols/meson.build +++ b/protocols/meson.build @@ -64,6 +64,7 @@ protocols = [ wayland_protocol_dir / 'staging/linux-drm-syncobj/linux-drm-syncobj-v1.xml', wayland_protocol_dir / 'staging/xdg-dialog/xdg-dialog-v1.xml', wayland_protocol_dir / 'staging/single-pixel-buffer/single-pixel-buffer-v1.xml', + wayland_protocol_dir / 'staging/security-context/security-context-v1.xml', ] wl_protocols = [] diff --git a/src/Compositor.cpp b/src/Compositor.cpp index b4d10c88..f00e1e34 100644 --- a/src/Compositor.cpp +++ b/src/Compositor.cpp @@ -24,6 +24,7 @@ #include "protocols/LayerShell.hpp" #include "protocols/XDGShell.hpp" #include "protocols/XDGOutput.hpp" +#include "protocols/SecurityContext.hpp" #include "protocols/core/Compositor.hpp" #include "protocols/core/Subcompositor.hpp" #include "desktop/LayerSurface.hpp" @@ -210,11 +211,22 @@ void CCompositor::setRandomSplash() { static std::vector> pendingOutputs; +// + +static bool filterGlobals(const wl_client* client, const wl_global* global, void* data) { + if (!PROTO::securityContext->isClientSandboxed(client)) + return true; + + return !g_pProtocolManager || !g_pProtocolManager->isGlobalPrivileged(global); +} + // void CCompositor::initServer(std::string socketName, int socketFd) { m_sWLDisplay = wl_display_create(); + wl_display_set_global_filter(m_sWLDisplay, ::filterGlobals, nullptr); + m_sWLEventLoop = wl_display_get_event_loop(m_sWLDisplay); // register crit signal handler diff --git a/src/managers/ProtocolManager.cpp b/src/managers/ProtocolManager.cpp index 157fa76c..6366eefe 100644 --- a/src/managers/ProtocolManager.cpp +++ b/src/managers/ProtocolManager.cpp @@ -45,6 +45,7 @@ #include "../protocols/GlobalShortcuts.hpp" #include "../protocols/XDGDialog.hpp" #include "../protocols/SinglePixel.hpp" +#include "../protocols/SecurityContext.hpp" #include "../protocols/core/Seat.hpp" #include "../protocols/core/DataDevice.hpp" @@ -155,6 +156,7 @@ CProtocolManager::CProtocolManager() { PROTO::globalShortcuts = std::make_unique(&hyprland_global_shortcuts_manager_v1_interface, 1, "GlobalShortcuts"); PROTO::xdgDialog = std::make_unique(&xdg_dialog_v1_interface, 1, "XDGDialog"); PROTO::singlePixel = std::make_unique(&wp_single_pixel_buffer_manager_v1_interface, 1, "SinglePixel"); + PROTO::securityContext = std::make_unique(&wp_security_context_manager_v1_interface, 1, "SecurityContext"); for (auto const& b : g_pCompositor->m_pAqBackend->getImplementations()) { if (b->type() != Aquamarine::AQ_BACKEND_DRM) @@ -225,9 +227,62 @@ CProtocolManager::~CProtocolManager() { PROTO::toplevelExport.reset(); PROTO::globalShortcuts.reset(); PROTO::xdgDialog.reset(); + PROTO::singlePixel.reset(); + PROTO::securityContext.reset(); PROTO::lease.reset(); PROTO::sync.reset(); PROTO::mesaDRM.reset(); PROTO::linuxDma.reset(); } + +bool CProtocolManager::isGlobalPrivileged(const wl_global* global) { + if (!global) + return false; + + for (auto& [k, v] : PROTO::outputs) { + if (global == v->getGlobal()) + return false; + } + + // this is a static whitelist of allowed protocols, + // outputs are dynamic so we checked them above + // clang-format off + static const std::vector ALLOWED_WHITELIST = { + PROTO::seat->getGlobal(), + PROTO::data->getGlobal(), + PROTO::compositor->getGlobal(), + PROTO::subcompositor->getGlobal(), + PROTO::shm->getGlobal(), + PROTO::viewport->getGlobal(), + PROTO::tearing->getGlobal(), + PROTO::fractional->getGlobal(), + PROTO::cursorShape->getGlobal(), + PROTO::idleInhibit->getGlobal(), + PROTO::relativePointer->getGlobal(), + PROTO::xdgDecoration->getGlobal(), + PROTO::alphaModifier->getGlobal(), + PROTO::pointerGestures->getGlobal(), + PROTO::shortcutsInhibit->getGlobal(), + PROTO::textInputV1->getGlobal(), + PROTO::textInputV3->getGlobal(), + PROTO::constraints->getGlobal(), + PROTO::activation->getGlobal(), + PROTO::idle->getGlobal(), + PROTO::ime->getGlobal(), + PROTO::virtualKeyboard->getGlobal(), + PROTO::virtualPointer->getGlobal(), + PROTO::serverDecorationKDE->getGlobal(), + PROTO::tablet->getGlobal(), + PROTO::presentation->getGlobal(), + PROTO::xdgShell->getGlobal(), + PROTO::xdgDialog->getGlobal(), + PROTO::singlePixel->getGlobal(), + PROTO::sync ? PROTO::sync->getGlobal() : nullptr, + PROTO::mesaDRM ? PROTO::mesaDRM->getGlobal() : nullptr, + PROTO::linuxDma ? PROTO::linuxDma->getGlobal() : nullptr, + }; + // clang-format on + + return std::find(ALLOWED_WHITELIST.begin(), ALLOWED_WHITELIST.end(), global) == ALLOWED_WHITELIST.end(); +} diff --git a/src/managers/ProtocolManager.hpp b/src/managers/ProtocolManager.hpp index 1b6d31b6..d5629e9e 100644 --- a/src/managers/ProtocolManager.hpp +++ b/src/managers/ProtocolManager.hpp @@ -11,6 +11,8 @@ class CProtocolManager { CProtocolManager(); ~CProtocolManager(); + bool isGlobalPrivileged(const wl_global* global); + private: std::unordered_map m_mModeChangeListeners; diff --git a/src/protocols/SecurityContext.cpp b/src/protocols/SecurityContext.cpp new file mode 100644 index 00000000..b93ef448 --- /dev/null +++ b/src/protocols/SecurityContext.cpp @@ -0,0 +1,214 @@ +#include "SecurityContext.hpp" +#include "../Compositor.hpp" +#include + +static int onListenFdEvent(int fd, uint32_t mask, void* data) { + auto sc = (CSecurityContext*)data; + sc->onListen(mask); + return 0; +} + +static int onCloseFdEvent(int fd, uint32_t mask, void* data) { + auto sc = (CSecurityContext*)data; + sc->onClose(mask); + return 0; +} + +SP CSecurityContextSandboxedClient::create(int clientFD) { + auto p = SP(new CSecurityContextSandboxedClient(clientFD)); + if (!p->client) + return nullptr; + return p; +} + +static void onSecurityContextClientDestroy(wl_listener* l, void* d) { + CSecurityContextSandboxedClient* client = wl_container_of(l, client, destroyListener); + client->onDestroy(); +} + +CSecurityContextSandboxedClient::CSecurityContextSandboxedClient(int clientFD) { + client = wl_client_create(g_pCompositor->m_sWLDisplay, clientFD); + if (!client) + return; + + destroyListener.notify = ::onSecurityContextClientDestroy; + wl_client_add_destroy_late_listener(client, &destroyListener); +} + +CSecurityContextSandboxedClient::~CSecurityContextSandboxedClient() { + wl_list_remove(&destroyListener.link); +} + +void CSecurityContextSandboxedClient::onDestroy() { + std::erase_if(PROTO::securityContext->m_vSandboxedClients, [this](const auto& e) { return e.get() == this; }); +} + +CSecurityContext::CSecurityContext(SP resource_, int listenFD_, int closeFD_) : listenFD(listenFD_), closeFD(closeFD_), resource(resource_) { + if (!good()) + return; + + resource->setDestroy([this](CWpSecurityContextV1* r) { + LOGM(LOG, "security_context at 0x{:x}: resource destroyed, keeping context until fd hangup", (uintptr_t)this); + resource = nullptr; + }); + resource->setOnDestroy([this](CWpSecurityContextV1* r) { + LOGM(LOG, "security_context at 0x{:x}: resource destroyed, keeping context until fd hangup", (uintptr_t)this); + resource = nullptr; + }); + + LOGM(LOG, "New security_context at 0x{:x}", (uintptr_t)this); + + resource->setSetSandboxEngine([this](CWpSecurityContextV1* r, const char* engine) { + if (!sandboxEngine.empty()) { + r->error(WP_SECURITY_CONTEXT_V1_ERROR_ALREADY_SET, "Sandbox engine already set"); + return; + } + + if (committed) { + r->error(WP_SECURITY_CONTEXT_V1_ERROR_ALREADY_USED, "Context already committed"); + return; + } + + sandboxEngine = engine ? engine : "(null)"; + LOGM(LOG, "security_context at 0x{:x} sets engine to {}", (uintptr_t)this, sandboxEngine); + }); + + resource->setSetAppId([this](CWpSecurityContextV1* r, const char* appid) { + if (!appID.empty()) { + r->error(WP_SECURITY_CONTEXT_V1_ERROR_ALREADY_SET, "Sandbox appid already set"); + return; + } + + if (committed) { + r->error(WP_SECURITY_CONTEXT_V1_ERROR_ALREADY_USED, "Context already committed"); + return; + } + + appID = appid ? appid : "(null)"; + LOGM(LOG, "security_context at 0x{:x} sets appid to {}", (uintptr_t)this, appID); + }); + + resource->setSetInstanceId([this](CWpSecurityContextV1* r, const char* instance) { + if (!instanceID.empty()) { + r->error(WP_SECURITY_CONTEXT_V1_ERROR_ALREADY_SET, "Sandbox instance already set"); + return; + } + + if (committed) { + r->error(WP_SECURITY_CONTEXT_V1_ERROR_ALREADY_USED, "Context already committed"); + return; + } + + instanceID = instance ? instance : "(null)"; + LOGM(LOG, "security_context at 0x{:x} sets instance to {}", (uintptr_t)this, instanceID); + }); + + resource->setCommit([this](CWpSecurityContextV1* r) { + committed = true; + + LOGM(LOG, "security_context at 0x{:x} commits", (uintptr_t)this); + + listenSource = wl_event_loop_add_fd(g_pCompositor->m_sWLEventLoop, listenFD, WL_EVENT_READABLE, ::onListenFdEvent, this); + closeSource = wl_event_loop_add_fd(g_pCompositor->m_sWLEventLoop, closeFD, 0, ::onCloseFdEvent, this); + + if (!listenSource || !closeSource) { + r->noMemory(); + return; + } + }); +} + +CSecurityContext::~CSecurityContext() { + if (listenSource) + wl_event_source_remove(listenSource); + if (closeSource) + wl_event_source_remove(closeSource); +} + +bool CSecurityContext::good() { + return resource->resource(); +} + +void CSecurityContext::onListen(uint32_t mask) { + if (mask & (WL_EVENT_HANGUP | WL_EVENT_ERROR)) { + LOGM(ERR, "security_context at 0x{:x} got an error in listen", (uintptr_t)this); + PROTO::securityContext->destroyContext(this); + return; + } + + if (!(mask & WL_EVENT_READABLE)) + return; + + int clientFD = accept(listenFD, nullptr, nullptr); + if (clientFD < 0) { + LOGM(ERR, "security_context at 0x{:x} couldn't accept", (uintptr_t)this); + return; + } + + auto newClient = CSecurityContextSandboxedClient::create(clientFD); + if (!newClient) { + LOGM(ERR, "security_context at 0x{:x} couldn't create a client", (uintptr_t)this); + close(clientFD); + return; + } + + PROTO::securityContext->m_vSandboxedClients.emplace_back(newClient); + + LOGM(LOG, "security_context at 0x{:x} got a new wl_client 0x{:x}", (uintptr_t)this, (uintptr_t)newClient->client); +} + +void CSecurityContext::onClose(uint32_t mask) { + if (!(mask & (WL_EVENT_ERROR | WL_EVENT_HANGUP))) + return; + + PROTO::securityContext->destroyContext(this); +} + +CSecurityContextManagerResource::CSecurityContextManagerResource(SP resource_) : resource(resource_) { + if (!good()) + return; + + resource->setDestroy([this](CWpSecurityContextManagerV1* r) { PROTO::securityContext->destroyResource(this); }); + resource->setOnDestroy([this](CWpSecurityContextManagerV1* r) { PROTO::securityContext->destroyResource(this); }); + + resource->setCreateListener([](CWpSecurityContextManagerV1* r, uint32_t id, int32_t lfd, int32_t cfd) { + const auto RESOURCE = + PROTO::securityContext->m_vContexts.emplace_back(makeShared(makeShared(r->client(), r->version(), id), lfd, cfd)); + + if (!RESOURCE->good()) { + r->noMemory(); + PROTO::securityContext->m_vContexts.pop_back(); + return; + } + }); +} + +bool CSecurityContextManagerResource::good() { + return resource->resource(); +} + +CSecurityContextProtocol::CSecurityContextProtocol(const wl_interface* iface, const int& ver, const std::string& name) : IWaylandProtocol(iface, ver, name) { + ; +} + +void CSecurityContextProtocol::bindManager(wl_client* client, void* data, uint32_t ver, uint32_t id) { + const auto RESOURCE = m_vManagers.emplace_back(makeShared(makeShared(client, ver, id))); + + if (!RESOURCE->good()) { + wl_client_post_no_memory(client); + m_vManagers.pop_back(); + return; + } +} + +void CSecurityContextProtocol::destroyResource(CSecurityContextManagerResource* res) { + std::erase_if(m_vManagers, [&](const auto& other) { return other.get() == res; }); +} + +void CSecurityContextProtocol::destroyContext(CSecurityContext* context) { + std::erase_if(m_vContexts, [&](const auto& other) { return other.get() == context; }); +} + +bool CSecurityContextProtocol::isClientSandboxed(const wl_client* client) { + return std::find_if(m_vSandboxedClients.begin(), m_vSandboxedClients.end(), [client](const auto& e) { return e->client == client; }) != m_vSandboxedClients.end(); +} diff --git a/src/protocols/SecurityContext.hpp b/src/protocols/SecurityContext.hpp new file mode 100644 index 00000000..bcbb69b2 --- /dev/null +++ b/src/protocols/SecurityContext.hpp @@ -0,0 +1,83 @@ +#pragma once + +#include +#include +#include +#include "WaylandProtocol.hpp" +#include "security-context-v1.hpp" + +class CSecurityContext { + public: + CSecurityContext(SP resource_, int listenFD_, int closeFD_); + ~CSecurityContext(); + + bool good(); + + std::string sandboxEngine, appID, instanceID; + int listenFD = -1, closeFD = -1; + + void onListen(uint32_t mask); + void onClose(uint32_t mask); + + private: + SP resource; + + wl_event_source * listenSource = nullptr, *closeSource = nullptr; + + bool committed = false; +}; + +class CSecurityContextManagerResource { + public: + CSecurityContextManagerResource(SP resource_); + + bool good(); + + private: + SP resource; +}; + +class CSecurityContextSandboxedClient { + public: + static SP create(int clientFD); + ~CSecurityContextSandboxedClient(); + + void onDestroy(); + + wl_listener destroyListener; + + private: + CSecurityContextSandboxedClient(int clientFD); + + wl_client* client = nullptr; + + friend class CSecurityContextProtocol; + friend class CSecurityContext; +}; + +class CSecurityContextProtocol : public IWaylandProtocol { + public: + CSecurityContextProtocol(const wl_interface* iface, const int& ver, const std::string& name); + + virtual void bindManager(wl_client* client, void* data, uint32_t ver, uint32_t id); + + bool isClientSandboxed(const wl_client* client); + + private: + void destroyResource(CSecurityContextManagerResource* resource); + + void destroyContext(CSecurityContext* context); + + // + std::vector> m_vManagers; + std::vector> m_vContexts; + std::vector> m_vSandboxedClients; + + friend class CSecurityContextManagerResource; + friend class CSecurityContext; + friend class CSecurityContextSandboxedClient; +}; + +namespace PROTO { + inline UP securityContext; +}; \ No newline at end of file diff --git a/src/protocols/TextInputV1.hpp b/src/protocols/TextInputV1.hpp index 9bee452c..d3b0d71b 100644 --- a/src/protocols/TextInputV1.hpp +++ b/src/protocols/TextInputV1.hpp @@ -60,7 +60,7 @@ class CTextInputV1 { friend class CTextInputV1Protocol; }; -class CTextInputV1Protocol : IWaylandProtocol { +class CTextInputV1Protocol : public IWaylandProtocol { public: CTextInputV1Protocol(const wl_interface* iface, const int& ver, const std::string& name); diff --git a/src/protocols/WaylandProtocol.cpp b/src/protocols/WaylandProtocol.cpp index 0782d323..00b112b0 100644 --- a/src/protocols/WaylandProtocol.cpp +++ b/src/protocols/WaylandProtocol.cpp @@ -40,3 +40,7 @@ IWaylandProtocol::~IWaylandProtocol() { void IWaylandProtocol::removeGlobal() { wl_global_remove(m_pGlobal); } + +wl_global* IWaylandProtocol::getGlobal() { + return m_pGlobal; +} diff --git a/src/protocols/WaylandProtocol.hpp b/src/protocols/WaylandProtocol.hpp index 87c75ed8..056322ac 100644 --- a/src/protocols/WaylandProtocol.hpp +++ b/src/protocols/WaylandProtocol.hpp @@ -53,6 +53,7 @@ class IWaylandProtocol { virtual void onDisplayDestroy(); virtual void removeGlobal(); + virtual wl_global* getGlobal(); virtual void bindManager(wl_client* client, void* data, uint32_t ver, uint32_t id) = 0; From 4e41cda27ed4176005082436cb35878335e63fae Mon Sep 17 00:00:00 2001 From: Vaxry Date: Sun, 6 Oct 2024 15:08:26 +0100 Subject: [PATCH 0483/2181] security-context: close client fds after disconnect --- src/protocols/SecurityContext.cpp | 7 ++++--- src/protocols/SecurityContext.hpp | 5 +++-- 2 files changed, 7 insertions(+), 5 deletions(-) diff --git a/src/protocols/SecurityContext.cpp b/src/protocols/SecurityContext.cpp index b93ef448..b42c3a97 100644 --- a/src/protocols/SecurityContext.cpp +++ b/src/protocols/SecurityContext.cpp @@ -14,8 +14,8 @@ static int onCloseFdEvent(int fd, uint32_t mask, void* data) { return 0; } -SP CSecurityContextSandboxedClient::create(int clientFD) { - auto p = SP(new CSecurityContextSandboxedClient(clientFD)); +SP CSecurityContextSandboxedClient::create(int clientFD_) { + auto p = SP(new CSecurityContextSandboxedClient(clientFD_)); if (!p->client) return nullptr; return p; @@ -26,7 +26,7 @@ static void onSecurityContextClientDestroy(wl_listener* l, void* d) { client->onDestroy(); } -CSecurityContextSandboxedClient::CSecurityContextSandboxedClient(int clientFD) { +CSecurityContextSandboxedClient::CSecurityContextSandboxedClient(int clientFD_) : clientFD(clientFD_) { client = wl_client_create(g_pCompositor->m_sWLDisplay, clientFD); if (!client) return; @@ -37,6 +37,7 @@ CSecurityContextSandboxedClient::CSecurityContextSandboxedClient(int clientFD) { CSecurityContextSandboxedClient::~CSecurityContextSandboxedClient() { wl_list_remove(&destroyListener.link); + close(clientFD); } void CSecurityContextSandboxedClient::onDestroy() { diff --git a/src/protocols/SecurityContext.hpp b/src/protocols/SecurityContext.hpp index bcbb69b2..76313bcf 100644 --- a/src/protocols/SecurityContext.hpp +++ b/src/protocols/SecurityContext.hpp @@ -47,9 +47,10 @@ class CSecurityContextSandboxedClient { wl_listener destroyListener; private: - CSecurityContextSandboxedClient(int clientFD); + CSecurityContextSandboxedClient(int clientFD_); - wl_client* client = nullptr; + wl_client* client = nullptr; + int clientFD = -1; friend class CSecurityContextProtocol; friend class CSecurityContext; From 97444ed7a8a83406970fcc05907db1110435b59b Mon Sep 17 00:00:00 2001 From: Aqa-Ib Date: Mon, 7 Oct 2024 14:22:55 +0200 Subject: [PATCH 0484/2181] layout: fix auto group when opening a new window in a non-focused workspace using window rules (#8006) --- src/layout/IHyprLayout.cpp | 29 +++++++++++++++-------------- 1 file changed, 15 insertions(+), 14 deletions(-) diff --git a/src/layout/IHyprLayout.cpp b/src/layout/IHyprLayout.cpp index 4b5c9d4f..f090e87d 100644 --- a/src/layout/IHyprLayout.cpp +++ b/src/layout/IHyprLayout.cpp @@ -181,33 +181,34 @@ void IHyprLayout::onWindowCreatedFloating(PHLWINDOW pWindow) { } bool IHyprLayout::onWindowCreatedAutoGroup(PHLWINDOW pWindow) { - static auto AUTOGROUP = CConfigValue("group:auto_group"); - if ((*AUTOGROUP || g_pInputManager->m_bWasDraggingWindow) // check if auto_group is enabled, or, if the user is manually dragging the window into the group. - && g_pCompositor->m_pLastWindow.lock() // check if a focused window exists. - && g_pCompositor->m_pLastWindow != pWindow // fixes a freeze when activating togglefloat to transform a floating group into a tiled group. - && g_pCompositor->m_pLastWindow->m_pWorkspace == - pWindow - ->m_pWorkspace // fix for multimonitor: when there is a focused group in monitor 1 and monitor 2 is empty, this enables adding the first window of monitor 2 when using the mouse to focus it. - && g_pCompositor->m_pLastWindow->m_sGroupData.pNextWindow.lock() // check if the focused window is a group - && pWindow->canBeGroupedInto(g_pCompositor->m_pLastWindow.lock()) // check if the new window can be grouped into the focused group - && !g_pXWaylandManager->shouldBeFloated(pWindow)) { // don't group XWayland windows that should be floated. + static auto PAUTOGROUP = CConfigValue("group:auto_group"); + PHLWINDOW OPENINGON = g_pCompositor->m_pLastWindow.lock() && g_pCompositor->m_pLastWindow->m_pWorkspace == pWindow->m_pWorkspace ? + g_pCompositor->m_pLastWindow.lock() : + g_pCompositor->getFirstWindowOnWorkspace(pWindow->workspaceID()); + + if ((*PAUTOGROUP || g_pInputManager->m_bWasDraggingWindow) // check if auto_group is enabled, or, if the user is manually dragging the window into the group. + && OPENINGON // check if OPENINGON exists. + && OPENINGON != pWindow // fixes a freeze when activating togglefloat to transform a floating group into a tiled group. + && OPENINGON->m_sGroupData.pNextWindow.lock() // check if OPENINGON is a group + && pWindow->canBeGroupedInto(OPENINGON) // check if the new window can be grouped into OPENINGON + && !g_pXWaylandManager->shouldBeFloated(pWindow)) { // don't group XWayland windows that should be floated. switch (pWindow->m_bIsFloating) { case false: - if (g_pCompositor->m_pLastWindow->m_bIsFloating) + if (OPENINGON->m_bIsFloating) pWindow->m_bIsFloating = true; break; case true: - if (!g_pCompositor->m_pLastWindow->m_bIsFloating) + if (!OPENINGON->m_bIsFloating) pWindow->m_bIsFloating = false; break; } static auto USECURRPOS = CConfigValue("group:insert_after_current"); - (*USECURRPOS ? g_pCompositor->m_pLastWindow : g_pCompositor->m_pLastWindow->getGroupTail())->insertWindowToGroup(pWindow); + (*USECURRPOS ? OPENINGON : OPENINGON->getGroupTail())->insertWindowToGroup(pWindow); - g_pCompositor->m_pLastWindow->setGroupCurrent(pWindow); + OPENINGON->setGroupCurrent(pWindow); pWindow->applyGroupRules(); pWindow->updateWindowDecos(); recalculateWindow(pWindow); From 5bf7b1e1fadf743f41ec765f7545370e3d7ccf96 Mon Sep 17 00:00:00 2001 From: Timon Schelling Date: Mon, 7 Oct 2024 15:44:03 +0000 Subject: [PATCH 0485/2181] flake.nix: add xdph follows fixes a duplicate hyprland-protocols instance sometimes being created due to xdph not following hyprlands instance --- flake.lock | 29 +++-------------------------- flake.nix | 5 +++-- 2 files changed, 6 insertions(+), 28 deletions(-) diff --git a/flake.lock b/flake.lock index 2579dd11..2f9fbbc6 100644 --- a/flake.lock +++ b/flake.lock @@ -78,31 +78,6 @@ "type": "github" } }, - "hyprland-protocols_2": { - "inputs": { - "nixpkgs": [ - "xdph", - "nixpkgs" - ], - "systems": [ - "xdph", - "systems" - ] - }, - "locked": { - "lastModified": 1721326555, - "narHash": "sha256-zCu4R0CSHEactW9JqYki26gy8h9f6rHmSwj4XJmlHgg=", - "owner": "hyprwm", - "repo": "hyprland-protocols", - "rev": "5a11232266bf1a1f5952d5b179c3f4b2facaaa84", - "type": "github" - }, - "original": { - "owner": "hyprwm", - "repo": "hyprland-protocols", - "type": "github" - } - }, "hyprlang": { "inputs": { "hyprutils": [ @@ -221,7 +196,9 @@ }, "xdph": { "inputs": { - "hyprland-protocols": "hyprland-protocols_2", + "hyprland-protocols": [ + "hyprland-protocols" + ], "hyprlang": [ "hyprlang" ], diff --git a/flake.nix b/flake.nix index ee5af6a1..cfd003f8 100644 --- a/flake.nix +++ b/flake.nix @@ -51,6 +51,7 @@ url = "github:hyprwm/xdg-desktop-portal-hyprland"; inputs.nixpkgs.follows = "nixpkgs"; inputs.systems.follows = "systems"; + inputs.hyprland-protocols.follows = "hyprland-protocols"; inputs.hyprlang.follows = "hyprlang"; inputs.hyprutils.follows = "hyprutils"; inputs.hyprwayland-scanner.follows = "hyprwayland-scanner"; @@ -98,13 +99,13 @@ inherit (pkgsFor.${system}) # hyprland-packages - + hyprland hyprland-debug hyprland-legacy-renderer hyprland-unwrapped # hyprland-extras - + xdg-desktop-portal-hyprland ; hyprland-cross = (pkgsCrossFor.${system} "aarch64-linux").hyprland; From 46d990f1b632dc52a667d876a32cffb24ef72bd8 Mon Sep 17 00:00:00 2001 From: Artur Manuel Date: Mon, 7 Oct 2024 19:49:19 +0100 Subject: [PATCH 0486/2181] feat: add a custom made treewide formatter (#7992) --- .gitignore | 4 +++ flake.lock | 77 +++++++++++++++++++++++++++++++++++++++++++++++ flake.nix | 22 ++++++++++++-- nix/default.nix | 2 +- nix/formatter.nix | 64 +++++++++++++++++++++++++++++++++++++++ nix/overlays.nix | 4 +-- 6 files changed, 168 insertions(+), 5 deletions(-) create mode 100644 nix/formatter.nix diff --git a/.gitignore b/.gitignore index 2e158a4e..a7934790 100644 --- a/.gitignore +++ b/.gitignore @@ -14,6 +14,7 @@ _deps build/ result* +/.pre-commit-config.yaml /.vscode/ /.idea/ .envrc @@ -39,3 +40,6 @@ PKGBUILD src/version.h hyprpm/Makefile hyprctl/Makefile + +**/.#*.* +**/#*.*# diff --git a/flake.lock b/flake.lock index 2f9fbbc6..85069a74 100644 --- a/flake.lock +++ b/flake.lock @@ -29,6 +29,43 @@ "type": "github" } }, + "flake-compat": { + "flake": false, + "locked": { + "lastModified": 1696426674, + "narHash": "sha256-kvjfFW7WAETZlt09AgDn1MrtKzP7t90Vf7vypd3OL1U=", + "owner": "edolstra", + "repo": "flake-compat", + "rev": "0f9255e01c2351cc7d116c072cb317785dd33b33", + "type": "github" + }, + "original": { + "owner": "edolstra", + "repo": "flake-compat", + "type": "github" + } + }, + "gitignore": { + "inputs": { + "nixpkgs": [ + "pre-commit-hooks", + "nixpkgs" + ] + }, + "locked": { + "lastModified": 1709087332, + "narHash": "sha256-HG2cCnktfHsKV0s4XW83gU3F57gaTljL9KNSuG6bnQs=", + "owner": "hercules-ci", + "repo": "gitignore.nix", + "rev": "637db329424fd7e46cf4185293b9cc8c88c95394", + "type": "github" + }, + "original": { + "owner": "hercules-ci", + "repo": "gitignore.nix", + "type": "github" + } + }, "hyprcursor": { "inputs": { "hyprlang": [ @@ -166,6 +203,45 @@ "type": "github" } }, + "nixpkgs-stable": { + "locked": { + "lastModified": 1720386169, + "narHash": "sha256-NGKVY4PjzwAa4upkGtAMz1npHGoRzWotlSnVlqI40mo=", + "owner": "NixOS", + "repo": "nixpkgs", + "rev": "194846768975b7ad2c4988bdb82572c00222c0d7", + "type": "github" + }, + "original": { + "owner": "NixOS", + "ref": "nixos-24.05", + "repo": "nixpkgs", + "type": "github" + } + }, + "pre-commit-hooks": { + "inputs": { + "flake-compat": "flake-compat", + "gitignore": "gitignore", + "nixpkgs": [ + "nixpkgs" + ], + "nixpkgs-stable": "nixpkgs-stable" + }, + "locked": { + "lastModified": 1728092656, + "narHash": "sha256-eMeCTJZ5xBeQ0f9Os7K8DThNVSo9gy4umZLDfF5q6OM=", + "owner": "cachix", + "repo": "git-hooks.nix", + "rev": "1211305a5b237771e13fcca0c51e60ad47326a9a", + "type": "github" + }, + "original": { + "owner": "cachix", + "repo": "git-hooks.nix", + "type": "github" + } + }, "root": { "inputs": { "aquamarine": "aquamarine", @@ -175,6 +251,7 @@ "hyprutils": "hyprutils", "hyprwayland-scanner": "hyprwayland-scanner", "nixpkgs": "nixpkgs", + "pre-commit-hooks": "pre-commit-hooks", "systems": "systems", "xdph": "xdph" } diff --git a/flake.nix b/flake.nix index cfd003f8..e3419ef8 100644 --- a/flake.nix +++ b/flake.nix @@ -56,6 +56,11 @@ inputs.hyprutils.follows = "hyprutils"; inputs.hyprwayland-scanner.follows = "hyprwayland-scanner"; }; + + pre-commit-hooks = { + url = "github:cachix/git-hooks.nix"; + inputs.nixpkgs.follows = "nixpkgs"; + }; }; outputs = inputs @ { @@ -77,7 +82,7 @@ pkgsCrossFor = eachSystem (system: crossSystem: import nixpkgs { localSystem = system; - crossSystem = crossSystem; + inherit crossSystem; overlays = with self.overlays; [ hyprland-packages hyprland-extras @@ -92,6 +97,18 @@ self.packages.${system}) // { inherit (self.packages.${system}) xdg-desktop-portal-hyprland; + pre-commit-check = inputs.pre-commit-hooks.lib.${system}.run { + src = ./.; + hooks = { + hyprland-treewide-formatter = { + enable = true; + entry = "${self.formatter.${system}}/bin/hyprland-treewide-formatter"; + pass_filenames = false; + excludes = ["subprojects"]; + always_run = true; + }; + }; + }; }); packages = eachSystem (system: { @@ -120,10 +137,11 @@ hardeningDisable = ["fortify"]; inputsFrom = [pkgsFor.${system}.hyprland]; packages = [pkgsFor.${system}.clang-tools]; + inherit (self.checks.${system}.pre-commit-check) shellHook; }; }); - formatter = eachSystem (system: nixpkgs.legacyPackages.${system}.alejandra); + formatter = eachSystem (system: pkgsFor.${system}.callPackage ./nix/formatter.nix {}); nixosModules.default = import ./nix/module.nix inputs; homeManagerModules.default = import ./nix/hm-module.nix self; diff --git a/nix/default.nix b/nix/default.nix index 6f086ccc..d463e271 100644 --- a/nix/default.nix +++ b/nix/default.nix @@ -68,7 +68,7 @@ in inherit version; src = cleanSourceWith { - filter = name: type: let + filter = name: _type: let baseName = baseNameOf (toString name); in ! (hasSuffix ".nix" baseName); diff --git a/nix/formatter.nix b/nix/formatter.nix new file mode 100644 index 00000000..66721c2c --- /dev/null +++ b/nix/formatter.nix @@ -0,0 +1,64 @@ +{ + writeShellApplication, + deadnix, + statix, + alejandra, + llvmPackages_19, + fd, +}: +writeShellApplication { + name = "hyprland-treewide-formatter"; + runtimeInputs = [ + deadnix + statix + alejandra + llvmPackages_19.clang-tools + fd + ]; + text = '' + # shellcheck disable=SC2148 + + # common excludes + excludes="subprojects" + + nix_format() { + if [ "$*" = 0 ]; then + fd '.*\.nix' . -E "$excludes" -x statix fix -- {} \; + fd '.*\.nix' . -E "$excludes" -X deadnix -e -- {} \; -X alejandra {} \; + elif [ -d "$1" ]; then + fd '.*\.nix' "$1" -E "$excludes" -i -x statix fix -- {} \; + fd '.*\.nix' "$1" -E "$excludes" -i -X deadnix -e -- {} \; -X alejandra {} \; + else + statix fix -- "$1" + deadnix -e "$1" + alejandra "$1" + fi + } + + cpp_format() { + if [ "$*" = 0 ] || [ "$1" = "." ]; then + fd '.*\.cpp' . -E "$excludes" | xargs clang-format --verbose -i + elif [ -d "$1" ]; then + fd '.*\.cpp' "$1" -E "$excludes" | xargs clang-format --verbose -i + else + clang-format --verbose -i "$1" + fi + } + + for i in "$@"; do + case ''${i##*.} in + "nix") + nix_format "$i" + ;; + "cpp") + cpp_format "$i" + ;; + *) + nix_format "$i" + cpp_format "$i" + ;; + esac + + done + ''; +} diff --git a/nix/overlays.nix b/nix/overlays.nix index 2b2788e7..a78f3003 100644 --- a/nix/overlays.nix +++ b/nix/overlays.nix @@ -29,7 +29,7 @@ in { self.overlays.udis86 # Hyprland packages themselves - (final: prev: let + (final: _prev: let date = mkDate (self.lastModifiedDate or "19700101"); in { hyprland = final.callPackage ./default.nix { @@ -70,7 +70,7 @@ in { # this version is the one used in the git submodule, and allows us to # fetch the source without '?submodules=1' udis86 = final: prev: { - udis86-hyprland = prev.udis86.overrideAttrs (self: super: { + udis86-hyprland = prev.udis86.overrideAttrs (_self: _super: { src = final.fetchFromGitHub { owner = "canihavesomecoffee"; repo = "udis86"; From a364df4c9e9a73f0460665463028539e3abe4a8b Mon Sep 17 00:00:00 2001 From: MightyPlaza <123664421+MightyPlaza@users.noreply.github.com> Date: Mon, 7 Oct 2024 18:52:49 +0000 Subject: [PATCH 0487/2181] internal: use clampWindowSize to unify min/maxsize handling (#8014) modified: src/desktop/Window.cpp modified: src/desktop/Window.hpp modified: src/events/Windows.cpp --- src/desktop/Window.cpp | 20 ++++++++++++++------ src/desktop/Window.hpp | 1 + src/events/Windows.cpp | 22 ++-------------------- 3 files changed, 17 insertions(+), 26 deletions(-) diff --git a/src/desktop/Window.cpp b/src/desktop/Window.cpp index feced807..fa85dc07 100644 --- a/src/desktop/Window.cpp +++ b/src/desktop/Window.cpp @@ -736,9 +736,8 @@ void CWindow::applyDynamicRule(const SWindowRule& r) { } m_sWindowData.maxSize = CWindowOverridableVar(VEC, priority); - m_vRealSize = - Vector2D(std::min((double)m_sWindowData.maxSize.value().x, m_vRealSize.goal().x), std::min((double)m_sWindowData.maxSize.value().y, m_vRealSize.goal().y)); - g_pXWaylandManager->setWindowSize(m_pSelf.lock(), m_vRealSize.goal()); + clampWindowSize(std::nullopt, m_sWindowData.maxSize.value()); + } catch (std::exception& e) { Debug::log(ERR, "maxsize rule \"{}\" failed with: {}", r.szRule, e.what()); } } else if (r.szRule.starts_with("minsize")) { try { @@ -751,9 +750,8 @@ void CWindow::applyDynamicRule(const SWindowRule& r) { } m_sWindowData.minSize = CWindowOverridableVar(VEC, priority); - m_vRealSize = - Vector2D(std::max((double)m_sWindowData.minSize.value().x, m_vRealSize.goal().x), std::max((double)m_sWindowData.minSize.value().y, m_vRealSize.goal().y)); - g_pXWaylandManager->setWindowSize(m_pSelf.lock(), m_vRealSize.goal()); + clampWindowSize(m_sWindowData.minSize.value(), std::nullopt); + if (m_sGroupData.pNextWindow.expired()) setHidden(false); } catch (std::exception& e) { Debug::log(ERR, "minsize rule \"{}\" failed with: {}", r.szRule, e.what()); } @@ -1253,6 +1251,16 @@ int CWindow::surfacesCount() { return no; } +void CWindow::clampWindowSize(const std::optional minSize, const std::optional maxSize) { + const Vector2D REALSIZE = m_vRealSize.goal(); + const Vector2D NEWSIZE = REALSIZE.clamp(minSize.value_or(Vector2D{0.f, 0.f}), maxSize.value_or(Vector2D{INFINITY, INFINITY})); + const Vector2D DELTA = REALSIZE - NEWSIZE; + + m_vRealPosition = m_vRealPosition.goal() + DELTA / 2.0; + m_vRealSize = NEWSIZE; + g_pXWaylandManager->setWindowSize(m_pSelf.lock(), NEWSIZE); +} + bool CWindow::isFullscreen() { return m_sFullscreenState.internal != FSMODE_NONE; } diff --git a/src/desktop/Window.hpp b/src/desktop/Window.hpp index d14248c5..9baf57c4 100644 --- a/src/desktop/Window.hpp +++ b/src/desktop/Window.hpp @@ -429,6 +429,7 @@ class CWindow { bool onSpecialWorkspace(); void activate(bool force = false); int surfacesCount(); + void clampWindowSize(const std::optional minSize, const std::optional maxSize); bool isFullscreen(); bool isEffectiveInternalFSMode(const eFullscreenMode); diff --git a/src/events/Windows.cpp b/src/events/Windows.cpp index 1c2c7cfa..37f29130 100644 --- a/src/events/Windows.cpp +++ b/src/events/Windows.cpp @@ -751,26 +751,8 @@ void Events::listener_commitWindow(void* owner, void* data) { const auto MINSIZE = PWINDOW->m_pXDGSurface->toplevel->current.minSize; const auto MAXSIZE = PWINDOW->m_pXDGSurface->toplevel->current.maxSize; - if (MAXSIZE > Vector2D{1, 1}) { - const auto REALSIZE = PWINDOW->m_vRealSize.goal(); - Vector2D newSize = REALSIZE; - - if (MAXSIZE.x < newSize.x) - newSize.x = MAXSIZE.x; - if (MAXSIZE.y < newSize.y) - newSize.y = MAXSIZE.y; - if (MINSIZE.x > newSize.x) - newSize.x = MINSIZE.x; - if (MINSIZE.y > newSize.y) - newSize.y = MINSIZE.y; - - const Vector2D DELTA = REALSIZE - newSize; - - PWINDOW->m_vRealPosition = PWINDOW->m_vRealPosition.goal() + DELTA / 2.0; - PWINDOW->m_vRealSize = newSize; - g_pXWaylandManager->setWindowSize(PWINDOW, newSize); - g_pHyprRenderer->damageWindow(PWINDOW); - } + PWINDOW->clampWindowSize(MINSIZE, MAXSIZE > Vector2D{1, 1} ? std::optional{MAXSIZE} : std::nullopt); + g_pHyprRenderer->damageWindow(PWINDOW); } if (!PWINDOW->m_pWorkspace->m_bVisible) From 0d70c442538ba0d1efc63558c859c184367c95ad Mon Sep 17 00:00:00 2001 From: Ikalco <73481042+ikalco@users.noreply.github.com> Date: Mon, 7 Oct 2024 19:23:48 -0500 Subject: [PATCH 0488/2181] screencopy: fix screencopy frames not being cleaned up (#8017) --------- Co-authored-by: Vaxry --- src/protocols/Screencopy.cpp | 13 ++++++++----- src/protocols/Screencopy.hpp | 4 ++-- src/protocols/ToplevelExport.cpp | 16 +++++++++++----- src/protocols/ToplevelExport.hpp | 4 ++-- subprojects/hyprland-protocols | 2 +- 5 files changed, 24 insertions(+), 15 deletions(-) diff --git a/src/protocols/Screencopy.cpp b/src/protocols/Screencopy.cpp index 63024541..1b06a1fa 100644 --- a/src/protocols/Screencopy.cpp +++ b/src/protocols/Screencopy.cpp @@ -394,12 +394,12 @@ void CScreencopyProtocol::bindManager(wl_client* client, void* data, uint32_t ve void CScreencopyProtocol::destroyResource(CScreencopyClient* client) { std::erase_if(m_vClients, [&](const auto& other) { return other.get() == client; }); std::erase_if(m_vFrames, [&](const auto& other) { return other->client.get() == client; }); - std::erase_if(m_vFramesAwaitingWrite, [&](const auto& other) { return other->client.get() == client; }); + std::erase_if(m_vFramesAwaitingWrite, [&](const auto& other) { return !other || other->client.get() == client; }); } void CScreencopyProtocol::destroyResource(CScreencopyFrame* frame) { std::erase_if(m_vFrames, [&](const auto& other) { return other.get() == frame; }); - std::erase_if(m_vFramesAwaitingWrite, [&](const auto& other) { return other.get() == frame; }); + std::erase_if(m_vFramesAwaitingWrite, [&](const auto& other) { return !other || other.get() == frame; }); } void CScreencopyProtocol::onOutputCommit(CMonitor* pMonitor) { @@ -412,8 +412,11 @@ void CScreencopyProtocol::onOutputCommit(CMonitor* pMonitor) { // share frame if correct output for (auto const& f : m_vFramesAwaitingWrite) { + if (!f) + continue; + if (!f->pMonitor || !f->buffer) { - framesToRemove.push_back(f); + framesToRemove.emplace_back(f); continue; } @@ -425,10 +428,10 @@ void CScreencopyProtocol::onOutputCommit(CMonitor* pMonitor) { f->client->lastFrame.reset(); ++f->client->frameCounter; - framesToRemove.push_back(f); + framesToRemove.emplace_back(f); } for (auto const& f : framesToRemove) { - destroyResource(f.get()); + std::erase(m_vFramesAwaitingWrite, f); } } diff --git a/src/protocols/Screencopy.hpp b/src/protocols/Screencopy.hpp index cbc56edb..e121d0fd 100644 --- a/src/protocols/Screencopy.hpp +++ b/src/protocols/Screencopy.hpp @@ -54,7 +54,7 @@ class CScreencopyFrame { bool good(); - SP self; + WP self; WP client; private: @@ -92,7 +92,7 @@ class CScreencopyProtocol : public IWaylandProtocol { private: std::vector> m_vFrames; - std::vector> m_vFramesAwaitingWrite; + std::vector> m_vFramesAwaitingWrite; std::vector> m_vClients; SP m_pSoftwareCursorTimer; diff --git a/src/protocols/ToplevelExport.cpp b/src/protocols/ToplevelExport.cpp index b28a827a..66df5926 100644 --- a/src/protocols/ToplevelExport.cpp +++ b/src/protocols/ToplevelExport.cpp @@ -354,12 +354,12 @@ void CToplevelExportProtocol::bindManager(wl_client* client, void* data, uint32_ void CToplevelExportProtocol::destroyResource(CToplevelExportClient* client) { std::erase_if(m_vClients, [&](const auto& other) { return other.get() == client; }); std::erase_if(m_vFrames, [&](const auto& other) { return other->client.get() == client; }); - std::erase_if(m_vFramesAwaitingWrite, [&](const auto& other) { return other->client.get() == client; }); + std::erase_if(m_vFramesAwaitingWrite, [&](const auto& other) { return !other || other->client.get() == client; }); } void CToplevelExportProtocol::destroyResource(CToplevelExportFrame* frame) { std::erase_if(m_vFrames, [&](const auto& other) { return other.get() == frame; }); - std::erase_if(m_vFramesAwaitingWrite, [&](const auto& other) { return other.get() == frame; }); + std::erase_if(m_vFramesAwaitingWrite, [&](const auto& other) { return !other || other.get() == frame; }); } void CToplevelExportProtocol::onOutputCommit(CMonitor* pMonitor) { @@ -370,11 +370,17 @@ void CToplevelExportProtocol::onOutputCommit(CMonitor* pMonitor) { // share frame if correct output for (auto const& f : m_vFramesAwaitingWrite) { - if (!f->pWindow || !validMapped(f->pWindow)) { - framesToRemove.push_back(f); + if (!f) + continue; + + if (!validMapped(f->pWindow)) { + framesToRemove.emplace_back(f); continue; } + if (!f->pWindow) + continue; + const auto PWINDOW = f->pWindow; if (pMonitor != g_pCompositor->getMonitorFromID(PWINDOW->m_iMonitorID)) @@ -394,7 +400,7 @@ void CToplevelExportProtocol::onOutputCommit(CMonitor* pMonitor) { } for (auto const& f : framesToRemove) { - destroyResource(f.get()); + std::erase(m_vFramesAwaitingWrite, f); } } diff --git a/src/protocols/ToplevelExport.hpp b/src/protocols/ToplevelExport.hpp index 638b69f0..9686431b 100644 --- a/src/protocols/ToplevelExport.hpp +++ b/src/protocols/ToplevelExport.hpp @@ -45,7 +45,7 @@ class CToplevelExportFrame { bool good(); - SP self; + WP self; WP client; private: @@ -85,7 +85,7 @@ class CToplevelExportProtocol : IWaylandProtocol { private: std::vector> m_vClients; std::vector> m_vFrames; - std::vector> m_vFramesAwaitingWrite; + std::vector> m_vFramesAwaitingWrite; void shareFrame(CToplevelExportFrame* frame); bool copyFrameDmabuf(CToplevelExportFrame* frame, timespec* now); diff --git a/subprojects/hyprland-protocols b/subprojects/hyprland-protocols index e06482e0..c7c3f4cd 160000 --- a/subprojects/hyprland-protocols +++ b/subprojects/hyprland-protocols @@ -1 +1 @@ -Subproject commit e06482e0e611130cd1929f75e8c1cf679e57d161 +Subproject commit c7c3f4cd0faed21fc90ba6bd06fe4f3e0e057ea8 From 4711796d3800f1a6673eccbd50e8e8a02bb0fd85 Mon Sep 17 00:00:00 2001 From: Vaxry Date: Tue, 8 Oct 2024 09:54:25 +0100 Subject: [PATCH 0489/2181] config: give simple help for super+q not working only on default config :P --- src/config/ConfigManager.cpp | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/config/ConfigManager.cpp b/src/config/ConfigManager.cpp index 2ce07ff0..018deaa7 100644 --- a/src/config/ConfigManager.cpp +++ b/src/config/ConfigManager.cpp @@ -867,8 +867,10 @@ void CConfigManager::postConfigReload(const Hyprlang::CParseResult& result) { if (result.error && !std::any_cast(m_pConfig->getConfigValue("debug:suppress_errors"))) g_pHyprError->queueCreate(result.getError(), CColor(1.0, 50.0 / 255.0, 50.0 / 255.0, 1.0)); else if (std::any_cast(m_pConfig->getConfigValue("autogenerated")) == 1) - g_pHyprError->queueCreate("Warning: You're using an autogenerated config! (config file: " + getMainConfigPath() + " )\nSUPER+Q -> kitty\nSUPER+M -> exit Hyprland", - CColor(1.0, 1.0, 70.0 / 255.0, 1.0)); + g_pHyprError->queueCreate( + "Warning: You're using an autogenerated config! (config file: " + getMainConfigPath() + + " )\nSUPER+Q -> kitty (if it doesn't launch, make sure it's installed or choose a different terminal in the config)\nSUPER+M -> exit Hyprland", + CColor(1.0, 1.0, 70.0 / 255.0, 1.0)); else if (*PENABLEEXPLICIT != prevEnabledExplicit) g_pHyprError->queueCreate("Warning: You changed the render:explicit_sync option, this requires you to restart Hyprland.", CColor(0.9, 0.76, 0.221, 1.0)); else From 45e82199fb29f422ebbbfe06ce03022dfb6d645e Mon Sep 17 00:00:00 2001 From: Aqa-Ib Date: Tue, 8 Oct 2024 12:20:41 +0200 Subject: [PATCH 0490/2181] layout: add drag_into_group to control merging dragging windows (#8004) --- src/config/ConfigDescriptions.hpp | 6 ++ src/config/ConfigManager.cpp | 1 + src/layout/IHyprLayout.cpp | 65 +++++++++++++------ .../decorations/CHyprGroupBarDecoration.cpp | 16 +++-- 4 files changed, 63 insertions(+), 25 deletions(-) diff --git a/src/config/ConfigDescriptions.hpp b/src/config/ConfigDescriptions.hpp index 385d4e59..2ca230be 100644 --- a/src/config/ConfigDescriptions.hpp +++ b/src/config/ConfigDescriptions.hpp @@ -778,6 +778,12 @@ inline static const std::vector CONFIG_OPTIONS = { .type = CONFIG_OPTION_BOOL, .data = SConfigOptionDescription::SBoolData{true}, }, + SConfigOptionDescription{ + .value = "group:drag_into_group", + .description = "whether dragging a window into a unlocked group will merge them. Options: 0 (disabled), 1 (enabled), 2 (only when dragging into the groupbar)", + .type = CONFIG_OPTION_CHOICE, + .data = SConfigOptionDescription::SChoiceData{0, "disabled,enabled,only when dragging into the groupbar"}, + }, /* * group:groupbar: diff --git a/src/config/ConfigManager.cpp b/src/config/ConfigManager.cpp index 018deaa7..9a5283fa 100644 --- a/src/config/ConfigManager.cpp +++ b/src/config/ConfigManager.cpp @@ -378,6 +378,7 @@ CConfigManager::CConfigManager() { m_pConfig->addConfigValue("group:focus_removed_window", Hyprlang::INT{1}); m_pConfig->addConfigValue("group:merge_groups_on_drag", Hyprlang::INT{1}); m_pConfig->addConfigValue("group:auto_group", Hyprlang::INT{1}); + m_pConfig->addConfigValue("group:drag_into_group", Hyprlang::INT{1}); m_pConfig->addConfigValue("group:groupbar:enabled", Hyprlang::INT{1}); m_pConfig->addConfigValue("group:groupbar:font_family", {STRVAL_EMPTY}); m_pConfig->addConfigValue("group:groupbar:font_size", Hyprlang::INT{8}); diff --git a/src/layout/IHyprLayout.cpp b/src/layout/IHyprLayout.cpp index f090e87d..f249d2b5 100644 --- a/src/layout/IHyprLayout.cpp +++ b/src/layout/IHyprLayout.cpp @@ -193,17 +193,7 @@ bool IHyprLayout::onWindowCreatedAutoGroup(PHLWINDOW pWindow) { && pWindow->canBeGroupedInto(OPENINGON) // check if the new window can be grouped into OPENINGON && !g_pXWaylandManager->shouldBeFloated(pWindow)) { // don't group XWayland windows that should be floated. - switch (pWindow->m_bIsFloating) { - case false: - if (OPENINGON->m_bIsFloating) - pWindow->m_bIsFloating = true; - break; - - case true: - if (!OPENINGON->m_bIsFloating) - pWindow->m_bIsFloating = false; - break; - } + pWindow->m_bIsFloating = OPENINGON->m_bIsFloating; // match the floating state static auto USECURRPOS = CConfigValue("group:insert_after_current"); (*USECURRPOS ? OPENINGON : OPENINGON->getGroupTail())->insertWindowToGroup(pWindow); @@ -335,21 +325,47 @@ void IHyprLayout::onEndDragWindow() { g_pInputManager->currentlyDraggedWindow.reset(); g_pInputManager->m_bWasDraggingWindow = true; - if (DRAGGINGWINDOW->m_bDraggingTiled) { - DRAGGINGWINDOW->m_bIsFloating = false; - g_pInputManager->refocus(); - changeWindowFloatingMode(DRAGGINGWINDOW); - DRAGGINGWINDOW->m_vLastFloatingSize = m_vDraggingWindowOriginalFloatSize; - } else if (g_pInputManager->dragMode == MBIND_MOVE) { + if (g_pInputManager->dragMode == MBIND_MOVE) { g_pHyprRenderer->damageWindow(DRAGGINGWINDOW); const auto MOUSECOORDS = g_pInputManager->getMouseCoordsInternal(); - PHLWINDOW pWindow = g_pCompositor->vectorToWindowUnified(MOUSECOORDS, RESERVED_EXTENTS | INPUT_EXTENTS | ALLOW_FLOATING | FLOATING_ONLY, DRAGGINGWINDOW); + PHLWINDOW pWindow = g_pCompositor->vectorToWindowUnified(MOUSECOORDS, RESERVED_EXTENTS | INPUT_EXTENTS | ALLOW_FLOATING, DRAGGINGWINDOW); if (pWindow) { if (pWindow->checkInputOnDecos(INPUT_TYPE_DRAG_END, MOUSECOORDS, DRAGGINGWINDOW)) return; - if (pWindow->m_sGroupData.pNextWindow.lock() && DRAGGINGWINDOW->canBeGroupedInto(pWindow)) { + bool denied = false; + if (!pWindow->m_bIsFloating && !DRAGGINGWINDOW->m_bDraggingTiled) + denied = true; + + static auto PDRAGINTOGROUP = CConfigValue("group:drag_into_group"); + if (pWindow->m_sGroupData.pNextWindow.lock() && DRAGGINGWINDOW->canBeGroupedInto(pWindow) && *PDRAGINTOGROUP == 1 && !denied) { + if (DRAGGINGWINDOW->m_bDraggingTiled) { + changeWindowFloatingMode(DRAGGINGWINDOW); + DRAGGINGWINDOW->m_vLastFloatingSize = m_vDraggingWindowOriginalFloatSize; + DRAGGINGWINDOW->m_bDraggingTiled = false; + } + + if (DRAGGINGWINDOW->m_sGroupData.pNextWindow.lock()) { + std::vector members; + PHLWINDOW curr = DRAGGINGWINDOW->getGroupHead(); + do { + members.push_back(curr); + curr = curr->m_sGroupData.pNextWindow.lock(); + } while (curr != members[0]); + + for (auto it = members.begin(); it != members.end(); ++it) { + (*it)->m_bIsFloating = pWindow->m_bIsFloating; // match the floating state of group members + if (pWindow->m_bIsFloating) + (*it)->m_vRealSize = pWindow->m_vRealSize.goal(); // match the size of group members + } + } + + DRAGGINGWINDOW->m_bIsFloating = pWindow->m_bIsFloating; // match the floating state of the window + + if (pWindow->m_bIsFloating) + g_pXWaylandManager->setWindowSize(DRAGGINGWINDOW, pWindow->m_vRealSize.goal()); // match the size of the window + static auto USECURRPOS = CConfigValue("group:insert_after_current"); (*USECURRPOS ? pWindow : pWindow->getGroupTail())->insertWindowToGroup(DRAGGINGWINDOW); pWindow->setGroupCurrent(DRAGGINGWINDOW); @@ -361,6 +377,13 @@ void IHyprLayout::onEndDragWindow() { } } + if (DRAGGINGWINDOW->m_bDraggingTiled) { + DRAGGINGWINDOW->m_bIsFloating = false; + g_pInputManager->refocus(); + changeWindowFloatingMode(DRAGGINGWINDOW); + DRAGGINGWINDOW->m_vLastFloatingSize = m_vDraggingWindowOriginalFloatSize; + } + g_pHyprRenderer->damageWindow(DRAGGINGWINDOW); g_pCompositor->focusWindow(DRAGGINGWINDOW); @@ -553,10 +576,10 @@ void IHyprLayout::changeWindowFloatingMode(PHLWINDOW pWindow) { pWindow->m_vLastFloatingSize = PSAVEDSIZE; - // move to narnia because we don't wanna find our own node. onWindowCreated should apply the coords back. + // move to narnia because we don't wanna find our own node. onWindowCreatedTiling should apply the coords back. pWindow->m_vPosition = Vector2D(-999999, -999999); - onWindowCreated(pWindow); + onWindowCreatedTiling(pWindow); pWindow->m_vRealPosition.setValue(PSAVEDPOS); pWindow->m_vRealSize.setValue(PSAVEDSIZE); diff --git a/src/render/decorations/CHyprGroupBarDecoration.cpp b/src/render/decorations/CHyprGroupBarDecoration.cpp index 4cdb9043..ef6c81e6 100644 --- a/src/render/decorations/CHyprGroupBarDecoration.cpp +++ b/src/render/decorations/CHyprGroupBarDecoration.cpp @@ -402,8 +402,9 @@ bool CHyprGroupBarDecoration::onBeginWindowDragOnDeco(const Vector2D& pos) { } bool CHyprGroupBarDecoration::onEndWindowDragOnDeco(const Vector2D& pos, PHLWINDOW pDraggedWindow) { - static auto PSTACKED = CConfigValue("group:groupbar:stacked"); - if (!pDraggedWindow->canBeGroupedInto(m_pWindow.lock())) + static auto PSTACKED = CConfigValue("group:groupbar:stacked"); + static auto PDRAGINTOGROUP = CConfigValue("group:drag_into_group"); + if (!pDraggedWindow->canBeGroupedInto(m_pWindow.lock()) || (*PDRAGINTOGROUP != 1 && *PDRAGINTOGROUP != 2)) return false; const float BARRELATIVE = *PSTACKED ? pos.y - assignedBoxGlobal().y - (m_fBarHeight + BAR_PADDING_OUTER_VERT) / 2 : pos.x - assignedBoxGlobal().x - m_fBarWidth / 2; @@ -435,6 +436,9 @@ bool CHyprGroupBarDecoration::onEndWindowDragOnDeco(const Vector2D& pos, PHLWIND // restores the group for (auto it = members.begin(); it != members.end(); ++it) { + (*it)->m_bIsFloating = pWindowInsertAfter->m_bIsFloating; // match the floating state of group members + if (pWindowInsertAfter->m_bIsFloating) + (*it)->m_vRealSize = pWindowInsertAfter->m_vRealSize.goal(); // match the size of group members if (std::next(it) != members.end()) (*it)->m_sGroupData.pNextWindow = *std::next(it); else @@ -442,9 +446,13 @@ bool CHyprGroupBarDecoration::onEndWindowDragOnDeco(const Vector2D& pos, PHLWIND } members[0]->m_sGroupData.head = true; members[0]->m_sGroupData.locked = WASLOCKED; - } else { + } else g_pLayoutManager->getCurrentLayout()->onWindowRemoved(pDraggedWindow); - } + + pDraggedWindow->m_bIsFloating = pWindowInsertAfter->m_bIsFloating; // match the floating state of the window + + if (pWindowInsertAfter->m_bIsFloating) + g_pXWaylandManager->setWindowSize(pDraggedWindow, pWindowInsertAfter->m_vRealSize.goal()); // match the size of the window pWindowInsertAfter->insertWindowToGroup(pDraggedWindow); From b3a7e3109bf2b7b4422424471130197dc08baeb1 Mon Sep 17 00:00:00 2001 From: davc0n Date: Tue, 8 Oct 2024 12:42:51 +0200 Subject: [PATCH 0491/2181] misc: refactor version command (#8027) Fixes a minor spacing issue if git status is not dirty. Additionally now should be easier to extend it eventually. --- src/main.cpp | 15 ++++++++++++--- 1 file changed, 12 insertions(+), 3 deletions(-) diff --git a/src/main.cpp b/src/main.cpp index 279e1ce1..57bb5507 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -116,11 +116,20 @@ int main(int argc, char** argv) { return 0; } else if (it->compare("-v") == 0 || it->compare("--version") == 0) { + auto result = "Hyprland, built from branch " + std::string(GIT_BRANCH) + " at commit " + GIT_COMMIT_HASH; + auto dirty = std::string(GIT_DIRTY); + if (!dirty.empty()) + result += " " + dirty; + auto commitMsg = trim(GIT_COMMIT_MESSAGE); std::replace(commitMsg.begin(), commitMsg.end(), '#', ' '); - std::string result = "Hyprland, built from branch " + std::string(GIT_BRANCH) + " at commit " + GIT_COMMIT_HASH + " " + GIT_DIRTY + " (" + commitMsg + - ").\nDate: " + GIT_COMMIT_DATE + "\nTag: " + GIT_TAG + ", commits: " + GIT_COMMITS + std::string{"\nbuilt against aquamarine "} + AQUAMARINE_VERSION + "\n" + - "\n\nflags: (if any)\n"; + result += " (" + commitMsg + ")."; + + result += "\nDate: " + std::string(GIT_COMMIT_DATE); + result += "\nTag: " + std::string(GIT_TAG) + ", commits: " + std::string(GIT_COMMITS); + result += "\nbuilt against aquamarine " + std::string(AQUAMARINE_VERSION); + + result += "\n\nflags: (if any)\n"; #ifdef LEGACY_RENDERER result += "legacyrenderer\n"; From e0cfbec66b97edb2957508152f32e77a1b181afc Mon Sep 17 00:00:00 2001 From: vaxerski Date: Tue, 8 Oct 2024 13:15:53 +0100 Subject: [PATCH 0492/2181] keybinds: fixup xkb_states for resolve_by_sym fixes #7750 --- src/devices/IKeyboard.cpp | 10 ++++++++++ src/devices/IKeyboard.hpp | 5 +++-- src/managers/KeybindManager.cpp | 2 +- 3 files changed, 14 insertions(+), 3 deletions(-) diff --git a/src/devices/IKeyboard.cpp b/src/devices/IKeyboard.cpp index 13440169..3300f252 100644 --- a/src/devices/IKeyboard.cpp +++ b/src/devices/IKeyboard.cpp @@ -178,13 +178,18 @@ void IKeyboard::updateXKBTranslationState(xkb_keymap* const keymap) { if (xkbState) xkb_state_unref(xkbState); + if (xkbSymState) + xkb_state_unref(xkbSymState); + xkbState = nullptr; xkbStaticState = nullptr; + xkbSymState = nullptr; if (keymap) { Debug::log(LOG, "Updating keyboard {:x}'s translation state from a provided keymap", (uintptr_t)this); xkbStaticState = xkb_state_new(keymap); xkbState = xkb_state_new(keymap); + xkbSymState = xkb_state_new(keymap); return; } @@ -230,6 +235,7 @@ void IKeyboard::updateXKBTranslationState(xkb_keymap* const keymap) { xkbState = xkb_state_new(KEYMAP); xkbStaticState = xkb_state_new(KEYMAP); + xkbSymState = xkb_state_new(KEYMAP); xkb_keymap_unref(KEYMAP); xkb_context_unref(PCONTEXT); @@ -252,6 +258,7 @@ void IKeyboard::updateXKBTranslationState(xkb_keymap* const keymap) { xkbState = xkb_state_new(NEWKEYMAP); xkbStaticState = xkb_state_new(NEWKEYMAP); + xkbSymState = xkb_state_new(NEWKEYMAP); xkb_keymap_unref(NEWKEYMAP); xkb_context_unref(PCONTEXT); @@ -332,6 +339,9 @@ void IKeyboard::updateModifiers(uint32_t depressed, uint32_t latched, uint32_t l xkb_state_update_mask(xkbState, depressed, latched, locked, 0, 0, group); + if (xkbSymState) + xkb_state_update_mask(xkbSymState, 0, 0, 0, 0, 0, group); + if (!updateModifiersState()) return; diff --git a/src/devices/IKeyboard.hpp b/src/devices/IKeyboard.hpp index 759b2f58..76d2c31b 100644 --- a/src/devices/IKeyboard.hpp +++ b/src/devices/IKeyboard.hpp @@ -82,8 +82,9 @@ class IKeyboard : public IHID { bool keymapOverridden = false; xkb_layout_index_t activeLayout = 0; - xkb_state * xkbState = nullptr, *xkbStaticState /* Static state: never gets modifiers or layout changes sent, used for keybinds. */ = nullptr; - xkb_keymap* xkbKeymap = nullptr; + xkb_state * xkbState = nullptr, *xkbStaticState /* Static state: never gets modifiers or layout changes sent, used for keybinds. */ = nullptr, + *xkbSymState = nullptr /* Same as static but gets layouts */; + xkb_keymap* xkbKeymap = nullptr; struct { uint32_t depressed = 0, latched = 0, locked = 0, group = 0; diff --git a/src/managers/KeybindManager.cpp b/src/managers/KeybindManager.cpp index cd47bf71..d893e258 100644 --- a/src/managers/KeybindManager.cpp +++ b/src/managers/KeybindManager.cpp @@ -376,7 +376,7 @@ bool CKeybindManager::onKeyEvent(std::any event, SP pKeyboard) { const auto KEYCODE = e.keycode + 8; // Because to xkbcommon it's +8 from libinput - const xkb_keysym_t keysym = xkb_state_key_get_one_sym(pKeyboard->resolveBindsBySym ? pKeyboard->xkbState : m_pXKBTranslationState, KEYCODE); + const xkb_keysym_t keysym = xkb_state_key_get_one_sym(pKeyboard->resolveBindsBySym ? pKeyboard->xkbSymState : m_pXKBTranslationState, KEYCODE); const xkb_keysym_t internalKeysym = xkb_state_key_get_one_sym(pKeyboard->xkbState, KEYCODE); if (handleInternalKeybinds(internalKeysym)) From 1bf63dfdcd76c09137b4647f9af2c5ebc9fc6e34 Mon Sep 17 00:00:00 2001 From: Vaxry <43317083+vaxerski@users.noreply.github.com> Date: Tue, 8 Oct 2024 16:59:15 +0100 Subject: [PATCH 0493/2181] protocols: Add support for hyprland-ctm-control-v1 (#8023) * initial ctm support * flake.lock: update * Meson: bump required versions and add ctm proto --------- Co-authored-by: Mihai Fufezan --- CMakeLists.txt | 6 ++- flake.lock | 36 ++++++------- meson.build | 2 +- protocols/meson.build | 3 +- src/helpers/Monitor.cpp | 6 +++ src/helpers/Monitor.hpp | 5 ++ src/managers/ProtocolManager.cpp | 3 ++ src/protocols/CTMControl.cpp | 86 ++++++++++++++++++++++++++++++++ src/protocols/CTMControl.hpp | 44 ++++++++++++++++ src/render/Renderer.cpp | 5 ++ 10 files changed, 174 insertions(+), 22 deletions(-) create mode 100644 src/protocols/CTMControl.cpp create mode 100644 src/protocols/CTMControl.hpp diff --git a/CMakeLists.txt b/CMakeLists.txt index 1bac29ab..4de449dc 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -100,7 +100,7 @@ find_package(OpenGL REQUIRED COMPONENTS ${GLES_VERSION}) pkg_check_modules(hyprctl_deps REQUIRED IMPORTED_TARGET hyprutils>=0.2.1) -pkg_check_modules(aquamarine_dep REQUIRED IMPORTED_TARGET aquamarine) +pkg_check_modules(aquamarine_dep REQUIRED IMPORTED_TARGET aquamarine>=0.4.2) add_compile_definitions(AQUAMARINE_VERSION="${aquamarine_dep_VERSION}") @@ -274,7 +274,7 @@ endfunction() target_link_libraries(Hyprland OpenGL::EGL OpenGL::GL Threads::Threads) -pkg_check_modules(hyprland_protocols_dep hyprland-protocols>=0.2.0) +pkg_check_modules(hyprland_protocols_dep hyprland-protocols>=0.4.0) if(hyprland_protocols_dep_FOUND) pkg_get_variable(HYPRLAND_PROTOCOLS hyprland-protocols pkgdatadir) message(STATUS "hyprland-protocols dependency set to ${HYPRLAND_PROTOCOLS}") @@ -301,6 +301,8 @@ protocolnew("protocols" "wlr-data-control-unstable-v1" true) protocolnew("${HYPRLAND_PROTOCOLS}/protocols" "hyprland-focus-grab-v1" true) protocolnew("protocols" "wlr-layer-shell-unstable-v1" true) protocolnew("protocols" "wayland-drm" true) +protocolnew("${HYPRLAND_PROTOCOLS}/protocols" "hyprland-ctm-control-v1" true) + protocolnew("staging/tearing-control" "tearing-control-v1" false) protocolnew("staging/fractional-scale" "fractional-scale-v1" false) protocolnew("unstable/xdg-output" "xdg-output-unstable-v1" false) diff --git a/flake.lock b/flake.lock index 85069a74..de9a4dce 100644 --- a/flake.lock +++ b/flake.lock @@ -16,11 +16,11 @@ ] }, "locked": { - "lastModified": 1727261104, - "narHash": "sha256-rxDI7WrxIRV9it9mDCHcLa7xQykf1JloXnoXr5xQ8zI=", + "lastModified": 1728326504, + "narHash": "sha256-dQXAj+4d6neY7ldCiH6gNym3upP49PVxRzEPxXlD9Aw=", "owner": "hyprwm", "repo": "aquamarine", - "rev": "b82fdaff917582a9d568969e15e61b398c71e990", + "rev": "65dd97b5d21e917295159bbef1d52e06963f4eb0", "type": "github" }, "original": { @@ -79,11 +79,11 @@ ] }, "locked": { - "lastModified": 1727532803, - "narHash": "sha256-ZaZ7h7PY8mQc4vtGmVqWLAq9CAO02gHMyNR5yY8zDmM=", + "lastModified": 1727821604, + "narHash": "sha256-hNw5J6xatedqytYowx0mJKgctjA4lQARZFdgnzM2RpM=", "owner": "hyprwm", "repo": "hyprcursor", - "rev": "b98726e431d4d3ed58bd58bee1047cdb81cec69f", + "rev": "d60e1e01e6e6633ef1c87148b9137cc1dd39263d", "type": "github" }, "original": { @@ -102,11 +102,11 @@ ] }, "locked": { - "lastModified": 1727451107, - "narHash": "sha256-qV9savtHwmZUa0eJE294WYJjKPGB2+bJhwByFShsVyo=", + "lastModified": 1728345020, + "narHash": "sha256-xGbkc7U/Roe0/Cv3iKlzijIaFBNguasI31ynL2IlEoM=", "owner": "hyprwm", "repo": "hyprland-protocols", - "rev": "6b3261ee13a6d2b99de79a31d352f6996e35bde3", + "rev": "a7c183800e74f337753de186522b9017a07a8cee", "type": "github" }, "original": { @@ -128,11 +128,11 @@ ] }, "locked": { - "lastModified": 1725997860, - "narHash": "sha256-d/rZ/fHR5l1n7PeyLw0StWMNLXVU9c4HFyfskw568so=", + "lastModified": 1728168612, + "narHash": "sha256-AnB1KfiXINmuiW7BALYrKqcjCnsLZPifhb/7BsfPbns=", "owner": "hyprwm", "repo": "hyprlang", - "rev": "dfeb5811dd6485490cce18d6cc1e38a055eea876", + "rev": "f054f2e44d6a0b74607a6bc0f52dba337a3db38e", "type": "github" }, "original": { @@ -189,11 +189,11 @@ }, "nixpkgs": { "locked": { - "lastModified": 1727348695, - "narHash": "sha256-J+PeFKSDV+pHL7ukkfpVzCOO7mBSrrpJ3svwBFABbhI=", + "lastModified": 1728018373, + "narHash": "sha256-NOiTvBbRLIOe5F6RbHaAh6++BNjsb149fGZd1T4+KBg=", "owner": "NixOS", "repo": "nixpkgs", - "rev": "1925c603f17fc89f4c8f6bf6f631a802ad85d784", + "rev": "bc947f541ae55e999ffdb4013441347d83b00feb", "type": "github" }, "original": { @@ -293,11 +293,11 @@ ] }, "locked": { - "lastModified": 1727524473, - "narHash": "sha256-1DGktDtSWIJpnDbVoj/qpvJSH5zg6JbOfuh6xqZMap0=", + "lastModified": 1728166987, + "narHash": "sha256-w6dVTguAn9zJ+7aPOhBQgDz8bn6YZ7b56cY8Kg5HJRI=", "owner": "hyprwm", "repo": "xdg-desktop-portal-hyprland", - "rev": "7e500e679ede40e79cf2d89b5f5fa3e34923bd26", + "rev": "fb9c8d665af0588bb087f97d0f673ddf0d501787", "type": "github" }, "original": { diff --git a/meson.build b/meson.build index 3545f46a..e9bbb99d 100644 --- a/meson.build +++ b/meson.build @@ -30,7 +30,7 @@ if cpp_compiler.check_header('execinfo.h') add_project_arguments('-DHAS_EXECINFO', language: 'cpp') endif -aquamarine = dependency('aquamarine') +aquamarine = dependency('aquamarine', version: '>=0.4.2') add_project_arguments(['-DAQUAMARINE_VERSION="@0@"'.format(aquamarine.version())], language: 'cpp') xcb_dep = dependency('xcb', required: get_option('xwayland')) diff --git a/protocols/meson.build b/protocols/meson.build index 3fa2ef2f..2c0d06d1 100644 --- a/protocols/meson.build +++ b/protocols/meson.build @@ -7,7 +7,7 @@ wayland_protos = dependency( hyprland_protos = dependency( 'hyprland-protocols', - version: '>=0.2', + version: '>=0.4', fallback: 'hyprland-protocols', ) @@ -36,6 +36,7 @@ protocols = [ hyprland_protocol_dir / 'protocols/hyprland-global-shortcuts-v1.xml', hyprland_protocol_dir / 'protocols/hyprland-toplevel-export-v1.xml', hyprland_protocol_dir / 'protocols/hyprland-focus-grab-v1.xml', + hyprland_protocol_dir / 'protocols/hyprland-ctm-control-v1.xml', wayland_protocol_dir / 'staging/tearing-control/tearing-control-v1.xml', wayland_protocol_dir / 'staging/fractional-scale/fractional-scale-v1.xml', wayland_protocol_dir / 'unstable/xdg-output/xdg-output-unstable-v1.xml', diff --git a/src/helpers/Monitor.cpp b/src/helpers/Monitor.cpp index c6cef41f..f3e7de4e 100644 --- a/src/helpers/Monitor.cpp +++ b/src/helpers/Monitor.cpp @@ -813,6 +813,12 @@ void CMonitor::scheduleDone() { }); } +void CMonitor::setCTM(const Mat3x3& ctm_) { + ctm = ctm_; + ctmUpdated = true; + g_pCompositor->scheduleFrameForMonitor(this, Aquamarine::IOutput::scheduleFrameReason::AQ_SCHEDULE_NEEDS_FRAME); +} + bool CMonitor::attemptDirectScanout() { if (!mirrors.empty() || isMirror() || g_pHyprRenderer->m_bDirectScanoutBlocked) return false; // do not DS if this monitor is being mirrored. Will break the functionality. diff --git a/src/helpers/Monitor.hpp b/src/helpers/Monitor.hpp index 2a2edab6..f5068dba 100644 --- a/src/helpers/Monitor.hpp +++ b/src/helpers/Monitor.hpp @@ -131,6 +131,10 @@ class CMonitor { CMonitor* pMirrorOf = nullptr; std::vector mirrors; + // ctm + Mat3x3 ctm = Mat3x3::identity(); + bool ctmUpdated = false; + // for tearing PHLWINDOWREF solitaryClient; @@ -179,6 +183,7 @@ class CMonitor { CBox logicalBox(); void scheduleDone(); bool attemptDirectScanout(); + void setCTM(const Mat3x3& ctm); bool m_bEnabled = false; bool m_bRenderingInitPassed = false; diff --git a/src/managers/ProtocolManager.cpp b/src/managers/ProtocolManager.cpp index 6366eefe..25a34657 100644 --- a/src/managers/ProtocolManager.cpp +++ b/src/managers/ProtocolManager.cpp @@ -46,6 +46,7 @@ #include "../protocols/XDGDialog.hpp" #include "../protocols/SinglePixel.hpp" #include "../protocols/SecurityContext.hpp" +#include "../protocols/CTMControl.hpp" #include "../protocols/core/Seat.hpp" #include "../protocols/core/DataDevice.hpp" @@ -157,6 +158,7 @@ CProtocolManager::CProtocolManager() { PROTO::xdgDialog = std::make_unique(&xdg_dialog_v1_interface, 1, "XDGDialog"); PROTO::singlePixel = std::make_unique(&wp_single_pixel_buffer_manager_v1_interface, 1, "SinglePixel"); PROTO::securityContext = std::make_unique(&wp_security_context_manager_v1_interface, 1, "SecurityContext"); + PROTO::ctm = std::make_unique(&hyprland_ctm_control_manager_v1_interface, 1, "CTMControl"); for (auto const& b : g_pCompositor->m_pAqBackend->getImplementations()) { if (b->type() != Aquamarine::AQ_BACKEND_DRM) @@ -229,6 +231,7 @@ CProtocolManager::~CProtocolManager() { PROTO::xdgDialog.reset(); PROTO::singlePixel.reset(); PROTO::securityContext.reset(); + PROTO::ctm.reset(); PROTO::lease.reset(); PROTO::sync.reset(); diff --git a/src/protocols/CTMControl.cpp b/src/protocols/CTMControl.cpp new file mode 100644 index 00000000..f2a54c6f --- /dev/null +++ b/src/protocols/CTMControl.cpp @@ -0,0 +1,86 @@ +#include "CTMControl.hpp" +#include "../Compositor.hpp" +#include "core/Output.hpp" + +CHyprlandCTMControlResource::CHyprlandCTMControlResource(SP resource_) : resource(resource_) { + if (!good()) + return; + + resource->setDestroy([this](CHyprlandCtmControlManagerV1* pMgr) { PROTO::ctm->destroyResource(this); }); + resource->setOnDestroy([this](CHyprlandCtmControlManagerV1* pMgr) { PROTO::ctm->destroyResource(this); }); + + resource->setSetCtmForOutput([this](CHyprlandCtmControlManagerV1* r, wl_resource* output, wl_fixed_t mat0, wl_fixed_t mat1, wl_fixed_t mat2, wl_fixed_t mat3, wl_fixed_t mat4, + wl_fixed_t mat5, wl_fixed_t mat6, wl_fixed_t mat7, wl_fixed_t mat8) { + const auto OUTPUTRESOURCE = CWLOutputResource::fromResource(output); + + if (!OUTPUTRESOURCE) + return; // ?! + + const auto PMONITOR = OUTPUTRESOURCE->monitor.lock(); + + if (!PMONITOR) + return; // ?!?! + + const std::array MAT = {wl_fixed_to_double(mat0), wl_fixed_to_double(mat1), wl_fixed_to_double(mat2), wl_fixed_to_double(mat3), wl_fixed_to_double(mat4), + wl_fixed_to_double(mat5), wl_fixed_to_double(mat6), wl_fixed_to_double(mat7), wl_fixed_to_double(mat8)}; + + for (auto& el : MAT) { + if (el < 0.F) { + resource->error(HYPRLAND_CTM_CONTROL_MANAGER_V1_ERROR_INVALID_MATRIX, "a matrix component was < 0"); + return; + } + } + + ctms[PMONITOR->szName] = MAT; + + LOGM(LOG, "CTM set for output {}: {}", PMONITOR->szName, ctms.at(PMONITOR->szName).toString()); + }); + + resource->setCommit([this](CHyprlandCtmControlManagerV1* r) { + LOGM(LOG, "Committing ctms to outputs"); + + for (auto& m : g_pCompositor->m_vMonitors) { + if (!ctms.contains(m->szName)) { + PROTO::ctm->setCTM(m, Mat3x3::identity()); + continue; + } + + PROTO::ctm->setCTM(m, ctms.at(m->szName)); + } + }); +} + +CHyprlandCTMControlResource::~CHyprlandCTMControlResource() { + for (auto& m : g_pCompositor->m_vMonitors) { + PROTO::ctm->setCTM(m, Mat3x3::identity()); + } +} + +bool CHyprlandCTMControlResource::good() { + return resource->resource(); +} + +CHyprlandCTMControlProtocol::CHyprlandCTMControlProtocol(const wl_interface* iface, const int& ver, const std::string& name) : IWaylandProtocol(iface, ver, name) { + ; +} + +void CHyprlandCTMControlProtocol::bindManager(wl_client* client, void* data, uint32_t ver, uint32_t id) { + + const auto RESOURCE = m_vManagers.emplace_back(makeShared(makeShared(client, ver, id))); + + if (!RESOURCE->good()) { + wl_client_post_no_memory(client); + m_vManagers.pop_back(); + return; + } + + LOGM(LOG, "New CTM Manager at 0x{:x}", (uintptr_t)RESOURCE.get()); +} + +void CHyprlandCTMControlProtocol::destroyResource(CHyprlandCTMControlResource* res) { + std::erase_if(m_vManagers, [&](const auto& other) { return other.get() == res; }); +} + +void CHyprlandCTMControlProtocol::setCTM(SP monitor, const Mat3x3& ctm) { + monitor->setCTM(ctm); +} diff --git a/src/protocols/CTMControl.hpp b/src/protocols/CTMControl.hpp new file mode 100644 index 00000000..08f1b0e8 --- /dev/null +++ b/src/protocols/CTMControl.hpp @@ -0,0 +1,44 @@ +#pragma once + +#include +#include +#include +#include "WaylandProtocol.hpp" +#include "hyprland-ctm-control-v1.hpp" +#include + +class CMonitor; + +class CHyprlandCTMControlResource { + public: + CHyprlandCTMControlResource(SP resource_); + ~CHyprlandCTMControlResource(); + + bool good(); + + private: + SP resource; + + std::unordered_map ctms; +}; + +class CHyprlandCTMControlProtocol : public IWaylandProtocol { + public: + CHyprlandCTMControlProtocol(const wl_interface* iface, const int& ver, const std::string& name); + + virtual void bindManager(wl_client* client, void* data, uint32_t ver, uint32_t id); + + private: + void destroyResource(CHyprlandCTMControlResource* resource); + + void setCTM(SP monitor, const Mat3x3& ctm); + + // + std::vector> m_vManagers; + + friend class CHyprlandCTMControlResource; +}; + +namespace PROTO { + inline UP ctm; +}; \ No newline at end of file diff --git a/src/render/Renderer.cpp b/src/render/Renderer.cpp index 310d45af..f388ec37 100644 --- a/src/render/Renderer.cpp +++ b/src/render/Renderer.cpp @@ -1498,6 +1498,11 @@ bool CHyprRenderer::commitPendingAndDoExplicitSync(CMonitor* pMonitor) { if (inFD >= 0) pMonitor->output->state->setExplicitInFence(inFD); + if (pMonitor->ctmUpdated) { + pMonitor->ctmUpdated = false; + pMonitor->output->state->setCTM(pMonitor->ctm); + } + bool ok = pMonitor->state.commit(); if (!ok) { if (inFD >= 0) { From 57b632ead88b4558a53e52aa9c098d48362ee768 Mon Sep 17 00:00:00 2001 From: Vaxry Date: Tue, 8 Oct 2024 17:02:55 +0100 Subject: [PATCH 0494/2181] pointer: expand sw cursor damage box fixes #8031 just a bit, rounding errors I guess --- src/managers/PointerManager.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/managers/PointerManager.cpp b/src/managers/PointerManager.cpp index 736b629c..cc9deec7 100644 --- a/src/managers/PointerManager.cpp +++ b/src/managers/PointerManager.cpp @@ -657,7 +657,7 @@ Vector2D CPointerManager::closestValid(const Vector2D& pos) { } void CPointerManager::damageIfSoftware() { - auto b = getCursorBoxGlobal(); + auto b = getCursorBoxGlobal().expand(4); static auto PNOHW = CConfigValue("cursor:no_hardware_cursors"); From e4a26f4f1d9d30569b9e7e6c265fccfd42fa5d72 Mon Sep 17 00:00:00 2001 From: JManch <61563764+JManch@users.noreply.github.com> Date: Tue, 8 Oct 2024 17:50:06 +0100 Subject: [PATCH 0495/2181] dispatchers: allow leading whitespace in window parameter (#8016) --- src/Compositor.cpp | 37 ++++++++++++++++++++----------------- 1 file changed, 20 insertions(+), 17 deletions(-) diff --git a/src/Compositor.cpp b/src/Compositor.cpp index f00e1e34..459aca11 100644 --- a/src/Compositor.cpp +++ b/src/Compositor.cpp @@ -2445,13 +2445,31 @@ void CCompositor::scheduleFrameForMonitor(CMonitor* pMonitor, IOutput::scheduleF pMonitor->output->scheduleFrame(reason); } -PHLWINDOW CCompositor::getWindowByRegex(const std::string& regexp) { +PHLWINDOW CCompositor::getWindowByRegex(const std::string& regexp_) { + auto regexp = trim(regexp_); + if (regexp.starts_with("active")) return m_pLastWindow.lock(); + else if (regexp.starts_with("floating") || regexp.starts_with("tiled")) { + // first floating on the current ws + if (!valid(m_pLastWindow)) + return nullptr; + + const bool FLOAT = regexp.starts_with("floating"); + + for (auto const& w : m_vWindows) { + if (!w->m_bIsMapped || w->m_bIsFloating != FLOAT || w->m_pWorkspace != m_pLastWindow->m_pWorkspace || w->isHidden()) + continue; + + return w; + } + + return nullptr; + } eFocusWindowMode mode = MODE_CLASS_REGEX; - std::regex regexCheck(regexp); + std::regex regexCheck(regexp_); std::string matchCheck; if (regexp.starts_with("class:")) { regexCheck = std::regex(regexp.substr(6)); @@ -2470,21 +2488,6 @@ PHLWINDOW CCompositor::getWindowByRegex(const std::string& regexp) { } else if (regexp.starts_with("pid:")) { mode = MODE_PID; matchCheck = regexp.substr(4); - } else if (regexp.starts_with("floating") || regexp.starts_with("tiled")) { - // first floating on the current ws - if (!valid(m_pLastWindow)) - return nullptr; - - const bool FLOAT = regexp.starts_with("floating"); - - for (auto const& w : m_vWindows) { - if (!w->m_bIsMapped || w->m_bIsFloating != FLOAT || w->m_pWorkspace != m_pLastWindow->m_pWorkspace || w->isHidden()) - continue; - - return w; - } - - return nullptr; } for (auto const& w : g_pCompositor->m_vWindows) { From 613eac4603f4a15868c88a47a8ee8dcb84ee2dd3 Mon Sep 17 00:00:00 2001 From: Aqa-Ib Date: Tue, 8 Oct 2024 20:31:15 +0200 Subject: [PATCH 0496/2181] layout: remove unnecessary check after 45e8219 (#8037) --- src/layout/IHyprLayout.cpp | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/layout/IHyprLayout.cpp b/src/layout/IHyprLayout.cpp index f249d2b5..24ee13f4 100644 --- a/src/layout/IHyprLayout.cpp +++ b/src/layout/IHyprLayout.cpp @@ -186,12 +186,12 @@ bool IHyprLayout::onWindowCreatedAutoGroup(PHLWINDOW pWindow) { g_pCompositor->m_pLastWindow.lock() : g_pCompositor->getFirstWindowOnWorkspace(pWindow->workspaceID()); - if ((*PAUTOGROUP || g_pInputManager->m_bWasDraggingWindow) // check if auto_group is enabled, or, if the user is manually dragging the window into the group. - && OPENINGON // check if OPENINGON exists. - && OPENINGON != pWindow // fixes a freeze when activating togglefloat to transform a floating group into a tiled group. - && OPENINGON->m_sGroupData.pNextWindow.lock() // check if OPENINGON is a group - && pWindow->canBeGroupedInto(OPENINGON) // check if the new window can be grouped into OPENINGON - && !g_pXWaylandManager->shouldBeFloated(pWindow)) { // don't group XWayland windows that should be floated. + if (*PAUTOGROUP // check if auto_group is enabled. + && OPENINGON // check if OPENINGON exists. + && OPENINGON != pWindow // fixes a freeze when activating togglefloat to transform a floating group into a tiled group. + && OPENINGON->m_sGroupData.pNextWindow.lock() // check if OPENINGON is a group + && pWindow->canBeGroupedInto(OPENINGON) // check if the new window can be grouped into OPENINGON + && !g_pXWaylandManager->shouldBeFloated(pWindow)) { // don't group XWayland windows that should be floated. pWindow->m_bIsFloating = OPENINGON->m_bIsFloating; // match the floating state From 60308a2bb576413cbc787d4bde4f8d0e3fa3c9d6 Mon Sep 17 00:00:00 2001 From: Vaxry Date: Tue, 8 Oct 2024 20:28:30 +0100 Subject: [PATCH 0497/2181] defaultConfig: add a nofocus rule for weird X windows ref #6543 --- example/hyprland.conf | 6 +++++- src/config/defaultConfig.hpp | 6 +++++- 2 files changed, 10 insertions(+), 2 deletions(-) diff --git a/example/hyprland.conf b/example/hyprland.conf index 4adc2d40..3478bcff 100644 --- a/example/hyprland.conf +++ b/example/hyprland.conf @@ -255,4 +255,8 @@ bindl = , XF86AudioPrev, exec, playerctl previous # Example windowrule v2 # windowrulev2 = float,class:^(kitty)$,title:^(kitty)$ -windowrulev2 = suppressevent maximize, class:.* # You'll probably like this. +# Ignore maximize requests from apps. You'll probably like this. +windowrulev2 = suppressevent maximize, class:.* + +# Fix some dragging issues with XWayland +windowrulev2 = nofocus,class:^$,title:^$,xwayland:1,floating:1,fullscreen:0,pinned:0 diff --git a/src/config/defaultConfig.hpp b/src/config/defaultConfig.hpp index 5843caa3..54ce6642 100644 --- a/src/config/defaultConfig.hpp +++ b/src/config/defaultConfig.hpp @@ -268,5 +268,9 @@ bindl = , XF86AudioPrev, exec, playerctl previous # Example windowrule v2 # windowrulev2 = float,class:^(kitty)$,title:^(kitty)$ -windowrulev2 = suppressevent maximize, class:.* # You'll probably like this. +# Ignore maximize requests from apps. You'll probably like this. +windowrulev2 = suppressevent maximize, class:.* + +# Fix some dragging issues with XWayland +windowrulev2 = nofocus,class:^$,title:^$,xwayland:1,floating:1,fullscreen:0,pinned:0 )#"; From 91299f7039d80b25b3f0296d3d0f4d2059d41869 Mon Sep 17 00:00:00 2001 From: Vaxry <43317083+vaxerski@users.noreply.github.com> Date: Tue, 8 Oct 2024 21:20:25 +0100 Subject: [PATCH 0498/2181] hyprerror: make hyprerror reserve space (#8040) --- src/hyprerror/HyprError.cpp | 20 ++++++++++++++++++++ src/hyprerror/HyprError.hpp | 12 ++++++++---- src/render/Renderer.cpp | 17 +++++++++++++++++ 3 files changed, 45 insertions(+), 4 deletions(-) diff --git a/src/hyprerror/HyprError.cpp b/src/hyprerror/HyprError.cpp index bbc3a006..5f63de24 100644 --- a/src/hyprerror/HyprError.cpp +++ b/src/hyprerror/HyprError.cpp @@ -3,6 +3,9 @@ #include "../Compositor.hpp" #include "../config/ConfigValue.hpp" +#include +using namespace Hyprutils::Utils; + CHyprError::CHyprError() { m_fFadeOpacity.create(AVARTYPE_FLOAT, g_pConfigManager->getAnimationPropertyConfig("fadeIn"), AVARDAMAGE_NONE); m_fFadeOpacity.registerVar(); @@ -130,6 +133,8 @@ void CHyprError::createQueued() { } m_szQueued = ""; + m_fLastHeight = yoffset + PAD + 1; + pango_font_description_free(pangoFD); g_object_unref(layoutText); @@ -158,6 +163,8 @@ void CHyprError::createQueued() { m_cQueued = CColor(); g_pHyprRenderer->damageMonitor(PMONITOR); + + g_pHyprRenderer->arrangeLayersForMonitor(PMONITOR->ID); } void CHyprError::draw() { @@ -174,6 +181,11 @@ void CHyprError::draw() { m_pTexture->destroyTexture(); m_bIsCreated = false; m_szQueued = ""; + + for (auto& m : g_pCompositor->m_vMonitors) { + g_pHyprRenderer->arrangeLayersForMonitor(m->ID); + } + return; } else { m_fFadeOpacity.setConfig(g_pConfigManager->getAnimationPropertyConfig("fadeOut")); @@ -203,3 +215,11 @@ void CHyprError::destroy() { else m_szQueued = ""; } + +bool CHyprError::active() { + return m_bIsCreated; +} + +float CHyprError::height() { + return m_fLastHeight; +} diff --git a/src/hyprerror/HyprError.hpp b/src/hyprerror/HyprError.hpp index 8dbb4521..a553614c 100644 --- a/src/hyprerror/HyprError.hpp +++ b/src/hyprerror/HyprError.hpp @@ -11,9 +11,12 @@ class CHyprError { CHyprError(); ~CHyprError(); - void queueCreate(std::string message, const CColor& color); - void draw(); - void destroy(); + void queueCreate(std::string message, const CColor& color); + void draw(); + void destroy(); + + bool active(); + float height(); // logical private: void createQueued(); @@ -23,7 +26,8 @@ class CHyprError { bool m_bIsCreated = false; SP m_pTexture; CAnimatedVariable m_fFadeOpacity; - CBox m_bDamageBox = {0, 0, 0, 0}; + CBox m_bDamageBox = {0, 0, 0, 0}; + float m_fLastHeight = 0.F; bool m_bMonitorChanged = false; }; diff --git a/src/render/Renderer.cpp b/src/render/Renderer.cpp index f388ec37..61f94014 100644 --- a/src/render/Renderer.cpp +++ b/src/render/Renderer.cpp @@ -97,6 +97,16 @@ CHyprRenderer::CHyprRenderer() { ensureCursorRenderingMode(); }); + static auto P3 = g_pHookSystem->hookDynamic("focusedMon", [&](void* self, SCallbackInfo& info, std::any param) { + g_pEventLoopManager->doLater([this]() { + if (!g_pHyprError->active()) + return; + for (auto& m : g_pCompositor->m_vMonitors) { + arrangeLayersForMonitor(m->ID); + } + }); + }); + m_pCursorTicker = wl_event_loop_add_timer(g_pCompositor->m_sWLEventLoop, cursorTicker, nullptr); wl_event_source_timer_update(m_pCursorTicker, 500); @@ -1757,6 +1767,13 @@ void CHyprRenderer::arrangeLayersForMonitor(const MONITORID& monitor) { CBox usableArea = {PMONITOR->vecPosition.x, PMONITOR->vecPosition.y, PMONITOR->vecSize.x, PMONITOR->vecSize.y}; + if (g_pHyprError->active() && g_pCompositor->m_pLastMonitor == PMONITOR->self) { + const auto HEIGHT = g_pHyprError->height(); + PMONITOR->vecReservedTopLeft.y = HEIGHT; + usableArea.y += HEIGHT; + usableArea.h -= HEIGHT; + } + for (auto& la : PMONITOR->m_aLayerSurfaceLayers) { std::stable_sort(la.begin(), la.end(), [](const PHLLSREF& a, const PHLLSREF& b) { return a->order > b->order; }); } From 8cced091f53c92bc8de97b9d3dac20b31980af70 Mon Sep 17 00:00:00 2001 From: Vaxry Date: Tue, 8 Oct 2024 21:58:40 +0100 Subject: [PATCH 0499/2181] renderer: reserve space for error at the bottom if that's set ref #8040 --- src/render/Renderer.cpp | 17 ++++++++++++----- 1 file changed, 12 insertions(+), 5 deletions(-) diff --git a/src/render/Renderer.cpp b/src/render/Renderer.cpp index 61f94014..bc95abc6 100644 --- a/src/render/Renderer.cpp +++ b/src/render/Renderer.cpp @@ -1756,7 +1756,9 @@ void CHyprRenderer::arrangeLayerArray(CMonitor* pMonitor, const std::vectorgetMonitorFromID(monitor); + const auto PMONITOR = g_pCompositor->getMonitorFromID(monitor); + + static auto BAR_POSITION = CConfigValue("debug:error_position"); if (!PMONITOR) return; @@ -1768,10 +1770,15 @@ void CHyprRenderer::arrangeLayersForMonitor(const MONITORID& monitor) { CBox usableArea = {PMONITOR->vecPosition.x, PMONITOR->vecPosition.y, PMONITOR->vecSize.x, PMONITOR->vecSize.y}; if (g_pHyprError->active() && g_pCompositor->m_pLastMonitor == PMONITOR->self) { - const auto HEIGHT = g_pHyprError->height(); - PMONITOR->vecReservedTopLeft.y = HEIGHT; - usableArea.y += HEIGHT; - usableArea.h -= HEIGHT; + const auto HEIGHT = g_pHyprError->height(); + if (*BAR_POSITION == 0) { + PMONITOR->vecReservedTopLeft.y = HEIGHT; + usableArea.y += HEIGHT; + usableArea.h -= HEIGHT; + } else { + PMONITOR->vecReservedBottomRight.y = HEIGHT; + usableArea.h -= HEIGHT; + } } for (auto& la : PMONITOR->m_aLayerSurfaceLayers) { From ac658500fbebe607f2db83f11c37f0a3a05ef734 Mon Sep 17 00:00:00 2001 From: Vaxry Date: Tue, 8 Oct 2024 23:33:10 +0100 Subject: [PATCH 0500/2181] keyboard: update group state on change for the sym resolve state fixes #8038 --- src/devices/IKeyboard.cpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/devices/IKeyboard.cpp b/src/devices/IKeyboard.cpp index 3300f252..d1119772 100644 --- a/src/devices/IKeyboard.cpp +++ b/src/devices/IKeyboard.cpp @@ -392,6 +392,9 @@ void IKeyboard::updateXkbStateWithKey(uint32_t xkbKey, bool pressed) { xkb_state_update_key(xkbState, xkbKey, pressed ? XKB_KEY_DOWN : XKB_KEY_UP); if (updateModifiersState()) { + if (xkbSymState) + xkb_state_update_mask(xkbSymState, 0, 0, 0, 0, 0, modifiersState.group); + keyboardEvents.modifiers.emit(SModifiersEvent{ .depressed = modifiersState.depressed, .latched = modifiersState.latched, From bc299928ad5571300180eb8edb6742ed3bbf0282 Mon Sep 17 00:00:00 2001 From: Vaxry Date: Wed, 9 Oct 2024 00:26:40 +0100 Subject: [PATCH 0501/2181] output/xdg-output: avoid sending events to released globals ref #6835 --- src/protocols/XDGOutput.cpp | 4 +++- src/protocols/XDGOutput.hpp | 2 ++ src/protocols/core/Output.cpp | 5 ++++- 3 files changed, 9 insertions(+), 2 deletions(-) diff --git a/src/protocols/XDGOutput.cpp b/src/protocols/XDGOutput.cpp index 0cdadd43..0598e713 100644 --- a/src/protocols/XDGOutput.cpp +++ b/src/protocols/XDGOutput.cpp @@ -51,6 +51,8 @@ void CXDGOutputProtocol::onManagerGetXDGOutput(CZxdgOutputManagerV1* mgr, uint32 #endif pXDGOutput->client = CLIENT; + pXDGOutput->outputProto = OUTPUT->owner; + if (!pXDGOutput->resource->resource()) { m_vXDGOutputs.pop_back(); mgr->noMemory(); @@ -104,7 +106,7 @@ CXDGOutput::CXDGOutput(SP resource_, SP monitor_) : mon void CXDGOutput::sendDetails() { static auto PXWLFORCESCALEZERO = CConfigValue("xwayland:force_zero_scaling"); - if (!monitor) + if (!monitor || !outputProto || outputProto->isDefunct()) return; const auto POS = isXWayland ? monitor->vecXWaylandPosition : monitor->vecPosition; diff --git a/src/protocols/XDGOutput.hpp b/src/protocols/XDGOutput.hpp index 15d86cc7..520f3aaa 100644 --- a/src/protocols/XDGOutput.hpp +++ b/src/protocols/XDGOutput.hpp @@ -6,6 +6,7 @@ class CMonitor; class CXDGOutputProtocol; +class CWLOutputProtocol; class CXDGOutput { public: @@ -16,6 +17,7 @@ class CXDGOutput { private: WP monitor; SP resource; + WP outputProto; std::optional overridePosition; diff --git a/src/protocols/core/Output.cpp b/src/protocols/core/Output.cpp index 7b88e0a8..4047774a 100644 --- a/src/protocols/core/Output.cpp +++ b/src/protocols/core/Output.cpp @@ -47,7 +47,7 @@ SP CWLOutputResource::getResource() { } void CWLOutputResource::updateState() { - if (!monitor || (owner && owner->defunct)) + if (!monitor || !owner || owner->defunct) return; if (resource->version() >= 2) @@ -119,6 +119,9 @@ bool CWLOutputProtocol::isDefunct() { } void CWLOutputProtocol::sendDone() { + if (defunct) + return; + for (auto const& r : m_vOutputs) { r->resource->sendDone(); } From 6ce07ee86453e8ef01faa7b4e1eb8f09475f32b7 Mon Sep 17 00:00:00 2001 From: Mihai Fufezan Date: Wed, 9 Oct 2024 12:00:43 +0300 Subject: [PATCH 0502/2181] CI/release: remove script backup line --- .github/workflows/release.yaml | 1 - 1 file changed, 1 deletion(-) diff --git a/.github/workflows/release.yaml b/.github/workflows/release.yaml index 1f52b4ff..d5ff1aa0 100644 --- a/.github/workflows/release.yaml +++ b/.github/workflows/release.yaml @@ -20,7 +20,6 @@ jobs: run: | git fetch --unshallow || echo "failed unshallowing" bash -c scripts/generateVersion.sh - mv scripts/generateVersion.sh scripts/generateVersion.sh.bak - name: Create tarball with submodules id: tar From 223dcc8bac7fee90aa6aa7596d9379e56b526e62 Mon Sep 17 00:00:00 2001 From: trianta <56975502+Trimutex@users.noreply.github.com> Date: Wed, 9 Oct 2024 04:24:05 -0500 Subject: [PATCH 0503/2181] output: update state even if no owner exists (#8044) --- src/protocols/core/Output.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/protocols/core/Output.cpp b/src/protocols/core/Output.cpp index 4047774a..3e68937f 100644 --- a/src/protocols/core/Output.cpp +++ b/src/protocols/core/Output.cpp @@ -47,7 +47,7 @@ SP CWLOutputResource::getResource() { } void CWLOutputResource::updateState() { - if (!monitor || !owner || owner->defunct) + if (!monitor || (owner && owner->defunct)) return; if (resource->version() >= 2) From 3d28879c2640cdb6e8426127692240100793bfef Mon Sep 17 00:00:00 2001 From: JManch <61563764+JManch@users.noreply.github.com> Date: Wed, 9 Oct 2024 10:24:35 +0100 Subject: [PATCH 0504/2181] hyprerror: fix height calc with bottom bar (#8043) --- src/hyprerror/HyprError.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/hyprerror/HyprError.cpp b/src/hyprerror/HyprError.cpp index 5f63de24..4044bcc9 100644 --- a/src/hyprerror/HyprError.cpp +++ b/src/hyprerror/HyprError.cpp @@ -133,7 +133,7 @@ void CHyprError::createQueued() { } m_szQueued = ""; - m_fLastHeight = yoffset + PAD + 1; + m_fLastHeight = yoffset + PAD + 1 - (TOPBAR ? 0 : Y - PAD); pango_font_description_free(pangoFD); g_object_unref(layoutText); From 6ae89940c761d4ed4317df0af29e8df41d472091 Mon Sep 17 00:00:00 2001 From: Aqa-Ib Date: Wed, 9 Oct 2024 11:58:49 +0200 Subject: [PATCH 0505/2181] layout: add merge_floated_into_tiled_on_groupbar (#8042) --- src/config/ConfigDescriptions.hpp | 6 ++++++ src/config/ConfigManager.cpp | 1 + src/render/decorations/CHyprGroupBarDecoration.cpp | 12 +++++++++--- 3 files changed, 16 insertions(+), 3 deletions(-) diff --git a/src/config/ConfigDescriptions.hpp b/src/config/ConfigDescriptions.hpp index 2ca230be..d684e44a 100644 --- a/src/config/ConfigDescriptions.hpp +++ b/src/config/ConfigDescriptions.hpp @@ -784,6 +784,12 @@ inline static const std::vector CONFIG_OPTIONS = { .type = CONFIG_OPTION_CHOICE, .data = SConfigOptionDescription::SChoiceData{0, "disabled,enabled,only when dragging into the groupbar"}, }, + SConfigOptionDescription{ + .value = "group:merge_floated_into_tiled_on_groupbar", + .description = "whether dragging a floating window into a tiled window groupbar will merge them", + .type = CONFIG_OPTION_BOOL, + .data = SConfigOptionDescription::SBoolData{false}, + }, /* * group:groupbar: diff --git a/src/config/ConfigManager.cpp b/src/config/ConfigManager.cpp index 9a5283fa..e973f1ab 100644 --- a/src/config/ConfigManager.cpp +++ b/src/config/ConfigManager.cpp @@ -377,6 +377,7 @@ CConfigManager::CConfigManager() { m_pConfig->addConfigValue("group:insert_after_current", Hyprlang::INT{1}); m_pConfig->addConfigValue("group:focus_removed_window", Hyprlang::INT{1}); m_pConfig->addConfigValue("group:merge_groups_on_drag", Hyprlang::INT{1}); + m_pConfig->addConfigValue("group:merge_floated_into_tiled_on_groupbar", Hyprlang::INT{0}); m_pConfig->addConfigValue("group:auto_group", Hyprlang::INT{1}); m_pConfig->addConfigValue("group:drag_into_group", Hyprlang::INT{1}); m_pConfig->addConfigValue("group:groupbar:enabled", Hyprlang::INT{1}); diff --git a/src/render/decorations/CHyprGroupBarDecoration.cpp b/src/render/decorations/CHyprGroupBarDecoration.cpp index ef6c81e6..eca3f2cb 100644 --- a/src/render/decorations/CHyprGroupBarDecoration.cpp +++ b/src/render/decorations/CHyprGroupBarDecoration.cpp @@ -402,9 +402,15 @@ bool CHyprGroupBarDecoration::onBeginWindowDragOnDeco(const Vector2D& pos) { } bool CHyprGroupBarDecoration::onEndWindowDragOnDeco(const Vector2D& pos, PHLWINDOW pDraggedWindow) { - static auto PSTACKED = CConfigValue("group:groupbar:stacked"); - static auto PDRAGINTOGROUP = CConfigValue("group:drag_into_group"); - if (!pDraggedWindow->canBeGroupedInto(m_pWindow.lock()) || (*PDRAGINTOGROUP != 1 && *PDRAGINTOGROUP != 2)) + static auto PSTACKED = CConfigValue("group:groupbar:stacked"); + static auto PDRAGINTOGROUP = CConfigValue("group:drag_into_group"); + static auto PMERGEFLOATEDINTOTILEDONGROUPBAR = CConfigValue("group:merge_floated_into_tiled_on_groupbar"); + + bool denied = false; + if (!m_pWindow->m_bIsFloating && !pDraggedWindow->m_bDraggingTiled && !*PMERGEFLOATEDINTOTILEDONGROUPBAR) + denied = true; + + if (!pDraggedWindow->canBeGroupedInto(m_pWindow.lock()) || (*PDRAGINTOGROUP != 1 && *PDRAGINTOGROUP != 2) || denied) return false; const float BARRELATIVE = *PSTACKED ? pos.y - assignedBoxGlobal().y - (m_fBarHeight + BAR_PADDING_OUTER_VERT) / 2 : pos.x - assignedBoxGlobal().x - m_fBarWidth / 2; From c4eb1940336cd88ca65ba65582ce104e49dfc7c9 Mon Sep 17 00:00:00 2001 From: Vaxry Date: Wed, 9 Oct 2024 22:00:06 +0100 Subject: [PATCH 0506/2181] gammactrl: guard pMonitor in setGamma --- src/protocols/GammaControl.cpp | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/src/protocols/GammaControl.cpp b/src/protocols/GammaControl.cpp index 077d6e2f..e794e543 100644 --- a/src/protocols/GammaControl.cpp +++ b/src/protocols/GammaControl.cpp @@ -46,6 +46,13 @@ CGammaControl::CGammaControl(SP resource_, wl_resource* out resource->setOnDestroy([this](CZwlrGammaControlV1* gamma) { PROTO::gamma->destroyGammaControl(this); }); resource->setSetGamma([this](CZwlrGammaControlV1* gamma, int32_t fd) { + if (!pMonitor) { + LOGM(ERR, "setGamma for a dead monitor"); + resource->sendFailed(); + close(fd); + return; + } + LOGM(LOG, "setGamma for {}", pMonitor->szName); int fdFlags = fcntl(fd, F_GETFL, 0); From b65773bea9b912a41cfcbc789fb2e60a07e3d0c1 Mon Sep 17 00:00:00 2001 From: Vaxry Date: Thu, 10 Oct 2024 11:01:13 +0100 Subject: [PATCH 0507/2181] hyprpm: disallow shallow on unknown branch --- hyprpm/src/core/PluginManager.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/hyprpm/src/core/PluginManager.cpp b/hyprpm/src/core/PluginManager.cpp index 669789b4..612995dc 100644 --- a/hyprpm/src/core/PluginManager.cpp +++ b/hyprpm/src/core/PluginManager.cpp @@ -436,7 +436,7 @@ bool CPluginManager::updateHeaders(bool force) { progress.printMessageAbove(std::string{Colors::YELLOW} + "!" + Colors::RESET + " Cloning https://github.com/hyprwm/hyprland, this might take a moment."); - const bool bShallow = (HLVER.branch == "main" || HLVER.branch == "") && !m_bNoShallow; + const bool bShallow = (HLVER.branch == "main") && !m_bNoShallow; // let us give a bit of leg-room for shallowing // due to timezones, etc. From d655a10381f01212635f2eadd69e1f22930f8f06 Mon Sep 17 00:00:00 2001 From: Vaxry <43317083+vaxerski@users.noreply.github.com> Date: Fri, 11 Oct 2024 10:56:19 +0100 Subject: [PATCH 0508/2181] config/layout: nuke no_gaps_when_only (#8072) --- src/config/ConfigDescriptions.hpp | 12 ------------ src/config/ConfigManager.cpp | 2 -- src/layout/DwindleLayout.cpp | 30 ++++-------------------------- src/layout/MasterLayout.cpp | 30 +++++------------------------- src/managers/input/Touch.cpp | 1 - 5 files changed, 9 insertions(+), 66 deletions(-) diff --git a/src/config/ConfigDescriptions.hpp b/src/config/ConfigDescriptions.hpp index d684e44a..bef5ee53 100644 --- a/src/config/ConfigDescriptions.hpp +++ b/src/config/ConfigDescriptions.hpp @@ -1446,12 +1446,6 @@ inline static const std::vector CONFIG_OPTIONS = { .type = CONFIG_OPTION_FLOAT, .data = SConfigOptionDescription::SFloatData{1, 0.1, 3}, }, - SConfigOptionDescription{ - .value = "dwindle:no_gaps_when_only", - .description = "whether to apply gaps when there is only one window on a workspace, aka. smart gaps. (default: disabled - 0) no border - 1, with border - 2 [0/1/2]", - .type = CONFIG_OPTION_CHOICE, - .data = SConfigOptionDescription::SChoiceData{0, "disabled,no border,with border"}, - }, SConfigOptionDescription{ .value = "dwindle:use_active_for_splits", .description = "whether to prefer the active window or the mouse position for splits", @@ -1512,12 +1506,6 @@ inline static const std::vector CONFIG_OPTIONS = { .type = CONFIG_OPTION_STRING_SHORT, .data = SConfigOptionDescription::SStringData{"none"}, }, - SConfigOptionDescription{ - .value = "master:no_gaps_when_only", - .description = "whether to apply gaps when there is only one window on a workspace, aka. smart gaps. (default: disabled - 0) no border - 1, with border - 2 [0/1/2]", - .type = CONFIG_OPTION_CHOICE, - .data = SConfigOptionDescription::SChoiceData{0, "disabled,no border,with border"}, - }, SConfigOptionDescription{ .value = "master:orientation", .description = "default placement of the master area, can be left, right, top, bottom or center", diff --git a/src/config/ConfigManager.cpp b/src/config/ConfigManager.cpp index e973f1ab..6ec63d4c 100644 --- a/src/config/ConfigManager.cpp +++ b/src/config/ConfigManager.cpp @@ -446,7 +446,6 @@ CConfigManager::CConfigManager() { m_pConfig->addConfigValue("dwindle:preserve_split", Hyprlang::INT{0}); m_pConfig->addConfigValue("dwindle:special_scale_factor", {1.f}); m_pConfig->addConfigValue("dwindle:split_width_multiplier", {1.0f}); - m_pConfig->addConfigValue("dwindle:no_gaps_when_only", Hyprlang::INT{0}); m_pConfig->addConfigValue("dwindle:use_active_for_splits", Hyprlang::INT{1}); m_pConfig->addConfigValue("dwindle:default_split_ratio", {1.f}); m_pConfig->addConfigValue("dwindle:split_bias", Hyprlang::INT{0}); @@ -459,7 +458,6 @@ CConfigManager::CConfigManager() { m_pConfig->addConfigValue("master:always_center_master", Hyprlang::INT{0}); m_pConfig->addConfigValue("master:new_on_active", {"none"}); m_pConfig->addConfigValue("master:new_on_top", Hyprlang::INT{0}); - m_pConfig->addConfigValue("master:no_gaps_when_only", Hyprlang::INT{0}); m_pConfig->addConfigValue("master:orientation", {"left"}); m_pConfig->addConfigValue("master:inherit_fullscreen", Hyprlang::INT{1}); m_pConfig->addConfigValue("master:allow_small_split", Hyprlang::INT{0}); diff --git a/src/layout/DwindleLayout.cpp b/src/layout/DwindleLayout.cpp index 04cbf21d..76b26af1 100644 --- a/src/layout/DwindleLayout.cpp +++ b/src/layout/DwindleLayout.cpp @@ -142,11 +142,10 @@ void CHyprDwindleLayout::applyNodeDataToWindow(SDwindleNodeData* pNode, bool for PWINDOW->unsetWindowData(PRIORITY_LAYOUT); PWINDOW->updateWindowData(); - static auto PNOGAPSWHENONLY = CConfigValue("dwindle:no_gaps_when_only"); - static auto PGAPSINDATA = CConfigValue("general:gaps_in"); - static auto PGAPSOUTDATA = CConfigValue("general:gaps_out"); - auto* const PGAPSIN = (CCssGapData*)(PGAPSINDATA.ptr())->getData(); - auto* const PGAPSOUT = (CCssGapData*)(PGAPSOUTDATA.ptr())->getData(); + static auto PGAPSINDATA = CConfigValue("general:gaps_in"); + static auto PGAPSOUTDATA = CConfigValue("general:gaps_out"); + auto* const PGAPSIN = (CCssGapData*)(PGAPSINDATA.ptr())->getData(); + auto* const PGAPSOUT = (CCssGapData*)(PGAPSOUTDATA.ptr())->getData(); auto gapsIn = WORKSPACERULE.gapsIn.value_or(*PGAPSIN); auto gapsOut = WORKSPACERULE.gapsOut.value_or(*PGAPSOUT); @@ -156,27 +155,6 @@ void CHyprDwindleLayout::applyNodeDataToWindow(SDwindleNodeData* pNode, bool for PWINDOW->m_vSize = nodeBox.size(); PWINDOW->m_vPosition = nodeBox.pos(); - const auto NODESONWORKSPACE = getNodesOnWorkspace(PWINDOW->workspaceID()); - - if (*PNOGAPSWHENONLY && !PWINDOW->onSpecialWorkspace() && (NODESONWORKSPACE == 1 || PWINDOW->isEffectiveInternalFSMode(FSMODE_MAXIMIZED))) { - - PWINDOW->m_sWindowData.decorate = CWindowOverridableVar(true, PRIORITY_LAYOUT); - PWINDOW->m_sWindowData.noBorder = CWindowOverridableVar(*PNOGAPSWHENONLY != 2, PRIORITY_LAYOUT); - PWINDOW->m_sWindowData.noRounding = CWindowOverridableVar(true, PRIORITY_LAYOUT); - PWINDOW->m_sWindowData.noShadow = CWindowOverridableVar(true, PRIORITY_LAYOUT); - - PWINDOW->updateWindowDecos(); - - const auto RESERVED = PWINDOW->getFullWindowReservedArea(); - - PWINDOW->m_vRealPosition = PWINDOW->m_vPosition + RESERVED.topLeft; - PWINDOW->m_vRealSize = PWINDOW->m_vSize - (RESERVED.topLeft + RESERVED.bottomRight); - - g_pXWaylandManager->setWindowSize(PWINDOW, PWINDOW->m_vRealSize.goal()); - - return; - } - PWINDOW->updateWindowDecos(); auto calcPos = PWINDOW->m_vPosition; diff --git a/src/layout/MasterLayout.cpp b/src/layout/MasterLayout.cpp index 04a6ea29..8fde960d 100644 --- a/src/layout/MasterLayout.cpp +++ b/src/layout/MasterLayout.cpp @@ -631,12 +631,11 @@ void CHyprMasterLayout::applyNodeDataToWindow(SMasterNodeData* pNode) { PWINDOW->unsetWindowData(PRIORITY_LAYOUT); PWINDOW->updateWindowData(); - static auto PNOGAPSWHENONLY = CConfigValue("master:no_gaps_when_only"); - static auto PANIMATE = CConfigValue("misc:animate_manual_resizes"); - static auto PGAPSINDATA = CConfigValue("general:gaps_in"); - static auto PGAPSOUTDATA = CConfigValue("general:gaps_out"); - auto* PGAPSIN = (CCssGapData*)(PGAPSINDATA.ptr())->getData(); - auto* PGAPSOUT = (CCssGapData*)(PGAPSOUTDATA.ptr())->getData(); + static auto PANIMATE = CConfigValue("misc:animate_manual_resizes"); + static auto PGAPSINDATA = CConfigValue("general:gaps_in"); + static auto PGAPSOUTDATA = CConfigValue("general:gaps_out"); + auto* PGAPSIN = (CCssGapData*)(PGAPSINDATA.ptr())->getData(); + auto* PGAPSOUT = (CCssGapData*)(PGAPSOUTDATA.ptr())->getData(); auto gapsIn = WORKSPACERULE.gapsIn.value_or(*PGAPSIN); auto gapsOut = WORKSPACERULE.gapsOut.value_or(*PGAPSOUT); @@ -649,25 +648,6 @@ void CHyprMasterLayout::applyNodeDataToWindow(SMasterNodeData* pNode) { PWINDOW->m_vSize = pNode->size; PWINDOW->m_vPosition = pNode->position; - if (*PNOGAPSWHENONLY && !PWINDOW->onSpecialWorkspace() && (getNodesOnWorkspace(PWINDOW->workspaceID()) == 1 || PWINDOW->isEffectiveInternalFSMode(FSMODE_MAXIMIZED))) { - - PWINDOW->m_sWindowData.decorate = CWindowOverridableVar(true, PRIORITY_LAYOUT); - PWINDOW->m_sWindowData.noBorder = CWindowOverridableVar(*PNOGAPSWHENONLY != 2, PRIORITY_LAYOUT); - PWINDOW->m_sWindowData.noRounding = CWindowOverridableVar(true, PRIORITY_LAYOUT); - PWINDOW->m_sWindowData.noShadow = CWindowOverridableVar(true, PRIORITY_LAYOUT); - - PWINDOW->updateWindowDecos(); - - const auto RESERVED = PWINDOW->getFullWindowReservedArea(); - - PWINDOW->m_vRealPosition = PWINDOW->m_vPosition + RESERVED.topLeft; - PWINDOW->m_vRealSize = PWINDOW->m_vSize - (RESERVED.topLeft + RESERVED.bottomRight); - - g_pXWaylandManager->setWindowSize(PWINDOW, PWINDOW->m_vRealSize.goal()); - - return; - } - PWINDOW->updateWindowDecos(); auto calcPos = PWINDOW->m_vPosition; diff --git a/src/managers/input/Touch.cpp b/src/managers/input/Touch.cpp index 9b03168e..0333648a 100644 --- a/src/managers/input/Touch.cpp +++ b/src/managers/input/Touch.cpp @@ -39,7 +39,6 @@ void CInputManager::onTouchDown(ITouch::SDownEvent e) { const auto PWORKSPACE = PMONITOR->activeWorkspace; const bool VERTANIMS = PWORKSPACE->m_vRenderOffset.getConfig()->pValues->internalStyle == "slidevert" || PWORKSPACE->m_vRenderOffset.getConfig()->pValues->internalStyle.starts_with("slidefadevert"); - // TODO: support no_gaps_when_only? const double TARGETLEFT = ((VERTANIMS ? gapsOut.top : gapsOut.left) + *PBORDERSIZE) / (VERTANIMS ? PMONITOR->vecSize.y : PMONITOR->vecSize.x); const double TARGETRIGHT = 1 - (((VERTANIMS ? gapsOut.bottom : gapsOut.right) + *PBORDERSIZE) / (VERTANIMS ? PMONITOR->vecSize.y : PMONITOR->vecSize.x)); const double POSITION = (VERTANIMS ? e.pos.y : e.pos.x); From 178a300eeaf006fed4c8c9a599657b4530f65559 Mon Sep 17 00:00:00 2001 From: Jasson Date: Fri, 11 Oct 2024 07:07:25 -0400 Subject: [PATCH 0509/2181] xwayland: minor cleanups and fixes (#8076) --- src/managers/XWaylandManager.cpp | 110 +++++++++++++++---------------- 1 file changed, 55 insertions(+), 55 deletions(-) diff --git a/src/managers/XWaylandManager.cpp b/src/managers/XWaylandManager.cpp index fad7e451..8b63d37e 100644 --- a/src/managers/XWaylandManager.cpp +++ b/src/managers/XWaylandManager.cpp @@ -5,14 +5,13 @@ #include "../protocols/XDGShell.hpp" #include "../protocols/core/Compositor.hpp" #include "../xwayland/XWayland.hpp" +#include #define OUTPUT_MANAGER_VERSION 3 #define OUTPUT_DONE_DEPRECATED_SINCE_VERSION 3 #define OUTPUT_DESCRIPTION_MUTABLE_SINCE_VERSION 3 -CHyprXWaylandManager::CHyprXWaylandManager() { - ; -} +CHyprXWaylandManager::CHyprXWaylandManager() = default; CHyprXWaylandManager::~CHyprXWaylandManager() { #ifndef NO_XWAYLAND @@ -21,7 +20,7 @@ CHyprXWaylandManager::~CHyprXWaylandManager() { } SP CHyprXWaylandManager::getWindowSurface(PHLWINDOW pWindow) { - return pWindow->m_pWLSurface->resource(); + return pWindow ? pWindow->m_pWLSurface->resource() : nullptr; } void CHyprXWaylandManager::activateSurface(SP pSurface, bool activate) { @@ -40,27 +39,31 @@ void CHyprXWaylandManager::activateSurface(SP pSurface, bool return; } - if (PWINDOW->m_bIsX11 && PWINDOW->m_pXWaylandSurface) { - if (activate) { - PWINDOW->m_pXWaylandSurface->setMinimized(false); - PWINDOW->m_pXWaylandSurface->restackToTop(); + if (PWINDOW->m_bIsX11) { + if (PWINDOW->m_pXWaylandSurface) { + if (activate) { + PWINDOW->m_pXWaylandSurface->setMinimized(false); + PWINDOW->m_pXWaylandSurface->restackToTop(); + } + PWINDOW->m_pXWaylandSurface->activate(activate); } - PWINDOW->m_pXWaylandSurface->activate(activate); - } else if (!PWINDOW->m_bIsX11 && PWINDOW->m_pXDGSurface) + } else if (PWINDOW->m_pXDGSurface) PWINDOW->m_pXDGSurface->toplevel->setActive(activate); } void CHyprXWaylandManager::activateWindow(PHLWINDOW pWindow, bool activate) { if (pWindow->m_bIsX11) { - setWindowSize(pWindow, pWindow->m_vRealSize.value()); // update xwayland output pos if (activate) { + setWindowSize(pWindow, pWindow->m_vRealSize.value()); // update xwayland output pos pWindow->m_pXWaylandSurface->setMinimized(false); + if (!pWindow->isX11OverrideRedirect()) pWindow->m_pXWaylandSurface->restackToTop(); } pWindow->m_pXWaylandSurface->activate(activate); + } else if (pWindow->m_pXDGSurface && pWindow->m_pXDGSurface->toplevel) pWindow->m_pXDGSurface->toplevel->setActive(activate); @@ -74,6 +77,9 @@ void CHyprXWaylandManager::activateWindow(PHLWINDOW pWindow, bool activate) { } void CHyprXWaylandManager::getGeometryForWindow(PHLWINDOW pWindow, CBox* pbox) { + if (!pWindow) + return; + if (pWindow->m_bIsX11) { const auto SIZEHINTS = pWindow->m_pXWaylandSurface->sizeHints.get(); @@ -83,7 +89,10 @@ void CHyprXWaylandManager::getGeometryForWindow(PHLWINDOW pWindow, CBox* pbox) { pbox->x = pWindow->m_pXWaylandSurface->geometry.x; pbox->y = pWindow->m_pXWaylandSurface->geometry.y; - if ((SIZEHINTS->flags & 0x2 /* ICCCM USSize */) || (SIZEHINTS->flags & 0x8 /* ICCCM PSize */)) { + constexpr int ICCCM_USSize = 0x2; + constexpr int ICCCM_PSize = 0x8; + + if ((SIZEHINTS->flags & ICCCM_USSize) || (SIZEHINTS->flags & ICCCM_PSize)) { pbox->w = SIZEHINTS->base_width; pbox->h = SIZEHINTS->base_height; } else { @@ -117,34 +126,34 @@ void CHyprXWaylandManager::setWindowSize(PHLWINDOW pWindow, Vector2D size, bool Vector2D windowPos = pWindow->m_vRealPosition.value(); if (pWindow->m_bIsX11 && PMONITOR) { - windowPos = windowPos - PMONITOR->vecPosition; // normalize to monitor + windowPos -= PMONITOR->vecPosition; // normalize to monitor if (*PXWLFORCESCALEZERO) - windowPos = windowPos * PMONITOR->scale; // scale if applicable - windowPos = windowPos + PMONITOR->vecXWaylandPosition; // move to correct position for xwayland + windowPos *= PMONITOR->scale; // scale if applicable + windowPos += PMONITOR->vecXWaylandPosition; // move to correct position for xwayland } - if (!force && ((pWindow->m_vPendingReportedSize == size && windowPos == pWindow->m_vReportedPosition) || (pWindow->m_vPendingReportedSize == size && !pWindow->m_bIsX11))) + if (!force && pWindow->m_vPendingReportedSize == size && (windowPos == pWindow->m_vReportedPosition || !pWindow->m_bIsX11)) return; pWindow->m_vReportedPosition = windowPos; pWindow->m_vPendingReportedSize = size; - pWindow->m_fX11SurfaceScaledBy = 1.f; + pWindow->m_fX11SurfaceScaledBy = 1.0f; if (*PXWLFORCESCALEZERO && pWindow->m_bIsX11 && PMONITOR) { - size = size * PMONITOR->scale; + size *= PMONITOR->scale; pWindow->m_fX11SurfaceScaledBy = PMONITOR->scale; } if (pWindow->m_bIsX11) pWindow->m_pXWaylandSurface->configure({windowPos, size}); else if (pWindow->m_pXDGSurface->toplevel) - pWindow->m_vPendingSizeAcks.push_back(std::make_pair<>(pWindow->m_pXDGSurface->toplevel->setSize(size), size.floor())); + pWindow->m_vPendingSizeAcks.emplace_back(pWindow->m_pXDGSurface->toplevel->setSize(size), size.floor()); } bool CHyprXWaylandManager::shouldBeFloated(PHLWINDOW pWindow, bool pending) { if (pWindow->m_bIsX11) { - for (auto const& a : pWindow->m_pXWaylandSurface->atoms) + for (const auto& a : pWindow->m_pXWaylandSurface->atoms) if (a == HYPRATOMS["_NET_WM_WINDOW_TYPE_DIALOG"] || a == HYPRATOMS["_NET_WM_WINDOW_TYPE_SPLASH"] || a == HYPRATOMS["_NET_WM_WINDOW_TYPE_TOOLBAR"] || a == HYPRATOMS["_NET_WM_WINDOW_TYPE_UTILITY"] || a == HYPRATOMS["_NET_WM_WINDOW_TYPE_TOOLTIP"] || a == HYPRATOMS["_NET_WM_WINDOW_TYPE_POPUP_MENU"] || a == HYPRATOMS["_NET_WM_WINDOW_TYPE_DOCK"] || a == HYPRATOMS["_NET_WM_WINDOW_TYPE_DROPDOWN_MENU"] || a == HYPRATOMS["_NET_WM_WINDOW_TYPE_MENU"] || @@ -157,16 +166,8 @@ bool CHyprXWaylandManager::shouldBeFloated(PHLWINDOW pWindow, bool pending) { return true; } - if (pWindow->isModal()) - return true; - - if (pWindow->m_pXWaylandSurface->transient) - return true; - - if (pWindow->m_pXWaylandSurface->role.contains("task_dialog") || pWindow->m_pXWaylandSurface->role.contains("pop-up")) - return true; - - if (pWindow->m_pXWaylandSurface->overrideRedirect) + if (pWindow->isModal() || pWindow->m_pXWaylandSurface->transient || + (pWindow->m_pXWaylandSurface->role.contains("task_dialog") || pWindow->m_pXWaylandSurface->role.contains("pop-up")) || pWindow->m_pXWaylandSurface->overrideRedirect) return true; const auto SIZEHINTS = pWindow->m_pXWaylandSurface->sizeHints.get(); @@ -203,6 +204,9 @@ void CHyprXWaylandManager::checkBorders(PHLWINDOW pWindow) { } void CHyprXWaylandManager::setWindowFullscreen(PHLWINDOW pWindow, bool fullscreen) { + if (!pWindow) + return; + if (pWindow->m_bIsX11) pWindow->m_pXWaylandSurface->setFullscreen(fullscreen); else if (pWindow->m_pXDGSurface && pWindow->m_pXDGSurface->toplevel) @@ -210,37 +214,33 @@ void CHyprXWaylandManager::setWindowFullscreen(PHLWINDOW pWindow, bool fullscree } Vector2D CHyprXWaylandManager::getMaxSizeForWindow(PHLWINDOW pWindow) { - if (!validMapped(pWindow)) - return Vector2D(99999, 99999); + constexpr int NO_MAX_SIZE_LIMIT = 99999; + if (!validMapped(pWindow) || + ((pWindow->m_bIsX11 && !pWindow->m_pXWaylandSurface->sizeHints) || (!pWindow->m_bIsX11 && !pWindow->m_pXDGSurface->toplevel) || + pWindow->m_sWindowData.noMaxSize.valueOrDefault())) + return Vector2D(NO_MAX_SIZE_LIMIT, NO_MAX_SIZE_LIMIT); - if ((pWindow->m_bIsX11 && !pWindow->m_pXWaylandSurface->sizeHints) || (!pWindow->m_bIsX11 && !pWindow->m_pXDGSurface->toplevel) || - pWindow->m_sWindowData.noMaxSize.valueOrDefault()) - return Vector2D(99999, 99999); + Vector2D maxSize = pWindow->m_bIsX11 ? Vector2D(pWindow->m_pXWaylandSurface->sizeHints->max_width, pWindow->m_pXWaylandSurface->sizeHints->max_height) : + pWindow->m_pXDGSurface->toplevel->current.maxSize; - auto MAXSIZE = pWindow->m_bIsX11 ? Vector2D(pWindow->m_pXWaylandSurface->sizeHints->max_width, pWindow->m_pXWaylandSurface->sizeHints->max_height) : - pWindow->m_pXDGSurface->toplevel->current.maxSize; + if (maxSize.x < 5) + maxSize.x = NO_MAX_SIZE_LIMIT; + if (maxSize.y < 5) + maxSize.y = NO_MAX_SIZE_LIMIT; - if (MAXSIZE.x < 5) - MAXSIZE.x = 99999; - if (MAXSIZE.y < 5) - MAXSIZE.y = 99999; - - return MAXSIZE; + return maxSize; } Vector2D CHyprXWaylandManager::getMinSizeForWindow(PHLWINDOW pWindow) { - if (!validMapped(pWindow)) + if (!validMapped(pWindow) || ((pWindow->m_bIsX11 && !pWindow->m_pXWaylandSurface->sizeHints) || (!pWindow->m_bIsX11 && !pWindow->m_pXDGSurface->toplevel))) return Vector2D(0, 0); - if ((pWindow->m_bIsX11 && !pWindow->m_pXWaylandSurface->sizeHints) || (!pWindow->m_bIsX11 && !pWindow->m_pXDGSurface->toplevel)) - return Vector2D(0, 0); + Vector2D minSize = pWindow->m_bIsX11 ? Vector2D(pWindow->m_pXWaylandSurface->sizeHints->min_width, pWindow->m_pXWaylandSurface->sizeHints->min_height) : + pWindow->m_pXDGSurface->toplevel->current.minSize; - auto MINSIZE = pWindow->m_bIsX11 ? Vector2D(pWindow->m_pXWaylandSurface->sizeHints->min_width, pWindow->m_pXWaylandSurface->sizeHints->min_height) : - pWindow->m_pXDGSurface->toplevel->current.minSize; + minSize = minSize.clamp({1, 1}); - MINSIZE = MINSIZE.clamp({1, 1}); - - return MINSIZE; + return minSize; } Vector2D CHyprXWaylandManager::xwaylandToWaylandCoords(const Vector2D& coord) { @@ -249,7 +249,7 @@ Vector2D CHyprXWaylandManager::xwaylandToWaylandCoords(const Vector2D& coord) { CMonitor* pMonitor = nullptr; double bestDistance = __FLT_MAX__; - for (auto const& m : g_pCompositor->m_vMonitors) { + for (const auto& m : g_pCompositor->m_vMonitors) { const auto SIZ = *PXWLFORCESCALEZERO ? m->vecTransformedSize : m->vecSize; double distance = @@ -268,9 +268,9 @@ Vector2D CHyprXWaylandManager::xwaylandToWaylandCoords(const Vector2D& coord) { Vector2D result = coord - pMonitor->vecXWaylandPosition; // if scaled, unscale if (*PXWLFORCESCALEZERO) - result = result / pMonitor->scale; + result /= pMonitor->scale; // add pos - result = result + pMonitor->vecPosition; + result += pMonitor->vecPosition; return result; -} +} \ No newline at end of file From 7564b26b7d386d248eaa47c1a481c09eefd8e3ca Mon Sep 17 00:00:00 2001 From: Toni500github <88878648+Toni500github@users.noreply.github.com> Date: Fri, 11 Oct 2024 13:19:16 +0200 Subject: [PATCH 0510/2181] internal: improve version query and define HYPRLAND_VERSION (#8034) --- CMakeLists.txt | 2 ++ hyprpm/src/core/PluginManager.cpp | 3 +-- meson.build | 1 + src/debug/HyprCtl.cpp | 23 +++++++++++++-------- src/debug/HyprCtl.hpp | 1 + src/main.cpp | 34 +++++-------------------------- 6 files changed, 25 insertions(+), 39 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 4de449dc..df919d76 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -71,6 +71,8 @@ else() message(STATUS "Configuring Hyprland in Release with CMake") endif() +add_compile_definitions(HYPRLAND_VERSION="${HYPRLAND_VERSION}") + include_directories(. "src/" "protocols/") set(CMAKE_CXX_STANDARD 26) diff --git a/hyprpm/src/core/PluginManager.cpp b/hyprpm/src/core/PluginManager.cpp index 612995dc..96ec60ad 100644 --- a/hyprpm/src/core/PluginManager.cpp +++ b/hyprpm/src/core/PluginManager.cpp @@ -440,8 +440,7 @@ bool CPluginManager::updateHeaders(bool force) { // let us give a bit of leg-room for shallowing // due to timezones, etc. - const std::string SHALLOW_DATE = - trim(HLVER.date).empty() ? "" : execAndGet("LC_TIME=\"en_US.UTF-8\" date --date='" + HLVER.date + " - 1 weeks' '+\%a \%b \%d \%H:\%M:\%S \%Y'"); + const std::string SHALLOW_DATE = trim(HLVER.date).empty() ? "" : execAndGet("LC_TIME=\"en_US.UTF-8\" date --date='" + HLVER.date + " - 1 weeks' '+%a %b %d %H:%M:%S %Y'"); if (m_bVerbose && bShallow) progress.printMessageAbove(std::string{Colors::BLUE} + "[v] " + Colors::RESET + "will shallow since: " + SHALLOW_DATE); diff --git a/meson.build b/meson.build index e9bbb99d..33e8fdbe 100644 --- a/meson.build +++ b/meson.build @@ -21,6 +21,7 @@ add_project_arguments( '-Wno-missing-field-initializers', '-Wno-narrowing', '-Wno-pointer-arith', datarootdir, + '-DHYPRLAND_VERSION="' + meson.project_version() + '"', ], language: 'cpp', ) diff --git a/src/debug/HyprCtl.cpp b/src/debug/HyprCtl.cpp index d9274727..e0bb2b83 100644 --- a/src/debug/HyprCtl.cpp +++ b/src/debug/HyprCtl.cpp @@ -853,26 +853,33 @@ std::string versionRequest(eHyprCtlOutputFormat format, std::string request) { std::replace(commitMsg.begin(), commitMsg.end(), '#', ' '); if (format == eHyprCtlOutputFormat::FORMAT_NORMAL) { - std::string result = "Hyprland, built from branch " + std::string(GIT_BRANCH) + " at commit " + GIT_COMMIT_HASH + " " + GIT_DIRTY + " (" + commitMsg + - ").\nDate: " + GIT_COMMIT_DATE + "\nTag: " + GIT_TAG + ", commits: " + GIT_COMMITS + std::string{"\nbuilt against aquamarine "} + AQUAMARINE_VERSION + "\n" + - "\n\nflags: (if any)\n"; + std::string result = std::format("Hyprland {} built from branch {} at commit {} {} ({}).\n" + "Date: {}\n" + "Tag: {}, commits: {}\n" + "built against aquamarine {}\n\n\n", + HYPRLAND_VERSION, GIT_BRANCH, GIT_COMMIT_HASH, GIT_DIRTY, commitMsg, GIT_COMMIT_DATE, GIT_TAG, GIT_COMMITS, AQUAMARINE_VERSION); +#if (!defined(LEGACY_RENDERER) && !defined(ISDEBUG) && !defined(NO_XWAYLAND)) + result += "no flags were set\n"; +#else + result += "flags set:\n"; #ifdef LEGACY_RENDERER result += "legacyrenderer\n"; #endif -#ifndef ISDEBUG +#ifdef ISDEBUG result += "debug\n"; #endif #ifdef NO_XWAYLAND result += "no xwayland\n"; #endif - +#endif return result; } else { std::string result = std::format( R"#({{ "branch": "{}", "commit": "{}", + "version": "{}", "dirty": {}, "commit_message": "{}", "commit_date": "{}", @@ -880,13 +887,13 @@ std::string versionRequest(eHyprCtlOutputFormat format, std::string request) { "commits": "{}", "buildAquamarine": "{}", "flags": [)#", - GIT_BRANCH, GIT_COMMIT_HASH, (strcmp(GIT_DIRTY, "dirty") == 0 ? "true" : "false"), escapeJSONStrings(commitMsg), GIT_COMMIT_DATE, GIT_TAG, GIT_COMMITS, - AQUAMARINE_VERSION); + GIT_BRANCH, GIT_COMMIT_HASH, HYPRLAND_VERSION, (strcmp(GIT_DIRTY, "dirty") == 0 ? "true" : "false"), escapeJSONStrings(commitMsg), GIT_COMMIT_DATE, GIT_TAG, + GIT_COMMITS, AQUAMARINE_VERSION); #ifdef LEGACY_RENDERER result += "\"legacyrenderer\","; #endif -#ifndef ISDEBUG +#ifdef ISDEBUG result += "\"debug\","; #endif #ifdef NO_XWAYLAND diff --git a/src/debug/HyprCtl.hpp b/src/debug/HyprCtl.hpp index d68bf14f..c1bf51ca 100644 --- a/src/debug/HyprCtl.hpp +++ b/src/debug/HyprCtl.hpp @@ -7,6 +7,7 @@ // exposed for main.cpp std::string systemInfoRequest(eHyprCtlOutputFormat format, std::string request); +std::string versionRequest(eHyprCtlOutputFormat format, std::string request); class CHyprCtl { public: diff --git a/src/main.cpp b/src/main.cpp index 57bb5507..45f212d3 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -23,6 +23,7 @@ void help() { std::cout << " --config FILE -c FILE - Specify config file to use\n"; std::cout << " --socket NAME - Sets the Wayland socket name (for Wayland socket handover)\n"; std::cout << " --wayland-fd FD - Sets the Wayland socket fd (for Wayland socket handover)\n"; + std::cout << " --systeminfo - Prints system infos\n"; std::cout << " --i-am-really-stupid - Omits root user privileges check (why would you do that?)\n"; std::cout << " --version -v - Print this binary's version\n"; } @@ -33,9 +34,9 @@ int main(int argc, char** argv) { throwError("XDG_RUNTIME_DIR is not set!"); // export HYPRLAND_CMD - std::string cmd = ""; - for (auto i = 0; i < argc; ++i) - cmd += std::string(i == 0 ? "" : " ") + argv[i]; + std::string cmd = argv[0]; + for (int i = 1; i < argc; ++i) + cmd += std::string(" ") + argv[i]; setenv("HYPRLAND_CMD", cmd.c_str(), 1); setenv("XDG_BACKEND", "wayland", 1); @@ -116,32 +117,7 @@ int main(int argc, char** argv) { return 0; } else if (it->compare("-v") == 0 || it->compare("--version") == 0) { - auto result = "Hyprland, built from branch " + std::string(GIT_BRANCH) + " at commit " + GIT_COMMIT_HASH; - auto dirty = std::string(GIT_DIRTY); - if (!dirty.empty()) - result += " " + dirty; - - auto commitMsg = trim(GIT_COMMIT_MESSAGE); - std::replace(commitMsg.begin(), commitMsg.end(), '#', ' '); - result += " (" + commitMsg + ")."; - - result += "\nDate: " + std::string(GIT_COMMIT_DATE); - result += "\nTag: " + std::string(GIT_TAG) + ", commits: " + std::string(GIT_COMMITS); - result += "\nbuilt against aquamarine " + std::string(AQUAMARINE_VERSION); - - result += "\n\nflags: (if any)\n"; - -#ifdef LEGACY_RENDERER - result += "legacyrenderer\n"; -#endif -#ifndef ISDEBUG - result += "debug\n"; -#endif -#ifdef NO_XWAYLAND - result += "no xwayland\n"; -#endif - - std::cout << result; + std::cout << versionRequest(eHyprCtlOutputFormat::FORMAT_NORMAL, "") << std::endl; return 0; } else if (it->compare("--systeminfo") == 0) { const auto SYSINFO = systemInfoRequest(eHyprCtlOutputFormat::FORMAT_NORMAL, ""); From f5db4839730643169b7e8b7fb6ae2fbb8743ebe9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Edgars=20C=C4=ABrulis?= Date: Sat, 12 Oct 2024 03:12:07 +0300 Subject: [PATCH 0511/2181] drm-timeline: Add check for conflicting acquire and release points (#8083) Signed-off-by: Edgars Cirulis --- src/protocols/DRMSyncobj.cpp | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/src/protocols/DRMSyncobj.cpp b/src/protocols/DRMSyncobj.cpp index 4993f1a4..a7f242ee 100644 --- a/src/protocols/DRMSyncobj.cpp +++ b/src/protocols/DRMSyncobj.cpp @@ -55,8 +55,13 @@ CDRMSyncobjSurfaceResource::CDRMSyncobjSurfaceResource(SP= pending.releasePoint) { + resource->error(WP_LINUX_DRM_SYNCOBJ_SURFACE_V1_ERROR_CONFLICTING_POINTS, "Acquire and release points are on the same timeline, and acquire >= release"); + surface->pending.rejected = true; + return; + } + } // wait for the acquire timeline to materialize auto materialized = pending.acquireTimeline->timeline->check(pending.acquirePoint, DRM_SYNCOBJ_WAIT_FLAGS_WAIT_AVAILABLE); From ee8116ac5dc412dce924a0163074ce7988dd0cfc Mon Sep 17 00:00:00 2001 From: UjinT34 <41110182+UjinT34@users.noreply.github.com> Date: Sat, 12 Oct 2024 03:29:51 +0300 Subject: [PATCH 0512/2181] input: Fix VRR for constrained cursors (#6877) --- src/Compositor.cpp | 4 +++ src/events/Windows.cpp | 19 +++++++++++-- src/helpers/Monitor.cpp | 8 +++++- src/helpers/Monitor.hpp | 2 ++ src/helpers/Timer.cpp | 5 ++-- src/helpers/Timer.hpp | 2 +- src/managers/AnimationManager.cpp | 2 +- src/managers/PointerManager.cpp | 43 +++++++++++++++++++++++++---- src/managers/PointerManager.hpp | 7 +++++ src/managers/SeatManager.hpp | 3 ++ src/managers/input/InputManager.cpp | 21 ++++++++++++-- src/managers/input/InputManager.hpp | 1 + 12 files changed, 100 insertions(+), 17 deletions(-) diff --git a/src/Compositor.cpp b/src/Compositor.cpp index 459aca11..dcc6422d 100644 --- a/src/Compositor.cpp +++ b/src/Compositor.cpp @@ -1,4 +1,5 @@ #include "Compositor.hpp" +#include "debug/Log.hpp" #include "helpers/Splashes.hpp" #include "config/ConfigValue.hpp" #include "managers/CursorManager.hpp" @@ -1380,6 +1381,9 @@ void CCompositor::changeWindowZOrder(PHLWINDOW pWindow, bool top) { if (!validMapped(pWindow)) return; + if (pWindow == (top ? m_vWindows.back() : m_vWindows.front())) + return; + auto moveToZ = [&](PHLWINDOW pw, bool top) -> void { if (top) { for (auto it = m_vWindows.begin(); it != m_vWindows.end(); ++it) { diff --git a/src/events/Windows.cpp b/src/events/Windows.cpp index 37f29130..e549907e 100644 --- a/src/events/Windows.cpp +++ b/src/events/Windows.cpp @@ -12,6 +12,7 @@ #include "../protocols/core/Compositor.hpp" #include "../protocols/ToplevelExport.hpp" #include "../xwayland/XSurface.hpp" +#include "managers/PointerManager.hpp" #include using namespace Hyprutils::String; @@ -758,8 +759,21 @@ void Events::listener_commitWindow(void* owner, void* data) { if (!PWINDOW->m_pWorkspace->m_bVisible) return; - g_pHyprRenderer->damageSurface(PWINDOW->m_pWLSurface->resource(), PWINDOW->m_vRealPosition.goal().x, PWINDOW->m_vRealPosition.goal().y, - PWINDOW->m_bIsX11 ? 1.0 / PWINDOW->m_fX11SurfaceScaledBy : 1.0); + const auto PMONITOR = g_pCompositor->getMonitorFromID(PWINDOW->m_iMonitorID); + + PMONITOR->debugLastPresentation(g_pSeatManager->isPointerFrameCommit ? "listener_commitWindow skip" : "listener_commitWindow"); + if (g_pSeatManager->isPointerFrameCommit) { + g_pSeatManager->isPointerFrameSkipped = false; + g_pSeatManager->isPointerFrameCommit = false; + } else + g_pHyprRenderer->damageSurface(PWINDOW->m_pWLSurface->resource(), PWINDOW->m_vRealPosition.goal().x, PWINDOW->m_vRealPosition.goal().y, + PWINDOW->m_bIsX11 ? 1.0 / PWINDOW->m_fX11SurfaceScaledBy : 1.0); + + if (g_pSeatManager->isPointerFrameSkipped) { + g_pPointerManager->sendStoredMovement(); + g_pSeatManager->sendPointerFrame(); + g_pSeatManager->isPointerFrameCommit = true; + } if (!PWINDOW->m_bIsX11) { PWINDOW->m_pSubsurfaceHead->recheckDamageForSubsurfaces(); @@ -767,7 +781,6 @@ void Events::listener_commitWindow(void* owner, void* data) { } // tearing: if solitary, redraw it. This still might be a single surface window - const auto PMONITOR = g_pCompositor->getMonitorFromID(PWINDOW->m_iMonitorID); if (PMONITOR && PMONITOR->solitaryClient.lock() == PWINDOW && PWINDOW->canBeTorn() && PMONITOR->tearingState.canTear && PWINDOW->m_pWLSurface->resource()->current.texture) { CRegion damageBox{PWINDOW->m_pWLSurface->resource()->accumulateCurrentBufferDamage()}; diff --git a/src/helpers/Monitor.cpp b/src/helpers/Monitor.cpp index f3e7de4e..091745df 100644 --- a/src/helpers/Monitor.cpp +++ b/src/helpers/Monitor.cpp @@ -16,6 +16,7 @@ #include "../protocols/core/Compositor.hpp" #include "sync/SyncTimeline.hpp" #include +#include "debug/Log.hpp" #include #include using namespace Hyprutils::String; @@ -384,7 +385,7 @@ bool CMonitor::shouldSkipScheduleFrameOnMouseEvent() { *PNOBREAK && output->state->state().adaptiveSync && activeWorkspace && activeWorkspace->m_bHasFullscreenWindow && activeWorkspace->m_efFullscreenMode == FSMODE_FULLSCREEN; // keep requested minimum refresh rate - if (shouldSkip && *PMINRR && lastPresentationTimer.getMillis() > 1000 / *PMINRR) { + if (shouldSkip && *PMINRR && lastPresentationTimer.getMillis() > 1000.0f / *PMINRR) { // damage whole screen because some previous cursor box damages were skipped damage.damageEntire(); return false; @@ -933,6 +934,11 @@ bool CMonitor::attemptDirectScanout() { return true; } +void CMonitor::debugLastPresentation(const std::string& message) { + Debug::log(TRACE, "{} (last presentation {} - {} fps)", message, lastPresentationTimer.getMillis(), + lastPresentationTimer.getMillis() > 0 ? 1000.0f / lastPresentationTimer.getMillis() : 0.0f); +} + CMonitorState::CMonitorState(CMonitor* owner) { m_pOwner = owner; } diff --git a/src/helpers/Monitor.hpp b/src/helpers/Monitor.hpp index f5068dba..ad8a823b 100644 --- a/src/helpers/Monitor.hpp +++ b/src/helpers/Monitor.hpp @@ -185,6 +185,8 @@ class CMonitor { bool attemptDirectScanout(); void setCTM(const Mat3x3& ctm); + void debugLastPresentation(const std::string& message); + bool m_bEnabled = false; bool m_bRenderingInitPassed = false; diff --git a/src/helpers/Timer.cpp b/src/helpers/Timer.cpp index 7b1726df..e00c5918 100644 --- a/src/helpers/Timer.cpp +++ b/src/helpers/Timer.cpp @@ -1,4 +1,5 @@ #include "Timer.hpp" +#include void CTimer::reset() { m_tpLastReset = std::chrono::steady_clock::now(); @@ -8,8 +9,8 @@ std::chrono::steady_clock::duration CTimer::getDuration() { return std::chrono::steady_clock::now() - m_tpLastReset; } -long CTimer::getMillis() { - return std::chrono::duration_cast(getDuration()).count(); +float CTimer::getMillis() { + return std::chrono::duration_cast(getDuration()).count() / 1000.f; } float CTimer::getSeconds() { diff --git a/src/helpers/Timer.hpp b/src/helpers/Timer.hpp index 827e7625..a58225d0 100644 --- a/src/helpers/Timer.hpp +++ b/src/helpers/Timer.hpp @@ -6,7 +6,7 @@ class CTimer { public: void reset(); float getSeconds(); - long getMillis(); + float getMillis(); const std::chrono::steady_clock::time_point& chrono() const; private: diff --git a/src/managers/AnimationManager.cpp b/src/managers/AnimationManager.cpp index 092d9721..0ff94f1f 100644 --- a/src/managers/AnimationManager.cpp +++ b/src/managers/AnimationManager.cpp @@ -259,7 +259,7 @@ void CAnimationManager::tick() { // manually schedule a frame if (PMONITOR) - g_pCompositor->scheduleFrameForMonitor(PMONITOR, Aquamarine::IOutput::AQ_SCHEDULE_CURSOR_SHAPE); + g_pCompositor->scheduleFrameForMonitor(PMONITOR, Aquamarine::IOutput::AQ_SCHEDULE_ANIMATION); } // do it here, because if this alters the animation vars deque we would be in trouble above. diff --git a/src/managers/PointerManager.cpp b/src/managers/PointerManager.cpp index cc9deec7..8c2a1bad 100644 --- a/src/managers/PointerManager.cpp +++ b/src/managers/PointerManager.cpp @@ -2,6 +2,7 @@ #include "../Compositor.hpp" #include "../config/ConfigValue.hpp" #include "../protocols/PointerGestures.hpp" +#include "../protocols/RelativePointer.hpp" #include "../protocols/FractionalScale.hpp" #include "../protocols/IdleNotify.hpp" #include "../protocols/core/Compositor.hpp" @@ -328,7 +329,7 @@ void CPointerManager::onCursorMoved() { continue; const auto CURSORPOS = getCursorPosForMonitor(m); - m->output->moveCursor(CURSORPOS); + m->output->moveCursor(CURSORPOS, m->shouldSkipScheduleFrameOnMouseEvent()); } if (recalc) @@ -342,7 +343,7 @@ bool CPointerManager::attemptHardwareCursor(SPmonitor.lock()); - state->monitor->output->moveCursor(CURSORPOS); + state->monitor->output->moveCursor(CURSORPOS, state->monitor->shouldSkipScheduleFrameOnMouseEvent()); auto texture = getCurrentCursorTexture(); @@ -385,7 +386,8 @@ bool CPointerManager::setHWCursorBuffer(SP state, SPcursorFrontBuffer = buf; - g_pCompositor->scheduleFrameForMonitor(state->monitor.get(), Aquamarine::IOutput::AQ_SCHEDULE_CURSOR_SHAPE); + if (!state->monitor->shouldSkipScheduleFrameOnMouseEvent()) + g_pCompositor->scheduleFrameForMonitor(state->monitor.get(), Aquamarine::IOutput::AQ_SCHEDULE_CURSOR_SHAPE); return true; } @@ -676,8 +678,11 @@ void CPointerManager::warpTo(const Vector2D& logical) { damageIfSoftware(); pointerPos = closestValid(logical); - recheckEnteredOutputs(); - onCursorMoved(); + + if (!g_pInputManager->isLocked()) { + recheckEnteredOutputs(); + onCursorMoved(); + } damageIfSoftware(); } @@ -859,7 +864,14 @@ void CPointerManager::attachPointer(SP pointer) { }); listener->frame = pointer->pointerEvents.frame.registerListener([this] (std::any e) { - g_pSeatManager->sendPointerFrame(); + bool shouldSkip = false; + if (!g_pSeatManager->mouse.expired() && g_pInputManager->isLocked()) { + auto PMONITOR = g_pCompositor->m_pLastMonitor.get(); + shouldSkip = PMONITOR && PMONITOR->shouldSkipScheduleFrameOnMouseEvent(); + } + g_pSeatManager->isPointerFrameSkipped = shouldSkip; + if (!g_pSeatManager->isPointerFrameSkipped) + g_pSeatManager->sendPointerFrame(); }); listener->swipeBegin = pointer->pointerEvents.swipeBegin.registerListener([this] (std::any e) { @@ -1080,3 +1092,22 @@ void CPointerManager::damageCursor(SP pMonitor) { Vector2D CPointerManager::cursorSizeLogical() { return currentCursorImage.size / currentCursorImage.scale; } + +void CPointerManager::storeMovement(uint64_t time, const Vector2D& delta, const Vector2D& deltaUnaccel) { + storedTime = time; + storedDelta += delta; + storedUnaccel += deltaUnaccel; +} + +void CPointerManager::setStoredMovement(uint64_t time, const Vector2D& delta, const Vector2D& deltaUnaccel) { + storedTime = time; + storedDelta = delta; + storedUnaccel = deltaUnaccel; +} + +void CPointerManager::sendStoredMovement() { + PROTO::relativePointer->sendRelativeMotion((uint64_t)storedTime * 1000, storedDelta, storedUnaccel); + storedTime = 0; + storedDelta = Vector2D{}; + storedUnaccel = Vector2D{}; +} diff --git a/src/managers/PointerManager.hpp b/src/managers/PointerManager.hpp index 4a4c4f61..6b89eb16 100644 --- a/src/managers/PointerManager.hpp +++ b/src/managers/PointerManager.hpp @@ -61,6 +61,9 @@ class CPointerManager { // Vector2D position(); Vector2D cursorSizeLogical(); + void storeMovement(uint64_t time, const Vector2D& delta, const Vector2D& deltaUnaccel); + void setStoredMovement(uint64_t time, const Vector2D& delta, const Vector2D& deltaUnaccel); + void sendStoredMovement(); void recheckEnteredOutputs(); @@ -154,6 +157,10 @@ class CPointerManager { Vector2D pointerPos = {0, 0}; + uint64_t storedTime = 0; + Vector2D storedDelta = {0, 0}; + Vector2D storedUnaccel = {0, 0}; + struct SMonitorPointerState { SMonitorPointerState(SP m) : monitor(m) {} ~SMonitorPointerState() {} diff --git a/src/managers/SeatManager.hpp b/src/managers/SeatManager.hpp index 5cc7eee0..e50f123f 100644 --- a/src/managers/SeatManager.hpp +++ b/src/managers/SeatManager.hpp @@ -128,6 +128,9 @@ class CSeatManager { void setGrab(SP grab); // nullptr removes SP seatGrab; + bool isPointerFrameSkipped = false; + bool isPointerFrameCommit = false; + private: struct SSeatResourceContainer { SSeatResourceContainer(SP); diff --git a/src/managers/input/InputManager.cpp b/src/managers/input/InputManager.cpp index 03c72919..eef5e040 100644 --- a/src/managers/input/InputManager.cpp +++ b/src/managers/input/InputManager.cpp @@ -87,6 +87,11 @@ void CInputManager::onMouseMoved(IPointer::SMotionEvent e) { const auto DELTA = *PNOACCEL == 1 ? e.unaccel : e.delta; + if (g_pSeatManager->isPointerFrameSkipped) + g_pPointerManager->storeMovement((uint64_t)e.timeMs, DELTA, e.unaccel); + else + g_pPointerManager->setStoredMovement((uint64_t)e.timeMs, DELTA, e.unaccel); + PROTO::relativePointer->sendRelativeMotion((uint64_t)e.timeMs * 1000, DELTA, e.unaccel); g_pPointerManager->move(DELTA); @@ -167,7 +172,7 @@ void CInputManager::mouseMoveUnified(uint32_t time, bool refocus) { m_vLastCursorPosFloored = MOUSECOORDSFLOORED; - const auto PMONITOR = g_pCompositor->getMonitorFromCursor(); + const auto PMONITOR = isLocked() && g_pCompositor->m_pLastMonitor ? g_pCompositor->m_pLastMonitor.get() : g_pCompositor->getMonitorFromCursor(); // this can happen if there are no displays hooked up to Hyprland if (PMONITOR == nullptr) @@ -184,9 +189,9 @@ void CInputManager::mouseMoveUnified(uint32_t time, bool refocus) { // constraints if (!g_pSeatManager->mouse.expired() && isConstrained()) { const auto SURF = CWLSurface::fromResource(g_pCompositor->m_pLastFocus.lock()); - const auto CONSTRAINT = SURF->constraint(); + const auto CONSTRAINT = SURF ? SURF->constraint() : nullptr; - if (SURF && CONSTRAINT) { + if (CONSTRAINT) { if (CONSTRAINT->isLocked()) { const auto HINT = CONSTRAINT->logicPositionHint(); g_pCompositor->warpCursorTo(HINT, true); @@ -1428,6 +1433,16 @@ bool CInputManager::isConstrained() { return false; } +bool CInputManager::isLocked() { + if (!isConstrained()) + return false; + + const auto SURF = CWLSurface::fromResource(g_pCompositor->m_pLastFocus.lock()); + const auto CONSTRAINT = SURF ? SURF->constraint() : nullptr; + + return CONSTRAINT && CONSTRAINT->isLocked(); +} + void CInputManager::updateCapabilities() { uint32_t caps = 0; diff --git a/src/managers/input/InputManager.hpp b/src/managers/input/InputManager.hpp index ebf00b2d..d5634796 100644 --- a/src/managers/input/InputManager.hpp +++ b/src/managers/input/InputManager.hpp @@ -108,6 +108,7 @@ class CInputManager { void unconstrainMouse(); bool isConstrained(); + bool isLocked(); Vector2D getMouseCoordsInternal(); void refocus(); From c3f7c9bbb52b9ad3d24ccfcc5c552ed16c9985a5 Mon Sep 17 00:00:00 2001 From: Vaxry Date: Sat, 12 Oct 2024 15:18:34 +0100 Subject: [PATCH 0513/2181] xcursor: don't crash on broken permissions in X themes ref #8079 --- src/managers/XCursorManager.cpp | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/src/managers/XCursorManager.cpp b/src/managers/XCursorManager.cpp index 1e7ca535..93ee7965 100644 --- a/src/managers/XCursorManager.cpp +++ b/src/managers/XCursorManager.cpp @@ -117,9 +117,11 @@ void CXCursorManager::loadTheme(std::string const& name, int size, float scale) cursors = loadStandardCursors(themeName, lastLoadSize); } else { for (auto const& p : paths) { - auto dirCursors = loadAllFromDir(p, lastLoadSize); - std::copy_if(dirCursors.begin(), dirCursors.end(), std::back_inserter(cursors), - [this](auto const& p) { return std::none_of(cursors.begin(), cursors.end(), [&p](auto const& dp) { return dp->shape == p->shape; }); }); + try { + auto dirCursors = loadAllFromDir(p, lastLoadSize); + std::copy_if(dirCursors.begin(), dirCursors.end(), std::back_inserter(cursors), + [this](auto const& p) { return std::none_of(cursors.begin(), cursors.end(), [&p](auto const& dp) { return dp->shape == p->shape; }); }); + } catch (std::exception& e) { Debug::log(ERR, "XCursor path {} can't be loaded: threw error {}", p, e.what()); } } } From 1822707c7e7394ce8c7572f2fe890763a307f499 Mon Sep 17 00:00:00 2001 From: Vaxry Date: Sat, 12 Oct 2024 17:56:46 +0100 Subject: [PATCH 0514/2181] drm-syncobj: fix crash on missing timelines fixes #8092 --- src/protocols/DRMSyncobj.cpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/protocols/DRMSyncobj.cpp b/src/protocols/DRMSyncobj.cpp index a7f242ee..1da4baaf 100644 --- a/src/protocols/DRMSyncobj.cpp +++ b/src/protocols/DRMSyncobj.cpp @@ -55,6 +55,9 @@ CDRMSyncobjSurfaceResource::CDRMSyncobjSurfaceResource(SP= pending.releasePoint) { resource->error(WP_LINUX_DRM_SYNCOBJ_SURFACE_V1_ERROR_CONFLICTING_POINTS, "Acquire and release points are on the same timeline, and acquire >= release"); From e79d3cd2ef5632e2e6b3b20fd0b5dc4d2843f956 Mon Sep 17 00:00:00 2001 From: Toni500git Date: Sun, 13 Oct 2024 14:23:33 +0200 Subject: [PATCH 0515/2181] hyprpm: convert std::cout and std::cerr to std::println() --- hyprpm/src/core/DataState.cpp | 6 +- hyprpm/src/core/PluginManager.cpp | 267 ++++++++++++++------------- hyprpm/src/core/PluginManager.hpp | 3 +- hyprpm/src/helpers/StringUtils.hpp | 32 ++++ hyprpm/src/main.cpp | 35 ++-- hyprpm/src/progress/CProgressBar.cpp | 16 +- hyprpm/src/progress/CProgressBar.hpp | 2 +- 7 files changed, 202 insertions(+), 159 deletions(-) create mode 100644 hyprpm/src/helpers/StringUtils.hpp diff --git a/hyprpm/src/core/DataState.cpp b/hyprpm/src/core/DataState.cpp index 05c63f4e..fb8679d6 100644 --- a/hyprpm/src/core/DataState.cpp +++ b/hyprpm/src/core/DataState.cpp @@ -1,6 +1,6 @@ #include "DataState.hpp" #include -#include +#include #include #include #include "PluginManager.hpp" @@ -8,7 +8,7 @@ std::string DataState::getDataStatePath() { const auto HOME = getenv("HOME"); if (!HOME) { - std::cerr << "DataState: no $HOME\n"; + std::println(stderr, "DataState: no $HOME"); throw std::runtime_error("no $HOME"); return ""; } @@ -242,4 +242,4 @@ bool DataState::setPluginEnabled(const std::string& name, bool enabled) { } return false; -} \ No newline at end of file +} diff --git a/hyprpm/src/core/PluginManager.cpp b/hyprpm/src/core/PluginManager.cpp index 96ec60ad..359b2c78 100644 --- a/hyprpm/src/core/PluginManager.cpp +++ b/hyprpm/src/core/PluginManager.cpp @@ -1,12 +1,15 @@ #include "PluginManager.hpp" #include "../helpers/Colors.hpp" +#include "../helpers/StringUtils.hpp" #include "../progress/CProgressBar.hpp" #include "Manifest.hpp" #include "DataState.hpp" +#include #include #include #include +#include #include #include #include @@ -31,6 +34,7 @@ static std::string execAndGet(std::string cmd) { if (!pipe) return ""; + result.reserve(buffer.size()); while (fgets(buffer.data(), buffer.size(), pipe.get()) != nullptr) { result += buffer.data(); } @@ -47,10 +51,10 @@ SHyprlandVersion CPluginManager::getHyprlandVersion() { once = true; const auto HLVERCALL = execAndGet("hyprctl version"); if (m_bVerbose) - std::cout << Colors::BLUE << "[v] " << Colors::RESET << "version returned: " << HLVERCALL << "\n"; + std::println("{}", verboseString("version returned: {}", HLVERCALL)); if (!HLVERCALL.contains("Tag:")) { - std::cerr << "\n" << Colors::RED << "✖" << Colors::RESET << " You don't seem to be running Hyprland."; + std::println(stderr, "\n{}", failureString("You don't seem to be running Hyprland.")); return SHyprlandVersion{}; } @@ -76,7 +80,7 @@ SHyprlandVersion CPluginManager::getHyprlandVersion() { } catch (...) { ; } if (m_bVerbose) - std::cout << Colors::BLUE << "[v] " << Colors::RESET << "parsed commit " << hlcommit << " at branch " << hlbranch << " on " << hldate << ", commits " << commits << "\n"; + std::println("{}", verboseString("parsed commit {} at branch {} on {}, commits {}", hlcommit, hlbranch, hldate, commits)); ver = SHyprlandVersion{hlbranch, hlcommit, hldate, commits}; return ver; @@ -102,20 +106,21 @@ bool CPluginManager::addNewPluginRepo(const std::string& url, const std::string& const auto HLVER = getHyprlandVersion(); if (!hasDeps()) { - std::cerr << "\n" << Colors::RED << "✖" << Colors::RESET << " Could not clone the plugin repository. Dependencies not satisfied. Hyprpm requires: cmake, meson, cpio\n"; + std::println(stderr, "\n{}", failureString("Could not clone the plugin repository. Dependencies not satisfied. Hyprpm requires: cmake, meson, cpio")); return false; } if (DataState::pluginRepoExists(url)) { - std::cerr << "\n" << Colors::RED << "✖" << Colors::RESET << " Could not clone the plugin repository. Repository already installed.\n"; + std::println(stderr, "\n{}", failureString("Could not clone the plugin repository. Repository already installed.")); return false; } auto GLOBALSTATE = DataState::getGlobalState(); if (!GLOBALSTATE.dontWarnInstall) { - std::cout << Colors::YELLOW << "!" << Colors::RED << " Disclaimer:\n " << Colors::RESET - << "plugins, especially not official, have no guarantee of stability, availablity or security.\n Run them at your own risk.\n " - << "This message will not appear again.\n"; + std::println("{}!{} Disclaimer: {}", Colors::YELLOW, Colors::RED, Colors::RESET); + std::println("plugins, especially not official, have no guarantee of stability, availablity or security.\n" + "Run them at your own risk.\n" + "This message will not appear again."); GLOBALSTATE.dontWarnInstall = true; DataState::updateGlobalState(GLOBALSTATE); } @@ -129,7 +134,7 @@ bool CPluginManager::addNewPluginRepo(const std::string& url, const std::string& std::getline(std::cin, input); if (input.size() > 0 && input[0] != 'Y' && input[0] != 'y') { - std::cout << "Aborting.\n"; + std::println(stderr, "Aborting."); return false; } @@ -144,7 +149,7 @@ bool CPluginManager::addNewPluginRepo(const std::string& url, const std::string& std::filesystem::create_directory("/tmp/hyprpm"); std::filesystem::permissions("/tmp/hyprpm", std::filesystem::perms::all, std::filesystem::perm_options::replace); } else if (!std::filesystem::is_directory("/tmp/hyprpm")) { - std::cerr << "\n" << Colors::RED << "✖" << Colors::RESET << " Could not prepare working dir for hyprpm\n"; + std::println(stderr, "\n{}", failureString("Could not prepare working dir for hyprpm")); return false; } @@ -153,59 +158,59 @@ bool CPluginManager::addNewPluginRepo(const std::string& url, const std::string& m_szWorkingPluginDirectory = "/tmp/hyprpm/" + USERNAME; if (!createSafeDirectory(m_szWorkingPluginDirectory)) { - std::cerr << "\n" << Colors::RED << "✖" << Colors::RESET << " Could not prepare working dir for repo\n"; + std::println(stderr, "\n{}", failureString("Could not prepare working dir for repo")); return false; } - progress.printMessageAbove(std::string{Colors::RESET} + " → Cloning " + url); + progress.printMessageAbove(infoString("Cloning {}", url)); std::string ret = execAndGet("cd /tmp/hyprpm && git clone --recursive " + url + " " + USERNAME); if (!std::filesystem::exists(m_szWorkingPluginDirectory + "/.git")) { - std::cerr << "\n" << Colors::RED << "✖" << Colors::RESET << " Could not clone the plugin repository. shell returned:\n" << ret << "\n"; + std::println(stderr, "\n{}", failureString("Could not clone the plugin repository. shell returned:\n{}", ret)); return false; } if (!rev.empty()) { std::string ret = execAndGet("git -C " + m_szWorkingPluginDirectory + " reset --hard --recurse-submodules " + rev); if (ret.compare(0, 6, "fatal:") == 0) { - std::cerr << "\n" << Colors::RED << "✖" << Colors::RESET << " Could not check out revision " << rev << ". shell returned:\n" << ret << "\n"; + std::println(stderr, "\n{}", failureString("Could not check out revision {}. shell returned:\n{}", rev, ret)); return false; } ret = execAndGet("git -C " + m_szWorkingPluginDirectory + " submodule update --init"); if (m_bVerbose) - std::cout << Colors::BLUE << "[v] " << Colors::RESET << "git submodule update --init returned: " << ret << "\n"; + std::println("{}", verboseString("git submodule update --init returned: {}", ret)); } progress.m_iSteps = 1; - progress.printMessageAbove(std::string{Colors::GREEN} + "✔" + Colors::RESET + " cloned"); + progress.printMessageAbove(successString("cloned")); progress.m_szCurrentMessage = "Reading the manifest"; progress.print(); std::unique_ptr pManifest; if (std::filesystem::exists(m_szWorkingPluginDirectory + "/hyprpm.toml")) { - progress.printMessageAbove(std::string{Colors::GREEN} + "✔" + Colors::RESET + " found hyprpm manifest"); + progress.printMessageAbove(successString("found hyprpm manifest")); pManifest = std::make_unique(MANIFEST_HYPRPM, m_szWorkingPluginDirectory + "/hyprpm.toml"); } else if (std::filesystem::exists(m_szWorkingPluginDirectory + "/hyprload.toml")) { - progress.printMessageAbove(std::string{Colors::GREEN} + "✔" + Colors::RESET + " found hyprload manifest"); + progress.printMessageAbove(successString("found hyprload manifest")); pManifest = std::make_unique(MANIFEST_HYPRLOAD, m_szWorkingPluginDirectory + "/hyprload.toml"); } if (!pManifest) { - std::cerr << "\n" << Colors::RED << "✖" << Colors::RESET << " The provided plugin repository does not have a valid manifest\n"; + std::println(stderr, "\n{}", failureString("The provided plugin repository does not have a valid manifest")); return false; } if (!pManifest->m_bGood) { - std::cerr << "\n" << Colors::RED << "✖" << Colors::RESET << " The provided plugin repository has a corrupted manifest\n"; + std::println(stderr, "\n{}", failureString("The provided plugin repository has a corrupted manifest")); return false; } progress.m_iSteps = 2; - progress.printMessageAbove(std::string{Colors::GREEN} + "✔" + Colors::RESET + " parsed manifest, found " + std::to_string(pManifest->m_vPlugins.size()) + " plugins:"); + progress.printMessageAbove(successString("parsed manifest, found " + std::to_string(pManifest->m_vPlugins.size()) + " plugins:")); for (auto const& pl : pManifest->m_vPlugins) { - std::string message = std::string{Colors::RESET} + " → " + pl.name + " by "; + std::string message = "→ " + pl.name + " by "; for (auto const& a : pl.authors) { message += a + ", "; } @@ -220,19 +225,19 @@ bool CPluginManager::addNewPluginRepo(const std::string& url, const std::string& if (!pManifest->m_sRepository.commitPins.empty()) { // check commit pins - progress.printMessageAbove(std::string{Colors::RESET} + " → Manifest has " + std::to_string(pManifest->m_sRepository.commitPins.size()) + " pins, checking"); + progress.printMessageAbove(infoString("Manifest has {} pins, checking", pManifest->m_sRepository.commitPins.size())); for (auto const& [hl, plugin] : pManifest->m_sRepository.commitPins) { if (hl != HLVER.hash) continue; - progress.printMessageAbove(std::string{Colors::GREEN} + "✔" + Colors::RESET + " commit pin " + plugin + " matched hl, resetting"); + progress.printMessageAbove(successString("commit pin {} matched hl, resetting", plugin)); execAndGet("cd " + m_szWorkingPluginDirectory + " && git reset --hard --recurse-submodules " + plugin); ret = execAndGet("git -C " + m_szWorkingPluginDirectory + " submodule update --init"); if (m_bVerbose) - std::cout << Colors::BLUE << "[v] " << Colors::RESET << "git submodule update --init returned: " << ret << "\n"; + std::println("{}", verboseString("git submodule update --init returned: {}", ret)); break; } @@ -244,12 +249,12 @@ bool CPluginManager::addNewPluginRepo(const std::string& url, const std::string& const auto HEADERSSTATUS = headersValid(); if (HEADERSSTATUS != HEADERS_OK) { - std::cerr << "\n" << headerError(HEADERSSTATUS); + std::println("\n{}", headerError(HEADERSSTATUS)); return false; } progress.m_iSteps = 3; - progress.printMessageAbove(std::string{Colors::GREEN} + "✔" + Colors::RESET + " Hyprland headers OK"); + progress.printMessageAbove(successString("Hyprland headers OK")); progress.m_szCurrentMessage = "Building plugin(s)"; progress.print(); @@ -257,35 +262,36 @@ bool CPluginManager::addNewPluginRepo(const std::string& url, const std::string& std::string out; if (p.since > HLVER.commits && HLVER.commits >= 1 /* for --depth 1 clones, we can't check this. */) { - progress.printMessageAbove(std::string{Colors::RED} + "✖" + Colors::RESET + " Not building " + p.name + ": your Hyprland version is too old.\n"); + progress.printMessageAbove(failureString("Not building {}: your Hyprland version is too old.\n", p.name)); p.failed = true; continue; } - progress.printMessageAbove(std::string{Colors::RESET} + " → Building " + p.name); + progress.printMessageAbove(infoString("Building {}", p.name)); for (auto const& bs : p.buildSteps) { - std::string cmd = std::format("cd {} && PKG_CONFIG_PATH=\"{}/share/pkgconfig\" {}", m_szWorkingPluginDirectory, DataState::getHeadersPath(), bs); + const std::string& cmd = std::format("cd {} && PKG_CONFIG_PATH=\"{}/share/pkgconfig\" {}", m_szWorkingPluginDirectory, DataState::getHeadersPath(), bs); out += " -> " + cmd + "\n" + execAndGet(cmd) + "\n"; } if (m_bVerbose) - std::cout << Colors::BLUE << "[v] " << Colors::RESET << "shell returned: " << out << "\n"; + std::println("{}", verboseString("shell returned: " + out)); if (!std::filesystem::exists(m_szWorkingPluginDirectory + "/" + p.output)) { - progress.printMessageAbove(std::string{Colors::RED} + "✖" + Colors::RESET + " Plugin " + p.name + " failed to build.\n" + - " This likely means that the plugin is either outdated, not yet available for your version, or broken.\n If you are on -git, update " - "first.\n Try re-running with -v to see " - "more verbose output.\n"); + progress.printMessageAbove(failureString("Plugin {} failed to build.\n" + " This likely means that the plugin is either outdated, not yet available for your version, or broken.\n" + " If you are on -git, update first\n" + " Try re-running with -v to see more verbose output.\n", + p.name)); p.failed = true; continue; } - progress.printMessageAbove(std::string{Colors::GREEN} + "✔" + Colors::RESET + " built " + p.name + " into " + p.output); + progress.printMessageAbove(successString("built {} into {}", p.name, p.output)); } - progress.printMessageAbove(std::string{Colors::GREEN} + "✔" + Colors::RESET + " all plugins built"); + progress.printMessageAbove(successString("all plugins built")); progress.m_iSteps = 4; progress.m_szCurrentMessage = "Installing repository"; progress.print(); @@ -304,13 +310,13 @@ bool CPluginManager::addNewPluginRepo(const std::string& url, const std::string& } DataState::addNewPluginRepo(repo); - progress.printMessageAbove(std::string{Colors::GREEN} + "✔" + Colors::RESET + " installed repository"); - progress.printMessageAbove(std::string{Colors::GREEN} + "✔" + Colors::RESET + " you can now enable the plugin(s) with hyprpm enable"); + progress.printMessageAbove(successString("installed repository")); + progress.printMessageAbove(successString("you can now enable the plugin(s) with hyprpm enable")); progress.m_iSteps = 5; progress.m_szCurrentMessage = "Done!"; progress.print(); - std::cout << "\n"; + std::print("\n"); // remove build files std::filesystem::remove_all(m_szWorkingPluginDirectory); @@ -320,7 +326,7 @@ bool CPluginManager::addNewPluginRepo(const std::string& url, const std::string& bool CPluginManager::removePluginRepo(const std::string& urlOrName) { if (!DataState::pluginRepoExists(urlOrName)) { - std::cerr << "\n" << Colors::RED << "✖" << Colors::RESET << " Could not remove the repository. Repository is not installed.\n"; + std::println(stderr, "\n{}", failureString("Could not remove the repository. Repository is not installed.")); return false; } @@ -331,7 +337,7 @@ bool CPluginManager::removePluginRepo(const std::string& urlOrName) { std::getline(std::cin, input); if (input.size() > 0 && input[0] != 'Y' && input[0] != 'y') { - std::cout << "Aborting.\n"; + std::println("Aborting."); return false; } @@ -347,15 +353,15 @@ eHeadersErrors CPluginManager::headersValid() { return HEADERS_MISSING; // find headers commit - std::string cmd = std::format("PKG_CONFIG_PATH=\"{}/share/pkgconfig\" pkgconf --cflags --keep-system-cflags hyprland", DataState::getHeadersPath()); - auto headers = execAndGet(cmd.c_str()); + const std::string& cmd = std::format("PKG_CONFIG_PATH=\"{}/share/pkgconfig\" pkgconf --cflags --keep-system-cflags hyprland", DataState::getHeadersPath()); + auto headers = execAndGet(cmd.c_str()); if (!headers.contains("-I/")) return HEADERS_MISSING; headers.pop_back(); // pop newline - std::string verHeader = ""; + std::string verHeader; while (!headers.empty()) { const auto PATH = headers.substr(0, headers.find(" -I/", 3)); @@ -406,7 +412,7 @@ bool CPluginManager::updateHeaders(bool force) { const auto HLVER = getHyprlandVersion(); if (!hasDeps()) { - std::cerr << "\n" << Colors::RED << "✖" << Colors::RESET << " Could not update. Dependencies not satisfied. Hyprpm requires: cmake, meson, cpio\n"; + std::println("\n{}", failureString("Could not update. Dependencies not satisfied. Hyprpm requires: cmake, meson, cpio")); return false; } @@ -416,7 +422,7 @@ bool CPluginManager::updateHeaders(bool force) { } if (!force && headersValid() == HEADERS_OK) { - std::cout << "\n" << std::string{Colors::GREEN} + "✔" + Colors::RESET + " Headers up to date.\n"; + std::println("\n{}", successString("Headers up to date.")); return true; } @@ -430,11 +436,11 @@ bool CPluginManager::updateHeaders(bool force) { const auto WORKINGDIR = "/tmp/hyprpm/hyprland-" + USERNAME; if (!createSafeDirectory(WORKINGDIR)) { - std::cerr << "\n" << Colors::RED << "✖" << Colors::RESET << " Could not prepare working dir for hl\n"; + std::println("\n{}", failureString("Could not prepare working dir for hl")); return false; } - progress.printMessageAbove(std::string{Colors::YELLOW} + "!" + Colors::RESET + " Cloning https://github.com/hyprwm/hyprland, this might take a moment."); + progress.printMessageAbove(statusString("!", Colors::YELLOW, "Cloning https://github.com/hyprwm/Hyprland, this might take a moment.")); const bool bShallow = (HLVER.branch == "main") && !m_bNoShallow; @@ -443,60 +449,60 @@ bool CPluginManager::updateHeaders(bool force) { const std::string SHALLOW_DATE = trim(HLVER.date).empty() ? "" : execAndGet("LC_TIME=\"en_US.UTF-8\" date --date='" + HLVER.date + " - 1 weeks' '+%a %b %d %H:%M:%S %Y'"); if (m_bVerbose && bShallow) - progress.printMessageAbove(std::string{Colors::BLUE} + "[v] " + Colors::RESET + "will shallow since: " + SHALLOW_DATE); + progress.printMessageAbove(verboseString("will shallow since: {}", SHALLOW_DATE)); std::string ret = - execAndGet("cd /tmp/hyprpm && git clone --recursive https://github.com/hyprwm/hyprland hyprland-" + USERNAME + (bShallow ? " --shallow-since='" + SHALLOW_DATE + "'" : "")); + execAndGet("cd /tmp/hyprpm && git clone --recursive https://github.com/hyprwm/Hyprland hyprland-" + USERNAME + (bShallow ? " --shallow-since='" + SHALLOW_DATE + "'" : "")); if (!std::filesystem::exists(WORKINGDIR)) { - progress.printMessageAbove(std::string{Colors::RED} + "✖" + Colors::RESET + " Clone failed. Retrying without shallow."); + progress.printMessageAbove(failureString("Clone failed. Retrying without shallow.")); ret = execAndGet("cd /tmp/hyprpm && git clone --recursive https://github.com/hyprwm/hyprland hyprland-" + USERNAME); } if (!std::filesystem::exists(WORKINGDIR + "/.git")) { - std::cerr << "\n" << Colors::RED << "✖" << Colors::RESET << " Could not clone the hyprland repository. shell returned:\n" << ret << "\n"; + std::println(stderr, "\n{}", failureString("Could not clone the Hyprland repository. shell returned:\n{}", ret)); return false; } - progress.printMessageAbove(std::string{Colors::GREEN} + "✔" + Colors::RESET + " cloned"); + progress.printMessageAbove(successString("Hyprland cloned")); progress.m_iSteps = 2; progress.m_szCurrentMessage = "Checking out sources"; progress.print(); if (m_bVerbose) - progress.printMessageAbove(std::string{Colors::BLUE} + "[v] " + Colors::RESET + "will run: " + "cd " + WORKINGDIR + " && git checkout " + HLVER.hash + " 2>&1"); + progress.printMessageAbove(verboseString("will run: cd {} && git checkout {} 2>&1", WORKINGDIR, HLVER.hash)); ret = execAndGet("cd " + WORKINGDIR + " && git checkout " + HLVER.hash + " 2>&1"); if (ret.contains("fatal: unable to read tree")) { - std::cerr << "\n" - << Colors::RED << "✖" << Colors::RESET - << " Could not checkout the running Hyprland commit. If you are on -git, try updating.\nYou can also try re-running hyprpm update with --no-shallow.\n"; + std::println(stderr, "\n{}", + failureString("Could not checkout the running Hyprland commit. If you are on -git, try updating.\n" + "You can also try re-running hyprpm update with --no-shallow.")); return false; } if (m_bVerbose) - progress.printMessageAbove(std::string{Colors::BLUE} + "[v] " + Colors::RESET + "git returned (co): " + ret); + progress.printMessageAbove(verboseString("git returned (co): {}", ret)); ret = execAndGet("cd " + WORKINGDIR + " ; git rm subprojects/tracy ; git submodule update --init 2>&1 ; git reset --hard --recurse-submodules " + HLVER.hash); if (m_bVerbose) - progress.printMessageAbove(std::string{Colors::BLUE} + "[v] " + Colors::RESET + "git returned (rs): " + ret); + progress.printMessageAbove(verboseString("git returned (rs): {}", ret)); - progress.printMessageAbove(std::string{Colors::GREEN} + "✔" + Colors::RESET + " checked out to running ver"); + progress.printMessageAbove(successString("checked out to running ver")); progress.m_iSteps = 3; progress.m_szCurrentMessage = "Building Hyprland"; progress.print(); - progress.printMessageAbove(std::string{Colors::YELLOW} + "!" + Colors::RESET + " configuring Hyprland"); + progress.printMessageAbove(statusString("!", Colors::YELLOW, "configuring Hyprland")); if (m_bVerbose) - progress.printMessageAbove(std::string{Colors::BLUE} + "[v] " + Colors::RESET + "setting PREFIX for cmake to " + DataState::getHeadersPath()); + progress.printMessageAbove(verboseString("setting PREFIX for cmake to {}", DataState::getHeadersPath())); ret = execAndGet(std::format("cd {} && cmake --no-warn-unused-cli -DCMAKE_BUILD_TYPE:STRING=Release -DCMAKE_INSTALL_PREFIX:STRING=\"{}\" -S . -B ./build -G Ninja", WORKINGDIR, DataState::getHeadersPath())); if (m_bVerbose) - progress.printMessageAbove(std::string{Colors::BLUE} + "[v] " + Colors::RESET + "cmake returned: " + ret); + progress.printMessageAbove(verboseString("cmake returned: {}", ret)); if (ret.contains("CMake Error at")) { // missing deps, let the user know. @@ -505,48 +511,46 @@ bool CPluginManager::updateHeaders(bool force) { missing = missing.substr(0, missing.find("-- Configuring incomplete")); missing = missing.substr(0, missing.find_last_of('\n')); - std::cerr << "\n" - << Colors::RED << "✖" << Colors::RESET << " Could not configure the hyprland source, cmake complained:\n" - << missing << "\n\nThis likely means that you are missing the above dependencies or they are out of date.\n"; + std::println(stderr, "\n{}", + failureString("Could not configure the hyprland source, cmake complained:\n{}\n\n" + "This likely means that you are missing the above dependencies or they are out of date.", + missing)); return false; } - progress.printMessageAbove(std::string{Colors::GREEN} + "✔" + Colors::RESET + " configured Hyprland"); + progress.printMessageAbove(successString("configured Hyprland")); progress.m_iSteps = 4; progress.m_szCurrentMessage = "Installing sources"; progress.print(); - std::string cmd = + const std::string& cmd = std::format("sed -i -e \"s#PREFIX = /usr/local#PREFIX = {}#\" {}/Makefile && cd {} && make installheaders", DataState::getHeadersPath(), WORKINGDIR, WORKINGDIR); if (m_bVerbose) - progress.printMessageAbove(std::string{Colors::BLUE} + "[v] " + Colors::RESET + "installation will run: " + cmd); + progress.printMessageAbove(verboseString("installation will run: {}", cmd)); ret = execAndGet(cmd); if (m_bVerbose) - std::cout << Colors::BLUE << "[v] " << Colors::RESET << "installer returned: " << ret << "\n"; + std::println("{}", verboseString("installer returned: {}", ret)); // remove build files std::filesystem::remove_all(WORKINGDIR); auto HEADERSVALID = headersValid(); if (HEADERSVALID == HEADERS_OK) { - progress.printMessageAbove(std::string{Colors::GREEN} + "✔" + Colors::RESET + " installed headers"); + progress.printMessageAbove(successString("installed headers")); progress.m_iSteps = 5; progress.m_szCurrentMessage = "Done!"; progress.print(); - std::cout << "\n"; + std::print("\n"); } else { - progress.printMessageAbove(std::string{Colors::RED} + "✖" + Colors::RESET + " failed to install headers with error code " + std::to_string((int)HEADERSVALID) + " (" + - headerErrorShort(HEADERSVALID) + ")"); + progress.printMessageAbove(failureString("failed to install headers with error code {} ({})", (int)HEADERSVALID, headerErrorShort(HEADERSVALID))); progress.m_iSteps = 5; progress.m_szCurrentMessage = "Failed"; progress.print(); - std::cout << "\n"; - - std::cerr << "\n" << headerError(HEADERSVALID); + std::print(stderr, "\n\n{}", headerError(HEADERSVALID)); return false; } @@ -556,14 +560,14 @@ bool CPluginManager::updateHeaders(bool force) { bool CPluginManager::updatePlugins(bool forceUpdateAll) { if (headersValid() != HEADERS_OK) { - std::cout << "\n" << std::string{Colors::RED} + "✖" + Colors::RESET + " headers are not up-to-date, please run hyprpm update.\n"; + std::println("{}", failureString("headers are not up-to-date, please run hyprpm update.")); return false; } const auto REPOS = DataState::getAllRepositories(); if (REPOS.size() < 1) { - std::cout << "\n" << std::string{Colors::RED} + "✖" + Colors::RESET + " No repos to update.\n"; + std::println("{}", failureString("No repos to update.")); return true; } @@ -585,25 +589,26 @@ bool CPluginManager::updatePlugins(bool forceUpdateAll) { progress.m_szCurrentMessage = "Updating " + repo.name; progress.print(); - progress.printMessageAbove(std::string{Colors::RESET} + " → checking for updates for " + repo.name); + progress.printMessageAbove(infoString("checking for updates for {}", repo.name)); createSafeDirectory(m_szWorkingPluginDirectory); - progress.printMessageAbove(std::string{Colors::RESET} + " → Cloning " + repo.url); + progress.printMessageAbove(infoString("Cloning {}", repo.url)); std::string ret = execAndGet("cd /tmp/hyprpm && git clone --recursive " + repo.url + " " + USERNAME); if (!std::filesystem::exists(m_szWorkingPluginDirectory + "/.git")) { - std::cout << "\n" << std::string{Colors::RED} + "✖" + Colors::RESET + " could not clone repo: shell returned:\n" + ret; + std::println("{}", failureString("could not clone repo: shell returned: {}", ret)); return false; } if (!repo.rev.empty()) { - progress.printMessageAbove(std::string{Colors::RESET} + " → Plugin has revision set, resetting: " + repo.rev); + progress.printMessageAbove(infoString("Plugin has revision set, resetting: {}", repo.rev)); std::string ret = execAndGet("git -C " + m_szWorkingPluginDirectory + " reset --hard --recurse-submodules " + repo.rev); if (ret.compare(0, 6, "fatal:") == 0) { - std::cout << "\n" << std::string{Colors::RED} + "✖" + Colors::RESET + " could not check out revision " + repo.rev + ": shell returned:\n" + ret; + std::println(stderr, "\n{}", failureString("could not check out revision {}: shell returned:\n{}", repo.rev, ret)); + return false; } } @@ -619,7 +624,7 @@ bool CPluginManager::updatePlugins(bool forceUpdateAll) { if (!update) { std::filesystem::remove_all(m_szWorkingPluginDirectory); - progress.printMessageAbove(std::string{Colors::GREEN} + "✔" + Colors::RESET + " repository " + repo.name + " is up-to-date."); + progress.printMessageAbove(successString("repository {} is up-to-date.", repo.name)); progress.m_iSteps++; progress.print(); continue; @@ -627,41 +632,41 @@ bool CPluginManager::updatePlugins(bool forceUpdateAll) { // we need to update - progress.printMessageAbove(std::string{Colors::GREEN} + "✔" + Colors::RESET + " repository " + repo.name + " has updates."); - progress.printMessageAbove(std::string{Colors::RESET} + " → Building " + repo.name); + progress.printMessageAbove(successString("repository {} has updates.", repo.name)); + progress.printMessageAbove(infoString("Building {}", repo.name)); progress.m_iSteps++; progress.print(); std::unique_ptr pManifest; if (std::filesystem::exists(m_szWorkingPluginDirectory + "/hyprpm.toml")) { - progress.printMessageAbove(std::string{Colors::GREEN} + "✔" + Colors::RESET + " found hyprpm manifest"); + progress.printMessageAbove(successString("found hyprpm manifest")); pManifest = std::make_unique(MANIFEST_HYPRPM, m_szWorkingPluginDirectory + "/hyprpm.toml"); } else if (std::filesystem::exists(m_szWorkingPluginDirectory + "/hyprload.toml")) { - progress.printMessageAbove(std::string{Colors::GREEN} + "✔" + Colors::RESET + " found hyprload manifest"); + progress.printMessageAbove(successString("found hyprload manifest")); pManifest = std::make_unique(MANIFEST_HYPRLOAD, m_szWorkingPluginDirectory + "/hyprload.toml"); } if (!pManifest) { - std::cerr << "\n" << Colors::RED << "✖" << Colors::RESET << " The provided plugin repository does not have a valid manifest\n"; + std::println(stderr, "\n{}", failureString("The provided plugin repository does not have a valid manifest")); continue; } if (!pManifest->m_bGood) { - std::cerr << "\n" << Colors::RED << "✖" << Colors::RESET << " The provided plugin repository has a corrupted manifest\n"; + std::println(stderr, "\n{}", failureString("The provided plugin repository has a corrupted manifest")); continue; } if (repo.rev.empty() && !pManifest->m_sRepository.commitPins.empty()) { // check commit pins unless a revision is specified - progress.printMessageAbove(std::string{Colors::RESET} + " → Manifest has " + std::to_string(pManifest->m_sRepository.commitPins.size()) + " pins, checking"); + progress.printMessageAbove(infoString("Manifest has {} pins, checking", pManifest->m_sRepository.commitPins.size())); for (auto const& [hl, plugin] : pManifest->m_sRepository.commitPins) { if (hl != HLVER.hash) continue; - progress.printMessageAbove(std::string{Colors::GREEN} + "✔" + Colors::RESET + " commit pin " + plugin + " matched hl, resetting"); + progress.printMessageAbove(successString("commit pin {} matched hl, resetting", plugin)); execAndGet("cd " + m_szWorkingPluginDirectory + " && git reset --hard --recurse-submodules " + plugin); } @@ -671,32 +676,33 @@ bool CPluginManager::updatePlugins(bool forceUpdateAll) { std::string out; if (p.since > HLVER.commits && HLVER.commits >= 1000 /* for shallow clones, we can't check this. 1000 is an arbitrary number I chose. */) { - progress.printMessageAbove(std::string{Colors::RED} + "✖" + Colors::RESET + " Not building " + p.name + ": your Hyprland version is too old.\n"); + progress.printMessageAbove(failureString("Not building {}: your Hyprland version is too old.\n", p.name)); p.failed = true; continue; } - progress.printMessageAbove(std::string{Colors::RESET} + " → Building " + p.name); + progress.printMessageAbove(infoString("Building {}", p.name)); for (auto const& bs : p.buildSteps) { - std::string cmd = std::format("cd {} && PKG_CONFIG_PATH=\"{}/share/pkgconfig\" {}", m_szWorkingPluginDirectory, DataState::getHeadersPath(), bs); + const std::string& cmd = std::format("cd {} && PKG_CONFIG_PATH=\"{}/share/pkgconfig\" {}", m_szWorkingPluginDirectory, DataState::getHeadersPath(), bs); out += " -> " + cmd + "\n" + execAndGet(cmd) + "\n"; } if (m_bVerbose) - std::cout << Colors::BLUE << "[v] " << Colors::RESET << "shell returned: " << out << "\n"; + std::println("{}", verboseString("shell returned: {}", out)); if (!std::filesystem::exists(m_szWorkingPluginDirectory + "/" + p.output)) { - std::cerr << "\n" - << Colors::RED << "✖" << Colors::RESET << " Plugin " << p.name << " failed to build.\n" - << " This likely means that the plugin is either outdated, not yet available for your version, or broken.\n If you are on -git, update first.\n Try " - "re-running with -v to see more verbose " - "output.\n"; + std::println(stderr, + "\n{}\n" + " This likely means that the plugin is either outdated, not yet available for your version, or broken.\n" + "If you are on -git, update first.\n" + "Try re-running with -v to see more verbose output.", + failureString("Plugin {} failed to build.")); p.failed = true; continue; } - progress.printMessageAbove(std::string{Colors::GREEN} + "✔" + Colors::RESET + " built " + p.name + " into " + p.output); + progress.printMessageAbove(successString("built {} into {}", p.name, p.output)); } // add repo toml to DataState @@ -717,7 +723,7 @@ bool CPluginManager::updatePlugins(bool forceUpdateAll) { std::filesystem::remove_all(m_szWorkingPluginDirectory); - progress.printMessageAbove(std::string{Colors::GREEN} + "✔" + Colors::RESET + " updated " + repo.name); + progress.printMessageAbove(successString("updated {}", repo.name)); } progress.m_iSteps++; @@ -732,7 +738,7 @@ bool CPluginManager::updatePlugins(bool forceUpdateAll) { progress.m_szCurrentMessage = "Done!"; progress.print(); - std::cout << "\n"; + std::print("\n"); return true; } @@ -740,27 +746,27 @@ bool CPluginManager::updatePlugins(bool forceUpdateAll) { bool CPluginManager::enablePlugin(const std::string& name) { bool ret = DataState::setPluginEnabled(name, true); if (ret) - std::cout << Colors::GREEN << "✔" << Colors::RESET << " Enabled " << name << "\n"; + std::println("{}", successString("Enabled {}", name)); return ret; } bool CPluginManager::disablePlugin(const std::string& name) { bool ret = DataState::setPluginEnabled(name, false); if (ret) - std::cout << Colors::GREEN << "✔" << Colors::RESET << " Disabled " << name << "\n"; + std::println("{}", successString("Disabled {}", name)); return ret; } ePluginLoadStateReturn CPluginManager::ensurePluginsLoadState() { if (headersValid() != HEADERS_OK) { - std::cerr << "\n" << std::string{Colors::RED} + "✖" + Colors::RESET + " headers are not up-to-date, please run hyprpm update.\n"; + std::println(stderr, "\n{}", failureString("headers are not up-to-date, please run hyprpm update.")); return LOADSTATE_HEADERS_OUTDATED; } const auto HOME = getenv("HOME"); const auto HIS = getenv("HYPRLAND_INSTANCE_SIGNATURE"); if (!HOME || !HIS) { - std::cerr << "PluginManager: no $HOME or HIS\n"; + std::println(stderr, "PluginManager: no $HOME or HIS"); return LOADSTATE_FAIL; } const auto HYPRPMPATH = DataState::getDataStatePath() + "/"; @@ -769,14 +775,14 @@ ePluginLoadStateReturn CPluginManager::ensurePluginsLoadState() { std::vector loadedPlugins; - std::cout << Colors::GREEN << "✔" << Colors::RESET << " Ensuring plugin load state\n"; + std::println("{}", successString("Ensuring plugin load state")); // iterate line by line while (!pluginLines.empty()) { - auto plLine = pluginLines.substr(0, pluginLines.find("\n")); + auto plLine = pluginLines.substr(0, pluginLines.find('\n')); - if (pluginLines.find("\n") != std::string::npos) - pluginLines = pluginLines.substr(pluginLines.find("\n") + 1); + if (pluginLines.find('\n') != std::string::npos) + pluginLines = pluginLines.substr(pluginLines.find('\n') + 1); else pluginLines = ""; @@ -819,7 +825,7 @@ ePluginLoadStateReturn CPluginManager::ensurePluginsLoadState() { if (!enabled(p)) { // unload loadUnloadPlugin(HYPRPMPATH + repoForName(p) + "/" + p + ".so", false); - std::cout << Colors::GREEN << "✔" << Colors::RESET << " Unloaded " << p << "\n"; + std::println("{}", successString("Unloaded {}", p)); } } @@ -833,11 +839,11 @@ ePluginLoadStateReturn CPluginManager::ensurePluginsLoadState() { continue; loadUnloadPlugin(HYPRPMPATH + repoForName(p.name) + "/" + p.filename, true); - std::cout << Colors::GREEN << "✔" << Colors::RESET << " Loaded " << p.name << "\n"; + std::println("{}", successString("Loaded {}"), p.name); } } - std::cout << Colors::GREEN << "✔" << Colors::RESET << " Plugin load state ensured\n"; + std::println("{}", successString("Plugin load state ensured")); return LOADSTATE_OK; } @@ -855,16 +861,17 @@ void CPluginManager::listAllPlugins() { const auto REPOS = DataState::getAllRepositories(); for (auto const& r : REPOS) { - std::cout << std::string{Colors::RESET} + " → Repository " + r.name + ":\n"; + std::println("{}", infoString("Repository {}:", r.name)); for (auto const& p : r.plugins) { - - std::cout << std::string{Colors::RESET} + " │ Plugin " + p.name; + std::println(" │ Plugin {}", p.name); if (!p.failed) - std::cout << "\n └─ enabled: " << (p.enabled ? Colors::GREEN : Colors::RED) << (p.enabled ? "true" : "false") << Colors::RESET << "\n"; + std::println(" └─ enabled: {}", (p.enabled ? std::string{Colors::GREEN} + "true" : std::string{Colors::RED} + "false")); else - std::cout << "\n └─ enabled: " << Colors::RED << "Plugin failed to build" << Colors::RESET << "\n"; + std::println(" └─ enabled: {}Plugin failed to build", Colors::RED); + + std::println("{}", Colors::RESET); } } } @@ -875,19 +882,19 @@ void CPluginManager::notify(const eNotifyIcons icon, uint32_t color, int duratio std::string CPluginManager::headerError(const eHeadersErrors err) { switch (err) { - case HEADERS_CORRUPTED: return std::string{Colors::RED} + "✖" + Colors::RESET + " Headers corrupted. Please run hyprpm update to fix those.\n"; - case HEADERS_MISMATCHED: return std::string{Colors::RED} + "✖" + Colors::RESET + " Headers version mismatch. Please run hyprpm update to fix those.\n"; - case HEADERS_NOT_HYPRLAND: return std::string{Colors::RED} + "✖" + Colors::RESET + " It doesn't seem you are running on hyprland.\n"; - case HEADERS_MISSING: return std::string{Colors::RED} + "✖" + Colors::RESET + " Headers missing. Please run hyprpm update to fix those.\n"; + case HEADERS_CORRUPTED: return failureString("Headers corrupted. Please run hyprpm update to fix those.\n"); + case HEADERS_MISMATCHED: return failureString("Headers version mismatch. Please run hyprpm update to fix those.\n"); + case HEADERS_NOT_HYPRLAND: return failureString("It doesn't seem you are running on hyprland.\n"); + case HEADERS_MISSING: return failureString("Headers missing. Please run hyprpm update to fix those.\n"); case HEADERS_DUPLICATED: { - return std::string{Colors::RED} + "✖" + Colors::RESET + " Headers duplicated!!! This is a very bad sign.\n" + - " This could be due to e.g. installing hyprland manually while a system package of hyprland is also installed.\n" + - " If the above doesn't apply, check your /usr/include and /usr/local/include directories\n and remove all the hyprland headers.\n"; + return failureString("Headers duplicated!!! This is a very bad sign.\n" + "This could be due to e.g. installing hyprland manually while a system package of hyprland is also installed.\n" + "If the above doesn't apply, check your /usr/include and /usr/local/include directories\n and remove all the hyprland headers.\n"); } default: break; } - return std::string{Colors::RED} + "✖" + Colors::RESET + " Unknown header error. Please run hyprpm update to fix those.\n"; + return failureString("Unknown header error. Please run hyprpm update to fix those.\n"); } std::string CPluginManager::headerErrorShort(const eHeadersErrors err) { diff --git a/hyprpm/src/core/PluginManager.hpp b/hyprpm/src/core/PluginManager.hpp index c16a9d0f..d4603084 100644 --- a/hyprpm/src/core/PluginManager.hpp +++ b/hyprpm/src/core/PluginManager.hpp @@ -2,6 +2,7 @@ #include #include +#include enum eHeadersErrors { HEADERS_OK = 0, @@ -68,7 +69,7 @@ class CPluginManager { std::string headerError(const eHeadersErrors err); std::string headerErrorShort(const eHeadersErrors err); - std::string m_szWorkingPluginDirectory = ""; + std::string m_szWorkingPluginDirectory; }; inline std::unique_ptr g_pPluginManager; diff --git a/hyprpm/src/helpers/StringUtils.hpp b/hyprpm/src/helpers/StringUtils.hpp new file mode 100644 index 00000000..c1a5fd98 --- /dev/null +++ b/hyprpm/src/helpers/StringUtils.hpp @@ -0,0 +1,32 @@ +#pragma once + +#include +#include +#include "Colors.hpp" + +template +std::string statusString(const std::string_view emoji, const std::string_view color, const std::string_view fmt, Args&&... args) { + std::string ret = std::format("{}{}{} ", color, emoji, Colors::RESET); + ret += std::vformat(fmt, std::make_format_args(args...)); + return ret; +} + +template +std::string successString(const std::string_view fmt, Args&&... args) { + return statusString("✔", Colors::GREEN, fmt, args...); +} + +template +std::string failureString(const std::string_view fmt, Args&&... args) { + return statusString("✖", Colors::RED, fmt, args...); +} + +template +std::string verboseString(const std::string_view fmt, Args&&... args) { + return statusString("[v]", Colors::BLUE, fmt, args...); +} + +template +std::string infoString(const std::string_view fmt, Args&&... args) { + return statusString("→", Colors::RESET, fmt, args...); +} diff --git a/hyprpm/src/main.cpp b/hyprpm/src/main.cpp index 4f00f708..67f14aed 100644 --- a/hyprpm/src/main.cpp +++ b/hyprpm/src/main.cpp @@ -1,15 +1,16 @@ -#include "progress/CProgressBar.hpp" #include "helpers/Colors.hpp" +#include "helpers/StringUtils.hpp" #include "core/PluginManager.hpp" #include "core/DataState.hpp" -#include +#include #include #include +#include #include #include -const std::string HELP = R"#(┏ hyprpm, a Hyprland Plugin Manager +constexpr std::string_view HELP = R"#(┏ hyprpm, a Hyprland Plugin Manager ┃ ┣ add [url] [git rev] → Install a new plugin repository from git. Git revision ┃ is optional, when set, commit locks are ignored. @@ -30,14 +31,14 @@ const std::string HELP = R"#(┏ hyprpm, a Hyprland Plugin Manager ┗ )#"; -int main(int argc, char** argv, char** envp) { +int main(int argc, char** argv, char** envp) { std::vector ARGS{argc}; for (int i = 0; i < argc; ++i) { ARGS[i] = std::string{argv[i]}; } if (ARGS.size() < 2) { - std::cout << HELP; + std::println(stderr, "{}", HELP); return 1; } @@ -47,7 +48,7 @@ int main(int argc, char** argv, char** envp) { for (int i = 1; i < argc; ++i) { if (ARGS[i].starts_with("-")) { if (ARGS[i] == "--help" || ARGS[i] == "-h") { - std::cout << HELP; + std::println("{}", HELP); return 0; } else if (ARGS[i] == "--notify" || ARGS[i] == "-n") { notify = true; @@ -57,9 +58,9 @@ int main(int argc, char** argv, char** envp) { noShallow = true; } else if (ARGS[i] == "--force" || ARGS[i] == "-f") { force = true; - std::cout << Colors::RED << "!" << Colors::RESET << " Using --force, I hope you know what you are doing.\n"; + std::println("{}", statusString("!", Colors::RED, "Using --force, I hope you know what you are doing.")); } else { - std::cerr << "Unrecognized option " << ARGS[i] << "\n"; + std::println(stderr, "Unrecognized option {}", ARGS[i]); return 1; } } else { @@ -68,7 +69,7 @@ int main(int argc, char** argv, char** envp) { } if (command.empty()) { - std::cout << HELP; + std::println(stderr, "{}", HELP); return 0; } @@ -78,7 +79,7 @@ int main(int argc, char** argv, char** envp) { if (command[0] == "add") { if (command.size() < 2) { - std::cerr << Colors::RED << "✖" << Colors::RESET << " Not enough args for add.\n"; + std::println(stderr, "{}", failureString("Not enough args for add.")); return 1; } @@ -90,7 +91,7 @@ int main(int argc, char** argv, char** envp) { return g_pPluginManager->addNewPluginRepo(command[1], rev) ? 0 : 1; } else if (command[0] == "remove") { if (ARGS.size() < 2) { - std::cerr << Colors::RED << "✖" << Colors::RESET << " Not enough args for remove.\n"; + std::println(stderr, "{}", failureString("Not enough args for remove.")); return 1; } @@ -116,12 +117,12 @@ int main(int argc, char** argv, char** envp) { g_pPluginManager->notify(ICON_ERROR, 0, 10000, "[hyprpm] Couldn't update headers"); } else if (command[0] == "enable") { if (ARGS.size() < 2) { - std::cerr << Colors::RED << "✖" << Colors::RESET << " Not enough args for enable.\n"; + std::println(stderr, "{}", failureString("Not enough args for enable.")); return 1; } if (!g_pPluginManager->enablePlugin(command[1])) { - std::cerr << Colors::RED << "✖" << Colors::RESET << " Couldn't enable plugin (missing?)\n"; + std::println(stderr, "{}", failureString("Couldn't enable plugin (missing?)")); return 1; } @@ -130,12 +131,12 @@ int main(int argc, char** argv, char** envp) { return 1; } else if (command[0] == "disable") { if (command.size() < 2) { - std::cerr << Colors::RED << "✖" << Colors::RESET << " Not enough args for disable.\n"; + std::println(stderr, "{}", failureString("Not enough args for disable.")); return 1; } if (!g_pPluginManager->disablePlugin(command[1])) { - std::cerr << Colors::RED << "✖" << Colors::RESET << " Couldn't disable plugin (missing?)\n"; + std::println(stderr, "{}", failureString("Couldn't disable plugin (missing?)")); return 1; } @@ -160,9 +161,9 @@ int main(int argc, char** argv, char** envp) { } else if (command[0] == "list") { g_pPluginManager->listAllPlugins(); } else { - std::cout << HELP; + std::println(stderr, "{}", HELP); return 1; } return 0; -} \ No newline at end of file +} diff --git a/hyprpm/src/progress/CProgressBar.cpp b/hyprpm/src/progress/CProgressBar.cpp index 45602f82..9f2df08a 100644 --- a/hyprpm/src/progress/CProgressBar.cpp +++ b/hyprpm/src/progress/CProgressBar.cpp @@ -1,11 +1,11 @@ #include "CProgressBar.hpp" -#include +#include #include #include #include -#include +#include #include #include @@ -16,11 +16,12 @@ void CProgressBar::printMessageAbove(const std::string& msg) { ioctl(STDOUT_FILENO, TIOCGWINSZ, &w); std::string spaces; + spaces.reserve(w.ws_col); for (size_t i = 0; i < w.ws_col; ++i) { spaces += ' '; } - std::cout << "\r" << spaces << "\r" << msg << "\n"; + std::println("\r{}\r{}", spaces, msg); print(); } @@ -29,15 +30,16 @@ void CProgressBar::print() { ioctl(STDOUT_FILENO, TIOCGWINSZ, &w); if (m_bFirstPrint) - std::cout << "\n"; + std::print("\n"); m_bFirstPrint = false; std::string spaces; + spaces.reserve(w.ws_col); for (size_t i = 0; i < w.ws_col; ++i) { spaces += ' '; } - std::cout << "\r" << spaces << "\r"; + std::print("\r{}\r", spaces); std::string message = ""; @@ -74,7 +76,7 @@ void CProgressBar::print() { message += " " + std::format("{} / {}", m_iSteps, m_iMaxSteps) + " "; // draw message - std::cout << message + " " + m_szCurrentMessage; + std::print("{} {}", message, m_szCurrentMessage); std::fflush(stdout); -} \ No newline at end of file +} diff --git a/hyprpm/src/progress/CProgressBar.hpp b/hyprpm/src/progress/CProgressBar.hpp index 6ac18f21..dfcb36f7 100644 --- a/hyprpm/src/progress/CProgressBar.hpp +++ b/hyprpm/src/progress/CProgressBar.hpp @@ -14,4 +14,4 @@ class CProgressBar { private: bool m_bFirstPrint = true; -}; \ No newline at end of file +}; From b61d4c363679a880e8577a3d983d73dbab367a9d Mon Sep 17 00:00:00 2001 From: Toni500git Date: Sun, 13 Oct 2024 14:23:56 +0200 Subject: [PATCH 0516/2181] hyprctl: convert std::cout and std::cerr to std::println() --- hyprctl/Strings.hpp | 2 ++ hyprctl/main.cpp | 37 +++++++++++++++++++------------------ 2 files changed, 21 insertions(+), 18 deletions(-) diff --git a/hyprctl/Strings.hpp b/hyprctl/Strings.hpp index 17725e77..f77626a5 100644 --- a/hyprctl/Strings.hpp +++ b/hyprctl/Strings.hpp @@ -1,5 +1,7 @@ #pragma once +#include + const std::string_view USAGE = R"#(usage: hyprctl [flags] [args...|--help] commands: diff --git a/hyprctl/main.cpp b/hyprctl/main.cpp index 1ad189b7..1f7f8d74 100644 --- a/hyprctl/main.cpp +++ b/hyprctl/main.cpp @@ -17,6 +17,7 @@ #include #include +#include #include #include #include @@ -44,11 +45,11 @@ struct SInstanceData { bool valid = true; }; -void log(std::string str) { +void log(const std::string& str) { if (quiet) return; - std::cout << str << "\n"; + std::println("{}", str); } std::string getRuntimeDir() { @@ -105,7 +106,7 @@ std::vector instances() { static volatile bool sigintReceived = false; void intHandler(int sig) { sigintReceived = true; - std::cout << "[hyprctl] SIGINT received, closing connection" << std::endl; + std::println("[hyprctl] SIGINT received, closing connection"); } int rollingRead(const int socket) { @@ -115,12 +116,12 @@ int rollingRead(const int socket) { constexpr size_t BUFFER_SIZE = 8192; std::array buffer = {0}; long sizeWritten = 0; - std::cout << "[hyprctl] reading from socket following up log:" << std::endl; + std::println("[hyprctl] reading from socket following up log:"); while (!sigintReceived) { sizeWritten = read(socket, buffer.data(), BUFFER_SIZE); if (sizeWritten < 0 && errno != EAGAIN) { if (errno != EINTR) - std::cout << "Couldn't read (5) " << strerror(errno) << ":" << errno << std::endl; + std::println("Couldn't read (5): {}: {}", strerror(errno), errno); close(socket); return 5; } @@ -129,7 +130,7 @@ int rollingRead(const int socket) { break; if (sizeWritten > 0) { - std::cout << std::string(buffer.data(), sizeWritten); + std::println("{}", std::string(buffer.data(), sizeWritten)); buffer.fill('\0'); } @@ -323,7 +324,7 @@ int main(int argc, char** argv) { bool parseArgs = true; if (argc < 2) { - std::cout << USAGE << std::endl; + std::println("{}", USAGE); return 1; } @@ -360,7 +361,7 @@ int main(int argc, char** argv) { ++i; if (i >= ARGS.size()) { - std::cout << USAGE << std::endl; + std::println("{}", USAGE); return 1; } @@ -371,24 +372,24 @@ int main(int argc, char** argv) { const std::string& cmd = ARGS[0]; if (cmd == "hyprpaper") { - std::cout << HYPRPAPER_HELP << std::endl; + std::println("{}", HYPRPAPER_HELP); } else if (cmd == "notify") { - std::cout << NOTIFY_HELP << std::endl; + std::println("{}", NOTIFY_HELP); } else if (cmd == "output") { - std::cout << OUTPUT_HELP << std::endl; + std::println("{}", OUTPUT_HELP); } else if (cmd == "plugin") { - std::cout << PLUGIN_HELP << std::endl; + std::println("{}", PLUGIN_HELP); } else if (cmd == "setprop") { - std::cout << SETPROP_HELP << std::endl; + std::println("{}", SETPROP_HELP); } else if (cmd == "switchxkblayout") { - std::cout << SWITCHXKBLAYOUT_HELP << std::endl; + std::println("{}", SWITCHXKBLAYOUT_HELP); } else { - std::cout << USAGE << std::endl; + std::println("{}", USAGE); } return 1; } else { - std::cout << USAGE << std::endl; + std::println("{}", USAGE); return 1; } @@ -399,7 +400,7 @@ int main(int argc, char** argv) { } if (fullRequest.empty()) { - std::cout << USAGE << std::endl; + std::println("{}", USAGE); return 1; } @@ -476,7 +477,7 @@ int main(int argc, char** argv) { else if (fullRequest.contains("/decorations")) exitStatus = request(fullRequest, 1); else if (fullRequest.contains("/--help")) - std::cout << USAGE << std::endl; + std::println("{}", USAGE); else if (fullRequest.contains("/rollinglog") && needRoll) exitStatus = request(fullRequest, 0, true); else { From 05a5e0b4f1ced12f2a0330132f37b0081d7a5e4d Mon Sep 17 00:00:00 2001 From: Toni500git Date: Sun, 13 Oct 2024 14:24:10 +0200 Subject: [PATCH 0517/2181] hyprland: convert std::cout and std::cerr to std::println() --- src/Compositor.cpp | 14 +++++++------ src/debug/Log.cpp | 4 ++-- src/main.cpp | 51 ++++++++++++++++++++++++---------------------- 3 files changed, 37 insertions(+), 32 deletions(-) diff --git a/src/Compositor.cpp b/src/Compositor.cpp index dcc6422d..fd4979b0 100644 --- a/src/Compositor.cpp +++ b/src/Compositor.cpp @@ -9,7 +9,9 @@ #include "managers/eventLoop/EventLoopManager.hpp" #include #include +#include #include +#include #include #include #include @@ -138,37 +140,37 @@ CCompositor::CCompositor() { m_szHyprTempDataRoot = std::string{getenv("XDG_RUNTIME_DIR")} + "/hypr"; if (m_szHyprTempDataRoot.starts_with("/hypr")) { - std::cout << "Bailing out, XDG_RUNTIME_DIR is invalid\n"; + std::println("Bailing out, $XDG_RUNTIME_DIR is invalid"); throw std::runtime_error("CCompositor() failed"); } if (!m_szHyprTempDataRoot.starts_with("/run/user")) - std::cout << "[!!WARNING!!] XDG_RUNTIME_DIR looks non-standard. Proceeding anyways...\n"; + std::println("[!!WARNING!!] XDG_RUNTIME_DIR looks non-standard. Proceeding anyways..."); std::random_device dev; std::mt19937 engine(dev()); std::uniform_int_distribution<> distribution(0, INT32_MAX); - m_szInstanceSignature = GIT_COMMIT_HASH + std::string("_") + std::to_string(time(NULL)) + "_" + std::to_string(distribution(engine)); + m_szInstanceSignature = std::format("{}_{}_{}", GIT_COMMIT_HASH, std::time(NULL), distribution(engine)); setenv("HYPRLAND_INSTANCE_SIGNATURE", m_szInstanceSignature.c_str(), true); if (!std::filesystem::exists(m_szHyprTempDataRoot)) mkdir(m_szHyprTempDataRoot.c_str(), S_IRWXU); else if (!std::filesystem::is_directory(m_szHyprTempDataRoot)) { - std::cout << "Bailing out, " << m_szHyprTempDataRoot << " is not a directory\n"; + std::println("Bailing out, {} is not a directory", m_szHyprTempDataRoot); throw std::runtime_error("CCompositor() failed"); } m_szInstancePath = m_szHyprTempDataRoot + "/" + m_szInstanceSignature; if (std::filesystem::exists(m_szInstancePath)) { - std::cout << "Bailing out, " << m_szInstancePath << " exists??\n"; + std::println("Bailing out, {} exists??", m_szInstancePath); throw std::runtime_error("CCompositor() failed"); } if (mkdir(m_szInstancePath.c_str(), S_IRWXU) < 0) { - std::cout << "Bailing out, couldn't create " << m_szInstancePath << "\n"; + std::println("Bailing out, couldn't create {}", m_szInstancePath); throw std::runtime_error("CCompositor() failed"); } diff --git a/src/debug/Log.cpp b/src/debug/Log.cpp index a4c5b08e..5a314833 100644 --- a/src/debug/Log.cpp +++ b/src/debug/Log.cpp @@ -4,7 +4,7 @@ #include "RollingLogFollow.hpp" #include -#include +#include #include void Debug::init(const std::string& IS) { @@ -69,5 +69,5 @@ void Debug::log(LogLevel level, std::string str) { // log it to the stdout too. if (!disableStdout) - std::cout << ((coloredLogs && !**coloredLogs) ? str : coloredStr) << "\n"; + std::println("{}", ((coloredLogs && !**coloredLogs) ? str : coloredStr)); } diff --git a/src/main.cpp b/src/main.cpp index 45f212d3..6bbf73fd 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -5,7 +5,9 @@ #include "init/initHelpers.hpp" #include "debug/HyprCtl.hpp" +#include #include +#include using namespace Hyprutils::String; #include @@ -17,15 +19,15 @@ using namespace Hyprutils::String; #include void help() { - std::cout << "usage: Hyprland [arg [...]].\n"; - std::cout << "\nArguments:\n"; - std::cout << " --help -h - Show this message again\n"; - std::cout << " --config FILE -c FILE - Specify config file to use\n"; - std::cout << " --socket NAME - Sets the Wayland socket name (for Wayland socket handover)\n"; - std::cout << " --wayland-fd FD - Sets the Wayland socket fd (for Wayland socket handover)\n"; - std::cout << " --systeminfo - Prints system infos\n"; - std::cout << " --i-am-really-stupid - Omits root user privileges check (why would you do that?)\n"; - std::cout << " --version -v - Print this binary's version\n"; + std::println("usage: Hyprland [arg [...]].\n"); + std::println(R"(Arguments: + --help -h - Show this message again + --config FILE -c FILE - Specify config file to use + --socket NAME - Sets the Wayland socket name (for Wayland socket handover) + --wayland-fd FD - Sets the Wayland socket fd (for Wayland socket handover) + --systeminfo - Prints system infos + --i-am-really-stupid - Omits root user privileges check (why would you do that?) + --version -v - Print this binary's version)"); } int main(int argc, char** argv) { @@ -53,7 +55,7 @@ int main(int argc, char** argv) { for (auto it = args.begin(); it != args.end(); it++) { if (it->compare("--i-am-really-stupid") == 0 && !ignoreSudo) { - std::cout << "[ WARNING ] Running Hyprland with superuser privileges might damage your system\n"; + std::println("[ WARNING ] Running Hyprland with superuser privileges might damage your system"); ignoreSudo = true; } else if (it->compare("--socket") == 0) { @@ -79,7 +81,7 @@ int main(int argc, char** argv) { if (fcntl(socketFd, F_GETFD) == -1) throw std::exception(); } catch (...) { - std::cerr << "[ ERROR ] Invalid Wayland FD!\n"; + std::println(stderr, "[ ERROR ] Invalid Wayland FD!"); help(); return 1; @@ -101,7 +103,7 @@ int main(int argc, char** argv) { throw std::exception(); } } catch (...) { - std::cerr << "[ ERROR ] Config file '" << configPath << "' doesn't exist!\n"; + std::println(stderr, "[ ERROR ] Config file '{}' doesn't exist!", configPath); help(); return 1; @@ -117,14 +119,13 @@ int main(int argc, char** argv) { return 0; } else if (it->compare("-v") == 0 || it->compare("--version") == 0) { - std::cout << versionRequest(eHyprCtlOutputFormat::FORMAT_NORMAL, "") << std::endl; + std::println("{}", versionRequest(eHyprCtlOutputFormat::FORMAT_NORMAL, "")); return 0; } else if (it->compare("--systeminfo") == 0) { - const auto SYSINFO = systemInfoRequest(eHyprCtlOutputFormat::FORMAT_NORMAL, ""); - std::cout << SYSINFO << "\n"; + std::println("{}", systemInfoRequest(eHyprCtlOutputFormat::FORMAT_NORMAL, "")); return 0; } else { - std::cerr << "[ ERROR ] Unknown option '" << it->c_str() << "'!\n"; + std::println(stderr, "[ ERROR ] Unknown option '{}' !", it->c_str()); help(); return 1; @@ -132,30 +133,32 @@ int main(int argc, char** argv) { } if (!ignoreSudo && Init::isSudo()) { - std::cerr << "[ ERROR ] Hyprland was launched with superuser privileges, but the privileges check is not omitted.\n"; - std::cerr << " Hint: Use the --i-am-really-stupid flag to omit that check.\n"; + std::println(stderr, + "[ ERROR ] Hyprland was launched with superuser privileges, but the privileges check is not omitted.\n" + " Hint: Use the --i-am-really-stupid flag to omit that check."); return 1; } else if (ignoreSudo && Init::isSudo()) { - std::cout << "Superuser privileges check is omitted. I hope you know what you're doing.\n"; + std::println("Superuser privileges check is omitted. I hope you know what you're doing."); } if (socketName.empty() ^ (socketFd == -1)) { - std::cerr << "[ ERROR ] Hyprland was launched with only one of --socket and --wayland-fd.\n"; - std::cerr << " Hint: Pass both --socket and --wayland-fd to perform Wayland socket handover.\n"; + std::println(stderr, + "[ ERROR ] Hyprland was launched with only one of --socket and --wayland-fd.\n" + " Hint: Pass both --socket and --wayland-fd to perform Wayland socket handover."); return 1; } - std::cout << "Welcome to Hyprland!\n"; + std::println("Welcome to Hyprland!"); // let's init the compositor. // it initializes basic Wayland stuff in the constructor. try { g_pCompositor = std::make_unique(); g_pCompositor->explicitConfigPath = configPath; - } catch (std::exception& e) { - std::cout << "Hyprland threw in ctor: " << e.what() << "\nCannot continue.\n"; + } catch (const std::exception& e) { + std::println(stderr, "Hyprland threw in ctor: {}\nCannot continue.", e.what()); return 1; } From 5c3bd8e93d9f25be3e16a0445ba6fce8d30b6d73 Mon Sep 17 00:00:00 2001 From: Vaxry Date: Sun, 13 Oct 2024 17:26:39 +0100 Subject: [PATCH 0518/2181] notif-overlay: add a bit of padding for icons --- src/debug/HyprNotificationOverlay.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/debug/HyprNotificationOverlay.cpp b/src/debug/HyprNotificationOverlay.cpp index 29da20c8..16f80ab6 100644 --- a/src/debug/HyprNotificationOverlay.cpp +++ b/src/debug/HyprNotificationOverlay.cpp @@ -37,7 +37,7 @@ CHyprNotificationOverlay::~CHyprNotificationOverlay() { void CHyprNotificationOverlay::addNotification(const std::string& text, const CColor& color, const float timeMs, const eIcons icon, const float fontSize) { const auto PNOTIF = m_dNotifications.emplace_back(std::make_unique()).get(); - PNOTIF->text = text; + PNOTIF->text = icon != eIcons::ICON_NONE ? " " + text /* tiny bit of padding otherwise icon touches text */ : text; PNOTIF->color = color == CColor(0) ? ICONS_COLORS[icon] : color; PNOTIF->started.reset(); PNOTIF->timeMs = timeMs; From 8e51a36c7fd500e865e34f08ab4dc4331dca59cf Mon Sep 17 00:00:00 2001 From: Vaxry Date: Mon, 14 Oct 2024 00:19:10 +0100 Subject: [PATCH 0519/2181] config/example: add optional smart gaps to the default config ref #8106 #8114 --- example/hyprland.conf | 7 +++++++ src/config/defaultConfig.hpp | 7 +++++++ 2 files changed, 14 insertions(+) diff --git a/example/hyprland.conf b/example/hyprland.conf index 3478bcff..6d7bddb8 100644 --- a/example/hyprland.conf +++ b/example/hyprland.conf @@ -117,6 +117,13 @@ animations { animation = workspaces, 1, 6, default } +# Ref https://wiki.hyprland.org/Configuring/Workspace-Rules/ +# "Smart gaps" / "No gaps when only" +# uncomment all three if you wish to use that. +# workspace = w[t1], gapsout:0, gapsin:0, border: 0, rounding:0 +# workspace = w[tg1], gapsout:0, gapsin:0, border: 0, rounding:0 +# workspace = f[1], gapsout:0, gapsin:0, border: 0, rounding:0 + # See https://wiki.hyprland.org/Configuring/Dwindle-Layout/ for more dwindle { pseudotile = true # Master switch for pseudotiling. Enabling is bound to mainMod + P in the keybinds section below diff --git a/src/config/defaultConfig.hpp b/src/config/defaultConfig.hpp index 54ce6642..5c8b0e68 100644 --- a/src/config/defaultConfig.hpp +++ b/src/config/defaultConfig.hpp @@ -130,6 +130,13 @@ animations { animation = workspaces, 1, 6, default } +# Ref https://wiki.hyprland.org/Configuring/Workspace-Rules/ +# "Smart gaps" / "No gaps when only" +# uncomment all three if you wish to use that. +# workspace = w[t1], gapsout:0, gapsin:0, border: 0, rounding:0 +# workspace = w[tg1], gapsout:0, gapsin:0, border: 0, rounding:0 +# workspace = f[1], gapsout:0, gapsin:0, border: 0, rounding:0 + # See https://wiki.hyprland.org/Configuring/Dwindle-Layout/ for more dwindle { pseudotile = true # Master switch for pseudotiling. Enabling is bound to mainMod + P in the keybinds section below From abfd550ee228ea23058039790e792b45d2467c8d Mon Sep 17 00:00:00 2001 From: Vaxry Date: Mon, 14 Oct 2024 00:24:32 +0100 Subject: [PATCH 0520/2181] xwm: avoid infinite parent lookup loop in lookupParentExists ref #8045 --- src/xwayland/XWM.cpp | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/src/xwayland/XWM.cpp b/src/xwayland/XWM.cpp index dcb22eae..248813bf 100644 --- a/src/xwayland/XWM.cpp +++ b/src/xwayland/XWM.cpp @@ -150,10 +150,17 @@ void CXWM::handleUnmapNotify(xcb_unmap_notify_event_t* e) { } static bool lookupParentExists(SP XSURF, SP prospectiveChild) { + std::vector> visited; + while (XSURF->parent) { if (XSURF->parent == prospectiveChild) return true; + visited.emplace_back(XSURF); + XSURF = XSURF->parent.lock(); + + if (std::find(visited.begin(), visited.end(), XSURF) != visited.end()) + return false; } return false; From e7fd0f5aec85c11a8eaf5e1abf8504f0a6d0710e Mon Sep 17 00:00:00 2001 From: Aqa-Ib Date: Sun, 13 Oct 2024 23:25:19 +0000 Subject: [PATCH 0521/2181] layout: deny auto-grouping a new floating window into a tiled group (#8108) --- src/layout/IHyprLayout.cpp | 17 +++++++++++------ 1 file changed, 11 insertions(+), 6 deletions(-) diff --git a/src/layout/IHyprLayout.cpp b/src/layout/IHyprLayout.cpp index 24ee13f4..80c9abff 100644 --- a/src/layout/IHyprLayout.cpp +++ b/src/layout/IHyprLayout.cpp @@ -186,12 +186,17 @@ bool IHyprLayout::onWindowCreatedAutoGroup(PHLWINDOW pWindow) { g_pCompositor->m_pLastWindow.lock() : g_pCompositor->getFirstWindowOnWorkspace(pWindow->workspaceID()); - if (*PAUTOGROUP // check if auto_group is enabled. - && OPENINGON // check if OPENINGON exists. - && OPENINGON != pWindow // fixes a freeze when activating togglefloat to transform a floating group into a tiled group. - && OPENINGON->m_sGroupData.pNextWindow.lock() // check if OPENINGON is a group - && pWindow->canBeGroupedInto(OPENINGON) // check if the new window can be grouped into OPENINGON - && !g_pXWaylandManager->shouldBeFloated(pWindow)) { // don't group XWayland windows that should be floated. + bool denied = false; + if (pWindow->m_bIsFloating && !OPENINGON->m_bIsFloating) + denied = true; + + if (*PAUTOGROUP // check if auto_group is enabled. + && OPENINGON // check if OPENINGON exists. + && OPENINGON != pWindow // fixes a freeze when activating togglefloat to transform a floating group into a tiled group. + && OPENINGON->m_sGroupData.pNextWindow.lock() // check if OPENINGON is a group. + && pWindow->canBeGroupedInto(OPENINGON) // check if the new window can be grouped into OPENINGON. + && !g_pXWaylandManager->shouldBeFloated(pWindow) // don't group a new window that should be floated. + && !denied) { // don't group a new floated window into a tiled group. pWindow->m_bIsFloating = OPENINGON->m_bIsFloating; // match the floating state From ce62521883e217aab4da305d71e40e4a50567dfb Mon Sep 17 00:00:00 2001 From: Ikalco <73481042+ikalco@users.noreply.github.com> Date: Mon, 14 Oct 2024 05:37:42 -0500 Subject: [PATCH 0522/2181] drm-lease: fix crashes and implementation (#8116) --- src/protocols/DRMLease.cpp | 28 ++++++++++++++++++++-------- src/protocols/DRMLease.hpp | 3 ++- 2 files changed, 22 insertions(+), 9 deletions(-) diff --git a/src/protocols/DRMLease.cpp b/src/protocols/DRMLease.cpp index 37f2e2eb..d0114ce7 100644 --- a/src/protocols/DRMLease.cpp +++ b/src/protocols/DRMLease.cpp @@ -44,10 +44,6 @@ CDRMLeaseResource::CDRMLeaseResource(SP resource_, SPleaseFD); - - resource->sendLeaseFd(aqlease->leaseFD); - lease = aqlease; for (auto const& m : requested) { @@ -61,8 +57,13 @@ CDRMLeaseResource::CDRMLeaseResource(SP resource_, SPsendFinished(); + LOGM(LOG, "Revoking lease for fd {}", lease->leaseFD); }); + LOGM(LOG, "Granting lease, sending fd {}", lease->leaseFD); + + resource->sendLeaseFd(lease->leaseFD); + close(lease->leaseFD); } @@ -70,6 +71,12 @@ bool CDRMLeaseResource::good() { return resource->resource(); } +CDRMLeaseResource::~CDRMLeaseResource() { + // destroy in this order to ensure listener gets called + lease.reset(); + listeners.destroyLease.reset(); +} + CDRMLeaseRequestResource::CDRMLeaseRequestResource(SP resource_) : resource(resource_) { if (!good()) return; @@ -100,7 +107,7 @@ CDRMLeaseRequestResource::CDRMLeaseRequestResource(SP reso return; } - auto RESOURCE = makeShared(makeShared(resource->client(), resource->version(), -1), self.lock()); + auto RESOURCE = makeShared(makeShared(resource->client(), resource->version(), id), self.lock()); if (!RESOURCE) { resource->noMemory(); return; @@ -185,7 +192,8 @@ CDRMLeaseDeviceResource::CDRMLeaseDeviceResource(SP resourc close(fd); for (auto const& m : PROTO::lease->primaryDevice->offeredOutputs) { - sendConnector(m.lock()); + if (m) + sendConnector(m.lock()); } resource->sendDone(); @@ -196,10 +204,10 @@ bool CDRMLeaseDeviceResource::good() { } void CDRMLeaseDeviceResource::sendConnector(SP monitor) { - if (std::find_if(connectorsSent.begin(), connectorsSent.end(), [monitor](const auto& e) { return e->monitor == monitor; }) != connectorsSent.end()) + if (std::find_if(connectorsSent.begin(), connectorsSent.end(), [monitor](const auto& e) { return e && !e->dead && e->monitor == monitor; }) != connectorsSent.end()) return; - auto RESOURCE = makeShared(makeShared(resource->client(), resource->version(), -1), monitor); + auto RESOURCE = makeShared(makeShared(resource->client(), resource->version(), 0), monitor); if (!RESOURCE) { resource->noMemory(); return; @@ -267,6 +275,9 @@ void CDRMLeaseProtocol::destroyResource(CDRMLeaseDeviceResource* resource) { } void CDRMLeaseProtocol::destroyResource(CDRMLeaseConnectorResource* resource) { + for (const auto& m : m_vManagers) { + std::erase_if(m->connectorsSent, [resource](const auto& e) { return e.expired() || e->dead || e.get() == resource; }); + } std::erase_if(m_vConnectors, [resource](const auto& e) { return e.get() == resource; }); } @@ -279,6 +290,7 @@ void CDRMLeaseProtocol::destroyResource(CDRMLeaseResource* resource) { } void CDRMLeaseProtocol::offer(SP monitor) { + std::erase_if(primaryDevice->offeredOutputs, [](const auto& e) { return e.expired(); }); if (std::find(primaryDevice->offeredOutputs.begin(), primaryDevice->offeredOutputs.end(), monitor) != primaryDevice->offeredOutputs.end()) return; diff --git a/src/protocols/DRMLease.hpp b/src/protocols/DRMLease.hpp index 56eaa3db..3671cfce 100644 --- a/src/protocols/DRMLease.hpp +++ b/src/protocols/DRMLease.hpp @@ -22,12 +22,13 @@ class CDRMLeaseRequestResource; class CDRMLeaseResource { public: CDRMLeaseResource(SP resource_, SP request); + ~CDRMLeaseResource(); bool good(); WP parent; std::vector> requested; - WP lease; + SP lease; int leaseFD = -1; From f309681d4a78d1c12d8a04fe37075a50a750c2ec Mon Sep 17 00:00:00 2001 From: deadacute <6218316+deadacute@users.noreply.github.com> Date: Sun, 13 Oct 2024 20:40:09 +0200 Subject: [PATCH 0523/2181] example: update desktop file to include DesktopNames --- example/hyprland.desktop | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/example/hyprland.desktop b/example/hyprland.desktop index 57ad076f..bb2801a9 100644 --- a/example/hyprland.desktop +++ b/example/hyprland.desktop @@ -2,4 +2,6 @@ Name=Hyprland Comment=An intelligent dynamic tiling Wayland compositor Exec=Hyprland -Type=Application \ No newline at end of file +Type=Application +DesktopNames=Hyprland +Keywords=tiling;wayland;compositor; From 22b1370ae512c92d84bbcd4cff2a3f8a4496c994 Mon Sep 17 00:00:00 2001 From: "fanlumaster(Fany Full)" <1730976608@qq.com> Date: Tue, 15 Oct 2024 01:03:16 +0800 Subject: [PATCH 0524/2181] IME: Fixup IME popup candidate windows position when scale is not 1.0 (#8117) --- src/managers/input/InputMethodPopup.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/managers/input/InputMethodPopup.cpp b/src/managers/input/InputMethodPopup.cpp index a8757030..cf48f2a5 100644 --- a/src/managers/input/InputMethodPopup.cpp +++ b/src/managers/input/InputMethodPopup.cpp @@ -100,14 +100,14 @@ void CInputPopup::updateBox() { cursorBoxParent = {0, 0, (int)parentBox.w, (int)parentBox.h}; } - Vector2D currentPopupSize = surface->getViewporterCorrectedSize(); + Vector2D currentPopupSize = surface->getViewporterCorrectedSize() / surface->resource()->current.scale; CMonitor* pMonitor = g_pCompositor->getMonitorFromVector(parentBox.middle()); Vector2D popupOffset(0, 0); if (parentBox.y + cursorBoxParent.y + cursorBoxParent.height + currentPopupSize.y > pMonitor->vecPosition.y + pMonitor->vecSize.y) - popupOffset.y = -currentPopupSize.y; + popupOffset.y -= currentPopupSize.y; else popupOffset.y = cursorBoxParent.height; From 01c2ff34ddcb5995409c33c2b549e93b98b56d6b Mon Sep 17 00:00:00 2001 From: Aqa-Ib Date: Mon, 14 Oct 2024 18:31:17 +0000 Subject: [PATCH 0525/2181] layout: simplify the conditions to autogroup (#8120) --- src/layout/IHyprLayout.cpp | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/src/layout/IHyprLayout.cpp b/src/layout/IHyprLayout.cpp index 80c9abff..fa3f8b8d 100644 --- a/src/layout/IHyprLayout.cpp +++ b/src/layout/IHyprLayout.cpp @@ -191,14 +191,12 @@ bool IHyprLayout::onWindowCreatedAutoGroup(PHLWINDOW pWindow) { denied = true; if (*PAUTOGROUP // check if auto_group is enabled. - && OPENINGON // check if OPENINGON exists. - && OPENINGON != pWindow // fixes a freeze when activating togglefloat to transform a floating group into a tiled group. && OPENINGON->m_sGroupData.pNextWindow.lock() // check if OPENINGON is a group. && pWindow->canBeGroupedInto(OPENINGON) // check if the new window can be grouped into OPENINGON. - && !g_pXWaylandManager->shouldBeFloated(pWindow) // don't group a new window that should be floated. - && !denied) { // don't group a new floated window into a tiled group. + && !g_pXWaylandManager->shouldBeFloated(pWindow) // fixes the popups of XWayland programs running in a floating group. + && !denied) { // don't group a new floated window into a tiled group (for convenience). - pWindow->m_bIsFloating = OPENINGON->m_bIsFloating; // match the floating state + pWindow->m_bIsFloating = OPENINGON->m_bIsFloating; // match the floating state. Needed to autogroup a new tiled window into a floated group. static auto USECURRPOS = CConfigValue("group:insert_after_current"); (*USECURRPOS ? OPENINGON : OPENINGON->getGroupTail())->insertWindowToGroup(pWindow); From ace803948aaed6328342ea57e81adc1a01236c71 Mon Sep 17 00:00:00 2001 From: Aqa-Ib Date: Wed, 16 Oct 2024 09:59:47 +0000 Subject: [PATCH 0526/2181] layout: enable group rules for new floating windows (#8122) * layout: enable group rules for new floating windows * fix comment * do not apply group rules to a new floating window if it shouldBeFloated. fixes child windows * comment --- src/layout/IHyprLayout.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/layout/IHyprLayout.cpp b/src/layout/IHyprLayout.cpp index fa3f8b8d..892ed12c 100644 --- a/src/layout/IHyprLayout.cpp +++ b/src/layout/IHyprLayout.cpp @@ -82,6 +82,8 @@ void IHyprLayout::onWindowRemovedFloating(PHLWINDOW pWindow) { } void IHyprLayout::onWindowCreatedFloating(PHLWINDOW pWindow) { + if (!g_pXWaylandManager->shouldBeFloated(pWindow)) // do not apply group rules to child windows + pWindow->applyGroupRules(); CBox desiredGeometry = {0}; g_pXWaylandManager->getGeometryForWindow(pWindow, &desiredGeometry); @@ -193,7 +195,7 @@ bool IHyprLayout::onWindowCreatedAutoGroup(PHLWINDOW pWindow) { if (*PAUTOGROUP // check if auto_group is enabled. && OPENINGON->m_sGroupData.pNextWindow.lock() // check if OPENINGON is a group. && pWindow->canBeGroupedInto(OPENINGON) // check if the new window can be grouped into OPENINGON. - && !g_pXWaylandManager->shouldBeFloated(pWindow) // fixes the popups of XWayland programs running in a floating group. + && !g_pXWaylandManager->shouldBeFloated(pWindow) // don't group child windows. Fix for floated groups. Tiled groups don't need this because we check if !denied. && !denied) { // don't group a new floated window into a tiled group (for convenience). pWindow->m_bIsFloating = OPENINGON->m_bIsFloating; // match the floating state. Needed to autogroup a new tiled window into a floated group. From 0baf166d39260c6d1d422cf528fb5fedc3010cdb Mon Sep 17 00:00:00 2001 From: vaxerski Date: Wed, 16 Oct 2024 10:01:31 +0000 Subject: [PATCH 0527/2181] [gha] Nix: update inputs --- flake.lock | 30 +++++++++++++++--------------- 1 file changed, 15 insertions(+), 15 deletions(-) diff --git a/flake.lock b/flake.lock index de9a4dce..0a12fe0a 100644 --- a/flake.lock +++ b/flake.lock @@ -16,11 +16,11 @@ ] }, "locked": { - "lastModified": 1728326504, - "narHash": "sha256-dQXAj+4d6neY7ldCiH6gNym3upP49PVxRzEPxXlD9Aw=", + "lastModified": 1728902391, + "narHash": "sha256-44bnoY0nAvbBQ/lVjmn511yL39Sv7SknV0BDxn34P3Q=", "owner": "hyprwm", "repo": "aquamarine", - "rev": "65dd97b5d21e917295159bbef1d52e06963f4eb0", + "rev": "9874e08eec85b5542ca22494e127b0cdce46b786", "type": "github" }, "original": { @@ -79,11 +79,11 @@ ] }, "locked": { - "lastModified": 1727821604, - "narHash": "sha256-hNw5J6xatedqytYowx0mJKgctjA4lQARZFdgnzM2RpM=", + "lastModified": 1728669738, + "narHash": "sha256-EDNAU9AYcx8OupUzbTbWE1d3HYdeG0wO6Msg3iL1muk=", "owner": "hyprwm", "repo": "hyprcursor", - "rev": "d60e1e01e6e6633ef1c87148b9137cc1dd39263d", + "rev": "0264e698149fcb857a66a53018157b41f8d97bb0", "type": "github" }, "original": { @@ -151,11 +151,11 @@ ] }, "locked": { - "lastModified": 1727300645, - "narHash": "sha256-OvAtVLaSRPnbXzOwlR1fVqCXR7i+ICRX3aPMCdIiv+c=", + "lastModified": 1728941256, + "narHash": "sha256-WRypmcZ2Bw94lLmcmxYokVOHPJSZ7T06V49QZ4tkZeQ=", "owner": "hyprwm", "repo": "hyprutils", - "rev": "3f5293432b6dc6a99f26aca2eba3876d2660665c", + "rev": "fd4be8b9ca932f7384e454bcd923c5451ef2aa85", "type": "github" }, "original": { @@ -189,11 +189,11 @@ }, "nixpkgs": { "locked": { - "lastModified": 1728018373, - "narHash": "sha256-NOiTvBbRLIOe5F6RbHaAh6++BNjsb149fGZd1T4+KBg=", + "lastModified": 1728888510, + "narHash": "sha256-nsNdSldaAyu6PE3YUA+YQLqUDJh+gRbBooMMekZJwvI=", "owner": "NixOS", "repo": "nixpkgs", - "rev": "bc947f541ae55e999ffdb4013441347d83b00feb", + "rev": "a3c0b3b21515f74fd2665903d4ce6bc4dc81c77c", "type": "github" }, "original": { @@ -229,11 +229,11 @@ "nixpkgs-stable": "nixpkgs-stable" }, "locked": { - "lastModified": 1728092656, - "narHash": "sha256-eMeCTJZ5xBeQ0f9Os7K8DThNVSo9gy4umZLDfF5q6OM=", + "lastModified": 1728778939, + "narHash": "sha256-WybK5E3hpGxtCYtBwpRj1E9JoiVxe+8kX83snTNaFHE=", "owner": "cachix", "repo": "git-hooks.nix", - "rev": "1211305a5b237771e13fcca0c51e60ad47326a9a", + "rev": "ff68f91754be6f3427e4986d7949e6273659be1d", "type": "github" }, "original": { From 781828a56e495439bfe9c0a701cb29f5e4e2df24 Mon Sep 17 00:00:00 2001 From: Vaxry Date: Wed, 16 Oct 2024 21:59:29 +0100 Subject: [PATCH 0528/2181] output: send enter events on late wl_output binds fixes #6560 --- src/protocols/core/Compositor.cpp | 6 ++++++ src/protocols/core/Compositor.hpp | 2 ++ src/protocols/core/Output.cpp | 21 +++++++++++++++++++++ 3 files changed, 29 insertions(+) diff --git a/src/protocols/core/Compositor.cpp b/src/protocols/core/Compositor.cpp index 37a4bdf1..3d4b63c1 100644 --- a/src/protocols/core/Compositor.cpp +++ b/src/protocols/core/Compositor.cpp @@ -589,3 +589,9 @@ void CWLCompositorProtocol::destroyResource(CWLSurfaceResource* resource) { void CWLCompositorProtocol::destroyResource(CWLRegionResource* resource) { std::erase_if(m_vRegions, [&](const auto& other) { return other.get() == resource; }); } + +void CWLCompositorProtocol::forEachSurface(std::function)> fn) { + for (auto& surf : m_vSurfaces) { + fn(surf); + } +} diff --git a/src/protocols/core/Compositor.hpp b/src/protocols/core/Compositor.hpp index dc1c851f..b3c067c9 100644 --- a/src/protocols/core/Compositor.hpp +++ b/src/protocols/core/Compositor.hpp @@ -169,6 +169,8 @@ class CWLCompositorProtocol : public IWaylandProtocol { virtual void bindManager(wl_client* client, void* data, uint32_t ver, uint32_t id); + void forEachSurface(std::function)> fn); + struct { CSignal newSurface; // SP } events; diff --git a/src/protocols/core/Output.cpp b/src/protocols/core/Output.cpp index 3e68937f..e9f35abc 100644 --- a/src/protocols/core/Output.cpp +++ b/src/protocols/core/Output.cpp @@ -1,4 +1,6 @@ #include "Output.hpp" +#include "Compositor.hpp" +#include "../../Compositor.hpp" #include "../../helpers/Monitor.hpp" CWLOutputResource::CWLOutputResource(SP resource_, SP pMonitor) : monitor(pMonitor), resource(resource_) { @@ -27,6 +29,25 @@ CWLOutputResource::CWLOutputResource(SP resource_, SP pMoni } updateState(); + + PROTO::compositor->forEachSurface([](SP surf) { + auto HLSurf = CWLSurface::fromResource(surf); + + if (!HLSurf) + return; + + const auto GEOMETRY = HLSurf->getSurfaceBoxGlobal(); + + if (!GEOMETRY.has_value()) + return; + + for (auto& m : g_pCompositor->m_vMonitors) { + if (!m->logicalBox().overlaps(*GEOMETRY)) + continue; + + surf->enter(m); + } + }); } SP CWLOutputResource::fromResource(wl_resource* res) { From 86e9f69a69990feb880dadd0c2b8c067b2a96fa9 Mon Sep 17 00:00:00 2001 From: Aqa-Ib Date: Wed, 16 Oct 2024 21:13:35 +0000 Subject: [PATCH 0529/2181] layout: move applyGroupRules() to onWindowCreated() (#8139) --- src/layout/DwindleLayout.cpp | 4 ---- src/layout/IHyprLayout.cpp | 7 ++++--- src/layout/MasterLayout.cpp | 2 -- src/render/decorations/CHyprGroupBarDecoration.cpp | 1 - 4 files changed, 4 insertions(+), 10 deletions(-) diff --git a/src/layout/DwindleLayout.cpp b/src/layout/DwindleLayout.cpp index 76b26af1..8a7426eb 100644 --- a/src/layout/DwindleLayout.cpp +++ b/src/layout/DwindleLayout.cpp @@ -308,8 +308,6 @@ void CHyprDwindleLayout::onWindowCreatedTiling(PHLWINDOW pWindow, eDirection dir applyNodeDataToWindow(PNODE); - pWindow->applyGroupRules(); - return; } @@ -450,8 +448,6 @@ void CHyprDwindleLayout::onWindowCreatedTiling(PHLWINDOW pWindow, eDirection dir NEWPARENT->recalcSizePosRecursive(false, horizontalOverride, verticalOverride); recalculateMonitor(pWindow->m_iMonitorID); - - pWindow->applyGroupRules(); } void CHyprDwindleLayout::onWindowRemovedTiling(PHLWINDOW pWindow) { diff --git a/src/layout/IHyprLayout.cpp b/src/layout/IHyprLayout.cpp index 892ed12c..b8d92636 100644 --- a/src/layout/IHyprLayout.cpp +++ b/src/layout/IHyprLayout.cpp @@ -20,6 +20,9 @@ void IHyprLayout::onWindowCreated(PHLWINDOW pWindow, eDirection direction) { pWindow->m_vPseudoSize = pWindow->m_vLastFloatingSize; + if (!g_pXWaylandManager->shouldBeFloated(pWindow)) // do not apply group rules to child windows + pWindow->applyGroupRules(); + bool autoGrouped = IHyprLayout::onWindowCreatedAutoGroup(pWindow); if (autoGrouped) return; @@ -82,8 +85,6 @@ void IHyprLayout::onWindowRemovedFloating(PHLWINDOW pWindow) { } void IHyprLayout::onWindowCreatedFloating(PHLWINDOW pWindow) { - if (!g_pXWaylandManager->shouldBeFloated(pWindow)) // do not apply group rules to child windows - pWindow->applyGroupRules(); CBox desiredGeometry = {0}; g_pXWaylandManager->getGeometryForWindow(pWindow, &desiredGeometry); @@ -194,6 +195,7 @@ bool IHyprLayout::onWindowCreatedAutoGroup(PHLWINDOW pWindow) { if (*PAUTOGROUP // check if auto_group is enabled. && OPENINGON->m_sGroupData.pNextWindow.lock() // check if OPENINGON is a group. + && OPENINGON != pWindow // prevent freeze when the "group set" window rule makes the new window to be already a group. && pWindow->canBeGroupedInto(OPENINGON) // check if the new window can be grouped into OPENINGON. && !g_pXWaylandManager->shouldBeFloated(pWindow) // don't group child windows. Fix for floated groups. Tiled groups don't need this because we check if !denied. && !denied) { // don't group a new floated window into a tiled group (for convenience). @@ -204,7 +206,6 @@ bool IHyprLayout::onWindowCreatedAutoGroup(PHLWINDOW pWindow) { (*USECURRPOS ? OPENINGON : OPENINGON->getGroupTail())->insertWindowToGroup(pWindow); OPENINGON->setGroupCurrent(pWindow); - pWindow->applyGroupRules(); pWindow->updateWindowDecos(); recalculateWindow(pWindow); diff --git a/src/layout/MasterLayout.cpp b/src/layout/MasterLayout.cpp index 8fde960d..f983770b 100644 --- a/src/layout/MasterLayout.cpp +++ b/src/layout/MasterLayout.cpp @@ -116,8 +116,6 @@ void CHyprMasterLayout::onWindowCreatedTiling(PHLWINDOW pWindow, eDirection dire return; } - pWindow->applyGroupRules(); - static auto PDROPATCURSOR = CConfigValue("master:drop_at_cursor"); eOrientation orientation = getDynamicOrientation(pWindow->m_pWorkspace); const auto NODEIT = std::find(m_lMasterNodesData.begin(), m_lMasterNodesData.end(), *PNODE); diff --git a/src/render/decorations/CHyprGroupBarDecoration.cpp b/src/render/decorations/CHyprGroupBarDecoration.cpp index eca3f2cb..74a1e2e9 100644 --- a/src/render/decorations/CHyprGroupBarDecoration.cpp +++ b/src/render/decorations/CHyprGroupBarDecoration.cpp @@ -466,7 +466,6 @@ bool CHyprGroupBarDecoration::onEndWindowDragOnDeco(const Vector2D& pos, PHLWIND std::swap(pDraggedHead->m_sGroupData.head, pWindowInsertEnd->m_sGroupData.head); m_pWindow->setGroupCurrent(pDraggedWindow); - pDraggedWindow->applyGroupRules(); pDraggedWindow->updateWindowDecos(); g_pLayoutManager->getCurrentLayout()->recalculateWindow(pDraggedWindow); From 09581d32fd465c5c4ff868090369ee67516c38a9 Mon Sep 17 00:00:00 2001 From: zakk4223 Date: Wed, 16 Oct 2024 16:13:59 -0500 Subject: [PATCH 0530/2181] hyprpm: Fix crashes due to misplaced fmt argument(s) (#8140) --- hyprpm/src/core/PluginManager.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/hyprpm/src/core/PluginManager.cpp b/hyprpm/src/core/PluginManager.cpp index 359b2c78..57c67641 100644 --- a/hyprpm/src/core/PluginManager.cpp +++ b/hyprpm/src/core/PluginManager.cpp @@ -697,7 +697,7 @@ bool CPluginManager::updatePlugins(bool forceUpdateAll) { " This likely means that the plugin is either outdated, not yet available for your version, or broken.\n" "If you are on -git, update first.\n" "Try re-running with -v to see more verbose output.", - failureString("Plugin {} failed to build.")); + failureString("Plugin {} failed to build.", p.name)); p.failed = true; continue; } @@ -839,7 +839,7 @@ ePluginLoadStateReturn CPluginManager::ensurePluginsLoadState() { continue; loadUnloadPlugin(HYPRPMPATH + repoForName(p.name) + "/" + p.filename, true); - std::println("{}", successString("Loaded {}"), p.name); + std::println("{}", successString("Loaded {}", p.name)); } } From b57086aa4362117c1f1025246f618d760e44b026 Mon Sep 17 00:00:00 2001 From: Vaxry Date: Wed, 16 Oct 2024 22:22:36 +0100 Subject: [PATCH 0531/2181] window: properly break cycles in X11TransientFor ref #8045 --- src/desktop/Window.cpp | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/src/desktop/Window.cpp b/src/desktop/Window.cpp index fa85dc07..a393f361 100644 --- a/src/desktop/Window.cpp +++ b/src/desktop/Window.cpp @@ -451,15 +451,21 @@ PHLWINDOW CWindow::X11TransientFor() { if (!m_pXWaylandSurface || !m_pXWaylandSurface->parent) return nullptr; - auto s = m_pXWaylandSurface->parent; - auto oldParent = s; + auto s = m_pXWaylandSurface->parent; + std::vector> visited; while (s) { - // break cyclic loop of m_pXWaylandSurface being parent of itself, #TODO reject this from even being created? - if (!s->parent || s->parent == oldParent) + // break loops. Some X apps make them, and it seems like it's valid behavior?!?!?! + // TODO: we should reject loops being created in the first place. + if (std::find(visited.begin(), visited.end(), s) != visited.end()) break; + + visited.emplace_back(s.lock()); s = s->parent; } + if (s == m_pXWaylandSurface) + return nullptr; // dead-ass circle + for (auto const& w : g_pCompositor->m_vWindows) { if (w->m_pXWaylandSurface != s) continue; From 495b92fb535f51a38e5130e6b89bd1fb01ce8cfb Mon Sep 17 00:00:00 2001 From: Behzad Date: Thu, 17 Oct 2024 17:50:18 +0330 Subject: [PATCH 0532/2181] makefile: fix typo (#8127) --- Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Makefile b/Makefile index 59efc0ef..98267eea 100644 --- a/Makefile +++ b/Makefile @@ -1,7 +1,7 @@ PREFIX = /usr/local legacyrenderer: - cmake --no-warn-unused-cli -DCMAKE_BUILD_TYPE:STRING=Release -DCMAKE_INSTALL_PREFIX:STRING=${PREFIX} -DLEGACY_RENDERER:BOOL=true -S . -B ./buildZ + cmake --no-warn-unused-cli -DCMAKE_BUILD_TYPE:STRING=Release -DCMAKE_INSTALL_PREFIX:STRING=${PREFIX} -DLEGACY_RENDERER:BOOL=true -S . -B ./build cmake --build ./build --config Release --target all -j`nproc 2>/dev/null || getconf NPROCESSORS_CONF` legacyrendererdebug: From 5f30cb7753266316b85a460c6266995678187294 Mon Sep 17 00:00:00 2001 From: MightyPlaza <123664421+MightyPlaza@users.noreply.github.com> Date: Thu, 17 Oct 2024 20:03:17 +0000 Subject: [PATCH 0533/2181] windowrules: allow specifying max size in size window rule (#8021) * allow specifying max size in size window rule modified: src/events/Windows.cpp * clean up modified: src/events/Windows.cpp --- src/events/Windows.cpp | 40 +++++++++++++++++++++++++++------------- 1 file changed, 27 insertions(+), 13 deletions(-) diff --git a/src/events/Windows.cpp b/src/events/Windows.cpp index e549907e..d2d5bebf 100644 --- a/src/events/Windows.cpp +++ b/src/events/Windows.cpp @@ -330,24 +330,38 @@ void Events::listener_mapWindow(void* owner, void* data) { for (auto const& r : PWINDOW->m_vMatchedRules) { if (r.szRule.starts_with("size")) { try { - const auto VALUE = r.szRule.substr(r.szRule.find(' ') + 1); - const auto SIZEXSTR = VALUE.substr(0, VALUE.find(' ')); - const auto SIZEYSTR = VALUE.substr(VALUE.find(' ') + 1); - const auto MAXSIZE = g_pXWaylandManager->getMaxSizeForWindow(PWINDOW); + auto stringToFloatClamp = [](const std::string& VALUE, const float CURR, const float REL) { + auto stringToPercentage = [](const std::string& VALUE, const float REL) { + if (VALUE.ends_with('%')) + return (std::stof(VALUE.substr(0, VALUE.length() - 1)) * REL) / 100; + else + return std::stof(VALUE); + }; - const auto SIZEX = SIZEXSTR == "max" ? - std::clamp(MAXSIZE.x, 20.0, PMONITOR->vecSize.x) : - (!SIZEXSTR.contains('%') ? std::stoi(SIZEXSTR) : std::stof(SIZEXSTR.substr(0, SIZEXSTR.length() - 1)) * 0.01 * PMONITOR->vecSize.x); - const auto SIZEY = SIZEYSTR == "max" ? - std::clamp(MAXSIZE.y, 20.0, PMONITOR->vecSize.y) : - (!SIZEYSTR.contains('%') ? std::stoi(SIZEYSTR) : std::stof(SIZEYSTR.substr(0, SIZEYSTR.length() - 1)) * 0.01 * PMONITOR->vecSize.y); + if (VALUE.starts_with('<')) + return std::min(CURR, stringToPercentage(VALUE.substr(1, VALUE.length() - 1), REL)); + else if (VALUE.starts_with('>')) + return std::max(CURR, stringToPercentage(VALUE.substr(1, VALUE.length() - 1), REL)); + + return stringToPercentage(VALUE, REL); + }; + + const auto VALUE = r.szRule.substr(r.szRule.find(' ') + 1); + const auto SIZEXSTR = VALUE.substr(0, VALUE.find(' ')); + const auto SIZEYSTR = VALUE.substr(VALUE.find(' ') + 1); + + const auto MAXSIZE = g_pXWaylandManager->getMaxSizeForWindow(PWINDOW); + + const float SIZEX = + SIZEXSTR == "max" ? std::clamp(MAXSIZE.x, 20.0, PMONITOR->vecSize.x) : stringToFloatClamp(SIZEXSTR, PWINDOW->m_vRealSize.goal().x, PMONITOR->vecSize.x); + + const float SIZEY = + SIZEYSTR == "max" ? std::clamp(MAXSIZE.y, 20.0, PMONITOR->vecSize.y) : stringToFloatClamp(SIZEYSTR, PWINDOW->m_vRealSize.goal().y, PMONITOR->vecSize.y); Debug::log(LOG, "Rule size, applying to {}", PWINDOW); - PWINDOW->m_vRealSize = Vector2D(SIZEX, SIZEY); - PWINDOW->m_vPseudoSize = PWINDOW->m_vRealSize.goal(); - g_pXWaylandManager->setWindowSize(PWINDOW, PWINDOW->m_vRealSize.goal()); + PWINDOW->clampWindowSize(Vector2D{SIZEXSTR.starts_with("<") ? 0 : SIZEX, SIZEYSTR.starts_with("<") ? 0 : SIZEY}, Vector2D{SIZEX, SIZEY}); PWINDOW->setHidden(false); } catch (...) { Debug::log(LOG, "Rule size failed, rule: {} -> {}", r.szRule, r.szValue); } From 0e630e9e74ad34683194a07cfe6afe55a2c0685f Mon Sep 17 00:00:00 2001 From: Maximilian Seidler <78690852+PaideiaDilemma@users.noreply.github.com> Date: Thu, 17 Oct 2024 20:05:55 +0000 Subject: [PATCH 0534/2181] session-lock: reset seat grab on a new session lock (#8147) --- src/managers/SessionLockManager.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/managers/SessionLockManager.cpp b/src/managers/SessionLockManager.cpp index 260a3992..4e05695a 100644 --- a/src/managers/SessionLockManager.cpp +++ b/src/managers/SessionLockManager.cpp @@ -3,6 +3,7 @@ #include "../config/ConfigValue.hpp" #include "../protocols/FractionalScale.hpp" #include "../protocols/SessionLock.hpp" +#include "../managers/SeatManager.hpp" #include #include @@ -84,6 +85,7 @@ void CSessionLockManager::onNewSessionLock(SP pLock) { }); g_pCompositor->focusSurface(nullptr); + g_pSeatManager->setGrab(nullptr); } bool CSessionLockManager::isSessionLocked() { From e5d3a71263187feec6c2249b3f7b74de0a71f47c Mon Sep 17 00:00:00 2001 From: Maximilian Seidler <78690852+PaideiaDilemma@users.noreply.github.com> Date: Sat, 19 Oct 2024 14:49:56 +0000 Subject: [PATCH 0535/2181] config: fix generateConfig loop (#8164) * config: fix generateConfig loop * config: cleanup getMainConfigPath --- src/config/ConfigManager.cpp | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/src/config/ConfigManager.cpp b/src/config/ConfigManager.cpp index 6ec63d4c..432b7faf 100644 --- a/src/config/ConfigManager.cpp +++ b/src/config/ConfigManager.cpp @@ -688,14 +688,13 @@ std::string CConfigManager::getMainConfigPath() { if (const auto CFG_ENV = getenv("HYPRLAND_CONFIG"); CFG_ENV) return CFG_ENV; - Debug::log(TRACE, "Seems as if HYPRLAND_CONFIG isn't set, let's see what we can do with HOME."); - static const auto paths = Hyprutils::Path::findConfig(ISDEBUG ? "hyprlandd" : "hyprland"); - if (paths.first.has_value()) { - return paths.first.value(); - } else if (paths.second.has_value()) { - auto configPath = Hyprutils::Path::fullConfigPath(paths.second.value(), ISDEBUG ? "hyprlandd" : "hyprland"); - return generateConfig(configPath).value(); + const auto PATHS = Hyprutils::Path::findConfig(ISDEBUG ? "hyprlandd" : "hyprland"); + if (PATHS.first.has_value()) { + return PATHS.first.value(); + } else if (PATHS.second.has_value()) { + const auto CONFIGPATH = Hyprutils::Path::fullConfigPath(PATHS.second.value(), ISDEBUG ? "hyprlandd" : "hyprland"); + return generateConfig(CONFIGPATH).value(); } else throw std::runtime_error("Neither HOME nor XDG_CONFIG_HOME are set in the environment. Could not find config in XDG_CONFIG_DIRS or /etc/xdg."); } From 904f9b6aee6a4524fba554f76b32747f85f0609d Mon Sep 17 00:00:00 2001 From: Vaxry Date: Sat, 19 Oct 2024 16:09:39 +0100 Subject: [PATCH 0536/2181] foreign-toplevel: don't send updates to X11 OR windows --- src/protocols/ForeignToplevel.cpp | 29 ++++++++++++++++++++++++----- src/protocols/ForeignToplevel.hpp | 1 + 2 files changed, 25 insertions(+), 5 deletions(-) diff --git a/src/protocols/ForeignToplevel.cpp b/src/protocols/ForeignToplevel.cpp index 1f8cbcbe..38bb5e69 100644 --- a/src/protocols/ForeignToplevel.cpp +++ b/src/protocols/ForeignToplevel.cpp @@ -31,8 +31,8 @@ CForeignToplevelList::CForeignToplevelList(SP resourc }); for (auto const& w : g_pCompositor->m_vWindows) { - if (!w->m_bIsMapped || w->m_bFadingOut) - continue; + if (!PROTO::foreignToplevel->windowValidForForeign(w)) + return; onMap(w); } @@ -112,20 +112,35 @@ bool CForeignToplevelList::good() { CForeignToplevelProtocol::CForeignToplevelProtocol(const wl_interface* iface, const int& ver, const std::string& name) : IWaylandProtocol(iface, ver, name) { static auto P = g_pHookSystem->hookDynamic("openWindow", [this](void* self, SCallbackInfo& info, std::any data) { + auto window = std::any_cast(data); + + if (!windowValidForForeign(window)) + return; + for (auto const& m : m_vManagers) { - m->onMap(std::any_cast(data)); + m->onMap(window); } }); static auto P1 = g_pHookSystem->hookDynamic("closeWindow", [this](void* self, SCallbackInfo& info, std::any data) { + auto window = std::any_cast(data); + + if (!windowValidForForeign(window)) + return; + for (auto const& m : m_vManagers) { - m->onUnmap(std::any_cast(data)); + m->onUnmap(window); } }); static auto P2 = g_pHookSystem->hookDynamic("windowTitle", [this](void* self, SCallbackInfo& info, std::any data) { + auto window = std::any_cast(data); + + if (!windowValidForForeign(window)) + return; + for (auto const& m : m_vManagers) { - m->onTitle(std::any_cast(data)); + m->onTitle(window); } }); } @@ -148,3 +163,7 @@ void CForeignToplevelProtocol::onManagerResourceDestroy(CForeignToplevelList* mg void CForeignToplevelProtocol::destroyHandle(CForeignToplevelHandle* handle) { std::erase_if(m_vHandles, [&](const auto& other) { return other.get() == handle; }); } + +bool CForeignToplevelProtocol::windowValidForForeign(PHLWINDOW pWindow) { + return validMapped(pWindow) && !pWindow->isX11OverrideRedirect(); +} diff --git a/src/protocols/ForeignToplevel.hpp b/src/protocols/ForeignToplevel.hpp index d95db41f..076bfd7c 100644 --- a/src/protocols/ForeignToplevel.hpp +++ b/src/protocols/ForeignToplevel.hpp @@ -50,6 +50,7 @@ class CForeignToplevelProtocol : public IWaylandProtocol { private: void onManagerResourceDestroy(CForeignToplevelList* mgr); void destroyHandle(CForeignToplevelHandle* handle); + bool windowValidForForeign(PHLWINDOW pWindow); // std::vector> m_vManagers; From 48bf32c5de5628a4a17387375ea997f738a4f807 Mon Sep 17 00:00:00 2001 From: Vaxry Date: Sat, 19 Oct 2024 16:09:46 +0100 Subject: [PATCH 0537/2181] foreign-toplevel-wlr: don't send updates to X11 OR windows --- src/protocols/ForeignToplevelWlr.cpp | 26 +++++++++++++++++++++++++- src/protocols/ForeignToplevelWlr.hpp | 1 + 2 files changed, 26 insertions(+), 1 deletion(-) diff --git a/src/protocols/ForeignToplevelWlr.cpp b/src/protocols/ForeignToplevelWlr.cpp index 291969db..1163a5e7 100644 --- a/src/protocols/ForeignToplevelWlr.cpp +++ b/src/protocols/ForeignToplevelWlr.cpp @@ -180,7 +180,7 @@ CForeignToplevelWlrManager::CForeignToplevelWlrManager(SPm_vWindows) { - if (!w->m_bIsMapped || w->m_bFadingOut) + if (!PROTO::foreignToplevelWlr->windowValidForForeign(w)) continue; onMap(w); @@ -313,6 +313,10 @@ bool CForeignToplevelWlrManager::good() { CForeignToplevelWlrProtocol::CForeignToplevelWlrProtocol(const wl_interface* iface, const int& ver, const std::string& name) : IWaylandProtocol(iface, ver, name) { static auto P = g_pHookSystem->hookDynamic("openWindow", [this](void* self, SCallbackInfo& info, std::any data) { const auto PWINDOW = std::any_cast(data); + + if (!windowValidForForeign(PWINDOW)) + return; + for (auto const& m : m_vManagers) { m->onMap(PWINDOW); } @@ -320,6 +324,10 @@ CForeignToplevelWlrProtocol::CForeignToplevelWlrProtocol(const wl_interface* ifa static auto P1 = g_pHookSystem->hookDynamic("closeWindow", [this](void* self, SCallbackInfo& info, std::any data) { const auto PWINDOW = std::any_cast(data); + + if (!windowValidForForeign(PWINDOW)) + return; + for (auto const& m : m_vManagers) { m->onUnmap(PWINDOW); } @@ -327,6 +335,10 @@ CForeignToplevelWlrProtocol::CForeignToplevelWlrProtocol(const wl_interface* ifa static auto P2 = g_pHookSystem->hookDynamic("windowTitle", [this](void* self, SCallbackInfo& info, std::any data) { const auto PWINDOW = std::any_cast(data); + + if (!windowValidForForeign(PWINDOW)) + return; + for (auto const& m : m_vManagers) { m->onTitle(PWINDOW); } @@ -334,6 +346,10 @@ CForeignToplevelWlrProtocol::CForeignToplevelWlrProtocol(const wl_interface* ifa static auto P3 = g_pHookSystem->hookDynamic("activeWindow", [this](void* self, SCallbackInfo& info, std::any data) { const auto PWINDOW = std::any_cast(data); + + if (!windowValidForForeign(PWINDOW)) + return; + for (auto const& m : m_vManagers) { m->onNewFocus(PWINDOW); } @@ -348,6 +364,10 @@ CForeignToplevelWlrProtocol::CForeignToplevelWlrProtocol(const wl_interface* ifa static auto P5 = g_pHookSystem->hookDynamic("fullscreen", [this](void* self, SCallbackInfo& info, std::any data) { const auto PWINDOW = std::any_cast(data); + + if (!windowValidForForeign(PWINDOW)) + return; + for (auto const& m : m_vManagers) { m->onFullscreen(PWINDOW); } @@ -383,3 +403,7 @@ PHLWINDOW CForeignToplevelWlrProtocol::windowFromHandleResource(wl_resource* res return nullptr; } + +bool CForeignToplevelWlrProtocol::windowValidForForeign(PHLWINDOW pWindow) { + return validMapped(pWindow) && !pWindow->isX11OverrideRedirect(); +} diff --git a/src/protocols/ForeignToplevelWlr.hpp b/src/protocols/ForeignToplevelWlr.hpp index 99f63b47..e726707d 100644 --- a/src/protocols/ForeignToplevelWlr.hpp +++ b/src/protocols/ForeignToplevelWlr.hpp @@ -63,6 +63,7 @@ class CForeignToplevelWlrProtocol : public IWaylandProtocol { private: void onManagerResourceDestroy(CForeignToplevelWlrManager* mgr); void destroyHandle(CForeignToplevelHandleWlr* handle); + bool windowValidForForeign(PHLWINDOW pWindow); // std::vector> m_vManagers; From 62ee5cc2739d70570dbe143c9bd75d00a51db942 Mon Sep 17 00:00:00 2001 From: Vaxry Date: Sat, 19 Oct 2024 16:21:47 +0100 Subject: [PATCH 0538/2181] monitor: modernize/refactor last legacy-handled events --- src/Compositor.cpp | 2 +- src/events/Events.hpp | 8 --- src/events/Monitors.cpp | 105 ---------------------------------------- src/helpers/Monitor.cpp | 74 +++++++++++++++++++++++++++- src/helpers/Monitor.hpp | 1 + 5 files changed, 74 insertions(+), 116 deletions(-) delete mode 100644 src/events/Monitors.cpp diff --git a/src/Compositor.cpp b/src/Compositor.cpp index fd4979b0..ca27f17a 100644 --- a/src/Compositor.cpp +++ b/src/Compositor.cpp @@ -3057,5 +3057,5 @@ void CCompositor::onNewMonitor(SP output) { } g_pHyprRenderer->damageMonitor(PNEWMONITOR.get()); - Events::listener_monitorFrame(PNEWMONITOR.get(), nullptr); + PNEWMONITOR->onMonitorFrame(); } diff --git a/src/events/Events.hpp b/src/events/Events.hpp index 0af16f64..84565979 100644 --- a/src/events/Events.hpp +++ b/src/events/Events.hpp @@ -24,12 +24,4 @@ namespace Events { DYNLISTENFUNC(requestMaximize); DYNLISTENFUNC(setOverrideRedirect); DYNLISTENFUNC(ackConfigure); - - // Monitor part 2 the sequel - DYNLISTENFUNC(monitorFrame); - DYNLISTENFUNC(monitorStateRequest); - DYNLISTENFUNC(monitorDamage); - DYNLISTENFUNC(monitorNeedsFrame); - DYNLISTENFUNC(monitorCommit); - DYNLISTENFUNC(monitorBind); }; diff --git a/src/events/Monitors.cpp b/src/events/Monitors.cpp deleted file mode 100644 index 9d2210f6..00000000 --- a/src/events/Monitors.cpp +++ /dev/null @@ -1,105 +0,0 @@ -#include "../Compositor.hpp" -#include "../helpers/WLClasses.hpp" -#include "../managers/input/InputManager.hpp" -#include "../render/Renderer.hpp" -#include "Events.hpp" -#include "../debug/HyprCtl.hpp" -#include "../config/ConfigValue.hpp" -#include "../protocols/Screencopy.hpp" -#include "../protocols/ToplevelExport.hpp" -#include - -// --------------------------------------------------------- // -// __ __ ____ _ _ _____ _______ ____ _____ _____ // -// | \/ |/ __ \| \ | |_ _|__ __/ __ \| __ \ / ____| // -// | \ / | | | | \| | | | | | | | | | |__) | (___ // -// | |\/| | | | | . ` | | | | | | | | | _ / \___ \ // -// | | | | |__| | |\ |_| |_ | | | |__| | | \ \ ____) | // -// |_| |_|\____/|_| \_|_____| |_| \____/|_| \_\_____/ // -// // -// --------------------------------------------------------- // - -void Events::listener_monitorFrame(void* owner, void* data) { - CMonitor* const PMONITOR = (CMonitor*)owner; - - if ((g_pCompositor->m_pAqBackend->hasSession() && !g_pCompositor->m_pAqBackend->session->active) || !g_pCompositor->m_bSessionActive || g_pCompositor->m_bUnsafeState) { - Debug::log(WARN, "Attempted to render frame on inactive session!"); - - if (g_pCompositor->m_bUnsafeState && std::ranges::any_of(g_pCompositor->m_vMonitors.begin(), g_pCompositor->m_vMonitors.end(), [&](auto& m) { - return m->output != g_pCompositor->m_pUnsafeOutput->output; - })) { - // restore from unsafe state - g_pCompositor->leaveUnsafeState(); - } - - return; // cannot draw on session inactive (different tty) - } - - if (!PMONITOR->m_bEnabled) - return; - - g_pHyprRenderer->recheckSolitaryForMonitor(PMONITOR); - - PMONITOR->tearingState.busy = false; - - if (PMONITOR->tearingState.activelyTearing && PMONITOR->solitaryClient.lock() /* can be invalidated by a recheck */) { - - if (!PMONITOR->tearingState.frameScheduledWhileBusy) - return; // we did not schedule a frame yet to be displayed, but we are tearing. Why render? - - PMONITOR->tearingState.nextRenderTorn = true; - PMONITOR->tearingState.frameScheduledWhileBusy = false; - } - - static auto PENABLERAT = CConfigValue("misc:render_ahead_of_time"); - static auto PRATSAFE = CConfigValue("misc:render_ahead_safezone"); - - PMONITOR->lastPresentationTimer.reset(); - - if (*PENABLERAT && !PMONITOR->tearingState.nextRenderTorn) { - if (!PMONITOR->RATScheduled) { - // render - g_pHyprRenderer->renderMonitor(PMONITOR); - } - - PMONITOR->RATScheduled = false; - - const auto& [avg, max, min] = g_pHyprRenderer->getRenderTimes(PMONITOR); - - if (max + *PRATSAFE > 1000.0 / PMONITOR->refreshRate) - return; - - const auto MSLEFT = 1000.0 / PMONITOR->refreshRate - PMONITOR->lastPresentationTimer.getMillis(); - - PMONITOR->RATScheduled = true; - - const auto ESTRENDERTIME = std::ceil(avg + *PRATSAFE); - const auto TIMETOSLEEP = std::floor(MSLEFT - ESTRENDERTIME); - - if (MSLEFT < 1 || MSLEFT < ESTRENDERTIME || TIMETOSLEEP < 1) - g_pHyprRenderer->renderMonitor(PMONITOR); - else - wl_event_source_timer_update(PMONITOR->renderTimer, TIMETOSLEEP); - } else { - g_pHyprRenderer->renderMonitor(PMONITOR); - } -} - -void Events::listener_monitorNeedsFrame(void* owner, void* data) { - const auto PMONITOR = (CMonitor*)owner; - - g_pCompositor->scheduleFrameForMonitor(PMONITOR, Aquamarine::IOutput::AQ_SCHEDULE_NEEDS_FRAME); -} - -void Events::listener_monitorCommit(void* owner, void* data) { - const auto PMONITOR = (CMonitor*)owner; - - if (true) { // FIXME: E->state->committed & WLR_OUTPUT_STATE_BUFFER - PROTO::screencopy->onOutputCommit(PMONITOR); - PROTO::toplevelExport->onOutputCommit(PMONITOR); - } -} - -void Events::listener_monitorBind(void* owner, void* data) { - ; -} diff --git a/src/helpers/Monitor.cpp b/src/helpers/Monitor.cpp index 091745df..74471f62 100644 --- a/src/helpers/Monitor.cpp +++ b/src/helpers/Monitor.cpp @@ -11,6 +11,8 @@ #include "../protocols/DRMLease.hpp" #include "../protocols/DRMSyncobj.hpp" #include "../protocols/core/Output.hpp" +#include "../protocols/Screencopy.hpp" +#include "../protocols/ToplevelExport.hpp" #include "../managers/PointerManager.hpp" #include "../managers/eventLoop/EventLoopManager.hpp" #include "../protocols/core/Compositor.hpp" @@ -44,8 +46,13 @@ void CMonitor::onConnect(bool noRule) { outTimeline = CSyncTimeline::create(output->getBackend()->drmFD()); } - listeners.frame = output->events.frame.registerListener([this](std::any d) { Events::listener_monitorFrame(this, nullptr); }); - listeners.commit = output->events.commit.registerListener([this](std::any d) { Events::listener_monitorCommit(this, nullptr); }); + listeners.frame = output->events.frame.registerListener([this](std::any d) { onMonitorFrame(); }); + listeners.commit = output->events.commit.registerListener([this](std::any d) { + if (true) { // FIXME: E->state->committed & WLR_OUTPUT_STATE_BUFFER + PROTO::screencopy->onOutputCommit(this); + PROTO::toplevelExport->onOutputCommit(this); + } + }); listeners.needsFrame = output->events.needsFrame.registerListener([this](std::any d) { g_pCompositor->scheduleFrameForMonitor(this, Aquamarine::IOutput::AQ_SCHEDULE_NEEDS_FRAME); }); @@ -939,6 +946,69 @@ void CMonitor::debugLastPresentation(const std::string& message) { lastPresentationTimer.getMillis() > 0 ? 1000.0f / lastPresentationTimer.getMillis() : 0.0f); } +void CMonitor::onMonitorFrame() { + if ((g_pCompositor->m_pAqBackend->hasSession() && !g_pCompositor->m_pAqBackend->session->active) || !g_pCompositor->m_bSessionActive || g_pCompositor->m_bUnsafeState) { + Debug::log(WARN, "Attempted to render frame on inactive session!"); + + if (g_pCompositor->m_bUnsafeState && std::ranges::any_of(g_pCompositor->m_vMonitors.begin(), g_pCompositor->m_vMonitors.end(), [&](auto& m) { + return m->output != g_pCompositor->m_pUnsafeOutput->output; + })) { + // restore from unsafe state + g_pCompositor->leaveUnsafeState(); + } + + return; // cannot draw on session inactive (different tty) + } + + if (!m_bEnabled) + return; + + g_pHyprRenderer->recheckSolitaryForMonitor(this); + + tearingState.busy = false; + + if (tearingState.activelyTearing && solitaryClient.lock() /* can be invalidated by a recheck */) { + + if (!tearingState.frameScheduledWhileBusy) + return; // we did not schedule a frame yet to be displayed, but we are tearing. Why render? + + tearingState.nextRenderTorn = true; + tearingState.frameScheduledWhileBusy = false; + } + + static auto PENABLERAT = CConfigValue("misc:render_ahead_of_time"); + static auto PRATSAFE = CConfigValue("misc:render_ahead_safezone"); + + lastPresentationTimer.reset(); + + if (*PENABLERAT && !tearingState.nextRenderTorn) { + if (!RATScheduled) { + // render + g_pHyprRenderer->renderMonitor(this); + } + + RATScheduled = false; + + const auto& [avg, max, min] = g_pHyprRenderer->getRenderTimes(this); + + if (max + *PRATSAFE > 1000.0 / refreshRate) + return; + + const auto MSLEFT = 1000.0 / refreshRate - lastPresentationTimer.getMillis(); + + RATScheduled = true; + + const auto ESTRENDERTIME = std::ceil(avg + *PRATSAFE); + const auto TIMETOSLEEP = std::floor(MSLEFT - ESTRENDERTIME); + + if (MSLEFT < 1 || MSLEFT < ESTRENDERTIME || TIMETOSLEEP < 1) + g_pHyprRenderer->renderMonitor(this); + else + wl_event_source_timer_update(renderTimer, TIMETOSLEEP); + } else + g_pHyprRenderer->renderMonitor(this); +} + CMonitorState::CMonitorState(CMonitor* owner) { m_pOwner = owner; } diff --git a/src/helpers/Monitor.hpp b/src/helpers/Monitor.hpp index ad8a823b..ceb90232 100644 --- a/src/helpers/Monitor.hpp +++ b/src/helpers/Monitor.hpp @@ -186,6 +186,7 @@ class CMonitor { void setCTM(const Mat3x3& ctm); void debugLastPresentation(const std::string& message); + void onMonitorFrame(); bool m_bEnabled = false; bool m_bRenderingInitPassed = false; From 0eaf3581a340f2521d96fe46d7956913c72d7698 Mon Sep 17 00:00:00 2001 From: Vaxry Date: Sat, 19 Oct 2024 16:24:03 +0100 Subject: [PATCH 0539/2181] window: guard PMONITOR in commit listener ref #8170 --- src/events/Windows.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/events/Windows.cpp b/src/events/Windows.cpp index d2d5bebf..37e5406c 100644 --- a/src/events/Windows.cpp +++ b/src/events/Windows.cpp @@ -775,7 +775,9 @@ void Events::listener_commitWindow(void* owner, void* data) { const auto PMONITOR = g_pCompositor->getMonitorFromID(PWINDOW->m_iMonitorID); - PMONITOR->debugLastPresentation(g_pSeatManager->isPointerFrameCommit ? "listener_commitWindow skip" : "listener_commitWindow"); + if (PMONITOR) + PMONITOR->debugLastPresentation(g_pSeatManager->isPointerFrameCommit ? "listener_commitWindow skip" : "listener_commitWindow"); + if (g_pSeatManager->isPointerFrameCommit) { g_pSeatManager->isPointerFrameSkipped = false; g_pSeatManager->isPointerFrameCommit = false; From ce3ba798df6bca5be1da4396644a9ef08a2acab4 Mon Sep 17 00:00:00 2001 From: Vaxry Date: Sat, 19 Oct 2024 17:03:22 +0100 Subject: [PATCH 0540/2181] defaultConfig: improve smart gaps --- example/hyprland.conf | 14 ++++++++++---- src/config/defaultConfig.hpp | 14 ++++++++++---- 2 files changed, 20 insertions(+), 8 deletions(-) diff --git a/example/hyprland.conf b/example/hyprland.conf index 6d7bddb8..012446f3 100644 --- a/example/hyprland.conf +++ b/example/hyprland.conf @@ -119,10 +119,16 @@ animations { # Ref https://wiki.hyprland.org/Configuring/Workspace-Rules/ # "Smart gaps" / "No gaps when only" -# uncomment all three if you wish to use that. -# workspace = w[t1], gapsout:0, gapsin:0, border: 0, rounding:0 -# workspace = w[tg1], gapsout:0, gapsin:0, border: 0, rounding:0 -# workspace = f[1], gapsout:0, gapsin:0, border: 0, rounding:0 +# uncomment all if you wish to use that. +# workspace = w[t1], gapsout:0, gapsin:0 +# workspace = w[tg1], gapsout:0, gapsin:0 +# workspace = f[1], gapsout:0, gapsin:0 +# windowrulev2 = bordersize 0, floating:0, onworkspace:w[t1] +# windowrulev2 = rounding 0, floating:0, onworkspace:w[t1] +# windowrulev2 = bordersize 0, floating:0, onworkspace:w[tg1] +# windowrulev2 = rounding 0, floating:0, onworkspace:w[tg1] +# windowrulev2 = bordersize 0, floating:0, onworkspace:f[1] +# windowrulev2 = rounding 0, floating:0, onworkspace:f[1] # See https://wiki.hyprland.org/Configuring/Dwindle-Layout/ for more dwindle { diff --git a/src/config/defaultConfig.hpp b/src/config/defaultConfig.hpp index 5c8b0e68..a5d759de 100644 --- a/src/config/defaultConfig.hpp +++ b/src/config/defaultConfig.hpp @@ -132,10 +132,16 @@ animations { # Ref https://wiki.hyprland.org/Configuring/Workspace-Rules/ # "Smart gaps" / "No gaps when only" -# uncomment all three if you wish to use that. -# workspace = w[t1], gapsout:0, gapsin:0, border: 0, rounding:0 -# workspace = w[tg1], gapsout:0, gapsin:0, border: 0, rounding:0 -# workspace = f[1], gapsout:0, gapsin:0, border: 0, rounding:0 +# uncomment all if you wish to use that. +# workspace = w[t1], gapsout:0, gapsin:0 +# workspace = w[tg1], gapsout:0, gapsin:0 +# workspace = f[1], gapsout:0, gapsin:0 +# windowrulev2 = bordersize 0, floating:0, onworkspace:w[t1] +# windowrulev2 = rounding 0, floating:0, onworkspace:w[t1] +# windowrulev2 = bordersize 0, floating:0, onworkspace:w[tg1] +# windowrulev2 = rounding 0, floating:0, onworkspace:w[tg1] +# windowrulev2 = bordersize 0, floating:0, onworkspace:f[1] +# windowrulev2 = rounding 0, floating:0, onworkspace:f[1] # See https://wiki.hyprland.org/Configuring/Dwindle-Layout/ for more dwindle { From f044e4c9514ec89c4c1fc8a523ca90b8cb907fb7 Mon Sep 17 00:00:00 2001 From: Vaxry <43317083+vaxerski@users.noreply.github.com> Date: Sat, 19 Oct 2024 23:03:29 +0100 Subject: [PATCH 0541/2181] internal: Move CMonitor to SP (#8178) * move monitors to sp * XD --- src/Compositor.cpp | 112 ++++++++--------- src/Compositor.hpp | 36 +++--- src/config/ConfigManager.cpp | 16 +-- src/config/ConfigManager.hpp | 4 +- src/debug/HyprCtl.cpp | 10 +- src/debug/HyprDebugOverlay.cpp | 18 +-- src/debug/HyprDebugOverlay.hpp | 24 ++-- src/debug/HyprNotificationOverlay.cpp | 6 +- src/debug/HyprNotificationOverlay.hpp | 8 +- src/desktop/DesktopTypes.hpp | 6 + src/desktop/LayerSurface.cpp | 6 +- src/desktop/Window.cpp | 2 +- src/desktop/Window.hpp | 2 +- src/events/Windows.cpp | 6 +- src/helpers/Monitor.cpp | 114 +++++++++--------- src/helpers/Monitor.hpp | 6 +- src/helpers/WLClasses.hpp | 20 +-- src/hyprerror/HyprError.cpp | 4 +- src/layout/DwindleLayout.cpp | 7 +- src/layout/MasterLayout.cpp | 7 +- src/managers/AnimationManager.cpp | 2 +- src/managers/CursorManager.cpp | 2 +- src/managers/KeybindManager.cpp | 16 +-- src/managers/KeybindManager.hpp | 2 +- src/managers/PointerManager.cpp | 34 ++---- src/managers/PointerManager.hpp | 2 - src/managers/ProtocolManager.cpp | 6 +- src/managers/ProtocolManager.hpp | 2 +- src/managers/SessionLockManager.cpp | 4 +- src/managers/XWaylandManager.cpp | 4 +- src/managers/input/InputManager.cpp | 10 +- src/managers/input/InputManager.hpp | 2 +- src/managers/input/InputMethodPopup.cpp | 6 +- src/managers/input/Swipe.cpp | 10 +- src/managers/input/Touch.cpp | 2 +- src/protocols/ForeignToplevelWlr.cpp | 4 +- src/protocols/ForeignToplevelWlr.hpp | 2 +- src/protocols/GammaControl.cpp | 8 +- src/protocols/GammaControl.hpp | 10 +- src/protocols/LayerShell.cpp | 6 +- src/protocols/LayerShell.hpp | 2 +- src/protocols/LinuxDMABUF.cpp | 4 +- src/protocols/OutputManagement.cpp | 22 ++-- src/protocols/OutputManagement.hpp | 24 ++-- src/protocols/OutputPower.cpp | 6 +- src/protocols/OutputPower.hpp | 4 +- src/protocols/PresentationTime.cpp | 4 +- src/protocols/Screencopy.cpp | 16 +-- src/protocols/Screencopy.hpp | 6 +- src/protocols/SessionLock.cpp | 8 +- src/protocols/SessionLock.hpp | 6 +- src/protocols/ToplevelExport.cpp | 2 +- src/protocols/ToplevelExport.hpp | 2 +- src/protocols/core/DataDevice.cpp | 2 +- src/protocols/core/DataDevice.hpp | 2 +- src/render/OpenGL.cpp | 22 ++-- src/render/OpenGL.hpp | 54 ++++----- src/render/Renderer.cpp | 62 +++++----- src/render/Renderer.hpp | 56 ++++----- .../decorations/CHyprBorderDecoration.cpp | 4 +- .../decorations/CHyprBorderDecoration.hpp | 2 +- .../decorations/CHyprDropShadowDecoration.cpp | 4 +- .../decorations/CHyprDropShadowDecoration.hpp | 2 +- .../decorations/CHyprGroupBarDecoration.cpp | 2 +- .../decorations/CHyprGroupBarDecoration.hpp | 2 +- .../decorations/IHyprWindowDecoration.hpp | 2 +- 66 files changed, 424 insertions(+), 446 deletions(-) diff --git a/src/Compositor.cpp b/src/Compositor.cpp index ca27f17a..b23b3194 100644 --- a/src/Compositor.cpp +++ b/src/Compositor.cpp @@ -412,8 +412,8 @@ void CCompositor::initAllSignals() { m_bSessionActive = true; for (auto const& m : m_vMonitors) { - scheduleFrameForMonitor(m.get()); - g_pHyprRenderer->applyMonitorRule(m.get(), &m->activeMonitorRule, true); + scheduleFrameForMonitor(m); + g_pHyprRenderer->applyMonitorRule(m, &m->activeMonitorRule, true); } g_pConfigManager->m_bWantsMonitorReload = true; @@ -498,7 +498,7 @@ void CCompositor::cleanup() { m_vWindows.clear(); for (auto const& m : m_vMonitors) { - g_pHyprOpenGL->destroyMonitorResources(m.get()); + g_pHyprOpenGL->destroyMonitorResources(m); m->output->state->setEnabled(false); m->state.commit(); @@ -717,38 +717,38 @@ void CCompositor::startCompositor() { g_pEventLoopManager->enterLoop(); } -CMonitor* CCompositor::getMonitorFromID(const MONITORID& id) { +PHLMONITOR CCompositor::getMonitorFromID(const MONITORID& id) { for (auto const& m : m_vMonitors) { if (m->ID == id) { - return m.get(); + return m; } } return nullptr; } -CMonitor* CCompositor::getMonitorFromName(const std::string& name) { +PHLMONITOR CCompositor::getMonitorFromName(const std::string& name) { for (auto const& m : m_vMonitors) { if (m->szName == name) { - return m.get(); + return m; } } return nullptr; } -CMonitor* CCompositor::getMonitorFromDesc(const std::string& desc) { +PHLMONITOR CCompositor::getMonitorFromDesc(const std::string& desc) { for (auto const& m : m_vMonitors) { if (m->szDescription.starts_with(desc)) - return m.get(); + return m; } return nullptr; } -CMonitor* CCompositor::getMonitorFromCursor() { +PHLMONITOR CCompositor::getMonitorFromCursor() { return getMonitorFromVector(g_pPointerManager->position()); } -CMonitor* CCompositor::getMonitorFromVector(const Vector2D& point) { +PHLMONITOR CCompositor::getMonitorFromVector(const Vector2D& point) { SP mon; for (auto const& m : m_vMonitors) { if (CBox{m->vecPosition, m->vecSize}.containsPoint(point)) { @@ -772,13 +772,13 @@ CMonitor* CCompositor::getMonitorFromVector(const Vector2D& point) { if (!pBestMon) { // ????? Debug::log(WARN, "getMonitorFromVector no close mon???"); - return m_vMonitors.front().get(); + return m_vMonitors.front(); } - return pBestMon.get(); + return pBestMon; } - return mon.get(); + return mon; } void CCompositor::removeWindowFromVectorSafe(PHLWINDOW pWindow) { @@ -790,9 +790,9 @@ void CCompositor::removeWindowFromVectorSafe(PHLWINDOW pWindow) { } } -bool CCompositor::monitorExists(CMonitor* pMonitor) { +bool CCompositor::monitorExists(PHLMONITOR pMonitor) { for (auto const& m : m_vRealMonitors) { - if (m.get() == pMonitor) + if (m == pMonitor) return true; } @@ -982,20 +982,20 @@ Vector2D CCompositor::vectorToSurfaceLocal(const Vector2D& vec, PHLWINDOW pWindo return vec - pWindow->m_vRealPosition.goal() - std::get<1>(iterData) + Vector2D{geom.x, geom.y}; } -CMonitor* CCompositor::getMonitorFromOutput(SP out) { +PHLMONITOR CCompositor::getMonitorFromOutput(SP out) { for (auto const& m : m_vMonitors) { if (m->output == out) { - return m.get(); + return m; } } return nullptr; } -CMonitor* CCompositor::getRealMonitorFromOutput(SP out) { +PHLMONITOR CCompositor::getRealMonitorFromOutput(SP out) { for (auto const& m : m_vRealMonitors) { if (m->output == out) { - return m.get(); + return m; } } @@ -1183,7 +1183,7 @@ void CCompositor::focusSurface(SP pSurface, PHLWINDOW pWindo SURF->constraint()->activate(); } -SP CCompositor::vectorToLayerPopupSurface(const Vector2D& pos, CMonitor* monitor, Vector2D* sCoords, PHLLS* ppLayerSurfaceFound) { +SP CCompositor::vectorToLayerPopupSurface(const Vector2D& pos, PHLMONITOR monitor, Vector2D* sCoords, PHLLS* ppLayerSurfaceFound) { for (auto const& lsl : monitor->m_aLayerSurfaceLayers | std::views::reverse) { for (auto const& ls : lsl | std::views::reverse) { if (ls->fadingOut || !ls->layerSurface || (ls->layerSurface && !ls->layerSurface->mapped) || ls->alpha.value() == 0.f) @@ -1779,7 +1779,7 @@ bool CCompositor::isPointOnAnyMonitor(const Vector2D& point) { return false; } -bool CCompositor::isPointOnReservedArea(const Vector2D& point, const CMonitor* pMonitor) { +bool CCompositor::isPointOnReservedArea(const Vector2D& point, const PHLMONITOR pMonitor) { const auto PMONITOR = pMonitor ? pMonitor : getMonitorFromVector(point); const auto XY1 = PMONITOR->vecPosition + PMONITOR->vecReservedTopLeft; @@ -1788,11 +1788,11 @@ bool CCompositor::isPointOnReservedArea(const Vector2D& point, const CMonitor* p return !VECINRECT(point, XY1.x, XY1.y, XY2.x, XY2.y); } -CMonitor* CCompositor::getMonitorInDirection(const char& dir) { - return this->getMonitorInDirection(m_pLastMonitor.get(), dir); +PHLMONITOR CCompositor::getMonitorInDirection(const char& dir) { + return getMonitorInDirection(m_pLastMonitor.lock(), dir); } -CMonitor* CCompositor::getMonitorInDirection(CMonitor* pSourceMonitor, const char& dir) { +PHLMONITOR CCompositor::getMonitorInDirection(PHLMONITOR pSourceMonitor, const char& dir) { if (!pSourceMonitor) return nullptr; @@ -1800,7 +1800,7 @@ CMonitor* CCompositor::getMonitorInDirection(CMonitor* pSourceMonitor, const cha const auto SIZEA = pSourceMonitor->vecSize; auto longestIntersect = -1; - CMonitor* longestIntersectMonitor = nullptr; + PHLMONITOR longestIntersectMonitor = nullptr; for (auto const& m : m_vMonitors) { if (m == m_pLastMonitor) @@ -1814,7 +1814,7 @@ CMonitor* CCompositor::getMonitorInDirection(CMonitor* pSourceMonitor, const cha const auto INTERSECTLEN = std::max(0.0, std::min(POSA.y + SIZEA.y, POSB.y + SIZEB.y) - std::max(POSA.y, POSB.y)); if (INTERSECTLEN > longestIntersect) { longestIntersect = INTERSECTLEN; - longestIntersectMonitor = m.get(); + longestIntersectMonitor = m; } } break; @@ -1823,7 +1823,7 @@ CMonitor* CCompositor::getMonitorInDirection(CMonitor* pSourceMonitor, const cha const auto INTERSECTLEN = std::max(0.0, std::min(POSA.y + SIZEA.y, POSB.y + SIZEB.y) - std::max(POSA.y, POSB.y)); if (INTERSECTLEN > longestIntersect) { longestIntersect = INTERSECTLEN; - longestIntersectMonitor = m.get(); + longestIntersectMonitor = m; } } break; @@ -1833,7 +1833,7 @@ CMonitor* CCompositor::getMonitorInDirection(CMonitor* pSourceMonitor, const cha const auto INTERSECTLEN = std::max(0.0, std::min(POSA.x + SIZEA.x, POSB.x + SIZEB.x) - std::max(POSA.x, POSB.x)); if (INTERSECTLEN > longestIntersect) { longestIntersect = INTERSECTLEN; - longestIntersectMonitor = m.get(); + longestIntersectMonitor = m; } } break; @@ -1843,7 +1843,7 @@ CMonitor* CCompositor::getMonitorInDirection(CMonitor* pSourceMonitor, const cha const auto INTERSECTLEN = std::max(0.0, std::min(POSA.x + SIZEA.x, POSB.x + SIZEB.x) - std::max(POSA.x, POSB.x)); if (INTERSECTLEN > longestIntersect) { longestIntersect = INTERSECTLEN; - longestIntersectMonitor = m.get(); + longestIntersectMonitor = m; } } break; @@ -1990,7 +1990,7 @@ MONITORID CCompositor::getNextAvailableMonitorID(std::string const& name) { return nextID; } -void CCompositor::swapActiveWorkspaces(CMonitor* pMonitorA, CMonitor* pMonitorB) { +void CCompositor::swapActiveWorkspaces(PHLMONITOR pMonitorA, PHLMONITOR pMonitorB) { const auto PWORKSPACEA = pMonitorA->activeWorkspace; const auto PWORKSPACEB = pMonitorB->activeWorkspace; @@ -2077,16 +2077,16 @@ void CCompositor::swapActiveWorkspaces(CMonitor* pMonitorA, CMonitor* pMonitorB) EMIT_HOOK_EVENT("moveWorkspace", (std::vector{PWORKSPACEB, pMonitorA})); } -CMonitor* CCompositor::getMonitorFromString(const std::string& name) { +PHLMONITOR CCompositor::getMonitorFromString(const std::string& name) { if (name == "current") - return g_pCompositor->m_pLastMonitor.get(); + return g_pCompositor->m_pLastMonitor.lock(); else if (isDirection(name)) return getMonitorInDirection(name[0]); else if (name[0] == '+' || name[0] == '-') { // relative if (m_vMonitors.size() == 1) - return m_vMonitors.begin()->get(); + return *m_vMonitors.begin(); const auto OFFSET = name[0] == '-' ? name : name.substr(1); @@ -2119,7 +2119,7 @@ CMonitor* CCompositor::getMonitorFromString(const std::string& name) { currentPlace = std::clamp(currentPlace, 0, (int)m_vMonitors.size() - 1); } - return m_vMonitors[currentPlace].get(); + return m_vMonitors[currentPlace]; } else if (isNumber(name)) { // change by ID MONITORID monID = MONITOR_INVALID; @@ -2143,7 +2143,7 @@ CMonitor* CCompositor::getMonitorFromString(const std::string& name) { continue; if (m->matchesStaticSelector(name)) { - return m.get(); + return m; } } } @@ -2151,7 +2151,7 @@ CMonitor* CCompositor::getMonitorFromString(const std::string& name) { return nullptr; } -void CCompositor::moveWorkspaceToMonitor(PHLWORKSPACE pWorkspace, CMonitor* pMonitor, bool noWarpCursor) { +void CCompositor::moveWorkspaceToMonitor(PHLWORKSPACE pWorkspace, PHLMONITOR pMonitor, bool noWarpCursor) { // We trust the monitor to be correct. @@ -2226,7 +2226,7 @@ void CCompositor::moveWorkspaceToMonitor(PHLWORKSPACE pWorkspace, CMonitor* pMon } } - if (SWITCHINGISACTIVE && POLDMON == g_pCompositor->m_pLastMonitor.get()) { // if it was active, preserve its' status. If it wasn't, don't. + if (SWITCHINGISACTIVE && POLDMON == g_pCompositor->m_pLastMonitor) { // if it was active, preserve its' status. If it wasn't, don't. Debug::log(LOG, "moveWorkspaceToMonitor: SWITCHINGISACTIVE, active {} -> {}", pMonitor->activeWorkspaceID(), pWorkspace->m_iID); if (valid(pMonitor->activeWorkspace)) { @@ -2438,7 +2438,7 @@ void CCompositor::updateWorkspaceWindowData(const WORKSPACEID& id) { } } -void CCompositor::scheduleFrameForMonitor(CMonitor* pMonitor, IOutput::scheduleFrameReason reason) { +void CCompositor::scheduleFrameForMonitor(PHLMONITOR pMonitor, IOutput::scheduleFrameReason reason) { if ((m_pAqBackend->hasSession() && !m_pAqBackend->session->active) || !m_bSessionActive) return; @@ -2555,7 +2555,7 @@ void CCompositor::warpCursorTo(const Vector2D& pos, bool force) { if (*PNOWARPS && !force) { const auto PMONITORNEW = getMonitorFromVector(pos); - if (PMONITORNEW != m_pLastMonitor.get()) + if (PMONITORNEW != m_pLastMonitor) setActiveMonitor(PMONITORNEW); return; } @@ -2563,7 +2563,7 @@ void CCompositor::warpCursorTo(const Vector2D& pos, bool force) { g_pPointerManager->warpTo(pos); const auto PMONITORNEW = getMonitorFromVector(pos); - if (PMONITORNEW != m_pLastMonitor.get()) + if (PMONITORNEW != m_pLastMonitor) setActiveMonitor(PMONITORNEW); } @@ -2690,8 +2690,8 @@ void CCompositor::renameWorkspace(const WORKSPACEID& id, const std::string& name g_pEventManager->postEvent({"renameworkspace", std::to_string(PWORKSPACE->m_iID) + "," + PWORKSPACE->m_szName}); } -void CCompositor::setActiveMonitor(CMonitor* pMonitor) { - if (m_pLastMonitor.get() == pMonitor) +void CCompositor::setActiveMonitor(PHLMONITOR pMonitor) { + if (m_pLastMonitor == pMonitor) return; if (!pMonitor) { @@ -2801,13 +2801,13 @@ PHLWINDOW CCompositor::getForceFocus() { } void CCompositor::arrangeMonitors() { - static auto* const PXWLFORCESCALEZERO = (Hyprlang::INT* const*)g_pConfigManager->getConfigValuePtr("xwayland:force_zero_scaling"); + static auto* const PXWLFORCESCALEZERO = (Hyprlang::INT* const*)g_pConfigManager->getConfigValuePtr("xwayland:force_zero_scaling"); - std::vector toArrange; - std::vector arranged; + std::vector toArrange; + std::vector arranged; for (auto const& m : m_vMonitors) - toArrange.push_back(m.get()); + toArrange.push_back(m); Debug::log(LOG, "arrangeMonitors: {} to arrange", toArrange.size()); @@ -2906,7 +2906,7 @@ void CCompositor::enterUnsafeState() { m_bUnsafeState = true; - setActiveMonitor(m_pUnsafeOutput); + setActiveMonitor(m_pUnsafeOutput.lock()); } void CCompositor::leaveUnsafeState() { @@ -2917,10 +2917,10 @@ void CCompositor::leaveUnsafeState() { m_bUnsafeState = false; - CMonitor* pNewMonitor = nullptr; + PHLMONITOR pNewMonitor = nullptr; for (auto const& pMonitor : m_vMonitors) { if (pMonitor->output != m_pUnsafeOutput->output) { - pNewMonitor = pMonitor.get(); + pNewMonitor = pMonitor; break; } } @@ -2931,7 +2931,7 @@ void CCompositor::leaveUnsafeState() { m_pUnsafeOutput->onDisconnect(); for (auto const& m : m_vMonitors) { - scheduleFrameForMonitor(m.get()); + scheduleFrameForMonitor(m); } } @@ -3007,7 +3007,7 @@ static void checkDefaultCursorWarp(SP monitor) { } // modechange happend check if cursor is on that monitor and warp it to middle to not place it out of bounds if resolution changed. - if (g_pCompositor->getMonitorFromCursor() == monitor.get()) { + if (g_pCompositor->getMonitorFromCursor() == monitor) { g_pCompositor->warpCursorTo(POS, true); g_pInputManager->refocus(); } @@ -3017,7 +3017,7 @@ void CCompositor::onNewMonitor(SP output) { // add it to real auto PNEWMONITOR = g_pCompositor->m_vRealMonitors.emplace_back(makeShared(output)); if (std::string("HEADLESS-1") == output->name) { - g_pCompositor->m_pUnsafeOutput = PNEWMONITOR.get(); + g_pCompositor->m_pUnsafeOutput = PNEWMONITOR; output->name = "FALLBACK"; // we are allowed to do this :) } @@ -3040,12 +3040,12 @@ void CCompositor::onNewMonitor(SP output) { // ready to process if we have a real monitor if ((!g_pHyprRenderer->m_pMostHzMonitor || PNEWMONITOR->refreshRate > g_pHyprRenderer->m_pMostHzMonitor->refreshRate) && PNEWMONITOR->m_bEnabled) - g_pHyprRenderer->m_pMostHzMonitor = PNEWMONITOR.get(); + g_pHyprRenderer->m_pMostHzMonitor = PNEWMONITOR; g_pCompositor->m_bReadyToProcess = true; g_pConfigManager->m_bWantsMonitorReload = true; - g_pCompositor->scheduleFrameForMonitor(PNEWMONITOR.get(), IOutput::AQ_SCHEDULE_NEW_MONITOR); + g_pCompositor->scheduleFrameForMonitor(PNEWMONITOR, IOutput::AQ_SCHEDULE_NEW_MONITOR); checkDefaultCursorWarp(PNEWMONITOR); @@ -3056,6 +3056,6 @@ void CCompositor::onNewMonitor(SP output) { } } - g_pHyprRenderer->damageMonitor(PNEWMONITOR.get()); + g_pHyprRenderer->damageMonitor(PNEWMONITOR); PNEWMONITOR->onMonitorFrame(); } diff --git a/src/Compositor.hpp b/src/Compositor.hpp index a57450f1..7fbd32e8 100644 --- a/src/Compositor.hpp +++ b/src/Compositor.hpp @@ -89,7 +89,7 @@ class CCompositor { bool m_bDPMSStateON = true; bool m_bUnsafeState = false; // unsafe state is when there is no monitors. bool m_bNextIsUnsafe = false; - CMonitor* m_pUnsafeOutput = nullptr; // fallback output for the unsafe state + PHLMONITORREF m_pUnsafeOutput; // fallback output for the unsafe state bool m_bIsShuttingDown = false; bool m_bFinalRequests = false; bool m_bDesktopEnvSet = false; @@ -97,22 +97,22 @@ class CCompositor { // ------------------------------------------------- // - CMonitor* getMonitorFromID(const MONITORID&); - CMonitor* getMonitorFromName(const std::string&); - CMonitor* getMonitorFromDesc(const std::string&); - CMonitor* getMonitorFromCursor(); - CMonitor* getMonitorFromVector(const Vector2D&); + PHLMONITOR getMonitorFromID(const MONITORID&); + PHLMONITOR getMonitorFromName(const std::string&); + PHLMONITOR getMonitorFromDesc(const std::string&); + PHLMONITOR getMonitorFromCursor(); + PHLMONITOR getMonitorFromVector(const Vector2D&); void removeWindowFromVectorSafe(PHLWINDOW); void focusWindow(PHLWINDOW, SP pSurface = nullptr); void focusSurface(SP, PHLWINDOW pWindowOwner = nullptr); - bool monitorExists(CMonitor*); + bool monitorExists(PHLMONITOR); PHLWINDOW vectorToWindowUnified(const Vector2D&, uint8_t properties, PHLWINDOW pIgnoreWindow = nullptr); SP vectorToLayerSurface(const Vector2D&, std::vector*, Vector2D*, PHLLS*); - SP vectorToLayerPopupSurface(const Vector2D&, CMonitor* monitor, Vector2D*, PHLLS*); + SP vectorToLayerPopupSurface(const Vector2D&, PHLMONITOR monitor, Vector2D*, PHLLS*); SP vectorWindowToSurface(const Vector2D&, PHLWINDOW, Vector2D& sl); Vector2D vectorToSurfaceLocal(const Vector2D&, PHLWINDOW, SP); - CMonitor* getMonitorFromOutput(SP); - CMonitor* getRealMonitorFromOutput(SP); + PHLMONITOR getMonitorFromOutput(SP); + PHLMONITOR getRealMonitorFromOutput(SP); PHLWINDOW getWindowFromSurface(SP); PHLWINDOW getWindowFromHandle(uint32_t); bool isWorkspaceVisible(PHLWORKSPACE); @@ -138,16 +138,16 @@ class CCompositor { PHLWINDOW getPrevWindowOnWorkspace(PHLWINDOW, bool focusableOnly = false, std::optional floating = {}); WORKSPACEID getNextAvailableNamedWorkspace(); bool isPointOnAnyMonitor(const Vector2D&); - bool isPointOnReservedArea(const Vector2D& point, const CMonitor* monitor = nullptr); - CMonitor* getMonitorInDirection(const char&); - CMonitor* getMonitorInDirection(CMonitor*, const char&); + bool isPointOnReservedArea(const Vector2D& point, const PHLMONITOR monitor = nullptr); + PHLMONITOR getMonitorInDirection(const char&); + PHLMONITOR getMonitorInDirection(PHLMONITOR, const char&); void updateAllWindowsAnimatedDecorationValues(); void updateWorkspaceWindows(const WORKSPACEID& id); void updateWindowAnimatedDecorationValues(PHLWINDOW); MONITORID getNextAvailableMonitorID(std::string const& name); - void moveWorkspaceToMonitor(PHLWORKSPACE, CMonitor*, bool noWarpCursor = false); - void swapActiveWorkspaces(CMonitor*, CMonitor*); - CMonitor* getMonitorFromString(const std::string&); + void moveWorkspaceToMonitor(PHLWORKSPACE, PHLMONITOR, bool noWarpCursor = false); + void swapActiveWorkspaces(PHLMONITOR, PHLMONITOR); + PHLMONITOR getMonitorFromString(const std::string&); bool workspaceIDOutOfBounds(const WORKSPACEID&); void setWindowFullscreenInternal(const PHLWINDOW PWINDOW, const eFullscreenMode MODE); void setWindowFullscreenClient(const PHLWINDOW PWINDOW, const eFullscreenMode MODE); @@ -156,7 +156,7 @@ class CCompositor { void changeWindowFullscreenModeClient(const PHLWINDOW PWINDOW, const eFullscreenMode MODE, const bool ON); void updateFullscreenFadeOnWorkspace(PHLWORKSPACE); PHLWINDOW getX11Parent(PHLWINDOW); - void scheduleFrameForMonitor(CMonitor*, Aquamarine::IOutput::scheduleFrameReason reason = Aquamarine::IOutput::AQ_SCHEDULE_CLIENT_UNKNOWN); + void scheduleFrameForMonitor(PHLMONITOR, Aquamarine::IOutput::scheduleFrameReason reason = Aquamarine::IOutput::AQ_SCHEDULE_CLIENT_UNKNOWN); void addToFadingOutSafe(PHLLS); void removeFromFadingOutSafe(PHLLS); void addToFadingOutSafe(PHLWINDOW); @@ -169,7 +169,7 @@ class CCompositor { PHLWORKSPACE createNewWorkspace(const WORKSPACEID&, const MONITORID&, const std::string& name = "", bool isEmpty = true); // will be deleted next frame if left empty and unfocused! void renameWorkspace(const WORKSPACEID&, const std::string& name = ""); - void setActiveMonitor(CMonitor*); + void setActiveMonitor(PHLMONITOR); bool isWorkspaceSpecial(const WORKSPACEID&); WORKSPACEID getNewSpecialID(); void performUserChecks(); diff --git a/src/config/ConfigManager.cpp b/src/config/ConfigManager.cpp index 432b7faf..f16ebe46 100644 --- a/src/config/ConfigManager.cpp +++ b/src/config/ConfigManager.cpp @@ -943,9 +943,9 @@ void CConfigManager::postConfigReload(const Hyprlang::CParseResult& result) { for (auto const& m : g_pCompositor->m_vMonitors) { // mark blur dirty - g_pHyprOpenGL->markBlurDirtyForMonitor(m.get()); + g_pHyprOpenGL->markBlurDirtyForMonitor(m); - g_pCompositor->scheduleFrameForMonitor(m.get()); + g_pCompositor->scheduleFrameForMonitor(m); // Force the compositor to fully re-render all monitors m->forceFullFrames = 2; @@ -1506,7 +1506,7 @@ void CConfigManager::performMonitorReload() { auto rule = getMonitorRuleFor(m); - if (!g_pHyprRenderer->applyMonitorRule(m.get(), &rule)) { + if (!g_pHyprRenderer->applyMonitorRule(m, &rule)) { overAgain = true; break; } @@ -1564,14 +1564,14 @@ void CConfigManager::ensureMonitorStatus() { auto rule = getMonitorRuleFor(rm); if (rule.disabled == rm->m_bEnabled) - g_pHyprRenderer->applyMonitorRule(rm.get(), &rule); + g_pHyprRenderer->applyMonitorRule(rm, &rule); } } -void CConfigManager::ensureVRR(CMonitor* pMonitor) { +void CConfigManager::ensureVRR(PHLMONITOR pMonitor) { static auto PVRR = reinterpret_cast(getConfigValuePtr("misc:vrr")); - static auto ensureVRRForDisplay = [&](CMonitor* m) -> void { + static auto ensureVRRForDisplay = [&](PHLMONITOR m) -> void { if (!m->output || m->createdByUser) return; @@ -1641,7 +1641,7 @@ void CConfigManager::ensureVRR(CMonitor* pMonitor) { } for (auto const& m : g_pCompositor->m_vMonitors) { - ensureVRRForDisplay(m.get()); + ensureVRRForDisplay(m); } } @@ -1653,7 +1653,7 @@ void CConfigManager::addParseError(const std::string& err) { g_pHyprError->queueCreate(err + "\nHyprland may not work correctly.", CColor(1.0, 50.0 / 255.0, 50.0 / 255.0, 1.0)); } -CMonitor* CConfigManager::getBoundMonitorForWS(const std::string& wsname) { +PHLMONITOR CConfigManager::getBoundMonitorForWS(const std::string& wsname) { auto monitor = getBoundMonitorStringForWS(wsname); if (monitor.substr(0, 5) == "desc:") return g_pCompositor->getMonitorFromDesc(monitor.substr(5)); diff --git a/src/config/ConfigManager.hpp b/src/config/ConfigManager.hpp index 2134acf4..e9ed2d64 100644 --- a/src/config/ConfigManager.hpp +++ b/src/config/ConfigManager.hpp @@ -173,7 +173,7 @@ class CConfigManager { SWorkspaceRule getWorkspaceRuleFor(PHLWORKSPACE workspace); std::string getDefaultWorkspaceFor(const std::string&); - CMonitor* getBoundMonitorForWS(const std::string&); + PHLMONITOR getBoundMonitorForWS(const std::string&); std::string getBoundMonitorStringForWS(const std::string&); const std::deque& getAllWorkspaceRules(); @@ -198,7 +198,7 @@ class CConfigManager { void appendMonitorRule(const SMonitorRule&); bool replaceMonitorRule(const SMonitorRule&); void ensureMonitorStatus(); - void ensureVRR(CMonitor* pMonitor = nullptr); + void ensureVRR(PHLMONITOR pMonitor = nullptr); std::string parseKeyword(const std::string&, const std::string&); diff --git a/src/debug/HyprCtl.cpp b/src/debug/HyprCtl.cpp index e0bb2b83..e09fb529 100644 --- a/src/debug/HyprCtl.cpp +++ b/src/debug/HyprCtl.cpp @@ -54,7 +54,7 @@ static std::string formatToString(uint32_t drmFormat) { return "Invalid"; } -static std::string availableModesForOutput(CMonitor* pMonitor, eHyprCtlOutputFormat format) { +static std::string availableModesForOutput(PHLMONITOR pMonitor, eHyprCtlOutputFormat format) { std::string result; for (auto const& m : pMonitor->output->modes) { @@ -117,7 +117,7 @@ std::string CHyprCtl::getMonitorData(Hyprutils::Memory::CSharedPointer (int)m->vecReservedBottomRight.x, (int)m->vecReservedBottomRight.y, m->scale, (int)m->transform, (m == g_pCompositor->m_pLastMonitor ? "true" : "false"), (m->dpmsStatus ? "true" : "false"), (m->output->state->state().adaptiveSync ? "true" : "false"), (uint64_t)m->solitaryClient.get(), (m->tearingState.activelyTearing ? "true" : "false"), (m->m_bEnabled ? "false" : "true"), formatToString(m->output->state->state().drmFormat), - availableModesForOutput(m.get(), format)); + availableModesForOutput(m, format)); } else { result += std::format("Monitor {} (ID {}):\n\t{}x{}@{:.5f} at {}x{}\n\tdescription: {}\n\tmake: {}\n\tmodel: {}\n\tserial: {}\n\tactive workspace: {} ({})\n\t" @@ -128,7 +128,7 @@ std::string CHyprCtl::getMonitorData(Hyprutils::Memory::CSharedPointer m->activeSpecialWorkspaceID(), (m->activeSpecialWorkspace ? m->activeSpecialWorkspace->m_szName : ""), (int)m->vecReservedTopLeft.x, (int)m->vecReservedTopLeft.y, (int)m->vecReservedBottomRight.x, (int)m->vecReservedBottomRight.y, m->scale, (int)m->transform, (m == g_pCompositor->m_pLastMonitor ? "yes" : "no"), (int)m->dpmsStatus, m->output->state->state().adaptiveSync, (uint64_t)m->solitaryClient.get(), - m->tearingState.activelyTearing, !m->m_bEnabled, formatToString(m->output->state->state().drmFormat), availableModesForOutput(m.get(), format)); + m->tearingState.activelyTearing, !m->m_bEnabled, formatToString(m->output->state->state().drmFormat), availableModesForOutput(m, format)); } return result; @@ -1030,7 +1030,7 @@ std::string dispatchKeyword(eHyprCtlOutputFormat format, std::string in) { // decorations will probably need a repaint if (COMMAND.contains("decoration:") || COMMAND.contains("border") || COMMAND == "workspace" || COMMAND.contains("zoom_factor") || COMMAND == "source") { for (auto const& m : g_pCompositor->m_vMonitors) { - g_pHyprRenderer->damageMonitor(m.get()); + g_pHyprRenderer->damageMonitor(m); g_pLayoutManager->getCurrentLayout()->recalculateMonitor(m->ID); } } @@ -1779,7 +1779,7 @@ std::string CHyprCtl::getReply(std::string request) { } for (auto const& m : g_pCompositor->m_vMonitors) { - g_pHyprRenderer->damageMonitor(m.get()); + g_pHyprRenderer->damageMonitor(m); g_pLayoutManager->getCurrentLayout()->recalculateMonitor(m->ID); } } diff --git a/src/debug/HyprDebugOverlay.cpp b/src/debug/HyprDebugOverlay.cpp index 2da64e63..9326cfe0 100644 --- a/src/debug/HyprDebugOverlay.cpp +++ b/src/debug/HyprDebugOverlay.cpp @@ -7,7 +7,7 @@ CHyprDebugOverlay::CHyprDebugOverlay() { m_pTexture = makeShared(); } -void CHyprMonitorDebugOverlay::renderData(CMonitor* pMonitor, float durationUs) { +void CHyprMonitorDebugOverlay::renderData(PHLMONITOR pMonitor, float durationUs) { m_dLastRenderTimes.push_back(durationUs / 1000.f); if (m_dLastRenderTimes.size() > (long unsigned int)pMonitor->refreshRate) @@ -17,7 +17,7 @@ void CHyprMonitorDebugOverlay::renderData(CMonitor* pMonitor, float durationUs) m_pMonitor = pMonitor; } -void CHyprMonitorDebugOverlay::renderDataNoOverlay(CMonitor* pMonitor, float durationUs) { +void CHyprMonitorDebugOverlay::renderDataNoOverlay(PHLMONITOR pMonitor, float durationUs) { m_dLastRenderTimesNoOverlay.push_back(durationUs / 1000.f); if (m_dLastRenderTimesNoOverlay.size() > (long unsigned int)pMonitor->refreshRate) @@ -27,7 +27,7 @@ void CHyprMonitorDebugOverlay::renderDataNoOverlay(CMonitor* pMonitor, float dur m_pMonitor = pMonitor; } -void CHyprMonitorDebugOverlay::frameData(CMonitor* pMonitor) { +void CHyprMonitorDebugOverlay::frameData(PHLMONITOR pMonitor) { m_dLastFrametimes.push_back(std::chrono::duration_cast(std::chrono::high_resolution_clock::now() - m_tpLastFrame).count() / 1000.f); if (m_dLastFrametimes.size() > (long unsigned int)pMonitor->refreshRate) @@ -39,7 +39,7 @@ void CHyprMonitorDebugOverlay::frameData(CMonitor* pMonitor) { m_pMonitor = pMonitor; // anim data too - const auto PMONITORFORTICKS = g_pHyprRenderer->m_pMostHzMonitor ? g_pHyprRenderer->m_pMostHzMonitor : g_pCompositor->m_pLastMonitor.get(); + const auto PMONITORFORTICKS = g_pHyprRenderer->m_pMostHzMonitor ? g_pHyprRenderer->m_pMostHzMonitor.lock() : g_pCompositor->m_pLastMonitor.lock(); if (PMONITORFORTICKS) { if (m_dLastAnimationTicks.size() > (long unsigned int)PMONITORFORTICKS->refreshRate) m_dLastAnimationTicks.pop_front(); @@ -188,21 +188,21 @@ int CHyprMonitorDebugOverlay::draw(int offset) { return posY - offset; } -void CHyprDebugOverlay::renderData(CMonitor* pMonitor, float durationUs) { +void CHyprDebugOverlay::renderData(PHLMONITOR pMonitor, float durationUs) { m_mMonitorOverlays[pMonitor].renderData(pMonitor, durationUs); } -void CHyprDebugOverlay::renderDataNoOverlay(CMonitor* pMonitor, float durationUs) { +void CHyprDebugOverlay::renderDataNoOverlay(PHLMONITOR pMonitor, float durationUs) { m_mMonitorOverlays[pMonitor].renderDataNoOverlay(pMonitor, durationUs); } -void CHyprDebugOverlay::frameData(CMonitor* pMonitor) { +void CHyprDebugOverlay::frameData(PHLMONITOR pMonitor) { m_mMonitorOverlays[pMonitor].frameData(pMonitor); } void CHyprDebugOverlay::draw() { - const auto PMONITOR = g_pCompositor->m_vMonitors.front().get(); + const auto PMONITOR = g_pCompositor->m_vMonitors.front(); if (!m_pCairoSurface || !m_pCairo) { m_pCairoSurface = cairo_image_surface_create(CAIRO_FORMAT_ARGB32, PMONITOR->vecPixelSize.x, PMONITOR->vecPixelSize.y); @@ -218,7 +218,7 @@ void CHyprDebugOverlay::draw() { // draw the things int offsetY = 0; for (auto const& m : g_pCompositor->m_vMonitors) { - offsetY += m_mMonitorOverlays[m.get()].draw(offsetY); + offsetY += m_mMonitorOverlays[m].draw(offsetY); offsetY += 5; // for padding between mons } diff --git a/src/debug/HyprDebugOverlay.hpp b/src/debug/HyprDebugOverlay.hpp index e7742b35..19b9120a 100644 --- a/src/debug/HyprDebugOverlay.hpp +++ b/src/debug/HyprDebugOverlay.hpp @@ -5,7 +5,7 @@ #include "../render/Texture.hpp" #include #include -#include +#include class CHyprRenderer; @@ -13,9 +13,9 @@ class CHyprMonitorDebugOverlay { public: int draw(int offset); - void renderData(CMonitor* pMonitor, float durationUs); - void renderDataNoOverlay(CMonitor* pMonitor, float durationUs); - void frameData(CMonitor* pMonitor); + void renderData(PHLMONITOR pMonitor, float durationUs); + void renderDataNoOverlay(PHLMONITOR pMonitor, float durationUs); + void frameData(PHLMONITOR pMonitor); private: std::deque m_dLastFrametimes; @@ -23,7 +23,7 @@ class CHyprMonitorDebugOverlay { std::deque m_dLastRenderTimesNoOverlay; std::deque m_dLastAnimationTicks; std::chrono::high_resolution_clock::time_point m_tpLastFrame; - CMonitor* m_pMonitor = nullptr; + PHLMONITORREF m_pMonitor; CBox m_wbLastDrawnBox; friend class CHyprRenderer; @@ -33,17 +33,17 @@ class CHyprDebugOverlay { public: CHyprDebugOverlay(); void draw(); - void renderData(CMonitor*, float durationUs); - void renderDataNoOverlay(CMonitor*, float durationUs); - void frameData(CMonitor*); + void renderData(PHLMONITOR, float durationUs); + void renderDataNoOverlay(PHLMONITOR, float durationUs); + void frameData(PHLMONITOR); private: - std::unordered_map m_mMonitorOverlays; + std::map m_mMonitorOverlays; - cairo_surface_t* m_pCairoSurface = nullptr; - cairo_t* m_pCairo = nullptr; + cairo_surface_t* m_pCairoSurface = nullptr; + cairo_t* m_pCairo = nullptr; - SP m_pTexture; + SP m_pTexture; friend class CHyprMonitorDebugOverlay; friend class CHyprRenderer; diff --git a/src/debug/HyprNotificationOverlay.cpp b/src/debug/HyprNotificationOverlay.cpp index 16f80ab6..e46999e6 100644 --- a/src/debug/HyprNotificationOverlay.cpp +++ b/src/debug/HyprNotificationOverlay.cpp @@ -45,7 +45,7 @@ void CHyprNotificationOverlay::addNotification(const std::string& text, const CC PNOTIF->fontSize = fontSize; for (auto const& m : g_pCompositor->m_vMonitors) { - g_pCompositor->scheduleFrameForMonitor(m.get()); + g_pCompositor->scheduleFrameForMonitor(m); } } @@ -61,7 +61,7 @@ void CHyprNotificationOverlay::dismissNotifications(const int amount) { } } -CBox CHyprNotificationOverlay::drawNotifications(CMonitor* pMonitor) { +CBox CHyprNotificationOverlay::drawNotifications(PHLMONITOR pMonitor) { static constexpr auto ANIM_DURATION_MS = 600.0; static constexpr auto ANIM_LAG_MS = 100.0; static constexpr auto NOTIF_LEFTBAR_SIZE = 5.0; @@ -187,7 +187,7 @@ CBox CHyprNotificationOverlay::drawNotifications(CMonitor* pMonitor) { return CBox{(int)(pMonitor->vecPosition.x + pMonitor->vecSize.x - maxWidth - 20), (int)pMonitor->vecPosition.y, (int)maxWidth + 20, (int)offsetY + 10}; } -void CHyprNotificationOverlay::draw(CMonitor* pMonitor) { +void CHyprNotificationOverlay::draw(PHLMONITOR pMonitor) { const auto MONSIZE = pMonitor->vecTransformedSize; diff --git a/src/debug/HyprNotificationOverlay.hpp b/src/debug/HyprNotificationOverlay.hpp index 352c44c9..0bba8b04 100644 --- a/src/debug/HyprNotificationOverlay.hpp +++ b/src/debug/HyprNotificationOverlay.hpp @@ -41,13 +41,13 @@ class CHyprNotificationOverlay { CHyprNotificationOverlay(); ~CHyprNotificationOverlay(); - void draw(CMonitor* pMonitor); + void draw(PHLMONITOR pMonitor); void addNotification(const std::string& text, const CColor& color, const float timeMs, const eIcons icon = ICON_NONE, const float fontSize = 13.f); void dismissNotifications(const int amount); bool hasAny(); private: - CBox drawNotifications(CMonitor* pMonitor); + CBox drawNotifications(PHLMONITOR pMonitor); CBox m_bLastDamage; std::deque> m_dNotifications; @@ -55,8 +55,8 @@ class CHyprNotificationOverlay { cairo_surface_t* m_pCairoSurface = nullptr; cairo_t* m_pCairo = nullptr; - CMonitor* m_pLastMonitor = nullptr; - Vector2D m_vecLastSize = Vector2D(-1, -1); + PHLMONITORREF m_pLastMonitor; + Vector2D m_vecLastSize = Vector2D(-1, -1); SP m_pTexture; }; diff --git a/src/desktop/DesktopTypes.hpp b/src/desktop/DesktopTypes.hpp index 4e40c4e0..7f812cc1 100644 --- a/src/desktop/DesktopTypes.hpp +++ b/src/desktop/DesktopTypes.hpp @@ -3,6 +3,7 @@ class CWorkspace; class CWindow; class CLayerSurface; +class CMonitor; /* Shared pointer to a workspace */ typedef SP PHLWORKSPACE; @@ -18,3 +19,8 @@ typedef WP PHLWINDOWREF; typedef SP PHLLS; /* Weak pointer to a layer surface */ typedef WP PHLLSREF; + +/* Shared pointer to a monitor */ +typedef SP PHLMONITOR; +/* Weak pointer to a monitor */ +typedef WP PHLMONITORREF; diff --git a/src/desktop/LayerSurface.cpp b/src/desktop/LayerSurface.cpp index 0e7e71b6..6c024ee0 100644 --- a/src/desktop/LayerSurface.cpp +++ b/src/desktop/LayerSurface.cpp @@ -6,9 +6,9 @@ #include "../managers/SeatManager.hpp" PHLLS CLayerSurface::create(SP resource) { - PHLLS pLS = SP(new CLayerSurface(resource)); + PHLLS pLS = SP(new CLayerSurface(resource)); - CMonitor* pMonitor = resource->monitor.empty() ? g_pCompositor->getMonitorFromCursor() : g_pCompositor->getMonitorFromName(resource->monitor); + auto pMonitor = resource->monitor.empty() ? g_pCompositor->getMonitorFromCursor() : g_pCompositor->getMonitorFromName(resource->monitor); pLS->surface->assign(resource->surface.lock(), pLS); @@ -18,7 +18,7 @@ PHLLS CLayerSurface::create(SP resource) { } if (pMonitor->pMirrorOf) - pMonitor = g_pCompositor->m_vMonitors.front().get(); + pMonitor = g_pCompositor->m_vMonitors.front(); pLS->self = pLS; diff --git a/src/desktop/Window.cpp b/src/desktop/Window.cpp index a393f361..1297bb83 100644 --- a/src/desktop/Window.cpp +++ b/src/desktop/Window.cpp @@ -1188,7 +1188,7 @@ void CWindow::setSuspended(bool suspend) { m_bSuspended = suspend; } -bool CWindow::visibleOnMonitor(CMonitor* pMonitor) { +bool CWindow::visibleOnMonitor(PHLMONITOR pMonitor) { CBox wbox = {m_vRealPosition.value(), m_vRealSize.value()}; return !wbox.intersection({pMonitor->vecPosition, pMonitor->vecSize}).empty(); diff --git a/src/desktop/Window.hpp b/src/desktop/Window.hpp index 9baf57c4..b2a8e763 100644 --- a/src/desktop/Window.hpp +++ b/src/desktop/Window.hpp @@ -424,7 +424,7 @@ class CWindow { float rounding(); bool canBeTorn(); void setSuspended(bool suspend); - bool visibleOnMonitor(CMonitor* pMonitor); + bool visibleOnMonitor(PHLMONITOR pMonitor); WORKSPACEID workspaceID(); bool onSpecialWorkspace(); void activate(bool force = false); diff --git a/src/events/Windows.cpp b/src/events/Windows.cpp index 37e5406c..21055f79 100644 --- a/src/events/Windows.cpp +++ b/src/events/Windows.cpp @@ -49,10 +49,10 @@ void Events::listener_mapWindow(void* owner, void* data) { static auto PNEWTAKESOVERFS = CConfigValue("misc:new_window_takes_over_fullscreen"); static auto PINITIALWSTRACKING = CConfigValue("misc:initial_workspace_tracking"); - auto PMONITOR = g_pCompositor->m_pLastMonitor.get(); + auto PMONITOR = g_pCompositor->m_pLastMonitor.lock(); if (!g_pCompositor->m_pLastMonitor) { g_pCompositor->setActiveMonitor(g_pCompositor->getMonitorFromVector({})); - PMONITOR = g_pCompositor->m_pLastMonitor.get(); + PMONITOR = g_pCompositor->m_pLastMonitor.lock(); } auto PWORKSPACE = PMONITOR->activeSpecialWorkspace ? PMONITOR->activeSpecialWorkspace : PMONITOR->activeWorkspace; PWINDOW->m_iMonitorID = PMONITOR->ID; @@ -314,7 +314,7 @@ void Events::listener_mapWindow(void* owner, void* data) { else if (PMONITOR->activeWorkspaceID() != REQUESTEDWORKSPACEID) g_pKeybindManager->m_mDispatchers["workspace"](requestedWorkspaceName); - PMONITOR = g_pCompositor->m_pLastMonitor.get(); + PMONITOR = g_pCompositor->m_pLastMonitor.lock(); } } else workspaceSilent = false; diff --git a/src/helpers/Monitor.cpp b/src/helpers/Monitor.cpp index 74471f62..6ded5ea4 100644 --- a/src/helpers/Monitor.cpp +++ b/src/helpers/Monitor.cpp @@ -25,7 +25,7 @@ using namespace Hyprutils::String; using namespace Hyprutils::Utils; int ratHandler(void* data) { - g_pHyprRenderer->renderMonitor((CMonitor*)data); + g_pHyprRenderer->renderMonitor(((CMonitor*)data)->self.lock()); return 1; } @@ -49,12 +49,12 @@ void CMonitor::onConnect(bool noRule) { listeners.frame = output->events.frame.registerListener([this](std::any d) { onMonitorFrame(); }); listeners.commit = output->events.commit.registerListener([this](std::any d) { if (true) { // FIXME: E->state->committed & WLR_OUTPUT_STATE_BUFFER - PROTO::screencopy->onOutputCommit(this); - PROTO::toplevelExport->onOutputCommit(this); + PROTO::screencopy->onOutputCommit(self.lock()); + PROTO::toplevelExport->onOutputCommit(self.lock()); } }); listeners.needsFrame = - output->events.needsFrame.registerListener([this](std::any d) { g_pCompositor->scheduleFrameForMonitor(this, Aquamarine::IOutput::AQ_SCHEDULE_NEEDS_FRAME); }); + output->events.needsFrame.registerListener([this](std::any d) { g_pCompositor->scheduleFrameForMonitor(self.lock(), Aquamarine::IOutput::AQ_SCHEDULE_NEEDS_FRAME); }); listeners.presented = output->events.present.registerListener([this](std::any d) { auto E = std::any_cast(d); @@ -84,7 +84,7 @@ void CMonitor::onConnect(bool noRule) { return; Debug::log(LOG, "Reapplying monitor rule for {} from a state request", szName); - g_pHyprRenderer->applyMonitorRule(this, &activeMonitorRule, true); + g_pHyprRenderer->applyMonitorRule(self.lock(), &activeMonitorRule, true); return; } @@ -98,7 +98,7 @@ void CMonitor::onConnect(bool noRule) { SMonitorRule rule = activeMonitorRule; rule.resolution = SIZE; - g_pHyprRenderer->applyMonitorRule(this, &rule); + g_pHyprRenderer->applyMonitorRule(self.lock(), &rule); }); tearingState.canTear = output->getBackend()->type() == Aquamarine::AQ_BACKEND_DRM; @@ -171,7 +171,7 @@ void CMonitor::onConnect(bool noRule) { // set mode, also applies if (!noRule) - g_pHyprRenderer->applyMonitorRule(this, &monitorRule, true); + g_pHyprRenderer->applyMonitorRule(self.lock(), &monitorRule, true); if (!state.commit()) Debug::log(WARN, "state.commit() failed in CMonitor::onCommit"); @@ -187,7 +187,7 @@ void CMonitor::onConnect(bool noRule) { continue; if (ws->m_szLastMonitor == szName || g_pCompositor->m_vMonitors.size() == 1 /* avoid lost workspaces on recover */) { - g_pCompositor->moveWorkspaceToMonitor(ws, this); + g_pCompositor->moveWorkspaceToMonitor(ws, self.lock()); ws->startAnim(true, true, true); ws->m_szLastMonitor = ""; } @@ -204,13 +204,13 @@ void CMonitor::onConnect(bool noRule) { setMirror(activeMonitorRule.mirrorOf); if (!g_pCompositor->m_pLastMonitor) // set the last monitor if it isnt set yet - g_pCompositor->setActiveMonitor(this); + g_pCompositor->setActiveMonitor(self.lock()); g_pHyprRenderer->arrangeLayersForMonitor(ID); g_pLayoutManager->getCurrentLayout()->recalculateMonitor(ID); // ensure VRR (will enable if necessary) - g_pConfigManager->ensureVRR(this); + g_pConfigManager->ensureVRR(self.lock()); // verify last mon valid bool found = false; @@ -222,19 +222,19 @@ void CMonitor::onConnect(bool noRule) { } if (!found) - g_pCompositor->setActiveMonitor(this); + g_pCompositor->setActiveMonitor(self.lock()); renderTimer = wl_event_loop_add_timer(g_pCompositor->m_sWLEventLoop, ratHandler, this); - g_pCompositor->scheduleFrameForMonitor(this, Aquamarine::IOutput::AQ_SCHEDULE_NEW_MONITOR); + g_pCompositor->scheduleFrameForMonitor(self.lock(), Aquamarine::IOutput::AQ_SCHEDULE_NEW_MONITOR); - PROTO::gamma->applyGammaToState(this); + PROTO::gamma->applyGammaToState(self.lock()); events.connect.emit(); g_pEventManager->postEvent(SHyprIPCEvent{"monitoradded", szName}); g_pEventManager->postEvent(SHyprIPCEvent{"monitoraddedv2", std::format("{},{},{}", ID, szName, szShortDescription)}); - EMIT_HOOK_EVENT("monitorAdded", this); + EMIT_HOOK_EVENT("monitorAdded", self.lock()); } void CMonitor::onDisconnect(bool destroy) { @@ -242,7 +242,7 @@ void CMonitor::onDisconnect(bool destroy) { if (g_pCompositor->m_bIsShuttingDown) return; g_pEventManager->postEvent(SHyprIPCEvent{"monitorremoved", szName}); - EMIT_HOOK_EVENT("monitorRemoved", this); + EMIT_HOOK_EVENT("monitorRemoved", self.lock()); g_pCompositor->arrangeMonitors(); }}; @@ -259,21 +259,21 @@ void CMonitor::onDisconnect(bool destroy) { events.disconnect.emit(); // Cleanup everything. Move windows back, snap cursor, shit. - CMonitor* BACKUPMON = nullptr; + PHLMONITOR BACKUPMON = nullptr; for (auto const& m : g_pCompositor->m_vMonitors) { if (m.get() != this) { - BACKUPMON = m.get(); + BACKUPMON = m; break; } } // remove mirror if (pMirrorOf) { - pMirrorOf->mirrors.erase(std::find_if(pMirrorOf->mirrors.begin(), pMirrorOf->mirrors.end(), [&](const auto& other) { return other == this; })); + pMirrorOf->mirrors.erase(std::find_if(pMirrorOf->mirrors.begin(), pMirrorOf->mirrors.end(), [&](const auto& other) { return other == self; })); // unlock software for mirrored monitor - g_pPointerManager->unlockSoftwareForMonitor(pMirrorOf); - pMirrorOf = nullptr; + g_pPointerManager->unlockSoftwareForMonitor(pMirrorOf.lock()); + pMirrorOf.reset(); } if (!mirrors.empty()) { @@ -340,16 +340,16 @@ void CMonitor::onDisconnect(bool destroy) { if (!state.commit()) Debug::log(WARN, "state.commit() failed in CMonitor::onDisconnect"); - if (g_pCompositor->m_pLastMonitor.get() == this) - g_pCompositor->setActiveMonitor(BACKUPMON ? BACKUPMON : g_pCompositor->m_pUnsafeOutput); + if (g_pCompositor->m_pLastMonitor == self) + g_pCompositor->setActiveMonitor(BACKUPMON ? BACKUPMON : g_pCompositor->m_pUnsafeOutput.lock()); - if (g_pHyprRenderer->m_pMostHzMonitor == this) { - int mostHz = 0; - CMonitor* pMonitorMostHz = nullptr; + if (g_pHyprRenderer->m_pMostHzMonitor == self) { + int mostHz = 0; + PHLMONITOR pMonitorMostHz = nullptr; for (auto const& m : g_pCompositor->m_vMonitors) { - if (m->refreshRate > mostHz && m.get() != this) { - pMonitorMostHz = m.get(); + if (m->refreshRate > mostHz && m != self) { + pMonitorMostHz = m; mostHz = m->refreshRate; } } @@ -361,11 +361,11 @@ void CMonitor::onDisconnect(bool destroy) { void CMonitor::addDamage(const pixman_region32_t* rg) { static auto PZOOMFACTOR = CConfigValue("cursor:zoom_factor"); - if (*PZOOMFACTOR != 1.f && g_pCompositor->getMonitorFromCursor() == this) { + if (*PZOOMFACTOR != 1.f && g_pCompositor->getMonitorFromCursor() == self) { damage.damageEntire(); - g_pCompositor->scheduleFrameForMonitor(this, Aquamarine::IOutput::AQ_SCHEDULE_DAMAGE); + g_pCompositor->scheduleFrameForMonitor(self.lock(), Aquamarine::IOutput::AQ_SCHEDULE_DAMAGE); } else if (damage.damage(rg)) - g_pCompositor->scheduleFrameForMonitor(this, Aquamarine::IOutput::AQ_SCHEDULE_DAMAGE); + g_pCompositor->scheduleFrameForMonitor(self.lock(), Aquamarine::IOutput::AQ_SCHEDULE_DAMAGE); } void CMonitor::addDamage(const CRegion* rg) { @@ -374,13 +374,13 @@ void CMonitor::addDamage(const CRegion* rg) { void CMonitor::addDamage(const CBox* box) { static auto PZOOMFACTOR = CConfigValue("cursor:zoom_factor"); - if (*PZOOMFACTOR != 1.f && g_pCompositor->getMonitorFromCursor() == this) { + if (*PZOOMFACTOR != 1.f && g_pCompositor->getMonitorFromCursor() == self) { damage.damageEntire(); - g_pCompositor->scheduleFrameForMonitor(this, Aquamarine::IOutput::AQ_SCHEDULE_DAMAGE); + g_pCompositor->scheduleFrameForMonitor(self.lock(), Aquamarine::IOutput::AQ_SCHEDULE_DAMAGE); } if (damage.damage(*box)) - g_pCompositor->scheduleFrameForMonitor(this, Aquamarine::IOutput::AQ_SCHEDULE_DAMAGE); + g_pCompositor->scheduleFrameForMonitor(self.lock(), Aquamarine::IOutput::AQ_SCHEDULE_DAMAGE); } bool CMonitor::shouldSkipScheduleFrameOnMouseEvent() { @@ -456,7 +456,7 @@ void CMonitor::setupDefaultWS(const SMonitorRule& monitorRule) { if (PNEWWORKSPACE) { // workspace exists, move it to the newly connected monitor - g_pCompositor->moveWorkspaceToMonitor(PNEWWORKSPACE, this); + g_pCompositor->moveWorkspaceToMonitor(PNEWWORKSPACE, self.lock()); activeWorkspace = PNEWWORKSPACE; g_pLayoutManager->getCurrentLayout()->recalculateMonitor(ID); PNEWWORKSPACE->startAnim(true, true, true); @@ -485,7 +485,7 @@ void CMonitor::setMirror(const std::string& mirrorOf) { return; } - if (PMIRRORMON == this) { + if (PMIRRORMON == self) { Debug::log(ERR, "Cannot mirror self!"); return; } @@ -494,13 +494,13 @@ void CMonitor::setMirror(const std::string& mirrorOf) { // disable mirroring if (pMirrorOf) { - pMirrorOf->mirrors.erase(std::find_if(pMirrorOf->mirrors.begin(), pMirrorOf->mirrors.end(), [&](const auto& other) { return other == this; })); + pMirrorOf->mirrors.erase(std::find_if(pMirrorOf->mirrors.begin(), pMirrorOf->mirrors.end(), [&](const auto& other) { return other == self; })); // unlock software for mirrored monitor - g_pPointerManager->unlockSoftwareForMonitor(pMirrorOf); + g_pPointerManager->unlockSoftwareForMonitor(pMirrorOf.lock()); } - pMirrorOf = nullptr; + pMirrorOf.reset(); // set rule const auto RULE = g_pConfigManager->getMonitorRuleFor(self.lock()); @@ -528,12 +528,12 @@ void CMonitor::setMirror(const std::string& mirrorOf) { setupDefaultWS(RULE); - g_pHyprRenderer->applyMonitorRule(this, (SMonitorRule*)&RULE, true); // will apply the offset and stuff + g_pHyprRenderer->applyMonitorRule(self.lock(), (SMonitorRule*)&RULE, true); // will apply the offset and stuff } else { - CMonitor* BACKUPMON = nullptr; + PHLMONITOR BACKUPMON = nullptr; for (auto const& m : g_pCompositor->m_vMonitors) { if (m.get() != this) { - BACKUPMON = m.get(); + BACKUPMON = m; break; } } @@ -557,14 +557,14 @@ void CMonitor::setMirror(const std::string& mirrorOf) { pMirrorOf = PMIRRORMON; - pMirrorOf->mirrors.push_back(this); + pMirrorOf->mirrors.push_back(self); // remove from mvmonitors - std::erase_if(g_pCompositor->m_vMonitors, [&](const auto& other) { return other.get() == this; }); + std::erase_if(g_pCompositor->m_vMonitors, [&](const auto& other) { return other == self; }); g_pCompositor->arrangeMonitors(); - g_pCompositor->setActiveMonitor(g_pCompositor->m_vMonitors.front().get()); + g_pCompositor->setActiveMonitor(g_pCompositor->m_vMonitors.front()); g_pCompositor->sanityCheckWorkspaces(); @@ -654,11 +654,11 @@ void CMonitor::changeWorkspace(const PHLWORKSPACE& pWorkspace, bool internal, bo EMIT_HOOK_EVENT("workspace", pWorkspace); } - g_pHyprRenderer->damageMonitor(this); + g_pHyprRenderer->damageMonitor(self.lock()); g_pCompositor->updateFullscreenFadeOnWorkspace(pWorkspace); - g_pConfigManager->ensureVRR(this); + g_pConfigManager->ensureVRR(self.lock()); g_pCompositor->updateSuspendedStates(); @@ -674,7 +674,7 @@ void CMonitor::setSpecialWorkspace(const PHLWORKSPACE& pWorkspace) { if (activeSpecialWorkspace == pWorkspace) return; - g_pHyprRenderer->damageMonitor(this); + g_pHyprRenderer->damageMonitor(self.lock()); if (!pWorkspace) { // remove special if exists @@ -696,7 +696,7 @@ void CMonitor::setSpecialWorkspace(const PHLWORKSPACE& pWorkspace) { g_pCompositor->updateFullscreenFadeOnWorkspace(activeWorkspace); - g_pConfigManager->ensureVRR(this); + g_pConfigManager->ensureVRR(self.lock()); g_pCompositor->updateSuspendedStates(); @@ -764,11 +764,11 @@ void CMonitor::setSpecialWorkspace(const PHLWORKSPACE& pWorkspace) { g_pEventManager->postEvent(SHyprIPCEvent{"activespecial", pWorkspace->m_szName + "," + szName}); - g_pHyprRenderer->damageMonitor(this); + g_pHyprRenderer->damageMonitor(self.lock()); g_pCompositor->updateFullscreenFadeOnWorkspace(pWorkspace); - g_pConfigManager->ensureVRR(this); + g_pConfigManager->ensureVRR(self.lock()); g_pCompositor->updateSuspendedStates(); } @@ -824,7 +824,7 @@ void CMonitor::scheduleDone() { void CMonitor::setCTM(const Mat3x3& ctm_) { ctm = ctm_; ctmUpdated = true; - g_pCompositor->scheduleFrameForMonitor(this, Aquamarine::IOutput::scheduleFrameReason::AQ_SCHEDULE_NEEDS_FRAME); + g_pCompositor->scheduleFrameForMonitor(self.lock(), Aquamarine::IOutput::scheduleFrameReason::AQ_SCHEDULE_NEEDS_FRAME); } bool CMonitor::attemptDirectScanout() { @@ -963,7 +963,7 @@ void CMonitor::onMonitorFrame() { if (!m_bEnabled) return; - g_pHyprRenderer->recheckSolitaryForMonitor(this); + g_pHyprRenderer->recheckSolitaryForMonitor(self.lock()); tearingState.busy = false; @@ -984,12 +984,12 @@ void CMonitor::onMonitorFrame() { if (*PENABLERAT && !tearingState.nextRenderTorn) { if (!RATScheduled) { // render - g_pHyprRenderer->renderMonitor(this); + g_pHyprRenderer->renderMonitor(self.lock()); } RATScheduled = false; - const auto& [avg, max, min] = g_pHyprRenderer->getRenderTimes(this); + const auto& [avg, max, min] = g_pHyprRenderer->getRenderTimes(self.lock()); if (max + *PRATSAFE > 1000.0 / refreshRate) return; @@ -1002,11 +1002,11 @@ void CMonitor::onMonitorFrame() { const auto TIMETOSLEEP = std::floor(MSLEFT - ESTRENDERTIME); if (MSLEFT < 1 || MSLEFT < ESTRENDERTIME || TIMETOSLEEP < 1) - g_pHyprRenderer->renderMonitor(this); + g_pHyprRenderer->renderMonitor(self.lock()); else wl_event_source_timer_update(renderTimer, TIMETOSLEEP); } else - g_pHyprRenderer->renderMonitor(this); + g_pHyprRenderer->renderMonitor(self.lock()); } CMonitorState::CMonitorState(CMonitor* owner) { @@ -1040,7 +1040,7 @@ bool CMonitorState::commit() { if (!updateSwapchain()) return false; - EMIT_HOOK_EVENT("preMonitorCommit", m_pOwner); + EMIT_HOOK_EVENT("preMonitorCommit", m_pOwner->self.lock()); ensureBufferPresent(); diff --git a/src/helpers/Monitor.hpp b/src/helpers/Monitor.hpp index ceb90232..f3d6d647 100644 --- a/src/helpers/Monitor.hpp +++ b/src/helpers/Monitor.hpp @@ -54,7 +54,7 @@ class CMonitorState { private: void ensureBufferPresent(); - CMonitor* m_pOwner; + CMonitor* m_pOwner = nullptr; }; class CMonitor { @@ -128,8 +128,8 @@ class CMonitor { WP self; // mirroring - CMonitor* pMirrorOf = nullptr; - std::vector mirrors; + PHLMONITORREF pMirrorOf; + std::vector mirrors; // ctm Mat3x3 ctm = Mat3x3::identity(); diff --git a/src/helpers/WLClasses.hpp b/src/helpers/WLClasses.hpp index 51f90166..9f2836e7 100644 --- a/src/helpers/WLClasses.hpp +++ b/src/helpers/WLClasses.hpp @@ -18,9 +18,9 @@ class CWLSurfaceResource; AQUAMARINE_FORWARD(ISwitch); struct SRenderData { - CMonitor* pMonitor; - timespec* when; - double x, y; + PHLMONITORREF pMonitor; + timespec* when; + double x, y; // for iters void* data = nullptr; @@ -59,16 +59,16 @@ struct SRenderData { }; struct SSwipeGesture { - PHLWORKSPACE pWorkspaceBegin = nullptr; + PHLWORKSPACE pWorkspaceBegin = nullptr; - double delta = 0; + double delta = 0; - int initialDirection = 0; - float avgSpeed = 0; - int speedPoints = 0; - int touch_id = 0; + int initialDirection = 0; + float avgSpeed = 0; + int speedPoints = 0; + int touch_id = 0; - CMonitor* pMonitor = nullptr; + PHLMONITORREF pMonitor; }; struct SSwitchDevice { diff --git a/src/hyprerror/HyprError.cpp b/src/hyprerror/HyprError.cpp index 4044bcc9..4761346e 100644 --- a/src/hyprerror/HyprError.cpp +++ b/src/hyprerror/HyprError.cpp @@ -14,7 +14,7 @@ CHyprError::CHyprError() { if (!m_bIsCreated) return; - g_pHyprRenderer->damageMonitor(g_pCompositor->m_pLastMonitor.get()); + g_pHyprRenderer->damageMonitor(g_pCompositor->m_pLastMonitor.lock()); m_bMonitorChanged = true; }); @@ -47,7 +47,7 @@ void CHyprError::createQueued() { m_fFadeOpacity.setValueAndWarp(0.f); m_fFadeOpacity = 1.f; - const auto PMONITOR = g_pCompositor->m_vMonitors.front().get(); + const auto PMONITOR = g_pCompositor->m_vMonitors.front(); const auto SCALE = PMONITOR->scale; diff --git a/src/layout/DwindleLayout.cpp b/src/layout/DwindleLayout.cpp index 8a7426eb..0fa57143 100644 --- a/src/layout/DwindleLayout.cpp +++ b/src/layout/DwindleLayout.cpp @@ -101,18 +101,17 @@ void CHyprDwindleLayout::applyNodeDataToWindow(SDwindleNodeData* pNode, bool for if (pNode->isNode) return; - CMonitor* PMONITOR = nullptr; + PHLMONITOR PMONITOR = nullptr; if (g_pCompositor->isWorkspaceSpecial(pNode->workspaceID)) { for (auto const& m : g_pCompositor->m_vMonitors) { if (m->activeSpecialWorkspaceID() == pNode->workspaceID) { - PMONITOR = m.get(); + PMONITOR = m; break; } } - } else { + } else PMONITOR = g_pCompositor->getMonitorFromID(g_pCompositor->getWorkspaceByID(pNode->workspaceID)->m_iMonitorID); - } if (!PMONITOR) { Debug::log(ERR, "Orphaned Node {}!!", pNode); diff --git a/src/layout/MasterLayout.cpp b/src/layout/MasterLayout.cpp index f983770b..95b5afdf 100644 --- a/src/layout/MasterLayout.cpp +++ b/src/layout/MasterLayout.cpp @@ -594,18 +594,17 @@ void CHyprMasterLayout::calculateWorkspace(PHLWORKSPACE pWorkspace) { } void CHyprMasterLayout::applyNodeDataToWindow(SMasterNodeData* pNode) { - CMonitor* PMONITOR = nullptr; + PHLMONITOR PMONITOR = nullptr; if (g_pCompositor->isWorkspaceSpecial(pNode->workspaceID)) { for (auto const& m : g_pCompositor->m_vMonitors) { if (m->activeSpecialWorkspaceID() == pNode->workspaceID) { - PMONITOR = m.get(); + PMONITOR = m; break; } } - } else { + } else PMONITOR = g_pCompositor->getMonitorFromID(g_pCompositor->getWorkspaceByID(pNode->workspaceID)->m_iMonitorID); - } if (!PMONITOR) { Debug::log(ERR, "Orphaned Node {}!!", pNode); diff --git a/src/managers/AnimationManager.cpp b/src/managers/AnimationManager.cpp index 0ff94f1f..9ff7497d 100644 --- a/src/managers/AnimationManager.cpp +++ b/src/managers/AnimationManager.cpp @@ -85,7 +85,7 @@ void CAnimationManager::tick() { PHLWINDOW PWINDOW = av->m_pWindow.lock(); PHLWORKSPACE PWORKSPACE = av->m_pWorkspace.lock(); PHLLS PLAYER = av->m_pLayer.lock(); - CMonitor* PMONITOR = nullptr; + PHLMONITOR PMONITOR = nullptr; bool animationsDisabled = animGlobalDisabled; if (PWINDOW) { diff --git a/src/managers/CursorManager.cpp b/src/managers/CursorManager.cpp index 6f8292f7..34084a49 100644 --- a/src/managers/CursorManager.cpp +++ b/src/managers/CursorManager.cpp @@ -309,7 +309,7 @@ void CCursorManager::updateTheme() { for (auto const& m : g_pCompositor->m_vMonitors) { m->forceFullFrames = 5; - g_pCompositor->scheduleFrameForMonitor(m.get(), Aquamarine::IOutput::AQ_SCHEDULE_CURSOR_SHAPE); + g_pCompositor->scheduleFrameForMonitor(m, Aquamarine::IOutput::AQ_SCHEDULE_CURSOR_SHAPE); } } diff --git a/src/managers/KeybindManager.cpp b/src/managers/KeybindManager.cpp index d893e258..9c22fb93 100644 --- a/src/managers/KeybindManager.cpp +++ b/src/managers/KeybindManager.cpp @@ -271,11 +271,11 @@ void updateRelativeCursorCoords() { g_pCompositor->m_pLastWindow->m_vRelativeCursorCoordsOnLastWarp = g_pInputManager->getMouseCoordsInternal() - g_pCompositor->m_pLastWindow->m_vPosition; } -bool CKeybindManager::tryMoveFocusToMonitor(CMonitor* monitor) { +bool CKeybindManager::tryMoveFocusToMonitor(PHLMONITOR monitor) { if (!monitor) return false; - const auto LASTMONITOR = g_pCompositor->m_pLastMonitor.get(); + const auto LASTMONITOR = g_pCompositor->m_pLastMonitor.lock(); if (!LASTMONITOR) return false; if (LASTMONITOR == monitor) { @@ -1096,7 +1096,7 @@ SDispatchResult CKeybindManager::changeworkspace(std::string args) { static auto PALLOWWORKSPACECYCLES = CConfigValue("binds:allow_workspace_cycles"); static auto PWORKSPACECENTERON = CConfigValue("binds:workspace_center_on"); - const auto PMONITOR = g_pCompositor->m_pLastMonitor.get(); + const auto PMONITOR = g_pCompositor->m_pLastMonitor.lock(); if (!PMONITOR) return {.success = false, .error = "Last monitor not found"}; @@ -1260,7 +1260,7 @@ SDispatchResult CKeybindManager::moveActiveToWorkspace(std::string args) { } auto pWorkspace = g_pCompositor->getWorkspaceByID(WORKSPACEID); - CMonitor* pMonitor = nullptr; + PHLMONITOR pMonitor = nullptr; const auto POLDWS = PWINDOW->m_pWorkspace; static auto PALLOWWORKSPACECYCLES = CConfigValue("binds:allow_workspace_cycles"); @@ -1795,7 +1795,7 @@ SDispatchResult CKeybindManager::exitHyprland(std::string argz) { } SDispatchResult CKeybindManager::moveCurrentWorkspaceToMonitor(std::string args) { - CMonitor* PMONITOR = g_pCompositor->getMonitorFromString(args); + PHLMONITOR PMONITOR = g_pCompositor->getMonitorFromString(args); if (!PMONITOR) { Debug::log(ERR, "Ignoring moveCurrentWorkspaceToMonitor: monitor doesnt exist"); @@ -1854,7 +1854,7 @@ SDispatchResult CKeybindManager::focusWorkspaceOnCurrentMonitor(std::string args return {.success = false, .error = "focusWorkspaceOnCurrentMonitor invalid workspace!"}; } - const auto PCURRMONITOR = g_pCompositor->m_pLastMonitor.get(); + const auto PCURRMONITOR = g_pCompositor->m_pLastMonitor.lock(); if (!PCURRMONITOR) { Debug::log(ERR, "focusWorkspaceOnCurrentMonitor monitor doesn't exist!"); @@ -1944,7 +1944,7 @@ SDispatchResult CKeybindManager::forceRendererReload(std::string args) { continue; auto rule = g_pConfigManager->getMonitorRuleFor(m); - if (!g_pHyprRenderer->applyMonitorRule(m.get(), &rule, true)) { + if (!g_pHyprRenderer->applyMonitorRule(m, &rule, true)) { overAgain = true; break; } @@ -2427,7 +2427,7 @@ SDispatchResult CKeybindManager::dpms(std::string arg) { } if (enable) - g_pHyprRenderer->damageMonitor(m.get()); + g_pHyprRenderer->damageMonitor(m); m->events.dpmsChanged.emit(); } diff --git a/src/managers/KeybindManager.hpp b/src/managers/KeybindManager.hpp index c81ca86f..8981dcaf 100644 --- a/src/managers/KeybindManager.hpp +++ b/src/managers/KeybindManager.hpp @@ -146,7 +146,7 @@ class CKeybindManager { void updateXKBTranslationState(); bool ensureMouseBindState(); - static bool tryMoveFocusToMonitor(CMonitor* monitor); + static bool tryMoveFocusToMonitor(PHLMONITOR monitor); static void moveWindowOutOfGroup(PHLWINDOW pWindow, const std::string& dir = ""); static void moveWindowIntoGroup(PHLWINDOW pWindow, PHLWINDOW pWindowInDirection); static void switchToWindow(PHLWINDOW PWINDOWTOCHANGETO); diff --git a/src/managers/PointerManager.cpp b/src/managers/PointerManager.cpp index 8c2a1bad..ae90349b 100644 --- a/src/managers/PointerManager.cpp +++ b/src/managers/PointerManager.cpp @@ -14,7 +14,7 @@ CPointerManager::CPointerManager() { hooks.monitorAdded = g_pHookSystem->hookDynamic("monitorAdded", [this](void* self, SCallbackInfo& info, std::any data) { - auto PMONITOR = std::any_cast(data)->self.lock(); + auto PMONITOR = std::any_cast(data); onMonitorLayoutChange(); @@ -29,7 +29,7 @@ CPointerManager::CPointerManager() { }); hooks.monitorPreRender = g_pHookSystem->hookDynamic("preMonitorCommit", [this](void* self, SCallbackInfo& info, std::any data) { - auto state = stateFor(std::any_cast(data)->self.lock()); + auto state = stateFor(std::any_cast(data)); if (!state) return; @@ -51,16 +51,7 @@ void CPointerManager::unlockSoftwareAll() { updateCursorBackend(); } -void CPointerManager::lockSoftwareForMonitor(CMonitor* Monitor) { - for (auto const& m : g_pCompositor->m_vMonitors) { - if (m->ID == Monitor->ID) { - lockSoftwareForMonitor(m); - return; - } - } -} - -void CPointerManager::lockSoftwareForMonitor(SP mon) { +void CPointerManager::lockSoftwareForMonitor(PHLMONITOR mon) { auto state = stateFor(mon); state->softwareLocks++; @@ -68,16 +59,7 @@ void CPointerManager::lockSoftwareForMonitor(SP mon) { updateCursorBackend(); } -void CPointerManager::unlockSoftwareForMonitor(CMonitor* Monitor) { - for (auto const& m : g_pCompositor->m_vMonitors) { - if (m->ID == Monitor->ID) { - unlockSoftwareForMonitor(m); - return; - } - } -} - -void CPointerManager::unlockSoftwareForMonitor(SP mon) { +void CPointerManager::unlockSoftwareForMonitor(PHLMONITOR mon) { auto state = stateFor(mon); state->softwareLocks--; if (state->softwareLocks < 0) @@ -387,7 +369,7 @@ bool CPointerManager::setHWCursorBuffer(SP state, SPcursorFrontBuffer = buf; if (!state->monitor->shouldSkipScheduleFrameOnMouseEvent()) - g_pCompositor->scheduleFrameForMonitor(state->monitor.get(), Aquamarine::IOutput::AQ_SCHEDULE_CURSOR_SHAPE); + g_pCompositor->scheduleFrameForMonitor(state->monitor.lock(), Aquamarine::IOutput::AQ_SCHEDULE_CURSOR_SHAPE); return true; } @@ -446,7 +428,7 @@ SP CPointerManager::renderHWCursorBuffer(SPmakeEGLCurrent(); - g_pHyprOpenGL->m_RenderData.pMonitor = state->monitor.get(); + g_pHyprOpenGL->m_RenderData.pMonitor = state->monitor; auto RBO = g_pHyprRenderer->getOrCreateRenderbuffer(buf, state->monitor->cursorSwapchain->currentOptions().format); if (!RBO) { @@ -503,7 +485,7 @@ SP CPointerManager::renderHWCursorBuffer(SPbind(); - g_pHyprOpenGL->beginSimple(state->monitor.get(), damage, RBO); + g_pHyprOpenGL->beginSimple(state->monitor.lock(), damage, RBO); g_pHyprOpenGL->clear(CColor{0.F, 0.F, 0.F, 0.F}); CBox xbox = {{}, Vector2D{currentCursorImage.size / currentCursorImage.scale * state->monitor->scale}.round()}; @@ -514,7 +496,7 @@ SP CPointerManager::renderHWCursorBuffer(SPend(); glFlush(); - g_pHyprOpenGL->m_RenderData.pMonitor = nullptr; + g_pHyprOpenGL->m_RenderData.pMonitor.reset(); g_pHyprRenderer->onRenderbufferDestroy(RBO.get()); diff --git a/src/managers/PointerManager.hpp b/src/managers/PointerManager.hpp index 6b89eb16..aef2490d 100644 --- a/src/managers/PointerManager.hpp +++ b/src/managers/PointerManager.hpp @@ -45,8 +45,6 @@ class CPointerManager { void lockSoftwareForMonitor(SP pMonitor); void unlockSoftwareForMonitor(SP pMonitor); - void lockSoftwareForMonitor(CMonitor* pMonitor); - void unlockSoftwareForMonitor(CMonitor* pMonitor); void lockSoftwareAll(); void unlockSoftwareAll(); bool softwareLockedFor(SP pMonitor); diff --git a/src/managers/ProtocolManager.cpp b/src/managers/ProtocolManager.cpp index 25a34657..601e564d 100644 --- a/src/managers/ProtocolManager.cpp +++ b/src/managers/ProtocolManager.cpp @@ -62,7 +62,7 @@ #include #include -void CProtocolManager::onMonitorModeChange(CMonitor* pMonitor) { +void CProtocolManager::onMonitorModeChange(PHLMONITOR pMonitor) { const bool ISMIRROR = pMonitor->isMirror(); // onModeChanged we check if the current mirror status matches the global. @@ -84,7 +84,7 @@ CProtocolManager::CProtocolManager() { // Outputs are a bit dumb, we have to agree. static auto P = g_pHookSystem->hookDynamic("monitorAdded", [this](void* self, SCallbackInfo& info, std::any param) { - auto M = std::any_cast(param); + auto M = std::any_cast(param); // ignore mirrored outputs. I don't think this will ever be hit as mirrors are applied after // this event is emitted iirc. @@ -103,7 +103,7 @@ CProtocolManager::CProtocolManager() { }); static auto P2 = g_pHookSystem->hookDynamic("monitorRemoved", [this](void* self, SCallbackInfo& info, std::any param) { - auto M = std::any_cast(param); + auto M = std::any_cast(param); if (!PROTO::outputs.contains(M->szName)) return; PROTO::outputs.at(M->szName)->remove(); diff --git a/src/managers/ProtocolManager.hpp b/src/managers/ProtocolManager.hpp index d5629e9e..69dadd0f 100644 --- a/src/managers/ProtocolManager.hpp +++ b/src/managers/ProtocolManager.hpp @@ -16,7 +16,7 @@ class CProtocolManager { private: std::unordered_map m_mModeChangeListeners; - void onMonitorModeChange(CMonitor* pMonitor); + void onMonitorModeChange(PHLMONITOR pMonitor); }; inline std::unique_ptr g_pProtocolManager; diff --git a/src/managers/SessionLockManager.cpp b/src/managers/SessionLockManager.cpp index 4e05695a..1b28cc27 100644 --- a/src/managers/SessionLockManager.cpp +++ b/src/managers/SessionLockManager.cpp @@ -73,7 +73,7 @@ void CSessionLockManager::onNewSessionLock(SP pLock) { g_pInputManager->refocus(); for (auto const& m : g_pCompositor->m_vMonitors) - g_pHyprRenderer->damageMonitor(m.get()); + g_pHyprRenderer->damageMonitor(m); }); m_pSessionLock->listeners.destroy = pLock->events.destroyed.registerListener([this](std::any data) { @@ -81,7 +81,7 @@ void CSessionLockManager::onNewSessionLock(SP pLock) { g_pCompositor->focusSurface(nullptr); for (auto const& m : g_pCompositor->m_vMonitors) - g_pHyprRenderer->damageMonitor(m.get()); + g_pHyprRenderer->damageMonitor(m); }); g_pCompositor->focusSurface(nullptr); diff --git a/src/managers/XWaylandManager.cpp b/src/managers/XWaylandManager.cpp index 8b63d37e..7b3081a2 100644 --- a/src/managers/XWaylandManager.cpp +++ b/src/managers/XWaylandManager.cpp @@ -247,7 +247,7 @@ Vector2D CHyprXWaylandManager::xwaylandToWaylandCoords(const Vector2D& coord) { static auto PXWLFORCESCALEZERO = CConfigValue("xwayland:force_zero_scaling"); - CMonitor* pMonitor = nullptr; + PHLMONITOR pMonitor = nullptr; double bestDistance = __FLT_MAX__; for (const auto& m : g_pCompositor->m_vMonitors) { const auto SIZ = *PXWLFORCESCALEZERO ? m->vecTransformedSize : m->vecSize; @@ -257,7 +257,7 @@ Vector2D CHyprXWaylandManager::xwaylandToWaylandCoords(const Vector2D& coord) { if (distance < bestDistance) { bestDistance = distance; - pMonitor = m.get(); + pMonitor = m; } } diff --git a/src/managers/input/InputManager.cpp b/src/managers/input/InputManager.cpp index eef5e040..196f0b71 100644 --- a/src/managers/input/InputManager.cpp +++ b/src/managers/input/InputManager.cpp @@ -172,7 +172,7 @@ void CInputManager::mouseMoveUnified(uint32_t time, bool refocus) { m_vLastCursorPosFloored = MOUSECOORDSFLOORED; - const auto PMONITOR = isLocked() && g_pCompositor->m_pLastMonitor ? g_pCompositor->m_pLastMonitor.get() : g_pCompositor->getMonitorFromCursor(); + const auto PMONITOR = isLocked() && g_pCompositor->m_pLastMonitor ? g_pCompositor->m_pLastMonitor.lock() : g_pCompositor->getMonitorFromCursor(); // this can happen if there are no displays hooked up to Hyprland if (PMONITOR == nullptr) @@ -212,7 +212,7 @@ void CInputManager::mouseMoveUnified(uint32_t time, bool refocus) { Debug::log(ERR, "BUG THIS: Null SURF/CONSTRAINT in mouse refocus. Ignoring constraints. {:x} {:x}", (uintptr_t)SURF.get(), (uintptr_t)CONSTRAINT.get()); } - if (PMONITOR != g_pCompositor->m_pLastMonitor.get() && (*PMOUSEFOCUSMON || refocus) && m_pForcedFocus.expired()) + if (PMONITOR != g_pCompositor->m_pLastMonitor && (*PMOUSEFOCUSMON || refocus) && m_pForcedFocus.expired()) g_pCompositor->setActiveMonitor(PMONITOR); if (g_pSessionLockManager->isSessionLocked()) { @@ -370,7 +370,7 @@ void CInputManager::mouseMoveUnified(uint32_t time, bool refocus) { g_pCompositor->vectorToLayerSurface(mouseCoords, &PMONITOR->m_aLayerSurfaceLayers[ZWLR_LAYER_SHELL_V1_LAYER_BACKGROUND], &surfaceCoords, &pFoundLayerSurface); if (g_pPointerManager->softwareLockedFor(PMONITOR->self.lock()) > 0 && !skipFrameSchedule) - g_pCompositor->scheduleFrameForMonitor(g_pCompositor->m_pLastMonitor.get(), Aquamarine::IOutput::AQ_SCHEDULE_CURSOR_MOVE); + g_pCompositor->scheduleFrameForMonitor(g_pCompositor->m_pLastMonitor.lock(), Aquamarine::IOutput::AQ_SCHEDULE_CURSOR_MOVE); // grabs if (g_pSeatManager->seatGrab && !g_pSeatManager->seatGrab->accepts(foundSurface)) { @@ -720,7 +720,7 @@ void CInputManager::processMouseDownNormal(const IPointer::SButtonEvent& e) { // notify app if we didnt handle it g_pSeatManager->sendPointerButton(e.timeMs, e.button, e.state); - if (const auto PMON = g_pCompositor->getMonitorFromVector(mouseCoords); PMON != g_pCompositor->m_pLastMonitor.get() && PMON) + if (const auto PMON = g_pCompositor->getMonitorFromVector(mouseCoords); PMON != g_pCompositor->m_pLastMonitor && PMON) g_pCompositor->setActiveMonitor(PMON); if (g_pSeatManager->seatGrab && e.state == WL_POINTER_BUTTON_STATE_PRESSED) { @@ -1359,7 +1359,7 @@ void CInputManager::refocus() { mouseMoveUnified(0, true); } -void CInputManager::refocusLastWindow(CMonitor* pMonitor) { +void CInputManager::refocusLastWindow(PHLMONITOR pMonitor) { if (!pMonitor) { refocus(); return; diff --git a/src/managers/input/InputManager.hpp b/src/managers/input/InputManager.hpp index d5634796..10faff24 100644 --- a/src/managers/input/InputManager.hpp +++ b/src/managers/input/InputManager.hpp @@ -112,7 +112,7 @@ class CInputManager { Vector2D getMouseCoordsInternal(); void refocus(); - void refocusLastWindow(CMonitor* pMonitor); + void refocusLastWindow(PHLMONITOR pMonitor); void simulateMouseMovement(); void sendMotionEventsToFocused(); diff --git a/src/managers/input/InputMethodPopup.cpp b/src/managers/input/InputMethodPopup.cpp index cf48f2a5..ffb4edcc 100644 --- a/src/managers/input/InputMethodPopup.cpp +++ b/src/managers/input/InputMethodPopup.cpp @@ -100,11 +100,11 @@ void CInputPopup::updateBox() { cursorBoxParent = {0, 0, (int)parentBox.w, (int)parentBox.h}; } - Vector2D currentPopupSize = surface->getViewporterCorrectedSize() / surface->resource()->current.scale; + Vector2D currentPopupSize = surface->getViewporterCorrectedSize() / surface->resource()->current.scale; - CMonitor* pMonitor = g_pCompositor->getMonitorFromVector(parentBox.middle()); + PHLMONITOR pMonitor = g_pCompositor->getMonitorFromVector(parentBox.middle()); - Vector2D popupOffset(0, 0); + Vector2D popupOffset(0, 0); if (parentBox.y + cursorBoxParent.y + cursorBoxParent.height + currentPopupSize.y > pMonitor->vecPosition.y + pMonitor->vecSize.y) popupOffset.y -= currentPopupSize.y; diff --git a/src/managers/input/Swipe.cpp b/src/managers/input/Swipe.cpp index aa1d3274..8f95c6c6 100644 --- a/src/managers/input/Swipe.cpp +++ b/src/managers/input/Swipe.cpp @@ -33,7 +33,7 @@ void CInputManager::beginWorkspaceSwipe() { m_sActiveSwipe.pWorkspaceBegin = PWORKSPACE; m_sActiveSwipe.delta = 0; - m_sActiveSwipe.pMonitor = g_pCompositor->m_pLastMonitor.get(); + m_sActiveSwipe.pMonitor = g_pCompositor->m_pLastMonitor; m_sActiveSwipe.avgSpeed = 0; m_sActiveSwipe.speedPoints = 0; @@ -179,7 +179,7 @@ void CInputManager::endWorkspaceSwipe() { } m_sActiveSwipe.pWorkspaceBegin->rememberPrevWorkspace(pSwitchedTo); - g_pHyprRenderer->damageMonitor(m_sActiveSwipe.pMonitor); + g_pHyprRenderer->damageMonitor(m_sActiveSwipe.pMonitor.lock()); if (PWORKSPACEL) PWORKSPACEL->m_bForceRendering = false; @@ -264,7 +264,7 @@ void CInputManager::updateWorkspaceSwipe(double delta) { if (workspaceIDLeft > m_sActiveSwipe.pWorkspaceBegin->m_iID || !PWORKSPACE) { if (*PSWIPENEW) { - g_pHyprRenderer->damageMonitor(m_sActiveSwipe.pMonitor); + g_pHyprRenderer->damageMonitor(m_sActiveSwipe.pMonitor.lock()); if (VERTANIMS) m_sActiveSwipe.pWorkspaceBegin->m_vRenderOffset.setValueAndWarp(Vector2D(0.0, ((-m_sActiveSwipe.delta) / SWIPEDISTANCE) * YDISTANCE)); @@ -304,7 +304,7 @@ void CInputManager::updateWorkspaceSwipe(double delta) { if (workspaceIDRight < m_sActiveSwipe.pWorkspaceBegin->m_iID || !PWORKSPACE) { if (*PSWIPENEW) { - g_pHyprRenderer->damageMonitor(m_sActiveSwipe.pMonitor); + g_pHyprRenderer->damageMonitor(m_sActiveSwipe.pMonitor.lock()); if (VERTANIMS) m_sActiveSwipe.pWorkspaceBegin->m_vRenderOffset.setValueAndWarp(Vector2D(0.0, ((-m_sActiveSwipe.delta) / SWIPEDISTANCE) * YDISTANCE)); @@ -341,7 +341,7 @@ void CInputManager::updateWorkspaceSwipe(double delta) { g_pCompositor->updateWorkspaceWindowDecos(workspaceIDRight); } - g_pHyprRenderer->damageMonitor(m_sActiveSwipe.pMonitor); + g_pHyprRenderer->damageMonitor(m_sActiveSwipe.pMonitor.lock()); g_pCompositor->updateWorkspaceWindowDecos(m_sActiveSwipe.pWorkspaceBegin->m_iID); diff --git a/src/managers/input/Touch.cpp b/src/managers/input/Touch.cpp index 0333648a..454391af 100644 --- a/src/managers/input/Touch.cpp +++ b/src/managers/input/Touch.cpp @@ -18,7 +18,7 @@ void CInputManager::onTouchDown(ITouch::SDownEvent e) { auto PMONITOR = g_pCompositor->getMonitorFromName(!e.device->boundOutput.empty() ? e.device->boundOutput : ""); - PMONITOR = PMONITOR ? PMONITOR : g_pCompositor->m_pLastMonitor.get(); + PMONITOR = PMONITOR ? PMONITOR : g_pCompositor->m_pLastMonitor.lock(); g_pCompositor->warpCursorTo({PMONITOR->vecPosition.x + e.pos.x * PMONITOR->vecSize.x, PMONITOR->vecPosition.y + e.pos.y * PMONITOR->vecSize.y}, true); diff --git a/src/protocols/ForeignToplevelWlr.cpp b/src/protocols/ForeignToplevelWlr.cpp index 1163a5e7..ffc335c9 100644 --- a/src/protocols/ForeignToplevelWlr.cpp +++ b/src/protocols/ForeignToplevelWlr.cpp @@ -44,7 +44,7 @@ CForeignToplevelHandleWlr::CForeignToplevelHandleWlr(SPm_pWorkspace != monitor->activeWorkspace) { g_pCompositor->moveWindowToWorkspaceSafe(PWINDOW, monitor->activeWorkspace); - g_pCompositor->setActiveMonitor(monitor.get()); + g_pCompositor->setActiveMonitor(monitor); } } } @@ -116,7 +116,7 @@ wl_resource* CForeignToplevelHandleWlr::res() { return resource->resource(); } -void CForeignToplevelHandleWlr::sendMonitor(CMonitor* pMonitor) { +void CForeignToplevelHandleWlr::sendMonitor(PHLMONITOR pMonitor) { if (lastMonitorID == pMonitor->ID) return; diff --git a/src/protocols/ForeignToplevelWlr.hpp b/src/protocols/ForeignToplevelWlr.hpp index e726707d..880b7a14 100644 --- a/src/protocols/ForeignToplevelWlr.hpp +++ b/src/protocols/ForeignToplevelWlr.hpp @@ -22,7 +22,7 @@ class CForeignToplevelHandleWlr { bool closed = false; MONITORID lastMonitorID = MONITOR_INVALID; - void sendMonitor(CMonitor* pMonitor); + void sendMonitor(PHLMONITOR pMonitor); void sendState(); friend class CForeignToplevelWlrManager; diff --git a/src/protocols/GammaControl.cpp b/src/protocols/GammaControl.cpp index e794e543..14c6596f 100644 --- a/src/protocols/GammaControl.cpp +++ b/src/protocols/GammaControl.cpp @@ -143,11 +143,11 @@ void CGammaControl::applyToMonitor() { pMonitor->output->state->setGammaLut({}); } - g_pHyprRenderer->damageMonitor(pMonitor.get()); + g_pHyprRenderer->damageMonitor(pMonitor.lock()); } -CMonitor* CGammaControl::getMonitor() { - return pMonitor ? pMonitor.get() : nullptr; +PHLMONITOR CGammaControl::getMonitor() { + return pMonitor ? pMonitor.lock() : nullptr; } void CGammaControl::onMonitorDestroy() { @@ -186,7 +186,7 @@ void CGammaControlProtocol::onGetGammaControl(CZwlrGammaControlManagerV1* pMgr, } } -void CGammaControlProtocol::applyGammaToState(CMonitor* pMonitor) { +void CGammaControlProtocol::applyGammaToState(PHLMONITOR pMonitor) { for (auto const& g : m_vGammaControllers) { if (g->getMonitor() != pMonitor) continue; diff --git a/src/protocols/GammaControl.hpp b/src/protocols/GammaControl.hpp index bbdc0139..5cfcd60a 100644 --- a/src/protocols/GammaControl.hpp +++ b/src/protocols/GammaControl.hpp @@ -14,13 +14,13 @@ class CGammaControl { CGammaControl(SP resource_, wl_resource* output); ~CGammaControl(); - bool good(); - void applyToMonitor(); - CMonitor* getMonitor(); + bool good(); + void applyToMonitor(); + PHLMONITOR getMonitor(); private: SP resource; - WP pMonitor; + PHLMONITORREF pMonitor; size_t gammaSize = 0; bool gammaTableSet = false; std::vector gammaTable; // [r,g,b]+ @@ -39,7 +39,7 @@ class CGammaControlProtocol : public IWaylandProtocol { virtual void bindManager(wl_client* client, void* data, uint32_t ver, uint32_t id); - void applyGammaToState(CMonitor* pMonitor); + void applyGammaToState(PHLMONITOR pMonitor); private: void onManagerResourceDestroy(wl_resource* res); diff --git a/src/protocols/LayerShell.cpp b/src/protocols/LayerShell.cpp index c02d23f3..5ceae5f2 100644 --- a/src/protocols/LayerShell.cpp +++ b/src/protocols/LayerShell.cpp @@ -14,8 +14,8 @@ void CLayerShellResource::SState::reset() { margin = {0, 0, 0, 0}; } -CLayerShellResource::CLayerShellResource(SP resource_, SP surf_, std::string namespace_, CMonitor* pMonitor, zwlrLayerShellV1Layer layer) : - layerNamespace(namespace_), surface(surf_), resource(resource_) { +CLayerShellResource::CLayerShellResource(SP resource_, SP surf_, std::string namespace_, PHLMONITOR pMonitor, + zwlrLayerShellV1Layer layer) : layerNamespace(namespace_), surface(surf_), resource(resource_) { if (!good()) return; @@ -218,7 +218,7 @@ void CLayerShellProtocol::destroyResource(CLayerShellResource* surf) { void CLayerShellProtocol::onGetLayerSurface(CZwlrLayerShellV1* pMgr, uint32_t id, wl_resource* surface, wl_resource* output, zwlrLayerShellV1Layer layer, std::string namespace_) { const auto CLIENT = pMgr->client(); - const auto PMONITOR = output ? CWLOutputResource::fromResource(output)->monitor.get() : nullptr; + const auto PMONITOR = output ? CWLOutputResource::fromResource(output)->monitor.lock() : nullptr; auto SURF = CWLSurfaceResource::fromResource(surface); if (!SURF) { diff --git a/src/protocols/LayerShell.hpp b/src/protocols/LayerShell.hpp index 801bdfd6..ad6c1a75 100644 --- a/src/protocols/LayerShell.hpp +++ b/src/protocols/LayerShell.hpp @@ -26,7 +26,7 @@ class CLayerShellRole : public ISurfaceRole { }; class CLayerShellResource { public: - CLayerShellResource(SP resource_, SP surf_, std::string namespace_, CMonitor* pMonitor, zwlrLayerShellV1Layer layer); + CLayerShellResource(SP resource_, SP surf_, std::string namespace_, PHLMONITOR pMonitor, zwlrLayerShellV1Layer layer); ~CLayerShellResource(); bool good(); diff --git a/src/protocols/LinuxDMABUF.cpp b/src/protocols/LinuxDMABUF.cpp index d9dd1d01..8e26c74f 100644 --- a/src/protocols/LinuxDMABUF.cpp +++ b/src/protocols/LinuxDMABUF.cpp @@ -452,7 +452,7 @@ CLinuxDMABufV1Protocol::CLinuxDMABufV1Protocol(const wl_interface* iface, const } static auto monitorAdded = g_pHookSystem->hookDynamic("monitorAdded", [this](void* self, SCallbackInfo& info, std::any param) { - auto pMonitor = std::any_cast(param); + auto pMonitor = std::any_cast(param); auto mon = pMonitor->self.lock(); auto tranche = SDMABUFTranche{ .device = mainDevice, @@ -464,7 +464,7 @@ CLinuxDMABufV1Protocol::CLinuxDMABufV1Protocol(const wl_interface* iface, const }); static auto monitorRemoved = g_pHookSystem->hookDynamic("monitorRemoved", [this](void* self, SCallbackInfo& info, std::any param) { - auto pMonitor = std::any_cast(param); + auto pMonitor = std::any_cast(param); auto mon = pMonitor->self.lock(); std::erase_if(formatTable->monitorTranches, [mon](std::pair, SDMABUFTranche> pair) { return pair.first == mon; }); resetFormatTable(); diff --git a/src/protocols/OutputManagement.cpp b/src/protocols/OutputManagement.cpp index 3fd0cf6c..77cedd41 100644 --- a/src/protocols/OutputManagement.cpp +++ b/src/protocols/OutputManagement.cpp @@ -29,12 +29,12 @@ COutputManager::COutputManager(SP resource_) : resource(re // send all heads at start for (auto const& m : g_pCompositor->m_vRealMonitors) { - if (m.get() == g_pCompositor->m_pUnsafeOutput) + if (m == g_pCompositor->m_pUnsafeOutput) continue; LOGM(LOG, " | sending output head for {}", m->szName); - makeAndSendNewHead(m.get()); + makeAndSendNewHead(m); } sendDone(); @@ -44,7 +44,7 @@ bool COutputManager::good() { return resource->resource(); } -void COutputManager::makeAndSendNewHead(CMonitor* pMonitor) { +void COutputManager::makeAndSendNewHead(PHLMONITOR pMonitor) { if (stopped) return; @@ -63,7 +63,7 @@ void COutputManager::makeAndSendNewHead(CMonitor* pMonitor) { RESOURCE->sendAllData(); } -void COutputManager::ensureMonitorSent(CMonitor* pMonitor) { +void COutputManager::ensureMonitorSent(PHLMONITOR pMonitor) { if (pMonitor == g_pCompositor->m_pUnsafeOutput) return; @@ -86,7 +86,7 @@ void COutputManager::sendDone() { resource->sendDone(wl_display_next_serial(g_pCompositor->m_sWLDisplay)); } -COutputHead::COutputHead(SP resource_, CMonitor* pMonitor_) : resource(resource_), pMonitor(pMonitor_) { +COutputHead::COutputHead(SP resource_, PHLMONITOR pMonitor_) : resource(resource_), pMonitor(pMonitor_) { if (!good()) return; @@ -105,7 +105,7 @@ COutputHead::COutputHead(SP resource_, CMonitor* pMonitor_) : m->resource->sendFinished(); } - pMonitor = nullptr; + pMonitor.reset(); for (auto const& m : PROTO::outputManagement->m_vManagers) { m->sendDone(); } @@ -221,8 +221,8 @@ void COutputHead::makeAndSendNewMode(SP mode) { RESOURCE->sendAllData(); } -CMonitor* COutputHead::monitor() { - return pMonitor; +PHLMONITOR COutputHead::monitor() { + return pMonitor.lock(); } COutputMode::COutputMode(SP resource_, SP mode_) : resource(resource_), mode(mode_) { @@ -424,14 +424,12 @@ bool COutputConfiguration::applyTestConfiguration(bool test) { return true; } -COutputConfigurationHead::COutputConfigurationHead(SP resource_, CMonitor* pMonitor_) : resource(resource_), pMonitor(pMonitor_) { +COutputConfigurationHead::COutputConfigurationHead(SP resource_, PHLMONITOR pMonitor_) : resource(resource_), pMonitor(pMonitor_) { if (!good()) return; resource->setOnDestroy([this](CZwlrOutputConfigurationHeadV1* r) { PROTO::outputManagement->destroyResource(this); }); - listeners.monitorDestroy = pMonitor->events.destroy.registerListener([this](std::any d) { pMonitor = nullptr; }); - resource->setSetMode([this](CZwlrOutputConfigurationHeadV1* r, wl_resource* outputMode) { const auto MODE = PROTO::outputManagement->modeFromResource(outputMode); @@ -612,7 +610,7 @@ void COutputManagementProtocol::destroyResource(COutputConfigurationHead* resour void COutputManagementProtocol::updateAllOutputs() { for (auto const& m : g_pCompositor->m_vRealMonitors) { for (auto const& mgr : m_vManagers) { - mgr->ensureMonitorSent(m.get()); + mgr->ensureMonitorSent(m); } } } diff --git a/src/protocols/OutputManagement.hpp b/src/protocols/OutputManagement.hpp index f4a84475..6deab017 100644 --- a/src/protocols/OutputManagement.hpp +++ b/src/protocols/OutputManagement.hpp @@ -56,7 +56,7 @@ class COutputManager { COutputManager(SP resource_); bool good(); - void ensureMonitorSent(CMonitor* pMonitor); + void ensureMonitorSent(PHLMONITOR pMonitor); void sendDone(); // holds the states for this manager. @@ -70,7 +70,7 @@ class COutputManager { std::vector> heads; - void makeAndSendNewHead(CMonitor* pMonitor); + void makeAndSendNewHead(PHLMONITOR pMonitor); friend class COutputManagementProtocol; }; @@ -92,16 +92,16 @@ class COutputMode { class COutputHead { public: - COutputHead(SP resource_, CMonitor* pMonitor_); + COutputHead(SP resource_, PHLMONITOR pMonitor_); - bool good(); - void sendAllData(); // this has to be separate as we need to send the head first, then set the data - void updateMode(); - CMonitor* monitor(); + bool good(); + void sendAllData(); // this has to be separate as we need to send the head first, then set the data + void updateMode(); + PHLMONITOR monitor(); private: SP resource; - CMonitor* pMonitor = nullptr; + PHLMONITORREF pMonitor; void makeAndSendNewMode(SP mode); void sendCurrentMode(); @@ -119,7 +119,7 @@ class COutputHead { class COutputConfigurationHead { public: - COutputConfigurationHead(SP resource_, CMonitor* pMonitor_); + COutputConfigurationHead(SP resource_, PHLMONITOR pMonitor_); bool good(); @@ -127,11 +127,7 @@ class COutputConfigurationHead { private: SP resource; - CMonitor* pMonitor = nullptr; - - struct { - CHyprSignalListener monitorDestroy; - } listeners; + PHLMONITORREF pMonitor; friend class COutputConfiguration; }; diff --git a/src/protocols/OutputPower.cpp b/src/protocols/OutputPower.cpp index 0c324bf0..257155e4 100644 --- a/src/protocols/OutputPower.cpp +++ b/src/protocols/OutputPower.cpp @@ -2,7 +2,7 @@ #include "../Compositor.hpp" #include "core/Output.hpp" -COutputPower::COutputPower(SP resource_, CMonitor* pMonitor_) : resource(resource_), pMonitor(pMonitor_) { +COutputPower::COutputPower(SP resource_, PHLMONITOR pMonitor_) : resource(resource_), pMonitor(pMonitor_) { if (!resource->resource()) return; @@ -24,7 +24,7 @@ COutputPower::COutputPower(SP resource_, CMonitor* pMonitor_ resource->sendMode(pMonitor->dpmsStatus ? ZWLR_OUTPUT_POWER_V1_MODE_ON : ZWLR_OUTPUT_POWER_V1_MODE_OFF); listeners.monitorDestroy = pMonitor->events.destroy.registerListener([this](std::any v) { - pMonitor = nullptr; + pMonitor.reset(); resource->sendFailed(); }); @@ -68,7 +68,7 @@ void COutputPowerProtocol::onGetOutputPower(CZwlrOutputPowerManagerV1* pMgr, uin } const auto CLIENT = pMgr->client(); - const auto RESOURCE = m_vOutputPowers.emplace_back(std::make_unique(makeShared(CLIENT, pMgr->version(), id), OUTPUT->monitor.get())).get(); + const auto RESOURCE = m_vOutputPowers.emplace_back(std::make_unique(makeShared(CLIENT, pMgr->version(), id), OUTPUT->monitor.lock())).get(); if (!RESOURCE->good()) { pMgr->noMemory(); diff --git a/src/protocols/OutputPower.hpp b/src/protocols/OutputPower.hpp index 410742ca..91f2c5f3 100644 --- a/src/protocols/OutputPower.hpp +++ b/src/protocols/OutputPower.hpp @@ -11,14 +11,14 @@ class CMonitor; class COutputPower { public: - COutputPower(SP resource_, CMonitor* pMonitor); + COutputPower(SP resource_, PHLMONITOR pMonitor); bool good(); private: SP resource; - CMonitor* pMonitor = nullptr; + PHLMONITORREF pMonitor; struct { CHyprSignalListener monitorDestroy; diff --git a/src/protocols/PresentationTime.cpp b/src/protocols/PresentationTime.cpp index 71f74cd5..b66694bf 100644 --- a/src/protocols/PresentationTime.cpp +++ b/src/protocols/PresentationTime.cpp @@ -73,8 +73,8 @@ void CPresentationFeedback::sendQueued(SP data, timespe CPresentationProtocol::CPresentationProtocol(const wl_interface* iface, const int& ver, const std::string& name) : IWaylandProtocol(iface, ver, name) { static auto P = g_pHookSystem->hookDynamic("monitorRemoved", [this](void* self, SCallbackInfo& info, std::any param) { - const auto PMONITOR = std::any_cast(param); - std::erase_if(m_vQueue, [PMONITOR](const auto& other) { return !other->surface || other->pMonitor.get() == PMONITOR; }); + const auto PMONITOR = std::any_cast(param); + std::erase_if(m_vQueue, [PMONITOR](const auto& other) { return !other->surface || other->pMonitor == PMONITOR; }); }); } diff --git a/src/protocols/Screencopy.cpp b/src/protocols/Screencopy.cpp index 1b06a1fa..780c081d 100644 --- a/src/protocols/Screencopy.cpp +++ b/src/protocols/Screencopy.cpp @@ -19,7 +19,7 @@ CScreencopyFrame::CScreencopyFrame(SP resource_, int32_t return; overlayCursor = !!overlay_cursor; - pMonitor = CWLOutputResource::fromResource(output)->monitor.get(); + pMonitor = CWLOutputResource::fromResource(output)->monitor; if (!pMonitor) { LOGM(ERR, "Client requested sharing of a monitor that doesnt exist"); @@ -38,7 +38,7 @@ CScreencopyFrame::CScreencopyFrame(SP resource_, int32_t g_pHyprRenderer->makeEGLCurrent(); - shmFormat = g_pHyprOpenGL->getPreferredReadFormat(pMonitor); + shmFormat = g_pHyprOpenGL->getPreferredReadFormat(pMonitor.lock()); if (shmFormat == DRM_FORMAT_INVALID) { LOGM(ERR, "No format supported by renderer in capture output"); resource->sendFailed(); @@ -87,7 +87,7 @@ void CScreencopyFrame::copy(CZwlrScreencopyFrameV1* pFrame, wl_resource* buffer_ return; } - if (!g_pCompositor->monitorExists(pMonitor)) { + if (!g_pCompositor->monitorExists(pMonitor.lock())) { LOGM(ERR, "Client requested sharing of a monitor that is gone"); resource->sendFailed(); PROTO::screencopy->destroyResource(this); @@ -165,7 +165,7 @@ void CScreencopyFrame::copy(CZwlrScreencopyFrameV1* pFrame, wl_resource* buffer_ } if (!withDamage) - g_pHyprRenderer->damageMonitor(pMonitor); + g_pHyprRenderer->damageMonitor(pMonitor.lock()); } void CScreencopyFrame::share() { @@ -205,7 +205,7 @@ bool CScreencopyFrame::copyDmabuf() { CRegion fakeDamage = {0, 0, INT16_MAX, INT16_MAX}; - if (!g_pHyprRenderer->beginRender(pMonitor, fakeDamage, RENDER_MODE_TO_BUFFER, buffer.lock(), nullptr, true)) { + if (!g_pHyprRenderer->beginRender(pMonitor.lock(), fakeDamage, RENDER_MODE_TO_BUFFER, buffer.lock(), nullptr, true)) { LOGM(ERR, "Can't copy: failed to begin rendering to dma frame"); return false; } @@ -240,7 +240,7 @@ bool CScreencopyFrame::copyShm() { CFramebuffer fb; fb.alloc(box.w, box.h, pMonitor->output->state->state().drmFormat); - if (!g_pHyprRenderer->beginRender(pMonitor, fakeDamage, RENDER_MODE_FULL_FAKE, nullptr, &fb, true)) { + if (!g_pHyprRenderer->beginRender(pMonitor.lock(), fakeDamage, RENDER_MODE_FULL_FAKE, nullptr, &fb, true)) { LOGM(ERR, "Can't copy: failed to begin rendering"); return false; } @@ -288,7 +288,7 @@ bool CScreencopyFrame::copyShm() { } } - g_pHyprOpenGL->m_RenderData.pMonitor = nullptr; + g_pHyprOpenGL->m_RenderData.pMonitor.reset(); LOGM(TRACE, "Copied frame via shm"); @@ -402,7 +402,7 @@ void CScreencopyProtocol::destroyResource(CScreencopyFrame* frame) { std::erase_if(m_vFramesAwaitingWrite, [&](const auto& other) { return !other || other.get() == frame; }); } -void CScreencopyProtocol::onOutputCommit(CMonitor* pMonitor) { +void CScreencopyProtocol::onOutputCommit(PHLMONITOR pMonitor) { if (m_vFramesAwaitingWrite.empty()) { g_pHyprRenderer->m_bDirectScanoutBlocked = false; return; // nothing to share diff --git a/src/protocols/Screencopy.hpp b/src/protocols/Screencopy.hpp index e121d0fd..62c9f8b8 100644 --- a/src/protocols/Screencopy.hpp +++ b/src/protocols/Screencopy.hpp @@ -60,7 +60,7 @@ class CScreencopyFrame { private: SP resource; - CMonitor* pMonitor = nullptr; + PHLMONITORREF pMonitor; bool overlayCursor = false; bool withDamage = false; bool lockedSWCursors = false; @@ -88,7 +88,7 @@ class CScreencopyProtocol : public IWaylandProtocol { void destroyResource(CScreencopyClient* resource); void destroyResource(CScreencopyFrame* resource); - void onOutputCommit(CMonitor* pMonitor); + void onOutputCommit(PHLMONITOR pMonitor); private: std::vector> m_vFrames; @@ -98,7 +98,7 @@ class CScreencopyProtocol : public IWaylandProtocol { SP m_pSoftwareCursorTimer; bool m_bTimerArmed = false; - void shareAllFrames(CMonitor* pMonitor); + void shareAllFrames(PHLMONITOR pMonitor); void shareFrame(CScreencopyFrame* frame); void sendFrameDamage(CScreencopyFrame* frame); bool copyFrameDmabuf(CScreencopyFrame* frame); diff --git a/src/protocols/SessionLock.cpp b/src/protocols/SessionLock.cpp index b1f701bf..642a5b89 100644 --- a/src/protocols/SessionLock.cpp +++ b/src/protocols/SessionLock.cpp @@ -5,7 +5,7 @@ #include "core/Compositor.hpp" #include "core/Output.hpp" -CSessionLockSurface::CSessionLockSurface(SP resource_, SP surface_, CMonitor* pMonitor_, WP owner_) : +CSessionLockSurface::CSessionLockSurface(SP resource_, SP surface_, PHLMONITOR pMonitor_, WP owner_) : resource(resource_), sessionLock(owner_), pSurface(surface_), pMonitor(pMonitor_) { if (!resource->resource()) return; @@ -82,8 +82,8 @@ bool CSessionLockSurface::inert() { return sessionLock.expired(); } -CMonitor* CSessionLockSurface::monitor() { - return pMonitor; +PHLMONITOR CSessionLockSurface::monitor() { + return pMonitor.lock(); } SP CSessionLockSurface::surface() { @@ -184,7 +184,7 @@ void CSessionLockProtocol::onGetLockSurface(CExtSessionLockV1* lock, uint32_t id LOGM(LOG, "New sessionLockSurface with id {}", id); auto PSURFACE = CWLSurfaceResource::fromResource(surface); - auto PMONITOR = CWLOutputResource::fromResource(output)->monitor.get(); + auto PMONITOR = CWLOutputResource::fromResource(output)->monitor.lock(); SP sessionLock; for (auto const& l : m_vLocks) { diff --git a/src/protocols/SessionLock.hpp b/src/protocols/SessionLock.hpp index a0c67e88..a1df6fcf 100644 --- a/src/protocols/SessionLock.hpp +++ b/src/protocols/SessionLock.hpp @@ -13,12 +13,12 @@ class CWLSurfaceResource; class CSessionLockSurface { public: - CSessionLockSurface(SP resource_, SP surface_, CMonitor* pMonitor_, WP owner_); + CSessionLockSurface(SP resource_, SP surface_, PHLMONITOR pMonitor_, WP owner_); ~CSessionLockSurface(); bool good(); bool inert(); - CMonitor* monitor(); + PHLMONITOR monitor(); SP surface(); struct { @@ -31,7 +31,7 @@ class CSessionLockSurface { SP resource; WP sessionLock; WP pSurface; - CMonitor* pMonitor = nullptr; + PHLMONITORREF pMonitor; bool ackdConfigure = false; bool committed = false; diff --git a/src/protocols/ToplevelExport.cpp b/src/protocols/ToplevelExport.cpp index 66df5926..8b6208be 100644 --- a/src/protocols/ToplevelExport.cpp +++ b/src/protocols/ToplevelExport.cpp @@ -362,7 +362,7 @@ void CToplevelExportProtocol::destroyResource(CToplevelExportFrame* frame) { std::erase_if(m_vFramesAwaitingWrite, [&](const auto& other) { return !other || other.get() == frame; }); } -void CToplevelExportProtocol::onOutputCommit(CMonitor* pMonitor) { +void CToplevelExportProtocol::onOutputCommit(PHLMONITOR pMonitor) { if (m_vFramesAwaitingWrite.empty()) return; // nothing to share diff --git a/src/protocols/ToplevelExport.hpp b/src/protocols/ToplevelExport.hpp index 9686431b..bcfa161c 100644 --- a/src/protocols/ToplevelExport.hpp +++ b/src/protocols/ToplevelExport.hpp @@ -80,7 +80,7 @@ class CToplevelExportProtocol : IWaylandProtocol { void destroyResource(CToplevelExportFrame* frame); void onWindowUnmap(PHLWINDOW pWindow); - void onOutputCommit(CMonitor* pMonitor); + void onOutputCommit(PHLMONITOR pMonitor); private: std::vector> m_vClients; diff --git a/src/protocols/core/DataDevice.cpp b/src/protocols/core/DataDevice.cpp index 5644f243..056a72c4 100644 --- a/src/protocols/core/DataDevice.cpp +++ b/src/protocols/core/DataDevice.cpp @@ -681,7 +681,7 @@ void CWLDataDeviceProtocol::abortDrag() { g_pSeatManager->resendEnterEvents(); } -void CWLDataDeviceProtocol::renderDND(CMonitor* pMonitor, timespec* when) { +void CWLDataDeviceProtocol::renderDND(PHLMONITOR pMonitor, timespec* when) { if (!dnd.dndSurface || !dnd.dndSurface->current.texture) return; diff --git a/src/protocols/core/DataDevice.hpp b/src/protocols/core/DataDevice.hpp index 50e9ac61..81ca1b11 100644 --- a/src/protocols/core/DataDevice.hpp +++ b/src/protocols/core/DataDevice.hpp @@ -131,7 +131,7 @@ class CWLDataDeviceProtocol : public IWaylandProtocol { virtual void bindManager(wl_client* client, void* data, uint32_t ver, uint32_t id); // renders and damages the dnd icon, if present - void renderDND(CMonitor* pMonitor, timespec* when); + void renderDND(PHLMONITOR pMonitor, timespec* when); // for inputmgr to force refocus // TODO: move handling to seatmgr bool dndActive(); diff --git a/src/render/OpenGL.cpp b/src/render/OpenGL.cpp index 833e2ccb..fc2d1012 100644 --- a/src/render/OpenGL.cpp +++ b/src/render/OpenGL.cpp @@ -340,7 +340,7 @@ CHyprOpenGLImpl::CHyprOpenGLImpl() { initAssets(); - static auto P = g_pHookSystem->hookDynamic("preRender", [&](void* self, SCallbackInfo& info, std::any data) { preRender(std::any_cast(data)); }); + static auto P = g_pHookSystem->hookDynamic("preRender", [&](void* self, SCallbackInfo& info, std::any data) { preRender(std::any_cast(data)); }); RASSERT(eglMakeCurrent(m_pEglDisplay, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT), "Couldn't unset current EGL!"); @@ -625,7 +625,7 @@ GLuint CHyprOpenGLImpl::compileShader(const GLuint& type, std::string src, bool return shader; } -bool CHyprOpenGLImpl::passRequiresIntrospection(CMonitor* pMonitor) { +bool CHyprOpenGLImpl::passRequiresIntrospection(PHLMONITOR pMonitor) { // passes requiring introspection are the ones that need to render blur, // or when we are rendering to a multigpu target @@ -731,7 +731,7 @@ bool CHyprOpenGLImpl::passRequiresIntrospection(CMonitor* pMonitor) { return false; } -void CHyprOpenGLImpl::beginSimple(CMonitor* pMonitor, const CRegion& damage, SP rb, CFramebuffer* fb) { +void CHyprOpenGLImpl::beginSimple(PHLMONITOR pMonitor, const CRegion& damage, SP rb, CFramebuffer* fb) { m_RenderData.pMonitor = pMonitor; #ifndef GLES2 @@ -783,7 +783,7 @@ void CHyprOpenGLImpl::beginSimple(CMonitor* pMonitor, const CRegion& damage, SP< m_RenderData.simplePass = true; } -void CHyprOpenGLImpl::begin(CMonitor* pMonitor, const CRegion& damage_, CFramebuffer* fb, std::optional finalDamage) { +void CHyprOpenGLImpl::begin(PHLMONITOR pMonitor, const CRegion& damage_, CFramebuffer* fb, std::optional finalDamage) { m_RenderData.pMonitor = pMonitor; static auto PFORCEINTROSPECTION = CConfigValue("opengl:force_introspection"); @@ -929,7 +929,7 @@ void CHyprOpenGLImpl::end() { } // reset our data - m_RenderData.pMonitor = nullptr; + m_RenderData.pMonitor.reset(); m_RenderData.mouseZoomFactor = 1.f; m_RenderData.mouseZoomUseMouse = true; m_RenderData.forceIntrospection = false; @@ -1858,11 +1858,11 @@ CFramebuffer* CHyprOpenGLImpl::blurMainFramebufferWithDamage(float a, CRegion* o return currentRenderToFB; } -void CHyprOpenGLImpl::markBlurDirtyForMonitor(CMonitor* pMonitor) { +void CHyprOpenGLImpl::markBlurDirtyForMonitor(PHLMONITOR pMonitor) { m_mMonitorRenderResources[pMonitor].blurFBDirty = true; } -void CHyprOpenGLImpl::preRender(CMonitor* pMonitor) { +void CHyprOpenGLImpl::preRender(PHLMONITOR pMonitor) { static auto PBLURNEWOPTIMIZE = CConfigValue("decoration:blur:new_optimizations"); static auto PBLURXRAY = CConfigValue("decoration:blur:xray"); static auto PBLUR = CConfigValue("decoration:blur:enabled"); @@ -2728,7 +2728,7 @@ void CHyprOpenGLImpl::initAssets() { CColor{0.9F, 0.9F, 0.9F, 0.7F}, 20, true); } -void CHyprOpenGLImpl::createBGTextureForMonitor(CMonitor* pMonitor) { +void CHyprOpenGLImpl::createBGTextureForMonitor(PHLMONITOR pMonitor) { RASSERT(m_RenderData.pMonitor, "Tried to createBGTex without begin()!"); Debug::log(LOG, "Creating a texture for BGTex"); @@ -2860,7 +2860,7 @@ void CHyprOpenGLImpl::clearWithTex() { auto TEXIT = m_mMonitorBGFBs.find(m_RenderData.pMonitor); if (TEXIT == m_mMonitorBGFBs.end()) { - createBGTextureForMonitor(m_RenderData.pMonitor); + createBGTextureForMonitor(m_RenderData.pMonitor.lock()); TEXIT = m_mMonitorBGFBs.find(m_RenderData.pMonitor); } @@ -2872,7 +2872,7 @@ void CHyprOpenGLImpl::clearWithTex() { } } -void CHyprOpenGLImpl::destroyMonitorResources(CMonitor* pMonitor) { +void CHyprOpenGLImpl::destroyMonitorResources(PHLMONITOR pMonitor) { g_pHyprRenderer->makeEGLCurrent(); if (!g_pHyprOpenGL) @@ -2935,7 +2935,7 @@ void CHyprOpenGLImpl::setRenderModifEnabled(bool enabled) { m_RenderData.renderModif.enabled = enabled; } -uint32_t CHyprOpenGLImpl::getPreferredReadFormat(CMonitor* pMonitor) { +uint32_t CHyprOpenGLImpl::getPreferredReadFormat(PHLMONITOR pMonitor) { return pMonitor->output->state->state().drmFormat; } diff --git a/src/render/OpenGL.hpp b/src/render/OpenGL.hpp index 0d1c267b..04f69d49 100644 --- a/src/render/OpenGL.hpp +++ b/src/render/OpenGL.hpp @@ -94,7 +94,7 @@ struct SMonitorRenderData { }; struct SCurrentRenderData { - CMonitor* pMonitor = nullptr; + PHLMONITORREF pMonitor; PHLWORKSPACE pWorkspace = nullptr; Mat3x3 projection; Mat3x3 savedProjection; @@ -149,8 +149,8 @@ class CHyprOpenGLImpl { CHyprOpenGLImpl(); ~CHyprOpenGLImpl(); - void begin(CMonitor*, const CRegion& damage, CFramebuffer* fb = nullptr, std::optional finalDamage = {}); - void beginSimple(CMonitor*, const CRegion& damage, SP rb = nullptr, CFramebuffer* fb = nullptr); + void begin(PHLMONITOR, const CRegion& damage, CFramebuffer* fb = nullptr, std::optional finalDamage = {}); + void beginSimple(PHLMONITOR, const CRegion& damage, SP rb = nullptr, CFramebuffer* fb = nullptr); void end(); void renderRect(CBox*, const CColor&, int round = 0); @@ -186,13 +186,13 @@ class CHyprOpenGLImpl { void scissor(const pixman_box32*, bool transform = true); void scissor(const int x, const int y, const int w, const int h, bool transform = true); - void destroyMonitorResources(CMonitor*); + void destroyMonitorResources(PHLMONITOR); - void markBlurDirtyForMonitor(CMonitor*); + void markBlurDirtyForMonitor(PHLMONITOR); void preWindowPass(); bool preBlurQueued(); - void preRender(CMonitor*); + void preRender(PHLMONITOR); void saveBufferForMirror(CBox*); void renderMirrored(); @@ -205,31 +205,31 @@ class CHyprOpenGLImpl { void setDamage(const CRegion& damage, std::optional finalDamage = {}); - uint32_t getPreferredReadFormat(CMonitor* pMonitor); - std::vector getDRMFormats(); - EGLImageKHR createEGLImage(const Aquamarine::SDMABUFAttrs& attrs); - SP createEGLSync(int fenceFD); - bool waitForTimelinePoint(SP timeline, uint64_t point); + uint32_t getPreferredReadFormat(PHLMONITOR pMonitor); + std::vector getDRMFormats(); + EGLImageKHR createEGLImage(const Aquamarine::SDMABUFAttrs& attrs); + SP createEGLSync(int fenceFD); + bool waitForTimelinePoint(SP timeline, uint64_t point); - SCurrentRenderData m_RenderData; + SCurrentRenderData m_RenderData; - GLint m_iCurrentOutputFb = 0; + GLint m_iCurrentOutputFb = 0; - int m_iGBMFD = -1; - gbm_device* m_pGbmDevice = nullptr; - EGLContext m_pEglContext = nullptr; - EGLDisplay m_pEglDisplay = nullptr; - EGLDeviceEXT m_pEglDevice = nullptr; + int m_iGBMFD = -1; + gbm_device* m_pGbmDevice = nullptr; + EGLContext m_pEglContext = nullptr; + EGLDisplay m_pEglDisplay = nullptr; + EGLDeviceEXT m_pEglDevice = nullptr; - bool m_bReloadScreenShader = true; // at launch it can be set + bool m_bReloadScreenShader = true; // at launch it can be set - PHLWINDOWREF m_pCurrentWindow; // hack to get the current rendered window - PHLLS m_pCurrentLayer; // hack to get the current rendered layer + PHLWINDOWREF m_pCurrentWindow; // hack to get the current rendered window + PHLLS m_pCurrentLayer; // hack to get the current rendered layer - std::map m_mWindowFramebuffers; - std::map m_mLayerFramebuffers; - std::unordered_map m_mMonitorRenderResources; - std::unordered_map m_mMonitorBGFBs; + std::map m_mWindowFramebuffers; + std::map m_mLayerFramebuffers; + std::unordered_map m_mMonitorRenderResources; + std::unordered_map m_mMonitorBGFBs; struct { PFNGLEGLIMAGETARGETRENDERBUFFERSTORAGEOESPROC glEGLImageTargetRenderbufferStorageOES = nullptr; @@ -282,7 +282,7 @@ class CHyprOpenGLImpl { void logShaderError(const GLuint&, bool program = false); GLuint createProgram(const std::string&, const std::string&, bool dynamic = false); GLuint compileShader(const GLuint&, std::string, bool dynamic = false); - void createBGTextureForMonitor(CMonitor*); + void createBGTextureForMonitor(PHLMONITOR); void initShaders(); void initDRMFormats(); void initEGL(bool gbm); @@ -304,7 +304,7 @@ class CHyprOpenGLImpl { void preBlurForCurrentMonitor(); - bool passRequiresIntrospection(CMonitor* pMonitor); + bool passRequiresIntrospection(PHLMONITOR pMonitor); friend class CHyprRenderer; }; diff --git a/src/render/Renderer.cpp b/src/render/Renderer.cpp index bc95abc6..1165b197 100644 --- a/src/render/Renderer.cpp +++ b/src/render/Renderer.cpp @@ -295,7 +295,7 @@ static void renderSurface(SP surface, int x, int y, void* da RDATA->surfaceCounter++; } -bool CHyprRenderer::shouldRenderWindow(PHLWINDOW pWindow, CMonitor* pMonitor) { +bool CHyprRenderer::shouldRenderWindow(PHLWINDOW pWindow, PHLMONITOR pMonitor) { if (!pWindow->visibleOnMonitor(pMonitor)) return false; @@ -389,7 +389,7 @@ bool CHyprRenderer::shouldRenderWindow(PHLWINDOW pWindow) { return false; } -void CHyprRenderer::renderWorkspaceWindowsFullscreen(CMonitor* pMonitor, PHLWORKSPACE pWorkspace, timespec* time) { +void CHyprRenderer::renderWorkspaceWindowsFullscreen(PHLMONITOR pMonitor, PHLWORKSPACE pWorkspace, timespec* time) { PHLWINDOW pWorkspaceWindow = nullptr; EMIT_HOOK_EVENT("render", RENDER_PRE_WINDOWS); @@ -479,7 +479,7 @@ void CHyprRenderer::renderWorkspaceWindowsFullscreen(CMonitor* pMonitor, PHLWORK } } -void CHyprRenderer::renderWorkspaceWindows(CMonitor* pMonitor, PHLWORKSPACE pWorkspace, timespec* time) { +void CHyprRenderer::renderWorkspaceWindows(PHLMONITOR pMonitor, PHLWORKSPACE pWorkspace, timespec* time) { PHLWINDOW lastWindow; EMIT_HOOK_EVENT("render", RENDER_PRE_WINDOWS); @@ -551,7 +551,7 @@ void CHyprRenderer::renderWorkspaceWindows(CMonitor* pMonitor, PHLWORKSPACE pWor } } -void CHyprRenderer::renderWindow(PHLWINDOW pWindow, CMonitor* pMonitor, timespec* time, bool decorate, eRenderPassMode mode, bool ignorePosition, bool ignoreAllGeometry) { +void CHyprRenderer::renderWindow(PHLWINDOW pWindow, PHLMONITOR pMonitor, timespec* time, bool decorate, eRenderPassMode mode, bool ignorePosition, bool ignoreAllGeometry) { if (pWindow->isHidden()) return; @@ -766,7 +766,7 @@ void CHyprRenderer::renderWindow(PHLWINDOW pWindow, CMonitor* pMonitor, timespec g_pHyprOpenGL->m_RenderData.clipBox = CBox(); } -void CHyprRenderer::renderLayer(PHLLS pLayer, CMonitor* pMonitor, timespec* time, bool popups) { +void CHyprRenderer::renderLayer(PHLLS pLayer, PHLMONITOR pMonitor, timespec* time, bool popups) { if (!pLayer) return; @@ -835,7 +835,7 @@ void CHyprRenderer::renderLayer(PHLLS pLayer, CMonitor* pMonitor, timespec* time g_pHyprOpenGL->m_RenderData.discardOpacity = DA; } -void CHyprRenderer::renderIMEPopup(CInputPopup* pPopup, CMonitor* pMonitor, timespec* time) { +void CHyprRenderer::renderIMEPopup(CInputPopup* pPopup, PHLMONITOR pMonitor, timespec* time) { const auto POS = pPopup->globalBox().pos(); SRenderData renderdata = {pMonitor, time, POS.x, POS.y}; @@ -851,7 +851,7 @@ void CHyprRenderer::renderIMEPopup(CInputPopup* pPopup, CMonitor* pMonitor, time SURF->breadthfirst([](SP s, const Vector2D& offset, void* data) { renderSurface(s, offset.x, offset.y, data); }, &renderdata); } -void CHyprRenderer::renderSessionLockSurface(SSessionLockSurface* pSurface, CMonitor* pMonitor, timespec* time) { +void CHyprRenderer::renderSessionLockSurface(SSessionLockSurface* pSurface, PHLMONITOR pMonitor, timespec* time) { SRenderData renderdata = {pMonitor, time, pMonitor->vecPosition.x, pMonitor->vecPosition.y}; renderdata.blur = false; @@ -863,7 +863,7 @@ void CHyprRenderer::renderSessionLockSurface(SSessionLockSurface* pSurface, CMon renderdata.surface->breadthfirst([](SP s, const Vector2D& offset, void* data) { renderSurface(s, offset.x, offset.y, data); }, &renderdata); } -void CHyprRenderer::renderAllClientsForWorkspace(CMonitor* pMonitor, PHLWORKSPACE pWorkspace, timespec* time, const Vector2D& translate, const float& scale) { +void CHyprRenderer::renderAllClientsForWorkspace(PHLMONITOR pMonitor, PHLWORKSPACE pWorkspace, timespec* time, const Vector2D& translate, const float& scale) { static auto PDIMSPECIAL = CConfigValue("decoration:dim_special"); static auto PBLURSPECIAL = CConfigValue("decoration:blur:special"); static auto PBLUR = CConfigValue("decoration:blur:enabled"); @@ -1036,7 +1036,7 @@ void CHyprRenderer::renderAllClientsForWorkspace(CMonitor* pMonitor, PHLWORKSPAC g_pHyprOpenGL->m_RenderData.renderModif = {}; } -void CHyprRenderer::renderLockscreen(CMonitor* pMonitor, timespec* now, const CBox& geometry) { +void CHyprRenderer::renderLockscreen(PHLMONITOR pMonitor, timespec* now, const CBox& geometry) { TRACY_GPU_ZONE("RenderLockscreen"); if (g_pSessionLockManager->isSessionLocked()) { @@ -1052,7 +1052,7 @@ void CHyprRenderer::renderLockscreen(CMonitor* pMonitor, timespec* now, const CB } } -void CHyprRenderer::renderSessionLockMissing(CMonitor* pMonitor) { +void CHyprRenderer::renderSessionLockMissing(PHLMONITOR pMonitor) { const auto ALPHA = g_pSessionLockManager->getRedScreenAlphaForMonitor(pMonitor->ID); CBox monbox = {{}, pMonitor->vecPixelSize}; @@ -1181,7 +1181,7 @@ void CHyprRenderer::calculateUVForSurface(PHLWINDOW pWindow, SPm_pLastMonitor.get()) { + if (pMonitor == g_pCompositor->m_pLastMonitor) { g_pHyprNotificationOverlay->draw(pMonitor); g_pHyprError->draw(); } // for drawing the debug overlay - if (pMonitor == g_pCompositor->m_vMonitors.front().get() && *PDEBUGOVERLAY == 1) { + if (pMonitor == g_pCompositor->m_vMonitors.front() && *PDEBUGOVERLAY == 1) { renderStartOverlay = std::chrono::high_resolution_clock::now(); g_pDebugOverlay->draw(); endRenderOverlay = std::chrono::high_resolution_clock::now(); @@ -1491,7 +1491,7 @@ void CHyprRenderer::renderMonitor(CMonitor* pMonitor) { g_pDebugOverlay->renderData(pMonitor, durationUs); if (*PDEBUGOVERLAY == 1) { - if (pMonitor == g_pCompositor->m_vMonitors.front().get()) { + if (pMonitor == g_pCompositor->m_vMonitors.front()) { const float noOverlayUs = durationUs - std::chrono::duration_cast(endRenderOverlay - renderStartOverlay).count() / 1000.f; g_pDebugOverlay->renderDataNoOverlay(pMonitor, noOverlayUs); } else { @@ -1500,7 +1500,7 @@ void CHyprRenderer::renderMonitor(CMonitor* pMonitor) { } } -bool CHyprRenderer::commitPendingAndDoExplicitSync(CMonitor* pMonitor) { +bool CHyprRenderer::commitPendingAndDoExplicitSync(PHLMONITOR pMonitor) { // apply timelines for explicit sync // save inFD otherwise reset will reset it auto inFD = pMonitor->output->state->state().explicitInFence; @@ -1565,7 +1565,7 @@ bool CHyprRenderer::commitPendingAndDoExplicitSync(CMonitor* pMonitor) { return ok; } -void CHyprRenderer::renderWorkspace(CMonitor* pMonitor, PHLWORKSPACE pWorkspace, timespec* now, const CBox& geometry) { +void CHyprRenderer::renderWorkspace(PHLMONITOR pMonitor, PHLWORKSPACE pWorkspace, timespec* now, const CBox& geometry) { Vector2D translate = {geometry.x, geometry.y}; float scale = (float)geometry.width / pMonitor->vecPixelSize.x; @@ -1582,7 +1582,7 @@ void CHyprRenderer::renderWorkspace(CMonitor* pMonitor, PHLWORKSPACE pWorkspace, g_pHyprOpenGL->m_RenderData.pWorkspace = nullptr; } -void CHyprRenderer::sendFrameEventsToWorkspace(CMonitor* pMonitor, PHLWORKSPACE pWorkspace, timespec* now) { +void CHyprRenderer::sendFrameEventsToWorkspace(PHLMONITOR pMonitor, PHLWORKSPACE pWorkspace, timespec* now) { for (auto const& w : g_pCompositor->m_vWindows) { if (w->isHidden() || !w->m_bIsMapped || w->m_bFadingOut || !w->m_pWLSurface->resource()) continue; @@ -1670,7 +1670,7 @@ static void applyExclusive(CBox& usableArea, uint32_t anchor, int32_t exclusive, } } -void CHyprRenderer::arrangeLayerArray(CMonitor* pMonitor, const std::vector& layerSurfaces, bool exclusiveZone, CBox* usableArea) { +void CHyprRenderer::arrangeLayerArray(PHLMONITOR pMonitor, const std::vector& layerSurfaces, bool exclusiveZone, CBox* usableArea) { CBox full_area = {pMonitor->vecPosition.x, pMonitor->vecPosition.y, pMonitor->vecSize.x, pMonitor->vecSize.y}; for (auto const& ls : layerSurfaces) { @@ -1865,7 +1865,7 @@ void CHyprRenderer::damageWindow(PHLWINDOW pWindow, bool forceFull) { windowBox.translate(pWindow->m_vFloatingOffset); for (auto const& m : g_pCompositor->m_vMonitors) { - if (forceFull || g_pHyprRenderer->shouldRenderWindow(pWindow, m.get())) { // only damage if window is rendered on monitor + if (forceFull || g_pHyprRenderer->shouldRenderWindow(pWindow, m)) { // only damage if window is rendered on monitor CBox fixedDamageBox = {windowBox.x - m->vecPosition.x, windowBox.y - m->vecPosition.y, windowBox.width, windowBox.height}; fixedDamageBox.scale(m->scale); m->addDamage(&fixedDamageBox); @@ -1881,7 +1881,7 @@ void CHyprRenderer::damageWindow(PHLWINDOW pWindow, bool forceFull) { Debug::log(LOG, "Damage: Window ({}): xy: {}, {} wh: {}, {}", pWindow->m_szTitle, windowBox.x, windowBox.y, windowBox.width, windowBox.height); } -void CHyprRenderer::damageMonitor(CMonitor* pMonitor) { +void CHyprRenderer::damageMonitor(PHLMONITOR pMonitor) { if (g_pCompositor->m_bUnsafeState || pMonitor->isMirror()) return; @@ -1925,7 +1925,7 @@ void CHyprRenderer::damageRegion(const CRegion& rg) { } } -void CHyprRenderer::damageMirrorsWith(CMonitor* pMonitor, const CRegion& pRegion) { +void CHyprRenderer::damageMirrorsWith(PHLMONITOR pMonitor, const CRegion& pRegion) { for (auto const& mirror : pMonitor->mirrors) { // transform the damage here, so it won't get clipped by the monitor damage ring @@ -1946,11 +1946,11 @@ void CHyprRenderer::damageMirrorsWith(CMonitor* pMonitor, const CRegion& pRegion mirror->addDamage(&transformed); - g_pCompositor->scheduleFrameForMonitor(mirror, Aquamarine::IOutput::AQ_SCHEDULE_DAMAGE); + g_pCompositor->scheduleFrameForMonitor(mirror.lock(), Aquamarine::IOutput::AQ_SCHEDULE_DAMAGE); } } -void CHyprRenderer::renderDragIcon(CMonitor* pMonitor, timespec* time) { +void CHyprRenderer::renderDragIcon(PHLMONITOR pMonitor, timespec* time) { PROTO::data->renderDND(pMonitor, time); } @@ -1965,7 +1965,7 @@ DAMAGETRACKINGMODES CHyprRenderer::damageTrackingModeFromStr(const std::string& return DAMAGE_TRACKING_INVALID; } -bool CHyprRenderer::applyMonitorRule(CMonitor* pMonitor, SMonitorRule* pMonitorRule, bool force) { +bool CHyprRenderer::applyMonitorRule(PHLMONITOR pMonitor, SMonitorRule* pMonitorRule, bool force) { static auto PDISABLESCALECHECKS = CConfigValue("debug:disable_scale_checks"); @@ -2436,7 +2436,7 @@ void CHyprRenderer::ensureCursorRenderingMode() { if (!g_pPointerManager->softwareLockedFor(m)) continue; - g_pHyprRenderer->damageMonitor(m.get()); // TODO: maybe just damage the cursor area? + g_pHyprRenderer->damageMonitor(m); // TODO: maybe just damage the cursor area? } setCursorHidden(true); @@ -2448,7 +2448,7 @@ void CHyprRenderer::ensureCursorRenderingMode() { if (!g_pPointerManager->softwareLockedFor(m)) continue; - g_pHyprRenderer->damageMonitor(m.get()); // TODO: maybe just damage the cursor area? + g_pHyprRenderer->damageMonitor(m); // TODO: maybe just damage the cursor area? } setCursorHidden(false); @@ -2479,7 +2479,7 @@ bool CHyprRenderer::shouldRenderCursor() { return !m_bCursorHidden && m_bCursorHasSurface; } -std::tuple CHyprRenderer::getRenderTimes(CMonitor* pMonitor) { +std::tuple CHyprRenderer::getRenderTimes(PHLMONITOR pMonitor) { const auto POVERLAY = &g_pDebugOverlay->m_mMonitorOverlays[pMonitor]; float avgRenderTime = 0; @@ -2590,7 +2590,7 @@ void CHyprRenderer::setOccludedForBackLayers(CRegion& region, PHLWORKSPACE pWork region.subtract(rg); } -bool CHyprRenderer::canSkipBackBufferClear(CMonitor* pMonitor) { +bool CHyprRenderer::canSkipBackBufferClear(PHLMONITOR pMonitor) { for (auto const& ls : pMonitor->m_aLayerSurfaceLayers[ZWLR_LAYER_SHELL_V1_LAYER_BACKGROUND]) { if (!ls->layerSurface) continue; @@ -2616,7 +2616,7 @@ bool CHyprRenderer::canSkipBackBufferClear(CMonitor* pMonitor) { return false; } -void CHyprRenderer::recheckSolitaryForMonitor(CMonitor* pMonitor) { +void CHyprRenderer::recheckSolitaryForMonitor(PHLMONITOR pMonitor) { pMonitor->solitaryClient.reset(); // reset it, if we find one it will be set. if (g_pHyprNotificationOverlay->hasAny() || g_pSessionLockManager->isSessionLocked()) @@ -2704,7 +2704,7 @@ void CHyprRenderer::unsetEGL() { eglMakeCurrent(g_pHyprOpenGL->m_pEglDisplay, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT); } -bool CHyprRenderer::beginRender(CMonitor* pMonitor, CRegion& damage, eRenderMode mode, SP buffer, CFramebuffer* fb, bool simple) { +bool CHyprRenderer::beginRender(PHLMONITOR pMonitor, CRegion& damage, eRenderMode mode, SP buffer, CFramebuffer* fb, bool simple) { makeEGLCurrent(); @@ -2777,7 +2777,7 @@ void CHyprRenderer::endRender() { if (m_eRenderMode != RENDER_MODE_TO_BUFFER_READ_ONLY) g_pHyprOpenGL->end(); else { - g_pHyprOpenGL->m_RenderData.pMonitor = nullptr; + g_pHyprOpenGL->m_RenderData.pMonitor.reset(); g_pHyprOpenGL->m_RenderData.mouseZoomFactor = 1.f; g_pHyprOpenGL->m_RenderData.mouseZoomUseMouse = true; } diff --git a/src/render/Renderer.hpp b/src/render/Renderer.hpp index 7d1ae4b1..41f40b5a 100644 --- a/src/render/Renderer.hpp +++ b/src/render/Renderer.hpp @@ -49,29 +49,29 @@ class CHyprRenderer { CHyprRenderer(); ~CHyprRenderer(); - void renderMonitor(CMonitor* pMonitor); + void renderMonitor(PHLMONITOR pMonitor); void arrangeLayersForMonitor(const MONITORID&); void damageSurface(SP, double, double, double scale = 1.0); void damageWindow(PHLWINDOW, bool forceFull = false); void damageBox(CBox*, bool skipFrameSchedule = false); void damageBox(const int& x, const int& y, const int& w, const int& h); void damageRegion(const CRegion&); - void damageMonitor(CMonitor*); - void damageMirrorsWith(CMonitor*, const CRegion&); - bool applyMonitorRule(CMonitor*, SMonitorRule*, bool force = false); - bool shouldRenderWindow(PHLWINDOW, CMonitor*); + void damageMonitor(PHLMONITOR); + void damageMirrorsWith(PHLMONITOR, const CRegion&); + bool applyMonitorRule(PHLMONITOR, SMonitorRule*, bool force = false); + bool shouldRenderWindow(PHLWINDOW, PHLMONITOR); bool shouldRenderWindow(PHLWINDOW); void ensureCursorRenderingMode(); bool shouldRenderCursor(); void setCursorHidden(bool hide); void calculateUVForSurface(PHLWINDOW, SP, SP pMonitor, bool main = false, const Vector2D& projSize = {}, const Vector2D& projSizeUnscaled = {}, bool fixMisalignedFSV1 = false); - std::tuple getRenderTimes(CMonitor* pMonitor); // avg max min - void renderLockscreen(CMonitor* pMonitor, timespec* now, const CBox& geometry); + std::tuple getRenderTimes(PHLMONITOR pMonitor); // avg max min + void renderLockscreen(PHLMONITOR pMonitor, timespec* now, const CBox& geometry); void setOccludedForBackLayers(CRegion& region, PHLWORKSPACE pWorkspace); void setOccludedForMainWorkspace(CRegion& region, PHLWORKSPACE pWorkspace); // TODO: merge occlusion methods - bool canSkipBackBufferClear(CMonitor* pMonitor); - void recheckSolitaryForMonitor(CMonitor* pMonitor); + bool canSkipBackBufferClear(PHLMONITOR pMonitor); + void recheckSolitaryForMonitor(PHLMONITOR pMonitor); void setCursorSurface(SP surf, int hotspotX, int hotspotY, bool force = false); void setCursorFromName(const std::string& name, bool force = false); void onRenderbufferDestroy(CRenderbuffer* rb); @@ -84,13 +84,13 @@ class CHyprRenderer { // if RENDER_MODE_NORMAL, provided damage will be written to. // otherwise, it will be the one used. - bool beginRender(CMonitor* pMonitor, CRegion& damage, eRenderMode mode = RENDER_MODE_NORMAL, SP buffer = {}, CFramebuffer* fb = nullptr, bool simple = false); - void endRender(); + bool beginRender(PHLMONITOR pMonitor, CRegion& damage, eRenderMode mode = RENDER_MODE_NORMAL, SP buffer = {}, CFramebuffer* fb = nullptr, bool simple = false); + void endRender(); - bool m_bBlockSurfaceFeedback = false; - bool m_bRenderingSnapshot = false; - CMonitor* m_pMostHzMonitor = nullptr; - bool m_bDirectScanoutBlocked = false; + bool m_bBlockSurfaceFeedback = false; + bool m_bRenderingSnapshot = false; + PHLMONITORREF m_pMostHzMonitor; + bool m_bDirectScanoutBlocked = false; DAMAGETRACKINGMODES damageTrackingModeFromStr(const std::string&); @@ -115,20 +115,20 @@ class CHyprRenderer { } m_sLastCursorData; private: - void arrangeLayerArray(CMonitor*, const std::vector&, bool, CBox*); - void renderWorkspaceWindowsFullscreen(CMonitor*, PHLWORKSPACE, timespec*); // renders workspace windows (fullscreen) (tiled, floating, pinned, but no special) - void renderWorkspaceWindows(CMonitor*, PHLWORKSPACE, timespec*); // renders workspace windows (no fullscreen) (tiled, floating, pinned, but no special) - void renderWindow(PHLWINDOW, CMonitor*, timespec*, bool, eRenderPassMode, bool ignorePosition = false, bool ignoreAllGeometry = false); - void renderLayer(PHLLS, CMonitor*, timespec*, bool popups = false); - void renderSessionLockSurface(SSessionLockSurface*, CMonitor*, timespec*); - void renderDragIcon(CMonitor*, timespec*); - void renderIMEPopup(CInputPopup*, CMonitor*, timespec*); - void renderWorkspace(CMonitor* pMonitor, PHLWORKSPACE pWorkspace, timespec* now, const CBox& geometry); - void sendFrameEventsToWorkspace(CMonitor* pMonitor, PHLWORKSPACE pWorkspace, timespec* now); // sends frame displayed events but doesn't actually render anything - void renderAllClientsForWorkspace(CMonitor* pMonitor, PHLWORKSPACE pWorkspace, timespec* now, const Vector2D& translate = {0, 0}, const float& scale = 1.f); - void renderSessionLockMissing(CMonitor* pMonitor); + void arrangeLayerArray(PHLMONITOR, const std::vector&, bool, CBox*); + void renderWorkspaceWindowsFullscreen(PHLMONITOR, PHLWORKSPACE, timespec*); // renders workspace windows (fullscreen) (tiled, floating, pinned, but no special) + void renderWorkspaceWindows(PHLMONITOR, PHLWORKSPACE, timespec*); // renders workspace windows (no fullscreen) (tiled, floating, pinned, but no special) + void renderWindow(PHLWINDOW, PHLMONITOR, timespec*, bool, eRenderPassMode, bool ignorePosition = false, bool ignoreAllGeometry = false); + void renderLayer(PHLLS, PHLMONITOR, timespec*, bool popups = false); + void renderSessionLockSurface(SSessionLockSurface*, PHLMONITOR, timespec*); + void renderDragIcon(PHLMONITOR, timespec*); + void renderIMEPopup(CInputPopup*, PHLMONITOR, timespec*); + void renderWorkspace(PHLMONITOR pMonitor, PHLWORKSPACE pWorkspace, timespec* now, const CBox& geometry); + void sendFrameEventsToWorkspace(PHLMONITOR pMonitor, PHLWORKSPACE pWorkspace, timespec* now); // sends frame displayed events but doesn't actually render anything + void renderAllClientsForWorkspace(PHLMONITOR pMonitor, PHLWORKSPACE pWorkspace, timespec* now, const Vector2D& translate = {0, 0}, const float& scale = 1.f); + void renderSessionLockMissing(PHLMONITOR pMonitor); - bool commitPendingAndDoExplicitSync(CMonitor* pMonitor); + bool commitPendingAndDoExplicitSync(PHLMONITOR pMonitor); bool m_bCursorHidden = false; bool m_bCursorHasSurface = false; diff --git a/src/render/decorations/CHyprBorderDecoration.cpp b/src/render/decorations/CHyprBorderDecoration.cpp index 1eaaa0af..68325a9c 100644 --- a/src/render/decorations/CHyprBorderDecoration.cpp +++ b/src/render/decorations/CHyprBorderDecoration.cpp @@ -46,7 +46,7 @@ CBox CHyprBorderDecoration::assignedBoxGlobal() { return box.translate(WORKSPACEOFFSET); } -void CHyprBorderDecoration::draw(CMonitor* pMonitor, float a) { +void CHyprBorderDecoration::draw(PHLMONITOR pMonitor, float a) { if (doesntWantBorders()) return; @@ -119,7 +119,7 @@ void CHyprBorderDecoration::damageEntire() { borderRegion.subtract(surfaceBoxShrunkRounding); for (auto const& m : g_pCompositor->m_vMonitors) { - if (!g_pHyprRenderer->shouldRenderWindow(m_pWindow.lock(), m.get())) { + if (!g_pHyprRenderer->shouldRenderWindow(m_pWindow.lock(), m)) { const CRegion monitorRegion({m->vecPosition, m->vecSize}); borderRegion.subtract(monitorRegion); } diff --git a/src/render/decorations/CHyprBorderDecoration.hpp b/src/render/decorations/CHyprBorderDecoration.hpp index 0e196565..5d248a81 100644 --- a/src/render/decorations/CHyprBorderDecoration.hpp +++ b/src/render/decorations/CHyprBorderDecoration.hpp @@ -11,7 +11,7 @@ class CHyprBorderDecoration : public IHyprWindowDecoration { virtual void onPositioningReply(const SDecorationPositioningReply& reply); - virtual void draw(CMonitor*, float a); + virtual void draw(PHLMONITOR, float a); virtual eDecorationType getDecorationType(); diff --git a/src/render/decorations/CHyprDropShadowDecoration.cpp b/src/render/decorations/CHyprDropShadowDecoration.cpp index 628a579a..a4388a67 100644 --- a/src/render/decorations/CHyprDropShadowDecoration.cpp +++ b/src/render/decorations/CHyprDropShadowDecoration.cpp @@ -67,7 +67,7 @@ void CHyprDropShadowDecoration::damageEntire() { } for (auto const& m : g_pCompositor->m_vMonitors) { - if (!g_pHyprRenderer->shouldRenderWindow(PWINDOW, m.get())) { + if (!g_pHyprRenderer->shouldRenderWindow(PWINDOW, m)) { const CRegion monitorRegion({m->vecPosition, m->vecSize}); shadowRegion.subtract(monitorRegion); } @@ -86,7 +86,7 @@ void CHyprDropShadowDecoration::updateWindow(PHLWINDOW pWindow) { m_bLastWindowBoxWithDecos = g_pDecorationPositioner->getBoxWithIncludedDecos(pWindow); } -void CHyprDropShadowDecoration::draw(CMonitor* pMonitor, float a) { +void CHyprDropShadowDecoration::draw(PHLMONITOR pMonitor, float a) { const auto PWINDOW = m_pWindow.lock(); diff --git a/src/render/decorations/CHyprDropShadowDecoration.hpp b/src/render/decorations/CHyprDropShadowDecoration.hpp index ecd5a47b..fce9a7c7 100644 --- a/src/render/decorations/CHyprDropShadowDecoration.hpp +++ b/src/render/decorations/CHyprDropShadowDecoration.hpp @@ -11,7 +11,7 @@ class CHyprDropShadowDecoration : public IHyprWindowDecoration { virtual void onPositioningReply(const SDecorationPositioningReply& reply); - virtual void draw(CMonitor*, float a); + virtual void draw(PHLMONITOR, float a); virtual eDecorationType getDecorationType(); diff --git a/src/render/decorations/CHyprGroupBarDecoration.cpp b/src/render/decorations/CHyprGroupBarDecoration.cpp index 74a1e2e9..4219a5a8 100644 --- a/src/render/decorations/CHyprGroupBarDecoration.cpp +++ b/src/render/decorations/CHyprGroupBarDecoration.cpp @@ -94,7 +94,7 @@ void CHyprGroupBarDecoration::damageEntire() { g_pHyprRenderer->damageBox(&box); } -void CHyprGroupBarDecoration::draw(CMonitor* pMonitor, float a) { +void CHyprGroupBarDecoration::draw(PHLMONITOR pMonitor, float a) { // get how many bars we will draw int barsToDraw = m_dwGroupMembers.size(); diff --git a/src/render/decorations/CHyprGroupBarDecoration.hpp b/src/render/decorations/CHyprGroupBarDecoration.hpp index bfb15d5c..e388fa38 100644 --- a/src/render/decorations/CHyprGroupBarDecoration.hpp +++ b/src/render/decorations/CHyprGroupBarDecoration.hpp @@ -31,7 +31,7 @@ class CHyprGroupBarDecoration : public IHyprWindowDecoration { virtual void onPositioningReply(const SDecorationPositioningReply& reply); - virtual void draw(CMonitor*, float a); + virtual void draw(PHLMONITOR, float a); virtual eDecorationType getDecorationType(); diff --git a/src/render/decorations/IHyprWindowDecoration.hpp b/src/render/decorations/IHyprWindowDecoration.hpp index a58560f3..99698a56 100644 --- a/src/render/decorations/IHyprWindowDecoration.hpp +++ b/src/render/decorations/IHyprWindowDecoration.hpp @@ -39,7 +39,7 @@ class IHyprWindowDecoration { virtual void onPositioningReply(const SDecorationPositioningReply& reply) = 0; - virtual void draw(CMonitor*, float a) = 0; + virtual void draw(PHLMONITOR, float a) = 0; virtual eDecorationType getDecorationType() = 0; From 6a5c342063814ca7e3d181f324c71305bcd656a0 Mon Sep 17 00:00:00 2001 From: Vaxry Date: Sat, 19 Oct 2024 23:45:51 +0100 Subject: [PATCH 0542/2181] layersurface: round geom in arrangeLayerArray fixes #8171 --- src/render/Renderer.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/render/Renderer.cpp b/src/render/Renderer.cpp index 1165b197..1946d5a2 100644 --- a/src/render/Renderer.cpp +++ b/src/render/Renderer.cpp @@ -1742,7 +1742,9 @@ void CHyprRenderer::arrangeLayerArray(PHLMONITOR pMonitor, const std::vectorgeometry = box; applyExclusive(*usableArea, PSTATE->anchor, PSTATE->exclusive, PSTATE->exclusiveEdge, PSTATE->margin.top, PSTATE->margin.right, PSTATE->margin.bottom, PSTATE->margin.left); From a17850e41cabb455880b43032cf65041cd77ef25 Mon Sep 17 00:00:00 2001 From: Vaxry Date: Sat, 19 Oct 2024 23:47:28 +0100 Subject: [PATCH 0543/2181] layersurface: fixup brace style --- src/render/Renderer.cpp | 44 ++++++++++++++++++++--------------------- 1 file changed, 22 insertions(+), 22 deletions(-) diff --git a/src/render/Renderer.cpp b/src/render/Renderer.cpp index 1946d5a2..5df0c070 100644 --- a/src/render/Renderer.cpp +++ b/src/render/Renderer.cpp @@ -1693,51 +1693,51 @@ void CHyprRenderer::arrangeLayerArray(PHLMONITOR pMonitor, const std::vectordesiredSize}; // Horizontal axis const uint32_t both_horiz = ZWLR_LAYER_SURFACE_V1_ANCHOR_LEFT | ZWLR_LAYER_SURFACE_V1_ANCHOR_RIGHT; - if (box.width == 0) { + if (box.width == 0) box.x = bounds.x; - } else if ((PSTATE->anchor & both_horiz) == both_horiz) { + else if ((PSTATE->anchor & both_horiz) == both_horiz) box.x = bounds.x + ((bounds.width / 2) - (box.width / 2)); - } else if ((PSTATE->anchor & ZWLR_LAYER_SURFACE_V1_ANCHOR_LEFT)) { + else if ((PSTATE->anchor & ZWLR_LAYER_SURFACE_V1_ANCHOR_LEFT)) box.x = bounds.x; - } else if ((PSTATE->anchor & ZWLR_LAYER_SURFACE_V1_ANCHOR_RIGHT)) { + else if ((PSTATE->anchor & ZWLR_LAYER_SURFACE_V1_ANCHOR_RIGHT)) box.x = bounds.x + (bounds.width - box.width); - } else { + else box.x = bounds.x + ((bounds.width / 2) - (box.width / 2)); - } + // Vertical axis const uint32_t both_vert = ZWLR_LAYER_SURFACE_V1_ANCHOR_TOP | ZWLR_LAYER_SURFACE_V1_ANCHOR_BOTTOM; - if (box.height == 0) { + if (box.height == 0) box.y = bounds.y; - } else if ((PSTATE->anchor & both_vert) == both_vert) { + else if ((PSTATE->anchor & both_vert) == both_vert) box.y = bounds.y + ((bounds.height / 2) - (box.height / 2)); - } else if ((PSTATE->anchor & ZWLR_LAYER_SURFACE_V1_ANCHOR_TOP)) { + else if ((PSTATE->anchor & ZWLR_LAYER_SURFACE_V1_ANCHOR_TOP)) box.y = bounds.y; - } else if ((PSTATE->anchor & ZWLR_LAYER_SURFACE_V1_ANCHOR_BOTTOM)) { + else if ((PSTATE->anchor & ZWLR_LAYER_SURFACE_V1_ANCHOR_BOTTOM)) box.y = bounds.y + (bounds.height - box.height); - } else { + else box.y = bounds.y + ((bounds.height / 2) - (box.height / 2)); - } + // Margin if (box.width == 0) { box.x += PSTATE->margin.left; box.width = bounds.width - (PSTATE->margin.left + PSTATE->margin.right); - } else if ((PSTATE->anchor & both_horiz) == both_horiz) { - // don't apply margins - } else if ((PSTATE->anchor & ZWLR_LAYER_SURFACE_V1_ANCHOR_LEFT)) { + } else if ((PSTATE->anchor & both_horiz) == both_horiz) + ; // don't apply margins + else if ((PSTATE->anchor & ZWLR_LAYER_SURFACE_V1_ANCHOR_LEFT)) box.x += PSTATE->margin.left; - } else if ((PSTATE->anchor & ZWLR_LAYER_SURFACE_V1_ANCHOR_RIGHT)) { + else if ((PSTATE->anchor & ZWLR_LAYER_SURFACE_V1_ANCHOR_RIGHT)) box.x -= PSTATE->margin.right; - } + if (box.height == 0) { box.y += PSTATE->margin.top; box.height = bounds.height - (PSTATE->margin.top + PSTATE->margin.bottom); - } else if ((PSTATE->anchor & both_vert) == both_vert) { - // don't apply margins - } else if ((PSTATE->anchor & ZWLR_LAYER_SURFACE_V1_ANCHOR_TOP)) { + } else if ((PSTATE->anchor & both_vert) == both_vert) + ; // don't apply margins + else if ((PSTATE->anchor & ZWLR_LAYER_SURFACE_V1_ANCHOR_TOP)) box.y += PSTATE->margin.top; - } else if ((PSTATE->anchor & ZWLR_LAYER_SURFACE_V1_ANCHOR_BOTTOM)) { + else if ((PSTATE->anchor & ZWLR_LAYER_SURFACE_V1_ANCHOR_BOTTOM)) box.y -= PSTATE->margin.bottom; - } + if (box.width <= 0 || box.height <= 0) { Debug::log(ERR, "LayerSurface {:x} has a negative/zero w/h???", (uintptr_t)ls.get()); continue; From 08cc063e175e48cea44d26b7e3762f4b8611f0c5 Mon Sep 17 00:00:00 2001 From: Vaxry Date: Sat, 19 Oct 2024 23:48:25 +0100 Subject: [PATCH 0544/2181] monitor: avoid crash on released buffer in surf --- src/helpers/Monitor.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/helpers/Monitor.cpp b/src/helpers/Monitor.cpp index 6ded5ea4..d8889585 100644 --- a/src/helpers/Monitor.cpp +++ b/src/helpers/Monitor.cpp @@ -845,7 +845,7 @@ bool CMonitor::attemptDirectScanout() { return false; // we can't scanout shm buffers. - if (!PSURFACE->current.buffer || !PSURFACE->current.texture || !PSURFACE->current.texture->m_pEglImage /* dmabuf */) + if (!PSURFACE->current.buffer || !PSURFACE->current.buffer->buffer || !PSURFACE->current.texture || !PSURFACE->current.texture->m_pEglImage /* dmabuf */) return false; Debug::log(TRACE, "attemptDirectScanout: surface {:x} passed, will attempt", (uintptr_t)PSURFACE.get()); From 4093b993a2c79ce576702641134d745ab97c6b2c Mon Sep 17 00:00:00 2001 From: Mike Will Date: Mon, 21 Oct 2024 11:08:25 -0400 Subject: [PATCH 0545/2181] input: add snapping to floating windows (#8088) * add snapping to floating windows Works for both moving and resizing of windows. It comes with 3 options: `general:snap:enabled` - whether it's enabled, off by default `general:snap:window_gap` - minimum gap in pixels between windows before snapping. Setting to 0 effectively turns off this method of snapping. `general:snap:monitor_gap` - minimum gap in pixels between window and monitor edges before snapping. Again, setting it to 0 effectively turns it off. * snap: add more ignore criteria and change if clause into a guard * snap: refactor code * snap: new refactoring approach and account for border size * snap: do corner snapping after all edge snapping is done The approach of performing corner snaps after each individual edge snap results in far fewer scenarios where snapping can occur. After trying it out for a while, I found that I prefer an approach that's more prone to snapping. * snap: combine snapWindows and snapMonitor into a single function * snap: add forced aspect ratio functionality * snap: avoid directly referring to border_size config value * snap: address vaxerski feedback - add new line between functions - use std::function typedef for SnapFn and make snap functions static - avoid uninitialized variable declarations. - change ignore condition m_bIsX11 to isX11OverrideRedirect() - use braces for CBox and Vector2D declarations. - add SNAP_INVALID to eSnapEdge enum - use bitshift notation for eSnapEdge and eRectCorner - make performSnap a non-member function. * snap: add corner-snapping to forced aspect ratio mode --- src/config/ConfigDescriptions.hpp | 18 ++++ src/config/ConfigManager.cpp | 3 + src/layout/IHyprLayout.cpp | 155 +++++++++++++++++++++++++++++- src/layout/IHyprLayout.hpp | 18 +++- 4 files changed, 185 insertions(+), 9 deletions(-) diff --git a/src/config/ConfigDescriptions.hpp b/src/config/ConfigDescriptions.hpp index bef5ee53..7e2dd1be 100644 --- a/src/config/ConfigDescriptions.hpp +++ b/src/config/ConfigDescriptions.hpp @@ -104,6 +104,24 @@ inline static const std::vector CONFIG_OPTIONS = { .type = CONFIG_OPTION_INT, .data = SConfigOptionDescription::SRangeData{0, 0, 4}, }, + SConfigOptionDescription{ + .value = "general:snap:enabled", + .description = "enable snapping for floating windows", + .type = CONFIG_OPTION_BOOL, + .data = SConfigOptionDescription::SBoolData{false}, + }, + SConfigOptionDescription{ + .value = "general:snap:window_gap", + .description = "minimum gap in pixels between windows before snapping", + .type = CONFIG_OPTION_INT, + .data = SConfigOptionDescription::SRangeData{10, 0, 100}, + }, + SConfigOptionDescription{ + .value = "general:snap:monitor_gap", + .description = "minimum gap in pixels between window and monitor edges before snapping", + .type = CONFIG_OPTION_INT, + .data = SConfigOptionDescription::SRangeData{10, 0, 100}, + }, /* * decoration: diff --git a/src/config/ConfigManager.cpp b/src/config/ConfigManager.cpp index f16ebe46..1dbd248d 100644 --- a/src/config/ConfigManager.cpp +++ b/src/config/ConfigManager.cpp @@ -341,6 +341,9 @@ CConfigManager::CConfigManager() { m_pConfig->addConfigValue("general:layout", {"dwindle"}); m_pConfig->addConfigValue("general:allow_tearing", Hyprlang::INT{0}); m_pConfig->addConfigValue("general:resize_corner", Hyprlang::INT{0}); + m_pConfig->addConfigValue("general:snap:enabled", Hyprlang::INT{0}); + m_pConfig->addConfigValue("general:snap:window_gap", Hyprlang::INT{10}); + m_pConfig->addConfigValue("general:snap:monitor_gap", Hyprlang::INT{10}); m_pConfig->addConfigValue("misc:disable_hyprland_logo", Hyprlang::INT{0}); m_pConfig->addConfigValue("misc:disable_splash_rendering", Hyprlang::INT{0}); diff --git a/src/layout/IHyprLayout.cpp b/src/layout/IHyprLayout.cpp index b8d92636..95919c65 100644 --- a/src/layout/IHyprLayout.cpp +++ b/src/layout/IHyprLayout.cpp @@ -396,6 +396,138 @@ void IHyprLayout::onEndDragWindow() { g_pInputManager->m_bWasDraggingWindow = false; } +static inline bool canSnap(const double sideA, const double sideB, const double gap) { + return std::abs(sideA - sideB) < gap; +} + +static void snapMoveLeft(double& pos, double& len, const double p) { + pos = p; +} + +static void snapMoveRight(double& pos, double& len, const double p) { + pos = p - len; +} + +static void snapResizeLeft(double& pos, double& len, const double p) { + len += pos - p; + pos = p; +} + +static void snapResizeRight(double& pos, double& len, const double p) { + len = p - pos; +} + +typedef std::function SnapFn; + +static void performSnap(Vector2D& pos, Vector2D& size, PHLWINDOW DRAGGINGWINDOW, const eMouseBindMode mode, const int corner, const Vector2D& beginSize) { + static auto SNAPWINDOWGAP = CConfigValue("general:snap:window_gap"); + static auto SNAPMONITORGAP = CConfigValue("general:snap:monitor_gap"); + + const SnapFn snapRight = (mode == MBIND_MOVE) ? snapMoveRight : snapResizeRight; + const SnapFn snapLeft = (mode == MBIND_MOVE) ? snapMoveLeft : snapResizeLeft; + const SnapFn snapDown = snapRight; + const SnapFn snapUp = snapLeft; + int snaps = 0; + + if (*SNAPWINDOWGAP) { + const auto PID = DRAGGINGWINDOW->getPID(); + const auto WSID = DRAGGINGWINDOW->workspaceID(); + const int BORD = DRAGGINGWINDOW->getRealBorderSize(); + + for (auto& other : g_pCompositor->m_vWindows) { + if (other->workspaceID() != WSID || other->getPID() == PID || !other->m_bIsMapped || other->m_bFadingOut || other->isX11OverrideRedirect()) + continue; + + const int bord = std::max(BORD, other->getRealBorderSize()); + const double gap = *SNAPWINDOWGAP + bord; + + const CBox box = other->getWindowMainSurfaceBox(); + const CBox ob = {box.x, box.y, box.x + box.w, box.y + box.h}; + const CBox bb = {ob.x - bord, ob.y - bord, ob.w + bord, ob.h + bord}; + const Vector2D end = {pos.x + size.x, pos.y + size.y}; + + // only snap windows if their ranges intersect in the opposite axis + if (pos.y <= bb.h && bb.y <= end.y) { + if (corner & (CORNER_TOPLEFT | CORNER_BOTTOMLEFT) && canSnap(pos.x, bb.w, gap)) { + snapLeft(pos.x, size.x, bb.w); + snaps |= SNAP_LEFT; + } else if (corner & (CORNER_TOPRIGHT | CORNER_BOTTOMRIGHT) && canSnap(end.x, bb.x, gap)) { + snapRight(pos.x, size.x, bb.x); + snaps |= SNAP_RIGHT; + } + } + if (pos.x <= bb.w && bb.x <= end.x) { + if (corner & (CORNER_TOPLEFT | CORNER_TOPRIGHT) && canSnap(pos.y, bb.h, gap)) { + snapUp(pos.y, size.y, bb.h); + snaps |= SNAP_UP; + } else if (corner & (CORNER_BOTTOMLEFT | CORNER_BOTTOMRIGHT) && canSnap(end.y, bb.y, gap)) { + snapDown(pos.y, size.y, bb.y); + snaps |= SNAP_DOWN; + } + } + + // corner snapping + if (pos.x == bb.w || bb.x == pos.x + size.x) { + if (corner & (CORNER_TOPLEFT | CORNER_TOPRIGHT) && canSnap(pos.y, ob.y, gap)) { + snapUp(pos.y, size.y, ob.y); + snaps |= SNAP_UP; + } else if (corner & (CORNER_BOTTOMLEFT | CORNER_BOTTOMRIGHT) && canSnap(end.y, ob.h, gap)) { + snapDown(pos.y, size.y, ob.h); + snaps |= SNAP_DOWN; + } + } + if (pos.y == bb.h || bb.y == pos.y + size.y) { + if (corner & (CORNER_TOPLEFT | CORNER_BOTTOMLEFT) && canSnap(pos.x, ob.x, gap)) { + snapLeft(pos.x, size.x, ob.x); + snaps |= SNAP_LEFT; + } else if (corner & (CORNER_TOPRIGHT | CORNER_BOTTOMRIGHT) && canSnap(end.x, ob.w, gap)) { + snapRight(pos.x, size.x, ob.w); + snaps |= SNAP_RIGHT; + } + } + } + } + + if (*SNAPMONITORGAP) { + const auto MON = g_pCompositor->getMonitorFromID(DRAGGINGWINDOW->m_iMonitorID); + const CBox mon = {MON->vecPosition.x, MON->vecPosition.y, MON->vecPosition.x + MON->vecSize.x, MON->vecPosition.y + MON->vecSize.y}; + const double gap = *SNAPMONITORGAP; + + if (canSnap(pos.x, mon.x, gap)) { + snapLeft(pos.x, size.x, mon.x); + snaps |= SNAP_LEFT; + } + if (canSnap(pos.x + size.x, mon.w, gap)) { + snapRight(pos.x, size.x, mon.w); + snaps |= SNAP_RIGHT; + } + if (canSnap(pos.y, mon.y, gap)) { + snapUp(pos.y, size.y, mon.y); + snaps |= SNAP_UP; + } + if (canSnap(pos.y + size.y, mon.h, gap)) { + snapDown(pos.y, size.y, mon.h); + snaps |= SNAP_DOWN; + } + } + + if (mode == MBIND_RESIZE_FORCE_RATIO) { + const double RATIO = beginSize.y / beginSize.x; + + if ((corner & (CORNER_TOPLEFT | CORNER_BOTTOMLEFT) && snaps & SNAP_LEFT) || (corner & (CORNER_TOPRIGHT | CORNER_BOTTOMRIGHT) && snaps & SNAP_RIGHT)) { + const double sizeY = size.x * RATIO; + if (corner & (CORNER_TOPLEFT | CORNER_TOPRIGHT)) + pos.y += size.y - sizeY; + size.y = sizeY; + } else if ((corner & (CORNER_TOPLEFT | CORNER_TOPRIGHT) && snaps & SNAP_UP) || (corner & (CORNER_BOTTOMLEFT | CORNER_BOTTOMRIGHT) && snaps & SNAP_DOWN)) { + const double sizeX = size.y / RATIO; + if (corner & (CORNER_TOPLEFT | CORNER_BOTTOMLEFT)) + pos.x += size.x - sizeX; + size.x = sizeX; + } + } +} + void IHyprLayout::onMouseMove(const Vector2D& mousePos) { if (g_pInputManager->currentlyDraggedWindow.expired()) return; @@ -418,6 +550,8 @@ void IHyprLayout::onMouseMove(const Vector2D& mousePos) { static auto PANIMATEMOUSE = CConfigValue("misc:animate_mouse_windowdragging"); static auto PANIMATE = CConfigValue("misc:animate_manual_resizes"); + static auto SNAPENABLED = CConfigValue("general:snap:enabled"); + const auto TIMERDELTA = std::chrono::duration_cast(std::chrono::high_resolution_clock::now() - TIMER).count(); const auto MSDELTA = std::chrono::duration_cast(std::chrono::high_resolution_clock::now() - MSTIMER).count(); const auto MSMONITOR = 1000.0 / g_pHyprRenderer->m_pMostHzMonitor->refreshRate; @@ -448,7 +582,13 @@ void IHyprLayout::onMouseMove(const Vector2D& mousePos) { if (g_pInputManager->dragMode == MBIND_MOVE) { - CBox wb = {m_vBeginDragPositionXY + DELTA, DRAGGINGWINDOW->m_vRealSize.goal()}; + Vector2D newPos = m_vBeginDragPositionXY + DELTA; + Vector2D newSize = DRAGGINGWINDOW->m_vRealSize.goal(); + + if (*SNAPENABLED && !DRAGGINGWINDOW->m_bDraggingTiled) + performSnap(newPos, newSize, DRAGGINGWINDOW, MBIND_MOVE, -1, m_vBeginDragSizeXY); + + CBox wb = {newPos, newSize}; wb.round(); if (*PANIMATEMOUSE) @@ -479,9 +619,11 @@ void IHyprLayout::onMouseMove(const Vector2D& mousePos) { else if (m_eGrabbedCorner == CORNER_BOTTOMLEFT) newSize = newSize + Vector2D(-DELTA.x, DELTA.y); - if ((m_vBeginDragSizeXY.x >= 1 && m_vBeginDragSizeXY.y >= 1) && - (g_pInputManager->dragMode == MBIND_RESIZE_FORCE_RATIO || - (!(g_pInputManager->dragMode == MBIND_RESIZE_BLOCK_RATIO) && DRAGGINGWINDOW->m_sWindowData.keepAspectRatio.valueOrDefault()))) { + eMouseBindMode mode = g_pInputManager->dragMode; + if (DRAGGINGWINDOW->m_sWindowData.keepAspectRatio.valueOrDefault() && mode != MBIND_RESIZE_BLOCK_RATIO) + mode = MBIND_RESIZE_FORCE_RATIO; + + if (m_vBeginDragSizeXY.x >= 1 && m_vBeginDragSizeXY.y >= 1 && mode == MBIND_RESIZE_FORCE_RATIO) { const float RATIO = m_vBeginDragSizeXY.y / m_vBeginDragSizeXY.x; @@ -510,6 +652,11 @@ void IHyprLayout::onMouseMove(const Vector2D& mousePos) { else if (m_eGrabbedCorner == CORNER_BOTTOMLEFT) newPos = newPos + Vector2D((m_vBeginDragSizeXY - newSize).x, 0.0); + if (*SNAPENABLED) { + performSnap(newPos, newSize, DRAGGINGWINDOW, mode, m_eGrabbedCorner, m_vBeginDragSizeXY); + newSize = newSize.clamp(MINSIZE, MAXSIZE); + } + CBox wb = {newPos, newSize}; wb.round(); diff --git a/src/layout/IHyprLayout.hpp b/src/layout/IHyprLayout.hpp index f9e2de0d..f1659ccd 100644 --- a/src/layout/IHyprLayout.hpp +++ b/src/layout/IHyprLayout.hpp @@ -18,11 +18,19 @@ struct SLayoutMessageHeader { enum eFullscreenMode : int8_t; enum eRectCorner { - CORNER_NONE = 0, - CORNER_TOPLEFT, - CORNER_TOPRIGHT, - CORNER_BOTTOMRIGHT, - CORNER_BOTTOMLEFT + CORNER_NONE = 0, + CORNER_TOPLEFT = (1 << 0), + CORNER_TOPRIGHT = (1 << 1), + CORNER_BOTTOMRIGHT = (1 << 2), + CORNER_BOTTOMLEFT = (1 << 3), +}; + +enum eSnapEdge { + SNAP_INVALID = 0, + SNAP_UP = (1 << 0), + SNAP_DOWN = (1 << 1), + SNAP_LEFT = (1 << 2), + SNAP_RIGHT = (1 << 3), }; enum eDirection { From 9df0f0b66c66706c9ce8cf9f80e834d5abfc1e96 Mon Sep 17 00:00:00 2001 From: Ikalco <73481042+ikalco@users.noreply.github.com> Date: Mon, 21 Oct 2024 10:09:14 -0500 Subject: [PATCH 0546/2181] renderer: fix floating window damage (#8182) --- src/events/Windows.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/events/Windows.cpp b/src/events/Windows.cpp index 21055f79..57a28948 100644 --- a/src/events/Windows.cpp +++ b/src/events/Windows.cpp @@ -687,6 +687,8 @@ void Events::listener_unmapWindow(void* owner, void* data) { g_pLayoutManager->getCurrentLayout()->onWindowRemoved(PWINDOW); + g_pHyprRenderer->damageWindow(PWINDOW); + // do this after onWindowRemoved because otherwise it'll think the window is invalid PWINDOW->m_bIsMapped = false; @@ -726,8 +728,6 @@ void Events::listener_unmapWindow(void* owner, void* data) { g_pCompositor->addToFadingOutSafe(PWINDOW); - g_pHyprRenderer->damageMonitor(g_pCompositor->getMonitorFromID(PWINDOW->m_iMonitorID)); - if (!PWINDOW->m_bX11DoesntWantBorders) // don't animate out if they weren't animated in. PWINDOW->m_vRealPosition = PWINDOW->m_vRealPosition.value() + Vector2D(0.01f, 0.01f); // it has to be animated, otherwise onWindowPostCreateClose will ignore it From 5e96d738e698f22969ca502d042d5751711c6d8a Mon Sep 17 00:00:00 2001 From: KAGEYAM4 <75798544+KAGEYAM4@users.noreply.github.com> Date: Tue, 22 Oct 2024 04:58:42 +0530 Subject: [PATCH 0547/2181] hyprpm: Add option to notify on fail and keep original notify (#8167) * Only generate notification on fail Hyprpm fail/pass notification are mutually exclusive. * Add option to notify on fail and keep original notify (#1) * Add option to notify on fail and keep original notify --------- Co-authored-by: KAGEYAM4 <75798544+KAGEYAM4@users.noreply.github.com> --------- Co-authored-by: littleblack111 --- hyprpm/src/main.cpp | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/hyprpm/src/main.cpp b/hyprpm/src/main.cpp index 67f14aed..55fb57e2 100644 --- a/hyprpm/src/main.cpp +++ b/hyprpm/src/main.cpp @@ -23,7 +23,8 @@ constexpr std::string_view HELP = R"#(┏ hyprpm, a Hyprland Plugin Manager ┃ ┣ Flags: ┃ -┣ --notify | -n → Send a hyprland notification for important events (e.g. load fail) +┣ --notify | -n → Send a hyprland notification for important events (including both successes and fail events) +┣ --notify-fail | -nn → Send a hyprland notification for fail events only ┣ --help | -h → Show this menu ┣ --verbose | -v → Enable too much logging ┣ --force | -f → Force an operation ignoring checks (e.g. update -f) @@ -43,7 +44,7 @@ int main(int argc, char** argv, char** envp) { } std::vector command; - bool notify = false, verbose = false, force = false, noShallow = false; + bool notify = false, notifyFail = false, verbose = false, force = false, noShallow = false; for (int i = 1; i < argc; ++i) { if (ARGS[i].starts_with("-")) { @@ -52,6 +53,8 @@ int main(int argc, char** argv, char** envp) { return 0; } else if (ARGS[i] == "--notify" || ARGS[i] == "-n") { notify = true; + } else if (ARGS[i] == "--notify-fail" || ARGS[i] == "-nn") { + notifyFail = notify = true; } else if (ARGS[i] == "--verbose" || ARGS[i] == "-v") { verbose = true; } else if (ARGS[i] == "--no-shallow" || ARGS[i] == "-s") { @@ -155,7 +158,7 @@ int main(int argc, char** argv, char** envp) { break; default: break; } - } else if (notify) { + } else if (notify && !notifyFail) { g_pPluginManager->notify(ICON_OK, 0, 4000, "[hyprpm] Loaded plugins"); } } else if (command[0] == "list") { From 29997ef4ba8ef0a80390e80199998d1390177454 Mon Sep 17 00:00:00 2001 From: Vaxry Date: Tue, 22 Oct 2024 21:34:15 +0100 Subject: [PATCH 0548/2181] default/config: improve default animations objectively better --- example/hyprland.conf | 30 ++++++++++++++++++++++-------- src/config/defaultConfig.hpp | 30 ++++++++++++++++++++++-------- 2 files changed, 44 insertions(+), 16 deletions(-) diff --git a/example/hyprland.conf b/example/hyprland.conf index 012446f3..f94cb1d1 100644 --- a/example/hyprland.conf +++ b/example/hyprland.conf @@ -103,18 +103,32 @@ decoration { # https://wiki.hyprland.org/Configuring/Variables/#animations animations { - enabled = true + enabled = yes, please :) # Default animations, see https://wiki.hyprland.org/Configuring/Animations/ for more - bezier = myBezier, 0.05, 0.9, 0.1, 1.05 + bezier = easeOutQuint,0.23,1,0.32,1 + bezier = easeInOutCubic,0.65,0.05,0.36,1 + bezier = linear,0,0,1,1 + bezier = almostLinear,0.5,0.5,0.75,1.0 + bezier = quick,0.15,0,0.1,1 - animation = windows, 1, 7, myBezier - animation = windowsOut, 1, 7, default, popin 80% - animation = border, 1, 10, default - animation = borderangle, 1, 8, default - animation = fade, 1, 7, default - animation = workspaces, 1, 6, default + animation = global, 1, 10, default + animation = border, 1, 5.39, easeOutQuint + animation = windows, 1, 4.79, easeOutQuint + animation = windowsIn, 1, 4.1, easeOutQuint, popin 87% + animation = windowsOut, 1, 1.49, linear, popin 87% + animation = fadeIn, 1, 1.73, almostLinear + animation = fadeOut, 1, 1.46, almostLinear + animation = fade, 1, 3.03, quick + animation = layers, 1, 3.81, easeOutQuint + animation = layersIn, 1, 4, easeOutQuint, fade + animation = layersOut, 1, 1.5, linear, fade + animation = fadeLayersIn, 1, 1.79, almostLinear + animation = fadeLayersOut, 1, 1.39, almostLinear + animation = workspaces, 1, 1.94, almostLinear, fade + animation = workspacesIn, 1, 1.21, almostLinear, fade + animation = workspacesOut, 1, 1.94, almostLinear, fade } # Ref https://wiki.hyprland.org/Configuring/Workspace-Rules/ diff --git a/src/config/defaultConfig.hpp b/src/config/defaultConfig.hpp index a5d759de..4a33ec91 100644 --- a/src/config/defaultConfig.hpp +++ b/src/config/defaultConfig.hpp @@ -116,18 +116,32 @@ decoration { # https://wiki.hyprland.org/Configuring/Variables/#animations animations { - enabled = true + enabled = yes, please :) # Default animations, see https://wiki.hyprland.org/Configuring/Animations/ for more - bezier = myBezier, 0.05, 0.9, 0.1, 1.05 + bezier = easeOutQuint,0.23,1,0.32,1 + bezier = easeInOutCubic,0.65,0.05,0.36,1 + bezier = linear,0,0,1,1 + bezier = almostLinear,0.5,0.5,0.75,1.0 + bezier = quick,0.15,0,0.1,1 - animation = windows, 1, 7, myBezier - animation = windowsOut, 1, 7, default, popin 80% - animation = border, 1, 10, default - animation = borderangle, 1, 8, default - animation = fade, 1, 7, default - animation = workspaces, 1, 6, default + animation = global, 1, 10, default + animation = border, 1, 5.39, easeOutQuint + animation = windows, 1, 4.79, easeOutQuint + animation = windowsIn, 1, 4.1, easeOutQuint, popin 87% + animation = windowsOut, 1, 1.49, linear, popin 87% + animation = fadeIn, 1, 1.73, almostLinear + animation = fadeOut, 1, 1.46, almostLinear + animation = fade, 1, 3.03, quick + animation = layers, 1, 3.81, easeOutQuint + animation = layersIn, 1, 4, easeOutQuint, fade + animation = layersOut, 1, 1.5, linear, fade + animation = fadeLayersIn, 1, 1.79, almostLinear + animation = fadeLayersOut, 1, 1.39, almostLinear + animation = workspaces, 1, 1.94, almostLinear, fade + animation = workspacesIn, 1, 1.21, almostLinear, fade + animation = workspacesOut, 1, 1.94, almostLinear, fade } # Ref https://wiki.hyprland.org/Configuring/Workspace-Rules/ From 2b6ff6837e81a3b459f2f3cc366830c420a7a62e Mon Sep 17 00:00:00 2001 From: Aqa-Ib Date: Tue, 22 Oct 2024 23:51:25 +0000 Subject: [PATCH 0549/2181] groups: add group_on_movetoworkspace (#8159) --- src/Compositor.cpp | 51 +++++++++++++++++++++++-------- src/config/ConfigDescriptions.hpp | 6 ++++ src/config/ConfigManager.cpp | 1 + src/layout/IHyprLayout.cpp | 5 +-- 4 files changed, 49 insertions(+), 14 deletions(-) diff --git a/src/Compositor.cpp b/src/Compositor.cpp index b23b3194..313d57ac 100644 --- a/src/Compositor.cpp +++ b/src/Compositor.cpp @@ -34,6 +34,7 @@ #include "render/Renderer.hpp" #include "xwayland/XWayland.hpp" #include "helpers/ByteOperations.hpp" +#include "render/decorations/CHyprGroupBarDecoration.hpp" #include #include @@ -2748,21 +2749,47 @@ void CCompositor::moveWindowToWorkspaceSafe(PHLWINDOW pWindow, PHLWORKSPACE pWor if (FULLSCREEN) setWindowFullscreenInternal(pWindow, FSMODE_NONE); - if (!pWindow->m_bIsFloating) { + const PHLWINDOW pFirstWindowOnWorkspace = g_pCompositor->getFirstWindowOnWorkspace(pWorkspace->m_iID); + const int visibleWindowsOnWorkspace = g_pCompositor->getWindowsOnWorkspace(pWorkspace->m_iID, std::nullopt, true); + const auto PWINDOWMONITOR = g_pCompositor->getMonitorFromID(pWindow->m_iMonitorID); + const auto POSTOMON = pWindow->m_vRealPosition.goal() - PWINDOWMONITOR->vecPosition; + const auto PWORKSPACEMONITOR = g_pCompositor->getMonitorFromID(pWorkspace->m_iMonitorID); + + if (!pWindow->m_bIsFloating) g_pLayoutManager->getCurrentLayout()->onWindowRemovedTiling(pWindow); - pWindow->moveToWorkspace(pWorkspace); - pWindow->m_iMonitorID = pWorkspace->m_iMonitorID; - g_pLayoutManager->getCurrentLayout()->onWindowCreatedTiling(pWindow); + + pWindow->moveToWorkspace(pWorkspace); + pWindow->m_iMonitorID = pWorkspace->m_iMonitorID; + + static auto PGROUPONMOVETOWORKSPACE = CConfigValue("group:group_on_movetoworkspace"); + if (*PGROUPONMOVETOWORKSPACE && visibleWindowsOnWorkspace == 1 && pFirstWindowOnWorkspace && pFirstWindowOnWorkspace != pWindow && + pFirstWindowOnWorkspace->m_sGroupData.pNextWindow.lock() && pWindow->canBeGroupedInto(pFirstWindowOnWorkspace)) { + + pWindow->m_bIsFloating = pFirstWindowOnWorkspace->m_bIsFloating; // match the floating state. Needed to group tiled into floated and vice versa. + if (!pWindow->m_sGroupData.pNextWindow.expired()) { + PHLWINDOW next = pWindow->m_sGroupData.pNextWindow.lock(); + while (next != pWindow) { + next->m_bIsFloating = pFirstWindowOnWorkspace->m_bIsFloating; // match the floating state of group members + next = next->m_sGroupData.pNextWindow.lock(); + } + } + + static auto USECURRPOS = CConfigValue("group:insert_after_current"); + (*USECURRPOS ? pFirstWindowOnWorkspace : pFirstWindowOnWorkspace->getGroupTail())->insertWindowToGroup(pWindow); + + pFirstWindowOnWorkspace->setGroupCurrent(pWindow); + pWindow->updateWindowDecos(); + g_pLayoutManager->getCurrentLayout()->recalculateWindow(pWindow); + + if (!pWindow->getDecorationByType(DECORATION_GROUPBAR)) + pWindow->addWindowDeco(std::make_unique(pWindow)); + } else { - const auto PWINDOWMONITOR = g_pCompositor->getMonitorFromID(pWindow->m_iMonitorID); - const auto POSTOMON = pWindow->m_vRealPosition.goal() - PWINDOWMONITOR->vecPosition; + if (!pWindow->m_bIsFloating) + g_pLayoutManager->getCurrentLayout()->onWindowCreatedTiling(pWindow); - const auto PWORKSPACEMONITOR = g_pCompositor->getMonitorFromID(pWorkspace->m_iMonitorID); - - pWindow->moveToWorkspace(pWorkspace); - pWindow->m_iMonitorID = pWorkspace->m_iMonitorID; - - pWindow->m_vRealPosition = POSTOMON + PWORKSPACEMONITOR->vecPosition; + if (pWindow->m_bIsFloating) + pWindow->m_vRealPosition = POSTOMON + PWORKSPACEMONITOR->vecPosition; } pWindow->updateToplevel(); diff --git a/src/config/ConfigDescriptions.hpp b/src/config/ConfigDescriptions.hpp index 7e2dd1be..7910e865 100644 --- a/src/config/ConfigDescriptions.hpp +++ b/src/config/ConfigDescriptions.hpp @@ -808,6 +808,12 @@ inline static const std::vector CONFIG_OPTIONS = { .type = CONFIG_OPTION_BOOL, .data = SConfigOptionDescription::SBoolData{false}, }, + SConfigOptionDescription{ + .value = "group:group_on_movetoworkspace", + .description = "whether using movetoworkspace[silent] will merge the window into the workspace's solitary unlocked group", + .type = CONFIG_OPTION_BOOL, + .data = SConfigOptionDescription::SBoolData{false}, + }, /* * group:groupbar: diff --git a/src/config/ConfigManager.cpp b/src/config/ConfigManager.cpp index 1dbd248d..8237fd44 100644 --- a/src/config/ConfigManager.cpp +++ b/src/config/ConfigManager.cpp @@ -383,6 +383,7 @@ CConfigManager::CConfigManager() { m_pConfig->addConfigValue("group:merge_floated_into_tiled_on_groupbar", Hyprlang::INT{0}); m_pConfig->addConfigValue("group:auto_group", Hyprlang::INT{1}); m_pConfig->addConfigValue("group:drag_into_group", Hyprlang::INT{1}); + m_pConfig->addConfigValue("group:group_on_movetoworkspace", Hyprlang::INT{0}); m_pConfig->addConfigValue("group:groupbar:enabled", Hyprlang::INT{1}); m_pConfig->addConfigValue("group:groupbar:font_family", {STRVAL_EMPTY}); m_pConfig->addConfigValue("group:groupbar:font_size", Hyprlang::INT{8}); diff --git a/src/layout/IHyprLayout.cpp b/src/layout/IHyprLayout.cpp index 95919c65..655f2341 100644 --- a/src/layout/IHyprLayout.cpp +++ b/src/layout/IHyprLayout.cpp @@ -194,8 +194,9 @@ bool IHyprLayout::onWindowCreatedAutoGroup(PHLWINDOW pWindow) { denied = true; if (*PAUTOGROUP // check if auto_group is enabled. - && OPENINGON->m_sGroupData.pNextWindow.lock() // check if OPENINGON is a group. + && OPENINGON // this shouldn't be 0, but honestly, better safe than sorry. && OPENINGON != pWindow // prevent freeze when the "group set" window rule makes the new window to be already a group. + && OPENINGON->m_sGroupData.pNextWindow.lock() // check if OPENINGON is a group. && pWindow->canBeGroupedInto(OPENINGON) // check if the new window can be grouped into OPENINGON. && !g_pXWaylandManager->shouldBeFloated(pWindow) // don't group child windows. Fix for floated groups. Tiled groups don't need this because we check if !denied. && !denied) { // don't group a new floated window into a tiled group (for convenience). @@ -352,7 +353,7 @@ void IHyprLayout::onEndDragWindow() { DRAGGINGWINDOW->m_bDraggingTiled = false; } - if (DRAGGINGWINDOW->m_sGroupData.pNextWindow.lock()) { + if (DRAGGINGWINDOW->m_sGroupData.pNextWindow) { std::vector members; PHLWINDOW curr = DRAGGINGWINDOW->getGroupHead(); do { From 6e0aadc585c6d9fdaaebfa5853adbf9610897c82 Mon Sep 17 00:00:00 2001 From: chitoroagad Date: Tue, 22 Oct 2024 18:05:30 +0100 Subject: [PATCH 0550/2181] updated flake.lock --- flake.lock | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/flake.lock b/flake.lock index 0a12fe0a..beb56b5c 100644 --- a/flake.lock +++ b/flake.lock @@ -16,11 +16,11 @@ ] }, "locked": { - "lastModified": 1728902391, - "narHash": "sha256-44bnoY0nAvbBQ/lVjmn511yL39Sv7SknV0BDxn34P3Q=", + "lastModified": 1729527199, + "narHash": "sha256-D5/YksfRga8Akd04ZtIkuYSIOjXVrAzQIQBSeplokzU=", "owner": "hyprwm", "repo": "aquamarine", - "rev": "9874e08eec85b5542ca22494e127b0cdce46b786", + "rev": "8d732fa8aff8b12ef2b1e2f00fc8153e41312b72", "type": "github" }, "original": { @@ -189,11 +189,11 @@ }, "nixpkgs": { "locked": { - "lastModified": 1728888510, - "narHash": "sha256-nsNdSldaAyu6PE3YUA+YQLqUDJh+gRbBooMMekZJwvI=", + "lastModified": 1729413321, + "narHash": "sha256-I4tuhRpZFa6Fu6dcH9Dlo5LlH17peT79vx1y1SpeKt0=", "owner": "NixOS", "repo": "nixpkgs", - "rev": "a3c0b3b21515f74fd2665903d4ce6bc4dc81c77c", + "rev": "1997e4aa514312c1af7e2bda7fad1644e778ff26", "type": "github" }, "original": { @@ -229,11 +229,11 @@ "nixpkgs-stable": "nixpkgs-stable" }, "locked": { - "lastModified": 1728778939, - "narHash": "sha256-WybK5E3hpGxtCYtBwpRj1E9JoiVxe+8kX83snTNaFHE=", + "lastModified": 1729104314, + "narHash": "sha256-pZRZsq5oCdJt3upZIU4aslS9XwFJ+/nVtALHIciX/BI=", "owner": "cachix", "repo": "git-hooks.nix", - "rev": "ff68f91754be6f3427e4986d7949e6273659be1d", + "rev": "3c3e88f0f544d6bb54329832616af7eb971b6be6", "type": "github" }, "original": { From cdac64970e894c3211d94da8925fbf905b52a594 Mon Sep 17 00:00:00 2001 From: Honkazel <169346573+Honkazel@users.noreply.github.com> Date: Thu, 24 Oct 2024 01:32:39 +0500 Subject: [PATCH 0551/2181] Makefile: fix legacyrendererdebug typo (#8214) --- Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Makefile b/Makefile index 98267eea..7cf21119 100644 --- a/Makefile +++ b/Makefile @@ -6,7 +6,7 @@ legacyrenderer: legacyrendererdebug: cmake --no-warn-unused-cli -DCMAKE_BUILD_TYPE:STRING=Debug -DCMAKE_INSTALL_PREFIX:STRING=${PREFIX} -DLEGACY_RENDERER:BOOL=true -S . -B ./build - cmake --build ./build --config Release --target all -j`nproc 2>/dev/null || getconf NPROCESSORS_CONF` + cmake --build ./build --config Debug --target all -j`nproc 2>/dev/null || getconf NPROCESSORS_CONF` release: cmake --no-warn-unused-cli -DCMAKE_BUILD_TYPE:STRING=Release -DCMAKE_INSTALL_PREFIX:STRING=${PREFIX} -S . -B ./build From f603a22af0c8890b9742d761d44f0b595740f5b1 Mon Sep 17 00:00:00 2001 From: Honkazel <169346573+Honkazel@users.noreply.github.com> Date: Thu, 24 Oct 2024 17:12:41 +0500 Subject: [PATCH 0552/2181] internal: Remove some unused lambda captures (#8218) --- src/devices/Tablet.cpp | 2 +- src/managers/TokenManager.cpp | 4 ++-- src/managers/input/InputManager.cpp | 2 +- src/protocols/DataDeviceWlr.cpp | 4 ++-- src/protocols/PrimarySelection.cpp | 2 +- 5 files changed, 7 insertions(+), 7 deletions(-) diff --git a/src/devices/Tablet.cpp b/src/devices/Tablet.cpp index 71ca8991..99e436fb 100644 --- a/src/devices/Tablet.cpp +++ b/src/devices/Tablet.cpp @@ -197,7 +197,7 @@ CTabletPad::CTabletPad(SP pad_) : pad(pad_) { }); }); - listeners.attach = pad->events.attach.registerListener([this](std::any d) { + listeners.attach = pad->events.attach.registerListener([](std::any d) { ; // TODO: this doesn't do anything in aq atm }); diff --git a/src/managers/TokenManager.cpp b/src/managers/TokenManager.cpp index cee97c1c..5efa2eb8 100644 --- a/src/managers/TokenManager.cpp +++ b/src/managers/TokenManager.cpp @@ -34,7 +34,7 @@ SP CTokenManager::getToken(const std::string& uuid) { // cleanup expired tokens const auto NOW = std::chrono::steady_clock::now(); - std::erase_if(m_mTokens, [this, &NOW](const auto& el) { return el.second->expiresAt < NOW; }); + std::erase_if(m_mTokens, [&NOW](const auto& el) { return el.second->expiresAt < NOW; }); if (!m_mTokens.contains(uuid)) return {}; @@ -46,4 +46,4 @@ void CTokenManager::removeToken(SP token) { if (!token) return; m_mTokens.erase(token->uuid); -} \ No newline at end of file +} diff --git a/src/managers/input/InputManager.cpp b/src/managers/input/InputManager.cpp index 196f0b71..6f7d8017 100644 --- a/src/managers/input/InputManager.cpp +++ b/src/managers/input/InputManager.cpp @@ -905,7 +905,7 @@ void CInputManager::setupKeyboard(SP keeb) { keeb.get()); keeb->keyboardEvents.keymap.registerStaticListener( - [this](void* owner, std::any data) { + [](void* owner, std::any data) { auto PKEEB = ((IKeyboard*)owner)->self.lock(); const auto LAYOUT = PKEEB->getActiveLayout(); diff --git a/src/protocols/DataDeviceWlr.cpp b/src/protocols/DataDeviceWlr.cpp index 69e28772..baf0a299 100644 --- a/src/protocols/DataDeviceWlr.cpp +++ b/src/protocols/DataDeviceWlr.cpp @@ -112,7 +112,7 @@ CWLRDataDevice::CWLRDataDevice(SP resource_) : resourc resource->setDestroy([this](CZwlrDataControlDeviceV1* r) { PROTO::dataWlr->destroyResource(this); }); resource->setOnDestroy([this](CZwlrDataControlDeviceV1* r) { PROTO::dataWlr->destroyResource(this); }); - resource->setSetSelection([this](CZwlrDataControlDeviceV1* r, wl_resource* sourceR) { + resource->setSetSelection([](CZwlrDataControlDeviceV1* r, wl_resource* sourceR) { auto source = sourceR ? CWLRDataSource::fromResource(sourceR) : CSharedPointer{}; if (!source) { LOGM(LOG, "wlr reset selection received"); @@ -129,7 +129,7 @@ CWLRDataDevice::CWLRDataDevice(SP resource_) : resourc g_pSeatManager->setCurrentSelection(source); }); - resource->setSetPrimarySelection([this](CZwlrDataControlDeviceV1* r, wl_resource* sourceR) { + resource->setSetPrimarySelection([](CZwlrDataControlDeviceV1* r, wl_resource* sourceR) { auto source = sourceR ? CWLRDataSource::fromResource(sourceR) : CSharedPointer{}; if (!source) { LOGM(LOG, "wlr reset primary selection received"); diff --git a/src/protocols/PrimarySelection.cpp b/src/protocols/PrimarySelection.cpp index f1db2d65..7602a466 100644 --- a/src/protocols/PrimarySelection.cpp +++ b/src/protocols/PrimarySelection.cpp @@ -113,7 +113,7 @@ CPrimarySelectionDevice::CPrimarySelectionDevice(SPsetDestroy([this](CZwpPrimarySelectionDeviceV1* r) { PROTO::primarySelection->destroyResource(this); }); resource->setOnDestroy([this](CZwpPrimarySelectionDeviceV1* r) { PROTO::primarySelection->destroyResource(this); }); - resource->setSetSelection([this](CZwpPrimarySelectionDeviceV1* r, wl_resource* sourceR, uint32_t serial) { + resource->setSetSelection([](CZwpPrimarySelectionDeviceV1* r, wl_resource* sourceR, uint32_t serial) { static auto PPRIMARYSEL = CConfigValue("misc:middle_click_paste"); if (!*PPRIMARYSEL) { From 7f46680ab16e8f67000a09d20fc7ba41e211f3ef Mon Sep 17 00:00:00 2001 From: czlabinger <118806077+czlabinger@users.noreply.github.com> Date: Thu, 24 Oct 2024 15:01:08 +0200 Subject: [PATCH 0553/2181] hyprctl: add caps/num lock state for keyboards (#8145) --------- Co-authored-by: Behzad --- src/debug/HyprCtl.cpp | 21 +++++++++++++++++---- 1 file changed, 17 insertions(+), 4 deletions(-) diff --git a/src/debug/HyprCtl.cpp b/src/debug/HyprCtl.cpp index e09fb529..82290f94 100644 --- a/src/debug/HyprCtl.cpp +++ b/src/debug/HyprCtl.cpp @@ -549,6 +549,15 @@ std::string configErrorsRequest(eHyprCtlOutputFormat format, std::string request std::string devicesRequest(eHyprCtlOutputFormat format, std::string request) { std::string result = ""; + auto getModState = [](SP keyboard, const char* xkbModName) -> bool { + auto IDX = xkb_keymap_mod_get_index(keyboard->xkbKeymap, xkbModName); + + if (IDX == XKB_MOD_INVALID) + return false; + + return (keyboard->modifiersState.locked & (1 << IDX)) > 0; + }; + if (format == eHyprCtlOutputFormat::FORMAT_JSON) { result += "{\n"; result += "\"mice\": [\n"; @@ -580,11 +589,13 @@ std::string devicesRequest(eHyprCtlOutputFormat format, std::string request) { "variant": "{}", "options": "{}", "active_keymap": "{}", + "capsLock": {}, + "numLock": {}, "main": {} }},)#", (uintptr_t)k.get(), escapeJSONStrings(k->hlName), escapeJSONStrings(k->currentRules.rules), escapeJSONStrings(k->currentRules.model), escapeJSONStrings(k->currentRules.layout), escapeJSONStrings(k->currentRules.variant), escapeJSONStrings(k->currentRules.options), escapeJSONStrings(KM), - (k->active ? "true" : "false")); + (getModState(k, XKB_MOD_NAME_CAPS) ? "true" : "false"), (getModState(k, XKB_MOD_NAME_NUM) ? "true" : "false"), (k->active ? "true" : "false")); } trimTrailingComma(result); @@ -668,9 +679,11 @@ std::string devicesRequest(eHyprCtlOutputFormat format, std::string request) { for (auto const& k : g_pInputManager->m_vKeyboards) { const auto KM = k->getActiveLayout(); - result += std::format("\tKeyboard at {:x}:\n\t\t{}\n\t\t\trules: r \"{}\", m \"{}\", l \"{}\", v \"{}\", o \"{}\"\n\t\t\tactive keymap: {}\n\t\t\tmain: {}\n", - (uintptr_t)k.get(), k->hlName, k->currentRules.rules, k->currentRules.model, k->currentRules.layout, k->currentRules.variant, - k->currentRules.options, KM, (k->active ? "yes" : "no")); + result += + std::format("\tKeyboard at {:x}:\n\t\t{}\n\t\t\trules: r \"{}\", m \"{}\", l \"{}\", v \"{}\", o \"{}\"\n\t\t\tactive keymap: {}\n\t\t\tcapsLock: " + "{}\n\t\t\tnumLock: {}\n\t\t\tmain: {}\n", + (uintptr_t)k.get(), k->hlName, k->currentRules.rules, k->currentRules.model, k->currentRules.layout, k->currentRules.variant, k->currentRules.options, + KM, (getModState(k, XKB_MOD_NAME_CAPS) ? "yes" : "no"), (getModState(k, XKB_MOD_NAME_NUM) ? "yes" : "no"), (k->active ? "yes" : "no")); } result += "\n\nTablets:\n"; From 3cec45d82113051d35e846e5d80719d8ea0f7002 Mon Sep 17 00:00:00 2001 From: izmyname <135810812+izmyname@users.noreply.github.com> Date: Thu, 24 Oct 2024 19:50:53 +0500 Subject: [PATCH 0554/2181] Improve hyprland-session.service (#8225) --- example/hyprland-session.service | 1 + 1 file changed, 1 insertion(+) diff --git a/example/hyprland-session.service b/example/hyprland-session.service index 7d33f5b3..b6f0b55b 100644 --- a/example/hyprland-session.service +++ b/example/hyprland-session.service @@ -10,5 +10,6 @@ After=graphical-session-pre.target Type=notify ExecStart=/usr/bin/Hyprland ExecStop=/usr/bin/hyprctl dispatch exit +ExecStopPost=/usr/bin/systemctl --user unset-environment DISPLAY WAYLAND_DISPLAY HYPRLAND_INSTANCE_SIGNATURE XDG_CURRENT_DESKTOP Restart=on-failure Slice=session.slice From f0e023bff2f2a25ffe5ed3166f55f7274d17c6bc Mon Sep 17 00:00:00 2001 From: Tom Englund Date: Fri, 25 Oct 2024 12:26:48 +0200 Subject: [PATCH 0555/2181] security-context: avoid UB in C macro (#8229) to safely use wl_container_of with a class the class has to be no virtual functions, no inheritance, and uniform access control (e.g all public) work around this by putting this into a destroywrapper struct. --- src/protocols/SecurityContext.cpp | 12 ++++++++---- src/protocols/SecurityContext.hpp | 12 +++++++++--- 2 files changed, 17 insertions(+), 7 deletions(-) diff --git a/src/protocols/SecurityContext.cpp b/src/protocols/SecurityContext.cpp index b42c3a97..13428b91 100644 --- a/src/protocols/SecurityContext.cpp +++ b/src/protocols/SecurityContext.cpp @@ -22,7 +22,8 @@ SP CSecurityContextSandboxedClient::create(int } static void onSecurityContextClientDestroy(wl_listener* l, void* d) { - CSecurityContextSandboxedClient* client = wl_container_of(l, client, destroyListener); + CSecurityContextSandboxedClientDestroyWrapper* wrap = wl_container_of(l, wrap, listener); + CSecurityContextSandboxedClient* client = wrap->parent; client->onDestroy(); } @@ -31,12 +32,15 @@ CSecurityContextSandboxedClient::CSecurityContextSandboxedClient(int clientFD_) if (!client) return; - destroyListener.notify = ::onSecurityContextClientDestroy; - wl_client_add_destroy_late_listener(client, &destroyListener); + wl_list_init(&destroyListener.listener.link); + destroyListener.listener.notify = ::onSecurityContextClientDestroy; + destroyListener.parent = this; + wl_client_add_destroy_late_listener(client, &destroyListener.listener); } CSecurityContextSandboxedClient::~CSecurityContextSandboxedClient() { - wl_list_remove(&destroyListener.link); + wl_list_remove(&destroyListener.listener.link); + wl_list_init(&destroyListener.listener.link); close(clientFD); } diff --git a/src/protocols/SecurityContext.hpp b/src/protocols/SecurityContext.hpp index 76313bcf..63f58bde 100644 --- a/src/protocols/SecurityContext.hpp +++ b/src/protocols/SecurityContext.hpp @@ -37,14 +37,20 @@ class CSecurityContextManagerResource { SP resource; }; +class CSecurityContextSandboxedClient; +struct CSecurityContextSandboxedClientDestroyWrapper { + wl_listener listener; + CSecurityContextSandboxedClient* parent = nullptr; +}; + class CSecurityContextSandboxedClient { public: static SP create(int clientFD); ~CSecurityContextSandboxedClient(); - void onDestroy(); + void onDestroy(); - wl_listener destroyListener; + CSecurityContextSandboxedClientDestroyWrapper destroyListener; private: CSecurityContextSandboxedClient(int clientFD_); @@ -81,4 +87,4 @@ class CSecurityContextProtocol : public IWaylandProtocol { namespace PROTO { inline UP securityContext; -}; \ No newline at end of file +}; From e5384774a8258e44cc7f7b690ce4f6ad1f92b562 Mon Sep 17 00:00:00 2001 From: izmyname <135810812+izmyname@users.noreply.github.com> Date: Sat, 26 Oct 2024 01:38:59 +0500 Subject: [PATCH 0556/2181] example/hyprland-session.service: add support for xdg autostart (#8230) --- example/hyprland-session.service | 1 + 1 file changed, 1 insertion(+) diff --git a/example/hyprland-session.service b/example/hyprland-session.service index b6f0b55b..3089a961 100644 --- a/example/hyprland-session.service +++ b/example/hyprland-session.service @@ -3,6 +3,7 @@ Description=Hyprland - Tiling compositor with the looks Documentation=man:Hyprland(1) BindsTo=graphical-session.target Before=graphical-session.target +Wants=xdg-desktop-autostart.target Wants=graphical-session-pre.target After=graphical-session-pre.target From d5689bb53935ff1adbbfc9fdf5b1f542ce39efb2 Mon Sep 17 00:00:00 2001 From: Vaxry Date: Sat, 26 Oct 2024 02:06:13 +0100 Subject: [PATCH 0557/2181] internal: cleanup CMonitor usage and fix a few ref hogs ref #8221 --- src/Compositor.cpp | 8 +++---- src/Compositor.hpp | 6 ++--- src/config/ConfigManager.cpp | 2 +- src/config/ConfigManager.hpp | 2 +- src/debug/HyprDebugOverlay.hpp | 8 +++---- src/helpers/Monitor.cpp | 8 +++---- src/helpers/Monitor.hpp | 2 +- src/managers/PointerManager.cpp | 16 ++++++------- src/managers/PointerManager.hpp | 22 +++++++++--------- src/protocols/CTMControl.cpp | 2 +- src/protocols/CTMControl.hpp | 2 +- src/protocols/DRMLease.cpp | 6 ++--- src/protocols/DRMLease.hpp | 10 ++++----- src/protocols/LinuxDMABUF.cpp | 20 ++++++++--------- src/protocols/LinuxDMABUF.hpp | 12 +++++----- src/protocols/OutputManagement.cpp | 2 +- src/protocols/OutputManagement.hpp | 2 +- src/protocols/PresentationTime.cpp | 6 ++--- src/protocols/PresentationTime.hpp | 6 ++--- src/protocols/VirtualPointer.cpp | 4 ++-- src/protocols/VirtualPointer.hpp | 12 +++++----- src/protocols/XDGOutput.cpp | 2 +- src/protocols/XDGOutput.hpp | 4 ++-- src/protocols/core/Compositor.cpp | 6 ++--- src/protocols/core/Compositor.hpp | 8 +++---- src/protocols/core/Output.cpp | 4 ++-- src/protocols/core/Output.hpp | 8 +++---- src/render/OpenGL.hpp | 36 +++++++++++++++--------------- src/render/Renderer.cpp | 4 ++-- src/render/Renderer.hpp | 4 ++-- 30 files changed, 116 insertions(+), 118 deletions(-) diff --git a/src/Compositor.cpp b/src/Compositor.cpp index 313d57ac..743895aa 100644 --- a/src/Compositor.cpp +++ b/src/Compositor.cpp @@ -750,7 +750,7 @@ PHLMONITOR CCompositor::getMonitorFromCursor() { } PHLMONITOR CCompositor::getMonitorFromVector(const Vector2D& point) { - SP mon; + PHLMONITOR mon; for (auto const& m : m_vMonitors) { if (CBox{m->vecPosition, m->vecSize}.containsPoint(point)) { mon = m; @@ -759,8 +759,8 @@ PHLMONITOR CCompositor::getMonitorFromVector(const Vector2D& point) { } if (!mon) { - float bestDistance = 0.f; - SP pBestMon; + float bestDistance = 0.f; + PHLMONITOR pBestMon; for (auto const& m : m_vMonitors) { float dist = vecToRectDistanceSquared(point, m->vecPosition, m->vecPosition + m->vecSize); @@ -3008,7 +3008,7 @@ PHLWINDOW CCompositor::windowForCPointer(CWindow* pWindow) { return {}; } -static void checkDefaultCursorWarp(SP monitor) { +static void checkDefaultCursorWarp(PHLMONITOR monitor) { static auto PCURSORMONITOR = CConfigValue("cursor:default_monitor"); static bool cursorDefaultDone = false; static bool firstLaunch = true; diff --git a/src/Compositor.hpp b/src/Compositor.hpp index 7fbd32e8..208b6ecf 100644 --- a/src/Compositor.hpp +++ b/src/Compositor.hpp @@ -59,8 +59,8 @@ class CCompositor { std::string m_szInstancePath = ""; std::string m_szCurrentSplash = "error"; - std::vector> m_vMonitors; - std::vector> m_vRealMonitors; // for all monitors, even those turned off + std::vector m_vMonitors; + std::vector m_vRealMonitors; // for all monitors, even those turned off std::vector m_vWindows; std::vector m_vLayers; std::vector m_vWorkspaces; @@ -80,7 +80,7 @@ class CCompositor { WP m_pLastFocus; PHLWINDOWREF m_pLastWindow; - WP m_pLastMonitor; + PHLMONITORREF m_pLastMonitor; std::vector m_vWindowFocusHistory; // first element is the most recently focused. diff --git a/src/config/ConfigManager.cpp b/src/config/ConfigManager.cpp index 8237fd44..e2dc4b0f 100644 --- a/src/config/ConfigManager.cpp +++ b/src/config/ConfigManager.cpp @@ -1087,7 +1087,7 @@ std::string CConfigManager::getDeviceString(const std::string& dev, const std::s return VAL; } -SMonitorRule CConfigManager::getMonitorRuleFor(const SP PMONITOR) { +SMonitorRule CConfigManager::getMonitorRuleFor(const PHLMONITOR PMONITOR) { auto applyWlrOutputConfig = [PMONITOR](SMonitorRule rule) -> SMonitorRule { const auto CONFIG = PROTO::outputManagement->getOutputStateFor(PMONITOR); diff --git a/src/config/ConfigManager.hpp b/src/config/ConfigManager.hpp index e9ed2d64..cf053daa 100644 --- a/src/config/ConfigManager.hpp +++ b/src/config/ConfigManager.hpp @@ -169,7 +169,7 @@ class CConfigManager { static std::string getMainConfigPath(); const std::string getConfigString(); - SMonitorRule getMonitorRuleFor(const SP); + SMonitorRule getMonitorRuleFor(const PHLMONITOR); SWorkspaceRule getWorkspaceRuleFor(PHLWORKSPACE workspace); std::string getDefaultWorkspaceFor(const std::string&); diff --git a/src/debug/HyprDebugOverlay.hpp b/src/debug/HyprDebugOverlay.hpp index 19b9120a..89d1d606 100644 --- a/src/debug/HyprDebugOverlay.hpp +++ b/src/debug/HyprDebugOverlay.hpp @@ -38,12 +38,12 @@ class CHyprDebugOverlay { void frameData(PHLMONITOR); private: - std::map m_mMonitorOverlays; + std::map m_mMonitorOverlays; - cairo_surface_t* m_pCairoSurface = nullptr; - cairo_t* m_pCairo = nullptr; + cairo_surface_t* m_pCairoSurface = nullptr; + cairo_t* m_pCairo = nullptr; - SP m_pTexture; + SP m_pTexture; friend class CHyprMonitorDebugOverlay; friend class CHyprRenderer; diff --git a/src/helpers/Monitor.cpp b/src/helpers/Monitor.cpp index d8889585..41290b7d 100644 --- a/src/helpers/Monitor.cpp +++ b/src/helpers/Monitor.cpp @@ -71,7 +71,7 @@ void CMonitor::onConnect(bool noRule) { Debug::log(LOG, "Removing monitor {} from realMonitors", szName); - std::erase_if(g_pCompositor->m_vRealMonitors, [&](SP& el) { return el.get() == this; }); + std::erase_if(g_pCompositor->m_vRealMonitors, [&](PHLMONITOR& el) { return el.get() == this; }); }); listeners.state = output->events.state.registerListener([this](std::any d) { @@ -149,7 +149,7 @@ void CMonitor::onConnect(bool noRule) { return; } - SP* thisWrapper = nullptr; + PHLMONITOR* thisWrapper = nullptr; // find the wrap for (auto& m : g_pCompositor->m_vRealMonitors) { @@ -356,7 +356,7 @@ void CMonitor::onDisconnect(bool destroy) { g_pHyprRenderer->m_pMostHzMonitor = pMonitorMostHz; } - std::erase_if(g_pCompositor->m_vMonitors, [&](SP& el) { return el.get() == this; }); + std::erase_if(g_pCompositor->m_vMonitors, [&](PHLMONITOR& el) { return el.get() == this; }); } void CMonitor::addDamage(const pixman_region32_t* rg) { @@ -509,7 +509,7 @@ void CMonitor::setMirror(const std::string& mirrorOf) { // push to mvmonitors - SP* thisWrapper = nullptr; + PHLMONITOR* thisWrapper = nullptr; // find the wrap for (auto& m : g_pCompositor->m_vRealMonitors) { diff --git a/src/helpers/Monitor.hpp b/src/helpers/Monitor.hpp index f3d6d647..dce44b4a 100644 --- a/src/helpers/Monitor.hpp +++ b/src/helpers/Monitor.hpp @@ -125,7 +125,7 @@ class CMonitor { SP outTimeline; uint64_t commitSeq = 0; - WP self; + PHLMONITORREF self; // mirroring PHLMONITORREF pMirrorOf; diff --git a/src/managers/PointerManager.cpp b/src/managers/PointerManager.cpp index ae90349b..0d6e0206 100644 --- a/src/managers/PointerManager.cpp +++ b/src/managers/PointerManager.cpp @@ -69,7 +69,7 @@ void CPointerManager::unlockSoftwareForMonitor(PHLMONITOR mon) { updateCursorBackend(); } -bool CPointerManager::softwareLockedFor(SP mon) { +bool CPointerManager::softwareLockedFor(PHLMONITOR mon) { auto state = stateFor(mon); return state->softwareLocks > 0 || state->hardwareFailed; } @@ -82,7 +82,7 @@ bool CPointerManager::hasCursor() { return currentCursorImage.pBuffer || currentCursorImage.surface; } -SP CPointerManager::stateFor(SP mon) { +SP CPointerManager::stateFor(PHLMONITOR mon) { auto it = std::find_if(monitorStates.begin(), monitorStates.end(), [mon](const auto& other) { return other->monitor == mon; }); if (it == monitorStates.end()) return monitorStates.emplace_back(makeShared(mon)); @@ -503,7 +503,7 @@ SP CPointerManager::renderHWCursorBuffer(SP pMonitor, timespec* now, CRegion& damage, std::optional overridePos) { +void CPointerManager::renderSoftwareCursorsFor(PHLMONITOR pMonitor, timespec* now, CRegion& damage, std::optional overridePos) { if (!hasCursor()) return; @@ -538,7 +538,7 @@ void CPointerManager::renderSoftwareCursorsFor(SP pMonitor, timespec* currentCursorImage.surface->resource()->frame(now); } -Vector2D CPointerManager::getCursorPosForMonitor(SP pMonitor) { +Vector2D CPointerManager::getCursorPosForMonitor(PHLMONITOR pMonitor) { return CBox{pointerPos - pMonitor->vecPosition, {0, 0}} .transform(wlTransformToHyprutils(invertTransform(pMonitor->transform)), pMonitor->vecTransformedSize.x / pMonitor->scale, pMonitor->vecTransformedSize.y / pMonitor->scale) @@ -546,7 +546,7 @@ Vector2D CPointerManager::getCursorPosForMonitor(SP pMonitor) { pMonitor->scale; } -Vector2D CPointerManager::transformedHotspot(SP pMonitor) { +Vector2D CPointerManager::transformedHotspot(PHLMONITOR pMonitor) { if (!pMonitor->cursorSwapchain) return {}; // doesn't matter, we have no hw cursor, and this is only for hw cursors @@ -556,7 +556,7 @@ Vector2D CPointerManager::transformedHotspot(SP pMonitor) { .pos(); } -CBox CPointerManager::getCursorBoxLogicalForMonitor(SP pMonitor) { +CBox CPointerManager::getCursorBoxLogicalForMonitor(PHLMONITOR pMonitor) { return getCursorBoxGlobal().translate(-pMonitor->vecPosition); } @@ -678,7 +678,7 @@ void CPointerManager::move(const Vector2D& deltaLogical) { void CPointerManager::warpAbsolute(Vector2D abs, SP dev) { - SP currentMonitor = g_pCompositor->m_pLastMonitor.lock(); + PHLMONITOR currentMonitor = g_pCompositor->m_pLastMonitor.lock(); if (!currentMonitor || !dev) return; @@ -1055,7 +1055,7 @@ void CPointerManager::detachTablet(SP tablet) { std::erase_if(tabletListeners, [tablet](const auto& e) { return e->tablet.expired() || e->tablet == tablet; }); } -void CPointerManager::damageCursor(SP pMonitor) { +void CPointerManager::damageCursor(PHLMONITOR pMonitor) { for (auto const& mw : monitorStates) { if (mw->monitor != pMonitor) continue; diff --git a/src/managers/PointerManager.hpp b/src/managers/PointerManager.hpp index aef2490d..a0cd0fff 100644 --- a/src/managers/PointerManager.hpp +++ b/src/managers/PointerManager.hpp @@ -43,18 +43,18 @@ class CPointerManager { void setCursorSurface(SP buf, const Vector2D& hotspot); void resetCursorImage(bool apply = true); - void lockSoftwareForMonitor(SP pMonitor); - void unlockSoftwareForMonitor(SP pMonitor); + void lockSoftwareForMonitor(PHLMONITOR pMonitor); + void unlockSoftwareForMonitor(PHLMONITOR pMonitor); void lockSoftwareAll(); void unlockSoftwareAll(); - bool softwareLockedFor(SP pMonitor); + bool softwareLockedFor(PHLMONITOR pMonitor); - void renderSoftwareCursorsFor(SP pMonitor, timespec* now, CRegion& damage /* logical */, std::optional overridePos = {} /* monitor-local */); + void renderSoftwareCursorsFor(PHLMONITOR pMonitor, timespec* now, CRegion& damage /* logical */, std::optional overridePos = {} /* monitor-local */); // this is needed e.g. during screensharing where // the software cursors aren't locked during the cursor move, but they // are rendered later. - void damageCursor(SP pMonitor); + void damageCursor(PHLMONITOR pMonitor); // Vector2D position(); @@ -78,13 +78,13 @@ class CPointerManager { Vector2D closestValid(const Vector2D& pos); // returns the thing in device coordinates. Is NOT offset by the hotspot, relies on set_cursor with hotspot. - Vector2D getCursorPosForMonitor(SP pMonitor); + Vector2D getCursorPosForMonitor(PHLMONITOR pMonitor); // returns the thing in logical coordinates of the monitor - CBox getCursorBoxLogicalForMonitor(SP pMonitor); + CBox getCursorBoxLogicalForMonitor(PHLMONITOR pMonitor); // returns the thing in global coords CBox getCursorBoxGlobal(); - Vector2D transformedHotspot(SP pMonitor); + Vector2D transformedHotspot(PHLMONITOR pMonitor); SP getCurrentCursorTexture(); @@ -160,10 +160,10 @@ class CPointerManager { Vector2D storedUnaccel = {0, 0}; struct SMonitorPointerState { - SMonitorPointerState(SP m) : monitor(m) {} + SMonitorPointerState(PHLMONITOR m) : monitor(m) {} ~SMonitorPointerState() {} - WP monitor; + PHLMONITORREF monitor; int softwareLocks = 0; bool hardwareFailed = false; @@ -176,7 +176,7 @@ class CPointerManager { }; std::vector> monitorStates; - SP stateFor(SP mon); + SP stateFor(PHLMONITOR mon); bool attemptHardwareCursor(SP state); SP renderHWCursorBuffer(SP state, SP texture); bool setHWCursorBuffer(SP state, SP buf); diff --git a/src/protocols/CTMControl.cpp b/src/protocols/CTMControl.cpp index f2a54c6f..cddad830 100644 --- a/src/protocols/CTMControl.cpp +++ b/src/protocols/CTMControl.cpp @@ -81,6 +81,6 @@ void CHyprlandCTMControlProtocol::destroyResource(CHyprlandCTMControlResource* r std::erase_if(m_vManagers, [&](const auto& other) { return other.get() == res; }); } -void CHyprlandCTMControlProtocol::setCTM(SP monitor, const Mat3x3& ctm) { +void CHyprlandCTMControlProtocol::setCTM(PHLMONITOR monitor, const Mat3x3& ctm) { monitor->setCTM(ctm); } diff --git a/src/protocols/CTMControl.hpp b/src/protocols/CTMControl.hpp index 08f1b0e8..70bc79bc 100644 --- a/src/protocols/CTMControl.hpp +++ b/src/protocols/CTMControl.hpp @@ -31,7 +31,7 @@ class CHyprlandCTMControlProtocol : public IWaylandProtocol { private: void destroyResource(CHyprlandCTMControlResource* resource); - void setCTM(SP monitor, const Mat3x3& ctm); + void setCTM(PHLMONITOR monitor, const Mat3x3& ctm); // std::vector> m_vManagers; diff --git a/src/protocols/DRMLease.cpp b/src/protocols/DRMLease.cpp index d0114ce7..be5a6985 100644 --- a/src/protocols/DRMLease.cpp +++ b/src/protocols/DRMLease.cpp @@ -129,7 +129,7 @@ SP CDRMLeaseConnectorResource::fromResource(wl_resou return data ? data->self.lock() : nullptr; } -CDRMLeaseConnectorResource::CDRMLeaseConnectorResource(SP resource_, SP monitor_) : monitor(monitor_), resource(resource_) { +CDRMLeaseConnectorResource::CDRMLeaseConnectorResource(SP resource_, PHLMONITOR monitor_) : monitor(monitor_), resource(resource_) { if (!good()) return; @@ -203,7 +203,7 @@ bool CDRMLeaseDeviceResource::good() { return resource->resource(); } -void CDRMLeaseDeviceResource::sendConnector(SP monitor) { +void CDRMLeaseDeviceResource::sendConnector(PHLMONITOR monitor) { if (std::find_if(connectorsSent.begin(), connectorsSent.end(), [monitor](const auto& e) { return e && !e->dead && e->monitor == monitor; }) != connectorsSent.end()) return; @@ -289,7 +289,7 @@ void CDRMLeaseProtocol::destroyResource(CDRMLeaseResource* resource) { std::erase_if(m_vLeases, [resource](const auto& e) { return e.get() == resource; }); } -void CDRMLeaseProtocol::offer(SP monitor) { +void CDRMLeaseProtocol::offer(PHLMONITOR monitor) { std::erase_if(primaryDevice->offeredOutputs, [](const auto& e) { return e.expired(); }); if (std::find(primaryDevice->offeredOutputs.begin(), primaryDevice->offeredOutputs.end(), monitor) != primaryDevice->offeredOutputs.end()) return; diff --git a/src/protocols/DRMLease.hpp b/src/protocols/DRMLease.hpp index 3671cfce..37de40e3 100644 --- a/src/protocols/DRMLease.hpp +++ b/src/protocols/DRMLease.hpp @@ -56,7 +56,7 @@ class CDRMLeaseRequestResource { class CDRMLeaseConnectorResource { public: - CDRMLeaseConnectorResource(SP resource_, SP monitor_); + CDRMLeaseConnectorResource(SP resource_, PHLMONITOR monitor_); static SP fromResource(wl_resource*); bool good(); @@ -64,7 +64,7 @@ class CDRMLeaseConnectorResource { WP self; WP parent; - WP monitor; + PHLMONITORREF monitor; bool dead = false; private: @@ -82,7 +82,7 @@ class CDRMLeaseDeviceResource { CDRMLeaseDeviceResource(SP resource_); bool good(); - void sendConnector(SP monitor); + void sendConnector(PHLMONITOR monitor); std::vector> connectorsSent; @@ -102,7 +102,7 @@ class CDRMLeaseDevice { bool success = false; SP backend; - std::vector> offeredOutputs; + std::vector offeredOutputs; }; class CDRMLeaseProtocol : public IWaylandProtocol { @@ -111,7 +111,7 @@ class CDRMLeaseProtocol : public IWaylandProtocol { virtual void bindManager(wl_client* client, void* data, uint32_t ver, uint32_t id); - void offer(SP monitor); + void offer(PHLMONITOR monitor); private: void destroyResource(CDRMLeaseDeviceResource* resource); diff --git a/src/protocols/LinuxDMABUF.cpp b/src/protocols/LinuxDMABUF.cpp index 8e26c74f..e81d7e01 100644 --- a/src/protocols/LinuxDMABUF.cpp +++ b/src/protocols/LinuxDMABUF.cpp @@ -21,7 +21,7 @@ static std::optional devIDFromFD(int fd) { return stat.st_rdev; } -CDMABUFFormatTable::CDMABUFFormatTable(SDMABUFTranche _rendererTranche, std::vector, SDMABUFTranche>> tranches_) : +CDMABUFFormatTable::CDMABUFFormatTable(SDMABUFTranche _rendererTranche, std::vector> tranches_) : rendererTranche(_rendererTranche), monitorTranches(tranches_) { std::vector formatsVec; @@ -436,7 +436,7 @@ CLinuxDMABufV1Protocol::CLinuxDMABufV1Protocol(const wl_interface* iface, const .formats = g_pHyprOpenGL->getDRMFormats(), }; - std::vector, SDMABUFTranche>> tches; + std::vector> tches; if (g_pCompositor->m_pAqBackend->hasSession()) { // this assumes there's only 1 device used for both scanout and rendering @@ -453,20 +453,18 @@ CLinuxDMABufV1Protocol::CLinuxDMABufV1Protocol(const wl_interface* iface, const static auto monitorAdded = g_pHookSystem->hookDynamic("monitorAdded", [this](void* self, SCallbackInfo& info, std::any param) { auto pMonitor = std::any_cast(param); - auto mon = pMonitor->self.lock(); auto tranche = SDMABUFTranche{ .device = mainDevice, .flags = ZWP_LINUX_DMABUF_FEEDBACK_V1_TRANCHE_FLAGS_SCANOUT, - .formats = mon->output->getRenderFormats(), + .formats = pMonitor->output->getRenderFormats(), }; - formatTable->monitorTranches.push_back(std::make_pair<>(mon, tranche)); + formatTable->monitorTranches.push_back(std::make_pair<>(pMonitor, tranche)); resetFormatTable(); }); static auto monitorRemoved = g_pHookSystem->hookDynamic("monitorRemoved", [this](void* self, SCallbackInfo& info, std::any param) { auto pMonitor = std::any_cast(param); - auto mon = pMonitor->self.lock(); - std::erase_if(formatTable->monitorTranches, [mon](std::pair, SDMABUFTranche> pair) { return pair.first == mon; }); + std::erase_if(formatTable->monitorTranches, [pMonitor](std::pair pair) { return pair.first == pMonitor; }); resetFormatTable(); }); } @@ -508,8 +506,8 @@ void CLinuxDMABufV1Protocol::resetFormatTable() { for (auto const& feedback : m_vFeedbacks) { feedback->resource->sendFormatTable(newFormatTable->tableFD, newFormatTable->tableSize); if (feedback->lastFeedbackWasScanout) { - SP mon; - auto HLSurface = CWLSurface::fromResource(feedback->surface); + PHLMONITOR mon; + auto HLSurface = CWLSurface::fromResource(feedback->surface); if (auto w = HLSurface->getWindow(); w) if (auto m = g_pCompositor->getMonitorFromID(w->m_iMonitorID); m) mon = m->self.lock(); @@ -560,7 +558,7 @@ void CLinuxDMABufV1Protocol::destroyResource(CLinuxDMABuffer* resource) { std::erase_if(m_vBuffers, [&](const auto& other) { return other.get() == resource; }); } -void CLinuxDMABufV1Protocol::updateScanoutTranche(SP surface, SP pMonitor) { +void CLinuxDMABufV1Protocol::updateScanoutTranche(SP surface, PHLMONITOR pMonitor) { SP feedbackResource; for (auto const& f : m_vFeedbacks) { if (f->surface != surface) @@ -582,7 +580,7 @@ void CLinuxDMABufV1Protocol::updateScanoutTranche(SP surface } const auto& monitorTranchePair = std::find_if(formatTable->monitorTranches.begin(), formatTable->monitorTranches.end(), - [pMonitor](std::pair, SDMABUFTranche> pair) { return pair.first == pMonitor; }); + [pMonitor](std::pair pair) { return pair.first == pMonitor; }); if (monitorTranchePair == formatTable->monitorTranches.end()) { LOGM(LOG, "updateScanoutTranche: monitor has no tranche"); diff --git a/src/protocols/LinuxDMABUF.hpp b/src/protocols/LinuxDMABUF.hpp index 0e25cdc6..e4941a6d 100644 --- a/src/protocols/LinuxDMABUF.hpp +++ b/src/protocols/LinuxDMABUF.hpp @@ -48,13 +48,13 @@ struct SDMABUFTranche { class CDMABUFFormatTable { public: - CDMABUFFormatTable(SDMABUFTranche rendererTranche, std::vector, SDMABUFTranche>> tranches); + CDMABUFFormatTable(SDMABUFTranche rendererTranche, std::vector> tranches); ~CDMABUFFormatTable(); - int tableFD = -1; - size_t tableSize = 0; - SDMABUFTranche rendererTranche; - std::vector, SDMABUFTranche>> monitorTranches; + int tableFD = -1; + size_t tableSize = 0; + SDMABUFTranche rendererTranche; + std::vector> monitorTranches; }; class CLinuxDMABBUFParamsResource { @@ -111,7 +111,7 @@ class CLinuxDMABufV1Protocol : public IWaylandProtocol { ~CLinuxDMABufV1Protocol(); virtual void bindManager(wl_client* client, void* data, uint32_t ver, uint32_t id); - void updateScanoutTranche(SP surface, SP pMonitor); + void updateScanoutTranche(SP surface, PHLMONITOR pMonitor); private: void destroyResource(CLinuxDMABUFResource* resource); diff --git a/src/protocols/OutputManagement.cpp b/src/protocols/OutputManagement.cpp index 77cedd41..0c6a3348 100644 --- a/src/protocols/OutputManagement.cpp +++ b/src/protocols/OutputManagement.cpp @@ -633,7 +633,7 @@ SP COutputManagementProtocol::modeFromResource(wl_resource* r) { return nullptr; } -SP COutputManagementProtocol::getOutputStateFor(SP pMonitor) { +SP COutputManagementProtocol::getOutputStateFor(PHLMONITOR pMonitor) { for (auto const& m : m_vManagers) { if (!m->monitorStates.contains(pMonitor->szName)) continue; diff --git a/src/protocols/OutputManagement.hpp b/src/protocols/OutputManagement.hpp index 6deab017..b9e7ce98 100644 --- a/src/protocols/OutputManagement.hpp +++ b/src/protocols/OutputManagement.hpp @@ -153,7 +153,7 @@ class COutputManagementProtocol : public IWaylandProtocol { virtual void bindManager(wl_client* client, void* data, uint32_t ver, uint32_t id); // doesn't have to return one - SP getOutputStateFor(SP pMonitor); + SP getOutputStateFor(PHLMONITOR pMonitor); private: void destroyResource(COutputManager* resource); diff --git a/src/protocols/PresentationTime.cpp b/src/protocols/PresentationTime.cpp index b66694bf..411036c3 100644 --- a/src/protocols/PresentationTime.cpp +++ b/src/protocols/PresentationTime.cpp @@ -14,7 +14,7 @@ void CQueuedPresentationData::setPresentationType(bool zeroCopy_) { zeroCopy = zeroCopy_; } -void CQueuedPresentationData::attachMonitor(SP pMonitor_) { +void CQueuedPresentationData::attachMonitor(PHLMONITOR pMonitor_) { pMonitor = pMonitor_; } @@ -73,7 +73,7 @@ void CPresentationFeedback::sendQueued(SP data, timespe CPresentationProtocol::CPresentationProtocol(const wl_interface* iface, const int& ver, const std::string& name) : IWaylandProtocol(iface, ver, name) { static auto P = g_pHookSystem->hookDynamic("monitorRemoved", [this](void* self, SCallbackInfo& info, std::any param) { - const auto PMONITOR = std::any_cast(param); + const auto PMONITOR = PHLMONITORREF{std::any_cast(param)}; std::erase_if(m_vQueue, [PMONITOR](const auto& other) { return !other->surface || other->pMonitor == PMONITOR; }); }); } @@ -107,7 +107,7 @@ void CPresentationProtocol::onGetFeedback(CWpPresentation* pMgr, wl_resource* su } } -void CPresentationProtocol::onPresented(SP pMonitor, timespec* when, uint32_t untilRefreshNs, uint64_t seq, uint32_t reportedFlags) { +void CPresentationProtocol::onPresented(PHLMONITOR pMonitor, timespec* when, uint32_t untilRefreshNs, uint64_t seq, uint32_t reportedFlags) { timespec now; timespec* presentedAt = when; if (!presentedAt) { diff --git a/src/protocols/PresentationTime.hpp b/src/protocols/PresentationTime.hpp index 421bb838..d9b45448 100644 --- a/src/protocols/PresentationTime.hpp +++ b/src/protocols/PresentationTime.hpp @@ -14,7 +14,7 @@ class CQueuedPresentationData { CQueuedPresentationData(SP surf); void setPresentationType(bool zeroCopy); - void attachMonitor(SP pMonitor); + void attachMonitor(PHLMONITOR pMonitor); void presented(); void discarded(); @@ -24,7 +24,7 @@ class CQueuedPresentationData { private: bool wasPresented = false; bool zeroCopy = false; - WP pMonitor; + PHLMONITORREF pMonitor; WP surface; friend class CPresentationFeedback; @@ -53,7 +53,7 @@ class CPresentationProtocol : public IWaylandProtocol { virtual void bindManager(wl_client* client, void* data, uint32_t ver, uint32_t id); - void onPresented(SP pMonitor, timespec* when, uint32_t untilRefreshNs, uint64_t seq, uint32_t reportedFlags); + void onPresented(PHLMONITOR pMonitor, timespec* when, uint32_t untilRefreshNs, uint64_t seq, uint32_t reportedFlags); void queueData(SP data); private: diff --git a/src/protocols/VirtualPointer.cpp b/src/protocols/VirtualPointer.cpp index eb92a640..4c5aa13a 100644 --- a/src/protocols/VirtualPointer.cpp +++ b/src/protocols/VirtualPointer.cpp @@ -1,7 +1,7 @@ #include "VirtualPointer.hpp" #include "core/Output.hpp" -CVirtualPointerV1Resource::CVirtualPointerV1Resource(SP resource_, WP boundOutput_) : boundOutput(boundOutput_), resource(resource_) { +CVirtualPointerV1Resource::CVirtualPointerV1Resource(SP resource_, PHLMONITORREF boundOutput_) : boundOutput(boundOutput_), resource(resource_) { if (!good()) return; @@ -134,7 +134,7 @@ void CVirtualPointerProtocol::destroyResource(CVirtualPointerV1Resource* pointer std::erase_if(m_vPointers, [&](const auto& other) { return other.get() == pointer; }); } -void CVirtualPointerProtocol::onCreatePointer(CZwlrVirtualPointerManagerV1* pMgr, wl_resource* seat, uint32_t id, WP output) { +void CVirtualPointerProtocol::onCreatePointer(CZwlrVirtualPointerManagerV1* pMgr, wl_resource* seat, uint32_t id, PHLMONITORREF output) { const auto RESOURCE = m_vPointers.emplace_back(makeShared(makeShared(pMgr->client(), pMgr->version(), id), output)); diff --git a/src/protocols/VirtualPointer.hpp b/src/protocols/VirtualPointer.hpp index 7ee450dc..68fe124e 100644 --- a/src/protocols/VirtualPointer.hpp +++ b/src/protocols/VirtualPointer.hpp @@ -12,7 +12,7 @@ class CVirtualPointerV1Resource { public: - CVirtualPointerV1Resource(SP resource_, WP boundOutput_); + CVirtualPointerV1Resource(SP resource_, PHLMONITORREF boundOutput_); ~CVirtualPointerV1Resource(); struct { @@ -35,12 +35,12 @@ class CVirtualPointerV1Resource { CSignal holdEnd; } events; - bool good(); - wl_client* client(); + bool good(); + wl_client* client(); - std::string name; + std::string name; - WP boundOutput; + PHLMONITORREF boundOutput; private: SP resource; @@ -63,7 +63,7 @@ class CVirtualPointerProtocol : public IWaylandProtocol { private: void onManagerResourceDestroy(wl_resource* res); void destroyResource(CVirtualPointerV1Resource* pointer); - void onCreatePointer(CZwlrVirtualPointerManagerV1* pMgr, wl_resource* seat, uint32_t id, WP output); + void onCreatePointer(CZwlrVirtualPointerManagerV1* pMgr, wl_resource* seat, uint32_t id, PHLMONITORREF output); // std::vector> m_vManagers; diff --git a/src/protocols/XDGOutput.cpp b/src/protocols/XDGOutput.cpp index 0598e713..deb87829 100644 --- a/src/protocols/XDGOutput.cpp +++ b/src/protocols/XDGOutput.cpp @@ -95,7 +95,7 @@ void CXDGOutputProtocol::updateAllOutputs() { // -CXDGOutput::CXDGOutput(SP resource_, SP monitor_) : monitor(monitor_), resource(resource_) { +CXDGOutput::CXDGOutput(SP resource_, PHLMONITOR monitor_) : monitor(monitor_), resource(resource_) { if (!resource->resource()) return; diff --git a/src/protocols/XDGOutput.hpp b/src/protocols/XDGOutput.hpp index 520f3aaa..6a5be284 100644 --- a/src/protocols/XDGOutput.hpp +++ b/src/protocols/XDGOutput.hpp @@ -10,12 +10,12 @@ class CWLOutputProtocol; class CXDGOutput { public: - CXDGOutput(SP resource, SP monitor_); + CXDGOutput(SP resource, PHLMONITOR monitor_); void sendDetails(); private: - WP monitor; + PHLMONITORREF monitor; SP resource; WP outputProto; diff --git a/src/protocols/core/Compositor.cpp b/src/protocols/core/Compositor.cpp index 3d4b63c1..9a2e00a9 100644 --- a/src/protocols/core/Compositor.cpp +++ b/src/protocols/core/Compositor.cpp @@ -182,7 +182,7 @@ wl_client* CWLSurfaceResource::client() { return pClient; } -void CWLSurfaceResource::enter(SP monitor) { +void CWLSurfaceResource::enter(PHLMONITOR monitor) { if (std::find(enteredOutputs.begin(), enteredOutputs.end(), monitor) != enteredOutputs.end()) return; @@ -209,7 +209,7 @@ void CWLSurfaceResource::enter(SP monitor) { resource->sendEnter(output->getResource().get()); } -void CWLSurfaceResource::leave(SP monitor) { +void CWLSurfaceResource::leave(PHLMONITOR monitor) { if (std::find(enteredOutputs.begin(), enteredOutputs.end(), monitor) == enteredOutputs.end()) return; @@ -509,7 +509,7 @@ void CWLSurfaceResource::updateCursorShm() { memcpy(shmData.data(), pixelData, bufLen); } -void CWLSurfaceResource::presentFeedback(timespec* when, SP pMonitor) { +void CWLSurfaceResource::presentFeedback(timespec* when, PHLMONITOR pMonitor) { frame(when); auto FEEDBACK = makeShared(self.lock()); FEEDBACK->attachMonitor(pMonitor); diff --git a/src/protocols/core/Compositor.hpp b/src/protocols/core/Compositor.hpp index b3c067c9..fbffd966 100644 --- a/src/protocols/core/Compositor.hpp +++ b/src/protocols/core/Compositor.hpp @@ -60,8 +60,8 @@ class CWLSurfaceResource { bool good(); wl_client* client(); - void enter(SP monitor); - void leave(SP monitor); + void enter(PHLMONITOR monitor); + void leave(PHLMONITOR monitor); void sendPreferredTransform(wl_output_transform t); void sendPreferredScale(int32_t scale); void frame(timespec* now); @@ -115,7 +115,7 @@ class CWLSurfaceResource { std::vector> callbacks; WP self; WP hlSurface; - std::vector> enteredOutputs; + std::vector enteredOutputs; bool mapped = false; std::vector> subsurfaces; SP role; @@ -124,7 +124,7 @@ class CWLSurfaceResource { void breadthfirst(std::function, const Vector2D&, void*)> fn, void* data); CRegion accumulateCurrentBufferDamage(); - void presentFeedback(timespec* when, SP pMonitor); + void presentFeedback(timespec* when, PHLMONITOR pMonitor); void lockPendingState(); void unlockPendingState(); diff --git a/src/protocols/core/Output.cpp b/src/protocols/core/Output.cpp index e9f35abc..edeeb584 100644 --- a/src/protocols/core/Output.cpp +++ b/src/protocols/core/Output.cpp @@ -3,7 +3,7 @@ #include "../../Compositor.hpp" #include "../../helpers/Monitor.hpp" -CWLOutputResource::CWLOutputResource(SP resource_, SP pMonitor) : monitor(pMonitor), resource(resource_) { +CWLOutputResource::CWLOutputResource(SP resource_, PHLMONITOR pMonitor) : monitor(pMonitor), resource(resource_) { if (!good()) return; @@ -83,7 +83,7 @@ void CWLOutputResource::updateState() { resource->sendDone(); } -CWLOutputProtocol::CWLOutputProtocol(const wl_interface* iface, const int& ver, const std::string& name, SP pMonitor) : +CWLOutputProtocol::CWLOutputProtocol(const wl_interface* iface, const int& ver, const std::string& name, PHLMONITOR pMonitor) : IWaylandProtocol(iface, ver, name), monitor(pMonitor), szName(pMonitor->szName) { listeners.modeChanged = monitor->events.modeChanged.registerListener([this](std::any d) { diff --git a/src/protocols/core/Output.hpp b/src/protocols/core/Output.hpp index 49c32ec1..a4c81d72 100644 --- a/src/protocols/core/Output.hpp +++ b/src/protocols/core/Output.hpp @@ -12,7 +12,7 @@ class CWLOutputProtocol; class CWLOutputResource { public: - CWLOutputResource(SP resource_, SP pMonitor); + CWLOutputResource(SP resource_, PHLMONITOR pMonitor); static SP fromResource(wl_resource*); bool good(); @@ -20,7 +20,7 @@ class CWLOutputResource { SP getResource(); void updateState(); - WP monitor; + PHLMONITORREF monitor; WP owner; WP self; @@ -33,14 +33,14 @@ class CWLOutputResource { class CWLOutputProtocol : public IWaylandProtocol { public: - CWLOutputProtocol(const wl_interface* iface, const int& ver, const std::string& name, SP pMonitor); + CWLOutputProtocol(const wl_interface* iface, const int& ver, const std::string& name, PHLMONITOR pMonitor); virtual void bindManager(wl_client* client, void* data, uint32_t ver, uint32_t id); SP outputResourceFrom(wl_client* client); void sendDone(); - WP monitor; + PHLMONITORREF monitor; WP self; // will mark the protocol for removal, will be removed when no. of bound outputs is 0 (or when overwritten by a new global) diff --git a/src/render/OpenGL.hpp b/src/render/OpenGL.hpp index 04f69d49..115dcac7 100644 --- a/src/render/OpenGL.hpp +++ b/src/render/OpenGL.hpp @@ -206,30 +206,30 @@ class CHyprOpenGLImpl { void setDamage(const CRegion& damage, std::optional finalDamage = {}); uint32_t getPreferredReadFormat(PHLMONITOR pMonitor); - std::vector getDRMFormats(); - EGLImageKHR createEGLImage(const Aquamarine::SDMABUFAttrs& attrs); - SP createEGLSync(int fenceFD); - bool waitForTimelinePoint(SP timeline, uint64_t point); + std::vector getDRMFormats(); + EGLImageKHR createEGLImage(const Aquamarine::SDMABUFAttrs& attrs); + SP createEGLSync(int fenceFD); + bool waitForTimelinePoint(SP timeline, uint64_t point); - SCurrentRenderData m_RenderData; + SCurrentRenderData m_RenderData; - GLint m_iCurrentOutputFb = 0; + GLint m_iCurrentOutputFb = 0; - int m_iGBMFD = -1; - gbm_device* m_pGbmDevice = nullptr; - EGLContext m_pEglContext = nullptr; - EGLDisplay m_pEglDisplay = nullptr; - EGLDeviceEXT m_pEglDevice = nullptr; + int m_iGBMFD = -1; + gbm_device* m_pGbmDevice = nullptr; + EGLContext m_pEglContext = nullptr; + EGLDisplay m_pEglDisplay = nullptr; + EGLDeviceEXT m_pEglDevice = nullptr; - bool m_bReloadScreenShader = true; // at launch it can be set + bool m_bReloadScreenShader = true; // at launch it can be set - PHLWINDOWREF m_pCurrentWindow; // hack to get the current rendered window - PHLLS m_pCurrentLayer; // hack to get the current rendered layer + PHLWINDOWREF m_pCurrentWindow; // hack to get the current rendered window + PHLLS m_pCurrentLayer; // hack to get the current rendered layer - std::map m_mWindowFramebuffers; - std::map m_mLayerFramebuffers; - std::unordered_map m_mMonitorRenderResources; - std::unordered_map m_mMonitorBGFBs; + std::map m_mWindowFramebuffers; + std::map m_mLayerFramebuffers; + std::map m_mMonitorRenderResources; + std::map m_mMonitorBGFBs; struct { PFNGLEGLIMAGETARGETRENDERBUFFERSTORAGEOESPROC glEGLImageTargetRenderbufferStorageOES = nullptr; diff --git a/src/render/Renderer.cpp b/src/render/Renderer.cpp index 5df0c070..c69167c8 100644 --- a/src/render/Renderer.cpp +++ b/src/render/Renderer.cpp @@ -1085,7 +1085,7 @@ void CHyprRenderer::renderSessionLockMissing(PHLMONITOR pMonitor) { g_pSessionLockManager->onLockscreenRenderedOnMonitor(pMonitor->ID); } -void CHyprRenderer::calculateUVForSurface(PHLWINDOW pWindow, SP pSurface, SP pMonitor, bool main, const Vector2D& projSize, +void CHyprRenderer::calculateUVForSurface(PHLWINDOW pWindow, SP pSurface, PHLMONITOR pMonitor, bool main, const Vector2D& projSize, const Vector2D& projSizeUnscaled, bool fixMisalignedFSV1) { if (!pWindow || !pWindow->m_bIsX11) { Vector2D uvTL; @@ -1603,7 +1603,7 @@ void CHyprRenderer::sendFrameEventsToWorkspace(PHLMONITOR pMonitor, PHLWORKSPACE } } -void CHyprRenderer::setSurfaceScanoutMode(SP surface, SP monitor) { +void CHyprRenderer::setSurfaceScanoutMode(SP surface, PHLMONITOR monitor) { if (!PROTO::linuxDma) return; diff --git a/src/render/Renderer.hpp b/src/render/Renderer.hpp index 41f40b5a..4524008b 100644 --- a/src/render/Renderer.hpp +++ b/src/render/Renderer.hpp @@ -64,7 +64,7 @@ class CHyprRenderer { void ensureCursorRenderingMode(); bool shouldRenderCursor(); void setCursorHidden(bool hide); - void calculateUVForSurface(PHLWINDOW, SP, SP pMonitor, bool main = false, const Vector2D& projSize = {}, const Vector2D& projSizeUnscaled = {}, + void calculateUVForSurface(PHLWINDOW, SP, PHLMONITOR pMonitor, bool main = false, const Vector2D& projSize = {}, const Vector2D& projSizeUnscaled = {}, bool fixMisalignedFSV1 = false); std::tuple getRenderTimes(PHLMONITOR pMonitor); // avg max min void renderLockscreen(PHLMONITOR pMonitor, timespec* now, const CBox& geometry); @@ -95,7 +95,7 @@ class CHyprRenderer { DAMAGETRACKINGMODES damageTrackingModeFromStr(const std::string&); - void setSurfaceScanoutMode(SP surface, SP monitor); // nullptr monitor resets + void setSurfaceScanoutMode(SP surface, PHLMONITOR monitor); // nullptr monitor resets void initiateManualCrash(); bool m_bCrashingInProgress = false; From 3dd8db83f166733d1dd6a753bd6eb07727320768 Mon Sep 17 00:00:00 2001 From: Vaxry Date: Sat, 26 Oct 2024 02:12:43 +0100 Subject: [PATCH 0558/2181] pointer: add default auto for no_hw_cursors auto defaults to off on nvidia, on for everyone else. Gotta wait until we do fucking drm_dumb and it fucking works --- src/config/ConfigDescriptions.hpp | 4 ++-- src/config/ConfigManager.cpp | 14 +++++++++++++- src/config/ConfigManager.hpp | 2 ++ src/managers/PointerManager.cpp | 12 ++++-------- 4 files changed, 21 insertions(+), 11 deletions(-) diff --git a/src/config/ConfigDescriptions.hpp b/src/config/ConfigDescriptions.hpp index 7910e865..0177f92b 100644 --- a/src/config/ConfigDescriptions.hpp +++ b/src/config/ConfigDescriptions.hpp @@ -1244,8 +1244,8 @@ inline static const std::vector CONFIG_OPTIONS = { SConfigOptionDescription{ .value = "cursor:no_hardware_cursors", .description = "disables hardware cursors", - .type = CONFIG_OPTION_BOOL, - .data = SConfigOptionDescription::SBoolData{false}, + .type = CONFIG_OPTION_CHOICE, + .data = SConfigOptionDescription::SChoiceData{0, "Disabled,Enabled,Auto"}, }, SConfigOptionDescription{ .value = "cursor:no_break_fs_vrr", diff --git a/src/config/ConfigManager.cpp b/src/config/ConfigManager.cpp index e2dc4b0f..909dfc63 100644 --- a/src/config/ConfigManager.cpp +++ b/src/config/ConfigManager.cpp @@ -552,7 +552,7 @@ CConfigManager::CConfigManager() { m_pConfig->addConfigValue("opengl:nvidia_anti_flicker", Hyprlang::INT{1}); m_pConfig->addConfigValue("opengl:force_introspection", Hyprlang::INT{2}); - m_pConfig->addConfigValue("cursor:no_hardware_cursors", Hyprlang::INT{0}); + m_pConfig->addConfigValue("cursor:no_hardware_cursors", Hyprlang::INT{2}); m_pConfig->addConfigValue("cursor:no_break_fs_vrr", Hyprlang::INT{0}); m_pConfig->addConfigValue("cursor:min_refresh_rate", Hyprlang::INT{24}); m_pConfig->addConfigValue("cursor:hotspot_padding", Hyprlang::INT{0}); @@ -2778,6 +2778,18 @@ const std::vector& CConfigManager::getAllDescriptions( return CONFIG_OPTIONS; } +bool CConfigManager::shouldUseSoftwareCursors() { + static auto PNOHW = CConfigValue("cursor:no_hardware_cursors"); + + switch (*PNOHW) { + case 0: return false; + case 1: return true; + default: return g_pHyprRenderer->isNvidia(); + } + + return true; +} + std::string SConfigOptionDescription::jsonify() const { auto parseData = [this]() -> std::string { return std::visit( diff --git a/src/config/ConfigManager.hpp b/src/config/ConfigManager.hpp index cf053daa..88b74b6e 100644 --- a/src/config/ConfigManager.hpp +++ b/src/config/ConfigManager.hpp @@ -200,6 +200,8 @@ class CConfigManager { void ensureMonitorStatus(); void ensureVRR(PHLMONITOR pMonitor = nullptr); + bool shouldUseSoftwareCursors(); + std::string parseKeyword(const std::string&, const std::string&); void addParseError(const std::string&); diff --git a/src/managers/PointerManager.cpp b/src/managers/PointerManager.cpp index 0d6e0206..d2114e79 100644 --- a/src/managers/PointerManager.cpp +++ b/src/managers/PointerManager.cpp @@ -247,9 +247,7 @@ void CPointerManager::resetCursorImage(bool apply) { } void CPointerManager::updateCursorBackend() { - static auto PNOHW = CConfigValue("cursor:no_hardware_cursors"); - - const auto CURSORBOX = getCursorBoxGlobal(); + const auto CURSORBOX = getCursorBoxGlobal(); for (auto const& m : g_pCompositor->m_vMonitors) { auto state = stateFor(m); @@ -268,7 +266,7 @@ void CPointerManager::updateCursorBackend() { continue; } - if (state->softwareLocks > 0 || *PNOHW || !attemptHardwareCursor(state)) { + if (state->softwareLocks > 0 || g_pConfigManager->shouldUseSoftwareCursors() || !attemptHardwareCursor(state)) { Debug::log(TRACE, "Output {} rejected hardware cursors, falling back to sw", m->szName); state->box = getCursorBoxLogicalForMonitor(state->monitor.lock()); state->hardwareFailed = true; @@ -641,15 +639,13 @@ Vector2D CPointerManager::closestValid(const Vector2D& pos) { } void CPointerManager::damageIfSoftware() { - auto b = getCursorBoxGlobal().expand(4); - - static auto PNOHW = CConfigValue("cursor:no_hardware_cursors"); + auto b = getCursorBoxGlobal().expand(4); for (auto const& mw : monitorStates) { if (mw->monitor.expired() || !mw->monitor->output) continue; - if ((mw->softwareLocks > 0 || mw->hardwareFailed || *PNOHW) && b.overlaps({mw->monitor->vecPosition, mw->monitor->vecSize})) { + if ((mw->softwareLocks > 0 || mw->hardwareFailed || g_pConfigManager->shouldUseSoftwareCursors()) && b.overlaps({mw->monitor->vecPosition, mw->monitor->vecSize})) { g_pHyprRenderer->damageBox(&b, mw->monitor->shouldSkipScheduleFrameOnMouseEvent()); break; } From 0b29caf9ab86518ff474eed5e7d19c12f96ebbd0 Mon Sep 17 00:00:00 2001 From: Aqa-Ib Date: Sat, 26 Oct 2024 01:22:37 +0000 Subject: [PATCH 0559/2181] core: fix group members disappearing when you move the group to another monitor (#8237) * fix group members disappearance when you move the group to another monitor * remove repeated action --- src/Compositor.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Compositor.cpp b/src/Compositor.cpp index 743895aa..d4e2db17 100644 --- a/src/Compositor.cpp +++ b/src/Compositor.cpp @@ -2795,11 +2795,11 @@ void CCompositor::moveWindowToWorkspaceSafe(PHLWINDOW pWindow, PHLWORKSPACE pWor pWindow->updateToplevel(); pWindow->updateDynamicRules(); pWindow->uncacheWindowDecos(); + pWindow->updateGroupOutputs(); if (!pWindow->m_sGroupData.pNextWindow.expired()) { PHLWINDOW next = pWindow->m_sGroupData.pNextWindow.lock(); while (next != pWindow) { - next->moveToWorkspace(pWorkspace); next->updateToplevel(); next = next->m_sGroupData.pNextWindow.lock(); } From c356e425008cba8bd0c87487a2c79b9be4eda2aa Mon Sep 17 00:00:00 2001 From: Damianu Date: Sat, 26 Oct 2024 17:50:31 +0200 Subject: [PATCH 0560/2181] misc: Fix bad links to wiki (#8240) Same as in https://github.com/hyprwm/hyprland-wiki/pull/828 --- README.md | 2 +- docs/ISSUE_GUIDELINES.md | 2 +- example/hyprland.conf | 2 +- src/config/defaultConfig.hpp | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index f271c29c..0970819c 100644 --- a/README.md +++ b/README.md @@ -100,7 +100,7 @@ easy IPC, much more QoL stuff than other compositors and more... -[Configure]: https://wiki.hyprland.org/Configuring/Configuring-Hyprland/ +[Configure]: https://wiki.hyprland.org/Configuring/ [Stars]: https://starchart.cc/hyprwm/Hyprland [Hypr]: https://github.com/hyprwm/Hypr diff --git a/docs/ISSUE_GUIDELINES.md b/docs/ISSUE_GUIDELINES.md index 2f6cbbf8..9328642d 100644 --- a/docs/ISSUE_GUIDELINES.md +++ b/docs/ISSUE_GUIDELINES.md @@ -3,7 +3,7 @@ First of all, please remember to: - Check that your issue is not a duplicate - Read the [FAQ](https://wiki.hyprland.org/FAQ/) -- Read the [Configuring Page](https://wiki.hyprland.org/Configuring/Configuring-Hyprland) +- Read the [Configuring Page](https://wiki.hyprland.org/Configuring/)
diff --git a/example/hyprland.conf b/example/hyprland.conf index f94cb1d1..f1139c3b 100644 --- a/example/hyprland.conf +++ b/example/hyprland.conf @@ -1,6 +1,6 @@ # This is an example Hyprland config file. # Refer to the wiki for more information. -# https://wiki.hyprland.org/Configuring/Configuring-Hyprland/ +# https://wiki.hyprland.org/Configuring/ # Please note not all available settings / options are set here. # For a full list, see the wiki diff --git a/src/config/defaultConfig.hpp b/src/config/defaultConfig.hpp index 4a33ec91..facb16e2 100644 --- a/src/config/defaultConfig.hpp +++ b/src/config/defaultConfig.hpp @@ -13,7 +13,7 @@ autogenerated = 1 # remove this line to remove the warning # This is an example Hyprland config file. # Refer to the wiki for more information. -# https://wiki.hyprland.org/Configuring/Configuring-Hyprland/ +# https://wiki.hyprland.org/Configuring/ # Please note not all available settings / options are set here. # For a full list, see the wiki From f3f7d3629a632682b1b3acf800f0b5fb10cd48f4 Mon Sep 17 00:00:00 2001 From: izmyname <135810812+izmyname@users.noreply.github.com> Date: Sun, 27 Oct 2024 00:49:00 +0500 Subject: [PATCH 0561/2181] Build with hyprland-session.service (#8251) Co-authored-by: Mihai Fufezan --- CMakeLists.txt | 10 ++++++++++ meson.build | 3 +++ .../hyprland-session.service.in | 6 +++--- {example => systemd}/hyprland-systemd.desktop | 0 systemd/meson.build | 15 +++++++++++++++ 5 files changed, 31 insertions(+), 3 deletions(-) rename example/hyprland-session.service => systemd/hyprland-session.service.in (61%) rename {example => systemd}/hyprland-systemd.desktop (100%) create mode 100644 systemd/meson.build diff --git a/CMakeLists.txt b/CMakeLists.txt index df919d76..ec8c331e 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -15,7 +15,9 @@ include(GNUInstallDirs) set(HYPRLAND_VERSION ${VER}) set(PREFIX ${CMAKE_INSTALL_PREFIX}) set(INCLUDEDIR ${CMAKE_INSTALL_INCLUDEDIR}) +set(BINDIR ${CMAKE_INSTALL_BINDIR}) configure_file(hyprland.pc.in hyprland.pc @ONLY) +configure_file(systemd/hyprland-session.service.in systemd/hyprland-session.service @ONLY) set(CMAKE_MESSAGE_LOG_LEVEL "STATUS") @@ -357,6 +359,11 @@ install( install(FILES ${CMAKE_SOURCE_DIR}/example/hyprland.desktop DESTINATION ${CMAKE_INSTALL_DATAROOTDIR}/wayland-sessions) + +# session file -systemd +install(FILES ${CMAKE_SOURCE_DIR}/systemd/hyprland-systemd.desktop + DESTINATION ${CMAKE_INSTALL_DATAROOTDIR}/wayland-sessions) + # allow Hyprland to find assets add_compile_definitions(DATAROOTDIR="${CMAKE_INSTALL_FULL_DATAROOTDIR}") @@ -397,3 +404,6 @@ install( DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/hyprland FILES_MATCHING PATTERN "*.h*") + +#install systemd service +install(FILES ${CMAKE_BINARY_DIR}/systemd/hyprland-session.service DESTINATION ${CMAKE_INSTALL_LIBDIR}/systemd/user) diff --git a/meson.build b/meson.build index 33e8fdbe..d0ba9a5c 100644 --- a/meson.build +++ b/meson.build @@ -80,6 +80,8 @@ if get_option('tracy_enable') and get_option('buildtype') != 'debugoptimized' warning('Profiling builds should set -- buildtype = debugoptimized') endif + + subdir('protocols') subdir('src') subdir('hyprctl') @@ -87,6 +89,7 @@ subdir('hyprpm/src') subdir('assets') subdir('example') subdir('docs') +subdir('systemd') # Generate hyprland.pc pkg_install_dir = join_paths(get_option('datadir'), 'pkgconfig') diff --git a/example/hyprland-session.service b/systemd/hyprland-session.service.in similarity index 61% rename from example/hyprland-session.service rename to systemd/hyprland-session.service.in index 3089a961..dafdc141 100644 --- a/example/hyprland-session.service +++ b/systemd/hyprland-session.service.in @@ -9,8 +9,8 @@ After=graphical-session-pre.target [Service] Type=notify -ExecStart=/usr/bin/Hyprland -ExecStop=/usr/bin/hyprctl dispatch exit -ExecStopPost=/usr/bin/systemctl --user unset-environment DISPLAY WAYLAND_DISPLAY HYPRLAND_INSTANCE_SIGNATURE XDG_CURRENT_DESKTOP +ExecStart=@PREFIX@/@BINDIR@/Hyprland +ExecStop=@PREFIX@/@BINDIR@/hyprctl dispatch exit +ExecStopPost=systemctl --user unset-environment DISPLAY WAYLAND_DISPLAY HYPRLAND_INSTANCE_SIGNATURE XDG_CURRENT_DESKTOP Restart=on-failure Slice=session.slice diff --git a/example/hyprland-systemd.desktop b/systemd/hyprland-systemd.desktop similarity index 100% rename from example/hyprland-systemd.desktop rename to systemd/hyprland-systemd.desktop diff --git a/systemd/meson.build b/systemd/meson.build new file mode 100644 index 00000000..497e64f4 --- /dev/null +++ b/systemd/meson.build @@ -0,0 +1,15 @@ +install_data( + 'hyprland-systemd.desktop', + install_dir: join_paths(get_option('datadir'), 'wayland-sessions'), + install_tag: 'runtime', +) + +conf_data = configuration_data() +conf_data.set('PREFIX', get_option('prefix')) +conf_data.set('BINDIR', get_option('bindir')) + +configure_file( + configuration: conf_data, + input: 'hyprland-session.service.in', + output: '@BASENAME@', + install_dir: join_paths(get_option('libdir'), 'systemd/user') ) From a3d3b4fd64a51a8c1663b450bd2a408f1f0fa9b3 Mon Sep 17 00:00:00 2001 From: Aqa-Ib Date: Sun, 27 Oct 2024 00:44:55 +0000 Subject: [PATCH 0562/2181] groups: fix swallowing (#8223) * fix swallowing for groups * remove unnecessary check * clang-format * clarify comment * make variables consistent * make aditional variables consistent --- src/desktop/Window.hpp | 1 + src/events/Windows.cpp | 32 +++++++++---------- src/layout/IHyprLayout.cpp | 29 +++++++---------- .../decorations/CHyprGroupBarDecoration.cpp | 7 ++-- 4 files changed, 31 insertions(+), 38 deletions(-) diff --git a/src/desktop/Window.hpp b/src/desktop/Window.hpp index b2a8e763..9867a8c9 100644 --- a/src/desktop/Window.hpp +++ b/src/desktop/Window.hpp @@ -357,6 +357,7 @@ class CWindow { // swallowing PHLWINDOWREF m_pSwallowed; + bool m_bGroupSwallowed = false; // focus stuff bool m_bStayFocused = false; diff --git a/src/events/Windows.cpp b/src/events/Windows.cpp index 57a28948..e8abe30d 100644 --- a/src/events/Windows.cpp +++ b/src/events/Windows.cpp @@ -44,8 +44,6 @@ void Events::listener_mapWindow(void* owner, void* data) { static auto PINACTIVEALPHA = CConfigValue("decoration:inactive_opacity"); static auto PACTIVEALPHA = CConfigValue("decoration:active_opacity"); static auto PDIMSTRENGTH = CConfigValue("decoration:dim_strength"); - static auto PSWALLOW = CConfigValue("misc:enable_swallow"); - static auto PSWALLOWREGEX = CConfigValue("misc:swallow_regex"); static auto PNEWTAKESOVERFS = CConfigValue("misc:new_window_takes_over_fullscreen"); static auto PINITIALWSTRACKING = CConfigValue("misc:initial_workspace_tracking"); @@ -322,6 +320,10 @@ void Events::listener_mapWindow(void* owner, void* data) { PWINDOW->updateWindowData(); + // Verify window swallowing. Get the swallower before calling onWindowCreated(PWINDOW) because getSwallower() wouldn't get it after if PWINDOW gets auto grouped. + const auto SWALLOWER = PWINDOW->getSwallower(); + PWINDOW->m_pSwallowed = SWALLOWER; + if (PWINDOW->m_bIsFloating) { g_pLayoutManager->getCurrentLayout()->onWindowCreated(PWINDOW); PWINDOW->m_bCreatedOverFullscreen = true; @@ -567,20 +569,12 @@ void Events::listener_mapWindow(void* owner, void* data) { g_pCompositor->focusWindow(nullptr); } - // verify swallowing - if (*PSWALLOW && std::string{*PSWALLOWREGEX} != STRVAL_EMPTY) { - const auto SWALLOWER = PWINDOW->getSwallower(); - - if (SWALLOWER) { - // swallow - PWINDOW->m_pSwallowed = SWALLOWER; - - g_pLayoutManager->getCurrentLayout()->onWindowRemoved(SWALLOWER); - - SWALLOWER->setHidden(true); - - g_pLayoutManager->getCurrentLayout()->recalculateMonitor(PWINDOW->m_iMonitorID); - } + // swallow + if (SWALLOWER) { + g_pLayoutManager->getCurrentLayout()->onWindowRemoved(SWALLOWER); + g_pHyprRenderer->damageWindow(SWALLOWER); + SWALLOWER->setHidden(true); + g_pLayoutManager->getCurrentLayout()->recalculateMonitor(PWINDOW->m_iMonitorID); } PWINDOW->m_bFirstMap = false; @@ -662,7 +656,13 @@ void Events::listener_unmapWindow(void* owner, void* data) { // swallowing if (valid(PWINDOW->m_pSwallowed)) { PWINDOW->m_pSwallowed->setHidden(false); + + if (PWINDOW->m_sGroupData.pNextWindow.lock()) + PWINDOW->m_pSwallowed->m_bGroupSwallowed = true; // flag for the swallowed window to be created into the group where it belongs when auto_group = false. + g_pLayoutManager->getCurrentLayout()->onWindowCreated(PWINDOW->m_pSwallowed.lock()); + + PWINDOW->m_pSwallowed->m_bGroupSwallowed = false; PWINDOW->m_pSwallowed.reset(); } diff --git a/src/layout/IHyprLayout.cpp b/src/layout/IHyprLayout.cpp index 655f2341..454a6132 100644 --- a/src/layout/IHyprLayout.cpp +++ b/src/layout/IHyprLayout.cpp @@ -184,22 +184,20 @@ void IHyprLayout::onWindowCreatedFloating(PHLWINDOW pWindow) { } bool IHyprLayout::onWindowCreatedAutoGroup(PHLWINDOW pWindow) { - static auto PAUTOGROUP = CConfigValue("group:auto_group"); - PHLWINDOW OPENINGON = g_pCompositor->m_pLastWindow.lock() && g_pCompositor->m_pLastWindow->m_pWorkspace == pWindow->m_pWorkspace ? - g_pCompositor->m_pLastWindow.lock() : - g_pCompositor->getFirstWindowOnWorkspace(pWindow->workspaceID()); + static auto PAUTOGROUP = CConfigValue("group:auto_group"); + const PHLWINDOW OPENINGON = g_pCompositor->m_pLastWindow.lock() && g_pCompositor->m_pLastWindow->m_pWorkspace == pWindow->m_pWorkspace ? + g_pCompositor->m_pLastWindow.lock() : + g_pCompositor->getFirstWindowOnWorkspace(pWindow->workspaceID()); + const bool FLOATEDINTOTILED = pWindow->m_bIsFloating && !OPENINGON->m_bIsFloating; + const bool SWALLOWING = pWindow->m_pSwallowed || pWindow->m_bGroupSwallowed; - bool denied = false; - if (pWindow->m_bIsFloating && !OPENINGON->m_bIsFloating) - denied = true; - - if (*PAUTOGROUP // check if auto_group is enabled. + if ((*PAUTOGROUP || SWALLOWING) // continue if auto_group is enabled or if dealing with window swallowing. && OPENINGON // this shouldn't be 0, but honestly, better safe than sorry. && OPENINGON != pWindow // prevent freeze when the "group set" window rule makes the new window to be already a group. && OPENINGON->m_sGroupData.pNextWindow.lock() // check if OPENINGON is a group. && pWindow->canBeGroupedInto(OPENINGON) // check if the new window can be grouped into OPENINGON. - && !g_pXWaylandManager->shouldBeFloated(pWindow) // don't group child windows. Fix for floated groups. Tiled groups don't need this because we check if !denied. - && !denied) { // don't group a new floated window into a tiled group (for convenience). + && !g_pXWaylandManager->shouldBeFloated(pWindow) // don't group child windows. Fix for floated groups. Tiled groups don't need this because we check if !FLOATEDINTOTILED. + && !FLOATEDINTOTILED) { // don't group a new floated window into a tiled group (for convenience). pWindow->m_bIsFloating = OPENINGON->m_bIsFloating; // match the floating state. Needed to autogroup a new tiled window into a floated group. @@ -341,12 +339,9 @@ void IHyprLayout::onEndDragWindow() { if (pWindow->checkInputOnDecos(INPUT_TYPE_DRAG_END, MOUSECOORDS, DRAGGINGWINDOW)) return; - bool denied = false; - if (!pWindow->m_bIsFloating && !DRAGGINGWINDOW->m_bDraggingTiled) - denied = true; - - static auto PDRAGINTOGROUP = CConfigValue("group:drag_into_group"); - if (pWindow->m_sGroupData.pNextWindow.lock() && DRAGGINGWINDOW->canBeGroupedInto(pWindow) && *PDRAGINTOGROUP == 1 && !denied) { + const bool FLOATEDINTOTILED = !pWindow->m_bIsFloating && !DRAGGINGWINDOW->m_bDraggingTiled; + static auto PDRAGINTOGROUP = CConfigValue("group:drag_into_group"); + if (pWindow->m_sGroupData.pNextWindow.lock() && DRAGGINGWINDOW->canBeGroupedInto(pWindow) && *PDRAGINTOGROUP == 1 && !FLOATEDINTOTILED) { if (DRAGGINGWINDOW->m_bDraggingTiled) { changeWindowFloatingMode(DRAGGINGWINDOW); DRAGGINGWINDOW->m_vLastFloatingSize = m_vDraggingWindowOriginalFloatSize; diff --git a/src/render/decorations/CHyprGroupBarDecoration.cpp b/src/render/decorations/CHyprGroupBarDecoration.cpp index 4219a5a8..1868bb5c 100644 --- a/src/render/decorations/CHyprGroupBarDecoration.cpp +++ b/src/render/decorations/CHyprGroupBarDecoration.cpp @@ -405,12 +405,9 @@ bool CHyprGroupBarDecoration::onEndWindowDragOnDeco(const Vector2D& pos, PHLWIND static auto PSTACKED = CConfigValue("group:groupbar:stacked"); static auto PDRAGINTOGROUP = CConfigValue("group:drag_into_group"); static auto PMERGEFLOATEDINTOTILEDONGROUPBAR = CConfigValue("group:merge_floated_into_tiled_on_groupbar"); + const bool FLOATEDINTOTILED = !m_pWindow->m_bIsFloating && !pDraggedWindow->m_bDraggingTiled; - bool denied = false; - if (!m_pWindow->m_bIsFloating && !pDraggedWindow->m_bDraggingTiled && !*PMERGEFLOATEDINTOTILEDONGROUPBAR) - denied = true; - - if (!pDraggedWindow->canBeGroupedInto(m_pWindow.lock()) || (*PDRAGINTOGROUP != 1 && *PDRAGINTOGROUP != 2) || denied) + if (!pDraggedWindow->canBeGroupedInto(m_pWindow.lock()) || (*PDRAGINTOGROUP != 1 && *PDRAGINTOGROUP != 2) || (FLOATEDINTOTILED && !*PMERGEFLOATEDINTOTILEDONGROUPBAR)) return false; const float BARRELATIVE = *PSTACKED ? pos.y - assignedBoxGlobal().y - (m_fBarHeight + BAR_PADDING_OUTER_VERT) / 2 : pos.x - assignedBoxGlobal().x - m_fBarWidth / 2; From f9b52203f58bcb716144d89ee9f85fe12ebfe94d Mon Sep 17 00:00:00 2001 From: Tom Englund Date: Sun, 27 Oct 2024 18:51:26 +0100 Subject: [PATCH 0563/2181] internal: optimize cursor move a bit (#8264) * window: inline and const getWindowMainSurfaceBox getWindowMainSurfaceBox gets called a lot of times from deep down from mousemoveunified, profiling mousemoveunified it spends quite a lot of cpu time in here, let the compiler optimize the call to getWindowMainSurfaceBox by inlining and making it const. reducing the overhead. * inputmgr: return early and use std::any_of return early in mousemoveunified to reduce the amount of unnecessery calls to various pointers when not needed, also make isconstrained use std::any_of instead of for loop to use the STL optimized paths with hopes and dreams marginally faster. * decoration: return early, reduce temporar copy return earlier and reduce the temp copies by using one .lock instead of two --- src/desktop/Window.cpp | 4 --- src/desktop/Window.hpp | 10 +++--- src/managers/input/InputManager.cpp | 35 +++++++------------ .../decorations/DecorationPositioner.cpp | 14 ++++---- 4 files changed, 27 insertions(+), 36 deletions(-) diff --git a/src/desktop/Window.cpp b/src/desktop/Window.cpp index 1297bb83..0772b676 100644 --- a/src/desktop/Window.cpp +++ b/src/desktop/Window.cpp @@ -240,10 +240,6 @@ CBox CWindow::getWindowBoxUnified(uint64_t properties) { return box; } -CBox CWindow::getWindowMainSurfaceBox() { - return {m_vRealPosition.value().x, m_vRealPosition.value().y, m_vRealSize.value().x, m_vRealSize.value().y}; -} - SBoxExtents CWindow::getFullWindowReservedArea() { return g_pDecorationPositioner->getWindowDecorationReserved(m_pSelf.lock()); } diff --git a/src/desktop/Window.hpp b/src/desktop/Window.hpp index 9867a8c9..64f39558 100644 --- a/src/desktop/Window.hpp +++ b/src/desktop/Window.hpp @@ -396,10 +396,12 @@ class CWindow { } // methods - CBox getFullWindowBoundingBox(); - SBoxExtents getFullWindowExtents(); - CBox getWindowBoxUnified(uint64_t props); - CBox getWindowMainSurfaceBox(); + CBox getFullWindowBoundingBox(); + SBoxExtents getFullWindowExtents(); + CBox getWindowBoxUnified(uint64_t props); + inline CBox getWindowMainSurfaceBox() const { + return {m_vRealPosition.value().x, m_vRealPosition.value().y, m_vRealSize.value().x, m_vRealSize.value().y}; + } CBox getWindowIdealBoundingBoxIgnoreReserved(); void addWindowDeco(std::unique_ptr deco); void updateWindowDecos(); diff --git a/src/managers/input/InputManager.cpp b/src/managers/input/InputManager.cpp index 6f7d8017..028286bf 100644 --- a/src/managers/input/InputManager.cpp +++ b/src/managers/input/InputManager.cpp @@ -139,6 +139,15 @@ void CInputManager::sendMotionEventsToFocused() { } void CInputManager::mouseMoveUnified(uint32_t time, bool refocus) { + if (!g_pCompositor->m_bReadyToProcess || g_pCompositor->m_bIsShuttingDown || g_pCompositor->m_bUnsafeState) + return; + + Vector2D const mouseCoords = getMouseCoordsInternal(); + auto const MOUSECOORDSFLOORED = mouseCoords.floor(); + + if (MOUSECOORDSFLOORED == m_vLastCursorPosFloored && !refocus) + return; + static auto PFOLLOWMOUSE = CConfigValue("input:follow_mouse"); static auto PMOUSEREFOCUS = CConfigValue("input:mouse_refocus"); static auto PFOLLOWONDND = CConfigValue("misc:always_follow_on_dnd"); @@ -159,15 +168,6 @@ void CInputManager::mouseMoveUnified(uint32_t time, bool refocus) { PHLWINDOW pFoundWindow; PHLLS pFoundLayerSurface; - if (!g_pCompositor->m_bReadyToProcess || g_pCompositor->m_bIsShuttingDown || g_pCompositor->m_bUnsafeState) - return; - - Vector2D mouseCoords = getMouseCoordsInternal(); - const auto MOUSECOORDSFLOORED = mouseCoords.floor(); - - if (MOUSECOORDSFLOORED == m_vLastCursorPosFloored && !refocus) - return; - EMIT_HOOK_EVENT_CANCELLABLE("mouseMove", MOUSECOORDSFLOORED); m_vLastCursorPosFloored = MOUSECOORDSFLOORED; @@ -1418,19 +1418,10 @@ void CInputManager::unconstrainMouse() { } bool CInputManager::isConstrained() { - for (auto const& c : m_vConstraints) { - const auto C = c.lock(); - - if (!C) - continue; - - if (!C->isActive() || C->owner()->resource() != g_pCompositor->m_pLastFocus) - continue; - - return true; - } - - return false; + return std::any_of(m_vConstraints.begin(), m_vConstraints.end(), [](auto const& c) { + const auto constraint = c.lock(); + return constraint && constraint->isActive() && constraint->owner()->resource() == g_pCompositor->m_pLastFocus; + }); } bool CInputManager::isLocked() { diff --git a/src/render/decorations/DecorationPositioner.cpp b/src/render/decorations/DecorationPositioner.cpp index 4666a59e..3eb45546 100644 --- a/src/render/decorations/DecorationPositioner.cpp +++ b/src/render/decorations/DecorationPositioner.cpp @@ -297,15 +297,16 @@ SBoxExtents CDecorationPositioner::getWindowDecorationExtents(PHLWINDOW pWindow, CBox accum = pWindow->getWindowMainSurfaceBox(); for (auto const& data : m_vWindowPositioningDatas) { - if (data->pWindow.lock() != pWindow) - continue; - - if (!data->pWindow.lock() || !data->pDecoration) + if (!data->pDecoration) continue; if (!(data->pDecoration->getDecorationFlags() & DECORATION_ALLOWS_MOUSE_INPUT) && inputOnly) continue; + auto const window = data->pWindow.lock(); + if (!window || window != pWindow) + continue; + CBox decoBox; if (data->positioningInfo.policy == DECORATION_POSITION_ABSOLUTE) { @@ -373,9 +374,10 @@ CBox CDecorationPositioner::getBoxWithIncludedDecos(PHLWINDOW pWindow) { } CBox CDecorationPositioner::getWindowDecorationBox(IHyprWindowDecoration* deco) { - const auto DATA = getDataFor(deco, deco->m_pWindow.lock()); + auto const window = deco->m_pWindow.lock(); + const auto DATA = getDataFor(deco, window); CBox box = DATA->lastReply.assignedGeometry; - box.translate(getEdgeDefinedPoint(DATA->positioningInfo.edges, deco->m_pWindow.lock())); + box.translate(getEdgeDefinedPoint(DATA->positioningInfo.edges, window)); return box; } From b6e226c3200276978e487a68a16fd696fcb7e7c8 Mon Sep 17 00:00:00 2001 From: Ryan Date: Sun, 27 Oct 2024 14:26:42 -0400 Subject: [PATCH 0564/2181] groupbar: set locked color when groups are globally locked (#8257) --- src/render/decorations/CHyprGroupBarDecoration.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/render/decorations/CHyprGroupBarDecoration.cpp b/src/render/decorations/CHyprGroupBarDecoration.cpp index 1868bb5c..e342e244 100644 --- a/src/render/decorations/CHyprGroupBarDecoration.cpp +++ b/src/render/decorations/CHyprGroupBarDecoration.cpp @@ -143,7 +143,7 @@ void CHyprGroupBarDecoration::draw(PHLMONITOR pMonitor, float a) { auto* const GROUPCOLACTIVELOCKED = (CGradientValueData*)(PGROUPCOLACTIVELOCKED.ptr())->getData(); auto* const GROUPCOLINACTIVELOCKED = (CGradientValueData*)(PGROUPCOLINACTIVELOCKED.ptr())->getData(); - const bool GROUPLOCKED = m_pWindow->getGroupHead()->m_sGroupData.locked; + const bool GROUPLOCKED = m_pWindow->getGroupHead()->m_sGroupData.locked || g_pKeybindManager->m_bGroupsLocked; const auto* const PCOLACTIVE = GROUPLOCKED ? GROUPCOLACTIVELOCKED : GROUPCOLACTIVE; const auto* const PCOLINACTIVE = GROUPLOCKED ? GROUPCOLINACTIVELOCKED : GROUPCOLINACTIVE; From 5d4b54b01286c10d4b6bf402a772b5938b054ce6 Mon Sep 17 00:00:00 2001 From: Vaxry <43317083+vaxerski@users.noreply.github.com> Date: Sun, 27 Oct 2024 18:45:38 +0000 Subject: [PATCH 0565/2181] core: move internal structures to monitor pointers (#8266) --- src/Compositor.cpp | 63 ++++++++++++++-------------- src/debug/HyprCtl.cpp | 6 +-- src/desktop/LayerSurface.cpp | 24 ++++++----- src/desktop/LayerSurface.hpp | 5 ++- src/desktop/Window.cpp | 54 +++++++++++++----------- src/desktop/Window.hpp | 5 ++- src/desktop/Workspace.cpp | 30 +++++++------ src/desktop/Workspace.hpp | 11 ++--- src/events/Windows.cpp | 34 +++++++-------- src/helpers/MiscFunctions.cpp | 6 +-- src/helpers/Monitor.cpp | 20 ++++----- src/layout/DwindleLayout.cpp | 18 ++++---- src/layout/IHyprLayout.cpp | 18 ++++---- src/layout/MasterLayout.cpp | 40 +++++++++--------- src/managers/AnimationManager.cpp | 6 +-- src/managers/KeybindManager.cpp | 34 +++++++-------- src/managers/XWaylandManager.cpp | 2 +- src/managers/input/Swipe.cpp | 3 +- src/managers/input/Touch.cpp | 4 +- src/protocols/ForeignToplevelWlr.cpp | 4 +- src/protocols/LinuxDMABUF.cpp | 2 +- src/protocols/ToplevelExport.cpp | 8 ++-- src/render/OpenGL.cpp | 12 +++--- src/render/Renderer.cpp | 32 +++++++------- 24 files changed, 226 insertions(+), 215 deletions(-) diff --git a/src/Compositor.cpp b/src/Compositor.cpp index d4e2db17..a2fe9935 100644 --- a/src/Compositor.cpp +++ b/src/Compositor.cpp @@ -834,7 +834,7 @@ PHLWINDOW CCompositor::vectorToWindowUnified(const Vector2D& pos, uint8_t proper continue; const auto BB = w->getWindowBoxUnified(properties); - const auto PWINDOWMONITOR = getMonitorFromID(w->m_iMonitorID); + const auto PWINDOWMONITOR = w->m_pMonitor.lock(); // to avoid focusing windows behind special workspaces from other monitors if (!*PSPECIALFALLTHRU && PWINDOWMONITOR && PWINDOWMONITOR->activeSpecialWorkspace && w->m_pWorkspace != PWINDOWMONITOR->activeSpecialWorkspace && @@ -1063,7 +1063,7 @@ void CCompositor::focusWindow(PHLWINDOW pWindow, SP pSurface if (pWindow->m_bPinned) pWindow->m_pWorkspace = m_pLastMonitor->activeWorkspace; - const auto PMONITOR = getMonitorFromID(pWindow->m_iMonitorID); + const auto PMONITOR = pWindow->m_pMonitor.lock(); if (!isWorkspaceVisible(pWindow->m_pWorkspace)) { const auto PWORKSPACE = pWindow->m_pWorkspace; @@ -1259,7 +1259,7 @@ bool CCompositor::isWorkspaceVisibleNotCovered(PHLWORKSPACE w) { if (!valid(w)) return false; - const auto PMONITOR = getMonitorFromID(w->m_iMonitorID); + const auto PMONITOR = w->m_pMonitor.lock(); if (PMONITOR->activeSpecialWorkspace) return PMONITOR->activeSpecialWorkspace->m_iID == w->m_iID; @@ -1354,7 +1354,7 @@ PHLWINDOW CCompositor::getTopLeftWindowOnWorkspace(const WORKSPACEID& id) { if (!PWORKSPACE) return nullptr; - const auto PMONITOR = getMonitorFromID(PWORKSPACE->m_iMonitorID); + const auto PMONITOR = PWORKSPACE->m_pMonitor.lock(); for (auto const& w : m_vWindows) { if (w->workspaceID() != id || !w->m_bIsMapped || w->isHidden()) @@ -1405,7 +1405,7 @@ void CCompositor::changeWindowZOrder(PHLWINDOW pWindow, bool top) { } if (pw->m_bIsMapped) - g_pHyprRenderer->damageMonitor(getMonitorFromID(pw->m_iMonitorID)); + g_pHyprRenderer->damageMonitor(pw->m_pMonitor.lock()); }; if (top) @@ -1444,7 +1444,7 @@ void CCompositor::cleanupFadingOut(const MONITORID& monid) { auto w = ww.lock(); - if (w->m_iMonitorID != monid) + if (w->monitorID() != monid && w->m_pMonitor) continue; if (!w->m_bFadingOut || w->m_fAlpha.value() == 0.f) { @@ -1474,7 +1474,7 @@ void CCompositor::cleanupFadingOut(const MONITORID& monid) { continue; } - if (ls->monitorID != monid) + if (ls->monitorID() != monid && ls->monitor) continue; // mark blur for recalc @@ -1537,7 +1537,7 @@ PHLWINDOW CCompositor::getWindowInDirection(PHLWINDOW pWindow, char dir) { static auto PMETHOD = CConfigValue("binds:focus_preferred_method"); static auto PMONITORFALLBACK = CConfigValue("binds:window_direction_monitor_fallback"); - const auto PMONITOR = g_pCompositor->getMonitorFromID(pWindow->m_iMonitorID); + const auto PMONITOR = pWindow->m_pMonitor.lock(); if (!PMONITOR) return nullptr; // ?? @@ -1558,13 +1558,13 @@ PHLWINDOW CCompositor::getWindowInDirection(PHLWINDOW pWindow, char dir) { if (w == pWindow || !w->m_bIsMapped || w->isHidden() || (!w->isFullscreen() && w->m_bIsFloating) || !isWorkspaceVisible(w->m_pWorkspace)) continue; - if (pWindow->m_iMonitorID == w->m_iMonitorID && pWindow->m_pWorkspace != w->m_pWorkspace) + if (pWindow->m_pMonitor == w->m_pMonitor && pWindow->m_pWorkspace != w->m_pWorkspace) continue; if (PWORKSPACE->m_bHasFullscreenWindow && !w->isFullscreen() && !w->m_bCreatedOverFullscreen) continue; - if (!*PMONITORFALLBACK && pWindow->m_iMonitorID != w->m_iMonitorID) + if (!*PMONITORFALLBACK && pWindow->m_pMonitor != w->m_pMonitor) continue; const auto BWINDOWIDEALBB = w->getWindowIdealBoundingBoxIgnoreReserved(); @@ -1650,13 +1650,13 @@ PHLWINDOW CCompositor::getWindowInDirection(PHLWINDOW pWindow, char dir) { if (w == pWindow || !w->m_bIsMapped || w->isHidden() || (!w->isFullscreen() && !w->m_bIsFloating) || !isWorkspaceVisible(w->m_pWorkspace)) continue; - if (pWindow->m_iMonitorID == w->m_iMonitorID && pWindow->m_pWorkspace != w->m_pWorkspace) + if (pWindow->m_pMonitor == w->m_pMonitor && pWindow->m_pWorkspace != w->m_pWorkspace) continue; if (PWORKSPACE->m_bHasFullscreenWindow && !w->isFullscreen() && !w->m_bCreatedOverFullscreen) continue; - if (!*PMONITORFALLBACK && pWindow->m_iMonitorID != w->m_iMonitorID) + if (!*PMONITORFALLBACK && pWindow->m_pMonitor != w->m_pMonitor) continue; const auto DIST = w->middle().distance(pWindow->middle()); @@ -1996,7 +1996,7 @@ void CCompositor::swapActiveWorkspaces(PHLMONITOR pMonitorA, PHLMONITOR pMonitor const auto PWORKSPACEA = pMonitorA->activeWorkspace; const auto PWORKSPACEB = pMonitorB->activeWorkspace; - PWORKSPACEA->m_iMonitorID = pMonitorB->ID; + PWORKSPACEA->m_pMonitor = pMonitorB; PWORKSPACEA->moveToMonitor(pMonitorB->ID); for (auto const& w : m_vWindows) { @@ -2006,7 +2006,7 @@ void CCompositor::swapActiveWorkspaces(PHLMONITOR pMonitorA, PHLMONITOR pMonitor continue; } - w->m_iMonitorID = pMonitorB->ID; + w->m_pMonitor = pMonitorB; // additionally, move floating and fs windows manually if (w->m_bIsFloating) @@ -2021,7 +2021,7 @@ void CCompositor::swapActiveWorkspaces(PHLMONITOR pMonitorA, PHLMONITOR pMonitor } } - PWORKSPACEB->m_iMonitorID = pMonitorA->ID; + PWORKSPACEB->m_pMonitor = pMonitorA; PWORKSPACEB->moveToMonitor(pMonitorA->ID); for (auto const& w : m_vWindows) { @@ -2031,7 +2031,7 @@ void CCompositor::swapActiveWorkspaces(PHLMONITOR pMonitorA, PHLMONITOR pMonitor continue; } - w->m_iMonitorID = pMonitorA->ID; + w->m_pMonitor = pMonitorA; // additionally, move floating and fs windows manually if (w->m_bIsFloating) @@ -2156,12 +2156,12 @@ void CCompositor::moveWorkspaceToMonitor(PHLWORKSPACE pWorkspace, PHLMONITOR pMo // We trust the monitor to be correct. - if (pWorkspace->m_iMonitorID == pMonitor->ID) + if (pWorkspace->m_pMonitor == pMonitor) return; Debug::log(LOG, "moveWorkspaceToMonitor: Moving {} to monitor {}", pWorkspace->m_iID, pMonitor->ID); - const auto POLDMON = getMonitorFromID(pWorkspace->m_iMonitorID); + const auto POLDMON = pWorkspace->m_pMonitor.lock(); const bool SWITCHINGISACTIVE = POLDMON ? POLDMON->activeWorkspace == pWorkspace : false; @@ -2171,7 +2171,7 @@ void CCompositor::moveWorkspaceToMonitor(PHLWORKSPACE pWorkspace, PHLMONITOR pMo nextWorkspaceOnMonitorID = pWorkspace->m_iID; else { for (auto const& w : m_vWorkspaces) { - if (w->m_iMonitorID == POLDMON->ID && w->m_iID != pWorkspace->m_iID && !w->m_bIsSpecialWorkspace) { + if (w->m_pMonitor == POLDMON && w->m_iID != pWorkspace->m_iID && !w->m_bIsSpecialWorkspace) { nextWorkspaceOnMonitorID = w->m_iID; break; } @@ -2196,7 +2196,7 @@ void CCompositor::moveWorkspaceToMonitor(PHLWORKSPACE pWorkspace, PHLMONITOR pMo } // move the workspace - pWorkspace->m_iMonitorID = pMonitor->ID; + pWorkspace->m_pMonitor = pMonitor; pWorkspace->moveToMonitor(pMonitor->ID); for (auto const& w : m_vWindows) { @@ -2206,7 +2206,7 @@ void CCompositor::moveWorkspaceToMonitor(PHLWORKSPACE pWorkspace, PHLMONITOR pMo continue; } - w->m_iMonitorID = pMonitor->ID; + w->m_pMonitor = pMonitor; // additionally, move floating and fs windows manually if (w->m_bIsMapped && !w->isHidden()) { @@ -2299,7 +2299,7 @@ void CCompositor::updateFullscreenFadeOnWorkspace(PHLWORKSPACE pWorkspace) { } } - const auto PMONITOR = getMonitorFromID(pWorkspace->m_iMonitorID); + const auto PMONITOR = pWorkspace->m_pMonitor.lock(); if (pWorkspace->m_iID == PMONITOR->activeWorkspaceID() || pWorkspace->m_iID == PMONITOR->activeSpecialWorkspaceID()) { for (auto const& ls : PMONITOR->m_aLayerSurfaceLayers[ZWLR_LAYER_SHELL_V1_LAYER_TOP]) { @@ -2342,7 +2342,7 @@ void CCompositor::setWindowFullscreenState(const PHLWINDOW PWINDOW, sFullscreenS state.internal = std::clamp(state.internal, (eFullscreenMode)0, FSMODE_MAX); state.client = std::clamp(state.client, (eFullscreenMode)0, FSMODE_MAX); - const auto PMONITOR = getMonitorFromID(PWINDOW->m_iMonitorID); + const auto PMONITOR = PWINDOW->m_pMonitor.lock(); const auto PWORKSPACE = PWINDOW->m_pWorkspace; const eFullscreenMode CURRENT_EFFECTIVE_MODE = (eFullscreenMode)std::bit_floor((uint8_t)PWINDOW->m_sFullscreenState.internal); @@ -2360,7 +2360,7 @@ void CCompositor::setWindowFullscreenState(const PHLWINDOW PWINDOW, sFullscreenS if (!CHANGEINTERNAL) { PWINDOW->updateDynamicRules(); updateWindowAnimatedDecorationValues(PWINDOW); - g_pLayoutManager->getCurrentLayout()->recalculateMonitor(PWINDOW->m_iMonitorID); + g_pLayoutManager->getCurrentLayout()->recalculateMonitor(PWINDOW->monitorID()); return; } @@ -2375,7 +2375,7 @@ void CCompositor::setWindowFullscreenState(const PHLWINDOW PWINDOW, sFullscreenS PWINDOW->updateDynamicRules(); updateWindowAnimatedDecorationValues(PWINDOW); - g_pLayoutManager->getCurrentLayout()->recalculateMonitor(PWINDOW->m_iMonitorID); + g_pLayoutManager->getCurrentLayout()->recalculateMonitor(PWINDOW->monitorID()); // make all windows on the same workspace under the fullscreen window for (auto const& w : m_vWindows) { @@ -2663,13 +2663,12 @@ PHLWORKSPACE CCompositor::createNewWorkspace(const WORKSPACEID& id, const MONITO auto monID = monid; // check if bound - if (const auto PMONITOR = g_pConfigManager->getBoundMonitorForWS(NAME); PMONITOR) { + if (const auto PMONITOR = g_pConfigManager->getBoundMonitorForWS(NAME); PMONITOR) monID = PMONITOR->ID; - } const bool SPECIAL = id >= SPECIAL_WORKSPACE_START && id <= -2; - const auto PWORKSPACE = m_vWorkspaces.emplace_back(CWorkspace::create(id, monID, NAME, SPECIAL, isEmpty)); + const auto PWORKSPACE = m_vWorkspaces.emplace_back(CWorkspace::create(id, getMonitorFromID(monID), NAME, SPECIAL, isEmpty)); PWORKSPACE->m_fAlpha.setValueAndWarp(0); @@ -2751,15 +2750,15 @@ void CCompositor::moveWindowToWorkspaceSafe(PHLWINDOW pWindow, PHLWORKSPACE pWor const PHLWINDOW pFirstWindowOnWorkspace = g_pCompositor->getFirstWindowOnWorkspace(pWorkspace->m_iID); const int visibleWindowsOnWorkspace = g_pCompositor->getWindowsOnWorkspace(pWorkspace->m_iID, std::nullopt, true); - const auto PWINDOWMONITOR = g_pCompositor->getMonitorFromID(pWindow->m_iMonitorID); + const auto PWINDOWMONITOR = pWindow->m_pMonitor.lock(); const auto POSTOMON = pWindow->m_vRealPosition.goal() - PWINDOWMONITOR->vecPosition; - const auto PWORKSPACEMONITOR = g_pCompositor->getMonitorFromID(pWorkspace->m_iMonitorID); + const auto PWORKSPACEMONITOR = pWorkspace->m_pMonitor.lock(); if (!pWindow->m_bIsFloating) g_pLayoutManager->getCurrentLayout()->onWindowRemovedTiling(pWindow); pWindow->moveToWorkspace(pWorkspace); - pWindow->m_iMonitorID = pWorkspace->m_iMonitorID; + pWindow->m_pMonitor = pWorkspace->m_pMonitor; static auto PGROUPONMOVETOWORKSPACE = CConfigValue("group:group_on_movetoworkspace"); if (*PGROUPONMOVETOWORKSPACE && visibleWindowsOnWorkspace == 1 && pFirstWindowOnWorkspace && pFirstWindowOnWorkspace != pWindow && @@ -3077,7 +3076,7 @@ void CCompositor::onNewMonitor(SP output) { checkDefaultCursorWarp(PNEWMONITOR); for (auto const& w : g_pCompositor->m_vWindows) { - if (w->m_iMonitorID == PNEWMONITOR->ID) { + if (w->m_pMonitor == PNEWMONITOR) { w->m_iLastSurfaceMonitorID = MONITOR_INVALID; w->updateSurfaceScaleTransformDetails(); } diff --git a/src/debug/HyprCtl.cpp b/src/debug/HyprCtl.cpp index 82290f94..bf3ecfc8 100644 --- a/src/debug/HyprCtl.cpp +++ b/src/debug/HyprCtl.cpp @@ -242,7 +242,7 @@ std::string CHyprCtl::getWindowData(PHLWINDOW w, eHyprCtlOutputFormat format) { (uintptr_t)w.get(), (w->m_bIsMapped ? "true" : "false"), (w->isHidden() ? "true" : "false"), (int)w->m_vRealPosition.goal().x, (int)w->m_vRealPosition.goal().y, (int)w->m_vRealSize.goal().x, (int)w->m_vRealSize.goal().y, w->m_pWorkspace ? w->workspaceID() : WORKSPACE_INVALID, escapeJSONStrings(!w->m_pWorkspace ? "" : w->m_pWorkspace->m_szName), ((int)w->m_bIsFloating == 1 ? "true" : "false"), (w->m_bIsPseudotiled ? "true" : "false"), - (int64_t)w->m_iMonitorID, escapeJSONStrings(w->m_szClass), escapeJSONStrings(w->m_szTitle), escapeJSONStrings(w->m_szInitialClass), + (int64_t)w->monitorID(), escapeJSONStrings(w->m_szClass), escapeJSONStrings(w->m_szTitle), escapeJSONStrings(w->m_szInitialClass), escapeJSONStrings(w->m_szInitialTitle), w->getPID(), ((int)w->m_bIsX11 == 1 ? "true" : "false"), (w->m_bPinned ? "true" : "false"), (uint8_t)w->m_sFullscreenState.internal, (uint8_t)w->m_sFullscreenState.client, getGroupedData(w, format), getTagsData(w, format), (uintptr_t)w->m_pSwallowed.lock().get(), getFocusHistoryID(w)); @@ -254,7 +254,7 @@ std::string CHyprCtl::getWindowData(PHLWINDOW w, eHyprCtlOutputFormat format) { "{}\n\tfullscreen: {}\n\tfullscreenClient: {}\n\tgrouped: {}\n\ttags: {}\n\tswallowing: {:x}\n\tfocusHistoryID: {}\n\n", (uintptr_t)w.get(), w->m_szTitle, (int)w->m_bIsMapped, (int)w->isHidden(), (int)w->m_vRealPosition.goal().x, (int)w->m_vRealPosition.goal().y, (int)w->m_vRealSize.goal().x, (int)w->m_vRealSize.goal().y, w->m_pWorkspace ? w->workspaceID() : WORKSPACE_INVALID, (!w->m_pWorkspace ? "" : w->m_pWorkspace->m_szName), - (int)w->m_bIsFloating, (int)w->m_bIsPseudotiled, (int64_t)w->m_iMonitorID, w->m_szClass, w->m_szTitle, w->m_szInitialClass, w->m_szInitialTitle, w->getPID(), + (int)w->m_bIsFloating, (int)w->m_bIsPseudotiled, (int64_t)w->monitorID(), w->m_szClass, w->m_szTitle, w->m_szInitialClass, w->m_szInitialTitle, w->getPID(), (int)w->m_bIsX11, (int)w->m_bPinned, (uint8_t)w->m_sFullscreenState.internal, (uint8_t)w->m_sFullscreenState.client, getGroupedData(w, format), getTagsData(w, format), (uintptr_t)w->m_pSwallowed.lock().get(), getFocusHistoryID(w)); } @@ -288,7 +288,7 @@ std::string clientsRequest(eHyprCtlOutputFormat format, std::string request) { std::string CHyprCtl::getWorkspaceData(PHLWORKSPACE w, eHyprCtlOutputFormat format) { const auto PLASTW = w->getLastFocusedWindow(); - const auto PMONITOR = g_pCompositor->getMonitorFromID(w->m_iMonitorID); + const auto PMONITOR = w->m_pMonitor.lock(); if (format == eHyprCtlOutputFormat::FORMAT_JSON) { return std::format(R"#({{ "id": {}, diff --git a/src/desktop/LayerSurface.cpp b/src/desktop/LayerSurface.cpp index 6c024ee0..f073da82 100644 --- a/src/desktop/LayerSurface.cpp +++ b/src/desktop/LayerSurface.cpp @@ -26,7 +26,7 @@ PHLLS CLayerSurface::create(SP resource) { pLS->layer = resource->current.layer; pLS->popupHead = std::make_unique(pLS); - pLS->monitorID = pMonitor->ID; + pLS->monitor = pMonitor; pMonitor->m_aLayerSurfaceLayers[resource->current.layer].emplace_back(pLS); pLS->forceBlur = g_pConfigManager->shouldBlurLS(pLS->szNamespace); @@ -50,7 +50,7 @@ PHLLS CLayerSurface::create(SP resource) { void CLayerSurface::registerCallbacks() { alpha.setUpdateCallback([this](void*) { if (dimAround) - g_pHyprRenderer->damageMonitor(g_pCompositor->getMonitorFromID(monitorID)); + g_pHyprRenderer->damageMonitor(monitor.lock()); }); } @@ -82,9 +82,9 @@ CLayerSurface::~CLayerSurface() { void CLayerSurface::onDestroy() { Debug::log(LOG, "LayerSurface {:x} destroyed", (uintptr_t)layerSurface.get()); - const auto PMONITOR = g_pCompositor->getMonitorFromID(monitorID); + const auto PMONITOR = monitor.lock(); - if (!g_pCompositor->getMonitorFromID(monitorID)) + if (!PMONITOR) Debug::log(WARN, "Layersurface destroyed on an invalid monitor (removed?)"); if (!fadingOut) { @@ -137,7 +137,7 @@ void CLayerSurface::onMap() { g_pCompositor->removeFromFadingOutSafe(self.lock()); // fix if it changed its mon - const auto PMONITOR = g_pCompositor->getMonitorFromID(monitorID); + const auto PMONITOR = monitor.lock(); if (!PMONITOR) return; @@ -197,7 +197,7 @@ void CLayerSurface::onUnmap() { std::erase_if(g_pInputManager->m_dExclusiveLSes, [this](const auto& other) { return !other.lock() || other.lock() == self.lock(); }); - if (!g_pCompositor->getMonitorFromID(monitorID) || g_pCompositor->m_bUnsafeState) { + if (!monitor || g_pCompositor->m_bUnsafeState) { Debug::log(WARN, "Layersurface unmapping on invalid monitor (removed?) ignoring."); g_pCompositor->addToFadingOutSafe(self.lock()); @@ -221,7 +221,7 @@ void CLayerSurface::onUnmap() { g_pCompositor->addToFadingOutSafe(self.lock()); - const auto PMONITOR = g_pCompositor->getMonitorFromID(monitorID); + const auto PMONITOR = monitor.lock(); const bool WASLASTFOCUS = g_pCompositor->m_pLastFocus == surface->resource(); @@ -256,13 +256,13 @@ void CLayerSurface::onCommit() { if (layerSurface->surface && !layerSurface->surface->current.texture) { fadingOut = false; geometry = {}; - g_pHyprRenderer->arrangeLayersForMonitor(monitorID); + g_pHyprRenderer->arrangeLayersForMonitor(monitorID()); } return; } - const auto PMONITOR = g_pCompositor->getMonitorFromID(monitorID); + const auto PMONITOR = monitor.lock(); if (!PMONITOR) return; @@ -336,7 +336,7 @@ void CLayerSurface::onCommit() { // moveMouseUnified won't focus non interactive layers but it won't unfocus them either, // so unfocus the surface here. g_pCompositor->focusSurface(nullptr); - g_pInputManager->refocusLastWindow(g_pCompositor->getMonitorFromID(monitorID)); + g_pInputManager->refocusLastWindow(monitor.lock()); } else if (!WASEXCLUSIVE && ISEXCLUSIVE) { // if now exclusive and not previously g_pSeatManager->setGrab(nullptr); @@ -545,3 +545,7 @@ int CLayerSurface::popupsCount() { popupHead->breadthfirst([](CPopup* p, void* data) { *(int*)data += 1; }, &no); return no; } + +MONITORID CLayerSurface::monitorID() { + return monitor ? monitor->ID : MONITOR_INVALID; +} diff --git a/src/desktop/LayerSurface.hpp b/src/desktop/LayerSurface.hpp index e0f17039..6aa8eb81 100644 --- a/src/desktop/LayerSurface.hpp +++ b/src/desktop/LayerSurface.hpp @@ -42,7 +42,7 @@ class CLayerSurface { bool mapped = false; uint32_t layer = 0; - MONITORID monitorID = -1; + PHLMONITORREF monitor; bool fadingOut = false; bool readyToDelete = false; @@ -70,6 +70,7 @@ class CLayerSurface { void onMap(); void onUnmap(); void onCommit(); + MONITORID monitorID(); private: struct { @@ -83,6 +84,6 @@ class CLayerSurface { // For the list lookup bool operator==(const CLayerSurface& rhs) const { - return layerSurface == rhs.layerSurface && monitorID == rhs.monitorID; + return layerSurface == rhs.layerSurface && monitor == rhs.monitor; } }; diff --git a/src/desktop/Window.cpp b/src/desktop/Window.cpp index 0772b676..e4f987eb 100644 --- a/src/desktop/Window.cpp +++ b/src/desktop/Window.cpp @@ -113,7 +113,7 @@ SBoxExtents CWindow::getFullWindowExtents() { const int BORDERSIZE = getRealBorderSize(); if (m_sWindowData.dimAround.valueOrDefault()) { - if (const auto PMONITOR = g_pCompositor->getMonitorFromID(m_iMonitorID); PMONITOR) + if (const auto PMONITOR = m_pMonitor.lock(); PMONITOR) return {{m_vRealPosition.value().x - PMONITOR->vecPosition.x, m_vRealPosition.value().y - PMONITOR->vecPosition.y}, {PMONITOR->vecSize.x - (m_vRealPosition.value().x - PMONITOR->vecPosition.x), PMONITOR->vecSize.y - (m_vRealPosition.value().y - PMONITOR->vecPosition.y)}}; } @@ -173,7 +173,7 @@ SBoxExtents CWindow::getFullWindowExtents() { CBox CWindow::getFullWindowBoundingBox() { if (m_sWindowData.dimAround.valueOrDefault()) { - if (const auto PMONITOR = g_pCompositor->getMonitorFromID(m_iMonitorID); PMONITOR) + if (const auto PMONITOR = m_pMonitor.lock(); PMONITOR) return {PMONITOR->vecPosition.x, PMONITOR->vecPosition.y, PMONITOR->vecSize.x, PMONITOR->vecSize.y}; } @@ -186,7 +186,7 @@ CBox CWindow::getFullWindowBoundingBox() { } CBox CWindow::getWindowIdealBoundingBoxIgnoreReserved() { - const auto PMONITOR = g_pCompositor->getMonitorFromID(m_iMonitorID); + const auto PMONITOR = m_pMonitor.lock(); if (!PMONITOR) return {m_vPosition, m_vSize}; @@ -221,7 +221,7 @@ CBox CWindow::getWindowIdealBoundingBoxIgnoreReserved() { CBox CWindow::getWindowBoxUnified(uint64_t properties) { if (m_sWindowData.dimAround.valueOrDefault()) { - const auto PMONITOR = g_pCompositor->getMonitorFromID(m_iMonitorID); + const auto PMONITOR = m_pMonitor.lock(); if (PMONITOR) return {PMONITOR->vecPosition.x, PMONITOR->vecPosition.y, PMONITOR->vecSize.x, PMONITOR->vecSize.y}; } @@ -352,9 +352,9 @@ void CWindow::updateSurfaceScaleTransformDetails(bool force) { const auto PLASTMONITOR = g_pCompositor->getMonitorFromID(m_iLastSurfaceMonitorID); - m_iLastSurfaceMonitorID = m_iMonitorID; + m_iLastSurfaceMonitorID = monitorID(); - const auto PNEWMONITOR = g_pCompositor->getMonitorFromID(m_iMonitorID); + const auto PNEWMONITOR = m_pMonitor.lock(); if (!PNEWMONITOR) return; @@ -366,10 +366,10 @@ void CWindow::updateSurfaceScaleTransformDetails(bool force) { m_pWLSurface->resource()->breadthfirst([PNEWMONITOR](SP s, const Vector2D& offset, void* d) { s->enter(PNEWMONITOR->self.lock()); }, nullptr); } - m_pWLSurface->resource()->breadthfirst( - [this](SP s, const Vector2D& offset, void* d) { - const auto PMONITOR = g_pCompositor->getMonitorFromID(m_iMonitorID); + const auto PMONITOR = m_pMonitor.lock(); + m_pWLSurface->resource()->breadthfirst( + [PMONITOR](SP s, const Vector2D& offset, void* d) { const auto PSURFACE = CWLSurface::fromResource(s); if (PSURFACE && PSURFACE->m_fLastScale == PMONITOR->scale) return; @@ -404,7 +404,7 @@ void CWindow::moveToWorkspace(PHLWORKSPACE pWorkspace) { const auto OLDWORKSPACE = m_pWorkspace; - m_iMonitorMovedFrom = OLDWORKSPACE ? OLDWORKSPACE->m_iMonitorID : -1; + m_iMonitorMovedFrom = OLDWORKSPACE ? OLDWORKSPACE->monitorID() : -1; m_fMovingToWorkspaceAlpha.setValueAndWarp(1.F); m_fMovingToWorkspaceAlpha = 0.F; m_fMovingToWorkspaceAlpha.setCallbackOnEnd([this](void* thisptr) { m_iMonitorMovedFrom = -1; }); @@ -415,11 +415,11 @@ void CWindow::moveToWorkspace(PHLWORKSPACE pWorkspace) { g_pCompositor->updateWorkspaceWindows(OLDWORKSPACE->m_iID); g_pCompositor->updateWorkspaceWindowData(OLDWORKSPACE->m_iID); - g_pLayoutManager->getCurrentLayout()->recalculateMonitor(OLDWORKSPACE->m_iMonitorID); + g_pLayoutManager->getCurrentLayout()->recalculateMonitor(OLDWORKSPACE->monitorID()); g_pCompositor->updateWorkspaceWindows(workspaceID()); g_pCompositor->updateWorkspaceWindowData(workspaceID()); - g_pLayoutManager->getCurrentLayout()->recalculateMonitor(m_iMonitorID); + g_pLayoutManager->getCurrentLayout()->recalculateMonitor(monitorID()); g_pCompositor->updateAllWindowsAnimatedDecorationValues(); @@ -431,14 +431,14 @@ void CWindow::moveToWorkspace(PHLWORKSPACE pWorkspace) { if (const auto SWALLOWED = m_pSwallowed.lock()) { SWALLOWED->moveToWorkspace(pWorkspace); - SWALLOWED->m_iMonitorID = m_iMonitorID; + SWALLOWED->m_pMonitor = m_pMonitor; } // update xwayland coords g_pXWaylandManager->setWindowSize(m_pSelf.lock(), m_vRealSize.value()); if (OLDWORKSPACE && g_pCompositor->isWorkspaceSpecial(OLDWORKSPACE->m_iID) && g_pCompositor->getWindowsOnWorkspace(OLDWORKSPACE->m_iID) == 0 && *PCLOSEONLASTSPECIAL) { - if (const auto PMONITOR = g_pCompositor->getMonitorFromID(OLDWORKSPACE->m_iMonitorID); PMONITOR) + if (const auto PMONITOR = OLDWORKSPACE->m_pMonitor.lock(); PMONITOR) PMONITOR->setSpecialWorkspace(nullptr); } } @@ -517,19 +517,19 @@ void CWindow::onUnmap() { std::erase_if(g_pCompositor->m_vWindowFocusHistory, [&](const auto& other) { return other.expired() || other.lock().get() == this; }); if (*PCLOSEONLASTSPECIAL && g_pCompositor->getWindowsOnWorkspace(workspaceID()) == 0 && onSpecialWorkspace()) { - const auto PMONITOR = g_pCompositor->getMonitorFromID(m_iMonitorID); + const auto PMONITOR = m_pMonitor.lock(); if (PMONITOR && PMONITOR->activeSpecialWorkspace && PMONITOR->activeSpecialWorkspace == m_pWorkspace) PMONITOR->setSpecialWorkspace(nullptr); } - const auto PMONITOR = g_pCompositor->getMonitorFromID(m_iMonitorID); + const auto PMONITOR = m_pMonitor.lock(); if (PMONITOR && PMONITOR->solitaryClient.lock().get() == this) PMONITOR->solitaryClient.reset(); g_pCompositor->updateWorkspaceWindows(workspaceID()); g_pCompositor->updateWorkspaceWindowData(workspaceID()); - g_pLayoutManager->getCurrentLayout()->recalculateMonitor(m_iMonitorID); + g_pLayoutManager->getCurrentLayout()->recalculateMonitor(monitorID()); g_pCompositor->updateAllWindowsAnimatedDecorationValues(); m_pWorkspace.reset(); @@ -790,7 +790,7 @@ void CWindow::updateDynamicRules() { EMIT_HOOK_EVENT("windowUpdateRules", m_pSelf.lock()); - g_pLayoutManager->getCurrentLayout()->recalculateMonitor(m_iMonitorID); + g_pLayoutManager->getCurrentLayout()->recalculateMonitor(monitorID()); } // check if the point is "hidden" under a rounded corner of the window @@ -857,7 +857,7 @@ void CWindow::createGroup() { g_pCompositor->updateWorkspaceWindows(workspaceID()); g_pCompositor->updateWorkspaceWindowData(workspaceID()); - g_pLayoutManager->getCurrentLayout()->recalculateMonitor(m_iMonitorID); + g_pLayoutManager->getCurrentLayout()->recalculateMonitor(monitorID()); g_pCompositor->updateAllWindowsAnimatedDecorationValues(); g_pEventManager->postEvent(SHyprIPCEvent{"togglegroup", std::format("1,{:x}", (uintptr_t)this)}); @@ -875,7 +875,7 @@ void CWindow::destroyGroup() { updateWindowDecos(); g_pCompositor->updateWorkspaceWindows(workspaceID()); g_pCompositor->updateWorkspaceWindowData(workspaceID()); - g_pLayoutManager->getCurrentLayout()->recalculateMonitor(m_iMonitorID); + g_pLayoutManager->getCurrentLayout()->recalculateMonitor(monitorID()); g_pCompositor->updateAllWindowsAnimatedDecorationValues(); g_pEventManager->postEvent(SHyprIPCEvent{"togglegroup", std::format("0,{:x}", (uintptr_t)this)}); @@ -911,7 +911,7 @@ void CWindow::destroyGroup() { g_pCompositor->updateWorkspaceWindows(workspaceID()); g_pCompositor->updateWorkspaceWindowData(workspaceID()); - g_pLayoutManager->getCurrentLayout()->recalculateMonitor(m_iMonitorID); + g_pLayoutManager->getCurrentLayout()->recalculateMonitor(monitorID()); g_pCompositor->updateAllWindowsAnimatedDecorationValues(); if (!addresses.empty()) @@ -1087,7 +1087,7 @@ void CWindow::updateGroupOutputs() { const auto WS = m_pWorkspace; while (curr.get() != this) { - curr->m_iMonitorID = m_iMonitorID; + curr->m_pMonitor = m_pMonitor; curr->moveToWorkspace(WS); curr->m_vRealPosition = m_vRealPosition.goal(); @@ -1209,7 +1209,7 @@ void CWindow::onWorkspaceAnimUpdate() { if (!PWORKSPACE) return; - const auto PWSMON = g_pCompositor->getMonitorFromID(PWORKSPACE->m_iMonitorID); + const auto PWSMON = m_pMonitor.lock(); if (!PWSMON) return; @@ -1275,6 +1275,10 @@ WORKSPACEID CWindow::workspaceID() { return m_pWorkspace ? m_pWorkspace->m_iID : m_iLastWorkspace; } +MONITORID CWindow::monitorID() { + return m_pMonitor ? m_pMonitor->ID : MONITOR_INVALID; +} + bool CWindow::onSpecialWorkspace() { return m_pWorkspace ? m_pWorkspace->m_bIsSpecialWorkspace : g_pCompositor->isWorkspaceSpecial(m_iLastWorkspace); } @@ -1461,7 +1465,7 @@ void CWindow::onX11Configure(CBox box) { m_pXWaylandSurface->configure(box); m_vPendingReportedSize = box.size(); m_vReportedSize = box.size(); - if (const auto PMONITOR = g_pCompositor->getMonitorFromID(m_iMonitorID); PMONITOR) + if (const auto PMONITOR = m_pMonitor.lock(); PMONITOR) m_fX11SurfaceScaledBy = PMONITOR->scale; return; } @@ -1487,7 +1491,7 @@ void CWindow::onX11Configure(CBox box) { static auto PXWLFORCESCALEZERO = CConfigValue("xwayland:force_zero_scaling"); if (*PXWLFORCESCALEZERO) { - if (const auto PMONITOR = g_pCompositor->getMonitorFromID(m_iMonitorID); PMONITOR) { + if (const auto PMONITOR = m_pMonitor.lock(); PMONITOR) { m_vRealSize.setValueAndWarp(m_vRealSize.goal() / PMONITOR->scale); m_fX11SurfaceScaledBy = PMONITOR->scale; } diff --git a/src/desktop/Window.hpp b/src/desktop/Window.hpp index 64f39558..825e8ca2 100644 --- a/src/desktop/Window.hpp +++ b/src/desktop/Window.hpp @@ -272,12 +272,12 @@ class CWindow { bool m_bDraggingTiled = false; // for dragging around tiled windows bool m_bWasMaximized = false; sFullscreenState m_sFullscreenState = {.internal = FSMODE_NONE, .client = FSMODE_NONE}; - MONITORID m_iMonitorID = -1; std::string m_szTitle = ""; std::string m_szClass = ""; std::string m_szInitialTitle = ""; std::string m_szInitialClass = ""; PHLWORKSPACE m_pWorkspace; + PHLMONITORREF m_pMonitor; bool m_bIsMapped = false; @@ -429,6 +429,7 @@ class CWindow { void setSuspended(bool suspend); bool visibleOnMonitor(PHLMONITOR pMonitor); WORKSPACEID workspaceID(); + MONITORID monitorID(); bool onSpecialWorkspace(); void activate(bool force = false); int surfacesCount(); @@ -559,7 +560,7 @@ struct std::formatter : std::formatter { if (formatWorkspace) std::format_to(out, ", workspace: {}", w->m_pWorkspace ? w->workspaceID() : WORKSPACE_INVALID); if (formatMonitor) - std::format_to(out, ", monitor: {}", w->m_iMonitorID); + std::format_to(out, ", monitor: {}", w->monitorID()); if (formatClass) std::format_to(out, ", class: {}", w->m_szClass); return std::format_to(out, "]"); diff --git a/src/desktop/Workspace.cpp b/src/desktop/Workspace.cpp index 2d92659c..2e1e91f2 100644 --- a/src/desktop/Workspace.cpp +++ b/src/desktop/Workspace.cpp @@ -5,14 +5,14 @@ #include using namespace Hyprutils::String; -PHLWORKSPACE CWorkspace::create(WORKSPACEID id, MONITORID monitorID, std::string name, bool special, bool isEmpty) { - PHLWORKSPACE workspace = makeShared(id, monitorID, name, special, isEmpty); +PHLWORKSPACE CWorkspace::create(WORKSPACEID id, PHLMONITOR monitor, std::string name, bool special, bool isEmpty) { + PHLWORKSPACE workspace = makeShared(id, monitor, name, special, isEmpty); workspace->init(workspace); return workspace; } -CWorkspace::CWorkspace(WORKSPACEID id, MONITORID monitorID, std::string name, bool special, bool isEmpty) { - m_iMonitorID = monitorID; +CWorkspace::CWorkspace(WORKSPACEID id, PHLMONITOR monitor, std::string name, bool special, bool isEmpty) { + m_pMonitor = monitor; m_iID = id; m_szName = name; m_bIsSpecialWorkspace = special; @@ -103,7 +103,7 @@ void CWorkspace::startAnim(bool in, bool left, bool instant) { }); if (ANIMSTYLE.starts_with("slidefade")) { - const auto PMONITOR = g_pCompositor->getMonitorFromID(m_iMonitorID); + const auto PMONITOR = m_pMonitor.lock(); float movePerc = 100.f; if (ANIMSTYLE.find("%") != std::string::npos) { @@ -151,7 +151,7 @@ void CWorkspace::startAnim(bool in, bool left, bool instant) { } } else if (ANIMSTYLE == "slidevert") { // fallback is slide - const auto PMONITOR = g_pCompositor->getMonitorFromID(m_iMonitorID); + const auto PMONITOR = m_pMonitor.lock(); const auto YDISTANCE = PMONITOR->vecSize.y + *PWORKSPACEGAP; m_fAlpha.setValueAndWarp(1.f); // fix a bug, if switching from fade -> slide. @@ -164,7 +164,7 @@ void CWorkspace::startAnim(bool in, bool left, bool instant) { } } else { // fallback is slide - const auto PMONITOR = g_pCompositor->getMonitorFromID(m_iMonitorID); + const auto PMONITOR = m_pMonitor.lock(); const auto XDISTANCE = PMONITOR->vecSize.x + *PWORKSPACEGAP; m_fAlpha.setValueAndWarp(1.f); // fix a bug, if switching from fade -> slide. @@ -224,7 +224,7 @@ void CWorkspace::rememberPrevWorkspace(const PHLWORKSPACE& prev) { m_sPrevWorkspace.id = prev->m_iID; m_sPrevWorkspace.name = prev->m_szName; - if (prev->m_iMonitorID == m_iMonitorID) { + if (prev->m_pMonitor == m_pMonitor) { m_sPrevWorkspacePerMonitor.id = prev->m_iID; m_sPrevWorkspacePerMonitor.name = prev->m_szName; } @@ -347,7 +347,7 @@ bool CWorkspace::matchesStaticSelector(const std::string& selector_) { const auto PMONITOR = g_pCompositor->getMonitorFromString(prop); - if (!(PMONITOR ? PMONITOR->ID == m_iMonitorID : false)) + if (!(PMONITOR ? PMONITOR == m_pMonitor : false)) return false; continue; } @@ -512,12 +512,16 @@ bool CWorkspace::matchesStaticSelector(const std::string& selector_) { } void CWorkspace::markInert() { - m_bInert = true; - m_iID = WORKSPACE_INVALID; - m_iMonitorID = MONITOR_INVALID; - m_bVisible = false; + m_bInert = true; + m_iID = WORKSPACE_INVALID; + m_bVisible = false; + m_pMonitor.reset(); } bool CWorkspace::inert() { return m_bInert; } + +MONITORID CWorkspace::monitorID() { + return m_pMonitor ? m_pMonitor->ID : MONITOR_INVALID; +} diff --git a/src/desktop/Workspace.hpp b/src/desktop/Workspace.hpp index 7a32459c..3ed9f50c 100644 --- a/src/desktop/Workspace.hpp +++ b/src/desktop/Workspace.hpp @@ -17,16 +17,16 @@ class CWindow; class CWorkspace { public: - static PHLWORKSPACE create(WORKSPACEID id, MONITORID monitorID, std::string name, bool special = false, bool isEmpty = true); + static PHLWORKSPACE create(WORKSPACEID id, PHLMONITOR monitor, std::string name, bool special = false, bool isEmpty = true); // use create() don't use this - CWorkspace(WORKSPACEID id, MONITORID monitorID, std::string name, bool special = false, bool isEmpty = true); + CWorkspace(WORKSPACEID id, PHLMONITOR monitor, std::string name, bool special = false, bool isEmpty = true); ~CWorkspace(); // Workspaces ID-based have IDs > 0 // and workspaces name-based have IDs starting with -1337 - WORKSPACEID m_iID = WORKSPACE_INVALID; - std::string m_szName = ""; - MONITORID m_iMonitorID = MONITOR_INVALID; + WORKSPACEID m_iID = WORKSPACE_INVALID; + std::string m_szName = ""; + PHLMONITORREF m_pMonitor; // Previous workspace ID and name is stored during a workspace change, allowing travel // to the previous workspace. SWorkspaceIDName m_sPrevWorkspace, m_sPrevWorkspacePerMonitor; @@ -68,6 +68,7 @@ class CWorkspace { void setActive(bool on); void moveToMonitor(const MONITORID&); + MONITORID monitorID(); PHLWINDOW getLastFocusedWindow(); void rememberPrevWorkspace(const PHLWORKSPACE& prevWorkspace); diff --git a/src/events/Windows.cpp b/src/events/Windows.cpp index e8abe30d..30d982fb 100644 --- a/src/events/Windows.cpp +++ b/src/events/Windows.cpp @@ -53,7 +53,7 @@ void Events::listener_mapWindow(void* owner, void* data) { PMONITOR = g_pCompositor->m_pLastMonitor.lock(); } auto PWORKSPACE = PMONITOR->activeSpecialWorkspace ? PMONITOR->activeSpecialWorkspace : PMONITOR->activeWorkspace; - PWINDOW->m_iMonitorID = PMONITOR->ID; + PWINDOW->m_pMonitor = PMONITOR; PWINDOW->m_pWorkspace = PWORKSPACE; PWINDOW->m_bIsMapped = true; PWINDOW->m_bReadyToDelete = false; @@ -144,18 +144,18 @@ void Events::listener_mapWindow(void* owner, void* data) { const auto MONITORSTR = trim(r.szRule.substr(r.szRule.find(' '))); if (MONITORSTR == "unset") { - PWINDOW->m_iMonitorID = PMONITOR->ID; + PWINDOW->m_pMonitor = PMONITOR; } else { if (isNumber(MONITORSTR)) { const MONITORID MONITOR = std::stoi(MONITORSTR); - if (!g_pCompositor->getMonitorFromID(MONITOR)) - PWINDOW->m_iMonitorID = 0; + if (const auto PM = g_pCompositor->getMonitorFromID(MONITOR); PM) + PWINDOW->m_pMonitor = PM; else - PWINDOW->m_iMonitorID = MONITOR; + PWINDOW->m_pMonitor = g_pCompositor->m_vMonitors.at(0); } else { const auto PMONITOR = g_pCompositor->getMonitorFromName(MONITORSTR); if (PMONITOR) - PWINDOW->m_iMonitorID = PMONITOR->ID; + PWINDOW->m_pMonitor = PMONITOR; else { Debug::log(ERR, "No monitor in monitor {} rule", MONITORSTR); continue; @@ -163,10 +163,10 @@ void Events::listener_mapWindow(void* owner, void* data) { } } - const auto PMONITORFROMID = g_pCompositor->getMonitorFromID(PWINDOW->m_iMonitorID); + const auto PMONITORFROMID = PWINDOW->m_pMonitor.lock(); - if (PWINDOW->m_iMonitorID != PMONITOR->ID) { - g_pKeybindManager->m_mDispatchers["focusmonitor"](std::to_string(PWINDOW->m_iMonitorID)); + if (PWINDOW->m_pMonitor != PMONITOR) { + g_pKeybindManager->m_mDispatchers["focusmonitor"](std::to_string(PWINDOW->monitorID())); PMONITOR = PMONITORFROMID; } PWINDOW->m_pWorkspace = PMONITOR->activeSpecialWorkspace ? PMONITOR->activeSpecialWorkspace : PMONITOR->activeWorkspace; @@ -296,19 +296,19 @@ void Events::listener_mapWindow(void* owner, void* data) { auto pWorkspace = g_pCompositor->getWorkspaceByID(REQUESTEDWORKSPACEID); if (!pWorkspace) - pWorkspace = g_pCompositor->createNewWorkspace(REQUESTEDWORKSPACEID, PWINDOW->m_iMonitorID, requestedWorkspaceName); + pWorkspace = g_pCompositor->createNewWorkspace(REQUESTEDWORKSPACEID, PWINDOW->monitorID(), requestedWorkspaceName); PWORKSPACE = pWorkspace; PWINDOW->m_pWorkspace = pWorkspace; - PWINDOW->m_iMonitorID = pWorkspace->m_iMonitorID; + PWINDOW->m_pMonitor = pWorkspace->m_pMonitor; - if (g_pCompositor->getMonitorFromID(PWINDOW->m_iMonitorID)->activeSpecialWorkspace && !pWorkspace->m_bIsSpecialWorkspace) + if (PWINDOW->m_pMonitor.lock()->activeSpecialWorkspace && !pWorkspace->m_bIsSpecialWorkspace) workspaceSilent = true; if (!workspaceSilent) { if (pWorkspace->m_bIsSpecialWorkspace) - g_pCompositor->getMonitorFromID(pWorkspace->m_iMonitorID)->setSpecialWorkspace(pWorkspace); + pWorkspace->m_pMonitor->setSpecialWorkspace(pWorkspace); else if (PMONITOR->activeWorkspaceID() != REQUESTEDWORKSPACEID) g_pKeybindManager->m_mDispatchers["workspace"](requestedWorkspaceName); @@ -574,7 +574,7 @@ void Events::listener_mapWindow(void* owner, void* data) { g_pLayoutManager->getCurrentLayout()->onWindowRemoved(SWALLOWER); g_pHyprRenderer->damageWindow(SWALLOWER); SWALLOWER->setHidden(true); - g_pLayoutManager->getCurrentLayout()->recalculateMonitor(PWINDOW->m_iMonitorID); + g_pLayoutManager->getCurrentLayout()->recalculateMonitor(PWINDOW->monitorID()); } PWINDOW->m_bFirstMap = false; @@ -635,7 +635,7 @@ void Events::listener_unmapWindow(void* owner, void* data) { return; } - const auto PMONITOR = g_pCompositor->getMonitorFromID(PWINDOW->m_iMonitorID); + const auto PMONITOR = PWINDOW->m_pMonitor.lock(); if (PMONITOR) { PWINDOW->m_vOriginalClosedPos = PWINDOW->m_vRealPosition.value() - PMONITOR->vecPosition; PWINDOW->m_vOriginalClosedSize = PWINDOW->m_vRealSize.value(); @@ -773,7 +773,7 @@ void Events::listener_commitWindow(void* owner, void* data) { if (!PWINDOW->m_pWorkspace->m_bVisible) return; - const auto PMONITOR = g_pCompositor->getMonitorFromID(PWINDOW->m_iMonitorID); + const auto PMONITOR = PWINDOW->m_pMonitor.lock(); if (PMONITOR) PMONITOR->debugLastPresentation(g_pSeatManager->isPointerFrameCommit ? "listener_commitWindow skip" : "listener_commitWindow"); @@ -911,7 +911,7 @@ void Events::listener_unmanagedSetGeometry(void* owner, void* data) { PWINDOW->m_vRealSize.setValueAndWarp(PWINDOW->m_pXWaylandSurface->geometry.size()); if (*PXWLFORCESCALEZERO) { - if (const auto PMONITOR = g_pCompositor->getMonitorFromID(PWINDOW->m_iMonitorID); PMONITOR) { + if (const auto PMONITOR = PWINDOW->m_pMonitor.lock(); PMONITOR) { PWINDOW->m_vRealSize.setValueAndWarp(PWINDOW->m_vRealSize.goal() / PMONITOR->scale); } } diff --git a/src/helpers/MiscFunctions.cpp b/src/helpers/MiscFunctions.cpp index 20c79a2b..29861af7 100644 --- a/src/helpers/MiscFunctions.cpp +++ b/src/helpers/MiscFunctions.cpp @@ -302,7 +302,7 @@ SWorkspaceIDName getWorkspaceIDNameFromString(const std::string& in) { // Collect all the workspaces we can't jump to. for (auto const& ws : g_pCompositor->m_vWorkspaces) { - if (ws->m_bIsSpecialWorkspace || (ws->m_iMonitorID != g_pCompositor->m_pLastMonitor->ID)) { + if (ws->m_bIsSpecialWorkspace || (ws->m_pMonitor != g_pCompositor->m_pLastMonitor)) { // Can't jump to this workspace invalidWSes.insert(ws->m_iID); } @@ -320,7 +320,7 @@ SWorkspaceIDName getWorkspaceIDNameFromString(const std::string& in) { // Prepare all named workspaces in case when we need them std::vector namedWSes; for (auto const& ws : g_pCompositor->m_vWorkspaces) { - if (ws->m_bIsSpecialWorkspace || (ws->m_iMonitorID != g_pCompositor->m_pLastMonitor->ID) || ws->m_iID >= 0) + if (ws->m_bIsSpecialWorkspace || (ws->m_pMonitor != g_pCompositor->m_pLastMonitor) || ws->m_iID >= 0) continue; namedWSes.push_back(ws->m_iID); @@ -464,7 +464,7 @@ SWorkspaceIDName getWorkspaceIDNameFromString(const std::string& in) { std::vector validWSes; for (auto const& ws : g_pCompositor->m_vWorkspaces) { - if (ws->m_bIsSpecialWorkspace || (ws->m_iMonitorID != g_pCompositor->m_pLastMonitor->ID && !onAllMonitors)) + if (ws->m_bIsSpecialWorkspace || (ws->m_pMonitor != g_pCompositor->m_pLastMonitor && !onAllMonitors)) continue; validWSes.push_back(ws->m_iID); diff --git a/src/helpers/Monitor.cpp b/src/helpers/Monitor.cpp index 41290b7d..9e71bf5f 100644 --- a/src/helpers/Monitor.cpp +++ b/src/helpers/Monitor.cpp @@ -314,9 +314,8 @@ void CMonitor::onDisconnect(bool destroy) { // move workspaces std::deque wspToMove; for (auto const& w : g_pCompositor->m_vWorkspaces) { - if (w->m_iMonitorID == ID || !g_pCompositor->getMonitorFromID(w->m_iMonitorID)) { + if (w->m_pMonitor == self || !w->m_pMonitor) wspToMove.push_back(w); - } } for (auto const& w : wspToMove) { @@ -464,7 +463,7 @@ void CMonitor::setupDefaultWS(const SMonitorRule& monitorRule) { if (newDefaultWorkspaceName == "") newDefaultWorkspaceName = std::to_string(wsID); - PNEWWORKSPACE = g_pCompositor->m_vWorkspaces.emplace_back(CWorkspace::create(wsID, ID, newDefaultWorkspaceName)); + PNEWWORKSPACE = g_pCompositor->m_vWorkspaces.emplace_back(CWorkspace::create(wsID, self.lock(), newDefaultWorkspaceName)); } activeWorkspace = PNEWWORKSPACE; @@ -541,9 +540,8 @@ void CMonitor::setMirror(const std::string& mirrorOf) { // move all the WS std::deque wspToMove; for (auto const& w : g_pCompositor->m_vWorkspaces) { - if (w->m_iMonitorID == ID) { + if (w->m_pMonitor == self || !w->m_pMonitor) wspToMove.push_back(w); - } } for (auto const& w : wspToMove) { @@ -626,7 +624,7 @@ void CMonitor::changeWorkspace(const PHLWORKSPACE& pWorkspace, bool internal, bo } if (!noFocus && !g_pCompositor->m_pLastMonitor->activeSpecialWorkspace && - !(g_pCompositor->m_pLastWindow.lock() && g_pCompositor->m_pLastWindow->m_bPinned && g_pCompositor->m_pLastWindow->m_iMonitorID == ID)) { + !(g_pCompositor->m_pLastWindow.lock() && g_pCompositor->m_pLastWindow->m_bPinned && g_pCompositor->m_pLastWindow->m_pMonitor == self)) { static auto PFOLLOWMOUSE = CConfigValue("input:follow_mouse"); auto pWindow = pWorkspace->getLastFocusedWindow(); @@ -687,7 +685,7 @@ void CMonitor::setSpecialWorkspace(const PHLWORKSPACE& pWorkspace) { g_pLayoutManager->getCurrentLayout()->recalculateMonitor(ID); - if (!(g_pCompositor->m_pLastWindow.lock() && g_pCompositor->m_pLastWindow->m_bPinned && g_pCompositor->m_pLastWindow->m_iMonitorID == ID)) { + if (!(g_pCompositor->m_pLastWindow.lock() && g_pCompositor->m_pLastWindow->m_bPinned && g_pCompositor->m_pLastWindow->m_pMonitor == self)) { if (const auto PLAST = activeWorkspace->getLastFocusedWindow(); PLAST) g_pCompositor->focusWindow(PLAST); else @@ -710,7 +708,7 @@ void CMonitor::setSpecialWorkspace(const PHLWORKSPACE& pWorkspace) { bool animate = true; //close if open elsewhere - const auto PMONITORWORKSPACEOWNER = g_pCompositor->getMonitorFromID(pWorkspace->m_iMonitorID); + const auto PMONITORWORKSPACEOWNER = pWorkspace->m_pMonitor.lock(); if (PMONITORWORKSPACEOWNER->activeSpecialWorkspace == pWorkspace) { PMONITORWORKSPACEOWNER->activeSpecialWorkspace.reset(); g_pLayoutManager->getCurrentLayout()->recalculateMonitor(PMONITORWORKSPACEOWNER->ID); @@ -723,7 +721,7 @@ void CMonitor::setSpecialWorkspace(const PHLWORKSPACE& pWorkspace) { } // open special - pWorkspace->m_iMonitorID = ID; + pWorkspace->m_pMonitor = self; activeSpecialWorkspace = pWorkspace; activeSpecialWorkspace->m_bVisible = true; if (animate) @@ -731,7 +729,7 @@ void CMonitor::setSpecialWorkspace(const PHLWORKSPACE& pWorkspace) { for (auto const& w : g_pCompositor->m_vWindows) { if (w->m_pWorkspace == pWorkspace) { - w->m_iMonitorID = ID; + w->m_pMonitor = self; w->updateSurfaceScaleTransformDetails(); w->setAnimationsToMove(); @@ -755,7 +753,7 @@ void CMonitor::setSpecialWorkspace(const PHLWORKSPACE& pWorkspace) { g_pLayoutManager->getCurrentLayout()->recalculateMonitor(ID); - if (!(g_pCompositor->m_pLastWindow.lock() && g_pCompositor->m_pLastWindow->m_bPinned && g_pCompositor->m_pLastWindow->m_iMonitorID == ID)) { + if (!(g_pCompositor->m_pLastWindow.lock() && g_pCompositor->m_pLastWindow->m_bPinned && g_pCompositor->m_pLastWindow->m_pMonitor == self)) { if (const auto PLAST = pWorkspace->getLastFocusedWindow(); PLAST) g_pCompositor->focusWindow(PLAST); else diff --git a/src/layout/DwindleLayout.cpp b/src/layout/DwindleLayout.cpp index 0fa57143..059dda99 100644 --- a/src/layout/DwindleLayout.cpp +++ b/src/layout/DwindleLayout.cpp @@ -111,7 +111,7 @@ void CHyprDwindleLayout::applyNodeDataToWindow(SDwindleNodeData* pNode, bool for } } } else - PMONITOR = g_pCompositor->getMonitorFromID(g_pCompositor->getWorkspaceByID(pNode->workspaceID)->m_iMonitorID); + PMONITOR = g_pCompositor->getWorkspaceByID(pNode->workspaceID)->m_pMonitor.lock(); if (!PMONITOR) { Debug::log(ERR, "Orphaned Node {}!!", pNode); @@ -234,7 +234,7 @@ void CHyprDwindleLayout::onWindowCreatedTiling(PHLWINDOW pWindow, eDirection dir m_lDwindleNodesData.push_back(SDwindleNodeData()); const auto PNODE = &m_lDwindleNodesData.back(); - const auto PMONITOR = g_pCompositor->getMonitorFromID(pWindow->m_iMonitorID); + const auto PMONITOR = pWindow->m_pMonitor.lock(); static auto PUSEACTIVE = CConfigValue("dwindle:use_active_for_splits"); static auto PDEFAULTSPLIT = CConfigValue("dwindle:default_split_ratio"); @@ -446,7 +446,7 @@ void CHyprDwindleLayout::onWindowCreatedTiling(PHLWINDOW pWindow, eDirection dir NEWPARENT->recalcSizePosRecursive(false, horizontalOverride, verticalOverride); - recalculateMonitor(pWindow->m_iMonitorID); + recalculateMonitor(pWindow->monitorID()); } void CHyprDwindleLayout::onWindowRemovedTiling(PHLWINDOW pWindow) { @@ -512,7 +512,7 @@ void CHyprDwindleLayout::recalculateMonitor(const MONITORID& monid) { } void CHyprDwindleLayout::calculateWorkspace(const PHLWORKSPACE& pWorkspace) { - const auto PMONITOR = g_pCompositor->getMonitorFromID(pWorkspace->m_iMonitorID); + const auto PMONITOR = pWorkspace->m_pMonitor.lock(); if (!PMONITOR) return; @@ -577,7 +577,7 @@ void CHyprDwindleLayout::resizeActiveWindow(const Vector2D& pixResize, eRectCorn static auto PSMARTRESIZING = CConfigValue("dwindle:smart_resizing"); // get some data about our window - const auto PMONITOR = g_pCompositor->getMonitorFromID(PWINDOW->m_iMonitorID); + const auto PMONITOR = PWINDOW->m_pMonitor.lock(); const bool DISPLAYLEFT = STICKS(PWINDOW->m_vPosition.x, PMONITOR->vecPosition.x + PMONITOR->vecReservedTopLeft.x); const bool DISPLAYRIGHT = STICKS(PWINDOW->m_vPosition.x + PWINDOW->m_vSize.x, PMONITOR->vecPosition.x + PMONITOR->vecSize.x - PMONITOR->vecReservedBottomRight.x); const bool DISPLAYTOP = STICKS(PWINDOW->m_vPosition.y, PMONITOR->vecPosition.y + PMONITOR->vecReservedTopLeft.y); @@ -750,7 +750,7 @@ void CHyprDwindleLayout::resizeActiveWindow(const Vector2D& pixResize, eRectCorn } void CHyprDwindleLayout::fullscreenRequestForWindow(PHLWINDOW pWindow, const eFullscreenMode CURRENT_EFFECTIVE_MODE, const eFullscreenMode EFFECTIVE_MODE) { - const auto PMONITOR = g_pCompositor->getMonitorFromID(pWindow->m_iMonitorID); + const auto PMONITOR = pWindow->m_pMonitor.lock(); const auto PWORKSPACE = pWindow->m_pWorkspace; // save position and size if floating @@ -860,9 +860,9 @@ void CHyprDwindleLayout::moveWindowTo(PHLWINDOW pWindow, const std::string& dir, const auto PMONITORFOCAL = g_pCompositor->getMonitorFromVector(focalPoint); - if (PMONITORFOCAL->ID != pWindow->m_iMonitorID) { + if (PMONITORFOCAL != pWindow->m_pMonitor) { pWindow->moveToWorkspace(PMONITORFOCAL->activeWorkspace); - pWindow->m_iMonitorID = PMONITORFOCAL->ID; + pWindow->m_pMonitor = PMONITORFOCAL; } onWindowCreatedTiling(pWindow); @@ -900,7 +900,7 @@ void CHyprDwindleLayout::switchWindows(PHLWINDOW pWindow, PHLWINDOW pWindow2) { PNODE->pWindow = pWindow2; if (PNODE->workspaceID != PNODE2->workspaceID) { - std::swap(pWindow2->m_iMonitorID, pWindow->m_iMonitorID); + std::swap(pWindow2->m_pMonitor, pWindow->m_pMonitor); std::swap(pWindow2->m_pWorkspace, pWindow->m_pWorkspace); } diff --git a/src/layout/IHyprLayout.cpp b/src/layout/IHyprLayout.cpp index 454a6132..a3c14e41 100644 --- a/src/layout/IHyprLayout.cpp +++ b/src/layout/IHyprLayout.cpp @@ -13,7 +13,7 @@ void IHyprLayout::onWindowCreated(PHLWINDOW pWindow, eDirection direction) { g_pXWaylandManager->getGeometryForWindow(pWindow, &desiredGeometry); if (desiredGeometry.width <= 5 || desiredGeometry.height <= 5) { - const auto PMONITOR = g_pCompositor->getMonitorFromID(pWindow->m_iMonitorID); + const auto PMONITOR = pWindow->m_pMonitor.lock(); pWindow->m_vLastFloatingSize = PMONITOR->vecSize / 2.f; } else pWindow->m_vLastFloatingSize = Vector2D(desiredGeometry.width, desiredGeometry.height); @@ -88,7 +88,7 @@ void IHyprLayout::onWindowCreatedFloating(PHLWINDOW pWindow) { CBox desiredGeometry = {0}; g_pXWaylandManager->getGeometryForWindow(pWindow, &desiredGeometry); - const auto PMONITOR = g_pCompositor->getMonitorFromID(pWindow->m_iMonitorID); + const auto PMONITOR = pWindow->m_pMonitor.lock(); if (pWindow->m_bIsX11) { Vector2D xy = {desiredGeometry.x, desiredGeometry.y}; @@ -485,7 +485,7 @@ static void performSnap(Vector2D& pos, Vector2D& size, PHLWINDOW DRAGGINGWINDOW, } if (*SNAPMONITORGAP) { - const auto MON = g_pCompositor->getMonitorFromID(DRAGGINGWINDOW->m_iMonitorID); + const auto MON = DRAGGINGWINDOW->m_pMonitor.lock(); const CBox mon = {MON->vecPosition.x, MON->vecPosition.y, MON->vecPosition.x + MON->vecSize.x, MON->vecPosition.y + MON->vecSize.y}; const double gap = *SNAPMONITORGAP; @@ -677,7 +677,7 @@ void IHyprLayout::onMouseMove(const Vector2D& mousePos) { const auto PMONITOR = g_pCompositor->getMonitorFromVector(middle); if (PMONITOR && !SPECIAL) { - DRAGGINGWINDOW->m_iMonitorID = PMONITOR->ID; + DRAGGINGWINDOW->m_pMonitor = PMONITOR; DRAGGINGWINDOW->moveToWorkspace(PMONITOR->activeWorkspace); DRAGGINGWINDOW->updateGroupOutputs(); @@ -705,8 +705,8 @@ void IHyprLayout::changeWindowFloatingMode(PHLWINDOW pWindow) { EMIT_HOOK_EVENT("changeFloatingMode", pWindow); if (!TILED) { - const auto PNEWMON = g_pCompositor->getMonitorFromVector(pWindow->m_vRealPosition.value() + pWindow->m_vRealSize.value() / 2.f); - pWindow->m_iMonitorID = PNEWMON->ID; + const auto PNEWMON = g_pCompositor->getMonitorFromVector(pWindow->m_vRealPosition.value() + pWindow->m_vRealSize.value() / 2.f); + pWindow->m_pMonitor = PNEWMON; pWindow->moveToWorkspace(PNEWMON->activeSpecialWorkspace ? PNEWMON->activeSpecialWorkspace : PNEWMON->activeWorkspace); pWindow->updateGroupOutputs(); @@ -734,7 +734,7 @@ void IHyprLayout::changeWindowFloatingMode(PHLWINDOW pWindow) { pWindow->m_vRealSize.setValue(PSAVEDSIZE); // fix pseudo leaving artifacts - g_pHyprRenderer->damageMonitor(g_pCompositor->getMonitorFromID(pWindow->m_iMonitorID)); + g_pHyprRenderer->damageMonitor(pWindow->m_pMonitor.lock()); if (pWindow == g_pCompositor->m_pLastWindow) m_pLastTiledWindow = pWindow; @@ -757,7 +757,7 @@ void IHyprLayout::changeWindowFloatingMode(PHLWINDOW pWindow) { pWindow->m_vSize = wb.pos(); pWindow->m_vPosition = wb.size(); - g_pHyprRenderer->damageMonitor(g_pCompositor->getMonitorFromID(pWindow->m_iMonitorID)); + g_pHyprRenderer->damageMonitor(pWindow->m_pMonitor.lock()); pWindow->unsetWindowData(PRIORITY_LAYOUT); pWindow->updateWindowData(); @@ -847,7 +847,7 @@ PHLWINDOW IHyprLayout::getNextWindowCandidate(PHLWINDOW pWindow) { pWindowCandidate = g_pCompositor->getFirstWindowOnWorkspace(pWindow->workspaceID()); if (!pWindowCandidate || pWindow == pWindowCandidate || !pWindowCandidate->m_bIsMapped || pWindowCandidate->isHidden() || pWindowCandidate->m_bX11ShouldntFocus || - pWindowCandidate->isX11OverrideRedirect() || pWindowCandidate->m_iMonitorID != g_pCompositor->m_pLastMonitor->ID) + pWindowCandidate->isX11OverrideRedirect() || pWindowCandidate->m_pMonitor != g_pCompositor->m_pLastMonitor) return nullptr; return pWindowCandidate; diff --git a/src/layout/MasterLayout.cpp b/src/layout/MasterLayout.cpp index 95b5afdf..a2321a41 100644 --- a/src/layout/MasterLayout.cpp +++ b/src/layout/MasterLayout.cpp @@ -80,7 +80,7 @@ void CHyprMasterLayout::onWindowCreatedTiling(PHLWINDOW pWindow, eDirection dire static auto PNEWONTOP = CConfigValue("master:new_on_top"); static auto PNEWSTATUS = CConfigValue("master:new_status"); - const auto PMONITOR = g_pCompositor->getMonitorFromID(pWindow->m_iMonitorID); + const auto PMONITOR = pWindow->m_pMonitor.lock(); const bool BNEWBEFOREACTIVE = *PNEWONACTIVE == "before"; const bool BNEWISMASTER = *PNEWSTATUS == "master"; @@ -229,7 +229,7 @@ void CHyprMasterLayout::onWindowCreatedTiling(PHLWINDOW pWindow, eDirection dire } // recalc - recalculateMonitor(pWindow->m_iMonitorID); + recalculateMonitor(pWindow->monitorID()); } void CHyprMasterLayout::onWindowRemovedTiling(PHLWINDOW pWindow) { @@ -279,7 +279,7 @@ void CHyprMasterLayout::onWindowRemovedTiling(PHLWINDOW pWindow) { } } } - recalculateMonitor(pWindow->m_iMonitorID); + recalculateMonitor(pWindow->monitorID()); } void CHyprMasterLayout::recalculateMonitor(const MONITORID& monid) { @@ -297,7 +297,7 @@ void CHyprMasterLayout::recalculateMonitor(const MONITORID& monid) { } void CHyprMasterLayout::calculateWorkspace(PHLWORKSPACE pWorkspace) { - const auto PMONITOR = g_pCompositor->getMonitorFromID(pWorkspace->m_iMonitorID); + const auto PMONITOR = pWorkspace->m_pMonitor.lock(); if (!PMONITOR) return; @@ -604,7 +604,7 @@ void CHyprMasterLayout::applyNodeDataToWindow(SMasterNodeData* pNode) { } } } else - PMONITOR = g_pCompositor->getMonitorFromID(g_pCompositor->getWorkspaceByID(pNode->workspaceID)->m_iMonitorID); + PMONITOR = g_pCompositor->getWorkspaceByID(pNode->workspaceID)->m_pMonitor.lock(); if (!PMONITOR) { Debug::log(ERR, "Orphaned Node {}!!", pNode); @@ -711,7 +711,7 @@ void CHyprMasterLayout::resizeActiveWindow(const Vector2D& pixResize, eRectCorne return; } - const auto PMONITOR = g_pCompositor->getMonitorFromID(PWINDOW->m_iMonitorID); + const auto PMONITOR = PWINDOW->m_pMonitor.lock(); static auto ALWAYSCENTER = CConfigValue("master:always_center_master"); static auto PSMARTRESIZING = CConfigValue("master:smart_resizing"); @@ -840,7 +840,7 @@ void CHyprMasterLayout::resizeActiveWindow(const Vector2D& pixResize, eRectCorne } void CHyprMasterLayout::fullscreenRequestForWindow(PHLWINDOW pWindow, const eFullscreenMode CURRENT_EFFECTIVE_MODE, const eFullscreenMode EFFECTIVE_MODE) { - const auto PMONITOR = g_pCompositor->getMonitorFromID(pWindow->m_iMonitorID); + const auto PMONITOR = pWindow->m_pMonitor.lock(); const auto PWORKSPACE = pWindow->m_pWorkspace; // save position and size if floating @@ -896,7 +896,7 @@ void CHyprMasterLayout::recalculateWindow(PHLWINDOW pWindow) { if (!PNODE) return; - recalculateMonitor(pWindow->m_iMonitorID); + recalculateMonitor(pWindow->monitorID()); } SWindowRenderLayoutHints CHyprMasterLayout::requestRenderHints(PHLWINDOW pWindow) { @@ -922,9 +922,9 @@ void CHyprMasterLayout::moveWindowTo(PHLWINDOW pWindow, const std::string& dir, // if different monitors, send to monitor onWindowRemovedTiling(pWindow); pWindow->moveToWorkspace(PWINDOW2->m_pWorkspace); - pWindow->m_iMonitorID = PWINDOW2->m_iMonitorID; + pWindow->m_pMonitor = PWINDOW2->m_pMonitor; if (!silent) { - const auto pMonitor = g_pCompositor->getMonitorFromID(pWindow->m_iMonitorID); + const auto pMonitor = pWindow->m_pMonitor.lock(); g_pCompositor->setActiveMonitor(pMonitor); } onWindowCreatedTiling(pWindow); @@ -946,7 +946,7 @@ void CHyprMasterLayout::switchWindows(PHLWINDOW pWindow, PHLWINDOW pWindow2) { return; if (PNODE->workspaceID != PNODE2->workspaceID) { - std::swap(pWindow2->m_iMonitorID, pWindow->m_iMonitorID); + std::swap(pWindow2->m_pMonitor, pWindow->m_pMonitor); std::swap(pWindow2->m_pWorkspace, pWindow->m_pWorkspace); } @@ -957,9 +957,9 @@ void CHyprMasterLayout::switchWindows(PHLWINDOW pWindow, PHLWINDOW pWindow2) { pWindow->setAnimationsToMove(); pWindow2->setAnimationsToMove(); - recalculateMonitor(pWindow->m_iMonitorID); + recalculateMonitor(pWindow->monitorID()); if (PNODE2->workspaceID != PNODE->workspaceID) - recalculateMonitor(pWindow2->m_iMonitorID); + recalculateMonitor(pWindow2->monitorID()); g_pHyprRenderer->damageWindow(pWindow); g_pHyprRenderer->damageWindow(pWindow2); @@ -978,7 +978,7 @@ void CHyprMasterLayout::alterSplitRatio(PHLWINDOW pWindow, float ratio, bool exa float newRatio = exact ? ratio : PMASTER->percMaster + ratio; PMASTER->percMaster = std::clamp(newRatio, 0.05f, 0.95f); - recalculateMonitor(pWindow->m_iMonitorID); + recalculateMonitor(pWindow->monitorID()); } PHLWINDOW CHyprMasterLayout::getNextWindow(PHLWINDOW pWindow, bool next) { @@ -1185,7 +1185,7 @@ std::any CHyprMasterLayout::layoutMessage(SLayoutMessageHeader header, std::stri PNODE->isMaster = true; } - recalculateMonitor(header.pWindow->m_iMonitorID); + recalculateMonitor(header.pWindow->monitorID()); } else if (command == "removemaster") { @@ -1217,7 +1217,7 @@ std::any CHyprMasterLayout::layoutMessage(SLayoutMessageHeader header, std::stri PNODE->isMaster = false; } - recalculateMonitor(header.pWindow->m_iMonitorID); + recalculateMonitor(header.pWindow->monitorID()); } else if (command == "orientationleft" || command == "orientationright" || command == "orientationtop" || command == "orientationbottom" || command == "orientationcenter") { const auto PWINDOW = header.pWindow; @@ -1239,7 +1239,7 @@ std::any CHyprMasterLayout::layoutMessage(SLayoutMessageHeader header, std::stri else if (command == "orientationcenter") PWORKSPACEDATA->orientation = ORIENTATION_CENTER; - recalculateMonitor(header.pWindow->m_iMonitorID); + recalculateMonitor(header.pWindow->monitorID()); } else if (command == "orientationnext") { runOrientationCycle(header, nullptr, 1); @@ -1274,7 +1274,7 @@ std::any CHyprMasterLayout::layoutMessage(SLayoutMessageHeader header, std::stri } } - recalculateMonitor(PWINDOW->m_iMonitorID); + recalculateMonitor(PWINDOW->monitorID()); } else if (command == "rollprev") { const auto PWINDOW = header.pWindow; const auto PNODE = getNodeFromWindow(PWINDOW); @@ -1300,7 +1300,7 @@ std::any CHyprMasterLayout::layoutMessage(SLayoutMessageHeader header, std::stri } } - recalculateMonitor(PWINDOW->m_iMonitorID); + recalculateMonitor(PWINDOW->monitorID()); } return 0; @@ -1338,7 +1338,7 @@ void CHyprMasterLayout::runOrientationCycle(SLayoutMessageHeader& header, CVarLi nextOrPrev = cycle.size() + (nextOrPrev % (int)cycle.size()); PWORKSPACEDATA->orientation = cycle.at(nextOrPrev); - recalculateMonitor(header.pWindow->m_iMonitorID); + recalculateMonitor(header.pWindow->monitorID()); } void CHyprMasterLayout::buildOrientationCycleVectorFromEOperation(std::vector& cycle) { diff --git a/src/managers/AnimationManager.cpp b/src/managers/AnimationManager.cpp index 9ff7497d..0bdf5a7a 100644 --- a/src/managers/AnimationManager.cpp +++ b/src/managers/AnimationManager.cpp @@ -99,12 +99,12 @@ void CAnimationManager::tick() { PDECO->damageEntire(); } - PMONITOR = g_pCompositor->getMonitorFromID(PWINDOW->m_iMonitorID); + PMONITOR = PWINDOW->m_pMonitor.lock(); if (!PMONITOR) continue; animationsDisabled = PWINDOW->m_sWindowData.noAnim.valueOr(animationsDisabled); } else if (PWORKSPACE) { - PMONITOR = g_pCompositor->getMonitorFromID(PWORKSPACE->m_iMonitorID); + PMONITOR = PWORKSPACE->m_pMonitor.lock(); if (!PMONITOR) continue; @@ -325,7 +325,7 @@ void CAnimationManager::animationSlide(PHLWINDOW pWindow, std::string force, boo const auto GOALPOS = pWindow->m_vRealPosition.goal(); const auto GOALSIZE = pWindow->m_vRealSize.goal(); - const auto PMONITOR = g_pCompositor->getMonitorFromID(pWindow->m_iMonitorID); + const auto PMONITOR = pWindow->m_pMonitor.lock(); if (!PMONITOR) return; // unsafe state most likely diff --git a/src/managers/KeybindManager.cpp b/src/managers/KeybindManager.cpp index 9c22fb93..b54b71ed 100644 --- a/src/managers/KeybindManager.cpp +++ b/src/managers/KeybindManager.cpp @@ -349,9 +349,9 @@ void CKeybindManager::switchToWindow(PHLWINDOW PWINDOWTOCHANGETO) { g_pInputManager->m_pForcedFocus.reset(); } - if (PLASTWINDOW && PLASTWINDOW->m_iMonitorID != PWINDOWTOCHANGETO->m_iMonitorID) { + if (PLASTWINDOW && PLASTWINDOW->m_pMonitor != PWINDOWTOCHANGETO->m_pMonitor) { // event - const auto PNEWMON = g_pCompositor->getMonitorFromID(PWINDOWTOCHANGETO->m_iMonitorID); + const auto PNEWMON = PWINDOWTOCHANGETO->m_pMonitor.lock(); g_pCompositor->setActiveMonitor(PNEWMON); } @@ -1011,7 +1011,7 @@ static SDispatchResult toggleActiveFloatingCore(std::string args, std::optional< } g_pCompositor->updateWorkspaceWindows(PWINDOW->workspaceID()); g_pCompositor->updateWorkspaceWindowData(PWINDOW->workspaceID()); - g_pLayoutManager->getCurrentLayout()->recalculateMonitor(PWINDOW->m_iMonitorID); + g_pLayoutManager->getCurrentLayout()->recalculateMonitor(PWINDOW->monitorID()); g_pCompositor->updateAllWindowsAnimatedDecorationValues(); return {}; @@ -1035,7 +1035,7 @@ SDispatchResult CKeybindManager::centerWindow(std::string args) { if (!PWINDOW || !PWINDOW->m_bIsFloating || PWINDOW->isFullscreen()) return {.success = false, .error = "No floating window found"}; - const auto PMONITOR = g_pCompositor->getMonitorFromID(PWINDOW->m_iMonitorID); + const auto PMONITOR = PWINDOW->m_pMonitor.lock(); auto RESERVEDOFFSET = Vector2D(); if (args == "1") @@ -1081,7 +1081,7 @@ SWorkspaceIDName getWorkspaceToChangeFromArgs(std::string args, PHLWORKSPACE PCU const auto ID = PCURRENTWORKSPACE->m_iID; if (const auto PWORKSPACETOCHANGETO = g_pCompositor->getWorkspaceByID(PPREVWS.id); PWORKSPACETOCHANGETO) { - if (PER_MON && PCURRENTWORKSPACE->m_iMonitorID != PWORKSPACETOCHANGETO->m_iMonitorID) + if (PER_MON && PCURRENTWORKSPACE->m_pMonitor != PWORKSPACETOCHANGETO->m_pMonitor) return {WORKSPACE_NOT_CHANGED, ""}; return {ID, PWORKSPACETOCHANGETO->m_szName}; } @@ -1135,7 +1135,7 @@ SDispatchResult CKeybindManager::changeworkspace(std::string args) { g_pInputManager->releaseAllMouseButtons(); - const auto PMONITORWORKSPACEOWNER = PMONITOR->ID == pWorkspaceToChangeTo->m_iMonitorID ? PMONITOR : g_pCompositor->getMonitorFromID(pWorkspaceToChangeTo->m_iMonitorID); + const auto PMONITORWORKSPACEOWNER = PMONITOR == pWorkspaceToChangeTo->m_pMonitor ? PMONITOR : pWorkspaceToChangeTo->m_pMonitor.lock(); if (!PMONITORWORKSPACEOWNER) return {.success = false, .error = "Workspace to switch to has no monitor"}; @@ -1270,11 +1270,11 @@ SDispatchResult CKeybindManager::moveActiveToWorkspace(std::string args) { if (pWorkspace) { g_pCompositor->moveWindowToWorkspaceSafe(PWINDOW, pWorkspace); - pMonitor = g_pCompositor->getMonitorFromID(pWorkspace->m_iMonitorID); + pMonitor = pWorkspace->m_pMonitor.lock(); g_pCompositor->setActiveMonitor(pMonitor); } else { - pWorkspace = g_pCompositor->createNewWorkspace(WORKSPACEID, PWINDOW->m_iMonitorID, workspaceName, false); - pMonitor = g_pCompositor->getMonitorFromID(pWorkspace->m_iMonitorID); + pWorkspace = g_pCompositor->createNewWorkspace(WORKSPACEID, PWINDOW->monitorID(), workspaceName, false); + pMonitor = pWorkspace->m_pMonitor.lock(); g_pCompositor->moveWindowToWorkspaceSafe(PWINDOW, pWorkspace); } @@ -1283,7 +1283,7 @@ SDispatchResult CKeybindManager::moveActiveToWorkspace(std::string args) { if (pWorkspace->m_bIsSpecialWorkspace) pMonitor->setSpecialWorkspace(pWorkspace); else if (POLDWS->m_bIsSpecialWorkspace) - g_pCompositor->getMonitorFromID(POLDWS->m_iMonitorID)->setSpecialWorkspace(nullptr); + POLDWS->m_pMonitor.lock()->setSpecialWorkspace(nullptr); if (*PALLOWWORKSPACECYCLES) pWorkspace->rememberPrevWorkspace(POLDWS); @@ -1328,7 +1328,7 @@ SDispatchResult CKeybindManager::moveActiveToWorkspaceSilent(std::string args) { if (pWorkspace) { g_pCompositor->moveWindowToWorkspaceSafe(PWINDOW, pWorkspace); } else { - pWorkspace = g_pCompositor->createNewWorkspace(WORKSPACEID, PWINDOW->m_iMonitorID, workspaceName, false); + pWorkspace = g_pCompositor->createNewWorkspace(WORKSPACEID, PWINDOW->monitorID(), workspaceName, false); g_pCompositor->moveWindowToWorkspaceSafe(PWINDOW, pWorkspace); } @@ -1475,7 +1475,7 @@ SDispatchResult CKeybindManager::moveActiveTo(std::string args) { if (PLASTWINDOW->m_bIsFloating) { std::optional vPosx, vPosy; - const auto PMONITOR = g_pCompositor->getMonitorFromID(PLASTWINDOW->m_iMonitorID); + const auto PMONITOR = PLASTWINDOW->m_pMonitor.lock(); const auto BORDERSIZE = PLASTWINDOW->getRealBorderSize(); switch (arg) { @@ -1882,8 +1882,8 @@ SDispatchResult CKeybindManager::focusWorkspaceOnCurrentMonitor(std::string args workspaceID = pWorkspace->m_iID; } - if (pWorkspace->m_iMonitorID != PCURRMONITOR->ID) { - const auto POLDMONITOR = g_pCompositor->getMonitorFromID(pWorkspace->m_iMonitorID); + if (pWorkspace->m_pMonitor != PCURRMONITOR) { + const auto POLDMONITOR = pWorkspace->m_pMonitor.lock(); if (!POLDMONITOR) { // wat Debug::log(ERR, "focusWorkspaceOnCurrentMonitor old monitor doesn't exist!"); return {.success = false, .error = "focusWorkspaceOnCurrentMonitor old monitor doesn't exist!"}; @@ -2509,7 +2509,7 @@ SDispatchResult CKeybindManager::pinActive(std::string args) { PWINDOW->m_bPinned = !PWINDOW->m_bPinned; - const auto PMONITOR = g_pCompositor->getMonitorFromID(PWINDOW->m_iMonitorID); + const auto PMONITOR = PWINDOW->m_pMonitor.lock(); if (!PMONITOR) { Debug::log(ERR, "pin: monitor not found"); @@ -2658,9 +2658,9 @@ void CKeybindManager::moveWindowIntoGroup(PHLWINDOW pWindow, PHLWINDOW pWindowIn g_pLayoutManager->getCurrentLayout()->onWindowRemoved(pWindow); // This removes groupped property! - if (pWindow->m_iMonitorID != pWindowInDirection->m_iMonitorID) { + if (pWindow->m_pMonitor != pWindowInDirection->m_pMonitor) { pWindow->moveToWorkspace(pWindowInDirection->m_pWorkspace); - pWindow->m_iMonitorID = pWindowInDirection->m_iMonitorID; + pWindow->m_pMonitor = pWindowInDirection->m_pMonitor; } static auto USECURRPOS = CConfigValue("group:insert_after_current"); diff --git a/src/managers/XWaylandManager.cpp b/src/managers/XWaylandManager.cpp index 7b3081a2..d0dda8e6 100644 --- a/src/managers/XWaylandManager.cpp +++ b/src/managers/XWaylandManager.cpp @@ -117,7 +117,7 @@ void CHyprXWaylandManager::setWindowSize(PHLWINDOW pWindow, Vector2D size, bool static auto PXWLFORCESCALEZERO = CConfigValue("xwayland:force_zero_scaling"); - const auto PMONITOR = g_pCompositor->getMonitorFromID(pWindow->m_iMonitorID); + const auto PMONITOR = pWindow->m_pMonitor.lock(); size = size.clamp(Vector2D{0, 0}, Vector2D{std::numeric_limits::infinity(), std::numeric_limits::infinity()}); diff --git a/src/managers/input/Swipe.cpp b/src/managers/input/Swipe.cpp index 8f95c6c6..ba0783fa 100644 --- a/src/managers/input/Swipe.cpp +++ b/src/managers/input/Swipe.cpp @@ -15,9 +15,8 @@ void CInputManager::onSwipeBegin(IPointer::SSwipeBeginEvent e) { int onMonitor = 0; for (auto const& w : g_pCompositor->m_vWorkspaces) { - if (w->m_iMonitorID == g_pCompositor->m_pLastMonitor->ID && !g_pCompositor->isWorkspaceSpecial(w->m_iID)) { + if (w->m_pMonitor == g_pCompositor->m_pLastMonitor && !g_pCompositor->isWorkspaceSpecial(w->m_iID)) onMonitor++; - } } if (onMonitor < 2 && !*PSWIPENEW) diff --git a/src/managers/input/Touch.cpp b/src/managers/input/Touch.cpp index 454391af..4e3980aa 100644 --- a/src/managers/input/Touch.cpp +++ b/src/managers/input/Touch.cpp @@ -123,7 +123,7 @@ void CInputManager::onTouchMove(ITouch::SMotionEvent e) { return; } if (validMapped(m_sTouchData.touchFocusWindow)) { - const auto PMONITOR = g_pCompositor->getMonitorFromID(m_sTouchData.touchFocusWindow->m_iMonitorID); + const auto PMONITOR = m_sTouchData.touchFocusWindow->m_pMonitor.lock(); g_pCompositor->warpCursorTo({PMONITOR->vecPosition.x + e.pos.x * PMONITOR->vecSize.x, PMONITOR->vecPosition.y + e.pos.y * PMONITOR->vecSize.y}, true); @@ -133,7 +133,7 @@ void CInputManager::onTouchMove(ITouch::SMotionEvent e) { g_pSeatManager->sendTouchMotion(e.timeMs, e.touchID, local); } else if (!m_sTouchData.touchFocusLS.expired()) { - const auto PMONITOR = g_pCompositor->getMonitorFromID(m_sTouchData.touchFocusLS->monitorID); + const auto PMONITOR = m_sTouchData.touchFocusLS->monitor.lock(); g_pCompositor->warpCursorTo({PMONITOR->vecPosition.x + e.pos.x * PMONITOR->vecSize.x, PMONITOR->vecPosition.y + e.pos.y * PMONITOR->vecSize.y}, true); diff --git a/src/protocols/ForeignToplevelWlr.cpp b/src/protocols/ForeignToplevelWlr.cpp index ffc335c9..06814c88 100644 --- a/src/protocols/ForeignToplevelWlr.cpp +++ b/src/protocols/ForeignToplevelWlr.cpp @@ -207,7 +207,7 @@ void CForeignToplevelWlrManager::onMap(PHLWINDOW pWindow) { resource->sendToplevel(NEWHANDLE->resource.get()); NEWHANDLE->resource->sendAppId(pWindow->m_szClass.c_str()); NEWHANDLE->resource->sendTitle(pWindow->m_szTitle.c_str()); - if (const auto PMONITOR = g_pCompositor->getMonitorFromID(pWindow->m_iMonitorID); PMONITOR) + if (const auto PMONITOR = pWindow->m_pMonitor.lock(); PMONITOR) NEWHANDLE->sendMonitor(PMONITOR); NEWHANDLE->sendState(); NEWHANDLE->resource->sendDone(); @@ -266,7 +266,7 @@ void CForeignToplevelWlrManager::onMoveMonitor(PHLWINDOW pWindow) { if (!H || H->closed) return; - const auto PMONITOR = g_pCompositor->getMonitorFromID(pWindow->m_iMonitorID); + const auto PMONITOR = pWindow->m_pMonitor.lock(); if (!PMONITOR) return; diff --git a/src/protocols/LinuxDMABUF.cpp b/src/protocols/LinuxDMABUF.cpp index e81d7e01..7b2bcbf4 100644 --- a/src/protocols/LinuxDMABUF.cpp +++ b/src/protocols/LinuxDMABUF.cpp @@ -509,7 +509,7 @@ void CLinuxDMABufV1Protocol::resetFormatTable() { PHLMONITOR mon; auto HLSurface = CWLSurface::fromResource(feedback->surface); if (auto w = HLSurface->getWindow(); w) - if (auto m = g_pCompositor->getMonitorFromID(w->m_iMonitorID); m) + if (auto m = w->m_pMonitor.lock(); m) mon = m->self.lock(); if (!mon) { diff --git a/src/protocols/ToplevelExport.cpp b/src/protocols/ToplevelExport.cpp index 8b6208be..f2af89db 100644 --- a/src/protocols/ToplevelExport.cpp +++ b/src/protocols/ToplevelExport.cpp @@ -97,7 +97,7 @@ CToplevelExportFrame::CToplevelExportFrame(SP re resource->setDestroy([this](CHyprlandToplevelExportFrameV1* pFrame) { PROTO::toplevelExport->destroyResource(this); }); resource->setCopy([this](CHyprlandToplevelExportFrameV1* pFrame, wl_resource* res, int32_t ignoreDamage) { this->copy(pFrame, res, ignoreDamage); }); - const auto PMONITOR = g_pCompositor->getMonitorFromID(pWindow->m_iMonitorID); + const auto PMONITOR = pWindow->m_pMonitor.lock(); g_pHyprRenderer->makeEGLCurrent(); @@ -239,7 +239,7 @@ bool CToplevelExportFrame::copyShm(timespec* now) { auto [pixelData, fmt, bufLen] = buffer->beginDataPtr(0); // no need for end, cuz it's shm // render the client - const auto PMONITOR = g_pCompositor->getMonitorFromID(pWindow->m_iMonitorID); + const auto PMONITOR = pWindow->m_pMonitor.lock(); CRegion fakeDamage{0, 0, PMONITOR->vecPixelSize.x * 10, PMONITOR->vecPixelSize.y * 10}; g_pHyprRenderer->makeEGLCurrent(); @@ -296,7 +296,7 @@ bool CToplevelExportFrame::copyShm(timespec* now) { } bool CToplevelExportFrame::copyDmabuf(timespec* now) { - const auto PMONITOR = g_pCompositor->getMonitorFromID(pWindow->m_iMonitorID); + const auto PMONITOR = pWindow->m_pMonitor.lock(); CRegion fakeDamage{0, 0, INT16_MAX, INT16_MAX}; @@ -383,7 +383,7 @@ void CToplevelExportProtocol::onOutputCommit(PHLMONITOR pMonitor) { const auto PWINDOW = f->pWindow; - if (pMonitor != g_pCompositor->getMonitorFromID(PWINDOW->m_iMonitorID)) + if (pMonitor != PWINDOW->m_pMonitor.lock()) continue; CBox geometry = {PWINDOW->m_vRealPosition.value().x, PWINDOW->m_vRealPosition.value().y, PWINDOW->m_vRealSize.value().x, PWINDOW->m_vRealSize.value().y}; diff --git a/src/render/OpenGL.cpp b/src/render/OpenGL.cpp index fc2d1012..9e524fa4 100644 --- a/src/render/OpenGL.cpp +++ b/src/render/OpenGL.cpp @@ -693,7 +693,7 @@ bool CHyprOpenGLImpl::passRequiresIntrospection(PHLMONITOR pMonitor) { if (*PBLURSPECIAL) { for (auto const& ws : g_pCompositor->m_vWorkspaces) { - if (!ws->m_bIsSpecialWorkspace || ws->m_iMonitorID != pMonitor->ID) + if (!ws->m_bIsSpecialWorkspace || ws->m_pMonitor != pMonitor) continue; if (ws->m_fAlpha.value() == 0) @@ -2219,7 +2219,7 @@ void CHyprOpenGLImpl::renderBorder(CBox* box, const CGradientValueData& grad, in void CHyprOpenGLImpl::makeRawWindowSnapshot(PHLWINDOW pWindow, CFramebuffer* pFramebuffer) { // we trust the window is valid. - const auto PMONITOR = g_pCompositor->getMonitorFromID(pWindow->m_iMonitorID); + const auto PMONITOR = pWindow->m_pMonitor.lock(); if (!PMONITOR || !PMONITOR->output || PMONITOR->vecPixelSize.x <= 0 || PMONITOR->vecPixelSize.y <= 0) return; @@ -2267,7 +2267,7 @@ void CHyprOpenGLImpl::makeRawWindowSnapshot(PHLWINDOW pWindow, CFramebuffer* pFr void CHyprOpenGLImpl::makeWindowSnapshot(PHLWINDOW pWindow) { // we trust the window is valid. - const auto PMONITOR = g_pCompositor->getMonitorFromID(pWindow->m_iMonitorID); + const auto PMONITOR = pWindow->m_pMonitor.lock(); if (!PMONITOR || !PMONITOR->output || PMONITOR->vecPixelSize.x <= 0 || PMONITOR->vecPixelSize.y <= 0) return; @@ -2319,7 +2319,7 @@ void CHyprOpenGLImpl::makeWindowSnapshot(PHLWINDOW pWindow) { void CHyprOpenGLImpl::makeLayerSnapshot(PHLLS pLayer) { // we trust the window is valid. - const auto PMONITOR = g_pCompositor->getMonitorFromID(pLayer->monitorID); + const auto PMONITOR = pLayer->monitor.lock(); if (!PMONITOR || !PMONITOR->output || PMONITOR->vecPixelSize.x <= 0 || PMONITOR->vecPixelSize.y <= 0) return; @@ -2372,7 +2372,7 @@ void CHyprOpenGLImpl::renderSnapshot(PHLWINDOW pWindow) { if (!FBDATA->m_cTex->m_iTexID) return; - const auto PMONITOR = g_pCompositor->getMonitorFromID(pWindow->m_iMonitorID); + const auto PMONITOR = pWindow->m_pMonitor.lock(); CBox windowBox; // some mafs to figure out the correct box @@ -2411,7 +2411,7 @@ void CHyprOpenGLImpl::renderSnapshot(PHLLS pLayer) { if (!FBDATA->m_cTex->m_iTexID) return; - const auto PMONITOR = g_pCompositor->getMonitorFromID(pLayer->monitorID); + const auto PMONITOR = pLayer->monitor.lock(); CBox layerBox; // some mafs to figure out the correct box diff --git a/src/render/Renderer.cpp b/src/render/Renderer.cpp index c69167c8..1c38eb4e 100644 --- a/src/render/Renderer.cpp +++ b/src/render/Renderer.cpp @@ -314,7 +314,7 @@ bool CHyprRenderer::shouldRenderWindow(PHLWINDOW pWindow, PHLMONITOR pMonitor) { return true; const auto PWINDOWWORKSPACE = pWindow->m_pWorkspace; - if (PWINDOWWORKSPACE && PWINDOWWORKSPACE->m_iMonitorID == pMonitor->ID) { + if (PWINDOWWORKSPACE && PWINDOWWORKSPACE->m_pMonitor == pMonitor) { if (PWINDOWWORKSPACE->m_vRenderOffset.isBeingAnimated() || PWINDOWWORKSPACE->m_fAlpha.isBeingAnimated() || PWINDOWWORKSPACE->m_bForceRendering) return true; @@ -327,10 +327,10 @@ bool CHyprRenderer::shouldRenderWindow(PHLWINDOW pWindow, PHLMONITOR pMonitor) { return false; } - if (pWindow->m_iMonitorID == pMonitor->ID) + if (pWindow->m_pMonitor == pMonitor) return true; - if (!g_pCompositor->isWorkspaceVisible(pWindow->m_pWorkspace) && pWindow->m_iMonitorID != pMonitor->ID) + if (!g_pCompositor->isWorkspaceVisible(pWindow->m_pWorkspace) && pWindow->m_pMonitor != pMonitor) return false; // if not, check if it maybe is active on a different monitor. @@ -341,7 +341,7 @@ bool CHyprRenderer::shouldRenderWindow(PHLWINDOW pWindow, PHLMONITOR pMonitor) { return true; // if window is tiled and it's flying in, don't render on other mons (for slide) - if (!pWindow->m_bIsFloating && pWindow->m_vRealPosition.isBeingAnimated() && pWindow->m_bAnimatingIn && pWindow->m_iMonitorID != pMonitor->ID) + if (!pWindow->m_bIsFloating && pWindow->m_vRealPosition.isBeingAnimated() && pWindow->m_bAnimatingIn && pWindow->m_pMonitor != pMonitor) return false; if (pWindow->m_vRealPosition.isBeingAnimated()) { @@ -379,7 +379,7 @@ bool CHyprRenderer::shouldRenderWindow(PHLWINDOW pWindow) { return true; for (auto const& m : g_pCompositor->m_vMonitors) { - if (PWORKSPACE && PWORKSPACE->m_iMonitorID == m->ID && (PWORKSPACE->m_vRenderOffset.isBeingAnimated() || PWORKSPACE->m_fAlpha.isBeingAnimated())) + if (PWORKSPACE && PWORKSPACE->m_pMonitor == m && (PWORKSPACE->m_vRenderOffset.isBeingAnimated() || PWORKSPACE->m_fAlpha.isBeingAnimated())) return true; if (m->activeSpecialWorkspace && pWindow->onSpecialWorkspace()) @@ -422,10 +422,10 @@ void CHyprRenderer::renderWorkspaceWindowsFullscreen(PHLMONITOR pMonitor, PHLWOR if (w->isFullscreen() || !w->m_bIsFloating) continue; - if (w->m_iMonitorID == pWorkspace->m_iMonitorID && pWorkspace->m_bIsSpecialWorkspace != w->onSpecialWorkspace()) + if (w->m_pMonitor == pWorkspace->m_pMonitor && pWorkspace->m_bIsSpecialWorkspace != w->onSpecialWorkspace()) continue; - if (pWorkspace->m_bIsSpecialWorkspace && w->m_iMonitorID != pWorkspace->m_iMonitorID) + if (pWorkspace->m_bIsSpecialWorkspace && w->m_pMonitor != pWorkspace->m_pMonitor) continue; // special on another are rendered as a part of the base pass renderWindow(w, pMonitor, time, true, RENDER_PASS_ALL); @@ -439,14 +439,14 @@ void CHyprRenderer::renderWorkspaceWindowsFullscreen(PHLMONITOR pMonitor, PHLWOR if (!(PWORKSPACE && (PWORKSPACE->m_vRenderOffset.isBeingAnimated() || PWORKSPACE->m_fAlpha.isBeingAnimated() || PWORKSPACE->m_bForceRendering))) continue; - if (w->m_iMonitorID != pMonitor->ID) + if (w->m_pMonitor != pMonitor) continue; } if (!w->isFullscreen()) continue; - if (w->m_iMonitorID == pWorkspace->m_iMonitorID && pWorkspace->m_bIsSpecialWorkspace != w->onSpecialWorkspace()) + if (w->m_pMonitor == pWorkspace->m_pMonitor && pWorkspace->m_bIsSpecialWorkspace != w->onSpecialWorkspace()) continue; if (shouldRenderWindow(w, pMonitor)) @@ -469,10 +469,10 @@ void CHyprRenderer::renderWorkspaceWindowsFullscreen(PHLMONITOR pMonitor, PHLWOR if (w->m_pWorkspace != pWorkspaceWindow->m_pWorkspace || (!w->m_bCreatedOverFullscreen && !w->m_bPinned) || (!w->m_bIsMapped && !w->m_bFadingOut) || w->isFullscreen()) continue; - if (w->m_iMonitorID == pWorkspace->m_iMonitorID && pWorkspace->m_bIsSpecialWorkspace != w->onSpecialWorkspace()) + if (w->m_pMonitor == pWorkspace->m_pMonitor && pWorkspace->m_bIsSpecialWorkspace != w->onSpecialWorkspace()) continue; - if (pWorkspace->m_bIsSpecialWorkspace && w->m_iMonitorID != pWorkspace->m_iMonitorID) + if (pWorkspace->m_bIsSpecialWorkspace && w->m_pMonitor != pWorkspace->m_pMonitor) continue; // special on another are rendered as a part of the base pass renderWindow(w, pMonitor, time, true, RENDER_PASS_ALL); @@ -543,7 +543,7 @@ void CHyprRenderer::renderWorkspaceWindows(PHLMONITOR pMonitor, PHLWORKSPACE pWo if (pWorkspace->m_bIsSpecialWorkspace != w->onSpecialWorkspace()) continue; - if (pWorkspace->m_bIsSpecialWorkspace && w->m_iMonitorID != pWorkspace->m_iMonitorID) + if (pWorkspace->m_bIsSpecialWorkspace && w->m_pMonitor != pWorkspace->m_pMonitor) continue; // special on another are rendered as a part of the base pass // render the bad boy @@ -556,7 +556,7 @@ void CHyprRenderer::renderWindow(PHLWINDOW pWindow, PHLMONITOR pMonitor, timespe return; if (pWindow->m_bFadingOut) { - if (pMonitor->ID == pWindow->m_iMonitorID) // TODO: fix this + if (pMonitor == pWindow->m_pMonitor) // TODO: fix this g_pHyprOpenGL->renderSnapshot(pWindow); return; } @@ -965,7 +965,7 @@ void CHyprRenderer::renderAllClientsForWorkspace(PHLMONITOR pMonitor, PHLWORKSPA // and then special for (auto const& ws : g_pCompositor->m_vWorkspaces) { - if (ws->m_iMonitorID == pMonitor->ID && ws->m_fAlpha.value() > 0.f && ws->m_bIsSpecialWorkspace) { + if (ws->m_pMonitor == pMonitor && ws->m_fAlpha.value() > 0.f && ws->m_bIsSpecialWorkspace) { const auto SPECIALANIMPROGRS = ws->m_vRenderOffset.isBeingAnimated() ? ws->m_vRenderOffset.getCurveValue() : ws->m_fAlpha.getCurveValue(); const bool ANIMOUT = !pMonitor->activeSpecialWorkspace; @@ -2533,7 +2533,7 @@ void CHyprRenderer::initiateManualCrash() { void CHyprRenderer::setOccludedForMainWorkspace(CRegion& region, PHLWORKSPACE pWorkspace) { CRegion rg; - const auto PMONITOR = g_pCompositor->getMonitorFromID(pWorkspace->m_iMonitorID); + const auto PMONITOR = pWorkspace->m_pMonitor.lock(); if (!PMONITOR->activeSpecialWorkspace) return; @@ -2562,7 +2562,7 @@ void CHyprRenderer::setOccludedForMainWorkspace(CRegion& region, PHLWORKSPACE pW void CHyprRenderer::setOccludedForBackLayers(CRegion& region, PHLWORKSPACE pWorkspace) { CRegion rg; - const auto PMONITOR = g_pCompositor->getMonitorFromID(pWorkspace->m_iMonitorID); + const auto PMONITOR = pWorkspace->m_pMonitor.lock(); static auto PBLUR = CConfigValue("decoration:blur:enabled"); static auto PBLURSIZE = CConfigValue("decoration:blur:size"); From b1120ec4334abdb57677354dfcdcf48b6c34f397 Mon Sep 17 00:00:00 2001 From: Vaxry Date: Sun, 27 Oct 2024 23:39:52 +0000 Subject: [PATCH 0566/2181] layout: window snapping cleanup + fixes way better now heh fixes #8259 fixes #8267 --- src/layout/IHyprLayout.cpp | 94 ++++++++++++++++++++------------------ 1 file changed, 50 insertions(+), 44 deletions(-) diff --git a/src/layout/IHyprLayout.cpp b/src/layout/IHyprLayout.cpp index a3c14e41..30b5632c 100644 --- a/src/layout/IHyprLayout.cpp +++ b/src/layout/IHyprLayout.cpp @@ -415,7 +415,7 @@ static void snapResizeRight(double& pos, double& len, const double p) { typedef std::function SnapFn; -static void performSnap(Vector2D& pos, Vector2D& size, PHLWINDOW DRAGGINGWINDOW, const eMouseBindMode mode, const int corner, const Vector2D& beginSize) { +static void performSnap(Vector2D& sourcePos, Vector2D& sourceSize, PHLWINDOW DRAGGINGWINDOW, const eMouseBindMode mode, const int corner, const Vector2D& beginSize) { static auto SNAPWINDOWGAP = CConfigValue("general:snap:window_gap"); static auto SNAPMONITORGAP = CConfigValue("general:snap:monitor_gap"); @@ -425,59 +425,59 @@ static void performSnap(Vector2D& pos, Vector2D& size, PHLWINDOW DRAGGINGWINDOW, const SnapFn snapUp = snapLeft; int snaps = 0; + const int DRAGGINGBORDERSIZE = DRAGGINGWINDOW->getRealBorderSize(); + CBox sourceBox = CBox{sourcePos, sourceSize}.expand(DRAGGINGBORDERSIZE); + if (*SNAPWINDOWGAP) { const auto PID = DRAGGINGWINDOW->getPID(); const auto WSID = DRAGGINGWINDOW->workspaceID(); - const int BORD = DRAGGINGWINDOW->getRealBorderSize(); for (auto& other : g_pCompositor->m_vWindows) { if (other->workspaceID() != WSID || other->getPID() == PID || !other->m_bIsMapped || other->m_bFadingOut || other->isX11OverrideRedirect()) continue; - const int bord = std::max(BORD, other->getRealBorderSize()); - const double gap = *SNAPWINDOWGAP + bord; + const int BORDERSIZE = other->getRealBorderSize(); + const double GAPSIZE = *SNAPWINDOWGAP + BORDERSIZE; - const CBox box = other->getWindowMainSurfaceBox(); - const CBox ob = {box.x, box.y, box.x + box.w, box.y + box.h}; - const CBox bb = {ob.x - bord, ob.y - bord, ob.w + bord, ob.h + bord}; - const Vector2D end = {pos.x + size.x, pos.y + size.y}; + const CBox SURFBB = other->getWindowMainSurfaceBox().expand(BORDERSIZE); + const Vector2D end = sourceBox.pos() + sourceBox.size(); // only snap windows if their ranges intersect in the opposite axis - if (pos.y <= bb.h && bb.y <= end.y) { - if (corner & (CORNER_TOPLEFT | CORNER_BOTTOMLEFT) && canSnap(pos.x, bb.w, gap)) { - snapLeft(pos.x, size.x, bb.w); + if (sourceBox.y <= SURFBB.y + SURFBB.h && SURFBB.y <= end.y) { + if (corner & (CORNER_TOPLEFT | CORNER_BOTTOMLEFT) && canSnap(sourceBox.x, SURFBB.x + SURFBB.w, GAPSIZE)) { + snapLeft(sourceBox.x, sourceBox.w, SURFBB.x + SURFBB.w); snaps |= SNAP_LEFT; - } else if (corner & (CORNER_TOPRIGHT | CORNER_BOTTOMRIGHT) && canSnap(end.x, bb.x, gap)) { - snapRight(pos.x, size.x, bb.x); + } else if (corner & (CORNER_TOPRIGHT | CORNER_BOTTOMRIGHT) && canSnap(end.x, SURFBB.x, GAPSIZE)) { + snapRight(sourceBox.x, sourceBox.w, SURFBB.x); snaps |= SNAP_RIGHT; } } - if (pos.x <= bb.w && bb.x <= end.x) { - if (corner & (CORNER_TOPLEFT | CORNER_TOPRIGHT) && canSnap(pos.y, bb.h, gap)) { - snapUp(pos.y, size.y, bb.h); + if (sourceBox.x <= SURFBB.x + SURFBB.w && SURFBB.x <= end.x) { + if (corner & (CORNER_TOPLEFT | CORNER_TOPRIGHT) && canSnap(sourceBox.y, SURFBB.y + SURFBB.h, GAPSIZE)) { + snapUp(sourceBox.y, sourceBox.h, SURFBB.y + SURFBB.h); snaps |= SNAP_UP; - } else if (corner & (CORNER_BOTTOMLEFT | CORNER_BOTTOMRIGHT) && canSnap(end.y, bb.y, gap)) { - snapDown(pos.y, size.y, bb.y); + } else if (corner & (CORNER_BOTTOMLEFT | CORNER_BOTTOMRIGHT) && canSnap(end.y, SURFBB.y, GAPSIZE)) { + snapDown(sourceBox.y, sourceBox.h, SURFBB.y); snaps |= SNAP_DOWN; } } // corner snapping - if (pos.x == bb.w || bb.x == pos.x + size.x) { - if (corner & (CORNER_TOPLEFT | CORNER_TOPRIGHT) && canSnap(pos.y, ob.y, gap)) { - snapUp(pos.y, size.y, ob.y); + if (sourceBox.x == SURFBB.x + SURFBB.w || SURFBB.x == sourceBox.x + sourceBox.w) { + if (corner & (CORNER_TOPLEFT | CORNER_TOPRIGHT) && canSnap(sourceBox.y, SURFBB.y, GAPSIZE)) { + snapUp(sourceBox.y, sourceBox.w, SURFBB.y); snaps |= SNAP_UP; - } else if (corner & (CORNER_BOTTOMLEFT | CORNER_BOTTOMRIGHT) && canSnap(end.y, ob.h, gap)) { - snapDown(pos.y, size.y, ob.h); + } else if (corner & (CORNER_BOTTOMLEFT | CORNER_BOTTOMRIGHT) && canSnap(end.y, SURFBB.y + SURFBB.h, GAPSIZE)) { + snapDown(sourceBox.y, sourceBox.h, SURFBB.y + SURFBB.h); snaps |= SNAP_DOWN; } } - if (pos.y == bb.h || bb.y == pos.y + size.y) { - if (corner & (CORNER_TOPLEFT | CORNER_BOTTOMLEFT) && canSnap(pos.x, ob.x, gap)) { - snapLeft(pos.x, size.x, ob.x); + if (sourceBox.y == SURFBB.y + SURFBB.h || SURFBB.y == sourceBox.y + sourceBox.w) { + if (corner & (CORNER_TOPLEFT | CORNER_BOTTOMLEFT) && canSnap(sourceBox.x, SURFBB.x, GAPSIZE)) { + snapLeft(sourceBox.x, sourceBox.w, SURFBB.x); snaps |= SNAP_LEFT; - } else if (corner & (CORNER_TOPRIGHT | CORNER_BOTTOMRIGHT) && canSnap(end.x, ob.w, gap)) { - snapRight(pos.x, size.x, ob.w); + } else if (corner & (CORNER_TOPRIGHT | CORNER_BOTTOMRIGHT) && canSnap(end.x, SURFBB.x + SURFBB.w, GAPSIZE)) { + snapRight(sourceBox.x, sourceBox.w, SURFBB.x + SURFBB.w); snaps |= SNAP_RIGHT; } } @@ -485,24 +485,26 @@ static void performSnap(Vector2D& pos, Vector2D& size, PHLWINDOW DRAGGINGWINDOW, } if (*SNAPMONITORGAP) { - const auto MON = DRAGGINGWINDOW->m_pMonitor.lock(); - const CBox mon = {MON->vecPosition.x, MON->vecPosition.y, MON->vecPosition.x + MON->vecSize.x, MON->vecPosition.y + MON->vecSize.y}; + const auto MON = DRAGGINGWINDOW->m_pMonitor.lock(); + const CBox mon = + CBox{MON->vecPosition.x + MON->vecReservedTopLeft.x, MON->vecPosition.y + MON->vecReservedTopLeft.y, + MON->vecSize.x - MON->vecReservedTopLeft.x - MON->vecReservedBottomRight.x, MON->vecSize.y - MON->vecReservedBottomRight.y - MON->vecReservedTopLeft.y}; const double gap = *SNAPMONITORGAP; - if (canSnap(pos.x, mon.x, gap)) { - snapLeft(pos.x, size.x, mon.x); + if (canSnap(sourceBox.x, mon.x, gap)) { + snapLeft(sourceBox.x, sourceBox.w, mon.x); snaps |= SNAP_LEFT; } - if (canSnap(pos.x + size.x, mon.w, gap)) { - snapRight(pos.x, size.x, mon.w); + if (canSnap(sourceBox.x + sourceBox.w, mon.x + mon.w, gap)) { + snapRight(sourceBox.x, sourceBox.w, mon.w + mon.x); snaps |= SNAP_RIGHT; } - if (canSnap(pos.y, mon.y, gap)) { - snapUp(pos.y, size.y, mon.y); + if (canSnap(sourceBox.y, mon.y, gap)) { + snapUp(sourceBox.y, sourceBox.h, mon.y); snaps |= SNAP_UP; } - if (canSnap(pos.y + size.y, mon.h, gap)) { - snapDown(pos.y, size.y, mon.h); + if (canSnap(sourceBox.y + sourceBox.h, mon.y + mon.h, gap)) { + snapDown(sourceBox.y, sourceBox.h, mon.h + mon.y); snaps |= SNAP_DOWN; } } @@ -511,17 +513,21 @@ static void performSnap(Vector2D& pos, Vector2D& size, PHLWINDOW DRAGGINGWINDOW, const double RATIO = beginSize.y / beginSize.x; if ((corner & (CORNER_TOPLEFT | CORNER_BOTTOMLEFT) && snaps & SNAP_LEFT) || (corner & (CORNER_TOPRIGHT | CORNER_BOTTOMRIGHT) && snaps & SNAP_RIGHT)) { - const double sizeY = size.x * RATIO; + const double sizeY = sourceBox.h * RATIO; if (corner & (CORNER_TOPLEFT | CORNER_TOPRIGHT)) - pos.y += size.y - sizeY; - size.y = sizeY; + sourceBox.y += sourceBox.h - sizeY; + sourceBox.h = sizeY; } else if ((corner & (CORNER_TOPLEFT | CORNER_TOPRIGHT) && snaps & SNAP_UP) || (corner & (CORNER_BOTTOMLEFT | CORNER_BOTTOMRIGHT) && snaps & SNAP_DOWN)) { - const double sizeX = size.y / RATIO; + const double sizeX = sourceBox.h / RATIO; if (corner & (CORNER_TOPLEFT | CORNER_BOTTOMLEFT)) - pos.x += size.x - sizeX; - size.x = sizeX; + sourceBox.x += sourceBox.w - sizeX; + sourceBox.w = sizeX; } } + + sourceBox.expand(-DRAGGINGBORDERSIZE).round(); + sourcePos = sourceBox.pos(); + sourceSize = sourceBox.size(); } void IHyprLayout::onMouseMove(const Vector2D& mousePos) { From 6cf193e1662f6f750e964a3e174ae017246b4d48 Mon Sep 17 00:00:00 2001 From: Vaxry Date: Sun, 27 Oct 2024 23:41:22 +0000 Subject: [PATCH 0567/2181] layout: don't snap to self and allow same-pid snaps fixes #8255 --- src/layout/IHyprLayout.cpp | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/layout/IHyprLayout.cpp b/src/layout/IHyprLayout.cpp index 30b5632c..bd81500d 100644 --- a/src/layout/IHyprLayout.cpp +++ b/src/layout/IHyprLayout.cpp @@ -429,11 +429,10 @@ static void performSnap(Vector2D& sourcePos, Vector2D& sourceSize, PHLWINDOW DRA CBox sourceBox = CBox{sourcePos, sourceSize}.expand(DRAGGINGBORDERSIZE); if (*SNAPWINDOWGAP) { - const auto PID = DRAGGINGWINDOW->getPID(); const auto WSID = DRAGGINGWINDOW->workspaceID(); for (auto& other : g_pCompositor->m_vWindows) { - if (other->workspaceID() != WSID || other->getPID() == PID || !other->m_bIsMapped || other->m_bFadingOut || other->isX11OverrideRedirect()) + if (other == DRAGGINGWINDOW || other->workspaceID() != WSID || !other->m_bIsMapped || other->m_bFadingOut || other->isX11OverrideRedirect()) continue; const int BORDERSIZE = other->getRealBorderSize(); From 2c481202effe707451608e272b5a801f8c970052 Mon Sep 17 00:00:00 2001 From: Mike Will Date: Mon, 28 Oct 2024 09:39:05 -0400 Subject: [PATCH 0568/2181] layout: slight adjustments to snapping logic (#8273) fixes some bugs with resizing and corner snapping --- src/layout/IHyprLayout.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/layout/IHyprLayout.cpp b/src/layout/IHyprLayout.cpp index bd81500d..e3606532 100644 --- a/src/layout/IHyprLayout.cpp +++ b/src/layout/IHyprLayout.cpp @@ -464,14 +464,14 @@ static void performSnap(Vector2D& sourcePos, Vector2D& sourceSize, PHLWINDOW DRA // corner snapping if (sourceBox.x == SURFBB.x + SURFBB.w || SURFBB.x == sourceBox.x + sourceBox.w) { if (corner & (CORNER_TOPLEFT | CORNER_TOPRIGHT) && canSnap(sourceBox.y, SURFBB.y, GAPSIZE)) { - snapUp(sourceBox.y, sourceBox.w, SURFBB.y); + snapUp(sourceBox.y, sourceBox.h, SURFBB.y); snaps |= SNAP_UP; } else if (corner & (CORNER_BOTTOMLEFT | CORNER_BOTTOMRIGHT) && canSnap(end.y, SURFBB.y + SURFBB.h, GAPSIZE)) { snapDown(sourceBox.y, sourceBox.h, SURFBB.y + SURFBB.h); snaps |= SNAP_DOWN; } } - if (sourceBox.y == SURFBB.y + SURFBB.h || SURFBB.y == sourceBox.y + sourceBox.w) { + if (sourceBox.y == SURFBB.y + SURFBB.h || SURFBB.y == sourceBox.y + sourceBox.h) { if (corner & (CORNER_TOPLEFT | CORNER_BOTTOMLEFT) && canSnap(sourceBox.x, SURFBB.x, GAPSIZE)) { snapLeft(sourceBox.x, sourceBox.w, SURFBB.x); snaps |= SNAP_LEFT; @@ -512,7 +512,7 @@ static void performSnap(Vector2D& sourcePos, Vector2D& sourceSize, PHLWINDOW DRA const double RATIO = beginSize.y / beginSize.x; if ((corner & (CORNER_TOPLEFT | CORNER_BOTTOMLEFT) && snaps & SNAP_LEFT) || (corner & (CORNER_TOPRIGHT | CORNER_BOTTOMRIGHT) && snaps & SNAP_RIGHT)) { - const double sizeY = sourceBox.h * RATIO; + const double sizeY = sourceBox.w * RATIO; if (corner & (CORNER_TOPLEFT | CORNER_TOPRIGHT)) sourceBox.y += sourceBox.h - sizeY; sourceBox.h = sizeY; From d49a1334a8af7c704626cdf1746cb72415ad6d0d Mon Sep 17 00:00:00 2001 From: Aqa-Ib Date: Mon, 28 Oct 2024 16:52:14 +0000 Subject: [PATCH 0569/2181] swallow: check if swallow_regex doesn't exist (#8265) Avoid to run CWindow::getSwallower() when `swallow_regex` doesn't exist in the user's config file. --- src/desktop/Window.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/desktop/Window.cpp b/src/desktop/Window.cpp index e4f987eb..60f3b79d 100644 --- a/src/desktop/Window.cpp +++ b/src/desktop/Window.cpp @@ -1535,7 +1535,7 @@ PHLWINDOW CWindow::getSwallower() { static auto PSWALLOWEXREGEX = CConfigValue("misc:swallow_exception_regex"); static auto PSWALLOW = CConfigValue("misc:enable_swallow"); - if (!*PSWALLOW || (*PSWALLOWREGEX).empty()) + if (!*PSWALLOW || std::string{*PSWALLOWREGEX} == STRVAL_EMPTY || (*PSWALLOWREGEX).empty()) return nullptr; // check parent From c7315617eb6186912d03232e1968f32b88f153f2 Mon Sep 17 00:00:00 2001 From: Tom Englund Date: Mon, 28 Oct 2024 19:02:52 +0100 Subject: [PATCH 0570/2181] internal: few more marginal optimisations from profiling (#8271) * deco: reduce local temporars and function calls profiling shows this is a high used function, reduce the amount of function calls and local temporar copies and also check if we even need to add extents at all in the loop. * popup: optimize bfhelper in popups pass nodes as const reference and reserve the size of the children node vector help reduce the reallocations. * procotol: make compositor bfhelper use const ref use const ref for nodes and reserve second nodes vector size to reduce amount of reallocation needed. --- src/desktop/Popup.cpp | 3 +- src/desktop/Popup.hpp | 2 +- src/protocols/core/Compositor.cpp | 3 +- src/protocols/core/Compositor.hpp | 2 +- .../decorations/DecorationPositioner.cpp | 39 +++++++++++-------- 5 files changed, 29 insertions(+), 20 deletions(-) diff --git a/src/desktop/Popup.cpp b/src/desktop/Popup.cpp index 9e254fa6..58995f00 100644 --- a/src/desktop/Popup.cpp +++ b/src/desktop/Popup.cpp @@ -288,12 +288,13 @@ bool CPopup::visible() { return false; } -void CPopup::bfHelper(std::vector nodes, std::function fn, void* data) { +void CPopup::bfHelper(std::vector const& nodes, std::function fn, void* data) { for (auto const& n : nodes) { fn(n, data); } std::vector nodes2; + nodes2.reserve(nodes.size() * 2); for (auto const& n : nodes) { for (auto const& c : n->m_vChildren) { diff --git a/src/desktop/Popup.hpp b/src/desktop/Popup.hpp index 04996612..f34b8a2c 100644 --- a/src/desktop/Popup.hpp +++ b/src/desktop/Popup.hpp @@ -81,5 +81,5 @@ class CPopup { Vector2D localToGlobal(const Vector2D& rel); Vector2D t1ParentCoords(); - static void bfHelper(std::vector nodes, std::function fn, void* data); + static void bfHelper(std::vector const& nodes, std::function fn, void* data); }; diff --git a/src/protocols/core/Compositor.cpp b/src/protocols/core/Compositor.cpp index 9a2e00a9..d78d3d8b 100644 --- a/src/protocols/core/Compositor.cpp +++ b/src/protocols/core/Compositor.cpp @@ -252,9 +252,10 @@ void CWLSurfaceResource::resetRole() { role = makeShared(); } -void CWLSurfaceResource::bfHelper(std::vector> nodes, std::function, const Vector2D&, void*)> fn, void* data) { +void CWLSurfaceResource::bfHelper(std::vector> const& nodes, std::function, const Vector2D&, void*)> fn, void* data) { std::vector> nodes2; + nodes2.reserve(nodes.size() * 2); // first, gather all nodes below for (auto const& n : nodes) { diff --git a/src/protocols/core/Compositor.hpp b/src/protocols/core/Compositor.hpp index fbffd966..e5bdf082 100644 --- a/src/protocols/core/Compositor.hpp +++ b/src/protocols/core/Compositor.hpp @@ -147,7 +147,7 @@ class CWLSurfaceResource { void dropPendingBuffer(); void dropCurrentBuffer(); void commitPendingState(); - void bfHelper(std::vector> nodes, std::function, const Vector2D&, void*)> fn, void* data); + void bfHelper(std::vector> const& nodes, std::function, const Vector2D&, void*)> fn, void* data); void updateCursorShm(); friend class CWLPointerResource; diff --git a/src/render/decorations/DecorationPositioner.cpp b/src/render/decorations/DecorationPositioner.cpp index 3eb45546..995283c6 100644 --- a/src/render/decorations/DecorationPositioner.cpp +++ b/src/render/decorations/DecorationPositioner.cpp @@ -294,13 +294,11 @@ SBoxExtents CDecorationPositioner::getWindowDecorationReserved(PHLWINDOW pWindow } SBoxExtents CDecorationPositioner::getWindowDecorationExtents(PHLWINDOW pWindow, bool inputOnly) { - CBox accum = pWindow->getWindowMainSurfaceBox(); + CBox const mainSurfaceBox = pWindow->getWindowMainSurfaceBox(); + CBox accum = mainSurfaceBox; for (auto const& data : m_vWindowPositioningDatas) { - if (!data->pDecoration) - continue; - - if (!(data->pDecoration->getDecorationFlags() & DECORATION_ALLOWS_MOUSE_INPUT) && inputOnly) + if (!data->pDecoration || (inputOnly && !(data->pDecoration->getDecorationFlags() & DECORATION_ALLOWS_MOUSE_INPUT))) continue; auto const window = data->pWindow.lock(); @@ -308,31 +306,40 @@ SBoxExtents CDecorationPositioner::getWindowDecorationExtents(PHLWINDOW pWindow, continue; CBox decoBox; - if (data->positioningInfo.policy == DECORATION_POSITION_ABSOLUTE) { - decoBox = data->pWindow->getWindowMainSurfaceBox(); + decoBox = mainSurfaceBox; decoBox.addExtents(data->positioningInfo.desiredExtents); } else { - decoBox = data->lastReply.assignedGeometry; - const auto EDGEPOINT = getEdgeDefinedPoint(data->positioningInfo.edges, pWindow); - decoBox.translate(EDGEPOINT); + decoBox = data->lastReply.assignedGeometry; + decoBox.translate(getEdgeDefinedPoint(data->positioningInfo.edges, pWindow)); } + // Check bounds only if decoBox extends beyond accum SBoxExtents extentsToAdd; + bool needUpdate = false; - if (decoBox.x < accum.x) + if (decoBox.x < accum.x) { extentsToAdd.topLeft.x = accum.x - decoBox.x; - if (decoBox.y < accum.y) + needUpdate = true; + } + if (decoBox.y < accum.y) { extentsToAdd.topLeft.y = accum.y - decoBox.y; - if (decoBox.x + decoBox.w > accum.x + accum.w) + needUpdate = true; + } + if (decoBox.x + decoBox.w > accum.x + accum.w) { extentsToAdd.bottomRight.x = (decoBox.x + decoBox.w) - (accum.x + accum.w); - if (decoBox.y + decoBox.h > accum.y + accum.h) + needUpdate = true; + } + if (decoBox.y + decoBox.h > accum.y + accum.h) { extentsToAdd.bottomRight.y = (decoBox.y + decoBox.h) - (accum.y + accum.h); + needUpdate = true; + } - accum.addExtents(extentsToAdd); + if (needUpdate) + accum.addExtents(extentsToAdd); } - return accum.extentsFrom(pWindow->getWindowMainSurfaceBox()); + return accum.extentsFrom(mainSurfaceBox); } CBox CDecorationPositioner::getBoxWithIncludedDecos(PHLWINDOW pWindow) { From 7188ee4f992966c5793efebd6dc70ab377820066 Mon Sep 17 00:00:00 2001 From: MightyPlaza <123664421+MightyPlaza@users.noreply.github.com> Date: Mon, 28 Oct 2024 18:18:58 +0000 Subject: [PATCH 0571/2181] hyprctl: move setprop into dispatchers (#8275) * move setprop into dispatchers modified: src/debug/HyprCtl.cpp modified: src/managers/KeybindManager.cpp modified: src/managers/KeybindManager.hpp * add deprecated modified: src/debug/HyprCtl.cpp --- src/debug/HyprCtl.cpp | 97 +-------------------------------- src/managers/KeybindManager.cpp | 95 ++++++++++++++++++++++++++++++++ src/managers/KeybindManager.hpp | 1 + 3 files changed, 98 insertions(+), 95 deletions(-) diff --git a/src/debug/HyprCtl.cpp b/src/debug/HyprCtl.cpp index bf3ecfc8..93e0f620 100644 --- a/src/debug/HyprCtl.cpp +++ b/src/debug/HyprCtl.cpp @@ -1262,101 +1262,8 @@ std::string dispatchSeterror(eHyprCtlOutputFormat format, std::string request) { } std::string dispatchSetProp(eHyprCtlOutputFormat format, std::string request) { - CVarList vars(request, 0, ' '); - - if (vars.size() < 4) - return "not enough args"; - - const auto PLASTWINDOW = g_pCompositor->m_pLastWindow.lock(); - const auto PWINDOW = g_pCompositor->getWindowByRegex(vars[1]); - - if (!PWINDOW) - return "window not found"; - - const auto PROP = vars[2]; - const auto VAL = vars[3]; - - bool noFocus = PWINDOW->m_sWindowData.noFocus.valueOrDefault(); - - try { - if (PROP == "animationstyle") { - PWINDOW->m_sWindowData.animationStyle = CWindowOverridableVar(VAL, PRIORITY_SET_PROP); - } else if (PROP == "maxsize") { - PWINDOW->m_sWindowData.maxSize = CWindowOverridableVar(configStringToVector2D(VAL + " " + vars[4]), PRIORITY_SET_PROP); - PWINDOW->m_vRealSize = Vector2D(std::min((double)PWINDOW->m_sWindowData.maxSize.value().x, PWINDOW->m_vRealSize.goal().x), - std::min((double)PWINDOW->m_sWindowData.maxSize.value().y, PWINDOW->m_vRealSize.goal().y)); - g_pXWaylandManager->setWindowSize(PWINDOW, PWINDOW->m_vRealSize.goal()); - PWINDOW->setHidden(false); - } else if (PROP == "minsize") { - PWINDOW->m_sWindowData.minSize = CWindowOverridableVar(configStringToVector2D(VAL + " " + vars[4]), PRIORITY_SET_PROP); - PWINDOW->m_vRealSize = Vector2D(std::max((double)PWINDOW->m_sWindowData.minSize.value().x, PWINDOW->m_vRealSize.goal().x), - std::max((double)PWINDOW->m_sWindowData.minSize.value().y, PWINDOW->m_vRealSize.goal().y)); - g_pXWaylandManager->setWindowSize(PWINDOW, PWINDOW->m_vRealSize.goal()); - PWINDOW->setHidden(false); - } else if (PROP == "alpha") { - PWINDOW->m_sWindowData.alpha = CWindowOverridableVar(SAlphaValue{std::stof(VAL), PWINDOW->m_sWindowData.alpha.valueOrDefault().m_bOverride}, PRIORITY_SET_PROP); - } else if (PROP == "alphainactive") { - PWINDOW->m_sWindowData.alphaInactive = - CWindowOverridableVar(SAlphaValue{std::stof(VAL), PWINDOW->m_sWindowData.alphaInactive.valueOrDefault().m_bOverride}, PRIORITY_SET_PROP); - } else if (PROP == "alphafullscreen") { - PWINDOW->m_sWindowData.alphaFullscreen = - CWindowOverridableVar(SAlphaValue{std::stof(VAL), PWINDOW->m_sWindowData.alphaFullscreen.valueOrDefault().m_bOverride}, PRIORITY_SET_PROP); - } else if (PROP == "alphaoverride") { - PWINDOW->m_sWindowData.alpha = - CWindowOverridableVar(SAlphaValue{PWINDOW->m_sWindowData.alpha.valueOrDefault().m_fAlpha, (bool)configStringToInt(VAL)}, PRIORITY_SET_PROP); - } else if (PROP == "alphainactiveoverride") { - PWINDOW->m_sWindowData.alphaInactive = - CWindowOverridableVar(SAlphaValue{PWINDOW->m_sWindowData.alphaInactive.valueOrDefault().m_fAlpha, (bool)configStringToInt(VAL)}, PRIORITY_SET_PROP); - } else if (PROP == "alphafullscreenoverride") { - PWINDOW->m_sWindowData.alphaFullscreen = - CWindowOverridableVar(SAlphaValue{PWINDOW->m_sWindowData.alphaFullscreen.valueOrDefault().m_fAlpha, (bool)configStringToInt(VAL)}, PRIORITY_SET_PROP); - } else if (PROP == "activebordercolor" || PROP == "inactivebordercolor") { - CGradientValueData colorData = {}; - if (vars.size() > 4) { - for (int i = 3; i < static_cast(vars.size()); ++i) { - const auto TOKEN = vars[i]; - if (TOKEN.ends_with("deg")) - colorData.m_fAngle = std::stoi(TOKEN.substr(0, TOKEN.size() - 3)) * (PI / 180.0); - else - colorData.m_vColors.push_back(configStringToInt(TOKEN)); - } - } else if (VAL != "-1") - colorData.m_vColors.push_back(configStringToInt(VAL)); - - if (PROP == "activebordercolor") - PWINDOW->m_sWindowData.activeBorderColor = CWindowOverridableVar(colorData, PRIORITY_SET_PROP); - else - PWINDOW->m_sWindowData.inactiveBorderColor = CWindowOverridableVar(colorData, PRIORITY_SET_PROP); - } else if (auto search = g_pConfigManager->mbWindowProperties.find(PROP); search != g_pConfigManager->mbWindowProperties.end()) { - auto pWindowDataElement = search->second(PWINDOW); - if (VAL == "toggle") - *pWindowDataElement = CWindowOverridableVar(!pWindowDataElement->valueOrDefault(), PRIORITY_SET_PROP); - else if (VAL == "unset") - pWindowDataElement->unset(PRIORITY_SET_PROP); - else - *pWindowDataElement = CWindowOverridableVar((bool)configStringToInt(VAL), PRIORITY_SET_PROP); - } else if (auto search = g_pConfigManager->miWindowProperties.find(PROP); search != g_pConfigManager->miWindowProperties.end()) { - if (VAL == "unset") - search->second(PWINDOW)->unset(PRIORITY_SET_PROP); - else - *(search->second(PWINDOW)) = CWindowOverridableVar((int)configStringToInt(VAL), PRIORITY_SET_PROP); - } else { - return "prop not found"; - } - } catch (std::exception& e) { return "error in parsing prop value: " + std::string(e.what()); } - - g_pCompositor->updateAllWindowsAnimatedDecorationValues(); - - if (!(PWINDOW->m_sWindowData.noFocus.valueOrDefault() == noFocus)) { - g_pCompositor->focusWindow(nullptr); - g_pCompositor->focusWindow(PWINDOW); - g_pCompositor->focusWindow(PLASTWINDOW); - } - - for (auto const& m : g_pCompositor->m_vMonitors) - g_pLayoutManager->getCurrentLayout()->recalculateMonitor(m->ID); - - return "ok"; + auto result = g_pKeybindManager->m_mDispatchers["setprop"](request.substr(request.find_first_of(' ') + 1, -1)); + return "DEPRECATED: use hyprctl dispatch setprop instead" + (result.success ? "" : "\n" + result.error); } std::string dispatchGetOption(eHyprCtlOutputFormat format, std::string request) { diff --git a/src/managers/KeybindManager.cpp b/src/managers/KeybindManager.cpp index b54b71ed..c2779c58 100644 --- a/src/managers/KeybindManager.cpp +++ b/src/managers/KeybindManager.cpp @@ -126,6 +126,7 @@ CKeybindManager::CKeybindManager() { m_mDispatchers["denywindowfromgroup"] = denyWindowFromGroup; m_mDispatchers["event"] = event; m_mDispatchers["global"] = global; + m_mDispatchers["setprop"] = setProp; m_tScrollTimer.reset(); @@ -2891,3 +2892,97 @@ SDispatchResult CKeybindManager::event(std::string args) { g_pEventManager->postEvent(SHyprIPCEvent{"custom", args}); return {}; } + +SDispatchResult CKeybindManager::setProp(std::string args) { + CVarList vars(args, 3, ' '); + + if (vars.size() < 3) + return {.success = false, .error = "Not enough args"}; + + const auto PLASTWINDOW = g_pCompositor->m_pLastWindow.lock(); + const auto PWINDOW = g_pCompositor->getWindowByRegex(vars[0]); + + if (!PWINDOW) + return {.success = false, .error = "Window not found"}; + + const auto PROP = vars[1]; + const auto VAL = vars[2]; + + bool noFocus = PWINDOW->m_sWindowData.noFocus.valueOrDefault(); + + try { + if (PROP == "animationstyle") { + PWINDOW->m_sWindowData.animationStyle = CWindowOverridableVar(VAL, PRIORITY_SET_PROP); + } else if (PROP == "maxsize") { + PWINDOW->m_sWindowData.maxSize = CWindowOverridableVar(configStringToVector2D(VAL), PRIORITY_SET_PROP); + PWINDOW->clampWindowSize(std::nullopt, PWINDOW->m_sWindowData.maxSize.value()); + PWINDOW->setHidden(false); + } else if (PROP == "minsize") { + PWINDOW->m_sWindowData.minSize = CWindowOverridableVar(configStringToVector2D(VAL), PRIORITY_SET_PROP); + PWINDOW->clampWindowSize(PWINDOW->m_sWindowData.minSize.value(), std::nullopt); + PWINDOW->setHidden(false); + } else if (PROP == "alpha") { + PWINDOW->m_sWindowData.alpha = CWindowOverridableVar(SAlphaValue{std::stof(VAL), PWINDOW->m_sWindowData.alpha.valueOrDefault().m_bOverride}, PRIORITY_SET_PROP); + } else if (PROP == "alphainactive") { + PWINDOW->m_sWindowData.alphaInactive = + CWindowOverridableVar(SAlphaValue{std::stof(VAL), PWINDOW->m_sWindowData.alphaInactive.valueOrDefault().m_bOverride}, PRIORITY_SET_PROP); + } else if (PROP == "alphafullscreen") { + PWINDOW->m_sWindowData.alphaFullscreen = + CWindowOverridableVar(SAlphaValue{std::stof(VAL), PWINDOW->m_sWindowData.alphaFullscreen.valueOrDefault().m_bOverride}, PRIORITY_SET_PROP); + } else if (PROP == "alphaoverride") { + PWINDOW->m_sWindowData.alpha = + CWindowOverridableVar(SAlphaValue{PWINDOW->m_sWindowData.alpha.valueOrDefault().m_fAlpha, (bool)configStringToInt(VAL)}, PRIORITY_SET_PROP); + } else if (PROP == "alphainactiveoverride") { + PWINDOW->m_sWindowData.alphaInactive = + CWindowOverridableVar(SAlphaValue{PWINDOW->m_sWindowData.alphaInactive.valueOrDefault().m_fAlpha, (bool)configStringToInt(VAL)}, PRIORITY_SET_PROP); + } else if (PROP == "alphafullscreenoverride") { + PWINDOW->m_sWindowData.alphaFullscreen = + CWindowOverridableVar(SAlphaValue{PWINDOW->m_sWindowData.alphaFullscreen.valueOrDefault().m_fAlpha, (bool)configStringToInt(VAL)}, PRIORITY_SET_PROP); + } else if (PROP == "activebordercolor" || PROP == "inactivebordercolor") { + CGradientValueData colorData = {}; + if (vars.size() > 4) { + for (int i = 3; i < static_cast(vars.size()); ++i) { + const auto TOKEN = vars[i]; + if (TOKEN.ends_with("deg")) + colorData.m_fAngle = std::stoi(TOKEN.substr(0, TOKEN.size() - 3)) * (PI / 180.0); + else + colorData.m_vColors.push_back(configStringToInt(TOKEN)); + } + } else if (VAL != "-1") + colorData.m_vColors.push_back(configStringToInt(VAL)); + + if (PROP == "activebordercolor") + PWINDOW->m_sWindowData.activeBorderColor = CWindowOverridableVar(colorData, PRIORITY_SET_PROP); + else + PWINDOW->m_sWindowData.inactiveBorderColor = CWindowOverridableVar(colorData, PRIORITY_SET_PROP); + } else if (auto search = g_pConfigManager->mbWindowProperties.find(PROP); search != g_pConfigManager->mbWindowProperties.end()) { + auto pWindowDataElement = search->second(PWINDOW); + if (VAL == "toggle") + *pWindowDataElement = CWindowOverridableVar(!pWindowDataElement->valueOrDefault(), PRIORITY_SET_PROP); + else if (VAL == "unset") + pWindowDataElement->unset(PRIORITY_SET_PROP); + else + *pWindowDataElement = CWindowOverridableVar((bool)configStringToInt(VAL), PRIORITY_SET_PROP); + } else if (auto search = g_pConfigManager->miWindowProperties.find(PROP); search != g_pConfigManager->miWindowProperties.end()) { + if (VAL == "unset") + search->second(PWINDOW)->unset(PRIORITY_SET_PROP); + else + *(search->second(PWINDOW)) = CWindowOverridableVar((int)configStringToInt(VAL), PRIORITY_SET_PROP); + } else { + return {.success = false, .error = "Prop not found"}; + } + } catch (std::exception& e) { return {.success = false, .error = std::format("Error parsing prop value: {}", std::string(e.what()))}; } + + g_pCompositor->updateAllWindowsAnimatedDecorationValues(); + + if (!(PWINDOW->m_sWindowData.noFocus.valueOrDefault() == noFocus)) { + g_pCompositor->focusWindow(nullptr); + g_pCompositor->focusWindow(PWINDOW); + g_pCompositor->focusWindow(PLASTWINDOW); + } + + for (auto const& m : g_pCompositor->m_vMonitors) + g_pLayoutManager->getCurrentLayout()->recalculateMonitor(m->ID); + + return {}; +} diff --git a/src/managers/KeybindManager.hpp b/src/managers/KeybindManager.hpp index 8981dcaf..24a09836 100644 --- a/src/managers/KeybindManager.hpp +++ b/src/managers/KeybindManager.hpp @@ -217,6 +217,7 @@ class CKeybindManager { static SDispatchResult denyWindowFromGroup(std::string); static SDispatchResult global(std::string); static SDispatchResult event(std::string); + static SDispatchResult setProp(std::string); friend class CCompositor; friend class CInputManager; From d679d200299ed4670f0d0f138c793d5f507b7cec Mon Sep 17 00:00:00 2001 From: staticssleever668 Date: Mon, 28 Oct 2024 22:25:27 +0300 Subject: [PATCH 0572/2181] seat: avoid sending pointless 'keymap' and 'repeat_info' events (#8276) #### Describe your PR, what does it fix/add? Fix lag spikes when pressing more than 6 keys at the same time. #### Is there anything you want to mention? (unchecked code, possible bugs, found problems, breaking compatibility, etc.) Debugging process:
This is triggered by typing some applications, like CopyQ or XWayland. Typing in Firefox doesn't lead to lag, however it itself does lag handling these events. Profiling CopyQ shows that paths leading to `QtWaylandClient::QWaylandInputDevice::Keyboard::keyboard` take over 80% of processing time of an otherwise idle program. Looking at output of 'wev' even when it's not focused shows same events received over and over again. ``` [14: wl_keyboard] repeat_info: rate: 25 keys/sec; delay: 300 ms [14: wl_keyboard] keymap: format: 1 (xkb v1), size: 64754 ``` Looking at what passes through CInputManager::onKeyboardKey() -> CSeatManager::setKeyboard() shows Hyprland 'switching' between endpoints of the same keyboard, one of them being named like the other but with '-1' suffix.
Tested changing layouts in Fcitx5 and with following config. ``` input:kb_layout = us,cz input:kb_variant = ,qwerty input:kb_options = grp:alt_shift_toggle ``` Also tested changing 'input:repeat_delay' while running. Curiously, now these events appear in the output of 'wev' only once. Changing layouts still seems to work fine though. #### Is it ready for merging, or does it need work? Ready for merging. --- src/protocols/core/Seat.cpp | 24 ++++++++++++++++++------ src/protocols/core/Seat.hpp | 4 ++++ 2 files changed, 22 insertions(+), 6 deletions(-) diff --git a/src/protocols/core/Seat.cpp b/src/protocols/core/Seat.cpp index 6ae0ddc4..d95e0e12 100644 --- a/src/protocols/core/Seat.cpp +++ b/src/protocols/core/Seat.cpp @@ -317,12 +317,13 @@ void CWLKeyboardResource::sendKeymap(SP keyboard) { if (!(PROTO::seat->currentCaps & eHIDCapabilityType::HID_INPUT_CAPABILITY_KEYBOARD)) return; - wl_keyboard_keymap_format format = keyboard ? WL_KEYBOARD_KEYMAP_FORMAT_XKB_V1 : WL_KEYBOARD_KEYMAP_FORMAT_NO_KEYMAP; - int fd; - uint32_t size; + std::string_view keymap; + int fd; + uint32_t size; if (keyboard) { - fd = keyboard->xkbKeymapFD; - size = keyboard->xkbKeymapString.length() + 1; + keymap = keyboard->xkbKeymapString; + fd = keyboard->xkbKeymapFD; + size = keyboard->xkbKeymapString.length() + 1; } else { fd = open("/dev/null", O_RDONLY | O_CLOEXEC); if (fd < 0) { @@ -332,6 +333,15 @@ void CWLKeyboardResource::sendKeymap(SP keyboard) { size = 0; } + if (keymap == lastKeymap) { + if (!keyboard) + close(fd); + return; + } + lastKeymap = keymap; + + const wl_keyboard_keymap_format format = keyboard ? WL_KEYBOARD_KEYMAP_FORMAT_XKB_V1 : WL_KEYBOARD_KEYMAP_FORMAT_NO_KEYMAP; + resource->sendKeymap(format, fd, size); if (!keyboard) @@ -396,8 +406,10 @@ void CWLKeyboardResource::sendMods(uint32_t depressed, uint32_t latched, uint32_ } void CWLKeyboardResource::repeatInfo(uint32_t rate, uint32_t delayMs) { - if (!owner || resource->version() < 4) + if (!owner || resource->version() < 4 || (rate == lastRate && delayMs == lastDelayMs)) return; + lastRate = rate; + lastDelayMs = delayMs; resource->sendRepeatInfo(rate, delayMs); } diff --git a/src/protocols/core/Seat.hpp b/src/protocols/core/Seat.hpp index 755a9c2f..1b43dd04 100644 --- a/src/protocols/core/Seat.hpp +++ b/src/protocols/core/Seat.hpp @@ -119,6 +119,10 @@ class CWLKeyboardResource { struct { CHyprSignalListener destroySurface; } listeners; + + std::string lastKeymap = ""; + uint32_t lastRate = 0; + uint32_t lastDelayMs = 0; }; class CWLSeatResource { From 5f721dce36651232ae245d872c17dfa3aae5cc6c Mon Sep 17 00:00:00 2001 From: Aqa-Ib Date: Wed, 30 Oct 2024 10:00:58 +0000 Subject: [PATCH 0573/2181] group: fix moveWindowIntoGroup (#8297) --- src/layout/IHyprLayout.cpp | 19 ++++++++----------- src/managers/KeybindManager.cpp | 3 +-- .../decorations/CHyprGroupBarDecoration.cpp | 6 +++--- 3 files changed, 12 insertions(+), 16 deletions(-) diff --git a/src/layout/IHyprLayout.cpp b/src/layout/IHyprLayout.cpp index e3606532..f2616668 100644 --- a/src/layout/IHyprLayout.cpp +++ b/src/layout/IHyprLayout.cpp @@ -341,7 +341,9 @@ void IHyprLayout::onEndDragWindow() { const bool FLOATEDINTOTILED = !pWindow->m_bIsFloating && !DRAGGINGWINDOW->m_bDraggingTiled; static auto PDRAGINTOGROUP = CConfigValue("group:drag_into_group"); + if (pWindow->m_sGroupData.pNextWindow.lock() && DRAGGINGWINDOW->canBeGroupedInto(pWindow) && *PDRAGINTOGROUP == 1 && !FLOATEDINTOTILED) { + if (DRAGGINGWINDOW->m_bDraggingTiled) { changeWindowFloatingMode(DRAGGINGWINDOW); DRAGGINGWINDOW->m_vLastFloatingSize = m_vDraggingWindowOriginalFloatSize; @@ -349,17 +351,12 @@ void IHyprLayout::onEndDragWindow() { } if (DRAGGINGWINDOW->m_sGroupData.pNextWindow) { - std::vector members; - PHLWINDOW curr = DRAGGINGWINDOW->getGroupHead(); - do { - members.push_back(curr); - curr = curr->m_sGroupData.pNextWindow.lock(); - } while (curr != members[0]); - - for (auto it = members.begin(); it != members.end(); ++it) { - (*it)->m_bIsFloating = pWindow->m_bIsFloating; // match the floating state of group members - if (pWindow->m_bIsFloating) - (*it)->m_vRealSize = pWindow->m_vRealSize.goal(); // match the size of group members + PHLWINDOW next = DRAGGINGWINDOW->m_sGroupData.pNextWindow.lock(); + while (next != DRAGGINGWINDOW) { + next->m_bIsFloating = pWindow->m_bIsFloating; // match the floating state of group members + next->m_vRealSize = pWindow->m_vRealSize.goal(); // match the size of group members + next->m_vRealPosition = pWindow->m_vRealPosition.goal(); // match the position of group members + next = next->m_sGroupData.pNextWindow.lock(); } } diff --git a/src/managers/KeybindManager.cpp b/src/managers/KeybindManager.cpp index c2779c58..5be6a1d9 100644 --- a/src/managers/KeybindManager.cpp +++ b/src/managers/KeybindManager.cpp @@ -2665,9 +2665,8 @@ void CKeybindManager::moveWindowIntoGroup(PHLWINDOW pWindow, PHLWINDOW pWindowIn } static auto USECURRPOS = CConfigValue("group:insert_after_current"); - pWindowInDirection = *USECURRPOS ? pWindowInDirection : pWindowInDirection->getGroupTail(); + (*USECURRPOS ? pWindowInDirection : pWindowInDirection->getGroupTail())->insertWindowToGroup(pWindow); - pWindowInDirection->insertWindowToGroup(pWindow); pWindowInDirection->setGroupCurrent(pWindow); pWindow->updateWindowDecos(); g_pLayoutManager->getCurrentLayout()->recalculateWindow(pWindow); diff --git a/src/render/decorations/CHyprGroupBarDecoration.cpp b/src/render/decorations/CHyprGroupBarDecoration.cpp index e342e244..c9f812d7 100644 --- a/src/render/decorations/CHyprGroupBarDecoration.cpp +++ b/src/render/decorations/CHyprGroupBarDecoration.cpp @@ -439,9 +439,9 @@ bool CHyprGroupBarDecoration::onEndWindowDragOnDeco(const Vector2D& pos, PHLWIND // restores the group for (auto it = members.begin(); it != members.end(); ++it) { - (*it)->m_bIsFloating = pWindowInsertAfter->m_bIsFloating; // match the floating state of group members - if (pWindowInsertAfter->m_bIsFloating) - (*it)->m_vRealSize = pWindowInsertAfter->m_vRealSize.goal(); // match the size of group members + (*it)->m_bIsFloating = pWindowInsertAfter->m_bIsFloating; // match the floating state of group members + (*it)->m_vRealSize = pWindowInsertAfter->m_vRealSize.goal(); // match the size of group members + (*it)->m_vRealPosition = pWindowInsertAfter->m_vRealPosition.goal(); // match the position of group members if (std::next(it) != members.end()) (*it)->m_sGroupData.pNextWindow = *std::next(it); else From 12c1bb936dd463c4188def1c73c2bb786433a6dc Mon Sep 17 00:00:00 2001 From: MightyPlaza <123664421+MightyPlaza@users.noreply.github.com> Date: Wed, 30 Oct 2024 18:58:36 +0000 Subject: [PATCH 0574/2181] internal: check size limit in layouts (#8298) modified: src/desktop/Window.cpp modified: src/desktop/Window.hpp modified: src/events/Windows.cpp modified: src/helpers/MiscFunctions.cpp modified: src/helpers/MiscFunctions.hpp modified: src/layout/DwindleLayout.cpp modified: src/layout/IHyprLayout.cpp modified: src/layout/MasterLayout.cpp modified: src/macros.hpp --- src/desktop/Window.cpp | 2 +- src/desktop/Window.hpp | 7 +++++++ src/events/Windows.cpp | 32 +++++++++++--------------------- src/helpers/MiscFunctions.cpp | 7 +++++++ src/helpers/MiscFunctions.hpp | 1 + src/layout/DwindleLayout.cpp | 4 +++- src/layout/IHyprLayout.cpp | 19 +++++++++---------- src/layout/MasterLayout.cpp | 4 +++- src/macros.hpp | 2 ++ 9 files changed, 44 insertions(+), 34 deletions(-) diff --git a/src/desktop/Window.cpp b/src/desktop/Window.cpp index 60f3b79d..20fed565 100644 --- a/src/desktop/Window.cpp +++ b/src/desktop/Window.cpp @@ -1255,7 +1255,7 @@ int CWindow::surfacesCount() { void CWindow::clampWindowSize(const std::optional minSize, const std::optional maxSize) { const Vector2D REALSIZE = m_vRealSize.goal(); - const Vector2D NEWSIZE = REALSIZE.clamp(minSize.value_or(Vector2D{0.f, 0.f}), maxSize.value_or(Vector2D{INFINITY, INFINITY})); + const Vector2D NEWSIZE = REALSIZE.clamp(minSize.value_or(Vector2D{MIN_WINDOW_SIZE, MIN_WINDOW_SIZE}), maxSize.value_or(Vector2D{INFINITY, INFINITY})); const Vector2D DELTA = REALSIZE - NEWSIZE; m_vRealPosition = m_vRealPosition.goal() + DELTA / 2.0; diff --git a/src/desktop/Window.hpp b/src/desktop/Window.hpp index 825e8ca2..b8dd3cf7 100644 --- a/src/desktop/Window.hpp +++ b/src/desktop/Window.hpp @@ -144,6 +144,13 @@ class CWindowOverridableVar { unset(priority); } + operator std::optional() { + if (hasValue()) + return value(); + else + return std::nullopt; + } + private: std::map values; T defaultValue; // used for toggling, so required for bool diff --git a/src/events/Windows.cpp b/src/events/Windows.cpp index 30d982fb..f946ce03 100644 --- a/src/events/Windows.cpp +++ b/src/events/Windows.cpp @@ -334,13 +334,6 @@ void Events::listener_mapWindow(void* owner, void* data) { try { auto stringToFloatClamp = [](const std::string& VALUE, const float CURR, const float REL) { - auto stringToPercentage = [](const std::string& VALUE, const float REL) { - if (VALUE.ends_with('%')) - return (std::stof(VALUE.substr(0, VALUE.length() - 1)) * REL) / 100; - else - return std::stof(VALUE); - }; - if (VALUE.starts_with('<')) return std::min(CURR, stringToPercentage(VALUE.substr(1, VALUE.length() - 1), REL)); else if (VALUE.starts_with('>')) @@ -355,11 +348,11 @@ void Events::listener_mapWindow(void* owner, void* data) { const auto MAXSIZE = g_pXWaylandManager->getMaxSizeForWindow(PWINDOW); - const float SIZEX = - SIZEXSTR == "max" ? std::clamp(MAXSIZE.x, 20.0, PMONITOR->vecSize.x) : stringToFloatClamp(SIZEXSTR, PWINDOW->m_vRealSize.goal().x, PMONITOR->vecSize.x); + const float SIZEX = SIZEXSTR == "max" ? std::clamp(MAXSIZE.x, MIN_WINDOW_SIZE, PMONITOR->vecSize.x) : + stringToFloatClamp(SIZEXSTR, PWINDOW->m_vRealSize.goal().x, PMONITOR->vecSize.x); - const float SIZEY = - SIZEYSTR == "max" ? std::clamp(MAXSIZE.y, 20.0, PMONITOR->vecSize.y) : stringToFloatClamp(SIZEYSTR, PWINDOW->m_vRealSize.goal().y, PMONITOR->vecSize.y); + const float SIZEY = SIZEYSTR == "max" ? std::clamp(MAXSIZE.y, MIN_WINDOW_SIZE, PMONITOR->vecSize.y) : + stringToFloatClamp(SIZEYSTR, PWINDOW->m_vRealSize.goal().y, PMONITOR->vecSize.y); Debug::log(LOG, "Rule size, applying to {}", PWINDOW); @@ -472,18 +465,15 @@ void Events::listener_mapWindow(void* owner, void* data) { for (auto const& r : PWINDOW->m_vMatchedRules) { if (r.szRule.starts_with("size")) { try { - const auto VALUE = r.szRule.substr(r.szRule.find(' ') + 1); - const auto SIZEXSTR = VALUE.substr(0, VALUE.find(' ')); - const auto SIZEYSTR = VALUE.substr(VALUE.find(' ') + 1); + const auto VALUE = r.szRule.substr(r.szRule.find(' ') + 1); + const auto SIZEXSTR = VALUE.substr(0, VALUE.find(' ')); + const auto SIZEYSTR = VALUE.substr(VALUE.find(' ') + 1); - const auto MAXSIZE = g_pXWaylandManager->getMaxSizeForWindow(PWINDOW); + const auto MAXSIZE = g_pXWaylandManager->getMaxSizeForWindow(PWINDOW); - const auto SIZEX = SIZEXSTR == "max" ? - std::clamp(MAXSIZE.x, 20.0, PMONITOR->vecSize.x) : - (!SIZEXSTR.contains('%') ? std::stoi(SIZEXSTR) : std::stof(SIZEXSTR.substr(0, SIZEXSTR.length() - 1)) * 0.01 * PMONITOR->vecSize.x); - const auto SIZEY = SIZEYSTR == "max" ? - std::clamp(MAXSIZE.y, 20.0, PMONITOR->vecSize.y) : - (!SIZEYSTR.contains('%') ? std::stoi(SIZEYSTR) : std::stof(SIZEYSTR.substr(0, SIZEYSTR.length() - 1)) * 0.01 * PMONITOR->vecSize.y); + const float SIZEX = SIZEXSTR == "max" ? std::clamp(MAXSIZE.x, MIN_WINDOW_SIZE, PMONITOR->vecSize.x) : stringToPercentage(SIZEXSTR, PMONITOR->vecSize.x); + + const float SIZEY = SIZEYSTR == "max" ? std::clamp(MAXSIZE.y, MIN_WINDOW_SIZE, PMONITOR->vecSize.y) : stringToPercentage(SIZEYSTR, PMONITOR->vecSize.y); Debug::log(LOG, "Rule size (tiled), applying to {}", PWINDOW); diff --git a/src/helpers/MiscFunctions.cpp b/src/helpers/MiscFunctions.cpp index 29861af7..878f5ca1 100644 --- a/src/helpers/MiscFunctions.cpp +++ b/src/helpers/MiscFunctions.cpp @@ -863,3 +863,10 @@ bool allocateSHMFilePair(size_t size, int* rw_fd_ptr, int* ro_fd_ptr) { *ro_fd_ptr = ro_fd; return true; } + +float stringToPercentage(const std::string& VALUE, const float REL) { + if (VALUE.ends_with('%')) + return (std::stof(VALUE.substr(0, VALUE.length() - 1)) * REL) / 100.f; + else + return std::stof(VALUE); +}; diff --git a/src/helpers/MiscFunctions.hpp b/src/helpers/MiscFunctions.hpp index f696fc5d..34b23746 100644 --- a/src/helpers/MiscFunctions.hpp +++ b/src/helpers/MiscFunctions.hpp @@ -40,6 +40,7 @@ void throwError(const std::string& err); bool envEnabled(const std::string& env); int allocateSHMFile(size_t len); bool allocateSHMFilePair(size_t size, int* rw_fd_ptr, int* ro_fd_ptr); +float stringToPercentage(const std::string& VALUE, const float REL); template [[deprecated("use std::format instead")]] std::string getFormat(std::format_string fmt, Args&&... args) { diff --git a/src/layout/DwindleLayout.cpp b/src/layout/DwindleLayout.cpp index 059dda99..32f64e4e 100644 --- a/src/layout/DwindleLayout.cpp +++ b/src/layout/DwindleLayout.cpp @@ -568,7 +568,9 @@ void CHyprDwindleLayout::resizeActiveWindow(const Vector2D& pixResize, eRectCorn const auto PNODE = getNodeFromWindow(PWINDOW); if (!PNODE) { - PWINDOW->m_vRealSize = Vector2D(std::max((PWINDOW->m_vRealSize.goal() + pixResize).x, 20.0), std::max((PWINDOW->m_vRealSize.goal() + pixResize).y, 20.0)); + PWINDOW->m_vRealSize = + (PWINDOW->m_vRealSize.goal() + pixResize) + .clamp(PWINDOW->m_sWindowData.minSize.valueOr(Vector2D{MIN_WINDOW_SIZE, MIN_WINDOW_SIZE}), PWINDOW->m_sWindowData.maxSize.valueOr(Vector2D{INFINITY, INFINITY})); PWINDOW->updateWindowDecos(); return; } diff --git a/src/layout/IHyprLayout.cpp b/src/layout/IHyprLayout.cpp index f2616668..73e7a125 100644 --- a/src/layout/IHyprLayout.cpp +++ b/src/layout/IHyprLayout.cpp @@ -881,18 +881,17 @@ Vector2D IHyprLayout::predictSizeForNewWindowFloating(PHLWINDOW pWindow) { // ge for (auto const& r : g_pConfigManager->getMatchingRules(pWindow, true, true)) { if (r.szRule.starts_with("size")) { try { - const auto VALUE = r.szRule.substr(r.szRule.find(' ') + 1); - const auto SIZEXSTR = VALUE.substr(0, VALUE.find(' ')); - const auto SIZEYSTR = VALUE.substr(VALUE.find(' ') + 1); + const auto VALUE = r.szRule.substr(r.szRule.find(' ') + 1); + const auto SIZEXSTR = VALUE.substr(0, VALUE.find(' ')); + const auto SIZEYSTR = VALUE.substr(VALUE.find(' ') + 1); - const auto MAXSIZE = g_pXWaylandManager->getMaxSizeForWindow(pWindow); + const auto MAXSIZE = g_pXWaylandManager->getMaxSizeForWindow(pWindow); - const auto SIZEX = SIZEXSTR == "max" ? - std::clamp(MAXSIZE.x, 20.0, g_pCompositor->m_pLastMonitor->vecSize.x) : - (!SIZEXSTR.contains('%') ? std::stoi(SIZEXSTR) : std::stof(SIZEXSTR.substr(0, SIZEXSTR.length() - 1)) * 0.01 * g_pCompositor->m_pLastMonitor->vecSize.x); - const auto SIZEY = SIZEYSTR == "max" ? - std::clamp(MAXSIZE.y, 20.0, g_pCompositor->m_pLastMonitor->vecSize.y) : - (!SIZEYSTR.contains('%') ? std::stoi(SIZEYSTR) : std::stof(SIZEYSTR.substr(0, SIZEYSTR.length() - 1)) * 0.01 * g_pCompositor->m_pLastMonitor->vecSize.y); + const float SIZEX = SIZEXSTR == "max" ? std::clamp(MAXSIZE.x, MIN_WINDOW_SIZE, g_pCompositor->m_pLastMonitor->vecSize.x) : + stringToPercentage(SIZEXSTR, g_pCompositor->m_pLastMonitor->vecSize.x); + + const float SIZEY = SIZEYSTR == "max" ? std::clamp(MAXSIZE.y, MIN_WINDOW_SIZE, g_pCompositor->m_pLastMonitor->vecSize.y) : + stringToPercentage(SIZEYSTR, g_pCompositor->m_pLastMonitor->vecSize.y); sizeOverride = {SIZEX, SIZEY}; diff --git a/src/layout/MasterLayout.cpp b/src/layout/MasterLayout.cpp index a2321a41..afe79ecf 100644 --- a/src/layout/MasterLayout.cpp +++ b/src/layout/MasterLayout.cpp @@ -706,7 +706,9 @@ void CHyprMasterLayout::resizeActiveWindow(const Vector2D& pixResize, eRectCorne const auto PNODE = getNodeFromWindow(PWINDOW); if (!PNODE) { - PWINDOW->m_vRealSize = Vector2D(std::max((PWINDOW->m_vRealSize.goal() + pixResize).x, 20.0), std::max((PWINDOW->m_vRealSize.goal() + pixResize).y, 20.0)); + PWINDOW->m_vRealSize = + (PWINDOW->m_vRealSize.goal() + pixResize) + .clamp(PWINDOW->m_sWindowData.minSize.valueOr(Vector2D{MIN_WINDOW_SIZE, MIN_WINDOW_SIZE}), PWINDOW->m_sWindowData.maxSize.valueOr(Vector2D{INFINITY, INFINITY})); PWINDOW->updateWindowDecos(); return; } diff --git a/src/macros.hpp b/src/macros.hpp index 44014085..8915e12d 100644 --- a/src/macros.hpp +++ b/src/macros.hpp @@ -29,6 +29,8 @@ #define MONITOR_INVALID -1L +#define MIN_WINDOW_SIZE 20.0 + #define LISTENER(name) \ void listener_##name(wl_listener*, void*); \ inline wl_listener listen_##name = {.notify = listener_##name} From ee91df62f0be6ac65eae0eb3ed74383a3671aef7 Mon Sep 17 00:00:00 2001 From: nickodei <46863421+nickodei@users.noreply.github.com> Date: Wed, 30 Oct 2024 20:12:16 +0100 Subject: [PATCH 0575/2181] input: simulate mouse movement after scroll to refocus window (#8279) --- src/managers/input/InputManager.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/src/managers/input/InputManager.cpp b/src/managers/input/InputManager.cpp index 028286bf..91c12ece 100644 --- a/src/managers/input/InputManager.cpp +++ b/src/managers/input/InputManager.cpp @@ -831,6 +831,7 @@ void CInputManager::onMouseWheel(IPointer::SAxisEvent e) { int32_t deltaDiscrete = std::abs(discrete) != 0 && std::abs(discrete) < 1 ? std::copysign(1, discrete) : std::round(discrete); g_pSeatManager->sendPointerAxis(e.timeMs, e.axis, delta, deltaDiscrete, value120, e.source, WL_POINTER_AXIS_RELATIVE_DIRECTION_IDENTICAL); + simulateMouseMovement(); } Vector2D CInputManager::getMouseCoordsInternal() { From a0b2169ed600b71627188dcd208b26911da8d583 Mon Sep 17 00:00:00 2001 From: Vaxry Date: Wed, 30 Oct 2024 22:14:43 +0000 Subject: [PATCH 0576/2181] input: revert #8279 --- src/managers/input/InputManager.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/src/managers/input/InputManager.cpp b/src/managers/input/InputManager.cpp index 91c12ece..028286bf 100644 --- a/src/managers/input/InputManager.cpp +++ b/src/managers/input/InputManager.cpp @@ -831,7 +831,6 @@ void CInputManager::onMouseWheel(IPointer::SAxisEvent e) { int32_t deltaDiscrete = std::abs(discrete) != 0 && std::abs(discrete) < 1 ? std::copysign(1, discrete) : std::round(discrete); g_pSeatManager->sendPointerAxis(e.timeMs, e.axis, delta, deltaDiscrete, value120, e.source, WL_POINTER_AXIS_RELATIVE_DIRECTION_IDENTICAL); - simulateMouseMovement(); } Vector2D CInputManager::getMouseCoordsInternal() { From 7c7a84ff60f8c1e00c6a0de3f7656f0bbd933d56 Mon Sep 17 00:00:00 2001 From: Tom Englund Date: Thu, 31 Oct 2024 00:20:32 +0100 Subject: [PATCH 0577/2181] internal: more profiling less calls and local copies (#8300) * compositor: reduce amount of window box copies mousemoveunified can call this very frequently, the cbox copying actually shows up as an impact in such cases, move it down in the scope and only do it when necessery. * core: constify and reference frequent calls profiling shows these as frequent called functions try to reduce the amount of copies with references and const the variables. * pointermgr: remove not used local copy, const ref remove unneded local copies and const ref cursorsize. * inputmgr: reduce amount of calls to vectortowindow the amount of calls to g_pCompositor->vectorToWindowUnified fast ramps up in cpu usage with enough windows existing and moving the mouse, move the PWINDOWIDEAL up and reuse it if its already the same. * protocol: compositor remove unused local copy remove unused local copy of accumulateCurrentBufferDamage and const previousBuffer. * renderer: reduce scope of variables and refactor move a few variables down in their scopes to reduce the amount of calls and copies when not needed, also add one more for loop in renderWorkspaceWindows and store the windows in a vector with weakpointers that should be rendered, this adds a loop but reduces the amount of repeated calls to shouldRenderWindow and also makes the rest of the loops go over way smaller vector when many windows exist. --- src/Compositor.cpp | 29 ++++++---- src/managers/PointerManager.cpp | 19 +++---- src/managers/eventLoop/EventLoopManager.cpp | 2 +- src/managers/input/InputManager.cpp | 14 +++-- src/protocols/core/Compositor.cpp | 6 +- src/render/Renderer.cpp | 55 ++++++++++--------- .../decorations/CHyprBorderDecoration.cpp | 2 +- .../decorations/CHyprBorderDecoration.hpp | 2 +- .../decorations/CHyprDropShadowDecoration.cpp | 2 +- .../decorations/CHyprDropShadowDecoration.hpp | 2 +- .../decorations/CHyprGroupBarDecoration.cpp | 2 +- .../decorations/CHyprGroupBarDecoration.hpp | 2 +- .../decorations/IHyprWindowDecoration.hpp | 2 +- 13 files changed, 71 insertions(+), 68 deletions(-) diff --git a/src/Compositor.cpp b/src/Compositor.cpp index a2fe9935..65891633 100644 --- a/src/Compositor.cpp +++ b/src/Compositor.cpp @@ -811,10 +811,10 @@ PHLWINDOW CCompositor::vectorToWindowUnified(const Vector2D& pos, uint8_t proper // pinned windows on top of floating regardless if (properties & ALLOW_FLOATING) { for (auto const& w : m_vWindows | std::views::reverse) { - const auto BB = w->getWindowBoxUnified(properties); - CBox box = BB.copy().expand(!w->isX11OverrideRedirect() ? BORDER_GRAB_AREA : 0); if (w->m_bIsFloating && w->m_bIsMapped && !w->isHidden() && !w->m_bX11ShouldntFocus && w->m_bPinned && !w->m_sWindowData.noFocus.valueOrDefault() && w != pIgnoreWindow) { + const auto BB = w->getWindowBoxUnified(properties); + CBox box = BB.copy().expand(!w->isX11OverrideRedirect() ? BORDER_GRAB_AREA : 0); if (box.containsPoint(g_pPointerManager->position())) return w; @@ -833,22 +833,25 @@ PHLWINDOW CCompositor::vectorToWindowUnified(const Vector2D& pos, uint8_t proper if (special && !w->onSpecialWorkspace()) // because special floating may creep up into regular continue; - const auto BB = w->getWindowBoxUnified(properties); const auto PWINDOWMONITOR = w->m_pMonitor.lock(); // to avoid focusing windows behind special workspaces from other monitors - if (!*PSPECIALFALLTHRU && PWINDOWMONITOR && PWINDOWMONITOR->activeSpecialWorkspace && w->m_pWorkspace != PWINDOWMONITOR->activeSpecialWorkspace && - BB.x >= PWINDOWMONITOR->vecPosition.x && BB.y >= PWINDOWMONITOR->vecPosition.y && - BB.x + BB.width <= PWINDOWMONITOR->vecPosition.x + PWINDOWMONITOR->vecSize.x && BB.y + BB.height <= PWINDOWMONITOR->vecPosition.y + PWINDOWMONITOR->vecSize.y) - continue; + if (!*PSPECIALFALLTHRU && PWINDOWMONITOR && PWINDOWMONITOR->activeSpecialWorkspace && w->m_pWorkspace != PWINDOWMONITOR->activeSpecialWorkspace) { + const auto BB = w->getWindowBoxUnified(properties); + if (BB.x >= PWINDOWMONITOR->vecPosition.x && BB.y >= PWINDOWMONITOR->vecPosition.y && + BB.x + BB.width <= PWINDOWMONITOR->vecPosition.x + PWINDOWMONITOR->vecSize.x && + BB.y + BB.height <= PWINDOWMONITOR->vecPosition.y + PWINDOWMONITOR->vecSize.y) + continue; + } - CBox box = BB.copy().expand(!w->isX11OverrideRedirect() ? BORDER_GRAB_AREA : 0); if (w->m_bIsFloating && w->m_bIsMapped && isWorkspaceVisible(w->m_pWorkspace) && !w->isHidden() && !w->m_bPinned && !w->m_sWindowData.noFocus.valueOrDefault() && w != pIgnoreWindow && (!aboveFullscreen || w->m_bCreatedOverFullscreen)) { // OR windows should add focus to parent if (w->m_bX11ShouldntFocus && !w->isX11OverrideRedirect()) continue; + const auto BB = w->getWindowBoxUnified(properties); + CBox box = BB.copy().expand(!w->isX11OverrideRedirect() ? BORDER_GRAB_AREA : 0); if (box.containsPoint(g_pPointerManager->position())) { if (w->m_bIsX11 && w->isX11OverrideRedirect() && !w->m_pXWaylandSurface->wantsFocus()) { @@ -906,10 +909,12 @@ PHLWINDOW CCompositor::vectorToWindowUnified(const Vector2D& pos, uint8_t proper if (special != w->onSpecialWorkspace()) continue; - CBox box = (properties & USE_PROP_TILED) ? w->getWindowBoxUnified(properties) : CBox{w->m_vPosition, w->m_vSize}; - if (!w->m_bIsFloating && w->m_bIsMapped && box.containsPoint(pos) && w->workspaceID() == WSPID && !w->isHidden() && !w->m_bX11ShouldntFocus && - !w->m_sWindowData.noFocus.valueOrDefault() && w != pIgnoreWindow) - return w; + if (!w->m_bIsFloating && w->m_bIsMapped && w->workspaceID() == WSPID && !w->isHidden() && !w->m_bX11ShouldntFocus && !w->m_sWindowData.noFocus.valueOrDefault() && + w != pIgnoreWindow) { + CBox box = (properties & USE_PROP_TILED) ? w->getWindowBoxUnified(properties) : CBox{w->m_vPosition, w->m_vSize}; + if (box.containsPoint(pos)) + return w; + } } return nullptr; diff --git a/src/managers/PointerManager.cpp b/src/managers/PointerManager.cpp index d2114e79..b309ba82 100644 --- a/src/managers/PointerManager.cpp +++ b/src/managers/PointerManager.cpp @@ -52,7 +52,7 @@ void CPointerManager::unlockSoftwareAll() { } void CPointerManager::lockSoftwareForMonitor(PHLMONITOR mon) { - auto state = stateFor(mon); + auto const state = stateFor(mon); state->softwareLocks++; if (state->softwareLocks == 1) @@ -60,7 +60,7 @@ void CPointerManager::lockSoftwareForMonitor(PHLMONITOR mon) { } void CPointerManager::unlockSoftwareForMonitor(PHLMONITOR mon) { - auto state = stateFor(mon); + auto const state = stateFor(mon); state->softwareLocks--; if (state->softwareLocks < 0) state->softwareLocks = 0; @@ -70,7 +70,7 @@ void CPointerManager::unlockSoftwareForMonitor(PHLMONITOR mon) { } bool CPointerManager::softwareLockedFor(PHLMONITOR mon) { - auto state = stateFor(mon); + auto const state = stateFor(mon); return state->softwareLocks > 0 || state->hardwareFailed; } @@ -250,14 +250,13 @@ void CPointerManager::updateCursorBackend() { const auto CURSORBOX = getCursorBoxGlobal(); for (auto const& m : g_pCompositor->m_vMonitors) { - auto state = stateFor(m); - if (!m->m_bEnabled || !m->dpmsStatus) { Debug::log(TRACE, "Not updating hw cursors: disabled / dpms off display"); continue; } auto CROSSES = !m->logicalBox().intersection(CURSORBOX).empty(); + auto state = stateFor(m); if (!CROSSES) { if (state->cursorFrontBuffer) @@ -373,10 +372,8 @@ bool CPointerManager::setHWCursorBuffer(SP state, SP CPointerManager::renderHWCursorBuffer(SP state, SP texture) { - auto output = state->monitor->output; - - auto maxSize = output->cursorPlaneSize(); - auto cursorSize = currentCursorImage.size; + auto maxSize = state->monitor->output->cursorPlaneSize(); + auto const& cursorSize = currentCursorImage.size; if (maxSize == Vector2D{}) return nullptr; @@ -423,8 +420,6 @@ SP CPointerManager::renderHWCursorBuffer(SPmakeEGLCurrent(); g_pHyprOpenGL->m_RenderData.pMonitor = state->monitor; @@ -483,7 +478,7 @@ SP CPointerManager::renderHWCursorBuffer(SPbind(); - g_pHyprOpenGL->beginSimple(state->monitor.lock(), damage, RBO); + g_pHyprOpenGL->beginSimple(state->monitor.lock(), {0, 0, INT16_MAX, INT16_MAX}, RBO); g_pHyprOpenGL->clear(CColor{0.F, 0.F, 0.F, 0.F}); CBox xbox = {{}, Vector2D{currentCursorImage.size / currentCursorImage.scale * state->monitor->scale}.round()}; diff --git a/src/managers/eventLoop/EventLoopManager.cpp b/src/managers/eventLoop/EventLoopManager.cpp index 081268c3..755ecbbc 100644 --- a/src/managers/eventLoop/EventLoopManager.cpp +++ b/src/managers/eventLoop/EventLoopManager.cpp @@ -98,7 +98,7 @@ void CEventLoopManager::nudgeTimers() { long nextTimerUs = 10 * 1000 * 1000; // 10s for (auto const& t : m_sTimers.timers) { - if (const auto µs = t->leftUs(); µs < nextTimerUs) + if (auto const& µs = t->leftUs(); µs < nextTimerUs) nextTimerUs = µs; } diff --git a/src/managers/input/InputManager.cpp b/src/managers/input/InputManager.cpp index 028286bf..af725927 100644 --- a/src/managers/input/InputManager.cpp +++ b/src/managers/input/InputManager.cpp @@ -291,7 +291,8 @@ void CInputManager::mouseMoveUnified(uint32_t time, bool refocus) { foundSurface = g_pCompositor->vectorToLayerSurface(mouseCoords, &PMONITOR->m_aLayerSurfaceLayers[ZWLR_LAYER_SHELL_V1_LAYER_TOP], &surfaceCoords, &pFoundLayerSurface); // then, we check if the workspace doesnt have a fullscreen window - const auto PWORKSPACE = PMONITOR->activeWorkspace; + const auto PWORKSPACE = PMONITOR->activeWorkspace; + const auto PWINDOWIDEAL = g_pCompositor->vectorToWindowUnified(mouseCoords, RESERVED_EXTENTS | INPUT_EXTENTS | ALLOW_FLOATING); if (PWORKSPACE->m_bHasFullscreenWindow && !foundSurface && PWORKSPACE->m_efFullscreenMode == FSMODE_FULLSCREEN) { pFoundWindow = g_pCompositor->getFullscreenWindowOnWorkspace(PWORKSPACE->m_iID); @@ -301,8 +302,6 @@ void CInputManager::mouseMoveUnified(uint32_t time, bool refocus) { return; } - const auto PWINDOWIDEAL = g_pCompositor->vectorToWindowUnified(mouseCoords, RESERVED_EXTENTS | INPUT_EXTENTS | ALLOW_FLOATING); - if (PWINDOWIDEAL && ((PWINDOWIDEAL->m_bIsFloating && PWINDOWIDEAL->m_bCreatedOverFullscreen) /* floating over fullscreen */ || (PMONITOR->activeSpecialWorkspace == PWINDOWIDEAL->m_pWorkspace) /* on an open special workspace */)) @@ -322,7 +321,8 @@ void CInputManager::mouseMoveUnified(uint32_t time, bool refocus) { if (PWORKSPACE->m_bHasFullscreenWindow && PWORKSPACE->m_efFullscreenMode == FSMODE_MAXIMIZED) { if (!foundSurface) { if (PMONITOR->activeSpecialWorkspace) { - pFoundWindow = g_pCompositor->vectorToWindowUnified(mouseCoords, RESERVED_EXTENTS | INPUT_EXTENTS | ALLOW_FLOATING); + if (pFoundWindow != PWINDOWIDEAL) + pFoundWindow = g_pCompositor->vectorToWindowUnified(mouseCoords, RESERVED_EXTENTS | INPUT_EXTENTS | ALLOW_FLOATING); if (pFoundWindow && !pFoundWindow->onSpecialWorkspace()) { pFoundWindow = g_pCompositor->getFullscreenWindowOnWorkspace(PWORKSPACE->m_iID); @@ -335,7 +335,8 @@ void CInputManager::mouseMoveUnified(uint32_t time, bool refocus) { } if (!foundSurface) { - pFoundWindow = g_pCompositor->vectorToWindowUnified(mouseCoords, RESERVED_EXTENTS | INPUT_EXTENTS | ALLOW_FLOATING); + if (pFoundWindow != PWINDOWIDEAL) + pFoundWindow = g_pCompositor->vectorToWindowUnified(mouseCoords, RESERVED_EXTENTS | INPUT_EXTENTS | ALLOW_FLOATING); if (!(pFoundWindow && pFoundWindow->m_bIsFloating && pFoundWindow->m_bCreatedOverFullscreen)) pFoundWindow = g_pCompositor->getFullscreenWindowOnWorkspace(PWORKSPACE->m_iID); @@ -344,7 +345,8 @@ void CInputManager::mouseMoveUnified(uint32_t time, bool refocus) { } } else { - pFoundWindow = g_pCompositor->vectorToWindowUnified(mouseCoords, RESERVED_EXTENTS | INPUT_EXTENTS | ALLOW_FLOATING); + if (pFoundWindow != PWINDOWIDEAL) + pFoundWindow = g_pCompositor->vectorToWindowUnified(mouseCoords, RESERVED_EXTENTS | INPUT_EXTENTS | ALLOW_FLOATING); } if (pFoundWindow) { diff --git a/src/protocols/core/Compositor.cpp b/src/protocols/core/Compositor.cpp index d78d3d8b..57f61f87 100644 --- a/src/protocols/core/Compositor.cpp +++ b/src/protocols/core/Compositor.cpp @@ -423,10 +423,8 @@ void CWLSurfaceResource::unlockPendingState() { } void CWLSurfaceResource::commitPendingState() { - auto previousBuffer = current.buffer; - CRegion previousBufferDamage = accumulateCurrentBufferDamage(); - - current = pending; + auto const previousBuffer = current.buffer; + current = pending; pending.damage.clear(); pending.bufferDamage.clear(); pending.newBuffer = false; diff --git a/src/render/Renderer.cpp b/src/render/Renderer.cpp index 1c38eb4e..1dedcc7d 100644 --- a/src/render/Renderer.cpp +++ b/src/render/Renderer.cpp @@ -158,9 +158,7 @@ static void renderSurface(SP surface, int x, int y, void* da if (!surface->current.texture) return; - const auto& TEXTURE = surface->current.texture; - const auto RDATA = (SRenderData*)data; - const auto INTERACTIVERESIZEINPROGRESS = RDATA->pWindow && g_pInputManager->currentlyDraggedWindow && g_pInputManager->dragMode == MBIND_RESIZE; + const auto& TEXTURE = surface->current.texture; // this is bad, probably has been logged elsewhere. Means the texture failed // uploading to the GPU. @@ -175,6 +173,8 @@ static void renderSurface(SP surface, int x, int y, void* da } } + const auto RDATA = (SRenderData*)data; + const auto INTERACTIVERESIZEINPROGRESS = RDATA->pWindow && g_pInputManager->currentlyDraggedWindow && g_pInputManager->dragMode == MBIND_RESIZE; TRACY_GPU_ZONE("RenderSurface"); double outputX = -RDATA->pMonitor->vecPosition.x, outputY = -RDATA->pMonitor->vecPosition.y; @@ -484,36 +484,43 @@ void CHyprRenderer::renderWorkspaceWindows(PHLMONITOR pMonitor, PHLWORKSPACE pWo EMIT_HOOK_EVENT("render", RENDER_PRE_WINDOWS); - // Non-floating main + std::vector windows; + windows.reserve(g_pCompositor->m_vWindows.size()); + for (auto const& w : g_pCompositor->m_vWindows) { if (w->isHidden() || (!w->m_bIsMapped && !w->m_bFadingOut)) continue; - if (w->m_bIsFloating) - continue; // floating are in the second pass - if (!shouldRenderWindow(w, pMonitor)) continue; + windows.push_back(w); + } + + // Non-floating main + for (auto& w : windows) { + if (w->m_bIsFloating) + continue; // floating are in the second pass + if (pWorkspace->m_bIsSpecialWorkspace != w->onSpecialWorkspace()) continue; // render active window after all others of this pass if (w == g_pCompositor->m_pLastWindow) { - lastWindow = w; + lastWindow = w.lock(); continue; } // render the bad boy - renderWindow(w, pMonitor, time, true, RENDER_PASS_MAIN); + renderWindow(w.lock(), pMonitor, time, true, RENDER_PASS_MAIN); } if (lastWindow) renderWindow(lastWindow, pMonitor, time, true, RENDER_PASS_MAIN); // Non-floating popup - for (auto const& w : g_pCompositor->m_vWindows) { - if (w->isHidden() || (!w->m_bIsMapped && !w->m_bFadingOut)) + for (auto& w : windows) { + if (!w) continue; if (w->m_bIsFloating) @@ -522,24 +529,19 @@ void CHyprRenderer::renderWorkspaceWindows(PHLMONITOR pMonitor, PHLWORKSPACE pWo if (pWorkspace->m_bIsSpecialWorkspace != w->onSpecialWorkspace()) continue; - if (!shouldRenderWindow(w, pMonitor)) - continue; - // render the bad boy - renderWindow(w, pMonitor, time, true, RENDER_PASS_POPUP); + renderWindow(w.lock(), pMonitor, time, true, RENDER_PASS_POPUP); + w.reset(); } // floating on top - for (auto const& w : g_pCompositor->m_vWindows) { - if (w->isHidden() || (!w->m_bIsMapped && !w->m_bFadingOut)) + for (auto& w : windows) { + if (!w) continue; if (!w->m_bIsFloating || w->m_bPinned) continue; - if (!shouldRenderWindow(w, pMonitor)) - continue; - if (pWorkspace->m_bIsSpecialWorkspace != w->onSpecialWorkspace()) continue; @@ -547,7 +549,7 @@ void CHyprRenderer::renderWorkspaceWindows(PHLMONITOR pMonitor, PHLWORKSPACE pWo continue; // special on another are rendered as a part of the base pass // render the bad boy - renderWindow(w, pMonitor, time, true, RENDER_PASS_ALL); + renderWindow(w.lock(), pMonitor, time, true, RENDER_PASS_ALL); } } @@ -1093,8 +1095,8 @@ void CHyprRenderer::calculateUVForSurface(PHLWINDOW pWindow, SPcurrent.viewport.hasSource) { // we stretch it to dest. if no dest, to 1,1 - Vector2D bufferSize = pSurface->current.bufferSize; - auto bufferSource = pSurface->current.viewport.source; + Vector2D const& bufferSize = pSurface->current.bufferSize; + auto const& bufferSource = pSurface->current.viewport.source; // calculate UV for the basic src_box. Assume dest == size. Scale to dest later uvTL = Vector2D(bufferSource.x / bufferSize.x, bufferSource.y / bufferSize.y); @@ -1904,10 +1906,11 @@ void CHyprRenderer::damageBox(CBox* pBox, bool skipFrameSchedule) { if (m->isMirror()) continue; // don't damage mirrors traditionally - CBox damageBox = {pBox->x - m->vecPosition.x, pBox->y - m->vecPosition.y, pBox->width, pBox->height}; - damageBox.scale(m->scale); - if (!skipFrameSchedule) + if (!skipFrameSchedule) { + CBox damageBox = {pBox->x - m->vecPosition.x, pBox->y - m->vecPosition.y, pBox->width, pBox->height}; + damageBox.scale(m->scale); m->addDamage(&damageBox); + } } static auto PLOGDAMAGE = CConfigValue("debug:log_damage"); diff --git a/src/render/decorations/CHyprBorderDecoration.cpp b/src/render/decorations/CHyprBorderDecoration.cpp index 68325a9c..d62e67c4 100644 --- a/src/render/decorations/CHyprBorderDecoration.cpp +++ b/src/render/decorations/CHyprBorderDecoration.cpp @@ -46,7 +46,7 @@ CBox CHyprBorderDecoration::assignedBoxGlobal() { return box.translate(WORKSPACEOFFSET); } -void CHyprBorderDecoration::draw(PHLMONITOR pMonitor, float a) { +void CHyprBorderDecoration::draw(PHLMONITOR pMonitor, float const& a) { if (doesntWantBorders()) return; diff --git a/src/render/decorations/CHyprBorderDecoration.hpp b/src/render/decorations/CHyprBorderDecoration.hpp index 5d248a81..bc9d7836 100644 --- a/src/render/decorations/CHyprBorderDecoration.hpp +++ b/src/render/decorations/CHyprBorderDecoration.hpp @@ -11,7 +11,7 @@ class CHyprBorderDecoration : public IHyprWindowDecoration { virtual void onPositioningReply(const SDecorationPositioningReply& reply); - virtual void draw(PHLMONITOR, float a); + virtual void draw(PHLMONITOR, float const& a); virtual eDecorationType getDecorationType(); diff --git a/src/render/decorations/CHyprDropShadowDecoration.cpp b/src/render/decorations/CHyprDropShadowDecoration.cpp index a4388a67..79d5940b 100644 --- a/src/render/decorations/CHyprDropShadowDecoration.cpp +++ b/src/render/decorations/CHyprDropShadowDecoration.cpp @@ -86,7 +86,7 @@ void CHyprDropShadowDecoration::updateWindow(PHLWINDOW pWindow) { m_bLastWindowBoxWithDecos = g_pDecorationPositioner->getBoxWithIncludedDecos(pWindow); } -void CHyprDropShadowDecoration::draw(PHLMONITOR pMonitor, float a) { +void CHyprDropShadowDecoration::draw(PHLMONITOR pMonitor, float const& a) { const auto PWINDOW = m_pWindow.lock(); diff --git a/src/render/decorations/CHyprDropShadowDecoration.hpp b/src/render/decorations/CHyprDropShadowDecoration.hpp index fce9a7c7..8335cde9 100644 --- a/src/render/decorations/CHyprDropShadowDecoration.hpp +++ b/src/render/decorations/CHyprDropShadowDecoration.hpp @@ -11,7 +11,7 @@ class CHyprDropShadowDecoration : public IHyprWindowDecoration { virtual void onPositioningReply(const SDecorationPositioningReply& reply); - virtual void draw(PHLMONITOR, float a); + virtual void draw(PHLMONITOR, float const& a); virtual eDecorationType getDecorationType(); diff --git a/src/render/decorations/CHyprGroupBarDecoration.cpp b/src/render/decorations/CHyprGroupBarDecoration.cpp index c9f812d7..ec9f876b 100644 --- a/src/render/decorations/CHyprGroupBarDecoration.cpp +++ b/src/render/decorations/CHyprGroupBarDecoration.cpp @@ -94,7 +94,7 @@ void CHyprGroupBarDecoration::damageEntire() { g_pHyprRenderer->damageBox(&box); } -void CHyprGroupBarDecoration::draw(PHLMONITOR pMonitor, float a) { +void CHyprGroupBarDecoration::draw(PHLMONITOR pMonitor, float const& a) { // get how many bars we will draw int barsToDraw = m_dwGroupMembers.size(); diff --git a/src/render/decorations/CHyprGroupBarDecoration.hpp b/src/render/decorations/CHyprGroupBarDecoration.hpp index e388fa38..338a8449 100644 --- a/src/render/decorations/CHyprGroupBarDecoration.hpp +++ b/src/render/decorations/CHyprGroupBarDecoration.hpp @@ -31,7 +31,7 @@ class CHyprGroupBarDecoration : public IHyprWindowDecoration { virtual void onPositioningReply(const SDecorationPositioningReply& reply); - virtual void draw(PHLMONITOR, float a); + virtual void draw(PHLMONITOR, float const& a); virtual eDecorationType getDecorationType(); diff --git a/src/render/decorations/IHyprWindowDecoration.hpp b/src/render/decorations/IHyprWindowDecoration.hpp index 99698a56..d6d57902 100644 --- a/src/render/decorations/IHyprWindowDecoration.hpp +++ b/src/render/decorations/IHyprWindowDecoration.hpp @@ -39,7 +39,7 @@ class IHyprWindowDecoration { virtual void onPositioningReply(const SDecorationPositioningReply& reply) = 0; - virtual void draw(PHLMONITOR, float a) = 0; + virtual void draw(PHLMONITOR, float const& a) = 0; virtual eDecorationType getDecorationType() = 0; From 93b4478e70af6ffb08a4a66a6d0364c3296db296 Mon Sep 17 00:00:00 2001 From: Mike Will Date: Thu, 31 Oct 2024 07:21:08 -0400 Subject: [PATCH 0578/2181] snap: add option `border_overlap` and other improvements (#8289) * snap: add option `border_overlap` and other improvements I really liked the way borders used to overlap when snapping and how only the window's main surface would snap to the monitor, so I would like to bring that behavior back, but in the form of a config option. Other improvements include: - reduced the number of snap functions from 4 down to 2, and only one ever gets called at any given time. - border size should not be added to gap size. It seemed like the right thing to do at the time, but it makes snapping feel way stronger than it actually should. - all const variables have been given the all-caps naming convention. - to avoid excessive casting, border size is declared as a double. - to avoid excessive x + w, y + h calculations. I'm using a struct called Range and working only with start and end values until the very end of the function. - check for both monitor snapping as well as reserved monitor space snapping in a relatively efficient way. * snap: always border-align for corners and reserved monitor space We probably don't want to treat reserved monitor space as if it were just a smaller monitor. Instead, it should be treated more like a borderless window, which means our window's border should never encroach upon it. --- src/config/ConfigDescriptions.hpp | 6 ++ src/config/ConfigManager.cpp | 1 + src/layout/IHyprLayout.cpp | 161 +++++++++++++++--------------- 3 files changed, 89 insertions(+), 79 deletions(-) diff --git a/src/config/ConfigDescriptions.hpp b/src/config/ConfigDescriptions.hpp index 0177f92b..07034e71 100644 --- a/src/config/ConfigDescriptions.hpp +++ b/src/config/ConfigDescriptions.hpp @@ -122,6 +122,12 @@ inline static const std::vector CONFIG_OPTIONS = { .type = CONFIG_OPTION_INT, .data = SConfigOptionDescription::SRangeData{10, 0, 100}, }, + SConfigOptionDescription{ + .value = "general:snap:border_overlap", + .description = "if true, windows snap such that only one border's worth of space is between them", + .type = CONFIG_OPTION_BOOL, + .data = SConfigOptionDescription::SBoolData{false}, + }, /* * decoration: diff --git a/src/config/ConfigManager.cpp b/src/config/ConfigManager.cpp index 909dfc63..f1ba8d7f 100644 --- a/src/config/ConfigManager.cpp +++ b/src/config/ConfigManager.cpp @@ -344,6 +344,7 @@ CConfigManager::CConfigManager() { m_pConfig->addConfigValue("general:snap:enabled", Hyprlang::INT{0}); m_pConfig->addConfigValue("general:snap:window_gap", Hyprlang::INT{10}); m_pConfig->addConfigValue("general:snap:monitor_gap", Hyprlang::INT{10}); + m_pConfig->addConfigValue("general:snap:border_overlap", Hyprlang::INT{0}); m_pConfig->addConfigValue("misc:disable_hyprland_logo", Hyprlang::INT{0}); m_pConfig->addConfigValue("misc:disable_splash_rendering", Hyprlang::INT{0}); diff --git a/src/layout/IHyprLayout.cpp b/src/layout/IHyprLayout.cpp index 73e7a125..980311d6 100644 --- a/src/layout/IHyprLayout.cpp +++ b/src/layout/IHyprLayout.cpp @@ -389,91 +389,93 @@ void IHyprLayout::onEndDragWindow() { g_pInputManager->m_bWasDraggingWindow = false; } -static inline bool canSnap(const double sideA, const double sideB, const double gap) { - return std::abs(sideA - sideB) < gap; +static inline bool canSnap(const double SIDEA, const double SIDEB, const double GAP) { + return std::abs(SIDEA - SIDEB) < GAP; } -static void snapMoveLeft(double& pos, double& len, const double p) { - pos = p; +static void snapMove(double& start, double& end, const double P) { + end = P + (end - start); + start = P; } -static void snapMoveRight(double& pos, double& len, const double p) { - pos = p - len; -} - -static void snapResizeLeft(double& pos, double& len, const double p) { - len += pos - p; - pos = p; -} - -static void snapResizeRight(double& pos, double& len, const double p) { - len = p - pos; +static void snapResize(double& start, double& end, const double P) { + start = P; } typedef std::function SnapFn; -static void performSnap(Vector2D& sourcePos, Vector2D& sourceSize, PHLWINDOW DRAGGINGWINDOW, const eMouseBindMode mode, const int corner, const Vector2D& beginSize) { - static auto SNAPWINDOWGAP = CConfigValue("general:snap:window_gap"); - static auto SNAPMONITORGAP = CConfigValue("general:snap:monitor_gap"); +static void performSnap(Vector2D& sourcePos, Vector2D& sourceSize, PHLWINDOW DRAGGINGWINDOW, const eMouseBindMode MODE, const int CORNER, const Vector2D& BEGINSIZE) { + static auto SNAPWINDOWGAP = CConfigValue("general:snap:window_gap"); + static auto SNAPMONITORGAP = CConfigValue("general:snap:monitor_gap"); + static auto SNAPBORDEROVERLAP = CConfigValue("general:snap:border_overlap"); - const SnapFn snapRight = (mode == MBIND_MOVE) ? snapMoveRight : snapResizeRight; - const SnapFn snapLeft = (mode == MBIND_MOVE) ? snapMoveLeft : snapResizeLeft; - const SnapFn snapDown = snapRight; - const SnapFn snapUp = snapLeft; - int snaps = 0; + const SnapFn SNAP = (MODE == MBIND_MOVE) ? snapMove : snapResize; + int snaps = 0; + const bool OVERLAP = *SNAPBORDEROVERLAP; const int DRAGGINGBORDERSIZE = DRAGGINGWINDOW->getRealBorderSize(); - CBox sourceBox = CBox{sourcePos, sourceSize}.expand(DRAGGINGBORDERSIZE); + + struct SRange { + double start = 0; + double end = 0; + }; + SRange sourceX = {sourcePos.x, sourcePos.x + sourceSize.x}; + SRange sourceY = {sourcePos.y, sourcePos.y + sourceSize.y}; if (*SNAPWINDOWGAP) { - const auto WSID = DRAGGINGWINDOW->workspaceID(); + const double GAPSIZE = *SNAPWINDOWGAP; + const auto WSID = DRAGGINGWINDOW->workspaceID(); for (auto& other : g_pCompositor->m_vWindows) { if (other == DRAGGINGWINDOW || other->workspaceID() != WSID || !other->m_bIsMapped || other->m_bFadingOut || other->isX11OverrideRedirect()) continue; - const int BORDERSIZE = other->getRealBorderSize(); - const double GAPSIZE = *SNAPWINDOWGAP + BORDERSIZE; + const int OTHERBORDERSIZE = other->getRealBorderSize(); + const double BORDERSIZE = OVERLAP ? std::max(DRAGGINGBORDERSIZE, OTHERBORDERSIZE) : (DRAGGINGBORDERSIZE + OTHERBORDERSIZE); - const CBox SURFBB = other->getWindowMainSurfaceBox().expand(BORDERSIZE); - const Vector2D end = sourceBox.pos() + sourceBox.size(); + const CBox SURF = other->getWindowMainSurfaceBox(); + const SRange SURFBX = {SURF.x - BORDERSIZE, SURF.x + SURF.w + BORDERSIZE}; + const SRange SURFBY = {SURF.y - BORDERSIZE, SURF.y + SURF.h + BORDERSIZE}; - // only snap windows if their ranges intersect in the opposite axis - if (sourceBox.y <= SURFBB.y + SURFBB.h && SURFBB.y <= end.y) { - if (corner & (CORNER_TOPLEFT | CORNER_BOTTOMLEFT) && canSnap(sourceBox.x, SURFBB.x + SURFBB.w, GAPSIZE)) { - snapLeft(sourceBox.x, sourceBox.w, SURFBB.x + SURFBB.w); + // only snap windows if their ranges overlap in the opposite axis + if (sourceY.start <= SURFBY.end && SURFBY.start <= sourceY.end) { + if (CORNER & (CORNER_TOPLEFT | CORNER_BOTTOMLEFT) && canSnap(sourceX.start, SURFBX.end, GAPSIZE)) { + SNAP(sourceX.start, sourceX.end, SURFBX.end); snaps |= SNAP_LEFT; - } else if (corner & (CORNER_TOPRIGHT | CORNER_BOTTOMRIGHT) && canSnap(end.x, SURFBB.x, GAPSIZE)) { - snapRight(sourceBox.x, sourceBox.w, SURFBB.x); + } else if (CORNER & (CORNER_TOPRIGHT | CORNER_BOTTOMRIGHT) && canSnap(sourceX.end, SURFBX.start, GAPSIZE)) { + SNAP(sourceX.end, sourceX.start, SURFBX.start); snaps |= SNAP_RIGHT; } } - if (sourceBox.x <= SURFBB.x + SURFBB.w && SURFBB.x <= end.x) { - if (corner & (CORNER_TOPLEFT | CORNER_TOPRIGHT) && canSnap(sourceBox.y, SURFBB.y + SURFBB.h, GAPSIZE)) { - snapUp(sourceBox.y, sourceBox.h, SURFBB.y + SURFBB.h); + if (sourceX.start <= SURFBX.end && SURFBX.start <= sourceX.end) { + if (CORNER & (CORNER_TOPLEFT | CORNER_TOPRIGHT) && canSnap(sourceY.start, SURFBY.end, GAPSIZE)) { + SNAP(sourceY.start, sourceY.end, SURFBY.end); snaps |= SNAP_UP; - } else if (corner & (CORNER_BOTTOMLEFT | CORNER_BOTTOMRIGHT) && canSnap(end.y, SURFBB.y, GAPSIZE)) { - snapDown(sourceBox.y, sourceBox.h, SURFBB.y); + } else if (CORNER & (CORNER_BOTTOMLEFT | CORNER_BOTTOMRIGHT) && canSnap(sourceY.end, SURFBY.start, GAPSIZE)) { + SNAP(sourceY.end, sourceY.start, SURFBY.start); snaps |= SNAP_DOWN; } } // corner snapping - if (sourceBox.x == SURFBB.x + SURFBB.w || SURFBB.x == sourceBox.x + sourceBox.w) { - if (corner & (CORNER_TOPLEFT | CORNER_TOPRIGHT) && canSnap(sourceBox.y, SURFBB.y, GAPSIZE)) { - snapUp(sourceBox.y, sourceBox.h, SURFBB.y); + const double BORDERDIFF = OTHERBORDERSIZE - DRAGGINGBORDERSIZE; + if (sourceX.start == SURFBX.end || SURFBX.start == sourceX.end) { + const SRange SURFY = {SURF.y - BORDERDIFF, SURF.y + SURF.h + BORDERDIFF}; + if (CORNER & (CORNER_TOPLEFT | CORNER_TOPRIGHT) && canSnap(sourceY.start, SURFY.start, GAPSIZE)) { + SNAP(sourceY.start, sourceY.end, SURFY.start); snaps |= SNAP_UP; - } else if (corner & (CORNER_BOTTOMLEFT | CORNER_BOTTOMRIGHT) && canSnap(end.y, SURFBB.y + SURFBB.h, GAPSIZE)) { - snapDown(sourceBox.y, sourceBox.h, SURFBB.y + SURFBB.h); + } else if (CORNER & (CORNER_BOTTOMLEFT | CORNER_BOTTOMRIGHT) && canSnap(sourceY.end, SURFY.end, GAPSIZE)) { + SNAP(sourceY.end, sourceY.start, SURFY.end); snaps |= SNAP_DOWN; } } - if (sourceBox.y == SURFBB.y + SURFBB.h || SURFBB.y == sourceBox.y + sourceBox.h) { - if (corner & (CORNER_TOPLEFT | CORNER_BOTTOMLEFT) && canSnap(sourceBox.x, SURFBB.x, GAPSIZE)) { - snapLeft(sourceBox.x, sourceBox.w, SURFBB.x); + if (sourceY.start == SURFBY.end || SURFBY.start == sourceY.end) { + const SRange SURFX = {SURF.x - BORDERDIFF, SURF.x + SURF.w + BORDERDIFF}; + if (CORNER & (CORNER_TOPLEFT | CORNER_BOTTOMLEFT) && canSnap(sourceX.start, SURFX.start, GAPSIZE)) { + SNAP(sourceX.start, sourceX.end, SURFX.start); snaps |= SNAP_LEFT; - } else if (corner & (CORNER_TOPRIGHT | CORNER_BOTTOMRIGHT) && canSnap(end.x, SURFBB.x + SURFBB.w, GAPSIZE)) { - snapRight(sourceBox.x, sourceBox.w, SURFBB.x + SURFBB.w); + } else if (CORNER & (CORNER_TOPRIGHT | CORNER_BOTTOMRIGHT) && canSnap(sourceX.end, SURFX.end, GAPSIZE)) { + SNAP(sourceX.end, sourceX.start, SURFX.end); snaps |= SNAP_RIGHT; } } @@ -481,49 +483,50 @@ static void performSnap(Vector2D& sourcePos, Vector2D& sourceSize, PHLWINDOW DRA } if (*SNAPMONITORGAP) { - const auto MON = DRAGGINGWINDOW->m_pMonitor.lock(); - const CBox mon = - CBox{MON->vecPosition.x + MON->vecReservedTopLeft.x, MON->vecPosition.y + MON->vecReservedTopLeft.y, - MON->vecSize.x - MON->vecReservedTopLeft.x - MON->vecReservedBottomRight.x, MON->vecSize.y - MON->vecReservedBottomRight.y - MON->vecReservedTopLeft.y}; - const double gap = *SNAPMONITORGAP; + const double GAPSIZE = *SNAPMONITORGAP; + const double BORDERSIZE = OVERLAP ? 0 : DRAGGINGBORDERSIZE; + const double BORDERDIFF = DRAGGINGBORDERSIZE - BORDERSIZE; + const auto MON = DRAGGINGWINDOW->m_pMonitor.lock(); - if (canSnap(sourceBox.x, mon.x, gap)) { - snapLeft(sourceBox.x, sourceBox.w, mon.x); + SRange monX = {MON->vecPosition.x + BORDERSIZE, MON->vecSize.x - BORDERSIZE}; + SRange monY = {MON->vecPosition.y + BORDERSIZE, MON->vecSize.y - BORDERSIZE}; + + if (canSnap(sourceX.start, monX.start, GAPSIZE) || canSnap(sourceX.start, (monX.start += MON->vecReservedTopLeft.x + BORDERDIFF), GAPSIZE)) { + SNAP(sourceX.start, sourceX.end, monX.start); snaps |= SNAP_LEFT; } - if (canSnap(sourceBox.x + sourceBox.w, mon.x + mon.w, gap)) { - snapRight(sourceBox.x, sourceBox.w, mon.w + mon.x); + if (canSnap(sourceX.end, monX.end, GAPSIZE) || canSnap(sourceX.end, (monX.end -= MON->vecReservedBottomRight.x + BORDERDIFF), GAPSIZE)) { + SNAP(sourceX.end, sourceX.start, monX.end); snaps |= SNAP_RIGHT; } - if (canSnap(sourceBox.y, mon.y, gap)) { - snapUp(sourceBox.y, sourceBox.h, mon.y); + if (canSnap(sourceY.start, monY.start, GAPSIZE) || canSnap(sourceY.start, (monY.start += MON->vecReservedTopLeft.y + BORDERDIFF), GAPSIZE)) { + SNAP(sourceY.start, sourceY.end, monY.start); snaps |= SNAP_UP; } - if (canSnap(sourceBox.y + sourceBox.h, mon.y + mon.h, gap)) { - snapDown(sourceBox.y, sourceBox.h, mon.h + mon.y); + if (canSnap(sourceY.end, monY.end, GAPSIZE) || canSnap(sourceY.end, (monY.end -= MON->vecReservedBottomRight.y + BORDERDIFF), GAPSIZE)) { + SNAP(sourceY.end, sourceY.start, monY.end); snaps |= SNAP_DOWN; } } - if (mode == MBIND_RESIZE_FORCE_RATIO) { - const double RATIO = beginSize.y / beginSize.x; - - if ((corner & (CORNER_TOPLEFT | CORNER_BOTTOMLEFT) && snaps & SNAP_LEFT) || (corner & (CORNER_TOPRIGHT | CORNER_BOTTOMRIGHT) && snaps & SNAP_RIGHT)) { - const double sizeY = sourceBox.w * RATIO; - if (corner & (CORNER_TOPLEFT | CORNER_TOPRIGHT)) - sourceBox.y += sourceBox.h - sizeY; - sourceBox.h = sizeY; - } else if ((corner & (CORNER_TOPLEFT | CORNER_TOPRIGHT) && snaps & SNAP_UP) || (corner & (CORNER_BOTTOMLEFT | CORNER_BOTTOMRIGHT) && snaps & SNAP_DOWN)) { - const double sizeX = sourceBox.h / RATIO; - if (corner & (CORNER_TOPLEFT | CORNER_BOTTOMLEFT)) - sourceBox.x += sourceBox.w - sizeX; - sourceBox.w = sizeX; + if (MODE == MBIND_RESIZE_FORCE_RATIO) { + if ((CORNER & (CORNER_TOPLEFT | CORNER_BOTTOMLEFT) && snaps & SNAP_LEFT) || (CORNER & (CORNER_TOPRIGHT | CORNER_BOTTOMRIGHT) && snaps & SNAP_RIGHT)) { + const double SIZEY = (sourceX.end - sourceX.start) * (BEGINSIZE.y / BEGINSIZE.x); + if (CORNER & (CORNER_TOPLEFT | CORNER_TOPRIGHT)) + sourceY.start = sourceY.end - SIZEY; + else + sourceY.end = sourceY.start + SIZEY; + } else if ((CORNER & (CORNER_TOPLEFT | CORNER_TOPRIGHT) && snaps & SNAP_UP) || (CORNER & (CORNER_BOTTOMLEFT | CORNER_BOTTOMRIGHT) && snaps & SNAP_DOWN)) { + const double SIZEX = (sourceY.end - sourceY.start) * (BEGINSIZE.x / BEGINSIZE.y); + if (CORNER & (CORNER_TOPLEFT | CORNER_BOTTOMLEFT)) + sourceX.start = sourceX.end - SIZEX; + else + sourceX.end = sourceX.start + SIZEX; } } - sourceBox.expand(-DRAGGINGBORDERSIZE).round(); - sourcePos = sourceBox.pos(); - sourceSize = sourceBox.size(); + sourcePos = {sourceX.start, sourceY.start}; + sourceSize = {sourceX.end - sourceX.start, sourceY.end - sourceY.start}; } void IHyprLayout::onMouseMove(const Vector2D& mousePos) { From c4d214c42d743a69f606ff476b7266b3ace7d70e Mon Sep 17 00:00:00 2001 From: Ikalco <73481042+ikalco@users.noreply.github.com> Date: Fri, 1 Nov 2024 07:30:26 -0500 Subject: [PATCH 0579/2181] monitors: fix vrr breaking monitor disconnect (#8314) --- src/config/ConfigManager.cpp | 8 +++++--- src/helpers/Monitor.cpp | 1 + 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/src/config/ConfigManager.cpp b/src/config/ConfigManager.cpp index f1ba8d7f..62c71dc7 100644 --- a/src/config/ConfigManager.cpp +++ b/src/config/ConfigManager.cpp @@ -1608,9 +1608,6 @@ void CConfigManager::ensureVRR(PHLMONITOR pMonitor) { m->vrrActive = true; return; } else if (USEVRR == 2) { - /* fullscreen */ - m->vrrActive = true; - const auto PWORKSPACE = m->activeWorkspace; if (!PWORKSPACE) @@ -1619,6 +1616,9 @@ void CConfigManager::ensureVRR(PHLMONITOR pMonitor) { const auto WORKSPACEFULL = PWORKSPACE->m_bHasFullscreenWindow && (PWORKSPACE->m_efFullscreenMode & FSMODE_FULLSCREEN); if (WORKSPACEFULL) { + /* fullscreen */ + m->vrrActive = true; + m->output->state->resetExplicitFences(); m->output->state->setAdaptiveSync(true); @@ -1631,6 +1631,8 @@ void CConfigManager::ensureVRR(PHLMONITOR pMonitor) { Debug::log(ERR, "Couldn't commit output {} in ensureVRR -> true", m->output->name); } else if (!WORKSPACEFULL) { + m->vrrActive = false; + m->output->state->resetExplicitFences(); m->output->state->setAdaptiveSync(false); diff --git a/src/helpers/Monitor.cpp b/src/helpers/Monitor.cpp index 9e71bf5f..bfab2fd3 100644 --- a/src/helpers/Monitor.cpp +++ b/src/helpers/Monitor.cpp @@ -334,6 +334,7 @@ void CMonitor::onDisconnect(bool destroy) { activeWorkspace.reset(); output->state->resetExplicitFences(); + output->state->setAdaptiveSync(false); output->state->setEnabled(false); if (!state.commit()) From 3852418d2446555509738bf1486940042107afe7 Mon Sep 17 00:00:00 2001 From: vaxerski Date: Fri, 1 Nov 2024 13:03:06 +0000 Subject: [PATCH 0580/2181] hyprctl: reload windowrules on reloadAll --- src/debug/HyprCtl.cpp | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/src/debug/HyprCtl.cpp b/src/debug/HyprCtl.cpp index 93e0f620..f5c63f86 100644 --- a/src/debug/HyprCtl.cpp +++ b/src/debug/HyprCtl.cpp @@ -1041,7 +1041,8 @@ std::string dispatchKeyword(eHyprCtlOutputFormat format, std::string in) { } // decorations will probably need a repaint - if (COMMAND.contains("decoration:") || COMMAND.contains("border") || COMMAND == "workspace" || COMMAND.contains("zoom_factor") || COMMAND == "source") { + if (COMMAND.contains("decoration:") || COMMAND.contains("border") || COMMAND == "workspace" || COMMAND.contains("zoom_factor") || COMMAND == "source" || + COMMAND.starts_with("windowrule")) { for (auto const& m : g_pCompositor->m_vMonitors) { g_pHyprRenderer->damageMonitor(m); g_pLayoutManager->getCurrentLayout()->recalculateMonitor(m->ID); @@ -1698,6 +1699,14 @@ std::string CHyprCtl::getReply(std::string request) { rd.blurFBDirty = true; } + for (auto const& w : g_pCompositor->m_vWindows) { + if (!w->m_bIsMapped || !g_pCompositor->isWorkspaceVisible(w->m_pWorkspace)) + continue; + + w->updateDynamicRules(); + g_pCompositor->updateWindowAnimatedDecorationValues(w); + } + for (auto const& m : g_pCompositor->m_vMonitors) { g_pHyprRenderer->damageMonitor(m); g_pLayoutManager->getCurrentLayout()->recalculateMonitor(m->ID); From d8b865366af9d5ed30d2ee0a437b9a3ed43c10bd Mon Sep 17 00:00:00 2001 From: Vaxry Date: Fri, 1 Nov 2024 15:52:03 +0000 Subject: [PATCH 0581/2181] renderer: Add a missing texture asset and a user check When an asset is missing, instead of a black screen, render an obnoxious, yet standard, missing texture. Additionally, warn the user assets failed to load. Shoutout to Arch for having their assets broken for months. Fix your shit. I am tired of it, and it's negatively impacting users. --- src/Compositor.cpp | 6 ++ src/render/Framebuffer.cpp | 15 +++- src/render/OpenGL.cpp | 155 +++++++++++++++++++++++++------------ src/render/OpenGL.hpp | 14 ++-- src/render/Renderer.cpp | 20 ++--- 5 files changed, 139 insertions(+), 71 deletions(-) diff --git a/src/Compositor.cpp b/src/Compositor.cpp index 65891633..62612398 100644 --- a/src/Compositor.cpp +++ b/src/Compositor.cpp @@ -2738,6 +2738,12 @@ void CCompositor::performUserChecks() { CColor{}, 15000, ICON_WARNING); } } + + if (g_pHyprOpenGL->failedAssetsNo > 0) { + g_pHyprNotificationOverlay->addNotification(std::format("Hyprland failed to load {} essential asset{}, blame your distro's packager for doing a bad job at packaging!", + g_pHyprOpenGL->failedAssetsNo, g_pHyprOpenGL->failedAssetsNo > 1 ? "s" : ""), + CColor{1.0, 0.1, 0.1, 1.0}, 15000, ICON_ERROR); + } } void CCompositor::moveWindowToWorkspaceSafe(PHLWINDOW pWindow, PHLWORKSPACE pWorkspace) { diff --git a/src/render/Framebuffer.cpp b/src/render/Framebuffer.cpp index c48ff6f3..7e086778 100644 --- a/src/render/Framebuffer.cpp +++ b/src/render/Framebuffer.cpp @@ -2,7 +2,7 @@ #include "OpenGL.hpp" CFramebuffer::CFramebuffer() { - m_cTex = makeShared(); + ; } bool CFramebuffer::alloc(int w, int h, uint32_t drmFormat) { @@ -12,6 +12,9 @@ bool CFramebuffer::alloc(int w, int h, uint32_t drmFormat) { uint32_t glFormat = FormatUtils::drmFormatToGL(drmFormat); uint32_t glType = FormatUtils::glFormatToType(glFormat); + if (!m_cTex) + m_cTex = makeShared(); + if (!m_iFbAllocated) { firstAlloc = true; glGenFramebuffers(1, &m_iFb); @@ -54,7 +57,8 @@ bool CFramebuffer::alloc(int w, int h, uint32_t drmFormat) { } glBindTexture(GL_TEXTURE_2D, 0); - glBindFramebuffer(GL_FRAMEBUFFER, g_pHyprOpenGL->m_iCurrentOutputFb); + if (g_pHyprOpenGL) + glBindFramebuffer(GL_FRAMEBUFFER, g_pHyprOpenGL->m_iCurrentOutputFb); m_vSize = Vector2D(w, h); @@ -85,14 +89,17 @@ void CFramebuffer::bind() { #else glBindFramebuffer(GL_FRAMEBUFFER, m_iFb); #endif - glViewport(0, 0, g_pHyprOpenGL->m_RenderData.pMonitor->vecPixelSize.x, g_pHyprOpenGL->m_RenderData.pMonitor->vecPixelSize.y); + if (g_pHyprOpenGL) + glViewport(0, 0, g_pHyprOpenGL->m_RenderData.pMonitor->vecPixelSize.x, g_pHyprOpenGL->m_RenderData.pMonitor->vecPixelSize.y); + else + glViewport(0, 0, m_vSize.x, m_vSize.y); } void CFramebuffer::release() { if (m_iFbAllocated) glDeleteFramebuffers(1, &m_iFb); - m_cTex->destroyTexture(); + m_cTex.reset(); m_iFbAllocated = false; m_vSize = Vector2D(); } diff --git a/src/render/OpenGL.cpp b/src/render/OpenGL.cpp index 9e524fa4..20963707 100644 --- a/src/render/OpenGL.cpp +++ b/src/render/OpenGL.cpp @@ -13,6 +13,13 @@ #include #include +const std::vector ASSET_PATHS = { +#ifdef DATAROOTDIR + DATAROOTDIR, +#endif + "/usr/share", +}; + inline void loadGLProc(void* pProc, const char* name) { void* proc = (void*)eglGetProcAddress(name); if (proc == NULL) { @@ -2595,11 +2602,32 @@ void CHyprOpenGLImpl::renderSplash(cairo_t* const CAIRO, cairo_surface_t* const cairo_surface_flush(CAIROSURFACE); } -SP CHyprOpenGLImpl::loadAsset(const std::string& file) { - const auto CAIROSURFACE = cairo_image_surface_create_from_png(file.c_str()); +SP CHyprOpenGLImpl::loadAsset(const std::string& filename) { - if (!CAIROSURFACE) - return nullptr; + std::string fullPath; + for (auto& e : ASSET_PATHS) { + std::string p = std::string{e} + "/hypr/" + filename; + std::error_code ec; + if (std::filesystem::exists(p, ec)) { + fullPath = p; + break; + } else + Debug::log(LOG, "loadAsset: looking at {} unsuccessful: ec {}", filename, ec.message()); + } + + if (fullPath.empty()) { + failedAssetsNo++; + Debug::log(ERR, "loadAsset: looking for {} failed (no provider found)", filename); + return m_pMissingAssetTexture; + } + + const auto CAIROSURFACE = cairo_image_surface_create_from_png(fullPath.c_str()); + + if (!CAIROSURFACE) { + failedAssetsNo++; + Debug::log(ERR, "loadAsset: failed to load {} (corrupt / inaccessible / not png)", fullPath); + return m_pMissingAssetTexture; + } const auto CAIROFORMAT = cairo_image_surface_get_format(CAIROSURFACE); auto tex = makeShared(); @@ -2710,51 +2738,68 @@ SP CHyprOpenGLImpl::renderText(const std::string& text, CColor col, in return tex; } -void CHyprOpenGLImpl::initAssets() { - std::string assetsPath = ""; -#ifndef DATAROOTDIR - assetsPath = "/usr/share/hypr/"; -#else - assetsPath = std::format("{}{}", DATAROOTDIR, "/hypr/"); -#endif +void CHyprOpenGLImpl::initMissingAssetTexture() { + SP tex = makeShared(); + tex->allocate(); - m_pLockDeadTexture = loadAsset(assetsPath + "lockdead.png"); - m_pLockDead2Texture = loadAsset(assetsPath + "lockdead2.png"); + const auto CAIROSURFACE = cairo_image_surface_create(CAIRO_FORMAT_ARGB32, 512, 512); + const auto CAIRO = cairo_create(CAIROSURFACE); + + cairo_set_antialias(CAIRO, CAIRO_ANTIALIAS_NONE); + cairo_save(CAIRO); + cairo_set_source_rgba(CAIRO, 0, 0, 0, 1); + cairo_set_operator(CAIRO, CAIRO_OPERATOR_SOURCE); + cairo_paint(CAIRO); + cairo_set_source_rgba(CAIRO, 1, 0, 1, 1); + cairo_rectangle(CAIRO, 256, 0, 256, 256); + cairo_fill(CAIRO); + cairo_rectangle(CAIRO, 0, 256, 256, 256); + cairo_fill(CAIRO); + cairo_restore(CAIRO); + + cairo_surface_flush(CAIROSURFACE); + + tex->m_vSize = {512, 512}; + + // copy the data to an OpenGL texture we have + const GLint glFormat = GL_RGBA; + const GLint glType = GL_UNSIGNED_BYTE; + + const auto DATA = cairo_image_surface_get_data(CAIROSURFACE); + glBindTexture(GL_TEXTURE_2D, tex->m_iTexID); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); +#ifndef GLES2 + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_R, GL_BLUE); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_B, GL_RED); +#endif + glTexImage2D(GL_TEXTURE_2D, 0, glFormat, tex->m_vSize.x, tex->m_vSize.y, 0, glFormat, glType, DATA); + + cairo_surface_destroy(CAIROSURFACE); + cairo_destroy(CAIRO); + + m_pMissingAssetTexture = tex; +} + +void CHyprOpenGLImpl::initAssets() { + initMissingAssetTexture(); + + static auto PFORCEWALLPAPER = CConfigValue("misc:force_default_wallpaper"); + + const auto FORCEWALLPAPER = std::clamp(*PFORCEWALLPAPER, static_cast(-1L), static_cast(2L)); + + m_pLockDeadTexture = loadAsset("lockdead.png"); + m_pLockDead2Texture = loadAsset("lockdead2.png"); m_pLockTtyTextTexture = renderText(std::format("Running on tty {}", g_pCompositor->m_pAqBackend->hasSession() && g_pCompositor->m_pAqBackend->session->vt > 0 ? std::to_string(g_pCompositor->m_pAqBackend->session->vt) : "unknown"), CColor{0.9F, 0.9F, 0.9F, 0.7F}, 20, true); -} -void CHyprOpenGLImpl::createBGTextureForMonitor(PHLMONITOR pMonitor) { - RASSERT(m_RenderData.pMonitor, "Tried to createBGTex without begin()!"); - - Debug::log(LOG, "Creating a texture for BGTex"); - - static auto PRENDERTEX = CConfigValue("misc:disable_hyprland_logo"); - static auto PNOSPLASH = CConfigValue("misc:disable_splash_rendering"); - static auto PFORCEWALLPAPER = CConfigValue("misc:force_default_wallpaper"); - - const auto FORCEWALLPAPER = std::clamp(*PFORCEWALLPAPER, static_cast(-1L), static_cast(2L)); - - if (*PRENDERTEX) - return; - - // release the last tex if exists - const auto PFB = &m_mMonitorBGFBs[pMonitor]; - PFB->release(); - - PFB->alloc(pMonitor->vecPixelSize.x, pMonitor->vecPixelSize.y, pMonitor->output->state->state().drmFormat); - - if (!m_pBackgroundTexture) { - std::string texPath = ""; -#ifndef DATAROOTDIR - texPath = "/usr/share/hypr/wall"; -#else - texPath = std::format("{}{}", DATAROOTDIR, "/hypr/wall"); -#endif + // create the default background texture + { + std::string texPath = std::format("{}", "wall"); // get the adequate tex if (FORCEWALLPAPER == -1) { @@ -2767,15 +2812,29 @@ void CHyprOpenGLImpl::createBGTextureForMonitor(PHLMONITOR pMonitor) { texPath += ".png"; - // check if wallpapers exist - std::error_code err; - if (!std::filesystem::exists(texPath, err)) { - Debug::log(ERR, "createBGTextureForMonitor: failed, file \"{}\" doesn't exist or access denied, ec: {}", texPath, err.message()); - return; // the texture will be empty, oh well. We'll clear with a solid color anyways. - } - m_pBackgroundTexture = loadAsset(texPath); } +} + +void CHyprOpenGLImpl::createBGTextureForMonitor(PHLMONITOR pMonitor) { + RASSERT(m_RenderData.pMonitor, "Tried to createBGTex without begin()!"); + + Debug::log(LOG, "Creating a texture for BGTex"); + + static auto PRENDERTEX = CConfigValue("misc:disable_hyprland_logo"); + static auto PNOSPLASH = CConfigValue("misc:disable_splash_rendering"); + + if (*PRENDERTEX) + return; + + // release the last tex if exists + const auto PFB = &m_mMonitorBGFBs[pMonitor]; + PFB->release(); + + PFB->alloc(pMonitor->vecPixelSize.x, pMonitor->vecPixelSize.y, pMonitor->output->state->state().drmFormat); + + if (!m_pBackgroundTexture) // ?!?!?! + return; // create a new one with cairo SP tex = makeShared(); diff --git a/src/render/OpenGL.hpp b/src/render/OpenGL.hpp index 115dcac7..c594a7cc 100644 --- a/src/render/OpenGL.hpp +++ b/src/render/OpenGL.hpp @@ -215,11 +215,12 @@ class CHyprOpenGLImpl { GLint m_iCurrentOutputFb = 0; - int m_iGBMFD = -1; - gbm_device* m_pGbmDevice = nullptr; - EGLContext m_pEglContext = nullptr; - EGLDisplay m_pEglDisplay = nullptr; - EGLDeviceEXT m_pEglDevice = nullptr; + int m_iGBMFD = -1; + gbm_device* m_pGbmDevice = nullptr; + EGLContext m_pEglContext = nullptr; + EGLDisplay m_pEglDisplay = nullptr; + EGLDeviceEXT m_pEglDevice = nullptr; + uint failedAssetsNo = 0; bool m_bReloadScreenShader = true; // at launch it can be set @@ -277,7 +278,7 @@ class CHyprOpenGLImpl { CShader m_sFinalScreenShader; CTimer m_tGlobalTimer; - SP m_pBackgroundTexture, m_pLockDeadTexture, m_pLockDead2Texture, m_pLockTtyTextTexture; + SP m_pMissingAssetTexture, m_pBackgroundTexture, m_pLockDeadTexture, m_pLockDead2Texture, m_pLockTtyTextTexture; void logShaderError(const GLuint&, bool program = false); GLuint createProgram(const std::string&, const std::string&, bool dynamic = false); @@ -290,6 +291,7 @@ class CHyprOpenGLImpl { SP loadAsset(const std::string& file); SP renderText(const std::string& text, CColor col, int pt, bool italic = false); void initAssets(); + void initMissingAssetTexture(); // std::optional> getModsForFormat(EGLint format); diff --git a/src/render/Renderer.cpp b/src/render/Renderer.cpp index 1dedcc7d..a133899b 100644 --- a/src/render/Renderer.cpp +++ b/src/render/Renderer.cpp @@ -1063,22 +1063,16 @@ void CHyprRenderer::renderSessionLockMissing(PHLMONITOR pMonitor) { if (ANY_PRESENT) { // render image2, without instructions. Lock still "alive", unless texture dead - if (g_pHyprOpenGL->m_pLockDead2Texture) - g_pHyprOpenGL->renderTexture(g_pHyprOpenGL->m_pLockDead2Texture, &monbox, ALPHA); - else - g_pHyprOpenGL->renderRect(&monbox, CColor(1.0, 0.2, 0.2, ALPHA)); + g_pHyprOpenGL->renderTexture(g_pHyprOpenGL->m_pLockDead2Texture, &monbox, ALPHA); } else { // render image, with instructions. Lock is gone. - if (g_pHyprOpenGL->m_pLockDeadTexture) { - g_pHyprOpenGL->renderTexture(g_pHyprOpenGL->m_pLockDeadTexture, &monbox, ALPHA); + g_pHyprOpenGL->renderTexture(g_pHyprOpenGL->m_pLockDeadTexture, &monbox, ALPHA); - // also render text for the tty number - if (g_pHyprOpenGL->m_pLockTtyTextTexture) { - CBox texbox = {{}, g_pHyprOpenGL->m_pLockTtyTextTexture->m_vSize}; - g_pHyprOpenGL->renderTexture(g_pHyprOpenGL->m_pLockTtyTextTexture, &texbox, 1.F); - } - } else - g_pHyprOpenGL->renderRect(&monbox, CColor(1.0, 0.2, 0.2, ALPHA)); + // also render text for the tty number + if (g_pHyprOpenGL->m_pLockTtyTextTexture) { + CBox texbox = {{}, g_pHyprOpenGL->m_pLockTtyTextTexture->m_vSize}; + g_pHyprOpenGL->renderTexture(g_pHyprOpenGL->m_pLockTtyTextTexture, &texbox, 1.F); + } } if (ALPHA < 1.f) /* animate */ From 3c0605c68e50416819fea471a8fbef05e4a18684 Mon Sep 17 00:00:00 2001 From: izmyname <135810812+izmyname@users.noreply.github.com> Date: Fri, 1 Nov 2024 22:21:36 +0500 Subject: [PATCH 0582/2181] hyprland-systemd.desktop improvements (#8318) --- systemd/hyprland-systemd.desktop | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/systemd/hyprland-systemd.desktop b/systemd/hyprland-systemd.desktop index b36a87b2..8c065a81 100644 --- a/systemd/hyprland-systemd.desktop +++ b/systemd/hyprland-systemd.desktop @@ -1,5 +1,7 @@ [Desktop Entry] -Name=Hyprland +Name=Hyprland (systemd session) Comment=An intelligent dynamic tiling Wayland compositor Exec=systemctl --user start --wait hyprland-session Type=Application +DesktopNames=Hyprland (systemd session) +Keywords=tiling;wayland;compositor; From 29e7dc642831801d14480cf7e4bb19f6ffb118e9 Mon Sep 17 00:00:00 2001 From: Pavel Solovev Date: Fri, 1 Nov 2024 13:54:17 +0000 Subject: [PATCH 0583/2181] Systemd fixes Fix installation path, install the service only if the systemd option is enabled --- meson.build | 3 ++- systemd/meson.build | 4 +++- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/meson.build b/meson.build index d0ba9a5c..76765645 100644 --- a/meson.build +++ b/meson.build @@ -53,7 +53,9 @@ epoll_dep = dependency('epoll-shim', required: false) # timerfd on BSDs # Handle options if get_option('systemd').enabled() + systemd = dependency('systemd') add_project_arguments('-DUSES_SYSTEMD', language: 'cpp') + subdir('systemd') endif if get_option('legacy_renderer').enabled() @@ -89,7 +91,6 @@ subdir('hyprpm/src') subdir('assets') subdir('example') subdir('docs') -subdir('systemd') # Generate hyprland.pc pkg_install_dir = join_paths(get_option('datadir'), 'pkgconfig') diff --git a/systemd/meson.build b/systemd/meson.build index 497e64f4..2cd5312a 100644 --- a/systemd/meson.build +++ b/systemd/meson.build @@ -7,9 +7,11 @@ install_data( conf_data = configuration_data() conf_data.set('PREFIX', get_option('prefix')) conf_data.set('BINDIR', get_option('bindir')) +user_unit_dir = systemd.get_variable(pkgconfig: 'systemduserunitdir', + pkgconfig_define: ['prefix', get_option('prefix')]) configure_file( configuration: conf_data, input: 'hyprland-session.service.in', output: '@BASENAME@', - install_dir: join_paths(get_option('libdir'), 'systemd/user') ) + install_dir: user_unit_dir ) From 32b18179dd789cde948c97eb3c2ebbdd6af36bf7 Mon Sep 17 00:00:00 2001 From: Mihai Fufezan Date: Fri, 1 Nov 2024 19:31:20 +0200 Subject: [PATCH 0584/2181] CMake: systemd fixes --- CMakeLists.txt | 19 ++++++++++--------- 1 file changed, 10 insertions(+), 9 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index ec8c331e..877ba461 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -17,7 +17,6 @@ set(PREFIX ${CMAKE_INSTALL_PREFIX}) set(INCLUDEDIR ${CMAKE_INSTALL_INCLUDEDIR}) set(BINDIR ${CMAKE_INSTALL_BINDIR}) configure_file(hyprland.pc.in hyprland.pc @ONLY) -configure_file(systemd/hyprland-session.service.in systemd/hyprland-session.service @ONLY) set(CMAKE_MESSAGE_LOG_LEVEL "STATUS") @@ -223,6 +222,16 @@ if(NO_SYSTEMD) else() message(STATUS "SYSTEMD support is requested (NO_SYSTEMD not defined)...") add_compile_definitions(USES_SYSTEMD) + configure_file(systemd/hyprland-session.service.in + systemd/hyprland-session.service @ONLY) + + # session file -systemd + install(FILES ${CMAKE_SOURCE_DIR}/systemd/hyprland-systemd.desktop + DESTINATION ${CMAKE_INSTALL_DATAROOTDIR}/wayland-sessions) + + # install systemd service + install(FILES ${CMAKE_BINARY_DIR}/systemd/hyprland-session.service + DESTINATION ${CMAKE_INSTALL_LIBDIR}/systemd/user) endif() set(CPACK_PROJECT_NAME ${PROJECT_NAME}) @@ -359,11 +368,6 @@ install( install(FILES ${CMAKE_SOURCE_DIR}/example/hyprland.desktop DESTINATION ${CMAKE_INSTALL_DATAROOTDIR}/wayland-sessions) - -# session file -systemd -install(FILES ${CMAKE_SOURCE_DIR}/systemd/hyprland-systemd.desktop - DESTINATION ${CMAKE_INSTALL_DATAROOTDIR}/wayland-sessions) - # allow Hyprland to find assets add_compile_definitions(DATAROOTDIR="${CMAKE_INSTALL_FULL_DATAROOTDIR}") @@ -404,6 +408,3 @@ install( DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/hyprland FILES_MATCHING PATTERN "*.h*") - -#install systemd service -install(FILES ${CMAKE_BINARY_DIR}/systemd/hyprland-session.service DESTINATION ${CMAKE_INSTALL_LIBDIR}/systemd/user) From 40081cb330fa838ad9c0a7b87c20b2300ea7fb38 Mon Sep 17 00:00:00 2001 From: Vaxry Date: Sat, 2 Nov 2024 15:26:25 +0000 Subject: [PATCH 0585/2181] renderer: improve api around new framebuffer changes ref #8325 --- src/protocols/Screencopy.cpp | 2 +- src/protocols/ToplevelExport.cpp | 2 +- src/render/Framebuffer.cpp | 19 ++++- src/render/Framebuffer.hpp | 12 ++- src/render/OpenGL.cpp | 75 ++++++++++--------- .../decorations/CHyprDropShadowDecoration.cpp | 2 +- 6 files changed, 68 insertions(+), 44 deletions(-) diff --git a/src/protocols/Screencopy.cpp b/src/protocols/Screencopy.cpp index 780c081d..1fcaff05 100644 --- a/src/protocols/Screencopy.cpp +++ b/src/protocols/Screencopy.cpp @@ -253,7 +253,7 @@ bool CScreencopyFrame::copyShm() { g_pHyprOpenGL->setMonitorTransformEnabled(false); #ifndef GLES2 - glBindFramebuffer(GL_READ_FRAMEBUFFER, fb.m_iFb); + glBindFramebuffer(GL_READ_FRAMEBUFFER, fb.getFBID()); #else glBindFramebuffer(GL_FRAMEBUFFER, fb.m_iFb); #endif diff --git a/src/protocols/ToplevelExport.cpp b/src/protocols/ToplevelExport.cpp index f2af89db..04c089d7 100644 --- a/src/protocols/ToplevelExport.cpp +++ b/src/protocols/ToplevelExport.cpp @@ -279,7 +279,7 @@ bool CToplevelExportFrame::copyShm(timespec* now) { outFB.bind(); #ifndef GLES2 - glBindFramebuffer(GL_READ_FRAMEBUFFER, outFB.m_iFb); + glBindFramebuffer(GL_READ_FRAMEBUFFER, outFB.getFBID()); #endif glPixelStorei(GL_PACK_ALIGNMENT, 1); diff --git a/src/render/Framebuffer.cpp b/src/render/Framebuffer.cpp index 7e086778..814a3339 100644 --- a/src/render/Framebuffer.cpp +++ b/src/render/Framebuffer.cpp @@ -65,9 +65,10 @@ bool CFramebuffer::alloc(int w, int h, uint32_t drmFormat) { return true; } -void CFramebuffer::addStencil() { +void CFramebuffer::addStencil(SP tex) { // TODO: Allow this with gles2 #ifndef GLES2 + m_pStencilTex = tex; glBindTexture(GL_TEXTURE_2D, m_pStencilTex->m_iTexID); glTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH24_STENCIL8, m_vSize.x, m_vSize.y, 0, GL_DEPTH_STENCIL, GL_UNSIGNED_INT_24_8, 0); @@ -109,5 +110,17 @@ CFramebuffer::~CFramebuffer() { } bool CFramebuffer::isAllocated() { - return m_iFbAllocated; -} \ No newline at end of file + return m_iFbAllocated && m_cTex; +} + +SP CFramebuffer::getTexture() { + return m_cTex; +} + +GLuint CFramebuffer::getFBID() { + return m_iFbAllocated ? m_iFb : 0; +} + +SP CFramebuffer::getStencilTex() { + return m_pStencilTex; +} diff --git a/src/render/Framebuffer.hpp b/src/render/Framebuffer.hpp index ca7f9e8a..84dfeef1 100644 --- a/src/render/Framebuffer.hpp +++ b/src/render/Framebuffer.hpp @@ -9,17 +9,23 @@ class CFramebuffer { ~CFramebuffer(); bool alloc(int w, int h, uint32_t format = GL_RGBA); - void addStencil(); + void addStencil(SP tex); void bind(); void release(); void reset(); bool isAllocated(); + SP getTexture(); + SP getStencilTex(); + GLuint getFBID(); Vector2D m_vSize; + private: SP m_cTex; - GLuint m_iFb; - bool m_iFbAllocated{false}; + GLuint m_iFb = -1; + bool m_iFbAllocated = false; SP m_pStencilTex; + + friend class CRenderbuffer; }; \ No newline at end of file diff --git a/src/render/OpenGL.cpp b/src/render/OpenGL.cpp index 20963707..415bb920 100644 --- a/src/render/OpenGL.cpp +++ b/src/render/OpenGL.cpp @@ -830,15 +830,15 @@ void CHyprOpenGLImpl::begin(PHLMONITOR pMonitor, const CRegion& damage_, CFrameb if (m_RenderData.pCurrentMonData->offloadFB.m_vSize != pMonitor->vecPixelSize) { m_RenderData.pCurrentMonData->stencilTex->allocate(); - m_RenderData.pCurrentMonData->offloadFB.m_pStencilTex = m_RenderData.pCurrentMonData->stencilTex; - m_RenderData.pCurrentMonData->mirrorFB.m_pStencilTex = m_RenderData.pCurrentMonData->stencilTex; - m_RenderData.pCurrentMonData->mirrorSwapFB.m_pStencilTex = m_RenderData.pCurrentMonData->stencilTex; - m_RenderData.pCurrentMonData->offMainFB.m_pStencilTex = m_RenderData.pCurrentMonData->stencilTex; - m_RenderData.pCurrentMonData->offloadFB.alloc(pMonitor->vecPixelSize.x, pMonitor->vecPixelSize.y, pMonitor->output->state->state().drmFormat); m_RenderData.pCurrentMonData->mirrorFB.alloc(pMonitor->vecPixelSize.x, pMonitor->vecPixelSize.y, pMonitor->output->state->state().drmFormat); m_RenderData.pCurrentMonData->mirrorSwapFB.alloc(pMonitor->vecPixelSize.x, pMonitor->vecPixelSize.y, pMonitor->output->state->state().drmFormat); m_RenderData.pCurrentMonData->offMainFB.alloc(pMonitor->vecPixelSize.x, pMonitor->vecPixelSize.y, pMonitor->output->state->state().drmFormat); + + m_RenderData.pCurrentMonData->offloadFB.addStencil(m_RenderData.pCurrentMonData->stencilTex); + m_RenderData.pCurrentMonData->mirrorFB.addStencil(m_RenderData.pCurrentMonData->stencilTex); + m_RenderData.pCurrentMonData->mirrorSwapFB.addStencil(m_RenderData.pCurrentMonData->stencilTex); + m_RenderData.pCurrentMonData->offMainFB.addStencil(m_RenderData.pCurrentMonData->stencilTex); } if (m_RenderData.pCurrentMonData->monitorMirrorFB.isAllocated() && m_RenderData.pMonitor->mirrors.empty()) @@ -870,10 +870,9 @@ void CHyprOpenGLImpl::begin(PHLMONITOR pMonitor, const CRegion& damage_, CFrameb // we can render to the rbo / fbo (fake) directly const auto PFBO = fb ? fb : PRBO->getFB(); m_RenderData.currentFB = PFBO; - if (PFBO->m_pStencilTex != m_RenderData.pCurrentMonData->stencilTex) { - PFBO->m_pStencilTex = m_RenderData.pCurrentMonData->stencilTex; - PFBO->addStencil(); - } + if (PFBO->getStencilTex() != m_RenderData.pCurrentMonData->stencilTex) + PFBO->addStencil(m_RenderData.pCurrentMonData->stencilTex); + PFBO->bind(); m_bOffloadedFramebuffer = false; } @@ -924,9 +923,9 @@ void CHyprOpenGLImpl::end() { blend(false); if (m_sFinalScreenShader.program < 1 && !g_pHyprRenderer->m_bCrashingInProgress) - renderTexturePrimitive(m_RenderData.pCurrentMonData->offloadFB.m_cTex, &monbox); + renderTexturePrimitive(m_RenderData.pCurrentMonData->offloadFB.getTexture(), &monbox); else - renderTexture(m_RenderData.pCurrentMonData->offloadFB.m_cTex, &monbox, 1.f); + renderTexture(m_RenderData.pCurrentMonData->offloadFB.getTexture(), &monbox, 1.f); blend(true); @@ -1269,7 +1268,7 @@ void CHyprOpenGLImpl::renderRectWithBlur(CBox* box, const CColor& col, int round m_bEndFrame = true; // fix transformed const auto SAVEDRENDERMODIF = m_RenderData.renderModif; m_RenderData.renderModif = {}; // fix shit - renderTextureInternalWithDamage(POUTFB->m_cTex, &MONITORBOX, blurA, &damage, 0, false, false, false); + renderTextureInternalWithDamage(POUTFB->getTexture(), &MONITORBOX, blurA, &damage, 0, false, false, false); m_bEndFrame = false; m_RenderData.renderModif = SAVEDRENDERMODIF; @@ -1629,7 +1628,8 @@ void CHyprOpenGLImpl::renderTextureMatte(SP tex, CBox* pBox, CFramebuf glBindTexture(tex->m_iTarget, tex->m_iTexID); glActiveTexture(GL_TEXTURE0 + 1); - glBindTexture(matte.m_cTex->m_iTarget, matte.m_cTex->m_iTexID); + auto matteTex = matte.getTexture(); + glBindTexture(matteTex->m_iTarget, matteTex->m_iTexID); glVertexAttribPointer(shader->posAttrib, 2, GL_FLOAT, GL_FALSE, 0, fullVerts); glVertexAttribPointer(shader->texAttrib, 2, GL_FLOAT, GL_FALSE, 0, fullVerts); @@ -1696,9 +1696,11 @@ CFramebuffer* CHyprOpenGLImpl::blurMainFramebufferWithDamage(float a, CRegion* o glActiveTexture(GL_TEXTURE0); - glBindTexture(m_RenderData.currentFB->m_cTex->m_iTarget, m_RenderData.currentFB->m_cTex->m_iTexID); + auto currentTex = m_RenderData.currentFB->getTexture(); - glTexParameteri(m_RenderData.currentFB->m_cTex->m_iTarget, GL_TEXTURE_MIN_FILTER, GL_LINEAR); + glBindTexture(currentTex->m_iTarget, currentTex->m_iTexID); + + glTexParameteri(currentTex->m_iTarget, GL_TEXTURE_MIN_FILTER, GL_LINEAR); glUseProgram(m_RenderData.pCurrentMonData->m_shBLURPREPARE.program); @@ -1740,9 +1742,11 @@ CFramebuffer* CHyprOpenGLImpl::blurMainFramebufferWithDamage(float a, CRegion* o glActiveTexture(GL_TEXTURE0); - glBindTexture(currentRenderToFB->m_cTex->m_iTarget, currentRenderToFB->m_cTex->m_iTexID); + auto currentTex = currentRenderToFB->getTexture(); - glTexParameteri(currentRenderToFB->m_cTex->m_iTarget, GL_TEXTURE_MIN_FILTER, GL_LINEAR); + glBindTexture(currentTex->m_iTarget, currentTex->m_iTexID); + + glTexParameteri(currentTex->m_iTarget, GL_TEXTURE_MIN_FILTER, GL_LINEAR); glUseProgram(pShader->program); @@ -1790,7 +1794,7 @@ CFramebuffer* CHyprOpenGLImpl::blurMainFramebufferWithDamage(float a, CRegion* o // draw the things. // first draw is swap -> mirr PMIRRORFB->bind(); - glBindTexture(PMIRRORSWAPFB->m_cTex->m_iTarget, PMIRRORSWAPFB->m_cTex->m_iTexID); + glBindTexture(PMIRRORSWAPFB->getTexture()->m_iTarget, PMIRRORSWAPFB->getTexture()->m_iTexID); // damage region will be scaled, make a temp CRegion tempDamage{damage}; @@ -1818,9 +1822,11 @@ CFramebuffer* CHyprOpenGLImpl::blurMainFramebufferWithDamage(float a, CRegion* o glActiveTexture(GL_TEXTURE0); - glBindTexture(currentRenderToFB->m_cTex->m_iTarget, currentRenderToFB->m_cTex->m_iTexID); + auto currentTex = currentRenderToFB->getTexture(); - glTexParameteri(currentRenderToFB->m_cTex->m_iTarget, GL_TEXTURE_MIN_FILTER, GL_LINEAR); + glBindTexture(currentTex->m_iTarget, currentTex->m_iTexID); + + glTexParameteri(currentTex->m_iTarget, GL_TEXTURE_MIN_FILTER, GL_LINEAR); glUseProgram(m_RenderData.pCurrentMonData->m_shBLURFINISH.program); @@ -1858,7 +1864,7 @@ CFramebuffer* CHyprOpenGLImpl::blurMainFramebufferWithDamage(float a, CRegion* o } // finish - glBindTexture(PMIRRORFB->m_cTex->m_iTarget, 0); + glBindTexture(PMIRRORFB->getTexture()->m_iTarget, 0); blend(BLENDBEFORE); @@ -1972,7 +1978,7 @@ void CHyprOpenGLImpl::preBlurForCurrentMonitor() { clear(CColor(0, 0, 0, 0)); m_bEndFrame = true; // fix transformed - renderTextureInternalWithDamage(POUTFB->m_cTex, &wholeMonitor, 1, &fakeDamage, 0, false, true, false); + renderTextureInternalWithDamage(POUTFB->getTexture(), &wholeMonitor, 1, &fakeDamage, 0, false, true, false); m_bEndFrame = false; m_RenderData.currentFB->bind(); @@ -2003,7 +2009,7 @@ bool CHyprOpenGLImpl::shouldUseNewBlurOptimizations(PHLLS pLayer, PHLWINDOW pWin static auto PBLURNEWOPTIMIZE = CConfigValue("decoration:blur:new_optimizations"); static auto PBLURXRAY = CConfigValue("decoration:blur:xray"); - if (!m_RenderData.pCurrentMonData->blurFB.m_cTex->m_iTexID) + if (!m_RenderData.pCurrentMonData->blurFB.getTexture()) return false; if (pWindow && pWindow->m_sWindowData.xray.hasValue() && !pWindow->m_sWindowData.xray.valueOrDefault()) @@ -2105,7 +2111,7 @@ void CHyprOpenGLImpl::renderTextureWithBlur(SP tex, CBox* pBox, float setMonitorTransformEnabled(true); if (!USENEWOPTIMIZE) setRenderModifEnabled(false); - renderTextureInternalWithDamage(POUTFB->m_cTex, &MONITORBOX, *PBLURIGNOREOPACITY ? blurA : a * blurA, &texDamage, 0, false, false, false); + renderTextureInternalWithDamage(POUTFB->getTexture(), &MONITORBOX, *PBLURIGNOREOPACITY ? blurA : a * blurA, &texDamage, 0, false, false, false); if (!USENEWOPTIMIZE) setRenderModifEnabled(true); setMonitorTransformEnabled(false); @@ -2238,9 +2244,8 @@ void CHyprOpenGLImpl::makeRawWindowSnapshot(PHLWINDOW pWindow, CFramebuffer* pFr g_pHyprRenderer->makeEGLCurrent(); - pFramebuffer->m_pStencilTex = m_RenderData.pCurrentMonData->stencilTex; - pFramebuffer->alloc(PMONITOR->vecPixelSize.x, PMONITOR->vecPixelSize.y, PMONITOR->output->state->state().drmFormat); + pFramebuffer->addStencil(m_RenderData.pCurrentMonData->stencilTex); g_pHyprRenderer->beginRender(PMONITOR, fakeDamage, RENDER_MODE_FULL_FAKE, nullptr, pFramebuffer); @@ -2376,7 +2381,7 @@ void CHyprOpenGLImpl::renderSnapshot(PHLWINDOW pWindow) { const auto FBDATA = &m_mWindowFramebuffers.at(ref); - if (!FBDATA->m_cTex->m_iTexID) + if (!FBDATA->getTexture()) return; const auto PMONITOR = pWindow->m_pMonitor.lock(); @@ -2402,7 +2407,7 @@ void CHyprOpenGLImpl::renderSnapshot(PHLWINDOW pWindow) { m_bEndFrame = true; - renderTextureInternalWithDamage(FBDATA->m_cTex, &windowBox, pWindow->m_fAlpha.value(), &fakeDamage, 0); + renderTextureInternalWithDamage(FBDATA->getTexture(), &windowBox, pWindow->m_fAlpha.value(), &fakeDamage, 0); m_bEndFrame = false; } @@ -2415,7 +2420,7 @@ void CHyprOpenGLImpl::renderSnapshot(PHLLS pLayer) { const auto FBDATA = &m_mLayerFramebuffers.at(pLayer); - if (!FBDATA->m_cTex->m_iTexID) + if (!FBDATA->getTexture()) return; const auto PMONITOR = pLayer->monitor.lock(); @@ -2435,7 +2440,7 @@ void CHyprOpenGLImpl::renderSnapshot(PHLLS pLayer) { m_bEndFrame = true; - renderTextureInternalWithDamage(FBDATA->m_cTex, &layerBox, pLayer->alpha.value(), &fakeDamage, 0); + renderTextureInternalWithDamage(FBDATA->getTexture(), &layerBox, pLayer->alpha.value(), &fakeDamage, 0); m_bEndFrame = false; } @@ -2526,7 +2531,7 @@ void CHyprOpenGLImpl::saveBufferForMirror(CBox* box) { blend(false); - renderTexture(m_RenderData.currentFB->m_cTex, box, 1.f, 0, false, false); + renderTexture(m_RenderData.currentFB->getTexture(), box, 1.f, 0, false, false); blend(true); @@ -2548,7 +2553,7 @@ void CHyprOpenGLImpl::renderMirrored() { monbox.y = (monitor->vecTransformedSize.y - monbox.h) / 2; const auto PFB = &m_mMonitorRenderResources[mirrored].monitorMirrorFB; - if (!PFB->isAllocated() || PFB->m_cTex->m_iTexID <= 0) + if (!PFB->isAllocated() || !PFB->getTexture()) return; // replace monitor projection to undo the mirrored monitor's projection @@ -2561,7 +2566,7 @@ void CHyprOpenGLImpl::renderMirrored() { // clear stuff outside of mirrored area (e.g. when changing to mirrored) clear(CColor(0, 0, 0, 0)); - renderTexture(PFB->m_cTex, &monbox, 1.f, 0, false, false); + renderTexture(PFB->getTexture(), &monbox, 1.f, 0, false, false); // reset matrix for further drawing m_RenderData.monitorProjection = monitor->projMatrix; @@ -2926,7 +2931,7 @@ void CHyprOpenGLImpl::clearWithTex() { if (TEXIT != m_mMonitorBGFBs.end()) { CBox monbox = {0, 0, m_RenderData.pMonitor->vecTransformedSize.x, m_RenderData.pMonitor->vecTransformedSize.y}; m_bEndFrame = true; - renderTexture(TEXIT->second.m_cTex, &monbox, 1); + renderTexture(TEXIT->second.getTexture(), &monbox, 1); m_bEndFrame = false; } } @@ -2978,7 +2983,7 @@ void CHyprOpenGLImpl::bindOffMain() { void CHyprOpenGLImpl::renderOffToMain(CFramebuffer* off) { CBox monbox = {0, 0, m_RenderData.pMonitor->vecTransformedSize.x, m_RenderData.pMonitor->vecTransformedSize.y}; - renderTexturePrimitive(off->m_cTex, &monbox); + renderTexturePrimitive(off->getTexture(), &monbox); } void CHyprOpenGLImpl::bindBackOnMain() { diff --git a/src/render/decorations/CHyprDropShadowDecoration.cpp b/src/render/decorations/CHyprDropShadowDecoration.cpp index 79d5940b..f146776f 100644 --- a/src/render/decorations/CHyprDropShadowDecoration.cpp +++ b/src/render/decorations/CHyprDropShadowDecoration.cpp @@ -199,7 +199,7 @@ void CHyprDropShadowDecoration::draw(PHLMONITOR pMonitor, float const& a) { CBox monbox = {0, 0, pMonitor->vecTransformedSize.x, pMonitor->vecTransformedSize.y}; g_pHyprOpenGL->setMonitorTransformEnabled(true); g_pHyprOpenGL->setRenderModifEnabled(false); - g_pHyprOpenGL->renderTextureMatte(alphaSwapFB.m_cTex, &monbox, alphaFB); + g_pHyprOpenGL->renderTextureMatte(alphaSwapFB.getTexture(), &monbox, alphaFB); g_pHyprOpenGL->setRenderModifEnabled(true); g_pHyprOpenGL->setMonitorTransformEnabled(false); From 514e0ff509f3bf4c98515f08216ac2eeb8797517 Mon Sep 17 00:00:00 2001 From: diniamo Date: Sun, 3 Nov 2024 09:52:09 +0100 Subject: [PATCH 0586/2181] flake: update nixpkgs --- flake.lock | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/flake.lock b/flake.lock index beb56b5c..27803dc5 100644 --- a/flake.lock +++ b/flake.lock @@ -189,11 +189,11 @@ }, "nixpkgs": { "locked": { - "lastModified": 1729413321, - "narHash": "sha256-I4tuhRpZFa6Fu6dcH9Dlo5LlH17peT79vx1y1SpeKt0=", + "lastModified": 1730531603, + "narHash": "sha256-Dqg6si5CqIzm87sp57j5nTaeBbWhHFaVyG7V6L8k3lY=", "owner": "NixOS", "repo": "nixpkgs", - "rev": "1997e4aa514312c1af7e2bda7fad1644e778ff26", + "rev": "7ffd9ae656aec493492b44d0ddfb28e79a1ea25d", "type": "github" }, "original": { From 5833abbbd11dca718379863cb2fb5c2423f5d7e7 Mon Sep 17 00:00:00 2001 From: trianta <56975502+Trimutex@users.noreply.github.com> Date: Sun, 3 Nov 2024 08:59:46 -0600 Subject: [PATCH 0587/2181] xwayland: minor fixups for stability (#8323) * xwayland: add inline safe closing of fds and fix LOCK_FILE_MODE permissions * xwayland: auto recreate xwayland instance if it crashes * xwayland: delay auto-restart until later --- src/xwayland/Server.cpp | 25 +++++++++++++------------ src/xwayland/XWM.cpp | 3 +++ 2 files changed, 16 insertions(+), 12 deletions(-) diff --git a/src/xwayland/Server.cpp b/src/xwayland/Server.cpp index 5ad9ff23..f356af18 100644 --- a/src/xwayland/Server.cpp +++ b/src/xwayland/Server.cpp @@ -30,7 +30,7 @@ constexpr int SOCKET_DIR_PERMISSIONS = 0755; constexpr int SOCKET_BACKLOG = 1; constexpr int MAX_SOCKET_RETRIES = 32; -constexpr int LOCK_FILE_MODE = 044; +constexpr int LOCK_FILE_MODE = 0444; static bool setCloseOnExec(int fd, bool cloexec) { int flags = fcntl(fd, F_GETFD); @@ -58,6 +58,11 @@ void cleanUpSocket(int fd, const char* path) { unlink(path); } +inline void closeSocketSafely(int& fd) { + if (fd >= 0) + close(fd); +} + static int createSocket(struct sockaddr_un* addr, size_t path_size) { socklen_t size = offsetof(struct sockaddr_un, sun_path) + path_size + 1; int fd = socket(AF_UNIX, SOCK_STREAM, 0); @@ -252,8 +257,8 @@ CXWaylandServer::~CXWaylandServer() { if (display < 0) return; - close(xFDs[0]); - close(xFDs[1]); + closeSocketSafely(xFDs[0]); + closeSocketSafely(xFDs[1]); std::string lockPath = std::format("/tmp/.X{}-lock", display); safeRemove(lockPath); @@ -283,14 +288,10 @@ void CXWaylandServer::die() { if (pipeFd >= 0) close(pipeFd); - if (waylandFDs[0] >= 0) - close(waylandFDs[0]); - if (waylandFDs[1] >= 0) - close(waylandFDs[1]); - if (xwmFDs[0] >= 0) - close(xwmFDs[0]); - if (xwmFDs[1] >= 0) - close(xwmFDs[1]); + closeSocketSafely(waylandFDs[0]); + closeSocketSafely(waylandFDs[1]); + closeSocketSafely(xwmFDs[0]); + closeSocketSafely(xwmFDs[1]); // possible crash. Better to leak a bit. //if (xwaylandClient) @@ -407,7 +408,7 @@ bool CXWaylandServer::start() { close(notify[1]); close(waylandFDs[1]); - close(xwmFDs[1]); + closeSocketSafely(xwmFDs[1]); waylandFDs[1] = -1; xwmFDs[1] = -1; diff --git a/src/xwayland/XWM.cpp b/src/xwayland/XWM.cpp index 248813bf..87fc34e4 100644 --- a/src/xwayland/XWM.cpp +++ b/src/xwayland/XWM.cpp @@ -13,6 +13,7 @@ #include "../defines.hpp" #include "../Compositor.hpp" #include "../protocols/core/Seat.hpp" +#include "../managers/eventLoop/EventLoopManager.hpp" #include "../managers/SeatManager.hpp" #include "../protocols/XWaylandShell.hpp" #include "../protocols/core/Compositor.hpp" @@ -691,6 +692,8 @@ int CXWM::onEvent(int fd, uint32_t mask) { Debug::log(CRIT, "XWayland has yeeten the xwm off?!"); g_pXWayland->pWM.reset(); g_pXWayland->pServer.reset(); + // Attempt to create fresh instance + g_pEventLoopManager->doLater([]() { g_pXWayland = std::make_unique(true); }); return 0; } From 180c26ada6233c3c59c331cb14a64aac1eeb2941 Mon Sep 17 00:00:00 2001 From: Vaxry Date: Sun, 3 Nov 2024 15:16:08 +0000 Subject: [PATCH 0588/2181] renderer: safeguard against non-sampleable currentFB in blurMainFb fixes #8325 --- src/render/Framebuffer.cpp | 6 ++++++ src/render/OpenGL.cpp | 5 +++++ 2 files changed, 11 insertions(+) diff --git a/src/render/Framebuffer.cpp b/src/render/Framebuffer.cpp index 814a3339..bf75d414 100644 --- a/src/render/Framebuffer.cpp +++ b/src/render/Framebuffer.cpp @@ -97,12 +97,18 @@ void CFramebuffer::bind() { } void CFramebuffer::release() { + if (!m_iFbAllocated && !m_cTex) + return; + + Debug::log(TRACE, "fb {} released", m_iFb); + if (m_iFbAllocated) glDeleteFramebuffers(1, &m_iFb); m_cTex.reset(); m_iFbAllocated = false; m_vSize = Vector2D(); + m_iFb = 0; } CFramebuffer::~CFramebuffer() { diff --git a/src/render/OpenGL.cpp b/src/render/OpenGL.cpp index 415bb920..45837509 100644 --- a/src/render/OpenGL.cpp +++ b/src/render/OpenGL.cpp @@ -1656,6 +1656,11 @@ void CHyprOpenGLImpl::renderTextureMatte(SP tex, CBox* pBox, CFramebuf // Dual (or more) kawase blur CFramebuffer* CHyprOpenGLImpl::blurMainFramebufferWithDamage(float a, CRegion* originalDamage) { + if (!m_RenderData.currentFB->getTexture()) { + Debug::log(ERR, "BUG THIS: null fb texture while attempting to blur main fb?! (introspection off?!)"); + return &m_RenderData.pCurrentMonData->mirrorFB; // return something to sample from at least + } + TRACY_GPU_ZONE("RenderBlurMainFramebufferWithDamage"); const auto BLENDBEFORE = m_bBlend; From cd0d0491261728260de3d1aff150e1b6c05f9e86 Mon Sep 17 00:00:00 2001 From: Gliczy <129636582+Gliczy@users.noreply.github.com> Date: Sun, 3 Nov 2024 17:08:13 +0100 Subject: [PATCH 0589/2181] flake.lock: update xdph --- flake.lock | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/flake.lock b/flake.lock index 27803dc5..560014b6 100644 --- a/flake.lock +++ b/flake.lock @@ -293,11 +293,11 @@ ] }, "locked": { - "lastModified": 1728166987, - "narHash": "sha256-w6dVTguAn9zJ+7aPOhBQgDz8bn6YZ7b56cY8Kg5HJRI=", + "lastModified": 1730187742, + "narHash": "sha256-M0umGIIvVFqCwA0fQ5edivMTbRYA0r/5tXK8sr+M7EA=", "owner": "hyprwm", "repo": "xdg-desktop-portal-hyprland", - "rev": "fb9c8d665af0588bb087f97d0f673ddf0d501787", + "rev": "998f646762b94fbac61b0271ce66d3e617262858", "type": "github" }, "original": { From 44899cd5488831b147f385f201959625bd010898 Mon Sep 17 00:00:00 2001 From: Mihai Fufezan Date: Mon, 4 Nov 2024 19:43:23 +0200 Subject: [PATCH 0590/2181] nix/overlays: fix xdph overlay Partial fix for https://github.com/hyprwm/Hyprland/issues/8343 --- nix/overlays.nix | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/nix/overlays.nix b/nix/overlays.nix index a78f3003..b1eb66ad 100644 --- a/nix/overlays.nix +++ b/nix/overlays.nix @@ -63,7 +63,7 @@ in { # Packages for extra software recommended for usage with Hyprland, # including forked or patched packages for compatibility. hyprland-extras = lib.composeManyExtensions [ - inputs.xdph.overlays.xdg-desktop-portal-hyprland + inputs.xdph.overlays.default ]; # udis86 from nixpkgs is too old, and also does not provide a .pc file From 0fb9a04526b06adfb3fd16b64e13b7d110ae7855 Mon Sep 17 00:00:00 2001 From: Mihai Fufezan Date: Mon, 4 Nov 2024 20:01:40 +0200 Subject: [PATCH 0591/2181] flake.lock: update xdph --- flake.lock | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/flake.lock b/flake.lock index 560014b6..8cee27e3 100644 --- a/flake.lock +++ b/flake.lock @@ -293,11 +293,11 @@ ] }, "locked": { - "lastModified": 1730187742, - "narHash": "sha256-M0umGIIvVFqCwA0fQ5edivMTbRYA0r/5tXK8sr+M7EA=", + "lastModified": 1730743262, + "narHash": "sha256-iTLqj3lU8kFehPm5tXpctzkD274t/k1nwSSq3qCWXeg=", "owner": "hyprwm", "repo": "xdg-desktop-portal-hyprland", - "rev": "998f646762b94fbac61b0271ce66d3e617262858", + "rev": "09b23cef06fe248e61cec8862c04b9bcb62f4b6d", "type": "github" }, "original": { From 88e9e0394541a853600bc2c910005c05fa156269 Mon Sep 17 00:00:00 2001 From: Vaxry Date: Mon, 4 Nov 2024 19:42:47 +0000 Subject: [PATCH 0592/2181] renderer: add expand_undersized_textures adds an option to disable the texture expansion for textures that are smaller while resizing up --- src/config/ConfigManager.cpp | 1 + src/render/Renderer.cpp | 28 ++++++++++++++++------------ 2 files changed, 17 insertions(+), 12 deletions(-) diff --git a/src/config/ConfigManager.cpp b/src/config/ConfigManager.cpp index 62c71dc7..c5d53e6a 100644 --- a/src/config/ConfigManager.cpp +++ b/src/config/ConfigManager.cpp @@ -590,6 +590,7 @@ CConfigManager::CConfigManager() { m_pConfig->addConfigValue("render:explicit_sync", Hyprlang::INT{2}); m_pConfig->addConfigValue("render:explicit_sync_kms", Hyprlang::INT{2}); m_pConfig->addConfigValue("render:direct_scanout", Hyprlang::INT{0}); + m_pConfig->addConfigValue("render:expand_undersized_textures", Hyprlang::INT{1}); // devices m_pConfig->addSpecialCategory("device", {"name"}); diff --git a/src/render/Renderer.cpp b/src/render/Renderer.cpp index a133899b..6af3a99d 100644 --- a/src/render/Renderer.cpp +++ b/src/render/Renderer.cpp @@ -1084,8 +1084,10 @@ void CHyprRenderer::renderSessionLockMissing(PHLMONITOR pMonitor) { void CHyprRenderer::calculateUVForSurface(PHLWINDOW pWindow, SP pSurface, PHLMONITOR pMonitor, bool main, const Vector2D& projSize, const Vector2D& projSizeUnscaled, bool fixMisalignedFSV1) { if (!pWindow || !pWindow->m_bIsX11) { - Vector2D uvTL; - Vector2D uvBR = Vector2D(1, 1); + static auto PEXPANDEDGES = CConfigValue("render:expand_undersized_textures"); + + Vector2D uvTL; + Vector2D uvBR = Vector2D(1, 1); if (pSurface->current.viewport.hasSource) { // we stretch it to dest. if no dest, to 1,1 @@ -1115,16 +1117,18 @@ void CHyprRenderer::calculateUVForSurface(PHLWINDOW pWindow, SPscale); - const bool SCALE_UNAWARE = MONITOR_WL_SCALE != pSurface->current.scale && !pSurface->current.viewport.hasDestination; - const auto EXPECTED_SIZE = - ((pSurface->current.viewport.hasDestination ? pSurface->current.viewport.destination : pSurface->current.bufferSize / pSurface->current.scale) * pMonitor->scale) - .round(); - if (!SCALE_UNAWARE && (EXPECTED_SIZE.x < projSize.x || EXPECTED_SIZE.y < projSize.y)) { - // this will not work with shm AFAIK, idk why. - // NOTE: this math is wrong if we have a source... or geom updates later, but I don't think we can do much - const auto FIX = projSize / EXPECTED_SIZE; - uvBR = uvBR * FIX; + if (*PEXPANDEDGES) { + const auto MONITOR_WL_SCALE = std::ceil(pMonitor->scale); + const bool SCALE_UNAWARE = MONITOR_WL_SCALE != pSurface->current.scale && !pSurface->current.viewport.hasDestination; + const auto EXPECTED_SIZE = + ((pSurface->current.viewport.hasDestination ? pSurface->current.viewport.destination : pSurface->current.bufferSize / pSurface->current.scale) * pMonitor->scale) + .round(); + if (!SCALE_UNAWARE && (EXPECTED_SIZE.x < projSize.x || EXPECTED_SIZE.y < projSize.y)) { + // this will not work with shm AFAIK, idk why. + // NOTE: this math is wrong if we have a source... or geom updates later, but I don't think we can do much + const auto FIX = projSize / EXPECTED_SIZE; + uvBR = uvBR * FIX; + } } g_pHyprOpenGL->m_RenderData.primarySurfaceUVTopLeft = uvTL; From e3882b23d09aad7f5c3a708536c87b062f3b0d8d Mon Sep 17 00:00:00 2001 From: Vaxry Date: Tue, 5 Nov 2024 09:59:03 +0000 Subject: [PATCH 0593/2181] screencopy: fix build with legacyrenderer fixes #8355 --- src/protocols/Screencopy.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/protocols/Screencopy.cpp b/src/protocols/Screencopy.cpp index 1fcaff05..a7e515cb 100644 --- a/src/protocols/Screencopy.cpp +++ b/src/protocols/Screencopy.cpp @@ -255,7 +255,7 @@ bool CScreencopyFrame::copyShm() { #ifndef GLES2 glBindFramebuffer(GL_READ_FRAMEBUFFER, fb.getFBID()); #else - glBindFramebuffer(GL_FRAMEBUFFER, fb.m_iFb); + glBindFramebuffer(GL_FRAMEBUFFER, fb.getFBID()); #endif const auto PFORMAT = FormatUtils::getPixelFormatFromDRM(shm.format); From d1638a09bacd84b994de3f77746b74f427b9d41e Mon Sep 17 00:00:00 2001 From: Vaxry Date: Tue, 5 Nov 2024 15:44:40 +0000 Subject: [PATCH 0594/2181] shadow: add sharp and refactor options options moved to decoration:shadow: --- src/Compositor.cpp | 11 +++--- src/config/ConfigDescriptions.hpp | 24 ++++++++----- src/config/ConfigManager.cpp | 17 +++++----- src/managers/AnimationManager.cpp | 2 +- src/render/OpenGL.cpp | 6 ++-- .../decorations/CHyprDropShadowDecoration.cpp | 34 +++++++++++++------ .../decorations/CHyprDropShadowDecoration.hpp | 2 ++ 7 files changed, 58 insertions(+), 38 deletions(-) diff --git a/src/Compositor.cpp b/src/Compositor.cpp index 62612398..495a2d85 100644 --- a/src/Compositor.cpp +++ b/src/Compositor.cpp @@ -1893,8 +1893,8 @@ void CCompositor::updateWindowAnimatedDecorationValues(PHLWINDOW pWindow) { static auto PINACTIVEALPHA = CConfigValue("decoration:inactive_opacity"); static auto PACTIVEALPHA = CConfigValue("decoration:active_opacity"); static auto PFULLSCREENALPHA = CConfigValue("decoration:fullscreen_opacity"); - static auto PSHADOWCOL = CConfigValue("decoration:col.shadow"); - static auto PSHADOWCOLINACTIVE = CConfigValue("decoration:col.shadow_inactive"); + static auto PSHADOWCOL = CConfigValue("decoration:shadow:color"); + static auto PSHADOWCOLINACTIVE = CConfigValue("decoration:shadow:color_inactive"); static auto PDIMSTRENGTH = CConfigValue("decoration:dim_strength"); static auto PDIMENABLED = CConfigValue("decoration:dim_inactive"); @@ -1965,11 +1965,10 @@ void CCompositor::updateWindowAnimatedDecorationValues(PHLWINDOW pWindow) { // shadow if (!pWindow->isX11OverrideRedirect() && !pWindow->m_bX11DoesntWantBorders) { - if (pWindow == m_pLastWindow) { + if (pWindow == m_pLastWindow) pWindow->m_cRealShadowColor = CColor(*PSHADOWCOL); - } else { - pWindow->m_cRealShadowColor = CColor(*PSHADOWCOLINACTIVE != INT_MAX ? *PSHADOWCOLINACTIVE : *PSHADOWCOL); - } + else + pWindow->m_cRealShadowColor = CColor(*PSHADOWCOLINACTIVE != INT64_MAX ? *PSHADOWCOLINACTIVE : *PSHADOWCOL); } else { pWindow->m_cRealShadowColor.setValueAndWarp(CColor(0, 0, 0, 0)); // no shadow } diff --git a/src/config/ConfigDescriptions.hpp b/src/config/ConfigDescriptions.hpp index 07034e71..5327c599 100644 --- a/src/config/ConfigDescriptions.hpp +++ b/src/config/ConfigDescriptions.hpp @@ -158,49 +158,55 @@ inline static const std::vector CONFIG_OPTIONS = { .data = SConfigOptionDescription::SFloatData{1, 0, 1}, }, SConfigOptionDescription{ - .value = "decoration:drop_shadow", + .value = "decoration:shadow:enabled", .description = "enable drop shadows on windows", .type = CONFIG_OPTION_BOOL, .data = SConfigOptionDescription::SBoolData{true}, }, SConfigOptionDescription{ - .value = "decoration:shadow_range", + .value = "decoration:shadow:range", .description = "Shadow range (size) in layout px", .type = CONFIG_OPTION_INT, .data = SConfigOptionDescription::SRangeData{4, 0, 100}, }, SConfigOptionDescription{ - .value = "decoration:shadow_render_power", + .value = "decoration:shadow:render_power", .description = "in what power to render the falloff (more power, the faster the falloff) [1 - 4]", .type = CONFIG_OPTION_INT, .data = SConfigOptionDescription::SRangeData{3, 1, 4}, }, SConfigOptionDescription{ - .value = "decoration:shadow_ignore_window", + .value = "decoration:shadow:sharp", + .description = "whether the shadow should be sharp or not. Akin to an infinitely high render power.", + .type = CONFIG_OPTION_BOOL, + .data = SConfigOptionDescription::SBoolData{false}, + }, + SConfigOptionDescription{ + .value = "decoration:shadow:ignore_window", .description = "if true, the shadow will not be rendered behind the window itself, only around it.", .type = CONFIG_OPTION_BOOL, .data = SConfigOptionDescription::SBoolData{true}, }, SConfigOptionDescription{ - .value = "decoration:col.shadow", + .value = "decoration:shadow:color", .description = "shadow's color. Alpha dictates shadow's opacity.", .type = CONFIG_OPTION_COLOR, .data = SConfigOptionDescription::SColorData{0xee1a1a1a}, }, SConfigOptionDescription{ - .value = "decoration:col.shadow_inactive", + .value = "decoration:shadow:color_inactive", .description = "inactive shadow color. (if not set, will fall back to col.shadow)", .type = CONFIG_OPTION_COLOR, - .data = SConfigOptionDescription::SColorData{}, //##TODO UNSET? + .data = SConfigOptionDescription::SColorData{}, //TODO: UNSET? }, SConfigOptionDescription{ - .value = "decoration:shadow_offset", + .value = "decoration:shadow:offset", .description = "shadow's rendering offset.", .type = CONFIG_OPTION_VECTOR, .data = SConfigOptionDescription::SVectorData{{}, {-250, -250}, {250, 250}}, }, SConfigOptionDescription{ - .value = "decoration:shadow_scale", + .value = "decoration:shadow:scale", .description = "shadow's scale. [0.0 - 1.0]", .type = CONFIG_OPTION_FLOAT, .data = SConfigOptionDescription::SFloatData{1, 0, 1}, diff --git a/src/config/ConfigManager.cpp b/src/config/ConfigManager.cpp index c5d53e6a..eafe4cbb 100644 --- a/src/config/ConfigManager.cpp +++ b/src/config/ConfigManager.cpp @@ -431,14 +431,15 @@ CConfigManager::CConfigManager() { m_pConfig->addConfigValue("decoration:inactive_opacity", {1.F}); m_pConfig->addConfigValue("decoration:fullscreen_opacity", {1.F}); m_pConfig->addConfigValue("decoration:no_blur_on_oversized", Hyprlang::INT{0}); - m_pConfig->addConfigValue("decoration:drop_shadow", Hyprlang::INT{1}); - m_pConfig->addConfigValue("decoration:shadow_range", Hyprlang::INT{4}); - m_pConfig->addConfigValue("decoration:shadow_render_power", Hyprlang::INT{3}); - m_pConfig->addConfigValue("decoration:shadow_ignore_window", Hyprlang::INT{1}); - m_pConfig->addConfigValue("decoration:shadow_offset", Hyprlang::VEC2{0, 0}); - m_pConfig->addConfigValue("decoration:shadow_scale", {1.f}); - m_pConfig->addConfigValue("decoration:col.shadow", Hyprlang::INT{0xee1a1a1a}); - m_pConfig->addConfigValue("decoration:col.shadow_inactive", {(Hyprlang::INT)INT_MAX}); + m_pConfig->addConfigValue("decoration:shadow:enabled", Hyprlang::INT{1}); + m_pConfig->addConfigValue("decoration:shadow:range", Hyprlang::INT{4}); + m_pConfig->addConfigValue("decoration:shadow:render_power", Hyprlang::INT{3}); + m_pConfig->addConfigValue("decoration:shadow:ignore_window", Hyprlang::INT{1}); + m_pConfig->addConfigValue("decoration:shadow:offset", Hyprlang::VEC2{0, 0}); + m_pConfig->addConfigValue("decoration:shadow:scale", {1.f}); + m_pConfig->addConfigValue("decoration:shadow:sharp", Hyprlang::INT{0}); + m_pConfig->addConfigValue("decoration:shadow:color", Hyprlang::INT{0xee1a1a1a}); + m_pConfig->addConfigValue("decoration:shadow:color_inactive", {(Hyprlang::INT)INT64_MAX}); m_pConfig->addConfigValue("decoration:dim_inactive", Hyprlang::INT{0}); m_pConfig->addConfigValue("decoration:dim_strength", {0.5f}); m_pConfig->addConfigValue("decoration:dim_special", {0.2f}); diff --git a/src/managers/AnimationManager.cpp b/src/managers/AnimationManager.cpp index 0bdf5a7a..ceb594aa 100644 --- a/src/managers/AnimationManager.cpp +++ b/src/managers/AnimationManager.cpp @@ -64,7 +64,7 @@ void CAnimationManager::tick() { if (!*PANIMENABLED) animGlobalDisabled = true; - static auto* const PSHADOWSENABLED = (Hyprlang::INT* const*)g_pConfigManager->getConfigValuePtr("decoration:drop_shadow"); + static auto* const PSHADOWSENABLED = (Hyprlang::INT* const*)g_pConfigManager->getConfigValuePtr("decoration:shadow:enabled"); const auto DEFAULTBEZIER = m_mBezierCurves.find("default"); diff --git a/src/render/OpenGL.cpp b/src/render/OpenGL.cpp index 45837509..52392436 100644 --- a/src/render/OpenGL.cpp +++ b/src/render/OpenGL.cpp @@ -2465,7 +2465,7 @@ void CHyprOpenGLImpl::renderRoundedShadow(CBox* box, int round, int range, const box = &newBox; - static auto PSHADOWPOWER = CConfigValue("decoration:shadow_render_power"); + static auto PSHADOWPOWER = CConfigValue("decoration:shadow:render_power"); const auto SHADOWPOWER = std::clamp((int)*PSHADOWPOWER, 1, 4); @@ -2475,7 +2475,7 @@ void CHyprOpenGLImpl::renderRoundedShadow(CBox* box, int round, int range, const newBox, wlTransformToHyprutils(invertTransform(!m_bEndFrame ? WL_OUTPUT_TRANSFORM_NORMAL : m_RenderData.pMonitor->transform)), newBox.rot); Mat3x3 glMatrix = m_RenderData.projection.copy().multiply(matrix); - glEnable(GL_BLEND); + blend(true); glUseProgram(m_RenderData.pCurrentMonData->m_shSHADOW.program); @@ -2485,7 +2485,7 @@ void CHyprOpenGLImpl::renderRoundedShadow(CBox* box, int round, int range, const glMatrix.transpose(); glUniformMatrix3fv(m_RenderData.pCurrentMonData->m_shSHADOW.proj, 1, GL_FALSE, glMatrix.getMatrix().data()); #endif - glUniform4f(m_RenderData.pCurrentMonData->m_shSHADOW.color, col.r, col.g, col.b, col.a * a); + glUniform4f(m_RenderData.pCurrentMonData->m_shSHADOW.color, col.r * col.a * a, col.g * col.a * a, col.b * col.a * a, col.a * a); const auto TOPLEFT = Vector2D(range + round, range + round); const auto BOTTOMRIGHT = Vector2D(box->width - (range + round), box->height - (range + round)); diff --git a/src/render/decorations/CHyprDropShadowDecoration.cpp b/src/render/decorations/CHyprDropShadowDecoration.cpp index f146776f..893ad498 100644 --- a/src/render/decorations/CHyprDropShadowDecoration.cpp +++ b/src/render/decorations/CHyprDropShadowDecoration.cpp @@ -36,7 +36,7 @@ std::string CHyprDropShadowDecoration::getDisplayName() { } void CHyprDropShadowDecoration::damageEntire() { - static auto PSHADOWS = CConfigValue("decoration:drop_shadow"); + static auto PSHADOWS = CConfigValue("decoration:shadow:enabled"); if (*PSHADOWS != 1) return; // disabled @@ -52,7 +52,7 @@ void CHyprDropShadowDecoration::damageEntire() { shadowBox.translate(PWORKSPACE->m_vRenderOffset.value()); shadowBox.translate(PWINDOW->m_vFloatingOffset); - static auto PSHADOWIGNOREWINDOW = CConfigValue("decoration:shadow_ignore_window"); + static auto PSHADOWIGNOREWINDOW = CConfigValue("decoration:shadow:ignore_window"); const auto ROUNDING = PWINDOW->rounding(); const auto ROUNDINGSIZE = ROUNDING - M_SQRT1_2 * ROUNDING + 1; @@ -102,11 +102,11 @@ void CHyprDropShadowDecoration::draw(PHLMONITOR pMonitor, float const& a) { if (PWINDOW->m_sWindowData.noShadow.valueOrDefault()) return; - static auto PSHADOWS = CConfigValue("decoration:drop_shadow"); - static auto PSHADOWSIZE = CConfigValue("decoration:shadow_range"); - static auto PSHADOWIGNOREWINDOW = CConfigValue("decoration:shadow_ignore_window"); - static auto PSHADOWSCALE = CConfigValue("decoration:shadow_scale"); - static auto PSHADOWOFFSET = CConfigValue("decoration:shadow_offset"); + static auto PSHADOWS = CConfigValue("decoration:shadow:enabled"); + static auto PSHADOWSIZE = CConfigValue("decoration:shadow:range"); + static auto PSHADOWIGNOREWINDOW = CConfigValue("decoration:shadow:ignore_window"); + static auto PSHADOWSCALE = CConfigValue("decoration:shadow:scale"); + static auto PSHADOWOFFSET = CConfigValue("decoration:shadow:offset"); if (*PSHADOWS != 1) return; // disabled @@ -184,7 +184,7 @@ void CHyprDropShadowDecoration::draw(PHLMONITOR pMonitor, float const& a) { g_pHyprOpenGL->renderRect(&fullBox, CColor(0, 0, 0, 1), 0); // render white shadow with the alpha of the shadow color (otherwise we clear with alpha later and shit it to 2 bit) - g_pHyprOpenGL->renderRoundedShadow(&fullBox, ROUNDING * pMonitor->scale, *PSHADOWSIZE * pMonitor->scale, CColor(1, 1, 1, PWINDOW->m_cRealShadowColor.value().a), a); + drawShadowInternal(&fullBox, ROUNDING * pMonitor->scale, *PSHADOWSIZE * pMonitor->scale, CColor(1, 1, 1, PWINDOW->m_cRealShadowColor.value().a), a); // render black window box ("clip") g_pHyprOpenGL->renderRect(&windowBox, CColor(0, 0, 0, 1.0), (ROUNDING + 1 /* This fixes small pixel gaps. */) * pMonitor->scale); @@ -204,9 +204,8 @@ void CHyprDropShadowDecoration::draw(PHLMONITOR pMonitor, float const& a) { g_pHyprOpenGL->setMonitorTransformEnabled(false); g_pHyprOpenGL->m_RenderData.damage = saveDamage; - } else { - g_pHyprOpenGL->renderRoundedShadow(&fullBox, ROUNDING * pMonitor->scale, *PSHADOWSIZE * pMonitor->scale, PWINDOW->m_cRealShadowColor.value(), a); - } + } else + drawShadowInternal(&fullBox, ROUNDING * pMonitor->scale, *PSHADOWSIZE * pMonitor->scale, PWINDOW->m_cRealShadowColor.value(), a); if (m_seExtents != m_seReportedExtents) g_pDecorationPositioner->repositionDeco(this); @@ -215,3 +214,16 @@ void CHyprDropShadowDecoration::draw(PHLMONITOR pMonitor, float const& a) { eDecorationLayer CHyprDropShadowDecoration::getDecorationLayer() { return DECORATION_LAYER_BOTTOM; } + +void CHyprDropShadowDecoration::drawShadowInternal(CBox* box, int round, int range, CColor color, float a) { + static auto PSHADOWSHARP = CConfigValue("decoration:shadow:sharp"); + + g_pHyprOpenGL->blend(true); + + color.a *= a; + + if (*PSHADOWSHARP) + g_pHyprOpenGL->renderRect(box, color, round); + else + g_pHyprOpenGL->renderRoundedShadow(box, round, range, color, 1.F); +} diff --git a/src/render/decorations/CHyprDropShadowDecoration.hpp b/src/render/decorations/CHyprDropShadowDecoration.hpp index 8335cde9..933ee0ef 100644 --- a/src/render/decorations/CHyprDropShadowDecoration.hpp +++ b/src/render/decorations/CHyprDropShadowDecoration.hpp @@ -34,6 +34,8 @@ class CHyprDropShadowDecoration : public IHyprWindowDecoration { Vector2D m_vLastWindowPos; Vector2D m_vLastWindowSize; + void drawShadowInternal(CBox* box, int round, int range, CColor color, float a); + CBox m_bLastWindowBox = {0}; CBox m_bLastWindowBoxWithDecos = {0}; }; From 55ccb1a8cf2c8541a32890e9b76e7c20fc9227cd Mon Sep 17 00:00:00 2001 From: Vaxry Date: Tue, 5 Nov 2024 16:00:39 +0000 Subject: [PATCH 0595/2181] shaders: fixup jagged edges in texture rounded corners --- src/render/shaders/Textures.hpp | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/src/render/shaders/Textures.hpp b/src/render/shaders/Textures.hpp index 6ac33a0a..e99d0a49 100644 --- a/src/render/shaders/Textures.hpp +++ b/src/render/shaders/Textures.hpp @@ -5,24 +5,27 @@ inline static constexpr auto ROUNDED_SHADER_FUNC = [](const std::string colorVarName) -> std::string { return R"#( - // branchless baby! + // shoutout me: I fixed this shader being a bit pixelated while watching hentai + highp vec2 pixCoord = vec2(gl_FragCoord); pixCoord -= topLeft + fullSize * 0.5; pixCoord *= vec2(lessThan(pixCoord, vec2(0.0))) * -2.0 + 1.0; pixCoord -= fullSize * 0.5 - radius; pixCoord += vec2(1.0, 1.0) / fullSize; // center the pix dont make it top-left + const float SMOOTHING_CONSTANT = 0.651724; // smoothing constant for the edge: more = blurrier, but smoother + if (pixCoord.x + pixCoord.y > radius) { float dist = length(pixCoord); - if (dist > radius) + if (dist > radius + SMOOTHING_CONSTANT * 2.0) discard; - if (dist > radius - 1.0) { + if (dist > radius - SMOOTHING_CONSTANT * 2.0) { float dist = length(pixCoord); - float normalized = 1.0 - smoothstep(0.0, 1.0, dist - radius + 0.5); + float normalized = 1.0 - smoothstep(0.0, 1.0, (dist - radius + SMOOTHING_CONSTANT) / (SMOOTHING_CONSTANT * 2.0)); )#" + colorVarName + R"#( = )#" + colorVarName + R"#( * normalized; From 0920572e703201368c9fbcc9108ce1888600ffa2 Mon Sep 17 00:00:00 2001 From: Vaxry Date: Tue, 5 Nov 2024 16:11:05 +0000 Subject: [PATCH 0596/2181] shaders: improve corner AA in borders shader --- src/render/shaders/Border.hpp | 10 ++++++++-- src/render/shaders/SharedValues.hpp | 3 +++ src/render/shaders/Textures.hpp | 6 +++++- 3 files changed, 16 insertions(+), 3 deletions(-) create mode 100644 src/render/shaders/SharedValues.hpp diff --git a/src/render/shaders/Border.hpp b/src/render/shaders/Border.hpp index a33694a7..1f4a1d97 100644 --- a/src/render/shaders/Border.hpp +++ b/src/render/shaders/Border.hpp @@ -1,6 +1,8 @@ #pragma once #include +#include +#include "SharedValues.hpp" // makes a stencil without corners inline const std::string FRAGBORDER1 = R"#( @@ -72,18 +74,22 @@ void main() { pixCoordOuter += vec2(1.0, 1.0) / fullSize; if (min(pixCoord.x, pixCoord.y) > 0.0 && radius > 0.0) { + // smoothing constant for the edge: more = blurrier, but smoother + const float SMOOTHING_CONSTANT = )#" + + std::format("{:.7f}", SHADER_ROUNDED_SMOOTHING_FACTOR) + R"#(; + float dist = length(pixCoord); float distOuter = length(pixCoordOuter); float h = (thick / 2.0); if (dist < radius - h) { // lower - float normalized = smoothstep(0.0, 1.0, dist - radius + thick + 0.5); + float normalized = smoothstep(0.0, 1.0, (dist - radius + thick + SMOOTHING_CONSTANT) / (SMOOTHING_CONSTANT * 2.0)); additionalAlpha *= normalized; done = true; } else if (min(pixCoordOuter.x, pixCoordOuter.y) > 0.0) { // higher - float normalized = 1.0 - smoothstep(0.0, 1.0, distOuter - radiusOuter + 0.5); + float normalized = 1.0 - smoothstep(0.0, 1.0, (distOuter - radiusOuter + SMOOTHING_CONSTANT) / (SMOOTHING_CONSTANT * 2.0)); additionalAlpha *= normalized; done = true; } else if (distOuter < radiusOuter - h) { diff --git a/src/render/shaders/SharedValues.hpp b/src/render/shaders/SharedValues.hpp new file mode 100644 index 00000000..9a74c892 --- /dev/null +++ b/src/render/shaders/SharedValues.hpp @@ -0,0 +1,3 @@ +#pragma once + +constexpr float SHADER_ROUNDED_SMOOTHING_FACTOR = M_PI / 5.34665792551; \ No newline at end of file diff --git a/src/render/shaders/Textures.hpp b/src/render/shaders/Textures.hpp index e99d0a49..b203ad04 100644 --- a/src/render/shaders/Textures.hpp +++ b/src/render/shaders/Textures.hpp @@ -1,6 +1,8 @@ #pragma once #include +#include +#include "SharedValues.hpp" inline static constexpr auto ROUNDED_SHADER_FUNC = [](const std::string colorVarName) -> std::string { return R"#( @@ -13,7 +15,9 @@ inline static constexpr auto ROUNDED_SHADER_FUNC = [](const std::string colorVar pixCoord -= fullSize * 0.5 - radius; pixCoord += vec2(1.0, 1.0) / fullSize; // center the pix dont make it top-left - const float SMOOTHING_CONSTANT = 0.651724; // smoothing constant for the edge: more = blurrier, but smoother + // smoothing constant for the edge: more = blurrier, but smoother + const float SMOOTHING_CONSTANT = )#" + + std::format("{:.7f}", SHADER_ROUNDED_SMOOTHING_FACTOR) + R"#(; if (pixCoord.x + pixCoord.y > radius) { From 64c46db0872a576a993035ac1fa5e40af53ca001 Mon Sep 17 00:00:00 2001 From: Vaxry Date: Tue, 5 Nov 2024 16:20:04 +0000 Subject: [PATCH 0597/2181] hyprctl: add mirrorOf to hyprctl monitors fixes #8026 --- src/debug/HyprCtl.cpp | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/src/debug/HyprCtl.cpp b/src/debug/HyprCtl.cpp index f5c63f86..3e0c75a6 100644 --- a/src/debug/HyprCtl.cpp +++ b/src/debug/HyprCtl.cpp @@ -107,6 +107,7 @@ std::string CHyprCtl::getMonitorData(Hyprutils::Memory::CSharedPointer "activelyTearing": {}, "disabled": {}, "currentFormat": "{}", + "mirrorOf": "{}", "availableModes": [{}] }},)#", @@ -117,18 +118,19 @@ std::string CHyprCtl::getMonitorData(Hyprutils::Memory::CSharedPointer (int)m->vecReservedBottomRight.x, (int)m->vecReservedBottomRight.y, m->scale, (int)m->transform, (m == g_pCompositor->m_pLastMonitor ? "true" : "false"), (m->dpmsStatus ? "true" : "false"), (m->output->state->state().adaptiveSync ? "true" : "false"), (uint64_t)m->solitaryClient.get(), (m->tearingState.activelyTearing ? "true" : "false"), (m->m_bEnabled ? "false" : "true"), formatToString(m->output->state->state().drmFormat), - availableModesForOutput(m, format)); + m->pMirrorOf ? std::format("{}", m->pMirrorOf->ID) : "none", availableModesForOutput(m, format)); } else { result += std::format("Monitor {} (ID {}):\n\t{}x{}@{:.5f} at {}x{}\n\tdescription: {}\n\tmake: {}\n\tmodel: {}\n\tserial: {}\n\tactive workspace: {} ({})\n\t" "special workspace: {} ({})\n\treserved: {} {} {} {}\n\tscale: {:.2f}\n\ttransform: {}\n\tfocused: {}\n\t" - "dpmsStatus: {}\n\tvrr: {}\n\tsolitary: {:x}\n\tactivelyTearing: {}\n\tdisabled: {}\n\tcurrentFormat: {}\n\tavailableModes: {}\n\n", + "dpmsStatus: {}\n\tvrr: {}\n\tsolitary: {:x}\n\tactivelyTearing: {}\n\tdisabled: {}\n\tcurrentFormat: {}\n\tmirrorOf: {}\n\tavailableModes: {}\n\n", m->szName, m->ID, (int)m->vecPixelSize.x, (int)m->vecPixelSize.y, m->refreshRate, (int)m->vecPosition.x, (int)m->vecPosition.y, m->szShortDescription, m->output->make, m->output->model, m->output->serial, m->activeWorkspaceID(), (!m->activeWorkspace ? "" : m->activeWorkspace->m_szName), m->activeSpecialWorkspaceID(), (m->activeSpecialWorkspace ? m->activeSpecialWorkspace->m_szName : ""), (int)m->vecReservedTopLeft.x, (int)m->vecReservedTopLeft.y, (int)m->vecReservedBottomRight.x, (int)m->vecReservedBottomRight.y, m->scale, (int)m->transform, (m == g_pCompositor->m_pLastMonitor ? "yes" : "no"), (int)m->dpmsStatus, m->output->state->state().adaptiveSync, (uint64_t)m->solitaryClient.get(), - m->tearingState.activelyTearing, !m->m_bEnabled, formatToString(m->output->state->state().drmFormat), availableModesForOutput(m, format)); + m->tearingState.activelyTearing, !m->m_bEnabled, formatToString(m->output->state->state().drmFormat), + m->pMirrorOf ? std::format("{}", m->pMirrorOf->ID) : "none", availableModesForOutput(m, format)); } return result; From 81ad218b8b082ce4c9b04bbb668d3c219fc4ff6f Mon Sep 17 00:00:00 2001 From: Vaxry Date: Tue, 5 Nov 2024 16:28:55 +0000 Subject: [PATCH 0598/2181] shadow: fix double premultiplication shader takes straight alpha aaaa --- src/render/OpenGL.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/render/OpenGL.cpp b/src/render/OpenGL.cpp index 52392436..eb0a029f 100644 --- a/src/render/OpenGL.cpp +++ b/src/render/OpenGL.cpp @@ -2485,7 +2485,7 @@ void CHyprOpenGLImpl::renderRoundedShadow(CBox* box, int round, int range, const glMatrix.transpose(); glUniformMatrix3fv(m_RenderData.pCurrentMonData->m_shSHADOW.proj, 1, GL_FALSE, glMatrix.getMatrix().data()); #endif - glUniform4f(m_RenderData.pCurrentMonData->m_shSHADOW.color, col.r * col.a * a, col.g * col.a * a, col.b * col.a * a, col.a * a); + glUniform4f(m_RenderData.pCurrentMonData->m_shSHADOW.color, col.r, col.g, col.b, col.a * a); const auto TOPLEFT = Vector2D(range + round, range + round); const auto BOTTOMRIGHT = Vector2D(box->width - (range + round), box->height - (range + round)); From e4ab28b1fb063e5554c953c721779644ef6ada08 Mon Sep 17 00:00:00 2001 From: Kamikadze <40305144+Kam1k4dze@users.noreply.github.com> Date: Tue, 5 Nov 2024 23:03:37 +0500 Subject: [PATCH 0599/2181] defaultConfig: update default config values for shadows (#8360) --- example/hyprland.conf | 10 ++++++---- src/config/defaultConfig.hpp | 10 ++++++---- 2 files changed, 12 insertions(+), 8 deletions(-) diff --git a/example/hyprland.conf b/example/hyprland.conf index f1139c3b..edeeac01 100644 --- a/example/hyprland.conf +++ b/example/hyprland.conf @@ -86,10 +86,12 @@ decoration { active_opacity = 1.0 inactive_opacity = 1.0 - drop_shadow = true - shadow_range = 4 - shadow_render_power = 3 - col.shadow = rgba(1a1a1aee) + shadow { + enabled = true + range = 4 + render_power = 3 + color = rgba(1a1a1aee) + } # https://wiki.hyprland.org/Configuring/Variables/#blur blur { diff --git a/src/config/defaultConfig.hpp b/src/config/defaultConfig.hpp index facb16e2..02781770 100644 --- a/src/config/defaultConfig.hpp +++ b/src/config/defaultConfig.hpp @@ -99,10 +99,12 @@ decoration { active_opacity = 1.0 inactive_opacity = 1.0 - drop_shadow = true - shadow_range = 4 - shadow_render_power = 3 - col.shadow = rgba(1a1a1aee) + shadow { + enabled = true + range = 4 + render_power = 3 + color = rgba(1a1a1aee) + } # https://wiki.hyprland.org/Configuring/Variables/#blur blur { From 3bf6f78dad5f78dd8f4f519ceaa5a98671c90b14 Mon Sep 17 00:00:00 2001 From: izmyname <135810812+izmyname@users.noreply.github.com> Date: Tue, 5 Nov 2024 23:14:48 +0500 Subject: [PATCH 0600/2181] hyprland-systemd.desktop: change name back to Hyprland (#8351) --- systemd/hyprland-systemd.desktop | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/systemd/hyprland-systemd.desktop b/systemd/hyprland-systemd.desktop index 8c065a81..64ebbd47 100644 --- a/systemd/hyprland-systemd.desktop +++ b/systemd/hyprland-systemd.desktop @@ -3,5 +3,5 @@ Name=Hyprland (systemd session) Comment=An intelligent dynamic tiling Wayland compositor Exec=systemctl --user start --wait hyprland-session Type=Application -DesktopNames=Hyprland (systemd session) +DesktopNames=Hyprland Keywords=tiling;wayland;compositor; From 97a309b7844aea82b200139febc99998e7f06402 Mon Sep 17 00:00:00 2001 From: Vaxry Date: Wed, 6 Nov 2024 14:02:39 +0000 Subject: [PATCH 0601/2181] layershell: check if workspace is valid in onMap ref #8296 --- src/desktop/LayerSurface.cpp | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/desktop/LayerSurface.cpp b/src/desktop/LayerSurface.cpp index f073da82..eb3cdfd2 100644 --- a/src/desktop/LayerSurface.cpp +++ b/src/desktop/LayerSurface.cpp @@ -175,8 +175,7 @@ void CLayerSurface::onMap() { CBox geomFixed = {geometry.x + PMONITOR->vecPosition.x, geometry.y + PMONITOR->vecPosition.y, geometry.width, geometry.height}; g_pHyprRenderer->damageBox(&geomFixed); - const auto WORKSPACE = PMONITOR->activeWorkspace; - const bool FULLSCREEN = WORKSPACE->m_bHasFullscreenWindow && WORKSPACE->m_efFullscreenMode == FSMODE_FULLSCREEN; + const bool FULLSCREEN = PMONITOR->activeWorkspace && PMONITOR->activeWorkspace->m_bHasFullscreenWindow && PMONITOR->activeWorkspace->m_efFullscreenMode == FSMODE_FULLSCREEN; startAnimation(!(layer == ZWLR_LAYER_SHELL_V1_LAYER_TOP && FULLSCREEN && !GRABSFOCUS)); readyToDelete = false; From 8f42401aa8ac5a7778e29024be7ef3e0a063de13 Mon Sep 17 00:00:00 2001 From: Aqa-Ib Date: Wed, 6 Nov 2024 17:52:10 +0100 Subject: [PATCH 0602/2181] groups: add merge_groups_on_groupbar (#8362) --- src/config/ConfigDescriptions.hpp | 6 ++++++ src/config/ConfigManager.cpp | 1 + src/layout/DwindleLayout.cpp | 5 ----- src/layout/IHyprLayout.cpp | 10 +++------- src/layout/MasterLayout.cpp | 20 +++++++------------ .../decorations/CHyprGroupBarDecoration.cpp | 8 +++++++- 6 files changed, 24 insertions(+), 26 deletions(-) diff --git a/src/config/ConfigDescriptions.hpp b/src/config/ConfigDescriptions.hpp index 5327c599..12e81f2a 100644 --- a/src/config/ConfigDescriptions.hpp +++ b/src/config/ConfigDescriptions.hpp @@ -778,6 +778,12 @@ inline static const std::vector CONFIG_OPTIONS = { .type = CONFIG_OPTION_BOOL, .data = SConfigOptionDescription::SBoolData{true}, }, + SConfigOptionDescription{ + .value = "group:merge_groups_on_groupbar", + .description = "whether one group will be merged with another when dragged into its groupbar", + .type = CONFIG_OPTION_BOOL, + .data = SConfigOptionDescription::SBoolData{true}, + }, SConfigOptionDescription{ .value = "general:col.border_active", .description = "border color for inactive windows", diff --git a/src/config/ConfigManager.cpp b/src/config/ConfigManager.cpp index eafe4cbb..769a7525 100644 --- a/src/config/ConfigManager.cpp +++ b/src/config/ConfigManager.cpp @@ -381,6 +381,7 @@ CConfigManager::CConfigManager() { m_pConfig->addConfigValue("group:insert_after_current", Hyprlang::INT{1}); m_pConfig->addConfigValue("group:focus_removed_window", Hyprlang::INT{1}); m_pConfig->addConfigValue("group:merge_groups_on_drag", Hyprlang::INT{1}); + m_pConfig->addConfigValue("group:merge_groups_on_groupbar", Hyprlang::INT{1}); m_pConfig->addConfigValue("group:merge_floated_into_tiled_on_groupbar", Hyprlang::INT{0}); m_pConfig->addConfigValue("group:auto_group", Hyprlang::INT{1}); m_pConfig->addConfigValue("group:drag_into_group", Hyprlang::INT{1}); diff --git a/src/layout/DwindleLayout.cpp b/src/layout/DwindleLayout.cpp index 32f64e4e..e6e9090f 100644 --- a/src/layout/DwindleLayout.cpp +++ b/src/layout/DwindleLayout.cpp @@ -310,11 +310,6 @@ void CHyprDwindleLayout::onWindowCreatedTiling(PHLWINDOW pWindow, eDirection dir return; } - if (!m_vOverrideFocalPoint && g_pInputManager->m_bWasDraggingWindow) { - if (OPENINGON->pWindow->checkInputOnDecos(INPUT_TYPE_DRAG_END, MOUSECOORDS, pWindow)) - return; - } - // get the node under our cursor m_lDwindleNodesData.push_back(SDwindleNodeData()); diff --git a/src/layout/IHyprLayout.cpp b/src/layout/IHyprLayout.cpp index 980311d6..a312555f 100644 --- a/src/layout/IHyprLayout.cpp +++ b/src/layout/IHyprLayout.cpp @@ -344,12 +344,6 @@ void IHyprLayout::onEndDragWindow() { if (pWindow->m_sGroupData.pNextWindow.lock() && DRAGGINGWINDOW->canBeGroupedInto(pWindow) && *PDRAGINTOGROUP == 1 && !FLOATEDINTOTILED) { - if (DRAGGINGWINDOW->m_bDraggingTiled) { - changeWindowFloatingMode(DRAGGINGWINDOW); - DRAGGINGWINDOW->m_vLastFloatingSize = m_vDraggingWindowOriginalFloatSize; - DRAGGINGWINDOW->m_bDraggingTiled = false; - } - if (DRAGGINGWINDOW->m_sGroupData.pNextWindow) { PHLWINDOW next = DRAGGINGWINDOW->m_sGroupData.pNextWindow.lock(); while (next != DRAGGINGWINDOW) { @@ -360,7 +354,9 @@ void IHyprLayout::onEndDragWindow() { } } - DRAGGINGWINDOW->m_bIsFloating = pWindow->m_bIsFloating; // match the floating state of the window + DRAGGINGWINDOW->m_bIsFloating = pWindow->m_bIsFloating; // match the floating state of the window + DRAGGINGWINDOW->m_vLastFloatingSize = m_vDraggingWindowOriginalFloatSize; + DRAGGINGWINDOW->m_bDraggingTiled = false; if (pWindow->m_bIsFloating) g_pXWaylandManager->setWindowSize(DRAGGINGWINDOW, pWindow->m_vRealSize.goal()); // match the size of the window diff --git a/src/layout/MasterLayout.cpp b/src/layout/MasterLayout.cpp index afe79ecf..b8b3efea 100644 --- a/src/layout/MasterLayout.cpp +++ b/src/layout/MasterLayout.cpp @@ -101,21 +101,15 @@ void CHyprMasterLayout::onWindowCreatedTiling(PHLWINDOW pWindow, eDirection dire PNODE->workspaceID = pWindow->workspaceID(); PNODE->pWindow = pWindow; - const auto WINDOWSONWORKSPACE = getNodesOnWorkspace(PNODE->workspaceID); - static auto PMFACT = CConfigValue("master:mfact"); - float lastSplitPercent = *PMFACT; + const auto WINDOWSONWORKSPACE = getNodesOnWorkspace(PNODE->workspaceID); + static auto PMFACT = CConfigValue("master:mfact"); + float lastSplitPercent = *PMFACT; - auto OPENINGON = isWindowTiled(g_pCompositor->m_pLastWindow.lock()) && g_pCompositor->m_pLastWindow->m_pWorkspace == pWindow->m_pWorkspace ? - getNodeFromWindow(g_pCompositor->m_pLastWindow.lock()) : - getMasterNodeOnWorkspace(pWindow->workspaceID()); - - const auto MOUSECOORDS = g_pInputManager->getMouseCoordsInternal(); - - if (g_pInputManager->m_bWasDraggingWindow && OPENINGON) { - if (OPENINGON->pWindow->checkInputOnDecos(INPUT_TYPE_DRAG_END, MOUSECOORDS, pWindow)) - return; - } + auto OPENINGON = isWindowTiled(g_pCompositor->m_pLastWindow.lock()) && g_pCompositor->m_pLastWindow->m_pWorkspace == pWindow->m_pWorkspace ? + getNodeFromWindow(g_pCompositor->m_pLastWindow.lock()) : + getMasterNodeOnWorkspace(pWindow->workspaceID()); + const auto MOUSECOORDS = g_pInputManager->getMouseCoordsInternal(); static auto PDROPATCURSOR = CConfigValue("master:drop_at_cursor"); eOrientation orientation = getDynamicOrientation(pWindow->m_pWorkspace); const auto NODEIT = std::find(m_lMasterNodesData.begin(), m_lMasterNodesData.end(), *PNODE); diff --git a/src/render/decorations/CHyprGroupBarDecoration.cpp b/src/render/decorations/CHyprGroupBarDecoration.cpp index ec9f876b..b5189be5 100644 --- a/src/render/decorations/CHyprGroupBarDecoration.cpp +++ b/src/render/decorations/CHyprGroupBarDecoration.cpp @@ -405,10 +405,16 @@ bool CHyprGroupBarDecoration::onEndWindowDragOnDeco(const Vector2D& pos, PHLWIND static auto PSTACKED = CConfigValue("group:groupbar:stacked"); static auto PDRAGINTOGROUP = CConfigValue("group:drag_into_group"); static auto PMERGEFLOATEDINTOTILEDONGROUPBAR = CConfigValue("group:merge_floated_into_tiled_on_groupbar"); + static auto PMERGEGROUPSONGROUPBAR = CConfigValue("group:merge_groups_on_groupbar"); const bool FLOATEDINTOTILED = !m_pWindow->m_bIsFloating && !pDraggedWindow->m_bDraggingTiled; - if (!pDraggedWindow->canBeGroupedInto(m_pWindow.lock()) || (*PDRAGINTOGROUP != 1 && *PDRAGINTOGROUP != 2) || (FLOATEDINTOTILED && !*PMERGEFLOATEDINTOTILEDONGROUPBAR)) + g_pInputManager->m_bWasDraggingWindow = false; + + if (!pDraggedWindow->canBeGroupedInto(m_pWindow.lock()) || (*PDRAGINTOGROUP != 1 && *PDRAGINTOGROUP != 2) || (FLOATEDINTOTILED && !*PMERGEFLOATEDINTOTILEDONGROUPBAR) || + (!*PMERGEGROUPSONGROUPBAR && pDraggedWindow->m_sGroupData.pNextWindow.lock() && m_pWindow->m_sGroupData.pNextWindow.lock())) { + g_pInputManager->m_bWasDraggingWindow = true; return false; + } const float BARRELATIVE = *PSTACKED ? pos.y - assignedBoxGlobal().y - (m_fBarHeight + BAR_PADDING_OUTER_VERT) / 2 : pos.x - assignedBoxGlobal().x - m_fBarWidth / 2; const float BARSIZE = *PSTACKED ? m_fBarHeight + BAR_PADDING_OUTER_VERT : m_fBarWidth + BAR_HORIZONTAL_PADDING; From 083a5cf3c1127dd2f638c3e9a665a88dd54a59a4 Mon Sep 17 00:00:00 2001 From: Mihai Fufezan Date: Wed, 6 Nov 2024 19:50:01 +0200 Subject: [PATCH 0603/2181] CI: update actions --- .github/workflows/ci.yaml | 2 +- .github/workflows/man-update.yaml | 4 ++-- .github/workflows/nix-update-inputs.yml | 4 ++-- .github/workflows/release.yaml | 2 +- .github/workflows/security-checks.yml | 2 +- .github/workflows/stale.yml | 2 +- 6 files changed, 8 insertions(+), 8 deletions(-) diff --git a/.github/workflows/ci.yaml b/.github/workflows/ci.yaml index 7739d2b2..22421d18 100644 --- a/.github/workflows/ci.yaml +++ b/.github/workflows/ci.yaml @@ -39,7 +39,7 @@ jobs: tar -cvf Hyprland.tar.xz hyprland - name: Release - uses: actions/upload-artifact@v3 + uses: actions/upload-artifact@v4 with: name: Build archive path: Hyprland.tar.xz diff --git a/.github/workflows/man-update.yaml b/.github/workflows/man-update.yaml index b47787c0..6c0a72f3 100644 --- a/.github/workflows/man-update.yaml +++ b/.github/workflows/man-update.yaml @@ -17,14 +17,14 @@ jobs: run: sudo apt install pandoc - name: Clone repository - uses: actions/checkout@v3 + uses: actions/checkout@v4 with: token: ${{ secrets.PAT }} - name: Build man pages run: make man - - uses: stefanzweifel/git-auto-commit-action@v4 + - uses: stefanzweifel/git-auto-commit-action@v5 name: Commit with: commit_message: "[gha] build man pages" diff --git a/.github/workflows/nix-update-inputs.yml b/.github/workflows/nix-update-inputs.yml index a8f68f3b..c9a094a2 100644 --- a/.github/workflows/nix-update-inputs.yml +++ b/.github/workflows/nix-update-inputs.yml @@ -13,7 +13,7 @@ jobs: runs-on: ubuntu-latest steps: - name: Clone repository - uses: actions/checkout@v3 + uses: actions/checkout@v4 with: token: ${{ secrets.PAT }} @@ -22,6 +22,6 @@ jobs: run: nix/update-inputs.sh - name: Commit - uses: stefanzweifel/git-auto-commit-action@v4 + uses: stefanzweifel/git-auto-commit-action@v5 with: commit_message: "[gha] Nix: update inputs" diff --git a/.github/workflows/release.yaml b/.github/workflows/release.yaml index d5ff1aa0..44baff97 100644 --- a/.github/workflows/release.yaml +++ b/.github/workflows/release.yaml @@ -11,7 +11,7 @@ jobs: steps: - name: Checkout Hyprland id: checkout - uses: actions/checkout@v3 + uses: actions/checkout@v4 with: submodules: recursive diff --git a/.github/workflows/security-checks.yml b/.github/workflows/security-checks.yml index 4f539132..284500e6 100644 --- a/.github/workflows/security-checks.yml +++ b/.github/workflows/security-checks.yml @@ -13,7 +13,7 @@ jobs: security-events: write steps: - name: Checkout code - uses: actions/checkout@v3 + uses: actions/checkout@v4 - name: Scan with Flawfinder uses: david-a-wheeler/flawfinder@8e4a779ad59dbfaee5da586aa9210853b701959c diff --git a/.github/workflows/stale.yml b/.github/workflows/stale.yml index b8be5f55..9d2eed80 100644 --- a/.github/workflows/stale.yml +++ b/.github/workflows/stale.yml @@ -19,7 +19,7 @@ jobs: pull-requests: write steps: - - uses: actions/stale@v5 + - uses: actions/stale@v9 with: repo-token: ${{ secrets.STALEBOT_PAT }} stale-issue-label: "stale" From 0ec128e5ed5e15aaebff6c4b5983326ab524d690 Mon Sep 17 00:00:00 2001 From: Vaxry Date: Wed, 6 Nov 2024 22:11:41 +0000 Subject: [PATCH 0604/2181] renderer: don't rely on datarootdir for local share --- src/render/OpenGL.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/src/render/OpenGL.cpp b/src/render/OpenGL.cpp index eb0a029f..63a7e822 100644 --- a/src/render/OpenGL.cpp +++ b/src/render/OpenGL.cpp @@ -18,6 +18,7 @@ const std::vector ASSET_PATHS = { DATAROOTDIR, #endif "/usr/share", + "/usr/local/share", }; inline void loadGLProc(void* pProc, const char* name) { From 2ec2b3bfb39ba22ba945bb23dc95970dfa50eb5a Mon Sep 17 00:00:00 2001 From: dawsers <47487972+dawsers@users.noreply.github.com> Date: Thu, 7 Nov 2024 00:30:17 +0100 Subject: [PATCH 0605/2181] renderer: minor fixup to window rendering logic (#8359) Don't render animating windows out of their monitor when they are not moving workspaces --- src/render/Renderer.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/render/Renderer.cpp b/src/render/Renderer.cpp index 6af3a99d..469acda9 100644 --- a/src/render/Renderer.cpp +++ b/src/render/Renderer.cpp @@ -355,7 +355,7 @@ bool CHyprRenderer::shouldRenderWindow(PHLWINDOW pWindow, PHLMONITOR pMonitor) { windowBox.translate(pWindow->m_vFloatingOffset); const CBox monitorBox = {pMonitor->vecPosition, pMonitor->vecSize}; - if (!windowBox.intersection(monitorBox).empty()) + if (!windowBox.intersection(monitorBox).empty() && (pWindow->workspaceID() == pMonitor->activeWorkspaceID() || pWindow->m_iMonitorMovedFrom != -1)) return true; } From 2dd0b2af71b2bd37f1febc608897f56d1eabab4c Mon Sep 17 00:00:00 2001 From: Mihai Fufezan Date: Thu, 7 Nov 2024 10:51:48 +0200 Subject: [PATCH 0606/2181] flake.lock: update --- flake.lock | 30 +++++++++++++++--------------- 1 file changed, 15 insertions(+), 15 deletions(-) diff --git a/flake.lock b/flake.lock index 8cee27e3..b9055015 100644 --- a/flake.lock +++ b/flake.lock @@ -16,11 +16,11 @@ ] }, "locked": { - "lastModified": 1729527199, - "narHash": "sha256-D5/YksfRga8Akd04ZtIkuYSIOjXVrAzQIQBSeplokzU=", + "lastModified": 1730968822, + "narHash": "sha256-NocDjINsh6ismkhb0Xr6xPRksmhuB2WGf8ZmXMhxu7Y=", "owner": "hyprwm", "repo": "aquamarine", - "rev": "8d732fa8aff8b12ef2b1e2f00fc8153e41312b72", + "rev": "a49bc3583ff223f426cb3526fdaa4bcaa247ec14", "type": "github" }, "original": { @@ -151,11 +151,11 @@ ] }, "locked": { - "lastModified": 1728941256, - "narHash": "sha256-WRypmcZ2Bw94lLmcmxYokVOHPJSZ7T06V49QZ4tkZeQ=", + "lastModified": 1730968903, + "narHash": "sha256-zFvzLXcSm0Ia4XI1SE4FQ9KE63hlGrRWhLtwMolWuR8=", "owner": "hyprwm", "repo": "hyprutils", - "rev": "fd4be8b9ca932f7384e454bcd923c5451ef2aa85", + "rev": "3ce0cde8709cdacbfba471f8e828433b58a561e9", "type": "github" }, "original": { @@ -189,11 +189,11 @@ }, "nixpkgs": { "locked": { - "lastModified": 1730531603, - "narHash": "sha256-Dqg6si5CqIzm87sp57j5nTaeBbWhHFaVyG7V6L8k3lY=", + "lastModified": 1730785428, + "narHash": "sha256-Zwl8YgTVJTEum+L+0zVAWvXAGbWAuXHax3KzuejaDyo=", "owner": "NixOS", "repo": "nixpkgs", - "rev": "7ffd9ae656aec493492b44d0ddfb28e79a1ea25d", + "rev": "4aa36568d413aca0ea84a1684d2d46f55dbabad7", "type": "github" }, "original": { @@ -205,11 +205,11 @@ }, "nixpkgs-stable": { "locked": { - "lastModified": 1720386169, - "narHash": "sha256-NGKVY4PjzwAa4upkGtAMz1npHGoRzWotlSnVlqI40mo=", + "lastModified": 1730741070, + "narHash": "sha256-edm8WG19kWozJ/GqyYx2VjW99EdhjKwbY3ZwdlPAAlo=", "owner": "NixOS", "repo": "nixpkgs", - "rev": "194846768975b7ad2c4988bdb82572c00222c0d7", + "rev": "d063c1dd113c91ab27959ba540c0d9753409edf3", "type": "github" }, "original": { @@ -229,11 +229,11 @@ "nixpkgs-stable": "nixpkgs-stable" }, "locked": { - "lastModified": 1729104314, - "narHash": "sha256-pZRZsq5oCdJt3upZIU4aslS9XwFJ+/nVtALHIciX/BI=", + "lastModified": 1730814269, + "narHash": "sha256-fWPHyhYE6xvMI1eGY3pwBTq85wcy1YXqdzTZF+06nOg=", "owner": "cachix", "repo": "git-hooks.nix", - "rev": "3c3e88f0f544d6bb54329832616af7eb971b6be6", + "rev": "d70155fdc00df4628446352fc58adc640cd705c2", "type": "github" }, "original": { From e58e97b0a38b8ccc87a4304c9e4e2b37c9966875 Mon Sep 17 00:00:00 2001 From: Mihai Fufezan Date: Thu, 7 Nov 2024 10:52:12 +0200 Subject: [PATCH 0607/2181] Nix: build aquamarine and hyprutils in debug when using hyprland-debug --- nix/default.nix | 4 +--- nix/overlays.nix | 8 +++++++- 2 files changed, 8 insertions(+), 4 deletions(-) diff --git a/nix/default.nix b/nix/default.nix index d463e271..29d31485 100644 --- a/nix/default.nix +++ b/nix/default.nix @@ -56,6 +56,7 @@ adapters = flatten [ stdenvAdapters.useMoldLinker + (lib.optional debug stdenvAdapters.keepDebugInfo) ]; customStdenv = foldl' (acc: adapter: adapter acc) stdenv adapters; @@ -147,9 +148,6 @@ in then "debugoptimized" else "release"; - # we want as much debug info as possible - dontStrip = debug; - mesonFlags = flatten [ (mapAttrsToList mesonEnable { "xwayland" = enableXWayland; diff --git a/nix/overlays.nix b/nix/overlays.nix index b1eb66ad..a7106315 100644 --- a/nix/overlays.nix +++ b/nix/overlays.nix @@ -40,7 +40,13 @@ in { inherit date; }; hyprland-unwrapped = final.hyprland.override {wrapRuntimeDeps = false;}; - hyprland-debug = final.hyprland.override {debug = true;}; + + # Build major libs with debug to get as much info as possible in a stacktrace + hyprland-debug = final.hyprland.override { + aquamarine = final.aquamarine.override {debug = true;}; + hyprutils = final.hyprutils.override {debug = true;}; + debug = true; + }; hyprland-legacy-renderer = final.hyprland.override {legacyRenderer = true;}; # deprecated packages From 3b66351eeb76e802bac37cc892529549efc49905 Mon Sep 17 00:00:00 2001 From: nickodei <46863421+nickodei@users.noreply.github.com> Date: Fri, 8 Nov 2024 18:25:37 +0100 Subject: [PATCH 0608/2181] input: Refocus window on scrolling if follows mouse (#8361) --- src/managers/input/InputManager.cpp | 36 ++++++++++++++++++----------- 1 file changed, 23 insertions(+), 13 deletions(-) diff --git a/src/managers/input/InputManager.cpp b/src/managers/input/InputManager.cpp index af725927..b12a6e03 100644 --- a/src/managers/input/InputManager.cpp +++ b/src/managers/input/InputManager.cpp @@ -759,6 +759,7 @@ void CInputManager::onMouseWheel(IPointer::SAxisEvent e) { static auto PINPUTSCROLLFACTOR = CConfigValue("input:scroll_factor"); static auto PTOUCHPADSCROLLFACTOR = CConfigValue("input:touchpad:scroll_factor"); static auto PEMULATEDISCRETE = CConfigValue("input:emulate_discrete_scroll"); + static auto PFOLLOWMOUSE = CConfigValue("input:follow_mouse"); auto factor = (*PTOUCHPADSCROLLFACTOR <= 0.f || e.source == WL_POINTER_AXIS_SOURCE_FINGER ? *PTOUCHPADSCROLLFACTOR : *PINPUTSCROLLFACTOR); @@ -774,24 +775,33 @@ void CInputManager::onMouseWheel(IPointer::SAxisEvent e) { const auto MOUSECOORDS = g_pInputManager->getMouseCoordsInternal(); const auto PWINDOW = g_pCompositor->vectorToWindowUnified(MOUSECOORDS, RESERVED_EXTENTS | INPUT_EXTENTS | ALLOW_FLOATING); - if (PWINDOW && PWINDOW->checkInputOnDecos(INPUT_TYPE_AXIS, MOUSECOORDS, e)) - return; + if (PWINDOW) { + if (PWINDOW->checkInputOnDecos(INPUT_TYPE_AXIS, MOUSECOORDS, e)) + return; - if (PWINDOW && *POFFWINDOWAXIS != 1) { - const auto BOX = PWINDOW->getWindowMainSurfaceBox(); + if (*POFFWINDOWAXIS != 1) { + const auto BOX = PWINDOW->getWindowMainSurfaceBox(); - if (!BOX.containsPoint(MOUSECOORDS) && !PWINDOW->hasPopupAt(MOUSECOORDS)) { - if (*POFFWINDOWAXIS == 0) - return; + if (!BOX.containsPoint(MOUSECOORDS) && !PWINDOW->hasPopupAt(MOUSECOORDS)) { + if (*POFFWINDOWAXIS == 0) + return; - const auto TEMPCURX = std::clamp(MOUSECOORDS.x, BOX.x, BOX.x + BOX.w - 1); - const auto TEMPCURY = std::clamp(MOUSECOORDS.y, BOX.y, BOX.y + BOX.h - 1); + const auto TEMPCURX = std::clamp(MOUSECOORDS.x, BOX.x, BOX.x + BOX.w - 1); + const auto TEMPCURY = std::clamp(MOUSECOORDS.y, BOX.y, BOX.y + BOX.h - 1); - if (*POFFWINDOWAXIS == 3) - g_pCompositor->warpCursorTo({TEMPCURX, TEMPCURY}, true); + if (*POFFWINDOWAXIS == 3) + g_pCompositor->warpCursorTo({TEMPCURX, TEMPCURY}, true); - g_pSeatManager->sendPointerMotion(e.timeMs, Vector2D{TEMPCURX, TEMPCURY} - BOX.pos()); - g_pSeatManager->sendPointerFrame(); + g_pSeatManager->sendPointerMotion(e.timeMs, Vector2D{TEMPCURX, TEMPCURY} - BOX.pos()); + g_pSeatManager->sendPointerFrame(); + } + } + + if (g_pSeatManager->state.pointerFocus) { + const auto PCURRWINDOW = g_pCompositor->getWindowFromSurface(g_pSeatManager->state.pointerFocus.lock()); + + if (*PFOLLOWMOUSE == 1 && PCURRWINDOW && PWINDOW != PCURRWINDOW) + simulateMouseMovement(); } } } From 4c7a2faf85a2d74508cc8a95df42ebe52b47383b Mon Sep 17 00:00:00 2001 From: Vaxry Date: Sat, 9 Nov 2024 01:53:01 +0000 Subject: [PATCH 0609/2181] input: cleanup device naming logic ref #8301 --- src/devices/IHID.hpp | 2 +- src/devices/IKeyboard.hpp | 1 - src/devices/IPointer.hpp | 1 - src/devices/ITouch.hpp | 1 - src/devices/Tablet.hpp | 5 ----- src/managers/input/InputManager.cpp | 27 ++++----------------------- src/managers/input/Tablets.cpp | 6 ++++++ 7 files changed, 11 insertions(+), 32 deletions(-) diff --git a/src/devices/IHID.hpp b/src/devices/IHID.hpp index cac25112..4a0ff8fd 100644 --- a/src/devices/IHID.hpp +++ b/src/devices/IHID.hpp @@ -36,5 +36,5 @@ class IHID { CSignal destroy; } events; - std::string deviceName; + std::string deviceName, hlName; }; \ No newline at end of file diff --git a/src/devices/IKeyboard.hpp b/src/devices/IKeyboard.hpp index 76d2c31b..dce2127a 100644 --- a/src/devices/IKeyboard.hpp +++ b/src/devices/IKeyboard.hpp @@ -94,7 +94,6 @@ class IKeyboard : public IHID { std::array modIndexes = {XKB_MOD_INVALID}; uint32_t leds = 0; - std::string hlName = ""; std::string xkbFilePath = ""; std::string xkbKeymapString = ""; int xkbKeymapFD = -1; diff --git a/src/devices/IPointer.hpp b/src/devices/IPointer.hpp index f38ef55a..503a690e 100644 --- a/src/devices/IPointer.hpp +++ b/src/devices/IPointer.hpp @@ -104,7 +104,6 @@ class IPointer : public IHID { CSignal holdEnd; } pointerEvents; - std::string hlName; bool connected = false; // means connected to the cursor std::string boundOutput = ""; diff --git a/src/devices/ITouch.hpp b/src/devices/ITouch.hpp index bf969b2f..766c0510 100644 --- a/src/devices/ITouch.hpp +++ b/src/devices/ITouch.hpp @@ -44,7 +44,6 @@ class ITouch : public IHID { CSignal frame; } touchEvents; - std::string hlName = ""; std::string boundOutput = ""; WP self; diff --git a/src/devices/Tablet.hpp b/src/devices/Tablet.hpp index 01901721..4894ac8e 100644 --- a/src/devices/Tablet.hpp +++ b/src/devices/Tablet.hpp @@ -92,7 +92,6 @@ class CTablet : public IHID { WP self; bool relativeInput = false; - std::string hlName = ""; std::string boundOutput = ""; CBox activeArea; CBox boundBox; // output-local @@ -154,8 +153,6 @@ class CTabletPad : public IHID { WP self; WP parent; - std::string hlName; - private: CTabletPad(SP pad); @@ -210,8 +207,6 @@ class CTabletTool : public IHID { std::vector buttonsDown; Vector2D absolutePos; // last known absolute position. - std::string hlName; - private: CTabletTool(SP tool); diff --git a/src/managers/input/InputManager.cpp b/src/managers/input/InputManager.cpp index b12a6e03..2787cbf7 100644 --- a/src/managers/input/InputManager.cpp +++ b/src/managers/input/InputManager.cpp @@ -1655,31 +1655,12 @@ std::string CInputManager::getNameForNewDevice(std::string internalName) { auto proposedNewName = deviceNameToInternalString(internalName); int dupeno = 0; - while (std::find_if(m_vKeyboards.begin(), m_vKeyboards.end(), - [&](const auto& other) { return other->hlName == proposedNewName + (dupeno == 0 ? "" : ("-" + std::to_string(dupeno))); }) != m_vKeyboards.end()) + auto makeNewName = [&]() { return (proposedNewName.empty() ? "unknown-device" : proposedNewName) + (dupeno == 0 ? "" : ("-" + std::to_string(dupeno))); }; + + while (std::find_if(m_vHIDs.begin(), m_vHIDs.end(), [&](const auto& other) { return other->hlName == makeNewName(); }) != m_vHIDs.end()) dupeno++; - while (std::find_if(m_vPointers.begin(), m_vPointers.end(), - [&](const auto& other) { return other->hlName == proposedNewName + (dupeno == 0 ? "" : ("-" + std::to_string(dupeno))); }) != m_vPointers.end()) - dupeno++; - - while (std::find_if(m_vTouches.begin(), m_vTouches.end(), - [&](const auto& other) { return other->hlName == proposedNewName + (dupeno == 0 ? "" : ("-" + std::to_string(dupeno))); }) != m_vTouches.end()) - dupeno++; - - while (std::find_if(m_vTabletPads.begin(), m_vTabletPads.end(), - [&](const auto& other) { return other->hlName == proposedNewName + (dupeno == 0 ? "" : ("-" + std::to_string(dupeno))); }) != m_vTabletPads.end()) - dupeno++; - - while (std::find_if(m_vTablets.begin(), m_vTablets.end(), - [&](const auto& other) { return other->hlName == proposedNewName + (dupeno == 0 ? "" : ("-" + std::to_string(dupeno))); }) != m_vTablets.end()) - dupeno++; - - while (std::find_if(m_vTabletTools.begin(), m_vTabletTools.end(), - [&](const auto& other) { return other->hlName == proposedNewName + (dupeno == 0 ? "" : ("-" + std::to_string(dupeno))); }) != m_vTabletTools.end()) - dupeno++; - - return proposedNewName + (dupeno == 0 ? "" : ("-" + std::to_string(dupeno))); + return makeNewName(); } void CInputManager::releaseAllMouseButtons() { diff --git a/src/managers/input/Tablets.cpp b/src/managers/input/Tablets.cpp index 9f80726e..3884afec 100644 --- a/src/managers/input/Tablets.cpp +++ b/src/managers/input/Tablets.cpp @@ -228,6 +228,12 @@ SP CInputManager::ensureTabletToolPresent(SPhlName = deviceNameToInternalString(pTool->getName()); + } catch (std::exception& e) { + Debug::log(ERR, "Tablet had no name???"); // logic error + } + PTOOL->events.destroy.registerStaticListener( [this](void* owner, std::any d) { auto TOOL = ((CTabletTool*)owner)->self; From f43d4a86383bc8a8251987552ad5a0e51dd85868 Mon Sep 17 00:00:00 2001 From: Vaxry Date: Sat, 9 Nov 2024 02:25:34 +0000 Subject: [PATCH 0610/2181] layershell: minor cleanups and improvements to focus ref #8293 --- src/desktop/LayerSurface.cpp | 19 ++++++++++++++----- 1 file changed, 14 insertions(+), 5 deletions(-) diff --git a/src/desktop/LayerSurface.cpp b/src/desktop/LayerSurface.cpp index eb3cdfd2..31c2482a 100644 --- a/src/desktop/LayerSurface.cpp +++ b/src/desktop/LayerSurface.cpp @@ -222,7 +222,7 @@ void CLayerSurface::onUnmap() { const auto PMONITOR = monitor.lock(); - const bool WASLASTFOCUS = g_pCompositor->m_pLastFocus == surface->resource(); + const bool WASLASTFOCUS = g_pSeatManager->state.keyboardFocus == surface->resource() || g_pSeatManager->state.pointerFocus == surface->resource(); if (!PMONITOR) return; @@ -231,7 +231,7 @@ void CLayerSurface::onUnmap() { // vvvvvvvvvvvvv if there is a last focus and the last focus is not keyboard focusable, fallback to window if (WASLASTFOCUS || (g_pCompositor->m_pLastFocus && g_pCompositor->m_pLastFocus->hlSurface && !g_pCompositor->m_pLastFocus->hlSurface->keyboardFocusable())) g_pInputManager->refocusLastWindow(PMONITOR); - else if (g_pCompositor->m_pLastFocus) + else if (g_pCompositor->m_pLastFocus && g_pCompositor->m_pLastFocus != surface->resource()) g_pSeatManager->setKeyboardFocus(g_pCompositor->m_pLastFocus.lock()); CBox geomFixed = {geometry.x + PMONITOR->vecPosition.x, geometry.y + PMONITOR->vecPosition.y, geometry.width, geometry.height}; @@ -320,8 +320,15 @@ void CLayerSurface::onCommit() { realSize.setValueAndWarp(geometry.size()); } - if (mapped) { - const bool WASLASTFOCUS = g_pCompositor->m_pLastFocus == surface->resource(); + if (mapped && (layerSurface->current.committed & CLayerShellResource::eCommittedState::STATE_INTERACTIVITY)) { + bool WASLASTFOCUS = false; + layerSurface->surface->breadthfirst( + [&WASLASTFOCUS](SP surf, const Vector2D& offset, void* data) { WASLASTFOCUS = WASLASTFOCUS || g_pSeatManager->state.keyboardFocus == surf; }, + nullptr); + if (!WASLASTFOCUS && popupHead) { + popupHead->breadthfirst([&WASLASTFOCUS](CPopup* popup, void* data) { WASLASTFOCUS = WASLASTFOCUS || (popup->m_pWLSurface && g_pSeatManager->state.keyboardFocus == popup->m_pWLSurface->resource()); }, + nullptr); + } const bool WASEXCLUSIVE = interactivity == ZWLR_LAYER_SURFACE_V1_KEYBOARD_INTERACTIVITY_EXCLUSIVE; const bool ISEXCLUSIVE = layerSurface->current.interactivity == ZWLR_LAYER_SURFACE_V1_KEYBOARD_INTERACTIVITY_EXCLUSIVE; @@ -331,11 +338,13 @@ void CLayerSurface::onCommit() { std::erase_if(g_pInputManager->m_dExclusiveLSes, [this](const auto& other) { return !other.lock() || other.lock() == self.lock(); }); // if the surface was focused and interactive but now isn't, refocus - if (WASLASTFOCUS && !layerSurface->current.interactivity) { + if (WASLASTFOCUS && layerSurface->current.interactivity == ZWLR_LAYER_SURFACE_V1_KEYBOARD_INTERACTIVITY_NONE) { // moveMouseUnified won't focus non interactive layers but it won't unfocus them either, // so unfocus the surface here. g_pCompositor->focusSurface(nullptr); g_pInputManager->refocusLastWindow(monitor.lock()); + } else if (WASLASTFOCUS && WASEXCLUSIVE && layerSurface->current.interactivity == ZWLR_LAYER_SURFACE_V1_KEYBOARD_INTERACTIVITY_ON_DEMAND) { + g_pInputManager->simulateMouseMovement(); } else if (!WASEXCLUSIVE && ISEXCLUSIVE) { // if now exclusive and not previously g_pSeatManager->setGrab(nullptr); From 0ccc0ace88fab3969c2eca95deb1cc9b2ac0d16d Mon Sep 17 00:00:00 2001 From: Vaxry Date: Sat, 9 Nov 2024 02:25:54 +0000 Subject: [PATCH 0611/2181] input: ignore non-kb ls-es in refocusLastWindow ref #8293 --- src/managers/input/InputManager.cpp | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/src/managers/input/InputManager.cpp b/src/managers/input/InputManager.cpp index 2787cbf7..c190f589 100644 --- a/src/managers/input/InputManager.cpp +++ b/src/managers/input/InputManager.cpp @@ -1388,13 +1388,19 @@ void CInputManager::refocusLastWindow(PHLMONITOR pMonitor) { foundSurface = m_dExclusiveLSes[m_dExclusiveLSes.size() - 1]->surface->resource(); // then any surfaces above windows on the same monitor - if (!foundSurface) + if (!foundSurface) { foundSurface = g_pCompositor->vectorToLayerSurface(g_pInputManager->getMouseCoordsInternal(), &pMonitor->m_aLayerSurfaceLayers[ZWLR_LAYER_SHELL_V1_LAYER_OVERLAY], &surfaceCoords, &pFoundLayerSurface); + if (pFoundLayerSurface && pFoundLayerSurface->interactivity == ZWLR_LAYER_SURFACE_V1_KEYBOARD_INTERACTIVITY_ON_DEMAND) + foundSurface = nullptr; + } - if (!foundSurface) + if (!foundSurface) { foundSurface = g_pCompositor->vectorToLayerSurface(g_pInputManager->getMouseCoordsInternal(), &pMonitor->m_aLayerSurfaceLayers[ZWLR_LAYER_SHELL_V1_LAYER_TOP], &surfaceCoords, &pFoundLayerSurface); + if (pFoundLayerSurface && pFoundLayerSurface->interactivity == ZWLR_LAYER_SURFACE_V1_KEYBOARD_INTERACTIVITY_ON_DEMAND) + foundSurface = nullptr; + } if (!foundSurface && g_pCompositor->m_pLastWindow.lock() && g_pCompositor->isWorkspaceVisibleNotCovered(g_pCompositor->m_pLastWindow->m_pWorkspace)) { // then the last focused window if we're on the same workspace as it From 726d69782124ffb5b609c0377cd21cfd4d6f6f88 Mon Sep 17 00:00:00 2001 From: Vaxry Date: Sat, 9 Nov 2024 02:26:24 +0000 Subject: [PATCH 0612/2181] popup: minor cleanups don't iterate over unmapped popups in breadthfirst, don't refocus if it wasnt in focus ref #8293 --- src/desktop/Popup.cpp | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/src/desktop/Popup.cpp b/src/desktop/Popup.cpp index 58995f00..ea6e877b 100644 --- a/src/desktop/Popup.cpp +++ b/src/desktop/Popup.cpp @@ -4,6 +4,8 @@ #include "../protocols/LayerShell.hpp" #include "../protocols/XDGShell.hpp" #include "../protocols/core/Compositor.hpp" +#include "../managers/SeatManager.hpp" +#include "../managers/eventLoop/EventLoopManager.hpp" #include CPopup::CPopup(PHLWINDOW pOwner) : m_pWindowOwner(pOwner) { @@ -106,6 +108,8 @@ void CPopup::onUnmap() { return; } + m_bMapped = false; + m_vLastSize = m_pResource->surface->surface->current.size; const auto COORDS = coordsGlobal(); @@ -116,8 +120,6 @@ void CPopup::onUnmap() { m_pSubsurfaceHead.reset(); - g_pInputManager->simulateMouseMovement(); - if (!m_pLayerOwner.expired() && m_pLayerOwner->layer < ZWLR_LAYER_SHELL_V1_LAYER_TOP) g_pHyprOpenGL->markBlurDirtyForMonitor(g_pCompositor->getMonitorFromID(m_pLayerOwner->layer)); @@ -131,6 +133,11 @@ void CPopup::onUnmap() { g_pHyprRenderer->damageBox(&box); }, nullptr); + + const bool WASLASTFOCUS = g_pSeatManager->state.keyboardFocus == m_pWLSurface->resource() || g_pSeatManager->state.pointerFocus == m_pWLSurface->resource(); + + if (WASLASTFOCUS) + g_pInputManager->simulateMouseMovement(); } void CPopup::onCommit(bool ignoreSiblings) { @@ -317,7 +324,7 @@ CPopup* CPopup::at(const Vector2D& globalCoords, bool allowsInput) { breadthfirst([](CPopup* popup, void* data) { ((std::vector*)data)->push_back(popup); }, &popups); for (auto const& p : popups | std::views::reverse) { - if (!p->m_pResource) + if (!p->m_pResource || !p->m_bMapped) continue; if (!allowsInput) { From b9c439a55e5ecef563657da211bc10ddc3273a1c Mon Sep 17 00:00:00 2001 From: Vaxry Date: Sat, 9 Nov 2024 02:27:01 +0000 Subject: [PATCH 0613/2181] compositor: make sure we don't ret early on no surface if there is no implicit surface passed, make sure the current focus is not null, otherwise we nope early without focusing the window fixes #8293 --- src/Compositor.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Compositor.cpp b/src/Compositor.cpp index 495a2d85..da20c5cf 100644 --- a/src/Compositor.cpp +++ b/src/Compositor.cpp @@ -1062,7 +1062,7 @@ void CCompositor::focusWindow(PHLWINDOW pWindow, SP pSurface return; } - if (m_pLastWindow.lock() == pWindow && g_pSeatManager->state.keyboardFocus == pSurface) + if (m_pLastWindow.lock() == pWindow && g_pSeatManager->state.keyboardFocus == pSurface && g_pSeatManager->state.keyboardFocus) return; if (pWindow->m_bPinned) From cca227a53e10b9101d2fbcfb99e6360b416d7168 Mon Sep 17 00:00:00 2001 From: Vaxry Date: Sat, 9 Nov 2024 02:34:04 +0000 Subject: [PATCH 0614/2181] tablet: use inputMgr unified naming scheme ref #8301 --- src/desktop/LayerSurface.cpp | 7 +++++-- src/managers/input/Tablets.cpp | 6 +++--- 2 files changed, 8 insertions(+), 5 deletions(-) diff --git a/src/desktop/LayerSurface.cpp b/src/desktop/LayerSurface.cpp index 31c2482a..cd1c4742 100644 --- a/src/desktop/LayerSurface.cpp +++ b/src/desktop/LayerSurface.cpp @@ -326,8 +326,11 @@ void CLayerSurface::onCommit() { [&WASLASTFOCUS](SP surf, const Vector2D& offset, void* data) { WASLASTFOCUS = WASLASTFOCUS || g_pSeatManager->state.keyboardFocus == surf; }, nullptr); if (!WASLASTFOCUS && popupHead) { - popupHead->breadthfirst([&WASLASTFOCUS](CPopup* popup, void* data) { WASLASTFOCUS = WASLASTFOCUS || (popup->m_pWLSurface && g_pSeatManager->state.keyboardFocus == popup->m_pWLSurface->resource()); }, - nullptr); + popupHead->breadthfirst( + [&WASLASTFOCUS](CPopup* popup, void* data) { + WASLASTFOCUS = WASLASTFOCUS || (popup->m_pWLSurface && g_pSeatManager->state.keyboardFocus == popup->m_pWLSurface->resource()); + }, + nullptr); } const bool WASEXCLUSIVE = interactivity == ZWLR_LAYER_SURFACE_V1_KEYBOARD_INTERACTIVITY_EXCLUSIVE; const bool ISEXCLUSIVE = layerSurface->current.interactivity == ZWLR_LAYER_SURFACE_V1_KEYBOARD_INTERACTIVITY_EXCLUSIVE; diff --git a/src/managers/input/Tablets.cpp b/src/managers/input/Tablets.cpp index 3884afec..36bd5636 100644 --- a/src/managers/input/Tablets.cpp +++ b/src/managers/input/Tablets.cpp @@ -201,7 +201,7 @@ void CInputManager::newTablet(SP pDevice) { m_vHIDs.push_back(PNEWTABLET); try { - PNEWTABLET->hlName = deviceNameToInternalString(pDevice->getName()); + PNEWTABLET->hlName = g_pInputManager->getNameForNewDevice(pDevice->getName()); } catch (std::exception& e) { Debug::log(ERR, "Tablet had no name???"); // logic error } @@ -229,7 +229,7 @@ SP CInputManager::ensureTabletToolPresent(SPhlName = deviceNameToInternalString(pTool->getName()); + PTOOL->hlName = g_pInputManager->getNameForNewDevice(pTool->getName()); } catch (std::exception& e) { Debug::log(ERR, "Tablet had no name???"); // logic error } @@ -249,7 +249,7 @@ void CInputManager::newTabletPad(SP pDevice) { m_vHIDs.push_back(PNEWPAD); try { - PNEWPAD->hlName = deviceNameToInternalString(pDevice->getName()); + PNEWPAD->hlName = g_pInputManager->getNameForNewDevice(pDevice->getName()); } catch (std::exception& e) { Debug::log(ERR, "Pad had no name???"); // logic error } From a425fbebe4cf4238e48a42f724ef2208959d66cf Mon Sep 17 00:00:00 2001 From: Vaxry Date: Sat, 9 Nov 2024 14:27:47 +0000 Subject: [PATCH 0615/2181] version: bump to 0.45.0 --- VERSION | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/VERSION b/VERSION index a8ab6c96..bcce5d06 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -0.44.0 +0.45.0 From dca75db127fedc58fc85ae0e6e47162e3d5d16f9 Mon Sep 17 00:00:00 2001 From: Vaxry Date: Sat, 9 Nov 2024 16:56:43 +0000 Subject: [PATCH 0616/2181] defaultConfig: fixup smart gaps rules --- example/hyprland.conf | 9 +++------ src/config/defaultConfig.hpp | 9 +++------ 2 files changed, 6 insertions(+), 12 deletions(-) diff --git a/example/hyprland.conf b/example/hyprland.conf index edeeac01..fe1a831a 100644 --- a/example/hyprland.conf +++ b/example/hyprland.conf @@ -136,13 +136,10 @@ animations { # Ref https://wiki.hyprland.org/Configuring/Workspace-Rules/ # "Smart gaps" / "No gaps when only" # uncomment all if you wish to use that. -# workspace = w[t1], gapsout:0, gapsin:0 -# workspace = w[tg1], gapsout:0, gapsin:0 +# workspace = w[tv1], gapsout:0, gapsin:0 # workspace = f[1], gapsout:0, gapsin:0 -# windowrulev2 = bordersize 0, floating:0, onworkspace:w[t1] -# windowrulev2 = rounding 0, floating:0, onworkspace:w[t1] -# windowrulev2 = bordersize 0, floating:0, onworkspace:w[tg1] -# windowrulev2 = rounding 0, floating:0, onworkspace:w[tg1] +# windowrulev2 = bordersize 0, floating:0, onworkspace:w[tv1] +# windowrulev2 = rounding 0, floating:0, onworkspace:w[tv1] # windowrulev2 = bordersize 0, floating:0, onworkspace:f[1] # windowrulev2 = rounding 0, floating:0, onworkspace:f[1] diff --git a/src/config/defaultConfig.hpp b/src/config/defaultConfig.hpp index 02781770..d680e92b 100644 --- a/src/config/defaultConfig.hpp +++ b/src/config/defaultConfig.hpp @@ -149,13 +149,10 @@ animations { # Ref https://wiki.hyprland.org/Configuring/Workspace-Rules/ # "Smart gaps" / "No gaps when only" # uncomment all if you wish to use that. -# workspace = w[t1], gapsout:0, gapsin:0 -# workspace = w[tg1], gapsout:0, gapsin:0 +# workspace = w[tv1], gapsout:0, gapsin:0 # workspace = f[1], gapsout:0, gapsin:0 -# windowrulev2 = bordersize 0, floating:0, onworkspace:w[t1] -# windowrulev2 = rounding 0, floating:0, onworkspace:w[t1] -# windowrulev2 = bordersize 0, floating:0, onworkspace:w[tg1] -# windowrulev2 = rounding 0, floating:0, onworkspace:w[tg1] +# windowrulev2 = bordersize 0, floating:0, onworkspace:w[tv1] +# windowrulev2 = rounding 0, floating:0, onworkspace:w[tv1] # windowrulev2 = bordersize 0, floating:0, onworkspace:f[1] # windowrulev2 = rounding 0, floating:0, onworkspace:f[1] From a8ff3a452c1c445d24bdd9e7e4fcd66c8ef2a147 Mon Sep 17 00:00:00 2001 From: Vaxry Date: Sat, 9 Nov 2024 17:11:38 +0000 Subject: [PATCH 0617/2181] core: move to os/Process from hyprutils nix bump too --- CMakeLists.txt | 2 +- flake.lock | 6 +++--- hyprpm/CMakeLists.txt | 2 +- hyprpm/src/core/PluginManager.cpp | 19 ++++++++----------- src/helpers/MiscFunctions.cpp | 20 ++++++++------------ 5 files changed, 21 insertions(+), 28 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 877ba461..1ac2e10f 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -101,7 +101,7 @@ else() endif() find_package(OpenGL REQUIRED COMPONENTS ${GLES_VERSION}) -pkg_check_modules(hyprctl_deps REQUIRED IMPORTED_TARGET hyprutils>=0.2.1) +pkg_check_modules(hyprctl_deps REQUIRED IMPORTED_TARGET hyprutils>=0.2.4) pkg_check_modules(aquamarine_dep REQUIRED IMPORTED_TARGET aquamarine>=0.4.2) diff --git a/flake.lock b/flake.lock index b9055015..47254052 100644 --- a/flake.lock +++ b/flake.lock @@ -151,11 +151,11 @@ ] }, "locked": { - "lastModified": 1730968903, - "narHash": "sha256-zFvzLXcSm0Ia4XI1SE4FQ9KE63hlGrRWhLtwMolWuR8=", + "lastModified": 1731163338, + "narHash": "sha256-Qflei0JBeqQ0c8jxA8e982xAxJvfMwfx4Aci2eJi84s=", "owner": "hyprwm", "repo": "hyprutils", - "rev": "3ce0cde8709cdacbfba471f8e828433b58a561e9", + "rev": "60d3dece30f98e8ad85131829c8529950630d6bc", "type": "github" }, "original": { diff --git a/hyprpm/CMakeLists.txt b/hyprpm/CMakeLists.txt index 692e8da1..65935638 100644 --- a/hyprpm/CMakeLists.txt +++ b/hyprpm/CMakeLists.txt @@ -9,7 +9,7 @@ file(GLOB_RECURSE SRCFILES CONFIGURE_DEPENDS "src/*.cpp") set(CMAKE_CXX_STANDARD 23) -pkg_check_modules(deps REQUIRED IMPORTED_TARGET tomlplusplus hyprutils>=0.1.1) +pkg_check_modules(deps REQUIRED IMPORTED_TARGET tomlplusplus hyprutils>=0.2.4) add_executable(hyprpm ${SRCFILES}) diff --git a/hyprpm/src/core/PluginManager.cpp b/hyprpm/src/core/PluginManager.cpp index 57c67641..159b9cd6 100644 --- a/hyprpm/src/core/PluginManager.cpp +++ b/hyprpm/src/core/PluginManager.cpp @@ -23,22 +23,19 @@ #include #include +#include using namespace Hyprutils::String; +using namespace Hyprutils::OS; static std::string execAndGet(std::string cmd) { cmd += " 2>&1"; - std::array buffer; - std::string result; - using PcloseType = int (*)(FILE*); - const std::unique_ptr pipe(popen(cmd.c_str(), "r"), static_cast(pclose)); - if (!pipe) - return ""; - result.reserve(buffer.size()); - while (fgets(buffer.data(), buffer.size(), pipe.get()) != nullptr) { - result += buffer.data(); - } - return result; + CProcess proc("/bin/sh", {cmd}); + + if (!proc.runSync()) + return "error"; + + return proc.stdOut(); } SHyprlandVersion CPluginManager::getHyprlandVersion() { diff --git a/src/helpers/MiscFunctions.cpp b/src/helpers/MiscFunctions.cpp index 878f5ca1..75154796 100644 --- a/src/helpers/MiscFunctions.cpp +++ b/src/helpers/MiscFunctions.cpp @@ -17,7 +17,9 @@ #include #endif #include +#include using namespace Hyprutils::String; +using namespace Hyprutils::OS; #if defined(__DragonFly__) || defined(__FreeBSD__) || defined(__NetBSD__) || defined(__OpenBSD__) #include @@ -583,18 +585,12 @@ float vecToRectDistanceSquared(const Vector2D& vec, const Vector2D& p1, const Ve // Execute a shell command and get the output std::string execAndGet(const char* cmd) { - std::array buffer; - std::string result; - using PcloseType = int (*)(FILE*); - const std::unique_ptr pipe(popen(cmd, "r"), static_cast(pclose)); - if (!pipe) { - Debug::log(ERR, "execAndGet: failed in pipe"); - return ""; - } - while (fgets(buffer.data(), buffer.size(), pipe.get()) != nullptr) { - result += buffer.data(); - } - return result; + CProcess proc("/bin/sh", {cmd}); + + if (!proc.runSync()) + return "error"; + + return proc.stdOut(); } void logSystemInfo() { From 99b01c5d124d08648d4c9e6754485ea585c42707 Mon Sep 17 00:00:00 2001 From: Vaxry Date: Sun, 10 Nov 2024 15:54:00 +0000 Subject: [PATCH 0618/2181] hyprpm: fix format --- hyprpm/src/core/PluginManager.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/hyprpm/src/core/PluginManager.cpp b/hyprpm/src/core/PluginManager.cpp index 159b9cd6..ef77f540 100644 --- a/hyprpm/src/core/PluginManager.cpp +++ b/hyprpm/src/core/PluginManager.cpp @@ -31,7 +31,7 @@ static std::string execAndGet(std::string cmd) { cmd += " 2>&1"; CProcess proc("/bin/sh", {cmd}); - + if (!proc.runSync()) return "error"; From 9e628067fc54851dc9138c2882abb21f72c5a5a6 Mon Sep 17 00:00:00 2001 From: WavyEbuilder Date: Sun, 10 Nov 2024 15:54:15 +0000 Subject: [PATCH 0619/2181] debug: clean up opening of files in HyprCtl (#8401) `std::ifstream` is more suited than `execAndGet` here. --- src/debug/HyprCtl.cpp | 23 ++++++++++++++++++++--- 1 file changed, 20 insertions(+), 3 deletions(-) diff --git a/src/debug/HyprCtl.cpp b/src/debug/HyprCtl.cpp index 3e0c75a6..709d8b69 100644 --- a/src/debug/HyprCtl.cpp +++ b/src/debug/HyprCtl.cpp @@ -1,6 +1,7 @@ #include "HyprCtl.hpp" #include +#include #include #include #include @@ -949,11 +950,27 @@ std::string systemInfoRequest(eHyprCtlOutputFormat format, std::string request) const std::string GPUINFO = execAndGet("lspci -vnn | grep VGA"); #endif result += "GPU information: \n" + GPUINFO; - if (GPUINFO.contains("NVIDIA") && std::filesystem::exists("/proc/driver/nvidia/version")) - result += execAndGet("cat /proc/driver/nvidia/version | grep NVRM"); + if (GPUINFO.contains("NVIDIA") && std::filesystem::exists("/proc/driver/nvidia/version")) { + std::ifstream file("/proc/driver/nvidia/version"); + std::string line; + if (file.is_open()) { + while (std::getline(file, line)) { + if (!line.contains("NVRM")) + continue; + result += line; + result += "\n"; + } + } else + result += "error"; + } result += "\n\n"; - result += "os-release: " + execAndGet("cat /etc/os-release") + "\n\n"; + if (std::ifstream file("/etc/os-release"); file.is_open()) { + std::stringstream buffer; + buffer << file.rdbuf(); + result += "os-release: " + buffer.str() + "\n\n"; + } else + result += "os-release: error\n\n"; result += "plugins:\n"; if (g_pPluginSystem) { From c10739e6e35c30ef5f273bfe5d219d361a31e226 Mon Sep 17 00:00:00 2001 From: Vaxry Date: Sun, 10 Nov 2024 22:53:11 +0000 Subject: [PATCH 0620/2181] core: fixup execAndGet fixes #8410 --- hyprpm/src/core/PluginManager.cpp | 2 +- src/helpers/MiscFunctions.cpp | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/hyprpm/src/core/PluginManager.cpp b/hyprpm/src/core/PluginManager.cpp index ef77f540..051ad500 100644 --- a/hyprpm/src/core/PluginManager.cpp +++ b/hyprpm/src/core/PluginManager.cpp @@ -30,7 +30,7 @@ using namespace Hyprutils::OS; static std::string execAndGet(std::string cmd) { cmd += " 2>&1"; - CProcess proc("/bin/sh", {cmd}); + CProcess proc("/bin/sh", {"-c", cmd}); if (!proc.runSync()) return "error"; diff --git a/src/helpers/MiscFunctions.cpp b/src/helpers/MiscFunctions.cpp index 75154796..7b4d63a7 100644 --- a/src/helpers/MiscFunctions.cpp +++ b/src/helpers/MiscFunctions.cpp @@ -585,7 +585,7 @@ float vecToRectDistanceSquared(const Vector2D& vec, const Vector2D& p1, const Ve // Execute a shell command and get the output std::string execAndGet(const char* cmd) { - CProcess proc("/bin/sh", {cmd}); + CProcess proc("/bin/sh", {"-c", cmd}); if (!proc.runSync()) return "error"; From 1fa0cd7a7574c8e93c567bf0453c155285dd3960 Mon Sep 17 00:00:00 2001 From: WavyEbuilder Date: Mon, 11 Nov 2024 13:44:41 +0000 Subject: [PATCH 0621/2181] debug: clean up fetching of the contents of /proc/device-tree (#8413) --- src/debug/HyprCtl.cpp | 21 ++++++++++++++++++++- 1 file changed, 20 insertions(+), 1 deletion(-) diff --git a/src/debug/HyprCtl.cpp b/src/debug/HyprCtl.cpp index 709d8b69..6429e781 100644 --- a/src/debug/HyprCtl.cpp +++ b/src/debug/HyprCtl.cpp @@ -1,7 +1,9 @@ #include "HyprCtl.hpp" +#include #include #include +#include #include #include #include @@ -945,7 +947,24 @@ std::string systemInfoRequest(eHyprCtlOutputFormat format, std::string request) #if defined(__DragonFly__) || defined(__FreeBSD__) const std::string GPUINFO = execAndGet("pciconf -lv | fgrep -A4 vga"); #elif defined(__arm__) || defined(__aarch64__) - const std::string GPUINFO = execAndGet("cat /proc/device-tree/soc*/gpu*/compatible"); + std::string GPUINFO; + const std::filesystem::path dev_tree = "/proc/device-tree"; + try { + if (std::filesystem::exists(dev_tree) && std::filesystem::is_directory(dev_tree)) { + std::for_each(std::filesystem::directory_iterator(dev_tree), std::filesystem::directory_iterator{}, [&](const std::filesystem::directory_entry& entry) { + if (std::filesystem::is_directory(entry) && entry.path().filename().string().starts_with("soc")) { + std::for_each(std::filesystem::directory_iterator(entry.path()), std::filesystem::directory_iterator{}, [&](const std::filesystem::directory_entry& sub_entry) { + if (std::filesystem::is_directory(sub_entry) && sub_entry.path().filename().string().starts_with("gpu")) { + std::filesystem::path file_path = sub_entry.path() / "compatible"; + std::ifstream file(file_path); + if (file) + GPUINFO.append(std::istreambuf_iterator(file), std::istreambuf_iterator()); + } + }); + } + }); + } + } catch (...) { GPUINFO = "error"; } #else const std::string GPUINFO = execAndGet("lspci -vnn | grep VGA"); #endif From 07052a515bea46e8b01d3ca5b2c284c272c5ed34 Mon Sep 17 00:00:00 2001 From: JManch <61563764+JManch@users.noreply.github.com> Date: Mon, 11 Nov 2024 13:45:33 +0000 Subject: [PATCH 0622/2181] pointer: map devices across all outputs by default (#8352) --- src/config/ConfigDescriptions.hpp | 10 +++- src/config/ConfigManager.cpp | 2 + src/devices/Tablet.hpp | 3 +- src/devices/VirtualPointer.cpp | 2 +- src/managers/PointerManager.cpp | 76 ++++++++++++++--------------- src/managers/input/InputManager.cpp | 3 ++ 6 files changed, 53 insertions(+), 43 deletions(-) diff --git a/src/config/ConfigDescriptions.hpp b/src/config/ConfigDescriptions.hpp index 12e81f2a..fde8173d 100644 --- a/src/config/ConfigDescriptions.hpp +++ b/src/config/ConfigDescriptions.hpp @@ -620,16 +620,22 @@ inline static const std::vector CONFIG_OPTIONS = { }, SConfigOptionDescription{ .value = "input:tablet:output", - .description = "the monitor to bind tablets. Empty means unbound..", + .description = "the monitor to bind tablets. Can be current or a monitor name. Leave empty to map across all monitors.", .type = CONFIG_OPTION_STRING_SHORT, .data = SConfigOptionDescription::SStringData{""}, //##TODO UNSET? }, SConfigOptionDescription{ .value = "input:tablet:region_position", - .description = "position of the mapped region in monitor layout.", + .description = "position of the mapped region in monitor layout relative to the top left corner of the bound monitor or all monitors.", .type = CONFIG_OPTION_VECTOR, .data = SConfigOptionDescription::SVectorData{{}, {-20000, -20000}, {20000, 20000}}, }, + SConfigOptionDescription{ + .value = "input:tablet:absolute_region_position", + .description = "whether to treat the region_position as an absolute position in monitor layout. Only applies when output is empty.", + .type = CONFIG_OPTION_BOOL, + .data = SConfigOptionDescription::SBoolData{false}, + }, SConfigOptionDescription{ .value = "input:tablet:region_size", .description = "size of the mapped region. When this variable is set, tablet input will be mapped to the region. [0, 0] or invalid size means unset.", diff --git a/src/config/ConfigManager.cpp b/src/config/ConfigManager.cpp index 769a7525..fbbc8dbd 100644 --- a/src/config/ConfigManager.cpp +++ b/src/config/ConfigManager.cpp @@ -516,6 +516,7 @@ CConfigManager::CConfigManager() { m_pConfig->addConfigValue("input:tablet:transform", Hyprlang::INT{0}); m_pConfig->addConfigValue("input:tablet:output", {STRVAL_EMPTY}); m_pConfig->addConfigValue("input:tablet:region_position", Hyprlang::VEC2{0, 0}); + m_pConfig->addConfigValue("input:tablet:absolute_region_position", Hyprlang::INT{0}); m_pConfig->addConfigValue("input:tablet:region_size", Hyprlang::VEC2{0, 0}); m_pConfig->addConfigValue("input:tablet:relative_input", Hyprlang::INT{0}); m_pConfig->addConfigValue("input:tablet:left_handed", Hyprlang::INT{0}); @@ -625,6 +626,7 @@ CConfigManager::CConfigManager() { m_pConfig->addSpecialConfigValue("device", "output", {STRVAL_EMPTY}); m_pConfig->addSpecialConfigValue("device", "enabled", Hyprlang::INT{1}); // only for mice, touchpads, and touchdevices m_pConfig->addSpecialConfigValue("device", "region_position", Hyprlang::VEC2{0, 0}); // only for tablets + m_pConfig->addSpecialConfigValue("device", "absolute_region_position", Hyprlang::INT{0}); // only for tablets m_pConfig->addSpecialConfigValue("device", "region_size", Hyprlang::VEC2{0, 0}); // only for tablets m_pConfig->addSpecialConfigValue("device", "relative_input", Hyprlang::INT{0}); // only for tablets m_pConfig->addSpecialConfigValue("device", "active_area_position", Hyprlang::VEC2{0, 0}); // only for tablets diff --git a/src/devices/Tablet.hpp b/src/devices/Tablet.hpp index 4894ac8e..8f49c984 100644 --- a/src/devices/Tablet.hpp +++ b/src/devices/Tablet.hpp @@ -92,9 +92,10 @@ class CTablet : public IHID { WP self; bool relativeInput = false; + bool absolutePos = false; std::string boundOutput = ""; CBox activeArea; - CBox boundBox; // output-local + CBox boundBox; private: CTablet(SP tablet); diff --git a/src/devices/VirtualPointer.cpp b/src/devices/VirtualPointer.cpp index 7ad18775..514c8c32 100644 --- a/src/devices/VirtualPointer.cpp +++ b/src/devices/VirtualPointer.cpp @@ -38,7 +38,7 @@ CVirtualPointer::CVirtualPointer(SP resource) : point listeners.holdBegin = pointer->events.holdBegin.registerListener([this](std::any d) { pointerEvents.holdBegin.emit(d); }); listeners.holdEnd = pointer->events.holdEnd.registerListener([this](std::any d) { pointerEvents.holdEnd.emit(d); }); - boundOutput = resource->boundOutput ? resource->boundOutput->szName : "entire"; + boundOutput = resource->boundOutput ? resource->boundOutput->szName : ""; deviceName = pointer->name; } diff --git a/src/managers/PointerManager.cpp b/src/managers/PointerManager.cpp index b309ba82..75be235f 100644 --- a/src/managers/PointerManager.cpp +++ b/src/managers/PointerManager.cpp @@ -668,9 +668,7 @@ void CPointerManager::move(const Vector2D& deltaLogical) { } void CPointerManager::warpAbsolute(Vector2D abs, SP dev) { - - PHLMONITOR currentMonitor = g_pCompositor->m_pLastMonitor.lock(); - if (!currentMonitor || !dev) + if (!dev) return; if (!std::isnan(abs.x)) @@ -678,20 +676,44 @@ void CPointerManager::warpAbsolute(Vector2D abs, SP dev) { if (!std::isnan(abs.y)) abs.y = std::clamp(abs.y, 0.0, 1.0); - // in logical global - CBox mappedArea = currentMonitor->logicalBox(); + // find x and y size of the entire space + const auto& MONITORS = g_pCompositor->m_vMonitors; + Vector2D topLeft = MONITORS.at(0)->vecPosition, bottomRight = MONITORS.at(0)->vecPosition + MONITORS.at(0)->vecSize; + for (size_t i = 1; i < MONITORS.size(); ++i) { + const auto EXTENT = MONITORS[i]->logicalBox().extent(); + const auto POS = MONITORS[i]->logicalBox().pos(); + if (EXTENT.x > bottomRight.x) + bottomRight.x = EXTENT.x; + if (EXTENT.y > bottomRight.y) + bottomRight.y = EXTENT.y; + if (POS.x < topLeft.x) + topLeft.x = POS.x; + if (POS.y < topLeft.y) + topLeft.y = POS.y; + } + CBox mappedArea = {topLeft, bottomRight - topLeft}; + + auto outputMappedArea = [&mappedArea](const std::string& output) { + if (output == "current") { + if (const auto PLASTMONITOR = g_pCompositor->m_pLastMonitor.lock(); PLASTMONITOR) + return PLASTMONITOR->logicalBox(); + } else if (const auto PMONITOR = g_pCompositor->getMonitorFromString(output); PMONITOR) + return PMONITOR->logicalBox(); + return mappedArea; + }; switch (dev->getType()) { case HID_TYPE_TABLET: { CTablet* TAB = reinterpret_cast(dev.get()); if (!TAB->boundOutput.empty()) { - if (const auto PMONITOR = g_pCompositor->getMonitorFromString(TAB->boundOutput); PMONITOR) { - currentMonitor = PMONITOR->self.lock(); - mappedArea = currentMonitor->logicalBox(); - } - } + mappedArea = outputMappedArea(TAB->boundOutput); + mappedArea.translate(TAB->boundBox.pos()); + } else if (TAB->absolutePos) { + mappedArea.x = TAB->boundBox.x; + mappedArea.y = TAB->boundBox.y; + } else + mappedArea.translate(TAB->boundBox.pos()); - mappedArea.translate(TAB->boundBox.pos()); if (!TAB->boundBox.empty()) { mappedArea.w = TAB->boundBox.w; mappedArea.h = TAB->boundBox.h; @@ -700,38 +722,14 @@ void CPointerManager::warpAbsolute(Vector2D abs, SP dev) { } case HID_TYPE_TOUCH: { ITouch* TOUCH = reinterpret_cast(dev.get()); - if (!TOUCH->boundOutput.empty()) { - if (const auto PMONITOR = g_pCompositor->getMonitorFromString(TOUCH->boundOutput); PMONITOR) { - currentMonitor = PMONITOR->self.lock(); - mappedArea = currentMonitor->logicalBox(); - } - } + if (!TOUCH->boundOutput.empty()) + mappedArea = outputMappedArea(TOUCH->boundOutput); break; } case HID_TYPE_POINTER: { IPointer* POINTER = reinterpret_cast(dev.get()); - if (!POINTER->boundOutput.empty()) { - if (POINTER->boundOutput == "entire") { - // find x and y size of the entire space - Vector2D bottomRight = {-9999999, -9999999}, topLeft = {9999999, 9999999}; - for (auto const& m : g_pCompositor->m_vMonitors) { - const auto EXTENT = m->logicalBox().extent(); - const auto POS = m->logicalBox().pos(); - if (EXTENT.x > bottomRight.x) - bottomRight.x = EXTENT.x; - if (EXTENT.y > bottomRight.y) - bottomRight.y = EXTENT.y; - if (POS.x < topLeft.x) - topLeft.x = POS.x; - if (POS.y < topLeft.y) - topLeft.y = POS.y; - } - mappedArea = {topLeft, bottomRight - topLeft}; - } else if (const auto PMONITOR = g_pCompositor->getMonitorFromString(POINTER->boundOutput); PMONITOR) { - currentMonitor = PMONITOR->self.lock(); - mappedArea = currentMonitor->logicalBox(); - } - } + if (!POINTER->boundOutput.empty()) + mappedArea = outputMappedArea(POINTER->boundOutput); break; } default: break; diff --git a/src/managers/input/InputManager.cpp b/src/managers/input/InputManager.cpp index c190f589..9110cd15 100644 --- a/src/managers/input/InputManager.cpp +++ b/src/managers/input/InputManager.cpp @@ -1595,6 +1595,9 @@ void CInputManager::setTabletConfigs() { const auto REGION_SIZE = g_pConfigManager->getDeviceVec(NAME, "region_size", "input:tablet:region_size"); t->boundBox = {REGION_POS, REGION_SIZE}; + const auto ABSOLUTE_REGION_POS = g_pConfigManager->getDeviceInt(NAME, "absolute_region_position", "input:tablet:absolute_region_position"); + t->absolutePos = ABSOLUTE_REGION_POS; + const auto ACTIVE_AREA_SIZE = g_pConfigManager->getDeviceVec(NAME, "active_area_size", "input:tablet:active_area_size"); const auto ACTIVE_AREA_POS = g_pConfigManager->getDeviceVec(NAME, "active_area_position", "input:tablet:active_area_position"); if (ACTIVE_AREA_SIZE.x != 0 || ACTIVE_AREA_SIZE.y != 0) { From a551f85b9129eac76a5f295ecfe4fb39f96f435c Mon Sep 17 00:00:00 2001 From: dawsers <47487972+dawsers@users.noreply.github.com> Date: Mon, 11 Nov 2024 14:48:50 +0100 Subject: [PATCH 0623/2181] renderer: scaled surfaces could have zero area (#8423) --- src/render/Renderer.cpp | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/render/Renderer.cpp b/src/render/Renderer.cpp index 469acda9..d98e32a9 100644 --- a/src/render/Renderer.cpp +++ b/src/render/Renderer.cpp @@ -222,6 +222,11 @@ static void renderSurface(SP surface, int x, int y, void* da windowBox.height = RDATA->h - y; } + const auto PROJSIZEUNSCALED = windowBox.size(); + + windowBox.scale(RDATA->pMonitor->scale); + windowBox.round(); + if (windowBox.width <= 1 || windowBox.height <= 1) { if (!g_pHyprRenderer->m_bBlockSurfaceFeedback) { Debug::log(TRACE, "presentFeedback for invisible surface"); @@ -231,11 +236,6 @@ static void renderSurface(SP surface, int x, int y, void* da return; // invisible } - const auto PROJSIZEUNSCALED = windowBox.size(); - - windowBox.scale(RDATA->pMonitor->scale); - windowBox.round(); - const bool MISALIGNEDFSV1 = std::floor(RDATA->pMonitor->scale) != RDATA->pMonitor->scale /* Fractional */ && surface->current.scale == 1 /* fs protocol */ && windowBox.size() != surface->current.bufferSize /* misaligned */ && DELTALESSTHAN(windowBox.width, surface->current.bufferSize.x, 3) && DELTALESSTHAN(windowBox.height, surface->current.bufferSize.y, 3) /* off by one-or-two */ && From 8fa4cfb7dfa0be52a66db5f3b13e0ecde3d78b41 Mon Sep 17 00:00:00 2001 From: Vaxry Date: Mon, 11 Nov 2024 13:55:32 +0000 Subject: [PATCH 0624/2181] keybinds: don't animate fullscreen size/pos changes coming in when fullscreen, don't animate the pos/size when switching to another fullscreen window, as they can look weird and distracting. Ideally we would do it differently but it's not really possible to do well without reading minds --- src/managers/KeybindManager.cpp | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/src/managers/KeybindManager.cpp b/src/managers/KeybindManager.cpp index 5be6a1d9..f2fdab53 100644 --- a/src/managers/KeybindManager.cpp +++ b/src/managers/KeybindManager.cpp @@ -338,6 +338,10 @@ void CKeybindManager::switchToWindow(PHLWINDOW PWINDOWTOCHANGETO) { if (!PWINDOWTOCHANGETO->m_bPinned) g_pCompositor->setWindowFullscreenInternal(PWINDOWTOCHANGETO, MODE); + + // warp the position + size animation, otherwise it looks weird. + PWINDOWTOCHANGETO->m_vRealPosition.warp(); + PWINDOWTOCHANGETO->m_vRealSize.warp(); } else { updateRelativeCursorCoords(); g_pCompositor->focusWindow(PWINDOWTOCHANGETO); @@ -2110,6 +2114,10 @@ SDispatchResult CKeybindManager::focusWindow(std::string regexp) { if (FSWINDOW != PWINDOW && !PWINDOW->m_bPinned) g_pCompositor->setWindowFullscreenClient(PWINDOW, FSMODE); + + // warp the position + size animation, otherwise it looks weird. + PWINDOW->m_vRealPosition.warp(); + PWINDOW->m_vRealSize.warp(); } } else g_pCompositor->focusWindow(PWINDOW); From 430b5c302a358faf888a015a7a7009a824e62d99 Mon Sep 17 00:00:00 2001 From: izmyname <135810812+izmyname@users.noreply.github.com> Date: Thu, 7 Nov 2024 20:35:01 +0500 Subject: [PATCH 0625/2181] systemd: hyprland-systemd.desktop -> hyprland-uwsm.desktop Remove hyprland-session.service. --- systemd/hyprland-systemd.desktop | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/systemd/hyprland-systemd.desktop b/systemd/hyprland-systemd.desktop index 64ebbd47..2ed1031b 100644 --- a/systemd/hyprland-systemd.desktop +++ b/systemd/hyprland-systemd.desktop @@ -1,7 +1,6 @@ [Desktop Entry] -Name=Hyprland (systemd session) +Name=Hyprland (uwsm-managed) Comment=An intelligent dynamic tiling Wayland compositor -Exec=systemctl --user start --wait hyprland-session -Type=Application +Exec=uwsm start -N Hyprland -D Hyprland -C An_intelligent_dynamic_tiling_Wayland_compositor -- Hyprland DesktopNames=Hyprland -Keywords=tiling;wayland;compositor; +Type=Application From ccfae82ad1c1a97d06efe980d6ba0dd72be4116c Mon Sep 17 00:00:00 2001 From: Izmyname Date: Thu, 7 Nov 2024 21:01:12 +0500 Subject: [PATCH 0626/2181] rename hyprland-systemd.desktop and remove hyprland-session.service --- CMakeLists.txt | 10 ++-------- systemd/hyprland-session.service.in | 16 ---------------- ...and-systemd.desktop => hyprland-uwsm.desktop} | 0 systemd/meson.build | 14 +------------- 4 files changed, 3 insertions(+), 37 deletions(-) delete mode 100644 systemd/hyprland-session.service.in rename systemd/{hyprland-systemd.desktop => hyprland-uwsm.desktop} (100%) diff --git a/CMakeLists.txt b/CMakeLists.txt index 1ac2e10f..d337680f 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -222,16 +222,10 @@ if(NO_SYSTEMD) else() message(STATUS "SYSTEMD support is requested (NO_SYSTEMD not defined)...") add_compile_definitions(USES_SYSTEMD) - configure_file(systemd/hyprland-session.service.in - systemd/hyprland-session.service @ONLY) - # session file -systemd - install(FILES ${CMAKE_SOURCE_DIR}/systemd/hyprland-systemd.desktop + # session file -uwsm + install(FILES ${CMAKE_SOURCE_DIR}/systemd/hyprland-uwsm.desktop DESTINATION ${CMAKE_INSTALL_DATAROOTDIR}/wayland-sessions) - - # install systemd service - install(FILES ${CMAKE_BINARY_DIR}/systemd/hyprland-session.service - DESTINATION ${CMAKE_INSTALL_LIBDIR}/systemd/user) endif() set(CPACK_PROJECT_NAME ${PROJECT_NAME}) diff --git a/systemd/hyprland-session.service.in b/systemd/hyprland-session.service.in deleted file mode 100644 index dafdc141..00000000 --- a/systemd/hyprland-session.service.in +++ /dev/null @@ -1,16 +0,0 @@ -[Unit] -Description=Hyprland - Tiling compositor with the looks -Documentation=man:Hyprland(1) -BindsTo=graphical-session.target -Before=graphical-session.target -Wants=xdg-desktop-autostart.target -Wants=graphical-session-pre.target -After=graphical-session-pre.target - -[Service] -Type=notify -ExecStart=@PREFIX@/@BINDIR@/Hyprland -ExecStop=@PREFIX@/@BINDIR@/hyprctl dispatch exit -ExecStopPost=systemctl --user unset-environment DISPLAY WAYLAND_DISPLAY HYPRLAND_INSTANCE_SIGNATURE XDG_CURRENT_DESKTOP -Restart=on-failure -Slice=session.slice diff --git a/systemd/hyprland-systemd.desktop b/systemd/hyprland-uwsm.desktop similarity index 100% rename from systemd/hyprland-systemd.desktop rename to systemd/hyprland-uwsm.desktop diff --git a/systemd/meson.build b/systemd/meson.build index 2cd5312a..731f04e3 100644 --- a/systemd/meson.build +++ b/systemd/meson.build @@ -1,17 +1,5 @@ install_data( - 'hyprland-systemd.desktop', + 'hyprland-uwsm.desktop', install_dir: join_paths(get_option('datadir'), 'wayland-sessions'), install_tag: 'runtime', ) - -conf_data = configuration_data() -conf_data.set('PREFIX', get_option('prefix')) -conf_data.set('BINDIR', get_option('bindir')) -user_unit_dir = systemd.get_variable(pkgconfig: 'systemduserunitdir', - pkgconfig_define: ['prefix', get_option('prefix')]) - -configure_file( - configuration: conf_data, - input: 'hyprland-session.service.in', - output: '@BASENAME@', - install_dir: user_unit_dir ) From 943c7d18cc7c9300e1a6b4b859558b8c7ac540cd Mon Sep 17 00:00:00 2001 From: Mihai Fufezan Date: Mon, 11 Nov 2024 09:36:15 +0200 Subject: [PATCH 0627/2181] meson: autodetect systemd --- meson.build | 8 ++++++-- nix/default.nix | 1 - 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/meson.build b/meson.build index 76765645..e4abad36 100644 --- a/meson.build +++ b/meson.build @@ -52,8 +52,12 @@ backtrace_dep = cpp_compiler.find_library('execinfo', required: false) epoll_dep = dependency('epoll-shim', required: false) # timerfd on BSDs # Handle options -if get_option('systemd').enabled() - systemd = dependency('systemd') +systemd_option = get_option('systemd') +systemd = dependency('systemd', required: systemd_option) +systemd_option.enable_auto_if(systemd.found()) + +if (systemd_option.enabled()) + message('Enabling systemd integration') add_project_arguments('-DUSES_SYSTEMD', language: 'cpp') subdir('systemd') endif diff --git a/nix/default.nix b/nix/default.nix index 29d31485..90c92272 100644 --- a/nix/default.nix +++ b/nix/default.nix @@ -152,7 +152,6 @@ in (mapAttrsToList mesonEnable { "xwayland" = enableXWayland; "legacy_renderer" = legacyRenderer; - "systemd" = withSystemd; }) (mapAttrsToList mesonBool { "b_pch" = false; From ff411658e8b217cadf69887f7313d6fd2fc417f2 Mon Sep 17 00:00:00 2001 From: Mihai Fufezan Date: Mon, 11 Nov 2024 10:05:01 +0200 Subject: [PATCH 0628/2181] Lock uwsm desktop file behind feature flag The file in the repo cannot be used in NixOS due to missing full paths, and the fact that `uwsm` does not have access to `PATH` to find the listed binaries. Might be useful in other situations as well. --- CMakeLists.txt | 9 +++++++-- meson_options.txt | 1 + systemd/meson.build | 12 +++++++----- 3 files changed, 15 insertions(+), 7 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index d337680f..117932d0 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -224,8 +224,13 @@ else() add_compile_definitions(USES_SYSTEMD) # session file -uwsm - install(FILES ${CMAKE_SOURCE_DIR}/systemd/hyprland-uwsm.desktop - DESTINATION ${CMAKE_INSTALL_DATAROOTDIR}/wayland-sessions) + if(NO_UWSM) + message(STATUS "UWSM support is disabled...") + else() + message(STATUS "UWSM support is enabled (NO_UWSM not defined)...") + install(FILES ${CMAKE_SOURCE_DIR}/systemd/hyprland-uwsm.desktop + DESTINATION ${CMAKE_INSTALL_DATAROOTDIR}/wayland-sessions) + endif() endif() set(CPACK_PROJECT_NAME ${PROJECT_NAME}) diff --git a/meson_options.txt b/meson_options.txt index d8c9d5e6..9b64fb32 100644 --- a/meson_options.txt +++ b/meson_options.txt @@ -1,4 +1,5 @@ option('xwayland', type: 'feature', value: 'auto', description: 'Enable support for X11 applications') option('systemd', type: 'feature', value: 'auto', description: 'Enable systemd integration') +option('uwsm', type: 'feature', value: 'enabled', description: 'Enable uwsm integration (only if systemd is enabled)') option('legacy_renderer', type: 'feature', value: 'disabled', description: 'Enable legacy renderer') option('tracy_enable', type: 'boolean', value: false , description: 'Enable profiling') diff --git a/systemd/meson.build b/systemd/meson.build index 731f04e3..bc62e95a 100644 --- a/systemd/meson.build +++ b/systemd/meson.build @@ -1,5 +1,7 @@ -install_data( - 'hyprland-uwsm.desktop', - install_dir: join_paths(get_option('datadir'), 'wayland-sessions'), - install_tag: 'runtime', -) +if (get_option('uwsm').allowed()) + install_data( + 'hyprland-uwsm.desktop', + install_dir: join_paths(get_option('datadir'), 'wayland-sessions'), + install_tag: 'runtime', + ) +endif From b88e4a1a9a8a240d54a5006b35964c9e02f86f6b Mon Sep 17 00:00:00 2001 From: Mihai Fufezan Date: Mon, 11 Nov 2024 10:15:58 +0200 Subject: [PATCH 0629/2181] Nix: disable uwsm desktop file installation Will be enabled in the NixOS module. --- nix/default.nix | 1 + 1 file changed, 1 insertion(+) diff --git a/nix/default.nix b/nix/default.nix index 90c92272..69174d4d 100644 --- a/nix/default.nix +++ b/nix/default.nix @@ -152,6 +152,7 @@ in (mapAttrsToList mesonEnable { "xwayland" = enableXWayland; "legacy_renderer" = legacyRenderer; + "uwsm" = false; }) (mapAttrsToList mesonBool { "b_pch" = false; From f5fa84554ffe55e29a397014964238be89ffa54d Mon Sep 17 00:00:00 2001 From: nnra <104775644+nnra6864@users.noreply.github.com> Date: Mon, 11 Nov 2024 16:49:35 +0100 Subject: [PATCH 0630/2181] config: Changed the default value of decoration:blur:ignore_opacity to true (#8418) This change is made in order to deliver the blur look majority of people expect by default. --- src/config/ConfigDescriptions.hpp | 2 +- src/config/ConfigManager.cpp | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/config/ConfigDescriptions.hpp b/src/config/ConfigDescriptions.hpp index fde8173d..27bc3c2d 100644 --- a/src/config/ConfigDescriptions.hpp +++ b/src/config/ConfigDescriptions.hpp @@ -268,7 +268,7 @@ inline static const std::vector CONFIG_OPTIONS = { .value = "blur:ignore_opacity", .description = "make the blur layer ignore the opacity of the window", .type = CONFIG_OPTION_BOOL, - .data = SConfigOptionDescription::SBoolData{false}, + .data = SConfigOptionDescription::SBoolData{true}, }, SConfigOptionDescription{ .value = "blur:new_optimizations", diff --git a/src/config/ConfigManager.cpp b/src/config/ConfigManager.cpp index fbbc8dbd..b768fda3 100644 --- a/src/config/ConfigManager.cpp +++ b/src/config/ConfigManager.cpp @@ -417,7 +417,7 @@ CConfigManager::CConfigManager() { m_pConfig->addConfigValue("decoration:blur:enabled", Hyprlang::INT{1}); m_pConfig->addConfigValue("decoration:blur:size", Hyprlang::INT{8}); m_pConfig->addConfigValue("decoration:blur:passes", Hyprlang::INT{1}); - m_pConfig->addConfigValue("decoration:blur:ignore_opacity", Hyprlang::INT{0}); + m_pConfig->addConfigValue("decoration:blur:ignore_opacity", Hyprlang::INT{1}); m_pConfig->addConfigValue("decoration:blur:new_optimizations", Hyprlang::INT{1}); m_pConfig->addConfigValue("decoration:blur:xray", Hyprlang::INT{0}); m_pConfig->addConfigValue("decoration:blur:contrast", {0.8916F}); From a29cfa78431a054a093f3c843228bac6783a6d33 Mon Sep 17 00:00:00 2001 From: SoSeDiK Date: Tue, 12 Nov 2024 02:53:55 +0200 Subject: [PATCH 0631/2181] logging: Add some context to config error logs (#8326) --- src/config/ConfigManager.cpp | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/src/config/ConfigManager.cpp b/src/config/ConfigManager.cpp index b768fda3..e3d59874 100644 --- a/src/config/ConfigManager.cpp +++ b/src/config/ConfigManager.cpp @@ -1851,7 +1851,7 @@ static bool parseModeLine(const std::string& modeline, drmModeModeInfo& mode) { if (it != flagsmap.end()) mode.flags |= it->second; else - Debug::log(ERR, "invalid flag {} in modeline", key); + Debug::log(ERR, "Invalid flag {} in modeline", key); } snprintf(mode.name, sizeof(mode.name), "%dx%d@%d", mode.hdisplay, mode.vdisplay, mode.vrefresh / 1000); @@ -1874,7 +1874,7 @@ std::optional CConfigManager::handleMonitor(const std::string& comm else if (ARGS[1] == "transform") { const auto TSF = std::stoi(ARGS[2]); if (std::clamp(TSF, 0, 7) != TSF) { - Debug::log(ERR, "invalid transform {} in monitor", TSF); + Debug::log(ERR, "Invalid transform {} in monitor", TSF); return "invalid transform"; } @@ -2027,7 +2027,7 @@ std::optional CConfigManager::handleMonitor(const std::string& comm m_dWorkspaceRules.emplace_back(wsRule); argno++; } else { - Debug::log(ERR, "Config error: invalid monitor syntax"); + Debug::log(ERR, "Config error: invalid monitor syntax at \"{}\"", ARGS[argno]); return "invalid syntax at \"" + ARGS[argno] + "\""; } @@ -2247,12 +2247,12 @@ std::optional CConfigManager::handleBind(const std::string& command const auto DISPATCHER = g_pKeybindManager->m_mDispatchers.find(HANDLER); if (DISPATCHER == g_pKeybindManager->m_mDispatchers.end()) { - Debug::log(ERR, "Invalid dispatcher!"); + Debug::log(ERR, "Invalid dispatcher: {}", HANDLER); return "Invalid dispatcher, requested \"" + HANDLER + "\" does not exist"; } if (MOD == 0 && MODSTR != "") { - Debug::log(ERR, "Invalid mod!"); + Debug::log(ERR, "Invalid mod: {}", MODSTR); return "Invalid mod, requested mod \"" + MODSTR + "\" is not a valid mod."; } @@ -2696,7 +2696,7 @@ std::optional CConfigManager::handleSubmap(const std::string& comma std::optional CConfigManager::handleSource(const std::string& command, const std::string& rawpath) { if (rawpath.length() < 2) { Debug::log(ERR, "source= path garbage"); - return "source path " + rawpath + " bogus!"; + return "source= path " + rawpath + " bogus!"; } std::unique_ptr glob_buf{new glob_t, [](glob_t* g) { globfree(g); }}; memset(glob_buf.get(), 0, sizeof(glob_t)); @@ -2718,8 +2718,8 @@ std::optional CConfigManager::handleSource(const std::string& comma continue; } - Debug::log(ERR, "source= file doesnt exist"); - return "source file " + value + " doesn't exist!"; + Debug::log(ERR, "source= file doesn't exist: {}", value); + return "source= file " + value + " doesn't exist!"; } configPaths.push_back(value); From bb160cfe377da2d2b2e4431a3399fa60114f3911 Mon Sep 17 00:00:00 2001 From: Vaxry Date: Tue, 12 Nov 2024 15:26:25 +0000 Subject: [PATCH 0632/2181] makefile: add stub to discourage direct make --- Makefile | 3 +++ 1 file changed, 3 insertions(+) diff --git a/Makefile b/Makefile index 7cf21119..6c79b8db 100644 --- a/Makefile +++ b/Makefile @@ -1,5 +1,8 @@ PREFIX = /usr/local +stub: + @echo "Do not run $(MAKE) directly without any arguments. Please refer to the wiki on how to compile Hyprland." + legacyrenderer: cmake --no-warn-unused-cli -DCMAKE_BUILD_TYPE:STRING=Release -DCMAKE_INSTALL_PREFIX:STRING=${PREFIX} -DLEGACY_RENDERER:BOOL=true -S . -B ./build cmake --build ./build --config Release --target all -j`nproc 2>/dev/null || getconf NPROCESSORS_CONF` From 3fb47372b79265ebdabeeefdad10359d5b18377a Mon Sep 17 00:00:00 2001 From: Mihai Fufezan Date: Wed, 13 Nov 2024 21:34:52 +0200 Subject: [PATCH 0633/2181] flake.lock: update --- flake.lock | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/flake.lock b/flake.lock index 47254052..c1fcb70d 100644 --- a/flake.lock +++ b/flake.lock @@ -16,11 +16,11 @@ ] }, "locked": { - "lastModified": 1730968822, - "narHash": "sha256-NocDjINsh6ismkhb0Xr6xPRksmhuB2WGf8ZmXMhxu7Y=", + "lastModified": 1731496216, + "narHash": "sha256-nlQrNN+tmJ+iP6Ck/czwZI0Hxz3oNvUyGkVruxJwgwA=", "owner": "hyprwm", "repo": "aquamarine", - "rev": "a49bc3583ff223f426cb3526fdaa4bcaa247ec14", + "rev": "3b00e96f90cb0040de6d88ad99bf5f4d443f0c59", "type": "github" }, "original": { @@ -151,11 +151,11 @@ ] }, "locked": { - "lastModified": 1731163338, - "narHash": "sha256-Qflei0JBeqQ0c8jxA8e982xAxJvfMwfx4Aci2eJi84s=", + "lastModified": 1731518387, + "narHash": "sha256-aZZw1ZvTMLkcA6udlvkA3hrCkuipoWLy8s/JNnIclxY=", "owner": "hyprwm", "repo": "hyprutils", - "rev": "60d3dece30f98e8ad85131829c8529950630d6bc", + "rev": "315fba5d21d87ddb756d4bebdb49f99d86b0ffe8", "type": "github" }, "original": { @@ -189,11 +189,11 @@ }, "nixpkgs": { "locked": { - "lastModified": 1730785428, - "narHash": "sha256-Zwl8YgTVJTEum+L+0zVAWvXAGbWAuXHax3KzuejaDyo=", + "lastModified": 1731139594, + "narHash": "sha256-IigrKK3vYRpUu+HEjPL/phrfh7Ox881er1UEsZvw9Q4=", "owner": "NixOS", "repo": "nixpkgs", - "rev": "4aa36568d413aca0ea84a1684d2d46f55dbabad7", + "rev": "76612b17c0ce71689921ca12d9ffdc9c23ce40b2", "type": "github" }, "original": { @@ -229,11 +229,11 @@ "nixpkgs-stable": "nixpkgs-stable" }, "locked": { - "lastModified": 1730814269, - "narHash": "sha256-fWPHyhYE6xvMI1eGY3pwBTq85wcy1YXqdzTZF+06nOg=", + "lastModified": 1731363552, + "narHash": "sha256-vFta1uHnD29VUY4HJOO/D6p6rxyObnf+InnSMT4jlMU=", "owner": "cachix", "repo": "git-hooks.nix", - "rev": "d70155fdc00df4628446352fc58adc640cd705c2", + "rev": "cd1af27aa85026ac759d5d3fccf650abe7e1bbf0", "type": "github" }, "original": { From 20031cea92417a852410827a5cdb4adbcaee4342 Mon Sep 17 00:00:00 2001 From: Vaxry <43317083+vaxerski@users.noreply.github.com> Date: Thu, 14 Nov 2024 20:15:51 +0000 Subject: [PATCH 0634/2181] pointer: add drm dumb buffers for cursors (#8399) --------- Co-authored-by: Mihai Fufezan --- CMakeLists.txt | 2 +- meson.build | 2 +- src/config/ConfigManager.cpp | 2 +- src/managers/PointerManager.cpp | 132 ++++++++++++++++++------------ src/protocols/core/Compositor.cpp | 26 ++++-- src/protocols/core/Compositor.hpp | 2 +- src/render/Texture.cpp | 21 ++++- src/render/Texture.hpp | 34 ++++---- 8 files changed, 142 insertions(+), 79 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 117932d0..1cbd8b0a 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -103,7 +103,7 @@ find_package(OpenGL REQUIRED COMPONENTS ${GLES_VERSION}) pkg_check_modules(hyprctl_deps REQUIRED IMPORTED_TARGET hyprutils>=0.2.4) -pkg_check_modules(aquamarine_dep REQUIRED IMPORTED_TARGET aquamarine>=0.4.2) +pkg_check_modules(aquamarine_dep REQUIRED IMPORTED_TARGET aquamarine>=0.4.5) add_compile_definitions(AQUAMARINE_VERSION="${aquamarine_dep_VERSION}") diff --git a/meson.build b/meson.build index e4abad36..d825f184 100644 --- a/meson.build +++ b/meson.build @@ -31,7 +31,7 @@ if cpp_compiler.check_header('execinfo.h') add_project_arguments('-DHAS_EXECINFO', language: 'cpp') endif -aquamarine = dependency('aquamarine', version: '>=0.4.2') +aquamarine = dependency('aquamarine', version: '>=0.4.5') add_project_arguments(['-DAQUAMARINE_VERSION="@0@"'.format(aquamarine.version())], language: 'cpp') xcb_dep = dependency('xcb', required: get_option('xwayland')) diff --git a/src/config/ConfigManager.cpp b/src/config/ConfigManager.cpp index e3d59874..10299277 100644 --- a/src/config/ConfigManager.cpp +++ b/src/config/ConfigManager.cpp @@ -571,7 +571,7 @@ CConfigManager::CConfigManager() { m_pConfig->addConfigValue("cursor:sync_gsettings_theme", Hyprlang::INT{1}); m_pConfig->addConfigValue("cursor:hide_on_key_press", Hyprlang::INT{0}); m_pConfig->addConfigValue("cursor:hide_on_touch", Hyprlang::INT{1}); - m_pConfig->addConfigValue("cursor:allow_dumb_copy", Hyprlang::INT{0}); + m_pConfig->addConfigValue("cursor:use_cpu_buffer", Hyprlang::INT{0}); m_pConfig->addConfigValue("autogenerated", Hyprlang::INT{0}); diff --git a/src/managers/PointerManager.cpp b/src/managers/PointerManager.cpp index 75be235f..0580c9be 100644 --- a/src/managers/PointerManager.cpp +++ b/src/managers/PointerManager.cpp @@ -375,6 +375,8 @@ SP CPointerManager::renderHWCursorBuffer(SPmonitor->output->cursorPlaneSize(); auto const& cursorSize = currentCursorImage.size; + static auto PDUMB = CConfigValue("cursor:use_cpu_buffer"); + if (maxSize == Vector2D{}) return nullptr; @@ -386,10 +388,23 @@ SP CPointerManager::renderHWCursorBuffer(SPmonitor->cursorSwapchain || maxSize != state->monitor->cursorSwapchain->currentOptions().size) { + if (!state->monitor->cursorSwapchain || maxSize != state->monitor->cursorSwapchain->currentOptions().size || + *PDUMB != (state->monitor->cursorSwapchain->getAllocator()->type() != Aquamarine::AQ_ALLOCATOR_TYPE_GBM)) { - if (!state->monitor->cursorSwapchain) - state->monitor->cursorSwapchain = Aquamarine::CSwapchain::create(state->monitor->output->getBackend()->preferredAllocator(), state->monitor->output->getBackend()); + if (!state->monitor->cursorSwapchain || *PDUMB != (state->monitor->cursorSwapchain->getAllocator()->type() != Aquamarine::AQ_ALLOCATOR_TYPE_GBM)) { + + auto allocator = state->monitor->output->getBackend()->preferredAllocator(); + if (*PDUMB) { + for (const auto& a : state->monitor->output->getBackend()->getAllocators()) { + if (a->type() == Aquamarine::AQ_ALLOCATOR_TYPE_DRM_DUMB) { + allocator = a; + break; + } + } + } + + state->monitor->cursorSwapchain = Aquamarine::CSwapchain::create(allocator, state->monitor->output->getBackend()); + } auto options = state->monitor->cursorSwapchain->currentOptions(); options.size = maxSize; @@ -397,8 +412,10 @@ SP CPointerManager::renderHWCursorBuffer(SPmonitor->output->getBackend()->preferredAllocator()->drmFD() != g_pCompositor->m_iDRMFD; - // We do not set the format. If it's unset (DRM_FORMAT_INVALID) then the swapchain will pick for us, + // We do not set the format (unless shm). If it's unset (DRM_FORMAT_INVALID) then the swapchain will pick for us, // but if it's set, we don't wanna change it. + if (*PDUMB) + options.format = DRM_FORMAT_ARGB8888; if (!state->monitor->cursorSwapchain->reconfigure(options)) { Debug::log(TRACE, "Failed to reconfigure cursor swapchain"); @@ -420,60 +437,69 @@ SP CPointerManager::renderHWCursorBuffer(SPdataCopy(); + if (texData.empty()) { + if (currentCursorImage.surface && currentCursorImage.surface->resource()->role->role() == SURFACE_ROLE_CURSOR) { + const auto SURFACE = currentCursorImage.surface->resource(); + auto& shmBuffer = CCursorSurfaceRole::cursorPixelData(SURFACE); + + bool flipRB = false; + + if (SURFACE->current.texture) { + Debug::log(TRACE, "Cursor CPU surface: format {}, expecting AR24", FormatUtils::drmFormatName(SURFACE->current.texture->m_iDrmFormat)); + if (SURFACE->current.texture->m_iDrmFormat == DRM_FORMAT_ABGR8888) { + Debug::log(TRACE, "Cursor CPU surface format AB24, will flip. WARNING: this will break on big endian!"); + flipRB = true; + } else if (SURFACE->current.texture->m_iDrmFormat != DRM_FORMAT_ARGB8888) { + Debug::log(TRACE, "Cursor CPU surface format rejected, falling back to sw"); + return nullptr; + } + } + + if (shmBuffer.data()) + texData = shmBuffer; + else { + texData.resize(texture->m_vSize.x * 4 * texture->m_vSize.y); + memset(texData.data(), 0x00, texData.size()); + } + + if (flipRB) { + for (size_t i = 0; i < shmBuffer.size(); i += 4) { + std::swap(shmBuffer.at(i), shmBuffer.at(i + 2)); // little-endian!!!!!! + } + } + } else { + Debug::log(TRACE, "Cannot use dumb copy on dmabuf cursor buffers"); + return nullptr; + } + } + + // then, we just yeet it into the dumb buffer + + auto [data, fmt, size] = buf->beginDataPtr(0); + + memset(data, 0, size); + if (buf->dmabuf().size.x > texture->m_vSize.x) { + size_t STRIDE = 4 * texture->m_vSize.x; + for (int i = 0; i < texture->m_vSize.y; i++) + memcpy(data + i * buf->dmabuf().strides[0], texData.data() + i * STRIDE, STRIDE); + } else + memcpy(data, texData.data(), std::min(size, texData.size())); + + buf->endDataPtr(); + + return buf; + } + g_pHyprRenderer->makeEGLCurrent(); g_pHyprOpenGL->m_RenderData.pMonitor = state->monitor; auto RBO = g_pHyprRenderer->getOrCreateRenderbuffer(buf, state->monitor->cursorSwapchain->currentOptions().format); if (!RBO) { Debug::log(TRACE, "Failed to create cursor RB with format {}, mod {}", buf->dmabuf().format, buf->dmabuf().modifier); - static auto PDUMB = CConfigValue("cursor:allow_dumb_copy"); - if (!*PDUMB) - return nullptr; - - auto bufData = buf->beginDataPtr(0); - auto bufPtr = std::get<0>(bufData); - - // clear buffer - memset(bufPtr, 0, std::get<2>(bufData)); - - if (currentCursorImage.pBuffer) { - auto texAttrs = currentCursorImage.pBuffer->shm(); - - if (!texAttrs.success) { - Debug::log(TRACE, "Cannot use dumb copy on dmabuf cursor buffers"); - return nullptr; - } - - auto texData = currentCursorImage.pBuffer->beginDataPtr(GBM_BO_TRANSFER_WRITE); - auto texPtr = std::get<0>(texData); - Debug::log(TRACE, "cursor texture {}x{} {} {} {}", texAttrs.size.x, texAttrs.size.y, (void*)texPtr, texAttrs.format, texAttrs.stride); - // copy cursor texture - for (int i = 0; i < texAttrs.size.y; i++) - memcpy(bufPtr + i * buf->dmabuf().strides[0], texPtr + i * texAttrs.stride, texAttrs.stride); - } else if (currentCursorImage.surface && currentCursorImage.surface->resource()->role->role() == SURFACE_ROLE_CURSOR) { - const auto SURFACE = currentCursorImage.surface->resource(); - auto& shmBuffer = CCursorSurfaceRole::cursorPixelData(SURFACE); - Debug::log(TRACE, "cursor texture pixel data length: {}B", shmBuffer.size()); - - if (shmBuffer.data()) { - // copy cursor texture - // assume format is 32bpp - size_t STRIDE = 4 * SURFACE->current.bufferSize.x; - for (int i = 0; i < SURFACE->current.bufferSize.y; i++) - memcpy(bufPtr + i * buf->dmabuf().strides[0], shmBuffer.data() + i * STRIDE, STRIDE); - } else { - // if there is no data, hide the cursor - memset(bufPtr, '\0', buf->size.x * buf->size.y * 4 /* assume 32bpp */); - } - - } else { - Debug::log(TRACE, "Unsupported cursor buffer/surface, falling back to sw (can't dumb copy)"); - return nullptr; - } - - buf->endDataPtr(); - - return buf; + return nullptr; } RBO->bind(); @@ -773,7 +799,7 @@ SP CPointerManager::getCurrentCursorTexture() { if (currentCursorImage.pBuffer) { if (!currentCursorImage.bufferTex) - currentCursorImage.bufferTex = makeShared(currentCursorImage.pBuffer); + currentCursorImage.bufferTex = makeShared(currentCursorImage.pBuffer, true); return currentCursorImage.bufferTex; } diff --git a/src/protocols/core/Compositor.cpp b/src/protocols/core/Compositor.cpp index 57f61f87..89f2a4cb 100644 --- a/src/protocols/core/Compositor.cpp +++ b/src/protocols/core/Compositor.cpp @@ -438,12 +438,13 @@ void CWLSurfaceResource::commitPendingState() { current.texture->m_eTransform = wlTransformToHyprutils(current.transform); if (current.buffer && current.buffer->buffer) { - current.buffer->buffer->update(accumulateCurrentBufferDamage()); + const auto DAMAGE = accumulateCurrentBufferDamage(); + current.buffer->buffer->update(DAMAGE); // if the surface is a cursor, update the shm buffer // TODO: don't update the entire texture - if (role->role() == SURFACE_ROLE_CURSOR) - updateCursorShm(); + if (role->role() == SURFACE_ROLE_CURSOR && !DAMAGE.empty()) + updateCursorShm(DAMAGE); // release the buffer if it's synchronous as update() has done everything thats needed // so we can let the app know we're done. @@ -486,13 +487,12 @@ void CWLSurfaceResource::commitPendingState() { lastBuffer = current.buffer ? current.buffer->buffer : WP{}; } -void CWLSurfaceResource::updateCursorShm() { +void CWLSurfaceResource::updateCursorShm(CRegion damage) { auto buf = current.buffer ? current.buffer->buffer : lastBuffer; if (!buf) return; - // TODO: actually use damage auto& shmData = CCursorSurfaceRole::cursorPixelData(self.lock()); auto shmAttrs = buf->shm(); @@ -501,11 +501,25 @@ void CWLSurfaceResource::updateCursorShm() { return; } + damage.intersect(CBox{0, 0, buf->size.x, buf->size.y}); + // no need to end, shm. auto [pixelData, fmt, bufLen] = buf->beginDataPtr(0); shmData.resize(bufLen); - memcpy(shmData.data(), pixelData, bufLen); + + if (const auto RECTS = damage.getRects(); RECTS.size() == 1 && RECTS.at(0).x2 == buf->size.x && RECTS.at(0).y2 == buf->size.y) + memcpy(shmData.data(), pixelData, bufLen); + else { + for (auto& box : damage.getRects()) { + for (auto y = box.y1; y < box.y2; ++y) { + // bpp is 32 INSALLAH + auto begin = 4 * box.y1 * (box.x2 - box.x1) + box.x1; + auto len = 4 * (box.x2 - box.x1); + memcpy((uint8_t*)shmData.data() + begin, (uint8_t*)pixelData + begin, len); + } + } + } } void CWLSurfaceResource::presentFeedback(timespec* when, PHLMONITOR pMonitor) { diff --git a/src/protocols/core/Compositor.hpp b/src/protocols/core/Compositor.hpp index e5bdf082..c036041a 100644 --- a/src/protocols/core/Compositor.hpp +++ b/src/protocols/core/Compositor.hpp @@ -148,7 +148,7 @@ class CWLSurfaceResource { void dropCurrentBuffer(); void commitPendingState(); void bfHelper(std::vector> const& nodes, std::function, const Vector2D&, void*)> fn, void* data); - void updateCursorShm(); + void updateCursorShm(CRegion damage = CBox{0, 0, INT16_MAX, INT16_MAX}); friend class CWLPointerResource; }; diff --git a/src/render/Texture.cpp b/src/render/Texture.cpp index 91e70afa..633f0212 100644 --- a/src/render/Texture.cpp +++ b/src/render/Texture.cpp @@ -3,6 +3,7 @@ #include "../Compositor.hpp" #include "../protocols/types/Buffer.hpp" #include "../helpers/Format.hpp" +#include CTexture::CTexture() { // naffin' @@ -16,7 +17,7 @@ CTexture::~CTexture() { destroyTexture(); } -CTexture::CTexture(uint32_t drmFormat, uint8_t* pixels, uint32_t stride, const Vector2D& size_) { +CTexture::CTexture(uint32_t drmFormat, uint8_t* pixels, uint32_t stride, const Vector2D& size_, bool keepDataCopy) : m_iDrmFormat(drmFormat), m_bKeepDataCopy(keepDataCopy) { createFromShm(drmFormat, pixels, stride, size_); } @@ -24,7 +25,7 @@ CTexture::CTexture(const Aquamarine::SDMABUFAttrs& attrs, void* image) { createFromDma(attrs, image); } -CTexture::CTexture(const SP buffer) { +CTexture::CTexture(const SP buffer, bool keepDataCopy) : m_bKeepDataCopy(keepDataCopy) { if (!buffer) return; @@ -43,6 +44,8 @@ CTexture::CTexture(const SP buffer) { auto [pixelData, fmt, bufLen] = buffer->beginDataPtr(0); + m_iDrmFormat = fmt; + createFromShm(fmt, pixelData, bufLen, shm.size); return; } @@ -80,6 +83,11 @@ void CTexture::createFromShm(uint32_t drmFormat, uint8_t* pixels, uint32_t strid GLCALL(glTexImage2D(GL_TEXTURE_2D, 0, format->glInternalFormat ? format->glInternalFormat : format->glFormat, size_.x, size_.y, 0, format->glFormat, format->glType, pixels)); GLCALL(glPixelStorei(GL_UNPACK_ROW_LENGTH_EXT, 0)); GLCALL(glBindTexture(GL_TEXTURE_2D, 0)); + + if (m_bKeepDataCopy) { + m_vDataCopy.resize(stride * size_.y); + memcpy(m_vDataCopy.data(), pixels, stride * size_.y); + } } void CTexture::createFromDma(const Aquamarine::SDMABUFAttrs& attrs, void* image) { @@ -135,6 +143,11 @@ void CTexture::update(uint32_t drmFormat, uint8_t* pixels, uint32_t stride, cons GLCALL(glPixelStorei(GL_UNPACK_SKIP_ROWS_EXT, 0)); glBindTexture(GL_TEXTURE_2D, 0); + + if (m_bKeepDataCopy) { + m_vDataCopy.resize(stride * m_vSize.y); + memcpy(m_vDataCopy.data(), pixels, stride * m_vSize.y); + } } void CTexture::destroyTexture() { @@ -152,3 +165,7 @@ void CTexture::allocate() { if (!m_iTexID) GLCALL(glGenTextures(1, &m_iTexID)); } + +const std::vector& CTexture::dataCopy() { + return m_vDataCopy; +} diff --git a/src/render/Texture.hpp b/src/render/Texture.hpp index e0ef5503..ae949d5f 100644 --- a/src/render/Texture.hpp +++ b/src/render/Texture.hpp @@ -24,26 +24,32 @@ class CTexture { CTexture(const CTexture&&) = delete; CTexture(const CTexture&) = delete; - CTexture(uint32_t drmFormat, uint8_t* pixels, uint32_t stride, const Vector2D& size); + CTexture(uint32_t drmFormat, uint8_t* pixels, uint32_t stride, const Vector2D& size, bool keepDataCopy = false); - CTexture(const SP buffer); + CTexture(const SP buffer, bool keepDataCopy = false); // this ctor takes ownership of the eglImage. CTexture(const Aquamarine::SDMABUFAttrs&, void* image); ~CTexture(); - void destroyTexture(); - void allocate(); - void update(uint32_t drmFormat, uint8_t* pixels, uint32_t stride, const CRegion& damage); + void destroyTexture(); + void allocate(); + void update(uint32_t drmFormat, uint8_t* pixels, uint32_t stride, const CRegion& damage); + const std::vector& dataCopy(); - TEXTURETYPE m_iType = TEXTURE_RGBA; - GLenum m_iTarget = GL_TEXTURE_2D; - GLuint m_iTexID = 0; - Vector2D m_vSize = {}; - void* m_pEglImage = nullptr; - eTransform m_eTransform = HYPRUTILS_TRANSFORM_NORMAL; - bool m_bOpaque = false; + TEXTURETYPE m_iType = TEXTURE_RGBA; + GLenum m_iTarget = GL_TEXTURE_2D; + GLuint m_iTexID = 0; + Vector2D m_vSize = {}; + void* m_pEglImage = nullptr; + eTransform m_eTransform = HYPRUTILS_TRANSFORM_NORMAL; + bool m_bOpaque = false; + uint32_t m_iDrmFormat = 0; // for shm private: - void createFromShm(uint32_t drmFormat, uint8_t* pixels, uint32_t stride, const Vector2D& size); - void createFromDma(const Aquamarine::SDMABUFAttrs&, void* image); + void createFromShm(uint32_t drmFormat, uint8_t* pixels, uint32_t stride, const Vector2D& size); + void createFromDma(const Aquamarine::SDMABUFAttrs&, void* image); + + bool m_bKeepDataCopy = false; + + std::vector m_vDataCopy; }; \ No newline at end of file From 6f7280a6901aeba0fd1768ccf78fea152fe41f4f Mon Sep 17 00:00:00 2001 From: Vaxry Date: Thu, 14 Nov 2024 20:20:51 +0000 Subject: [PATCH 0635/2181] descriptions: add use_cpu_buffer --- src/config/ConfigDescriptions.hpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/config/ConfigDescriptions.hpp b/src/config/ConfigDescriptions.hpp index 27bc3c2d..969ec66f 100644 --- a/src/config/ConfigDescriptions.hpp +++ b/src/config/ConfigDescriptions.hpp @@ -1350,8 +1350,8 @@ inline static const std::vector CONFIG_OPTIONS = { .data = SConfigOptionDescription::SBoolData{true}, }, SConfigOptionDescription{ - .value = "cursor:allow_dumb_copy", - .description = "Makes HW cursors work on Nvidia, at the cost of a possible hitch whenever the image changes", + .value = "cursor:use_cpu_buffer", + .description = "Makes HW cursors use a CPU buffer. Required on Nvidia to have HW cursors. Experimental", .type = CONFIG_OPTION_BOOL, .data = SConfigOptionDescription::SBoolData{false}, }, From 940ed3d525d838bc255070bd8cfc2f75df04229a Mon Sep 17 00:00:00 2001 From: Tom Englund Date: Thu, 14 Nov 2024 21:38:16 +0100 Subject: [PATCH 0636/2181] xcursors: store themes in a std:set to order it (#8474) using a unordered_set means its store based on a hash_value meaning currently it can end up loading inherited themes before the actual theme itself depending on the hash of the theme name used, reason for using set at all over vector is to keep unique members and not foreverever looping broken inherit themeing. --- src/managers/XCursorManager.cpp | 8 ++++---- src/managers/XCursorManager.hpp | 24 ++++++++++++------------ 2 files changed, 16 insertions(+), 16 deletions(-) diff --git a/src/managers/XCursorManager.cpp b/src/managers/XCursorManager.cpp index 93ee7965..5c3053c7 100644 --- a/src/managers/XCursorManager.cpp +++ b/src/managers/XCursorManager.cpp @@ -197,7 +197,7 @@ SP CXCursorManager::createCursor(std::string const& shape, XcursorIma return xcursor; } -std::unordered_set CXCursorManager::themePaths(std::string const& theme) { +std::set CXCursorManager::themePaths(std::string const& theme) { auto const* path = XcursorLibraryPath(); auto expandTilde = [](std::string const& path) { @@ -276,10 +276,10 @@ std::unordered_set CXCursorManager::themePaths(std::string const& t return themes; }; - std::unordered_set paths; - std::unordered_set inherits; + std::set paths; + std::set inherits; - auto scanTheme = [&path, &paths, &expandTilde, &inherits, &getInheritThemes](auto const& t) { + auto scanTheme = [&path, &paths, &expandTilde, &inherits, &getInheritThemes](auto const& t) { std::stringstream ss(path); std::string line; diff --git a/src/managers/XCursorManager.hpp b/src/managers/XCursorManager.hpp index 1f3c24db..2517e85e 100644 --- a/src/managers/XCursorManager.hpp +++ b/src/managers/XCursorManager.hpp @@ -1,7 +1,7 @@ #pragma once #include #include -#include +#include #include #include #include @@ -34,16 +34,16 @@ class CXCursorManager { void syncGsettings(); private: - SP createCursor(std::string const& shape, XcursorImages* xImages); - std::unordered_set themePaths(std::string const& theme); - std::string getLegacyShapeName(std::string const& shape); - std::vector> loadStandardCursors(std::string const& name, int size); - std::vector> loadAllFromDir(std::string const& path, int size); + SP createCursor(std::string const& shape, XcursorImages* xImages); + std::set themePaths(std::string const& theme); + std::string getLegacyShapeName(std::string const& shape); + std::vector> loadStandardCursors(std::string const& name, int size); + std::vector> loadAllFromDir(std::string const& path, int size); - int lastLoadSize = 0; - float lastLoadScale = 0; - std::string themeName = ""; - SP defaultCursor; - SP hyprCursor; - std::vector> cursors; + int lastLoadSize = 0; + float lastLoadScale = 0; + std::string themeName = ""; + SP defaultCursor; + SP hyprCursor; + std::vector> cursors; }; From 967fe76a60ec6b2928b495ed202f772beca05275 Mon Sep 17 00:00:00 2001 From: UjinT34 <41110182+UjinT34@users.noreply.github.com> Date: Fri, 15 Nov 2024 03:45:13 +0300 Subject: [PATCH 0637/2181] drm: enable explit out fence in AQ (#8431) --- src/render/Renderer.cpp | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/render/Renderer.cpp b/src/render/Renderer.cpp index d98e32a9..37e6f81e 100644 --- a/src/render/Renderer.cpp +++ b/src/render/Renderer.cpp @@ -1507,6 +1507,9 @@ bool CHyprRenderer::commitPendingAndDoExplicitSync(PHLMONITOR pMonitor) { pMonitor->output->state->resetExplicitFences(); if (inFD >= 0) pMonitor->output->state->setExplicitInFence(inFD); + auto explicitOptions = getExplicitSyncSettings(); + if (explicitOptions.explicitEnabled && explicitOptions.explicitKMSEnabled) + pMonitor->output->state->enableExplicitOutFenceForNextCommit(); if (pMonitor->ctmUpdated) { pMonitor->ctmUpdated = false; @@ -1530,8 +1533,6 @@ bool CHyprRenderer::commitPendingAndDoExplicitSync(PHLMONITOR pMonitor) { } } - auto explicitOptions = getExplicitSyncSettings(); - if (!explicitOptions.explicitEnabled) return ok; From 098e491a43e8b26f4382b48651a4131464bf6a2f Mon Sep 17 00:00:00 2001 From: Vaxry Date: Fri, 15 Nov 2024 00:47:34 +0000 Subject: [PATCH 0638/2181] protocols: mark primarySelection as not privileged fixes #8479 --- src/managers/ProtocolManager.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/src/managers/ProtocolManager.cpp b/src/managers/ProtocolManager.cpp index 601e564d..cf517b22 100644 --- a/src/managers/ProtocolManager.cpp +++ b/src/managers/ProtocolManager.cpp @@ -281,6 +281,7 @@ bool CProtocolManager::isGlobalPrivileged(const wl_global* global) { PROTO::xdgShell->getGlobal(), PROTO::xdgDialog->getGlobal(), PROTO::singlePixel->getGlobal(), + PROTO::primarySelection->getGlobal(), PROTO::sync ? PROTO::sync->getGlobal() : nullptr, PROTO::mesaDRM ? PROTO::mesaDRM->getGlobal() : nullptr, PROTO::linuxDma ? PROTO::linuxDma->getGlobal() : nullptr, From 7affc34ab43c5d5cbf670759b839a9e990d8bbea Mon Sep 17 00:00:00 2001 From: littleblack111 Date: Sat, 16 Nov 2024 07:21:59 +0800 Subject: [PATCH 0639/2181] bind: new long press option (#8302) --------- Co-authored-by: Vaxry --- src/config/ConfigManager.cpp | 13 ++++++----- src/debug/HyprCtl.cpp | 7 +++--- src/managers/KeybindManager.cpp | 40 ++++++++++++++++++++++++++++++--- src/managers/KeybindManager.hpp | 5 ++++- 4 files changed, 53 insertions(+), 12 deletions(-) diff --git a/src/config/ConfigManager.cpp b/src/config/ConfigManager.cpp index 10299277..58db00e9 100644 --- a/src/config/ConfigManager.cpp +++ b/src/config/ConfigManager.cpp @@ -2171,6 +2171,7 @@ std::optional CConfigManager::handleBind(const std::string& command bool transparent = false; bool ignoreMods = false; bool multiKey = false; + bool longPress = false; bool hasDescription = false; bool dontInhibit = false; const auto BINDARGS = command.substr(4); @@ -2192,6 +2193,8 @@ std::optional CConfigManager::handleBind(const std::string& command ignoreMods = true; } else if (arg == 's') { multiKey = true; + } else if (arg == 'o') { + longPress = true; } else if (arg == 'd') { hasDescription = true; } else if (arg == 'p') { @@ -2201,8 +2204,8 @@ std::optional CConfigManager::handleBind(const std::string& command } } - if (release && repeat) - return "flags r and e are mutually exclusive"; + if ((longPress || release) && repeat) + return "flags e is mutually exclusive with r and o"; if (mouse && (repeat || release || locked)) return "flag m is exclusive"; @@ -2264,9 +2267,9 @@ std::optional CConfigManager::handleBind(const std::string& command return "Invalid catchall, catchall keybinds are only allowed in submaps."; } - g_pKeybindManager->addKeybind(SKeybind{ - parsedKey.key, KEYSYMS, parsedKey.keycode, parsedKey.catchAll, MOD, MODS, HANDLER, COMMAND, locked, m_szCurrentSubmap, DESCRIPTION, release, - repeat, mouse, nonConsuming, transparent, ignoreMods, multiKey, hasDescription, dontInhibit}); + g_pKeybindManager->addKeybind(SKeybind{parsedKey.key, KEYSYMS, parsedKey.keycode, parsedKey.catchAll, MOD, MODS, HANDLER, + COMMAND, locked, m_szCurrentSubmap, DESCRIPTION, release, repeat, longPress, + mouse, nonConsuming, transparent, ignoreMods, multiKey, hasDescription, dontInhibit}); } return {}; diff --git a/src/debug/HyprCtl.cpp b/src/debug/HyprCtl.cpp index 6429e781..c5eba0a7 100644 --- a/src/debug/HyprCtl.cpp +++ b/src/debug/HyprCtl.cpp @@ -843,6 +843,7 @@ std::string bindsRequest(eHyprCtlOutputFormat format, std::string request) { "mouse": {}, "release": {}, "repeat": {}, + "longPress": {}, "non_consuming": {}, "has_description": {}, "modmask": {}, @@ -854,9 +855,9 @@ std::string bindsRequest(eHyprCtlOutputFormat format, std::string request) { "dispatcher": "{}", "arg": "{}" }},)#", - kb.locked ? "true" : "false", kb.mouse ? "true" : "false", kb.release ? "true" : "false", kb.repeat ? "true" : "false", kb.nonConsuming ? "true" : "false", - kb.hasDescription ? "true" : "false", kb.modmask, escapeJSONStrings(kb.submap), escapeJSONStrings(kb.key), kb.keycode, kb.catchAll ? "true" : "false", - escapeJSONStrings(kb.description), escapeJSONStrings(kb.handler), escapeJSONStrings(kb.arg)); + kb.locked ? "true" : "false", kb.mouse ? "true" : "false", kb.release ? "true" : "false", kb.repeat ? "true" : "false", kb.longPress ? "true" : "false", + kb.nonConsuming ? "true" : "false", kb.hasDescription ? "true" : "false", kb.modmask, escapeJSONStrings(kb.submap), escapeJSONStrings(kb.key), kb.keycode, + kb.catchAll ? "true" : "false", escapeJSONStrings(kb.description), escapeJSONStrings(kb.handler), escapeJSONStrings(kb.arg)); } trimTrailingComma(ret); ret += "]"; diff --git a/src/managers/KeybindManager.cpp b/src/managers/KeybindManager.cpp index f2fdab53..b14637f7 100644 --- a/src/managers/KeybindManager.cpp +++ b/src/managers/KeybindManager.cpp @@ -13,6 +13,7 @@ #include "eventLoop/EventLoopManager.hpp" #include "debug/Log.hpp" #include "helpers/varlist/VarList.hpp" +#include "eventLoop/EventLoopManager.hpp" #include #include @@ -130,9 +131,25 @@ CKeybindManager::CKeybindManager() { m_tScrollTimer.reset(); + m_pLongPressTimer = makeShared( + std::nullopt, + [this](SP self, void* data) { + if (!m_pLastLongPressKeybind || g_pSeatManager->keyboard.expired()) + return; + + const auto DISPATCHER = g_pKeybindManager->m_mDispatchers.find(m_pLastLongPressKeybind->handler); + + Debug::log(LOG, "Long press timeout passed, calling dispatcher."); + DISPATCHER->second(m_pLastLongPressKeybind->arg); + }, + nullptr); + + g_pEventLoopManager->addTimer(m_pLongPressTimer); + static auto P = g_pHookSystem->hookDynamic("configReloaded", [this](void* hk, SCallbackInfo& info, std::any param) { // clear cuz realloc'd - m_pActiveKeybind = nullptr; + m_pActiveKeybind = nullptr; + m_pLastLongPressKeybind = nullptr; m_vPressedSpecialBinds.clear(); }); } @@ -140,12 +157,17 @@ CKeybindManager::CKeybindManager() { CKeybindManager::~CKeybindManager() { if (m_pXKBTranslationState) xkb_state_unref(m_pXKBTranslationState); + if (m_pLongPressTimer && g_pEventLoopManager) { + g_pEventLoopManager->removeTimer(m_pLongPressTimer); + m_pLongPressTimer.reset(); + } } void CKeybindManager::addKeybind(SKeybind kb) { m_lKeybinds.push_back(kb); - m_pActiveKeybind = nullptr; + m_pActiveKeybind = nullptr; + m_pLastLongPressKeybind = nullptr; } void CKeybindManager::removeKeybind(uint32_t mod, const SParsedKey& key) { @@ -158,7 +180,8 @@ void CKeybindManager::removeKeybind(uint32_t mod, const SParsedKey& key) { } } - m_pActiveKeybind = nullptr; + m_pActiveKeybind = nullptr; + m_pLastLongPressKeybind = nullptr; } uint32_t CKeybindManager::stringToModMask(std::string mods) { @@ -409,6 +432,8 @@ bool CKeybindManager::onKeyEvent(std::any event, SP pKeyboard) { m_pActiveKeybind = nullptr; } + m_pLastLongPressKeybind = nullptr; + bool suppressEvent = false; if (e.state == WL_KEYBOARD_KEY_STATE_PRESSED) { @@ -705,6 +730,15 @@ SDispatchResult CKeybindManager::handleKeybinds(const uint32_t modmask, const SP } } + if (k.longPress) { + const auto PACTIVEKEEB = g_pSeatManager->keyboard.lock(); + + m_pLongPressTimer->updateTimeout(std::chrono::milliseconds(PACTIVEKEEB->repeatDelay)); + m_pLastLongPressKeybind = &k; + + continue; + } + const auto DISPATCHER = m_mDispatchers.find(k.mouse ? "mouse" : k.handler); if (SPECIALTRIGGERED && !pressed) diff --git a/src/managers/KeybindManager.hpp b/src/managers/KeybindManager.hpp index 24a09836..4a0af6e9 100644 --- a/src/managers/KeybindManager.hpp +++ b/src/managers/KeybindManager.hpp @@ -8,6 +8,7 @@ #include #include #include "../devices/IPointer.hpp" +#include "eventLoop/EventLoopTimer.hpp" class CInputManager; class CConfigManager; @@ -28,6 +29,7 @@ struct SKeybind { std::string description = ""; bool release = false; bool repeat = false; + bool longPress = false; bool mouse = false; bool nonConsuming = false; bool transparent = false; @@ -119,7 +121,8 @@ class CKeybindManager { inline static std::string m_szCurrentSelectedSubmap = ""; - SKeybind* m_pActiveKeybind = nullptr; + SKeybind * m_pActiveKeybind = nullptr, *m_pLastLongPressKeybind = nullptr; + SP m_pLongPressTimer; uint32_t m_uTimeLastMs = 0; uint32_t m_uLastCode = 0; From 83be2480c45bdead9110fdf137a1cd2f5a203378 Mon Sep 17 00:00:00 2001 From: sslater11 <43177940+sslater11@users.noreply.github.com> Date: Sat, 16 Nov 2024 16:39:58 +0000 Subject: [PATCH 0640/2181] workspace: fix missing name via focusworkspaceoncurrentmonitor (#8484) --- src/managers/KeybindManager.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/managers/KeybindManager.cpp b/src/managers/KeybindManager.cpp index b14637f7..4d2f4dcc 100644 --- a/src/managers/KeybindManager.cpp +++ b/src/managers/KeybindManager.cpp @@ -1887,7 +1887,7 @@ SDispatchResult CKeybindManager::moveWorkspaceToMonitor(std::string args) { } SDispatchResult CKeybindManager::focusWorkspaceOnCurrentMonitor(std::string args) { - auto workspaceID = getWorkspaceIDNameFromString(args).id; + auto [workspaceID, workspaceName] = getWorkspaceIDNameFromString(args); if (workspaceID == WORKSPACE_INVALID) { Debug::log(ERR, "focusWorkspaceOnCurrentMonitor invalid workspace!"); return {.success = false, .error = "focusWorkspaceOnCurrentMonitor invalid workspace!"}; @@ -1903,7 +1903,7 @@ SDispatchResult CKeybindManager::focusWorkspaceOnCurrentMonitor(std::string args auto pWorkspace = g_pCompositor->getWorkspaceByID(workspaceID); if (!pWorkspace) { - pWorkspace = g_pCompositor->createNewWorkspace(workspaceID, PCURRMONITOR->ID); + pWorkspace = g_pCompositor->createNewWorkspace(workspaceID, PCURRMONITOR->ID, workspaceName); // we can skip the moving, since it's already on the current monitor changeworkspace(pWorkspace->getConfigName()); return {}; From ec1e6be00377c26dd25497b1544091b3f643c4bc Mon Sep 17 00:00:00 2001 From: Vaxry Date: Sat, 16 Nov 2024 23:04:57 +0000 Subject: [PATCH 0641/2181] core: guard pmonitor in focuswindow may be null fixes #8483 --- src/Compositor.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Compositor.cpp b/src/Compositor.cpp index da20c5cf..fbbfd7e7 100644 --- a/src/Compositor.cpp +++ b/src/Compositor.cpp @@ -1077,7 +1077,7 @@ void CCompositor::focusWindow(PHLWINDOW pWindow, SP pSurface PWORKSPACE->rememberPrevWorkspace(m_pLastMonitor->activeWorkspace); if (PWORKSPACE->m_bIsSpecialWorkspace) m_pLastMonitor->changeWorkspace(PWORKSPACE, false, true); // if special ws, open on current monitor - else + else if (PMONITOR) PMONITOR->changeWorkspace(PWORKSPACE, false, true); // changeworkspace already calls focusWindow return; @@ -1088,7 +1088,7 @@ void CCompositor::focusWindow(PHLWINDOW pWindow, SP pSurface /* If special fallthrough is enabled, this behavior will be disabled, as I have no better idea of nicely tracking which window focuses are "via keybinds" and which ones aren't. */ - if (PMONITOR->activeSpecialWorkspace && PMONITOR->activeSpecialWorkspace != pWindow->m_pWorkspace && !pWindow->m_bPinned && !*PSPECIALFALLTHROUGH) + if (PMONITOR && PMONITOR->activeSpecialWorkspace && PMONITOR->activeSpecialWorkspace != pWindow->m_pWorkspace && !pWindow->m_bPinned && !*PSPECIALFALLTHROUGH) PMONITOR->setSpecialWorkspace(nullptr); // we need to make the PLASTWINDOW not equal to m_pLastWindow so that RENDERDATA is correct for an unfocused window From cf18eca86d21c28b127d58938b3a1004800b85c9 Mon Sep 17 00:00:00 2001 From: vaxerski Date: Sat, 16 Nov 2024 23:06:35 +0000 Subject: [PATCH 0642/2181] [gha] Nix: update inputs --- flake.lock | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/flake.lock b/flake.lock index c1fcb70d..969bc157 100644 --- a/flake.lock +++ b/flake.lock @@ -16,11 +16,11 @@ ] }, "locked": { - "lastModified": 1731496216, - "narHash": "sha256-nlQrNN+tmJ+iP6Ck/czwZI0Hxz3oNvUyGkVruxJwgwA=", + "lastModified": 1731774881, + "narHash": "sha256-1Dxryiw8u2ejntxrrv3sMtIE8WHKxmlN4KeH+uMGbmc=", "owner": "hyprwm", "repo": "aquamarine", - "rev": "3b00e96f90cb0040de6d88ad99bf5f4d443f0c59", + "rev": "b31a6a4da8199ae3489057db7d36069a70749a56", "type": "github" }, "original": { @@ -151,11 +151,11 @@ ] }, "locked": { - "lastModified": 1731518387, - "narHash": "sha256-aZZw1ZvTMLkcA6udlvkA3hrCkuipoWLy8s/JNnIclxY=", + "lastModified": 1731702627, + "narHash": "sha256-+JeO9gevnXannQxMfR5xzZtF4sYmSlWkX/BPmPx0mWk=", "owner": "hyprwm", "repo": "hyprutils", - "rev": "315fba5d21d87ddb756d4bebdb49f99d86b0ffe8", + "rev": "e911361a687753bbbdfe3b6a9eab755ecaf1d9e1", "type": "github" }, "original": { @@ -189,11 +189,11 @@ }, "nixpkgs": { "locked": { - "lastModified": 1731139594, - "narHash": "sha256-IigrKK3vYRpUu+HEjPL/phrfh7Ox881er1UEsZvw9Q4=", + "lastModified": 1731676054, + "narHash": "sha256-OZiZ3m8SCMfh3B6bfGC/Bm4x3qc1m2SVEAlkV6iY7Yg=", "owner": "NixOS", "repo": "nixpkgs", - "rev": "76612b17c0ce71689921ca12d9ffdc9c23ce40b2", + "rev": "5e4fbfb6b3de1aa2872b76d49fafc942626e2add", "type": "github" }, "original": { @@ -293,11 +293,11 @@ ] }, "locked": { - "lastModified": 1730743262, - "narHash": "sha256-iTLqj3lU8kFehPm5tXpctzkD274t/k1nwSSq3qCWXeg=", + "lastModified": 1731703417, + "narHash": "sha256-rheDc/7C+yI+QspYr9J2z9kQ5P9F4ATapI7qyFAe1XA=", "owner": "hyprwm", "repo": "xdg-desktop-portal-hyprland", - "rev": "09b23cef06fe248e61cec8862c04b9bcb62f4b6d", + "rev": "8070f36deec723de71e7557441acb17e478204d3", "type": "github" }, "original": { From 9d37b1b07339b1b222ceab5952cd9b927fbf6d73 Mon Sep 17 00:00:00 2001 From: staz Date: Sun, 17 Nov 2024 04:07:33 +0500 Subject: [PATCH 0643/2181] workspacerules: Do not check 'on-created-empty' if using a workspace windowrule (#8486) --- src/events/Windows.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/events/Windows.cpp b/src/events/Windows.cpp index f946ce03..77df7373 100644 --- a/src/events/Windows.cpp +++ b/src/events/Windows.cpp @@ -296,7 +296,7 @@ void Events::listener_mapWindow(void* owner, void* data) { auto pWorkspace = g_pCompositor->getWorkspaceByID(REQUESTEDWORKSPACEID); if (!pWorkspace) - pWorkspace = g_pCompositor->createNewWorkspace(REQUESTEDWORKSPACEID, PWINDOW->monitorID(), requestedWorkspaceName); + pWorkspace = g_pCompositor->createNewWorkspace(REQUESTEDWORKSPACEID, PWINDOW->monitorID(), requestedWorkspaceName, false); PWORKSPACE = pWorkspace; From af83c825138386d269d69b3ef755b844a2eacb22 Mon Sep 17 00:00:00 2001 From: Ruslan Date: Sun, 17 Nov 2024 02:18:30 +0300 Subject: [PATCH 0644/2181] hyprctl: add json output on hyprctl -j plugins list (#8480) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --------- Co-authored-by: Руслан Новокшонов --- src/debug/HyprCtl.cpp | 37 ++++++++++++++++++++++++++++++------- 1 file changed, 30 insertions(+), 7 deletions(-) diff --git a/src/debug/HyprCtl.cpp b/src/debug/HyprCtl.cpp index c5eba0a7..964a193b 100644 --- a/src/debug/HyprCtl.cpp +++ b/src/debug/HyprCtl.cpp @@ -1472,17 +1472,40 @@ std::string dispatchPlugin(eHyprCtlOutputFormat format, std::string request) { g_pPluginSystem->unloadPlugin(PLUGIN); } else if (OPERATION == "list") { - const auto PLUGINS = g_pPluginSystem->getAllPlugins(); + const auto PLUGINS = g_pPluginSystem->getAllPlugins(); + std::string result = ""; - if (PLUGINS.size() == 0) - return "no plugins loaded"; + if (format == eHyprCtlOutputFormat::FORMAT_JSON) { + result += "["; - std::string list = ""; - for (auto const& p : PLUGINS) { - list += std::format("\nPlugin {} by {}:\n\tHandle: {:x}\n\tVersion: {}\n\tDescription: {}\n", p->name, p->author, (uintptr_t)p->m_pHandle, p->version, p->description); + if (PLUGINS.size() == 0) + return "[]"; + + for (auto const& p : PLUGINS) { + result += std::format( + R"#( +{{ + "name": "{}", + "author": "{}", + "handle": "{:x}", + "version": "{}", + "description": "{}" +}},)#", + escapeJSONStrings(p->name), escapeJSONStrings(p->author), (uintptr_t)p->m_pHandle, escapeJSONStrings(p->version), escapeJSONStrings(p->description)); + } + trimTrailingComma(result); + result += "]"; + } else { + if (PLUGINS.size() == 0) + return "no plugins loaded"; + + for (auto const& p : PLUGINS) { + result += + std::format("\nPlugin {} by {}:\n\tHandle: {:x}\n\tVersion: {}\n\tDescription: {}\n", p->name, p->author, (uintptr_t)p->m_pHandle, p->version, p->description); + } } - return list; + return result; } else { return "unknown opt"; } From 0ddbd1c3a40f921816a2c512f871f1e51aca8fe2 Mon Sep 17 00:00:00 2001 From: Alexandre Acebedo Date: Sun, 17 Nov 2024 15:58:18 +0000 Subject: [PATCH 0645/2181] renderer: add lockdead_screen_delay (#8467) --- src/config/ConfigDescriptions.hpp | 6 ++++++ src/config/ConfigManager.cpp | 1 + src/managers/SessionLockManager.cpp | 10 ++++++++++ src/managers/SessionLockManager.hpp | 3 +++ src/render/Renderer.cpp | 9 +++++---- 5 files changed, 25 insertions(+), 4 deletions(-) diff --git a/src/config/ConfigDescriptions.hpp b/src/config/ConfigDescriptions.hpp index 969ec66f..2e3a6720 100644 --- a/src/config/ConfigDescriptions.hpp +++ b/src/config/ConfigDescriptions.hpp @@ -1121,6 +1121,12 @@ inline static const std::vector CONFIG_OPTIONS = { .type = CONFIG_OPTION_BOOL, .data = SConfigOptionDescription::SBoolData{false}, }, + SConfigOptionDescription{ + .value = "misc:lockdead_screen_delay", + .description = "the delay in ms after the lockdead screen appears if the lock screen did not appear after a lock event occurred.", + .type = CONFIG_OPTION_INT, + .data = SConfigOptionDescription::SRangeData{1000, 0, 5000}, + }, /* * binds: diff --git a/src/config/ConfigManager.cpp b/src/config/ConfigManager.cpp index 58db00e9..1c025179 100644 --- a/src/config/ConfigManager.cpp +++ b/src/config/ConfigManager.cpp @@ -377,6 +377,7 @@ CConfigManager::CConfigManager() { m_pConfig->addConfigValue("misc:middle_click_paste", Hyprlang::INT{1}); m_pConfig->addConfigValue("misc:render_unfocused_fps", Hyprlang::INT{15}); m_pConfig->addConfigValue("misc:disable_xdg_env_checks", Hyprlang::INT{0}); + m_pConfig->addConfigValue("misc:lockdead_screen_delay", Hyprlang::INT{1000}); m_pConfig->addConfigValue("group:insert_after_current", Hyprlang::INT{1}); m_pConfig->addConfigValue("group:focus_removed_window", Hyprlang::INT{1}); diff --git a/src/managers/SessionLockManager.cpp b/src/managers/SessionLockManager.cpp index 1b28cc27..c7a5934a 100644 --- a/src/managers/SessionLockManager.cpp +++ b/src/managers/SessionLockManager.cpp @@ -57,6 +57,7 @@ void CSessionLockManager::onNewSessionLock(SP pLock) { m_pSessionLock = std::make_unique(); m_pSessionLock->lock = pLock; + m_pSessionLock->mLockTimer.reset(); m_pSessionLock->listeners.newSurface = pLock->events.newLockSurface.registerListener([this](std::any data) { auto SURFACE = std::any_cast>(data); @@ -176,3 +177,12 @@ bool CSessionLockManager::isSessionLockPresent() { bool CSessionLockManager::anySessionLockSurfacesPresent() { return m_pSessionLock && std::ranges::any_of(m_pSessionLock->vSessionLockSurfaces, [](const auto& surf) { return surf->mapped; }); } + +bool CSessionLockManager::shallConsiderLockMissing() { + if (!m_pSessionLock) + return false; + + static auto LOCKDEAD_SCREEN_DELAY = CConfigValue("misc:lockdead_screen_delay"); + + return m_pSessionLock->mLockTimer.getMillis() > *LOCKDEAD_SCREEN_DELAY; +} \ No newline at end of file diff --git a/src/managers/SessionLockManager.hpp b/src/managers/SessionLockManager.hpp index 9b3b882c..59090605 100644 --- a/src/managers/SessionLockManager.hpp +++ b/src/managers/SessionLockManager.hpp @@ -29,6 +29,7 @@ struct SSessionLockSurface { struct SSessionLock { WP lock; + CTimer mLockTimer; std::vector> vSessionLockSurfaces; std::unordered_map mMonitorsWithoutMappedSurfaceTimers; @@ -61,6 +62,8 @@ class CSessionLockManager { void onLockscreenRenderedOnMonitor(uint64_t id); + bool shallConsiderLockMissing(); + private: UP m_pSessionLock; diff --git a/src/render/Renderer.cpp b/src/render/Renderer.cpp index 37e6f81e..3eba8458 100644 --- a/src/render/Renderer.cpp +++ b/src/render/Renderer.cpp @@ -1045,9 +1045,10 @@ void CHyprRenderer::renderLockscreen(PHLMONITOR pMonitor, timespec* now, const C Vector2D translate = {geometry.x, geometry.y}; const auto PSLS = g_pSessionLockManager->getSessionLockSurfaceForMonitor(pMonitor->ID); - if (!PSLS) - renderSessionLockMissing(pMonitor); - else { + if (!PSLS) { + if (g_pSessionLockManager->shallConsiderLockMissing()) + renderSessionLockMissing(pMonitor); + } else { renderSessionLockSurface(PSLS, pMonitor, now); g_pSessionLockManager->onLockscreenRenderedOnMonitor(pMonitor->ID); } @@ -2726,7 +2727,7 @@ bool CHyprRenderer::beginRender(PHLMONITOR pMonitor, CRegion& damage, eRenderMod return true; } - /* This is a constant expression, as we always use double-buffering in our swapchain + /* This is a constant expression, as we always use double-buffering in our swapchain TODO: Rewrite the CDamageRing to take advantage of that maybe? It's made to support longer swapchains atm because we used to do wlroots */ static constexpr const int HL_BUFFER_AGE = 2; From fb91c2550f5184785680f6af7b069cb857568104 Mon Sep 17 00:00:00 2001 From: Vaxry Date: Sun, 17 Nov 2024 16:16:49 +0000 Subject: [PATCH 0646/2181] renderer: don't render unmapped popups fixes #8485 --- src/desktop/Popup.hpp | 4 ++-- src/render/Renderer.cpp | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/desktop/Popup.hpp b/src/desktop/Popup.hpp index f34b8a2c..e9b3e0f0 100644 --- a/src/desktop/Popup.hpp +++ b/src/desktop/Popup.hpp @@ -41,6 +41,7 @@ class CPopup { // SP m_pWLSurface; + bool m_bMapped = false; private: // T1 owners, each popup has to have one of these @@ -57,8 +58,7 @@ class CPopup { bool m_bRequestedReposition = false; - bool m_bInert = false; - bool m_bMapped = false; + bool m_bInert = false; // std::vector> m_vChildren; diff --git a/src/render/Renderer.cpp b/src/render/Renderer.cpp index 3eba8458..6067a7f2 100644 --- a/src/render/Renderer.cpp +++ b/src/render/Renderer.cpp @@ -732,7 +732,7 @@ void CHyprRenderer::renderWindow(PHLWINDOW pWindow, PHLMONITOR pMonitor, timespe pWindow->m_pPopupHead->breadthfirst( [](CPopup* popup, void* data) { - if (!popup->m_pWLSurface || !popup->m_pWLSurface->resource()) + if (!popup->m_pWLSurface || !popup->m_pWLSurface->resource() || !popup->m_bMapped) return; auto pos = popup->coordsRelativeToParent(); auto rd = (SRenderData*)data; @@ -822,7 +822,7 @@ void CHyprRenderer::renderLayer(PHLLS pLayer, PHLMONITOR pMonitor, timespec* tim if (popups) { pLayer->popupHead->breadthfirst( [](CPopup* popup, void* data) { - if (!popup->m_pWLSurface || !popup->m_pWLSurface->resource()) + if (!popup->m_pWLSurface || !popup->m_pWLSurface->resource() || !popup->m_bMapped) return; Vector2D pos = popup->coordsRelativeToParent(); From 4f591e807abe1865d8f8135a1a64932cc418d0f0 Mon Sep 17 00:00:00 2001 From: Vaxry Date: Sun, 17 Nov 2024 16:42:30 +0000 Subject: [PATCH 0647/2181] renderer: simplify blur enabling logic --- src/render/OpenGL.cpp | 4 +--- src/render/Renderer.cpp | 22 ++++++++++++++-------- 2 files changed, 15 insertions(+), 11 deletions(-) diff --git a/src/render/OpenGL.cpp b/src/render/OpenGL.cpp index 63a7e822..9c00daee 100644 --- a/src/render/OpenGL.cpp +++ b/src/render/OpenGL.cpp @@ -2036,7 +2036,6 @@ bool CHyprOpenGLImpl::shouldUseNewBlurOptimizations(PHLLS pLayer, PHLWINDOW pWin void CHyprOpenGLImpl::renderTextureWithBlur(SP tex, CBox* pBox, float a, SP pSurface, int round, bool blockBlurOptimization, float blurA) { RASSERT(m_RenderData.pMonitor, "Tried to render texture with blur without begin()!"); - static auto PBLURENABLED = CConfigValue("decoration:blur:enabled"); static auto PNOBLUROVERSIZED = CConfigValue("decoration:no_blur_on_oversized"); TRACY_GPU_ZONE("RenderTextureWithBlur"); @@ -2050,8 +2049,7 @@ void CHyprOpenGLImpl::renderTextureWithBlur(SP tex, CBox* pBox, float m_RenderData.renderModif.applyToRegion(texDamage); - if (*PBLURENABLED == 0 || (*PNOBLUROVERSIZED && m_RenderData.primarySurfaceUVTopLeft != Vector2D(-1, -1)) || - (m_pCurrentWindow.lock() && (m_pCurrentWindow->m_sWindowData.noBlur.valueOrDefault() || m_pCurrentWindow->m_sWindowData.RGBX.valueOrDefault()))) { + if (*PNOBLUROVERSIZED && m_RenderData.primarySurfaceUVTopLeft != Vector2D(-1, -1)) { renderTexture(tex, pBox, a, round, false, true); return; } diff --git a/src/render/Renderer.cpp b/src/render/Renderer.cpp index 6067a7f2..fc17ef9f 100644 --- a/src/render/Renderer.cpp +++ b/src/render/Renderer.cpp @@ -174,6 +174,7 @@ static void renderSurface(SP surface, int x, int y, void* da } const auto RDATA = (SRenderData*)data; + const bool BLUR = RDATA->blur && !TEXTURE->m_bOpaque; const auto INTERACTIVERESIZEINPROGRESS = RDATA->pWindow && g_pInputManager->currentlyDraggedWindow && g_pInputManager->dragMode == MBIND_RESIZE; TRACY_GPU_ZONE("RenderSurface"); @@ -270,12 +271,12 @@ static void renderSurface(SP surface, int x, int y, void* da // is a subsurface that does NOT cover the entire frame. In such cases, we probably should fall back // to what we do for misaligned surfaces (blur the entire thing and then render shit without blur) if (RDATA->surfaceCounter == 0 && !RDATA->popup) { - if (RDATA->blur) + if (BLUR) g_pHyprOpenGL->renderTextureWithBlur(TEXTURE, &windowBox, ALPHA, surface, rounding, RDATA->blockBlurOptimization, RDATA->fadeAlpha); else g_pHyprOpenGL->renderTexture(TEXTURE, &windowBox, ALPHA, rounding, false, true); } else { - if (RDATA->blur && RDATA->popup) + if (BLUR && RDATA->popup) g_pHyprOpenGL->renderTextureWithBlur(TEXTURE, &windowBox, ALPHA, surface, rounding, true, RDATA->fadeAlpha); else g_pHyprOpenGL->renderTexture(TEXTURE, &windowBox, ALPHA, rounding, false, true); @@ -591,6 +592,7 @@ void CHyprRenderer::renderWindow(PHLWINDOW pWindow, PHLMONITOR pMonitor, timespe // whether to use m_fMovingToWorkspaceAlpha, only if fading out into an invisible ws const bool USE_WORKSPACE_FADE_ALPHA = pWindow->m_iMonitorMovedFrom != -1 && !g_pCompositor->isWorkspaceVisible(pWindow->m_pWorkspace); + const bool DONT_BLUR = pWindow->m_sWindowData.noBlur.valueOrDefault() || pWindow->m_sWindowData.RGBX.valueOrDefault() || pWindow->opaque(); renderdata.surface = pWindow->m_pWLSurface->resource(); renderdata.dontRound = pWindow->isEffectiveInternalFSMode(FSMODE_FULLSCREEN) || pWindow->m_sWindowData.noRounding.valueOrDefault(); @@ -599,7 +601,7 @@ void CHyprRenderer::renderWindow(PHLWINDOW pWindow, PHLMONITOR pMonitor, timespe renderdata.alpha = pWindow->m_fActiveInactiveAlpha.value(); renderdata.decorate = decorate && !pWindow->m_bX11DoesntWantBorders && !pWindow->isEffectiveInternalFSMode(FSMODE_FULLSCREEN); renderdata.rounding = ignoreAllGeometry || renderdata.dontRound ? 0 : pWindow->rounding() * pMonitor->scale; - renderdata.blur = !ignoreAllGeometry; // if it shouldn't, it will be ignored later + renderdata.blur = !ignoreAllGeometry && *PBLUR && !DONT_BLUR; renderdata.pWindow = pWindow; if (ignoreAllGeometry) { @@ -715,7 +717,7 @@ void CHyprRenderer::renderWindow(PHLWINDOW pWindow, PHLMONITOR pMonitor, timespe static CConfigValue PBLURPOPUPS = CConfigValue("decoration:blur:popups"); static CConfigValue PBLURIGNOREA = CConfigValue("decoration:blur:popups_ignorealpha"); - renderdata.blur = *PBLURPOPUPS; + renderdata.blur = *PBLURPOPUPS && *PBLUR; const auto DM = g_pHyprOpenGL->m_RenderData.discardMode; const auto DA = g_pHyprOpenGL->m_RenderData.discardOpacity; @@ -734,13 +736,15 @@ void CHyprRenderer::renderWindow(PHLWINDOW pWindow, PHLMONITOR pMonitor, timespe [](CPopup* popup, void* data) { if (!popup->m_pWLSurface || !popup->m_pWLSurface->resource() || !popup->m_bMapped) return; - auto pos = popup->coordsRelativeToParent(); - auto rd = (SRenderData*)data; - Vector2D oldPos = {rd->x, rd->y}; + const auto pos = popup->coordsRelativeToParent(); + auto rd = (SRenderData*)data; + const Vector2D oldPos = {rd->x, rd->y}; rd->x += pos.x; rd->y += pos.y; + popup->m_pWLSurface->resource()->breadthfirst([](SP s, const Vector2D& offset, void* data) { renderSurface(s, offset.x, offset.y, data); }, data); + rd->x = oldPos.x; rd->y = oldPos.y; }, @@ -785,6 +789,8 @@ void CHyprRenderer::renderLayer(PHLLS pLayer, PHLMONITOR pMonitor, timespec* tim return; } + static auto PBLUR = CConfigValue("decoration:blur:enabled"); + TRACY_GPU_ZONE("RenderLayer"); const auto REALPOS = pLayer->realPosition.value(); @@ -792,7 +798,7 @@ void CHyprRenderer::renderLayer(PHLLS pLayer, PHLMONITOR pMonitor, timespec* tim SRenderData renderdata = {pMonitor, time, REALPOS.x, REALPOS.y}; renderdata.fadeAlpha = pLayer->alpha.value(); - renderdata.blur = pLayer->forceBlur; + renderdata.blur = pLayer->forceBlur && *PBLUR; renderdata.surface = pLayer->surface->resource(); renderdata.decorate = false; renderdata.w = REALSIZ.x; From 8d5cdedbd350b4730a1aa57dc5491c88dff3415e Mon Sep 17 00:00:00 2001 From: Vaxry Date: Sun, 17 Nov 2024 16:46:49 +0000 Subject: [PATCH 0648/2181] hyprpm: fix format crash ref #8487 --- hyprpm/src/core/PluginManager.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/hyprpm/src/core/PluginManager.cpp b/hyprpm/src/core/PluginManager.cpp index 051ad500..db315193 100644 --- a/hyprpm/src/core/PluginManager.cpp +++ b/hyprpm/src/core/PluginManager.cpp @@ -272,7 +272,7 @@ bool CPluginManager::addNewPluginRepo(const std::string& url, const std::string& } if (m_bVerbose) - std::println("{}", verboseString("shell returned: " + out)); + std::println("{}", verboseString("shell returned: {}", out)); if (!std::filesystem::exists(m_szWorkingPluginDirectory + "/" + p.output)) { progress.printMessageAbove(failureString("Plugin {} failed to build.\n" From b735295d2b0025b26f88852c06f65514a963c711 Mon Sep 17 00:00:00 2001 From: Vaxry Date: Sun, 17 Nov 2024 19:31:54 +0000 Subject: [PATCH 0649/2181] windows/xdg: minor cleanup of min/max size calculations fixes #8495 --- src/desktop/Window.cpp | 26 ++++++++++++++++++++++++++ src/desktop/Window.hpp | 19 +++++++++---------- src/events/Windows.cpp | 8 ++++---- src/layout/DwindleLayout.cpp | 2 +- src/layout/IHyprLayout.cpp | 8 ++++---- src/layout/MasterLayout.cpp | 4 ++-- src/managers/XWaylandManager.cpp | 30 ------------------------------ src/managers/XWaylandManager.hpp | 2 -- src/protocols/XDGShell.cpp | 8 ++++++++ src/protocols/XDGShell.hpp | 3 +++ 10 files changed, 57 insertions(+), 53 deletions(-) diff --git a/src/desktop/Window.cpp b/src/desktop/Window.cpp index 20fed565..e74e13a2 100644 --- a/src/desktop/Window.cpp +++ b/src/desktop/Window.cpp @@ -1601,3 +1601,29 @@ bool CWindow::isX11OverrideRedirect() { bool CWindow::isModal() { return (m_pXWaylandSurface && m_pXWaylandSurface->modal); } + +Vector2D CWindow::requestedMinSize() { + if ((m_bIsX11 && !m_pXWaylandSurface->sizeHints) || (!m_bIsX11 && !m_pXDGSurface->toplevel)) + return Vector2D(1, 1); + + Vector2D minSize = m_bIsX11 ? Vector2D(m_pXWaylandSurface->sizeHints->min_width, m_pXWaylandSurface->sizeHints->min_height) : m_pXDGSurface->toplevel->layoutMinSize(); + + minSize = minSize.clamp({1, 1}); + + return minSize; +} + +Vector2D CWindow::requestedMaxSize() { + constexpr int NO_MAX_SIZE_LIMIT = 99999; + if (((m_bIsX11 && !m_pXWaylandSurface->sizeHints) || (!m_bIsX11 && !m_pXDGSurface->toplevel) || m_sWindowData.noMaxSize.valueOrDefault())) + return Vector2D(NO_MAX_SIZE_LIMIT, NO_MAX_SIZE_LIMIT); + + Vector2D maxSize = m_bIsX11 ? Vector2D(m_pXWaylandSurface->sizeHints->max_width, m_pXWaylandSurface->sizeHints->max_height) : m_pXDGSurface->toplevel->layoutMaxSize(); + + if (maxSize.x < 5) + maxSize.x = NO_MAX_SIZE_LIMIT; + if (maxSize.y < 5) + maxSize.y = NO_MAX_SIZE_LIMIT; + + return maxSize; +} diff --git a/src/desktop/Window.hpp b/src/desktop/Window.hpp index b8dd3cf7..ac81e5ef 100644 --- a/src/desktop/Window.hpp +++ b/src/desktop/Window.hpp @@ -403,12 +403,9 @@ class CWindow { } // methods - CBox getFullWindowBoundingBox(); - SBoxExtents getFullWindowExtents(); - CBox getWindowBoxUnified(uint64_t props); - inline CBox getWindowMainSurfaceBox() const { - return {m_vRealPosition.value().x, m_vRealPosition.value().y, m_vRealSize.value().x, m_vRealSize.value().y}; - } + CBox getFullWindowBoundingBox(); + SBoxExtents getFullWindowExtents(); + CBox getWindowBoxUnified(uint64_t props); CBox getWindowIdealBoundingBoxIgnoreReserved(); void addWindowDeco(std::unique_ptr deco); void updateWindowDecos(); @@ -441,19 +438,15 @@ class CWindow { void activate(bool force = false); int surfacesCount(); void clampWindowSize(const std::optional minSize, const std::optional maxSize); - bool isFullscreen(); bool isEffectiveInternalFSMode(const eFullscreenMode); - int getRealBorderSize(); void updateWindowData(); void updateWindowData(const struct SWorkspaceRule&); - void onBorderAngleAnimEnd(void* ptr); bool isInCurvedCorner(double x, double y); bool hasPopupAt(const Vector2D& pos); int popupsCount(); - void applyGroupRules(); void createGroup(); void destroyGroup(); @@ -481,6 +474,12 @@ class CWindow { void unsetWindowData(eOverridePriority priority); bool isX11OverrideRedirect(); bool isModal(); + Vector2D requestedMinSize(); + Vector2D requestedMaxSize(); + + inline CBox getWindowMainSurfaceBox() const { + return {m_vRealPosition.value().x, m_vRealPosition.value().y, m_vRealSize.value().x, m_vRealSize.value().y}; + } // listeners void onAck(uint32_t serial); diff --git a/src/events/Windows.cpp b/src/events/Windows.cpp index 77df7373..73ab45c1 100644 --- a/src/events/Windows.cpp +++ b/src/events/Windows.cpp @@ -346,7 +346,7 @@ void Events::listener_mapWindow(void* owner, void* data) { const auto SIZEXSTR = VALUE.substr(0, VALUE.find(' ')); const auto SIZEYSTR = VALUE.substr(VALUE.find(' ') + 1); - const auto MAXSIZE = g_pXWaylandManager->getMaxSizeForWindow(PWINDOW); + const auto MAXSIZE = PWINDOW->requestedMaxSize(); const float SIZEX = SIZEXSTR == "max" ? std::clamp(MAXSIZE.x, MIN_WINDOW_SIZE, PMONITOR->vecSize.x) : stringToFloatClamp(SIZEXSTR, PWINDOW->m_vRealSize.goal().x, PMONITOR->vecSize.x); @@ -469,7 +469,7 @@ void Events::listener_mapWindow(void* owner, void* data) { const auto SIZEXSTR = VALUE.substr(0, VALUE.find(' ')); const auto SIZEYSTR = VALUE.substr(VALUE.find(' ') + 1); - const auto MAXSIZE = g_pXWaylandManager->getMaxSizeForWindow(PWINDOW); + const auto MAXSIZE = PWINDOW->requestedMaxSize(); const float SIZEX = SIZEXSTR == "max" ? std::clamp(MAXSIZE.x, MIN_WINDOW_SIZE, PMONITOR->vecSize.x) : stringToPercentage(SIZEXSTR, PMONITOR->vecSize.x); @@ -753,8 +753,8 @@ void Events::listener_commitWindow(void* owner, void* data) { PWINDOW->m_vReportedSize = PWINDOW->m_vPendingReportedSize; // apply pending size. We pinged, the window ponged. if (!PWINDOW->m_bIsX11 && !PWINDOW->isFullscreen() && PWINDOW->m_bIsFloating) { - const auto MINSIZE = PWINDOW->m_pXDGSurface->toplevel->current.minSize; - const auto MAXSIZE = PWINDOW->m_pXDGSurface->toplevel->current.maxSize; + const auto MINSIZE = PWINDOW->m_pXDGSurface->toplevel->layoutMinSize(); + const auto MAXSIZE = PWINDOW->m_pXDGSurface->toplevel->layoutMaxSize(); PWINDOW->clampWindowSize(MINSIZE, MAXSIZE > Vector2D{1, 1} ? std::optional{MAXSIZE} : std::nullopt); g_pHyprRenderer->damageWindow(PWINDOW); diff --git a/src/layout/DwindleLayout.cpp b/src/layout/DwindleLayout.cpp index e6e9090f..c3e394f3 100644 --- a/src/layout/DwindleLayout.cpp +++ b/src/layout/DwindleLayout.cpp @@ -283,7 +283,7 @@ void CHyprDwindleLayout::onWindowCreatedTiling(PHLWINDOW pWindow, eDirection dir // first, check if OPENINGON isn't too big. const auto PREDSIZEMAX = OPENINGON ? Vector2D(OPENINGON->box.w, OPENINGON->box.h) : PMONITOR->vecSize; - if (const auto MAXSIZE = g_pXWaylandManager->getMaxSizeForWindow(pWindow); MAXSIZE.x < PREDSIZEMAX.x || MAXSIZE.y < PREDSIZEMAX.y) { + if (const auto MAXSIZE = pWindow->requestedMaxSize(); MAXSIZE.x < PREDSIZEMAX.x || MAXSIZE.y < PREDSIZEMAX.y) { // we can't continue. make it floating. pWindow->m_bIsFloating = true; m_lDwindleNodesData.remove(*PNODE); diff --git a/src/layout/IHyprLayout.cpp b/src/layout/IHyprLayout.cpp index a312555f..af8b907c 100644 --- a/src/layout/IHyprLayout.cpp +++ b/src/layout/IHyprLayout.cpp @@ -597,12 +597,12 @@ void IHyprLayout::onMouseMove(const Vector2D& mousePos) { } else if (g_pInputManager->dragMode == MBIND_RESIZE || g_pInputManager->dragMode == MBIND_RESIZE_FORCE_RATIO || g_pInputManager->dragMode == MBIND_RESIZE_BLOCK_RATIO) { if (DRAGGINGWINDOW->m_bIsFloating) { - Vector2D MINSIZE = g_pXWaylandManager->getMinSizeForWindow(DRAGGINGWINDOW).clamp(DRAGGINGWINDOW->m_sWindowData.minSize.valueOr(Vector2D(20, 20))); + Vector2D MINSIZE = DRAGGINGWINDOW->requestedMinSize().clamp(DRAGGINGWINDOW->m_sWindowData.minSize.valueOr(Vector2D(20, 20))); Vector2D MAXSIZE; if (DRAGGINGWINDOW->m_sWindowData.maxSize.hasValue()) - MAXSIZE = g_pXWaylandManager->getMaxSizeForWindow(DRAGGINGWINDOW).clamp({}, DRAGGINGWINDOW->m_sWindowData.maxSize.value()); + MAXSIZE = DRAGGINGWINDOW->requestedMaxSize().clamp({}, DRAGGINGWINDOW->m_sWindowData.maxSize.value()); else - MAXSIZE = g_pXWaylandManager->getMaxSizeForWindow(DRAGGINGWINDOW).clamp({}, Vector2D(std::numeric_limits::max(), std::numeric_limits::max())); + MAXSIZE = DRAGGINGWINDOW->requestedMaxSize().clamp({}, Vector2D(std::numeric_limits::max(), std::numeric_limits::max())); Vector2D newSize = m_vBeginDragSizeXY; Vector2D newPos = m_vBeginDragPositionXY; @@ -884,7 +884,7 @@ Vector2D IHyprLayout::predictSizeForNewWindowFloating(PHLWINDOW pWindow) { // ge const auto SIZEXSTR = VALUE.substr(0, VALUE.find(' ')); const auto SIZEYSTR = VALUE.substr(VALUE.find(' ') + 1); - const auto MAXSIZE = g_pXWaylandManager->getMaxSizeForWindow(pWindow); + const auto MAXSIZE = pWindow->requestedMaxSize(); const float SIZEX = SIZEXSTR == "max" ? std::clamp(MAXSIZE.x, MIN_WINDOW_SIZE, g_pCompositor->m_pLastMonitor->vecSize.x) : stringToPercentage(SIZEXSTR, g_pCompositor->m_pLastMonitor->vecSize.x); diff --git a/src/layout/MasterLayout.cpp b/src/layout/MasterLayout.cpp index b8b3efea..695dcc99 100644 --- a/src/layout/MasterLayout.cpp +++ b/src/layout/MasterLayout.cpp @@ -200,7 +200,7 @@ void CHyprMasterLayout::onWindowCreatedTiling(PHLWINDOW pWindow, eDirection dire PNODE->percMaster = lastSplitPercent; // first, check if it isn't too big. - if (const auto MAXSIZE = g_pXWaylandManager->getMaxSizeForWindow(pWindow); MAXSIZE.x < PMONITOR->vecSize.x * lastSplitPercent || MAXSIZE.y < PMONITOR->vecSize.y) { + if (const auto MAXSIZE = pWindow->requestedMaxSize(); MAXSIZE.x < PMONITOR->vecSize.x * lastSplitPercent || MAXSIZE.y < PMONITOR->vecSize.y) { // we can't continue. make it floating. pWindow->m_bIsFloating = true; m_lMasterNodesData.remove(*PNODE); @@ -212,7 +212,7 @@ void CHyprMasterLayout::onWindowCreatedTiling(PHLWINDOW pWindow, eDirection dire PNODE->percMaster = lastSplitPercent; // first, check if it isn't too big. - if (const auto MAXSIZE = g_pXWaylandManager->getMaxSizeForWindow(pWindow); + if (const auto MAXSIZE = pWindow->requestedMaxSize(); MAXSIZE.x < PMONITOR->vecSize.x * (1 - lastSplitPercent) || MAXSIZE.y < PMONITOR->vecSize.y * (1.f / (WINDOWSONWORKSPACE - 1))) { // we can't continue. make it floating. pWindow->m_bIsFloating = true; diff --git a/src/managers/XWaylandManager.cpp b/src/managers/XWaylandManager.cpp index d0dda8e6..832173eb 100644 --- a/src/managers/XWaylandManager.cpp +++ b/src/managers/XWaylandManager.cpp @@ -213,36 +213,6 @@ void CHyprXWaylandManager::setWindowFullscreen(PHLWINDOW pWindow, bool fullscree pWindow->m_pXDGSurface->toplevel->setFullscreen(fullscreen); } -Vector2D CHyprXWaylandManager::getMaxSizeForWindow(PHLWINDOW pWindow) { - constexpr int NO_MAX_SIZE_LIMIT = 99999; - if (!validMapped(pWindow) || - ((pWindow->m_bIsX11 && !pWindow->m_pXWaylandSurface->sizeHints) || (!pWindow->m_bIsX11 && !pWindow->m_pXDGSurface->toplevel) || - pWindow->m_sWindowData.noMaxSize.valueOrDefault())) - return Vector2D(NO_MAX_SIZE_LIMIT, NO_MAX_SIZE_LIMIT); - - Vector2D maxSize = pWindow->m_bIsX11 ? Vector2D(pWindow->m_pXWaylandSurface->sizeHints->max_width, pWindow->m_pXWaylandSurface->sizeHints->max_height) : - pWindow->m_pXDGSurface->toplevel->current.maxSize; - - if (maxSize.x < 5) - maxSize.x = NO_MAX_SIZE_LIMIT; - if (maxSize.y < 5) - maxSize.y = NO_MAX_SIZE_LIMIT; - - return maxSize; -} - -Vector2D CHyprXWaylandManager::getMinSizeForWindow(PHLWINDOW pWindow) { - if (!validMapped(pWindow) || ((pWindow->m_bIsX11 && !pWindow->m_pXWaylandSurface->sizeHints) || (!pWindow->m_bIsX11 && !pWindow->m_pXDGSurface->toplevel))) - return Vector2D(0, 0); - - Vector2D minSize = pWindow->m_bIsX11 ? Vector2D(pWindow->m_pXWaylandSurface->sizeHints->min_width, pWindow->m_pXWaylandSurface->sizeHints->min_height) : - pWindow->m_pXDGSurface->toplevel->current.minSize; - - minSize = minSize.clamp({1, 1}); - - return minSize; -} - Vector2D CHyprXWaylandManager::xwaylandToWaylandCoords(const Vector2D& coord) { static auto PXWLFORCESCALEZERO = CConfigValue("xwayland:force_zero_scaling"); diff --git a/src/managers/XWaylandManager.hpp b/src/managers/XWaylandManager.hpp index a9f95974..508a20d6 100644 --- a/src/managers/XWaylandManager.hpp +++ b/src/managers/XWaylandManager.hpp @@ -21,8 +21,6 @@ class CHyprXWaylandManager { void setWindowFullscreen(PHLWINDOW, bool); bool shouldBeFloated(PHLWINDOW, bool pending = false); void checkBorders(PHLWINDOW); - Vector2D getMaxSizeForWindow(PHLWINDOW); - Vector2D getMinSizeForWindow(PHLWINDOW); Vector2D xwaylandToWaylandCoords(const Vector2D&); }; diff --git a/src/protocols/XDGShell.cpp b/src/protocols/XDGShell.cpp index 25d8b1ba..932882e9 100644 --- a/src/protocols/XDGShell.cpp +++ b/src/protocols/XDGShell.cpp @@ -323,6 +323,14 @@ void CXDGToplevelResource::close() { resource->sendClose(); } +Vector2D CXDGToplevelResource::layoutMinSize() { + return owner ? current.minSize + owner->current.geometry.pos() : current.minSize; +} + +Vector2D CXDGToplevelResource::layoutMaxSize() { + return owner ? current.maxSize + owner->current.geometry.pos() : current.maxSize; +} + CXDGSurfaceResource::CXDGSurfaceResource(SP resource_, SP owner_, SP surface_) : owner(owner_), surface(surface_), resource(resource_) { if (!good()) diff --git a/src/protocols/XDGShell.hpp b/src/protocols/XDGShell.hpp index 9c766c20..ef847f3b 100644 --- a/src/protocols/XDGShell.hpp +++ b/src/protocols/XDGShell.hpp @@ -99,6 +99,9 @@ class CXDGToplevelResource { bool good(); + Vector2D layoutMinSize(); + Vector2D layoutMaxSize(); + // schedule a configure event uint32_t setSize(const Vector2D& size); uint32_t setMaximized(bool maximized); From 9b03307653c179a86a8dfdb4e5d16446d0cf6e23 Mon Sep 17 00:00:00 2001 From: Alessio Molinari Date: Sun, 17 Nov 2024 20:34:03 +0100 Subject: [PATCH 0650/2181] hooks: add pre connected/disconnected monitor events (#8503) --- src/helpers/Monitor.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/helpers/Monitor.cpp b/src/helpers/Monitor.cpp index bfab2fd3..9ac48220 100644 --- a/src/helpers/Monitor.cpp +++ b/src/helpers/Monitor.cpp @@ -39,6 +39,7 @@ CMonitor::~CMonitor() { } void CMonitor::onConnect(bool noRule) { + EMIT_HOOK_EVENT("preMonitorAdded", self.lock()); CScopeGuard x = {[]() { g_pCompositor->arrangeMonitors(); }}; if (output->supportsExplicit) { @@ -238,6 +239,7 @@ void CMonitor::onConnect(bool noRule) { } void CMonitor::onDisconnect(bool destroy) { + EMIT_HOOK_EVENT("preMonitorRemoved", self.lock()); CScopeGuard x = {[this]() { if (g_pCompositor->m_bIsShuttingDown) return; From e8717a4fce1eafa44d5b106b8159d56e8d368840 Mon Sep 17 00:00:00 2001 From: Vaxry Date: Sun, 17 Nov 2024 21:57:00 +0000 Subject: [PATCH 0651/2181] shell: don't use fgrep, prefer grep -F --- src/debug/CrashReporter.cpp | 2 +- src/debug/HyprCtl.cpp | 2 +- src/helpers/MiscFunctions.cpp | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/debug/CrashReporter.cpp b/src/debug/CrashReporter.cpp index 000d8c5d..319c1414 100644 --- a/src/debug/CrashReporter.cpp +++ b/src/debug/CrashReporter.cpp @@ -159,7 +159,7 @@ void CrashReporter::createAndSaveCrash(int sig) { finalCrashReport += "GPU:\n\t"; #if defined(__DragonFly__) || defined(__FreeBSD__) - finalCrashReport.writeCmdOutput("pciconf -lv | fgrep -A4 vga"); + finalCrashReport.writeCmdOutput("pciconf -lv | grep -F -A4 vga"); #else finalCrashReport.writeCmdOutput("lspci -vnn | grep VGA"); #endif diff --git a/src/debug/HyprCtl.cpp b/src/debug/HyprCtl.cpp index 964a193b..6c9c2b75 100644 --- a/src/debug/HyprCtl.cpp +++ b/src/debug/HyprCtl.cpp @@ -946,7 +946,7 @@ std::string systemInfoRequest(eHyprCtlOutputFormat format, std::string request) result += "\n\n"; #if defined(__DragonFly__) || defined(__FreeBSD__) - const std::string GPUINFO = execAndGet("pciconf -lv | fgrep -A4 vga"); + const std::string GPUINFO = execAndGet("pciconf -lv | grep -F -A4 vga"); #elif defined(__arm__) || defined(__aarch64__) std::string GPUINFO; const std::filesystem::path dev_tree = "/proc/device-tree"; diff --git a/src/helpers/MiscFunctions.cpp b/src/helpers/MiscFunctions.cpp index 7b4d63a7..cfaae542 100644 --- a/src/helpers/MiscFunctions.cpp +++ b/src/helpers/MiscFunctions.cpp @@ -606,7 +606,7 @@ void logSystemInfo() { Debug::log(NONE, "\n"); #if defined(__DragonFly__) || defined(__FreeBSD__) - const std::string GPUINFO = execAndGet("pciconf -lv | fgrep -A4 vga"); + const std::string GPUINFO = execAndGet("pciconf -lv | grep -F -A4 vga"); #elif defined(__arm__) || defined(__aarch64__) const std::string GPUINFO = execAndGet("cat /proc/device-tree/soc*/gpu*/compatible"); #else From 1ba050d603dca644aca48872f62388d794c030b9 Mon Sep 17 00:00:00 2001 From: Vaxry Date: Sun, 17 Nov 2024 21:58:00 +0000 Subject: [PATCH 0652/2181] shell: propagate new machanism from hyprctl to miscfunctions --- src/helpers/MiscFunctions.cpp | 19 ++++++++++++++++++- 1 file changed, 18 insertions(+), 1 deletion(-) diff --git a/src/helpers/MiscFunctions.cpp b/src/helpers/MiscFunctions.cpp index cfaae542..6ad1b37a 100644 --- a/src/helpers/MiscFunctions.cpp +++ b/src/helpers/MiscFunctions.cpp @@ -608,7 +608,24 @@ void logSystemInfo() { #if defined(__DragonFly__) || defined(__FreeBSD__) const std::string GPUINFO = execAndGet("pciconf -lv | grep -F -A4 vga"); #elif defined(__arm__) || defined(__aarch64__) - const std::string GPUINFO = execAndGet("cat /proc/device-tree/soc*/gpu*/compatible"); + const std::string GPUINFO; + const std::filesystem::path dev_tree = "/proc/device-tree"; + try { + if (std::filesystem::exists(dev_tree) && std::filesystem::is_directory(dev_tree)) { + std::for_each(std::filesystem::directory_iterator(dev_tree), std::filesystem::directory_iterator{}, [&](const std::filesystem::directory_entry& entry) { + if (std::filesystem::is_directory(entry) && entry.path().filename().string().starts_with("soc")) { + std::for_each(std::filesystem::directory_iterator(entry.path()), std::filesystem::directory_iterator{}, [&](const std::filesystem::directory_entry& sub_entry) { + if (std::filesystem::is_directory(sub_entry) && sub_entry.path().filename().string().starts_with("gpu")) { + std::filesystem::path file_path = sub_entry.path() / "compatible"; + std::ifstream file(file_path); + if (file) + GPUINFO.append(std::istreambuf_iterator(file), std::istreambuf_iterator()); + } + }); + } + }); + } + } catch (...) { GPUINFO = "error"; } #else const std::string GPUINFO = execAndGet("lspci -vnn | grep VGA"); #endif From 2259a885513e8ec793210ceb9d40ca096161849d Mon Sep 17 00:00:00 2001 From: Vaxry Date: Mon, 18 Nov 2024 13:59:57 +0000 Subject: [PATCH 0653/2181] miscfunctions: add missing include --- src/helpers/MiscFunctions.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/src/helpers/MiscFunctions.cpp b/src/helpers/MiscFunctions.cpp index 6ad1b37a..c7cd9ed4 100644 --- a/src/helpers/MiscFunctions.cpp +++ b/src/helpers/MiscFunctions.cpp @@ -6,6 +6,7 @@ #include #include #include +#include #include #include #include From 6744bb57c639d5359a414eea2566328bb05c7065 Mon Sep 17 00:00:00 2001 From: johannes hanika Date: Mon, 18 Nov 2024 15:02:34 +0100 Subject: [PATCH 0654/2181] constraints: don't warp pointer position on release (#8491) this was annoying for nuklear properties/ui slider elements that grab the pointer via GLFW_CURSOR_DISABLE to allow more range and finer control. upon mouse release, the pointer is reset to the middle of the window without this patch, making long mouse movements necessary to go back to the original position for readjustments. fwiw the new behaviour is consistent with x11 and weston. --- src/protocols/PointerConstraints.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/protocols/PointerConstraints.cpp b/src/protocols/PointerConstraints.cpp index 0f2dd991..7f08a7df 100644 --- a/src/protocols/PointerConstraints.cpp +++ b/src/protocols/PointerConstraints.cpp @@ -188,7 +188,7 @@ Vector2D CPointerConstraint::logicPositionHint() { const auto SURFBOX = pHLSurface->getSurfaceBoxGlobal(); const auto CONSTRAINTPOS = SURFBOX.has_value() ? SURFBOX->pos() : Vector2D{}; - return hintSet ? CONSTRAINTPOS + positionHint : (locked ? CONSTRAINTPOS + SURFBOX->size() / 2.f : cursorPosOnActivate); + return hintSet ? CONSTRAINTPOS + positionHint : cursorPosOnActivate; } CPointerConstraintsProtocol::CPointerConstraintsProtocol(const wl_interface* iface, const int& ver, const std::string& name) : IWaylandProtocol(iface, ver, name) { From 505c1f8f4a5a4a97534f1906a47c11de638d970d Mon Sep 17 00:00:00 2001 From: Vaxry Date: Mon, 18 Nov 2024 14:35:09 +0000 Subject: [PATCH 0655/2181] miscfunctions: fix cross build --- src/helpers/MiscFunctions.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/helpers/MiscFunctions.cpp b/src/helpers/MiscFunctions.cpp index c7cd9ed4..c8b3bef4 100644 --- a/src/helpers/MiscFunctions.cpp +++ b/src/helpers/MiscFunctions.cpp @@ -609,7 +609,7 @@ void logSystemInfo() { #if defined(__DragonFly__) || defined(__FreeBSD__) const std::string GPUINFO = execAndGet("pciconf -lv | grep -F -A4 vga"); #elif defined(__arm__) || defined(__aarch64__) - const std::string GPUINFO; + std::string GPUINFO; const std::filesystem::path dev_tree = "/proc/device-tree"; try { if (std::filesystem::exists(dev_tree) && std::filesystem::is_directory(dev_tree)) { From 97493511f96af288e1f7b2bd3a119e47d75541fc Mon Sep 17 00:00:00 2001 From: Aqa-Ib Date: Mon, 18 Nov 2024 15:44:15 +0100 Subject: [PATCH 0656/2181] internal: fix changeWindowZOrder reordering incorrectly (#8494) --- src/Compositor.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/Compositor.cpp b/src/Compositor.cpp index fbbfd7e7..0e0c75a1 100644 --- a/src/Compositor.cpp +++ b/src/Compositor.cpp @@ -1389,6 +1389,9 @@ void CCompositor::changeWindowZOrder(PHLWINDOW pWindow, bool top) { if (!validMapped(pWindow)) return; + if (top) + pWindow->m_bCreatedOverFullscreen = true; + if (pWindow == (top ? m_vWindows.back() : m_vWindows.front())) return; @@ -1413,9 +1416,6 @@ void CCompositor::changeWindowZOrder(PHLWINDOW pWindow, bool top) { g_pHyprRenderer->damageMonitor(pw->m_pMonitor.lock()); }; - if (top) - pWindow->m_bCreatedOverFullscreen = true; - if (!pWindow->m_bIsX11) moveToZ(pWindow, top); else { From df9ff4489973afa9e29bb94ac47c946db745b460 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=F0=9F=87=BA=F0=9F=87=A6=20Sviatoslav=20Sydorenko=20=28?= =?UTF-8?q?=D0=A1=D0=B2=D1=8F=D1=82=D0=BE=D1=81=D0=BB=D0=B0=D0=B2=20=D0=A1?= =?UTF-8?q?=D0=B8=D0=B4=D0=BE=D1=80=D0=B5=D0=BD=D0=BA=D0=BE=29?= Date: Mon, 18 Nov 2024 16:54:18 +0100 Subject: [PATCH 0657/2181] Fix example config name in auto-generated cfg header (#8509) Previously, it was suggesting to find `hypr.conf` in the `examples/` folder which doesn't exist. This patch fixed that to point to the existing file. Additionally, the change updates `HYPR` to `HYPRLAND` in the same header. --- src/config/defaultConfig.hpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/config/defaultConfig.hpp b/src/config/defaultConfig.hpp index d680e92b..c4eb3385 100644 --- a/src/config/defaultConfig.hpp +++ b/src/config/defaultConfig.hpp @@ -4,8 +4,8 @@ inline const std::string AUTOCONFIG = R"#( # ####################################################################################### -# AUTOGENERATED HYPR CONFIG. -# PLEASE USE THE CONFIG PROVIDED IN THE GIT REPO /examples/hypr.conf AND EDIT IT, +# AUTOGENERATED HYPRLAND CONFIG. +# PLEASE USE THE CONFIG PROVIDED IN THE GIT REPO /examples/hyprland.conf AND EDIT IT, # OR EDIT THIS ONE ACCORDING TO THE WIKI INSTRUCTIONS. # ####################################################################################### From cc923ad031579a5d1ebe07269d5ecb291331ee51 Mon Sep 17 00:00:00 2001 From: Maximilian Seidler <78690852+PaideiaDilemma@users.noreply.github.com> Date: Mon, 18 Nov 2024 20:45:22 +0100 Subject: [PATCH 0658/2181] config: update the configStringToInt implementation (#8476) Copied from hyprlang and removed std::expected. --- src/helpers/MiscFunctions.cpp | 74 ++++++++++++++++++++++++++--------- 1 file changed, 55 insertions(+), 19 deletions(-) diff --git a/src/helpers/MiscFunctions.cpp b/src/helpers/MiscFunctions.cpp index c8b3bef4..80681826 100644 --- a/src/helpers/MiscFunctions.cpp +++ b/src/helpers/MiscFunctions.cpp @@ -692,43 +692,79 @@ int64_t getPPIDof(int64_t pid) { } int64_t configStringToInt(const std::string& VALUE) { + auto parseHex = [](const std::string& value) -> int64_t { + try { + size_t position; + auto result = stoll(value, &position, 16); + if (position == value.size()) + return result; + } catch (const std::exception&) {} + throw std::invalid_argument("invalid hex " + value); + }; if (VALUE.starts_with("0x")) { // Values with 0x are hex - const auto VALUEWITHOUTHEX = VALUE.substr(2); - return stol(VALUEWITHOUTHEX, nullptr, 16); + return parseHex(VALUE); } else if (VALUE.starts_with("rgba(") && VALUE.ends_with(')')) { - const auto VALUEWITHOUTFUNC = VALUE.substr(5, VALUE.length() - 6); + const auto VALUEWITHOUTFUNC = trim(VALUE.substr(5, VALUE.length() - 6)); - if (trim(VALUEWITHOUTFUNC).length() != 8) { - Debug::log(WARN, "invalid length {} for rgba", VALUEWITHOUTFUNC.length()); - throw std::invalid_argument("rgba() expects length of 8 characters (4 bytes)"); + // try doing it the comma way first + if (std::count(VALUEWITHOUTFUNC.begin(), VALUEWITHOUTFUNC.end(), ',') == 3) { + // cool + std::string rolling = VALUEWITHOUTFUNC; + auto r = configStringToInt(trim(rolling.substr(0, rolling.find(',')))); + rolling = rolling.substr(rolling.find(',') + 1); + auto g = configStringToInt(trim(rolling.substr(0, rolling.find(',')))); + rolling = rolling.substr(rolling.find(',') + 1); + auto b = configStringToInt(trim(rolling.substr(0, rolling.find(',')))); + rolling = rolling.substr(rolling.find(',') + 1); + uint8_t a = 0; + try { + a = std::round(std::stof(trim(rolling.substr(0, rolling.find(',')))) * 255.f); + } catch (std::exception& e) { throw std::invalid_argument("failed parsing " + VALUEWITHOUTFUNC); } + + return a * (Hyprlang::INT)0x1000000 + r * (Hyprlang::INT)0x10000 + g * (Hyprlang::INT)0x100 + b; + } else if (VALUEWITHOUTFUNC.length() == 8) { + const auto RGBA = parseHex(VALUEWITHOUTFUNC); + // now we need to RGBA -> ARGB. The config holds ARGB only. + return (RGBA >> 8) + 0x1000000 * (RGBA & 0xFF); } - const auto RGBA = std::stol(VALUEWITHOUTFUNC, nullptr, 16); + throw std::invalid_argument("rgba() expects length of 8 characters (4 bytes) or 4 comma separated values"); - // now we need to RGBA -> ARGB. The config holds ARGB only. - return (RGBA >> 8) + 0x1000000 * (RGBA & 0xFF); } else if (VALUE.starts_with("rgb(") && VALUE.ends_with(')')) { - const auto VALUEWITHOUTFUNC = VALUE.substr(4, VALUE.length() - 5); + const auto VALUEWITHOUTFUNC = trim(VALUE.substr(4, VALUE.length() - 5)); - if (trim(VALUEWITHOUTFUNC).length() != 6) { - Debug::log(WARN, "invalid length {} for rgb", VALUEWITHOUTFUNC.length()); - throw std::invalid_argument("rgb() expects length of 6 characters (3 bytes)"); + // try doing it the comma way first + if (std::count(VALUEWITHOUTFUNC.begin(), VALUEWITHOUTFUNC.end(), ',') == 2) { + // cool + std::string rolling = VALUEWITHOUTFUNC; + auto r = configStringToInt(trim(rolling.substr(0, rolling.find(',')))); + rolling = rolling.substr(rolling.find(',') + 1); + auto g = configStringToInt(trim(rolling.substr(0, rolling.find(',')))); + rolling = rolling.substr(rolling.find(',') + 1); + auto b = configStringToInt(trim(rolling.substr(0, rolling.find(',')))); + + return (Hyprlang::INT)0xFF000000 + r * (Hyprlang::INT)0x10000 + g * (Hyprlang::INT)0x100 + b; + } else if (VALUEWITHOUTFUNC.length() == 6) { + return parseHex(VALUEWITHOUTFUNC) + 0xFF000000; } - const auto RGB = std::stol(VALUEWITHOUTFUNC, nullptr, 16); - - return RGB + 0xFF000000; // 0xFF for opaque + throw std::invalid_argument("rgb() expects length of 6 characters (3 bytes) or 3 comma separated values"); } else if (VALUE.starts_with("true") || VALUE.starts_with("on") || VALUE.starts_with("yes")) { return 1; } else if (VALUE.starts_with("false") || VALUE.starts_with("off") || VALUE.starts_with("no")) { return 0; } - if (VALUE.empty() || !isNumber(VALUE)) - return 0; + if (VALUE.empty() || !isNumber(VALUE, false)) + throw std::invalid_argument("cannot parse \"" + VALUE + "\" as an int."); - return std::stoll(VALUE); + try { + const auto RES = std::stoll(VALUE); + return RES; + } catch (std::exception& e) { throw std::invalid_argument(std::string{"stoll threw: "} + e.what()); } + + return 0; } Vector2D configStringToVector2D(const std::string& VALUE) { From 6113f4da7fa9839645525e57ff841db5bb00e475 Mon Sep 17 00:00:00 2001 From: MightyPlaza <123664421+MightyPlaza@users.noreply.github.com> Date: Mon, 18 Nov 2024 19:48:13 +0000 Subject: [PATCH 0659/2181] keybinds: allow repeating multiple binds (#8290) --- src/managers/KeybindManager.cpp | 69 +++++++++++++++------------------ src/managers/KeybindManager.hpp | 7 ++-- 2 files changed, 34 insertions(+), 42 deletions(-) diff --git a/src/managers/KeybindManager.cpp b/src/managers/KeybindManager.cpp index 4d2f4dcc..a0cd01a9 100644 --- a/src/managers/KeybindManager.cpp +++ b/src/managers/KeybindManager.cpp @@ -144,11 +144,30 @@ CKeybindManager::CKeybindManager() { }, nullptr); + m_pRepeatKeyTimer = makeShared( + std::nullopt, + [this](SP self, void* data) { + if (m_vActiveKeybinds.size() == 0 || g_pSeatManager->keyboard.expired()) + return; + + for (SKeybind* k : m_vActiveKeybinds) { + const auto DISPATCHER = g_pKeybindManager->m_mDispatchers.find(k->handler); + + Debug::log(LOG, "Keybind repeat triggered, calling dispatcher."); + DISPATCHER->second(k->arg); + } + + const auto PACTIVEKEEB = g_pSeatManager->keyboard.lock(); + self->updateTimeout(std::chrono::milliseconds(1000 / PACTIVEKEEB->repeatRate)); + }, + nullptr); + g_pEventLoopManager->addTimer(m_pLongPressTimer); + g_pEventLoopManager->addTimer(m_pRepeatKeyTimer); static auto P = g_pHookSystem->hookDynamic("configReloaded", [this](void* hk, SCallbackInfo& info, std::any param) { // clear cuz realloc'd - m_pActiveKeybind = nullptr; + m_vActiveKeybinds.clear(); m_pLastLongPressKeybind = nullptr; m_vPressedSpecialBinds.clear(); }); @@ -161,12 +180,16 @@ CKeybindManager::~CKeybindManager() { g_pEventLoopManager->removeTimer(m_pLongPressTimer); m_pLongPressTimer.reset(); } + if (m_pRepeatKeyTimer && g_pEventLoopManager) { + g_pEventLoopManager->removeTimer(m_pRepeatKeyTimer); + m_pRepeatKeyTimer.reset(); + } } void CKeybindManager::addKeybind(SKeybind kb) { m_lKeybinds.push_back(kb); - m_pActiveKeybind = nullptr; + m_vActiveKeybinds.clear(); m_pLastLongPressKeybind = nullptr; } @@ -180,7 +203,7 @@ void CKeybindManager::removeKeybind(uint32_t mod, const SParsedKey& key) { } } - m_pActiveKeybind = nullptr; + m_vActiveKeybinds.clear(); m_pLastLongPressKeybind = nullptr; } @@ -426,11 +449,7 @@ bool CKeybindManager::onKeyEvent(std::any event, SP pKeyboard) { .submapAtPress = m_szCurrentSelectedSubmap, }; - if (m_pActiveKeybindEventSource) { - wl_event_source_remove(m_pActiveKeybindEventSource); - m_pActiveKeybindEventSource = nullptr; - m_pActiveKeybind = nullptr; - } + m_vActiveKeybinds.clear(); m_pLastLongPressKeybind = nullptr; @@ -482,11 +501,7 @@ bool CKeybindManager::onAxisEvent(const IPointer::SAxisEvent& e) { m_tScrollTimer.reset(); - if (m_pActiveKeybindEventSource) { - wl_event_source_remove(m_pActiveKeybindEventSource); - m_pActiveKeybindEventSource = nullptr; - m_pActiveKeybind = nullptr; - } + m_vActiveKeybinds.clear(); bool found = false; if (e.source == WL_POINTER_AXIS_SOURCE_WHEEL && e.axis == WL_POINTER_AXIS_VERTICAL_SCROLL) { @@ -525,11 +540,7 @@ bool CKeybindManager::onMouseEvent(const IPointer::SButtonEvent& e) { .modmaskAtPressTime = MODS, }; - if (m_pActiveKeybindEventSource) { - wl_event_source_remove(m_pActiveKeybindEventSource); - m_pActiveKeybindEventSource = nullptr; - m_pActiveKeybind = nullptr; - } + m_vActiveKeybinds.clear(); if (e.state == WL_POINTER_BUTTON_STATE_PRESSED) { m_dPressedKeys.push_back(KEY); @@ -580,22 +591,6 @@ void CKeybindManager::onSwitchOffEvent(const std::string& switchName) { handleKeybinds(0, SPressedKeyWithMods{.keyName = "switch:off:" + switchName}, true); } -int repeatKeyHandler(void* data) { - SKeybind** ppActiveKeybind = (SKeybind**)data; - - if (!*ppActiveKeybind || g_pSeatManager->keyboard.expired()) - return 0; - - const auto DISPATCHER = g_pKeybindManager->m_mDispatchers.find((*ppActiveKeybind)->handler); - - Debug::log(LOG, "Keybind repeat triggered, calling dispatcher."); - DISPATCHER->second((*ppActiveKeybind)->arg); - - wl_event_source_timer_update(g_pKeybindManager->m_pActiveKeybindEventSource, 1000 / g_pSeatManager->keyboard->repeatRate); - - return 0; -} - eMultiKeyCase CKeybindManager::mkKeysymSetMatches(const std::set keybindKeysyms, const std::set pressedKeysyms) { // Returns whether two sets of keysyms are equal, partially equal, or not // matching. (Partially matching means that pressed is a subset of bound) @@ -770,12 +765,10 @@ SDispatchResult CKeybindManager::handleKeybinds(const uint32_t modmask, const SP } if (k.repeat) { - m_pActiveKeybind = &k; - m_pActiveKeybindEventSource = wl_event_loop_add_timer(g_pCompositor->m_sWLEventLoop, repeatKeyHandler, &m_pActiveKeybind); - const auto PACTIVEKEEB = g_pSeatManager->keyboard.lock(); - wl_event_source_timer_update(m_pActiveKeybindEventSource, PACTIVEKEEB->repeatDelay); + m_vActiveKeybinds.push_back(&k); + m_pRepeatKeyTimer->updateTimeout(std::chrono::milliseconds(PACTIVEKEEB->repeatDelay)); } if (!k.nonConsuming) diff --git a/src/managers/KeybindManager.hpp b/src/managers/KeybindManager.hpp index 4a0af6e9..d375db0f 100644 --- a/src/managers/KeybindManager.hpp +++ b/src/managers/KeybindManager.hpp @@ -102,8 +102,6 @@ class CKeybindManager { std::unordered_map> m_mDispatchers; - wl_event_source* m_pActiveKeybindEventSource = nullptr; - bool m_bGroupsLocked = false; std::list m_lKeybinds; @@ -121,8 +119,9 @@ class CKeybindManager { inline static std::string m_szCurrentSelectedSubmap = ""; - SKeybind * m_pActiveKeybind = nullptr, *m_pLastLongPressKeybind = nullptr; - SP m_pLongPressTimer; + std::vector m_vActiveKeybinds; + SKeybind* m_pLastLongPressKeybind = nullptr; + SP m_pLongPressTimer, m_pRepeatKeyTimer; uint32_t m_uTimeLastMs = 0; uint32_t m_uLastCode = 0; From 936dfedbadbae761cd307ba7509467b55ac5e1ae Mon Sep 17 00:00:00 2001 From: Vaxry Date: Mon, 18 Nov 2024 19:56:26 +0000 Subject: [PATCH 0660/2181] keybinds: move to managed pointers --- src/debug/HyprCtl.cpp | 26 ++++---- src/managers/KeybindManager.cpp | 107 +++++++++++++++----------------- src/managers/KeybindManager.hpp | 10 +-- 3 files changed, 68 insertions(+), 75 deletions(-) diff --git a/src/debug/HyprCtl.cpp b/src/debug/HyprCtl.cpp index 6c9c2b75..1b94296f 100644 --- a/src/debug/HyprCtl.cpp +++ b/src/debug/HyprCtl.cpp @@ -814,28 +814,28 @@ std::string globalShortcutsRequest(eHyprCtlOutputFormat format, std::string requ std::string bindsRequest(eHyprCtlOutputFormat format, std::string request) { std::string ret = ""; if (format == eHyprCtlOutputFormat::FORMAT_NORMAL) { - for (auto const& kb : g_pKeybindManager->m_lKeybinds) { + for (auto const& kb : g_pKeybindManager->m_vKeybinds) { ret += "bind"; - if (kb.locked) + if (kb->locked) ret += "l"; - if (kb.mouse) + if (kb->mouse) ret += "m"; - if (kb.release) + if (kb->release) ret += "r"; - if (kb.repeat) + if (kb->repeat) ret += "e"; - if (kb.nonConsuming) + if (kb->nonConsuming) ret += "n"; - if (kb.hasDescription) + if (kb->hasDescription) ret += "d"; - ret += std::format("\n\tmodmask: {}\n\tsubmap: {}\n\tkey: {}\n\tkeycode: {}\n\tcatchall: {}\n\tdescription: {}\n\tdispatcher: {}\n\targ: {}\n\n", kb.modmask, kb.submap, - kb.key, kb.keycode, kb.catchAll, kb.description, kb.handler, kb.arg); + ret += std::format("\n\tmodmask: {}\n\tsubmap: {}\n\tkey: {}\n\tkeycode: {}\n\tcatchall: {}\n\tdescription: {}\n\tdispatcher: {}\n\targ: {}\n\n", kb->modmask, + kb->submap, kb->key, kb->keycode, kb->catchAll, kb->description, kb->handler, kb->arg); } } else { // json ret += "["; - for (auto const& kb : g_pKeybindManager->m_lKeybinds) { + for (auto const& kb : g_pKeybindManager->m_vKeybinds) { ret += std::format( R"#( {{ @@ -855,9 +855,9 @@ std::string bindsRequest(eHyprCtlOutputFormat format, std::string request) { "dispatcher": "{}", "arg": "{}" }},)#", - kb.locked ? "true" : "false", kb.mouse ? "true" : "false", kb.release ? "true" : "false", kb.repeat ? "true" : "false", kb.longPress ? "true" : "false", - kb.nonConsuming ? "true" : "false", kb.hasDescription ? "true" : "false", kb.modmask, escapeJSONStrings(kb.submap), escapeJSONStrings(kb.key), kb.keycode, - kb.catchAll ? "true" : "false", escapeJSONStrings(kb.description), escapeJSONStrings(kb.handler), escapeJSONStrings(kb.arg)); + kb->locked ? "true" : "false", kb->mouse ? "true" : "false", kb->release ? "true" : "false", kb->repeat ? "true" : "false", kb->longPress ? "true" : "false", + kb->nonConsuming ? "true" : "false", kb->hasDescription ? "true" : "false", kb->modmask, escapeJSONStrings(kb->submap), escapeJSONStrings(kb->key), kb->keycode, + kb->catchAll ? "true" : "false", escapeJSONStrings(kb->description), escapeJSONStrings(kb->handler), escapeJSONStrings(kb->arg)); } trimTrailingComma(ret); ret += "]"; diff --git a/src/managers/KeybindManager.cpp b/src/managers/KeybindManager.cpp index a0cd01a9..995fee17 100644 --- a/src/managers/KeybindManager.cpp +++ b/src/managers/KeybindManager.cpp @@ -150,7 +150,7 @@ CKeybindManager::CKeybindManager() { if (m_vActiveKeybinds.size() == 0 || g_pSeatManager->keyboard.expired()) return; - for (SKeybind* k : m_vActiveKeybinds) { + for (const auto& k : m_vActiveKeybinds) { const auto DISPATCHER = g_pKeybindManager->m_mDispatchers.find(k->handler); Debug::log(LOG, "Keybind repeat triggered, calling dispatcher."); @@ -168,7 +168,7 @@ CKeybindManager::CKeybindManager() { static auto P = g_pHookSystem->hookDynamic("configReloaded", [this](void* hk, SCallbackInfo& info, std::any param) { // clear cuz realloc'd m_vActiveKeybinds.clear(); - m_pLastLongPressKeybind = nullptr; + m_pLastLongPressKeybind.reset(); m_vPressedSpecialBinds.clear(); }); } @@ -187,24 +187,17 @@ CKeybindManager::~CKeybindManager() { } void CKeybindManager::addKeybind(SKeybind kb) { - m_lKeybinds.push_back(kb); + m_vKeybinds.emplace_back(makeShared(kb)); m_vActiveKeybinds.clear(); - m_pLastLongPressKeybind = nullptr; + m_pLastLongPressKeybind.reset(); } void CKeybindManager::removeKeybind(uint32_t mod, const SParsedKey& key) { - for (auto it = m_lKeybinds.begin(); it != m_lKeybinds.end(); ++it) { - if (it->modmask == mod && it->key == key.key && it->keycode == key.keycode && it->catchAll == key.catchAll) { - it = m_lKeybinds.erase(it); - - if (it == m_lKeybinds.end()) - break; - } - } + std::erase_if(m_vKeybinds, [&mod, &key](const auto& el) { return el->modmask == mod && el->key == key.key && el->keycode == key.keycode && el->catchAll == key.catchAll; }); m_vActiveKeybinds.clear(); - m_pLastLongPressKeybind = nullptr; + m_pLastLongPressKeybind.reset(); } uint32_t CKeybindManager::stringToModMask(std::string mods) { @@ -451,7 +444,7 @@ bool CKeybindManager::onKeyEvent(std::any event, SP pKeyboard) { m_vActiveKeybinds.clear(); - m_pLastLongPressKeybind = nullptr; + m_pLastLongPressKeybind.reset(); bool suppressEvent = false; if (e.state == WL_KEYBOARD_KEY_STATE_PRESSED) { @@ -612,11 +605,11 @@ eMultiKeyCase CKeybindManager::mkKeysymSetMatches(const std::set k return MK_NO_MATCH; } -eMultiKeyCase CKeybindManager::mkBindMatches(const SKeybind keybind) { - if (mkKeysymSetMatches(keybind.sMkMods, m_sMkMods) != MK_FULL_MATCH) +eMultiKeyCase CKeybindManager::mkBindMatches(const SP keybind) { + if (mkKeysymSetMatches(keybind->sMkMods, m_sMkMods) != MK_FULL_MATCH) return MK_NO_MATCH; - return mkKeysymSetMatches(keybind.sMkKeys, m_sMkKeys); + return mkKeysymSetMatches(keybind->sMkKeys, m_sMkKeys); } std::string CKeybindManager::getCurrentSubmap() { @@ -640,35 +633,35 @@ SDispatchResult CKeybindManager::handleKeybinds(const uint32_t modmask, const SP m_sMkKeys.erase(key.keysym); } - for (auto& k : m_lKeybinds) { - const bool SPECIALDISPATCHER = k.handler == "global" || k.handler == "pass" || k.handler == "sendshortcut" || k.handler == "mouse"; + for (auto& k : m_vKeybinds) { + const bool SPECIALDISPATCHER = k->handler == "global" || k->handler == "pass" || k->handler == "sendshortcut" || k->handler == "mouse"; const bool SPECIALTRIGGERED = - std::find_if(m_vPressedSpecialBinds.begin(), m_vPressedSpecialBinds.end(), [&](const auto& other) { return other == &k; }) != m_vPressedSpecialBinds.end(); + std::find_if(m_vPressedSpecialBinds.begin(), m_vPressedSpecialBinds.end(), [&](const auto& other) { return other == k; }) != m_vPressedSpecialBinds.end(); const bool IGNORECONDITIONS = SPECIALDISPATCHER && !pressed && SPECIALTRIGGERED; // ignore mods. Pass, global dispatchers should be released immediately once the key is released. - if (!k.dontInhibit && !*PDISABLEINHIBIT && PROTO::shortcutsInhibit->isInhibited()) + if (!k->dontInhibit && !*PDISABLEINHIBIT && PROTO::shortcutsInhibit->isInhibited()) continue; - if (!k.locked && g_pSessionLockManager->isSessionLocked()) + if (!k->locked && g_pSessionLockManager->isSessionLocked()) continue; - if (!IGNORECONDITIONS && ((modmask != k.modmask && !k.ignoreMods) || k.submap != m_szCurrentSelectedSubmap || k.shadowed)) + if (!IGNORECONDITIONS && ((modmask != k->modmask && !k->ignoreMods) || k->submap != m_szCurrentSelectedSubmap || k->shadowed)) continue; - if (k.multiKey) { + if (k->multiKey) { switch (mkBindMatches(k)) { case MK_NO_MATCH: continue; case MK_PARTIAL_MATCH: found = true; continue; case MK_FULL_MATCH: found = true; } } else if (!key.keyName.empty()) { - if (key.keyName != k.key) + if (key.keyName != k->key) continue; - } else if (k.keycode != 0) { - if (key.keycode != k.keycode) + } else if (k->keycode != 0) { + if (key.keycode != k->keycode) continue; - } else if (k.catchAll) { + } else if (k->catchAll) { if (found || key.submapAtPress != m_szCurrentSelectedSubmap) continue; } else { @@ -679,8 +672,8 @@ SDispatchResult CKeybindManager::handleKeybinds(const uint32_t modmask, const SP // oMg such performance hit!!11! // this little maneouver is gonna cost us 4µs - const auto KBKEY = xkb_keysym_from_name(k.key.c_str(), XKB_KEYSYM_NO_FLAGS); - const auto KBKEYLOWER = xkb_keysym_from_name(k.key.c_str(), XKB_KEYSYM_CASE_INSENSITIVE); + const auto KBKEY = xkb_keysym_from_name(k->key.c_str(), XKB_KEYSYM_NO_FLAGS); + const auto KBKEYLOWER = xkb_keysym_from_name(k->key.c_str(), XKB_KEYSYM_CASE_INSENSITIVE); if (KBKEY == XKB_KEY_NoSymbol && KBKEYLOWER == XKB_KEY_NoSymbol) { // Keysym failed to resolve from the key name of the currently iterated bind. @@ -697,8 +690,8 @@ SDispatchResult CKeybindManager::handleKeybinds(const uint32_t modmask, const SP continue; } - if (pressed && k.release && !SPECIALDISPATCHER) { - if (k.nonConsuming) + if (pressed && k->release && !SPECIALDISPATCHER) { + if (k->nonConsuming) continue; found = true; // suppress the event @@ -707,7 +700,7 @@ SDispatchResult CKeybindManager::handleKeybinds(const uint32_t modmask, const SP if (!pressed) { // Require mods to be matching when the key was first pressed. - if (key.modmaskAtPressTime != modmask && !k.ignoreMods) { + if (key.modmaskAtPressTime != modmask && !k->ignoreMods) { // Handle properly `bindr` where a key is itself a bind mod for example: // "bindr = SUPER, SUPER_L, exec, $launcher". // This needs to be handled separately for the above case, because `key.modmaskAtPressTime` is set @@ -716,8 +709,8 @@ SDispatchResult CKeybindManager::handleKeybinds(const uint32_t modmask, const SP if (keycodeToModifier(key.keycode) == key.modmaskAtPressTime) continue; - } else if (!k.release && !SPECIALDISPATCHER) { - if (k.nonConsuming) + } else if (!k->release && !SPECIALDISPATCHER) { + if (k->nonConsuming) continue; found = true; // suppress the event @@ -725,25 +718,25 @@ SDispatchResult CKeybindManager::handleKeybinds(const uint32_t modmask, const SP } } - if (k.longPress) { + if (k->longPress) { const auto PACTIVEKEEB = g_pSeatManager->keyboard.lock(); m_pLongPressTimer->updateTimeout(std::chrono::milliseconds(PACTIVEKEEB->repeatDelay)); - m_pLastLongPressKeybind = &k; + m_pLastLongPressKeybind = k; continue; } - const auto DISPATCHER = m_mDispatchers.find(k.mouse ? "mouse" : k.handler); + const auto DISPATCHER = m_mDispatchers.find(k->mouse ? "mouse" : k->handler); if (SPECIALTRIGGERED && !pressed) - std::erase_if(m_vPressedSpecialBinds, [&](const auto& other) { return other == &k; }); + std::erase_if(m_vPressedSpecialBinds, [&](const auto& other) { return other == k; }); else if (SPECIALDISPATCHER && pressed) - m_vPressedSpecialBinds.push_back(&k); + m_vPressedSpecialBinds.push_back(k); // Should never happen, as we check in the ConfigManager, but oh well if (DISPATCHER == m_mDispatchers.end()) { - Debug::log(ERR, "Invalid handler in a keybind! (handler {} does not exist)", k.handler); + Debug::log(ERR, "Invalid handler in a keybind! (handler {} does not exist)", k->handler); } else { // call the dispatcher Debug::log(LOG, "Keybind triggered, calling dispatcher ({}, {}, {})", modmask, key.keyName, key.keysym); @@ -751,27 +744,27 @@ SDispatchResult CKeybindManager::handleKeybinds(const uint32_t modmask, const SP m_iPassPressed = (int)pressed; // if the dispatchers says to pass event then we will - if (k.handler == "mouse") - res = DISPATCHER->second((pressed ? "1" : "0") + k.arg); + if (k->handler == "mouse") + res = DISPATCHER->second((pressed ? "1" : "0") + k->arg); else - res = DISPATCHER->second(k.arg); + res = DISPATCHER->second(k->arg); m_iPassPressed = -1; - if (k.handler == "submap") { + if (k->handler == "submap") { found = true; // don't process keybinds on submap change. break; } } - if (k.repeat) { + if (k->repeat) { const auto PACTIVEKEEB = g_pSeatManager->keyboard.lock(); - m_vActiveKeybinds.push_back(&k); + m_vActiveKeybinds.push_back(k); m_pRepeatKeyTimer->updateTimeout(std::chrono::milliseconds(PACTIVEKEEB->repeatDelay)); } - if (!k.nonConsuming) + if (!k->nonConsuming) found = true; } @@ -792,17 +785,17 @@ SDispatchResult CKeybindManager::handleKeybinds(const uint32_t modmask, const SP void CKeybindManager::shadowKeybinds(const xkb_keysym_t& doesntHave, const uint32_t doesntHaveCode) { // shadow disables keybinds after one has been triggered - for (auto& k : m_lKeybinds) { + for (auto& k : m_vKeybinds) { bool shadow = false; - if (k.handler == "global" || k.transparent) + if (k->handler == "global" || k->transparent) continue; // can't be shadowed - if (k.multiKey && (mkBindMatches(k) == MK_FULL_MATCH)) + if (k->multiKey && (mkBindMatches(k) == MK_FULL_MATCH)) shadow = true; else { - const auto KBKEY = xkb_keysym_from_name(k.key.c_str(), XKB_KEYSYM_CASE_INSENSITIVE); + const auto KBKEY = xkb_keysym_from_name(k->key.c_str(), XKB_KEYSYM_CASE_INSENSITIVE); const auto KBKEYUPPER = xkb_keysym_to_upper(KBKEY); for (auto const& pk : m_dPressedKeys) { @@ -815,7 +808,7 @@ void CKeybindManager::shadowKeybinds(const xkb_keysym_t& doesntHave, const uint3 } } - if (pk.keycode != 0 && pk.keycode == k.keycode) { + if (pk.keycode != 0 && pk.keycode == k->keycode) { shadow = true; if (pk.keycode == doesntHaveCode && doesntHaveCode != 0) { @@ -826,7 +819,7 @@ void CKeybindManager::shadowKeybinds(const xkb_keysym_t& doesntHave, const uint3 } } - k.shadowed = shadow; + k->shadowed = shadow; } } @@ -1004,7 +997,7 @@ SDispatchResult CKeybindManager::kill(std::string args) { } void CKeybindManager::clearKeybinds() { - m_lKeybinds.clear(); + m_vKeybinds.clear(); } static SDispatchResult toggleActiveFloatingCore(std::string args, std::optional floatState) { @@ -2182,8 +2175,8 @@ SDispatchResult CKeybindManager::setSubmap(std::string submap) { return {}; } - for (auto const& k : g_pKeybindManager->m_lKeybinds) { - if (k.submap == submap) { + for (const auto& k : g_pKeybindManager->m_vKeybinds) { + if (k->submap == submap) { m_szCurrentSelectedSubmap = submap; Debug::log(LOG, "Changed keybind submap to {}", submap); g_pEventManager->postEvent(SHyprIPCEvent{"submap", submap}); diff --git a/src/managers/KeybindManager.hpp b/src/managers/KeybindManager.hpp index d375db0f..1f60fdd2 100644 --- a/src/managers/KeybindManager.hpp +++ b/src/managers/KeybindManager.hpp @@ -104,7 +104,7 @@ class CKeybindManager { bool m_bGroupsLocked = false; - std::list m_lKeybinds; + std::vector> m_vKeybinds; //since we cant find keycode through keyname in xkb: //on sendshortcut call, we once search for keyname (e.g. "g") the correct keycode (e.g. 42) @@ -119,15 +119,15 @@ class CKeybindManager { inline static std::string m_szCurrentSelectedSubmap = ""; - std::vector m_vActiveKeybinds; - SKeybind* m_pLastLongPressKeybind = nullptr; + std::vector> m_vActiveKeybinds; + WP m_pLastLongPressKeybind; SP m_pLongPressTimer, m_pRepeatKeyTimer; uint32_t m_uTimeLastMs = 0; uint32_t m_uLastCode = 0; uint32_t m_uLastMouseCode = 0; - std::vector m_vPressedSpecialBinds; + std::vector> m_vPressedSpecialBinds; int m_iPassPressed = -1; // used for pass @@ -137,7 +137,7 @@ class CKeybindManager { std::set m_sMkKeys = {}; std::set m_sMkMods = {}; - eMultiKeyCase mkBindMatches(const SKeybind); + eMultiKeyCase mkBindMatches(const SP); eMultiKeyCase mkKeysymSetMatches(const std::set, const std::set); bool handleInternalKeybinds(xkb_keysym_t); From 47a1650c4810ad3cb3e9f125cb0addf18aa7395c Mon Sep 17 00:00:00 2001 From: Vaxry Date: Mon, 18 Nov 2024 23:53:38 +0000 Subject: [PATCH 0661/2181] miscfunctions: move configStringToInt to std::expected --- src/config/ConfigManager.cpp | 54 +++++++++++++++++++++------------ src/debug/HyprCtl.cpp | 4 +-- src/desktop/LayerSurface.cpp | 2 +- src/desktop/Window.cpp | 8 ++--- src/helpers/MiscFunctions.cpp | 37 ++++++++++++++-------- src/helpers/MiscFunctions.hpp | 45 +++++++++++++-------------- src/managers/KeybindManager.cpp | 15 +++++---- src/plugins/HookSystem.cpp | 13 +++++--- 8 files changed, 106 insertions(+), 72 deletions(-) diff --git a/src/config/ConfigManager.cpp b/src/config/ConfigManager.cpp index 1c025179..fe80a5ab 100644 --- a/src/config/ConfigManager.cpp +++ b/src/config/ConfigManager.cpp @@ -67,7 +67,7 @@ static Hyprlang::CParseResult configHandleGradientSet(const char* VALUE, void** } try { - DATA->m_vColors.push_back(CColor(configStringToInt(var))); + DATA->m_vColors.push_back(CColor(*configStringToInt(var))); } catch (std::exception& e) { Debug::log(WARN, "Error parsing gradient {}", V); parseError = "Error parsing gradient " + V + ": " + e.what(); @@ -2615,7 +2615,14 @@ std::optional CConfigManager::handleWorkspaceRules(const std::strin const static std::string ruleOnCreatedEmpty = "on-created-empty:"; const static auto ruleOnCreatedEmptyLen = ruleOnCreatedEmpty.length(); - auto assignRule = [&](std::string rule) -> std::optional { +#define CHECK_OR_THROW(expr) \ + \ + auto X = expr; \ + if (!X) { \ + return "Failed parsing a workspace rule"; \ + } + + auto assignRule = [&](std::string rule) -> std::optional { size_t delim = std::string::npos; if ((delim = rule.find("gapsin:")) != std::string::npos) { CVarList varlist = CVarList(rule.substr(delim + 7), 0, ' '); @@ -2633,25 +2640,32 @@ std::optional CConfigManager::handleWorkspaceRules(const std::strin try { wsRule.borderSize = std::stoi(rule.substr(delim + 11)); } catch (...) { return "Error parsing workspace rule bordersize: {}", rule.substr(delim + 11); } - else if ((delim = rule.find("border:")) != std::string::npos) - wsRule.noBorder = !configStringToInt(rule.substr(delim + 7)); - else if ((delim = rule.find("shadow:")) != std::string::npos) - wsRule.noShadow = !configStringToInt(rule.substr(delim + 7)); - else if ((delim = rule.find("rounding:")) != std::string::npos) - wsRule.noRounding = !configStringToInt(rule.substr(delim + 9)); - else if ((delim = rule.find("decorate:")) != std::string::npos) - wsRule.decorate = configStringToInt(rule.substr(delim + 9)); - else if ((delim = rule.find("monitor:")) != std::string::npos) + else if ((delim = rule.find("border:")) != std::string::npos) { + CHECK_OR_THROW(configStringToInt(rule.substr(delim + 7))) + wsRule.noBorder = !*X; + } else if ((delim = rule.find("shadow:")) != std::string::npos) { + CHECK_OR_THROW(configStringToInt(rule.substr(delim + 7))) + wsRule.noShadow = !*X; + } else if ((delim = rule.find("rounding:")) != std::string::npos) { + CHECK_OR_THROW(configStringToInt(rule.substr(delim + 9))) + wsRule.noRounding = !*X; + } else if ((delim = rule.find("decorate:")) != std::string::npos) { + CHECK_OR_THROW(configStringToInt(rule.substr(delim + 9))) + wsRule.decorate = *X; + } else if ((delim = rule.find("monitor:")) != std::string::npos) wsRule.monitor = rule.substr(delim + 8); - else if ((delim = rule.find("default:")) != std::string::npos) - wsRule.isDefault = configStringToInt(rule.substr(delim + 8)); - else if ((delim = rule.find("persistent:")) != std::string::npos) - wsRule.isPersistent = configStringToInt(rule.substr(delim + 11)); - else if ((delim = rule.find("defaultName:")) != std::string::npos) + else if ((delim = rule.find("default:")) != std::string::npos) { + CHECK_OR_THROW(configStringToInt(rule.substr(delim + 8))) + wsRule.isDefault = *X; + } else if ((delim = rule.find("persistent:")) != std::string::npos) { + CHECK_OR_THROW(configStringToInt(rule.substr(delim + 11))) + wsRule.isPersistent = *X; + } else if ((delim = rule.find("defaultName:")) != std::string::npos) wsRule.defaultName = rule.substr(delim + 12); - else if ((delim = rule.find(ruleOnCreatedEmpty)) != std::string::npos) - wsRule.onCreatedEmptyRunCmd = cleanCmdForWorkspace(name, rule.substr(delim + ruleOnCreatedEmptyLen)); - else if ((delim = rule.find("layoutopt:")) != std::string::npos) { + else if ((delim = rule.find(ruleOnCreatedEmpty)) != std::string::npos) { + CHECK_OR_THROW(cleanCmdForWorkspace(name, rule.substr(delim + ruleOnCreatedEmptyLen))) + wsRule.onCreatedEmptyRunCmd = *X; + } else if ((delim = rule.find("layoutopt:")) != std::string::npos) { std::string opt = rule.substr(delim + 10); if (!opt.contains(":")) { // invalid @@ -2668,6 +2682,8 @@ std::optional CConfigManager::handleWorkspaceRules(const std::strin return {}; }; +#undef CHECK_OR_THROW + CVarList rulesList{rules, 0, ',', true}; for (auto const& r : rulesList) { const auto R = assignRule(r); diff --git a/src/debug/HyprCtl.cpp b/src/debug/HyprCtl.cpp index 1b94296f..4d3c2be4 100644 --- a/src/debug/HyprCtl.cpp +++ b/src/debug/HyprCtl.cpp @@ -1286,7 +1286,7 @@ std::string dispatchSeterror(eHyprCtlOutputFormat format, std::string request) { return "ok"; } - const CColor COLOR = configStringToInt(vars[1]); + const CColor COLOR = configStringToInt(vars[1]).value_or(0); for (size_t i = 2; i < vars.size(); ++i) errorMessage += vars[i] + ' '; @@ -1539,7 +1539,7 @@ std::string dispatchNotify(eHyprCtlOutputFormat format, std::string request) { time = std::stoi(TIME); } catch (std::exception& e) { return "invalid arg 2"; } - CColor color = configStringToInt(vars[3]); + CColor color = configStringToInt(vars[3]).value_or(0); size_t msgidx = 4; float fontsize = 13.f; diff --git a/src/desktop/LayerSurface.cpp b/src/desktop/LayerSurface.cpp index cd1c4742..40491123 100644 --- a/src/desktop/LayerSurface.cpp +++ b/src/desktop/LayerSurface.cpp @@ -400,7 +400,7 @@ void CLayerSurface::applyRules() { } else if (rule.rule.starts_with("xray")) { CVarList vars{rule.rule, 0, ' '}; try { - xray = configStringToInt(vars[1]); + xray = configStringToInt(vars[1]).value_or(false); } catch (...) {} } else if (rule.rule.starts_with("animation")) { CVarList vars{rule.rule, 2, 's'}; diff --git a/src/desktop/Window.cpp b/src/desktop/Window.cpp index e74e13a2..33e6a5f8 100644 --- a/src/desktop/Window.cpp +++ b/src/desktop/Window.cpp @@ -672,8 +672,8 @@ void CWindow::applyDynamicRule(const SWindowRule& r) { // Basic form has only two colors, everything else can be parsed as a gradient if (colorsAndAngles.size() == 2 && !colorsAndAngles[1].contains("deg")) { - m_sWindowData.activeBorderColor = CWindowOverridableVar(CGradientValueData(CColor(configStringToInt(colorsAndAngles[0]))), priority); - m_sWindowData.inactiveBorderColor = CWindowOverridableVar(CGradientValueData(CColor(configStringToInt(colorsAndAngles[1]))), priority); + m_sWindowData.activeBorderColor = CWindowOverridableVar(CGradientValueData(CColor(configStringToInt(colorsAndAngles[0]).value_or(0))), priority); + m_sWindowData.inactiveBorderColor = CWindowOverridableVar(CGradientValueData(CColor(configStringToInt(colorsAndAngles[1]).value_or(0))), priority); return; } @@ -685,9 +685,9 @@ void CWindow::applyDynamicRule(const SWindowRule& r) { } else if (token.contains("deg")) inactiveBorderGradient.m_fAngle = std::stoi(token.substr(0, token.size() - 3)) * (PI / 180.0); else if (active) - activeBorderGradient.m_vColors.push_back(configStringToInt(token)); + activeBorderGradient.m_vColors.push_back(configStringToInt(token).value_or(0)); else - inactiveBorderGradient.m_vColors.push_back(configStringToInt(token)); + inactiveBorderGradient.m_vColors.push_back(configStringToInt(token).value_or(0)); } // Includes sanity checks for the number of colors in each gradient diff --git a/src/helpers/MiscFunctions.cpp b/src/helpers/MiscFunctions.cpp index 80681826..fa2f84ab 100644 --- a/src/helpers/MiscFunctions.cpp +++ b/src/helpers/MiscFunctions.cpp @@ -691,15 +691,15 @@ int64_t getPPIDof(int64_t pid) { #endif } -int64_t configStringToInt(const std::string& VALUE) { - auto parseHex = [](const std::string& value) -> int64_t { +std::expected configStringToInt(const std::string& VALUE) { + auto parseHex = [](const std::string& value) -> std::expected { try { size_t position; auto result = stoll(value, &position, 16); if (position == value.size()) return result; } catch (const std::exception&) {} - throw std::invalid_argument("invalid hex " + value); + return std::unexpected("invalid hex " + value); }; if (VALUE.starts_with("0x")) { // Values with 0x are hex @@ -718,18 +718,25 @@ int64_t configStringToInt(const std::string& VALUE) { auto b = configStringToInt(trim(rolling.substr(0, rolling.find(',')))); rolling = rolling.substr(rolling.find(',') + 1); uint8_t a = 0; + + if (!r || !g || !b) + return std::unexpected("failed parsing " + VALUEWITHOUTFUNC); + try { a = std::round(std::stof(trim(rolling.substr(0, rolling.find(',')))) * 255.f); - } catch (std::exception& e) { throw std::invalid_argument("failed parsing " + VALUEWITHOUTFUNC); } + } catch (std::exception& e) { return std::unexpected("failed parsing " + VALUEWITHOUTFUNC); } - return a * (Hyprlang::INT)0x1000000 + r * (Hyprlang::INT)0x10000 + g * (Hyprlang::INT)0x100 + b; + return a * (Hyprlang::INT)0x1000000 + *r * (Hyprlang::INT)0x10000 + *g * (Hyprlang::INT)0x100 + *b; } else if (VALUEWITHOUTFUNC.length() == 8) { const auto RGBA = parseHex(VALUEWITHOUTFUNC); + + if (!RGBA) + return RGBA; // now we need to RGBA -> ARGB. The config holds ARGB only. - return (RGBA >> 8) + 0x1000000 * (RGBA & 0xFF); + return (*RGBA >> 8) + 0x1000000 * (*RGBA & 0xFF); } - throw std::invalid_argument("rgba() expects length of 8 characters (4 bytes) or 4 comma separated values"); + return std::unexpected("rgba() expects length of 8 characters (4 bytes) or 4 comma separated values"); } else if (VALUE.starts_with("rgb(") && VALUE.ends_with(')')) { const auto VALUEWITHOUTFUNC = trim(VALUE.substr(4, VALUE.length() - 5)); @@ -744,12 +751,16 @@ int64_t configStringToInt(const std::string& VALUE) { rolling = rolling.substr(rolling.find(',') + 1); auto b = configStringToInt(trim(rolling.substr(0, rolling.find(',')))); - return (Hyprlang::INT)0xFF000000 + r * (Hyprlang::INT)0x10000 + g * (Hyprlang::INT)0x100 + b; + if (!r || !g || !b) + return std::unexpected("failed parsing " + VALUEWITHOUTFUNC); + + return (Hyprlang::INT)0xFF000000 + *r * (Hyprlang::INT)0x10000 + *g * (Hyprlang::INT)0x100 + *b; } else if (VALUEWITHOUTFUNC.length() == 6) { - return parseHex(VALUEWITHOUTFUNC) + 0xFF000000; + auto r = parseHex(VALUEWITHOUTFUNC); + return r ? *r + 0xFF000000 : r; } - throw std::invalid_argument("rgb() expects length of 6 characters (3 bytes) or 3 comma separated values"); + return std::unexpected("rgb() expects length of 6 characters (3 bytes) or 3 comma separated values"); } else if (VALUE.starts_with("true") || VALUE.starts_with("on") || VALUE.starts_with("yes")) { return 1; } else if (VALUE.starts_with("false") || VALUE.starts_with("off") || VALUE.starts_with("no")) { @@ -757,14 +768,14 @@ int64_t configStringToInt(const std::string& VALUE) { } if (VALUE.empty() || !isNumber(VALUE, false)) - throw std::invalid_argument("cannot parse \"" + VALUE + "\" as an int."); + return std::unexpected("cannot parse \"" + VALUE + "\" as an int."); try { const auto RES = std::stoll(VALUE); return RES; - } catch (std::exception& e) { throw std::invalid_argument(std::string{"stoll threw: "} + e.what()); } + } catch (std::exception& e) { return std::unexpected(std::string{"stoll threw: "} + e.what()); } - return 0; + return std::unexpected("parse error"); } Vector2D configStringToVector2D(const std::string& VALUE) { diff --git a/src/helpers/MiscFunctions.hpp b/src/helpers/MiscFunctions.hpp index 34b23746..bb686df4 100644 --- a/src/helpers/MiscFunctions.hpp +++ b/src/helpers/MiscFunctions.hpp @@ -6,6 +6,7 @@ #include "math/Math.hpp" #include #include +#include #include "../SharedDefs.hpp" #include "../macros.hpp" @@ -19,28 +20,28 @@ struct SWorkspaceIDName { std::string name; }; -std::string absolutePath(const std::string&, const std::string&); -void addWLSignal(wl_signal*, wl_listener*, void* pOwner, const std::string& ownerString); -void removeWLSignal(wl_listener*); -std::string escapeJSONStrings(const std::string& str); -bool isDirection(const std::string&); -bool isDirection(const char&); -SWorkspaceIDName getWorkspaceIDNameFromString(const std::string&); -std::optional cleanCmdForWorkspace(const std::string&, std::string); -float vecToRectDistanceSquared(const Vector2D& vec, const Vector2D& p1, const Vector2D& p2); -void logSystemInfo(); -std::string execAndGet(const char*); -int64_t getPPIDof(int64_t pid); -int64_t configStringToInt(const std::string&); -Vector2D configStringToVector2D(const std::string&); -std::optional getPlusMinusKeywordResult(std::string in, float relative); -double normalizeAngleRad(double ang); -std::vector getBacktrace(); -void throwError(const std::string& err); -bool envEnabled(const std::string& env); -int allocateSHMFile(size_t len); -bool allocateSHMFilePair(size_t size, int* rw_fd_ptr, int* ro_fd_ptr); -float stringToPercentage(const std::string& VALUE, const float REL); +std::string absolutePath(const std::string&, const std::string&); +void addWLSignal(wl_signal*, wl_listener*, void* pOwner, const std::string& ownerString); +void removeWLSignal(wl_listener*); +std::string escapeJSONStrings(const std::string& str); +bool isDirection(const std::string&); +bool isDirection(const char&); +SWorkspaceIDName getWorkspaceIDNameFromString(const std::string&); +std::optional cleanCmdForWorkspace(const std::string&, std::string); +float vecToRectDistanceSquared(const Vector2D& vec, const Vector2D& p1, const Vector2D& p2); +void logSystemInfo(); +std::string execAndGet(const char*); +int64_t getPPIDof(int64_t pid); +std::expected configStringToInt(const std::string&); +Vector2D configStringToVector2D(const std::string&); +std::optional getPlusMinusKeywordResult(std::string in, float relative); +double normalizeAngleRad(double ang); +std::vector getBacktrace(); +void throwError(const std::string& err); +bool envEnabled(const std::string& env); +int allocateSHMFile(size_t len); +bool allocateSHMFilePair(size_t size, int* rw_fd_ptr, int* ro_fd_ptr); +float stringToPercentage(const std::string& VALUE, const float REL); template [[deprecated("use std::format instead")]] std::string getFormat(std::format_string fmt, Args&&... args) { diff --git a/src/managers/KeybindManager.cpp b/src/managers/KeybindManager.cpp index 995fee17..c9ca90e5 100644 --- a/src/managers/KeybindManager.cpp +++ b/src/managers/KeybindManager.cpp @@ -2972,11 +2972,14 @@ SDispatchResult CKeybindManager::setProp(std::string args) { const auto TOKEN = vars[i]; if (TOKEN.ends_with("deg")) colorData.m_fAngle = std::stoi(TOKEN.substr(0, TOKEN.size() - 3)) * (PI / 180.0); - else - colorData.m_vColors.push_back(configStringToInt(TOKEN)); + else if (const auto V = configStringToInt(TOKEN); V) + colorData.m_vColors.push_back(*V); } - } else if (VAL != "-1") - colorData.m_vColors.push_back(configStringToInt(VAL)); + } else if (VAL != "-1") { + const auto V = configStringToInt(VAL); + if (V) + colorData.m_vColors.push_back(*V); + } if (PROP == "activebordercolor") PWINDOW->m_sWindowData.activeBorderColor = CWindowOverridableVar(colorData, PRIORITY_SET_PROP); @@ -2993,8 +2996,8 @@ SDispatchResult CKeybindManager::setProp(std::string args) { } else if (auto search = g_pConfigManager->miWindowProperties.find(PROP); search != g_pConfigManager->miWindowProperties.end()) { if (VAL == "unset") search->second(PWINDOW)->unset(PRIORITY_SET_PROP); - else - *(search->second(PWINDOW)) = CWindowOverridableVar((int)configStringToInt(VAL), PRIORITY_SET_PROP); + else if (const auto V = configStringToInt(VAL); V) + *(search->second(PWINDOW)) = CWindowOverridableVar((int)*V, PRIORITY_SET_PROP); } else { return {.success = false, .error = "Prop not found"}; } diff --git a/src/plugins/HookSystem.cpp b/src/plugins/HookSystem.cpp index 745b2593..69ca81cb 100644 --- a/src/plugins/HookSystem.cpp +++ b/src/plugins/HookSystem.cpp @@ -90,11 +90,14 @@ CFunctionHook::SAssembly CFunctionHook::fixInstructionProbeRIPCalls(const SInstr std::string code = probe.assembly.substr(lastAsmNewline, probe.assembly.find("\n", lastAsmNewline) - lastAsmNewline); if (code.contains("%rip")) { - CVarList tokens{code, 0, 's'}; - size_t plusPresent = tokens[1][0] == '+' ? 1 : 0; - size_t minusPresent = tokens[1][0] == '-' ? 1 : 0; - std::string addr = tokens[1].substr((plusPresent || minusPresent), tokens[1].find("(%rip)") - (plusPresent || minusPresent)); - const int32_t OFFSET = (minusPresent ? -1 : 1) * configStringToInt(addr); + CVarList tokens{code, 0, 's'}; + size_t plusPresent = tokens[1][0] == '+' ? 1 : 0; + size_t minusPresent = tokens[1][0] == '-' ? 1 : 0; + std::string addr = tokens[1].substr((plusPresent || minusPresent), tokens[1].find("(%rip)") - (plusPresent || minusPresent)); + auto addrResult = configStringToInt(addr); + if (!addrResult) + return {}; + const int32_t OFFSET = (minusPresent ? -1 : 1) * *addrResult; if (OFFSET == 0) return {}; const uint64_t DESTINATION = currentAddress + OFFSET + len; From 67cee430061626ccd73dc6d30eed9db289053608 Mon Sep 17 00:00:00 2001 From: Vaxry Date: Tue, 19 Nov 2024 01:16:11 +0000 Subject: [PATCH 0662/2181] internal: minor cleanups for color results --- src/debug/HyprCtl.cpp | 8 +++++--- src/managers/KeybindManager.cpp | 23 ++++++++++++++--------- 2 files changed, 19 insertions(+), 12 deletions(-) diff --git a/src/debug/HyprCtl.cpp b/src/debug/HyprCtl.cpp index 4d3c2be4..7c0a9417 100644 --- a/src/debug/HyprCtl.cpp +++ b/src/debug/HyprCtl.cpp @@ -1529,9 +1529,8 @@ std::string dispatchNotify(eHyprCtlOutputFormat format, std::string request) { icon = std::stoi(ICON); } catch (std::exception& e) { return "invalid arg 1"; } - if (icon > ICON_NONE || icon < 0) { + if (icon > ICON_NONE || icon < 0) icon = ICON_NONE; - } const auto TIME = vars[2]; int time = 0; @@ -1539,7 +1538,10 @@ std::string dispatchNotify(eHyprCtlOutputFormat format, std::string request) { time = std::stoi(TIME); } catch (std::exception& e) { return "invalid arg 2"; } - CColor color = configStringToInt(vars[3]).value_or(0); + const auto COLOR_RESULT = configStringToInt(vars[3]); + if (!COLOR_RESULT) + return "invalid arg 3"; + CColor color = *COLOR_RESULT; size_t msgidx = 4; float fontsize = 13.f; diff --git a/src/managers/KeybindManager.cpp b/src/managers/KeybindManager.cpp index c9ca90e5..75e2a7b3 100644 --- a/src/managers/KeybindManager.cpp +++ b/src/managers/KeybindManager.cpp @@ -2920,6 +2920,9 @@ SDispatchResult CKeybindManager::event(std::string args) { return {}; } +#include +#include + SDispatchResult CKeybindManager::setProp(std::string args) { CVarList vars(args, 3, ' '); @@ -2972,14 +2975,17 @@ SDispatchResult CKeybindManager::setProp(std::string args) { const auto TOKEN = vars[i]; if (TOKEN.ends_with("deg")) colorData.m_fAngle = std::stoi(TOKEN.substr(0, TOKEN.size() - 3)) * (PI / 180.0); - else if (const auto V = configStringToInt(TOKEN); V) - colorData.m_vColors.push_back(*V); + else + configStringToInt(TOKEN).and_then([&colorData](const auto& e) { + colorData.m_vColors.push_back(e); + return std::result_of::type(1); + }); } - } else if (VAL != "-1") { - const auto V = configStringToInt(VAL); - if (V) - colorData.m_vColors.push_back(*V); - } + } else if (VAL != "-1") + configStringToInt(VAL).and_then([&colorData](const auto& e) { + colorData.m_vColors.push_back(e); + return std::result_of::type(1); + }); if (PROP == "activebordercolor") PWINDOW->m_sWindowData.activeBorderColor = CWindowOverridableVar(colorData, PRIORITY_SET_PROP); @@ -2998,9 +3004,8 @@ SDispatchResult CKeybindManager::setProp(std::string args) { search->second(PWINDOW)->unset(PRIORITY_SET_PROP); else if (const auto V = configStringToInt(VAL); V) *(search->second(PWINDOW)) = CWindowOverridableVar((int)*V, PRIORITY_SET_PROP); - } else { + } else return {.success = false, .error = "Prop not found"}; - } } catch (std::exception& e) { return {.success = false, .error = std::format("Error parsing prop value: {}", std::string(e.what()))}; } g_pCompositor->updateAllWindowsAnimatedDecorationValues(); From aa067a4cf12522ede1752dd2048ce67d07e903f1 Mon Sep 17 00:00:00 2001 From: Vaxry Date: Tue, 19 Nov 2024 21:40:16 +0000 Subject: [PATCH 0663/2181] xdg-shell: don't report invalid min/max sizes on unset fixes #8522 --- src/protocols/XDGShell.cpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/protocols/XDGShell.cpp b/src/protocols/XDGShell.cpp index 932882e9..f121070d 100644 --- a/src/protocols/XDGShell.cpp +++ b/src/protocols/XDGShell.cpp @@ -324,10 +324,14 @@ void CXDGToplevelResource::close() { } Vector2D CXDGToplevelResource::layoutMinSize() { + if (current.minSize.x <= 1 && current.minSize.y <= 1) + return {0, 0}; return owner ? current.minSize + owner->current.geometry.pos() : current.minSize; } Vector2D CXDGToplevelResource::layoutMaxSize() { + if (current.maxSize.x <= 1 && current.maxSize.y <= 1) + return {0, 0}; return owner ? current.maxSize + owner->current.geometry.pos() : current.maxSize; } From c4eda46d0ef022a17348623beec4154ba34af691 Mon Sep 17 00:00:00 2001 From: Vaxry Date: Tue, 19 Nov 2024 22:07:25 +0000 Subject: [PATCH 0664/2181] xdg-shell: even more robust layout min/max size although I don't think any apps use this, but better safe than sorry --- src/protocols/XDGShell.cpp | 18 ++++++++++++------ 1 file changed, 12 insertions(+), 6 deletions(-) diff --git a/src/protocols/XDGShell.cpp b/src/protocols/XDGShell.cpp index f121070d..688d0006 100644 --- a/src/protocols/XDGShell.cpp +++ b/src/protocols/XDGShell.cpp @@ -324,15 +324,21 @@ void CXDGToplevelResource::close() { } Vector2D CXDGToplevelResource::layoutMinSize() { - if (current.minSize.x <= 1 && current.minSize.y <= 1) - return {0, 0}; - return owner ? current.minSize + owner->current.geometry.pos() : current.minSize; + Vector2D minSize; + if (current.minSize.x > 1) + minSize.x = owner ? current.minSize.x + owner->current.geometry.pos().x : current.minSize.x; + if (current.minSize.y > 1) + minSize.y = owner ? current.minSize.y + owner->current.geometry.pos().y : current.minSize.y; + return minSize; } Vector2D CXDGToplevelResource::layoutMaxSize() { - if (current.maxSize.x <= 1 && current.maxSize.y <= 1) - return {0, 0}; - return owner ? current.maxSize + owner->current.geometry.pos() : current.maxSize; + Vector2D maxSize; + if (current.maxSize.x > 1) + maxSize.x = owner ? current.maxSize.x + owner->current.geometry.pos().x : current.maxSize.x; + if (current.maxSize.y > 1) + maxSize.y = owner ? current.maxSize.y + owner->current.geometry.pos().y : current.maxSize.y; + return maxSize; } CXDGSurfaceResource::CXDGSurfaceResource(SP resource_, SP owner_, SP surface_) : From e5fa017172156fa5c70fedeaee5f51eace9577c0 Mon Sep 17 00:00:00 2001 From: Vaxry Date: Wed, 20 Nov 2024 10:32:50 +0000 Subject: [PATCH 0665/2181] internal: fix some misused configStringToInt conversions fixes #8523 --- src/config/ConfigManager.cpp | 4 ++-- src/desktop/Window.cpp | 2 +- src/desktop/Workspace.cpp | 4 ++-- src/managers/KeybindManager.cpp | 8 ++++---- 4 files changed, 9 insertions(+), 9 deletions(-) diff --git a/src/config/ConfigManager.cpp b/src/config/ConfigManager.cpp index fe80a5ab..357e7a60 100644 --- a/src/config/ConfigManager.cpp +++ b/src/config/ConfigManager.cpp @@ -2101,13 +2101,13 @@ std::optional CConfigManager::handleAnimation(const std::string& co PANIM->second.pValues = &PANIM->second; // This helper casts strings like "1", "true", "off", "yes"... to int. - int64_t enabledInt = configStringToInt(ARGS[1]) == 1; + int64_t enabledInt = configStringToInt(ARGS[1]).value_or(0) == 1; // Checking that the int is 1 or 0 because the helper can return integers out of range. if (enabledInt != 0 && enabledInt != 1) return "invalid animation on/off state"; - PANIM->second.internalEnabled = configStringToInt(ARGS[1]) == 1; + PANIM->second.internalEnabled = configStringToInt(ARGS[1]).value_or(0) == 1; if (PANIM->second.internalEnabled) { // speed diff --git a/src/desktop/Window.cpp b/src/desktop/Window.cpp index 33e6a5f8..117d301c 100644 --- a/src/desktop/Window.cpp +++ b/src/desktop/Window.cpp @@ -707,7 +707,7 @@ void CWindow::applyDynamicRule(const SWindowRule& r) { *(search->second(m_pSelf.lock())) = CWindowOverridableVar(true, priority); } else { try { - *(search->second(m_pSelf.lock())) = CWindowOverridableVar((bool)configStringToInt(VARS[1]), priority); + *(search->second(m_pSelf.lock())) = CWindowOverridableVar((bool)configStringToInt(VARS[1]).value_or(0), priority); } catch (...) {} } } else if (auto search = g_pConfigManager->miWindowProperties.find(VARS[0]); search != g_pConfigManager->miWindowProperties.end()) { diff --git a/src/desktop/Workspace.cpp b/src/desktop/Workspace.cpp index 2e1e91f2..8cddbb6b 100644 --- a/src/desktop/Workspace.cpp +++ b/src/desktop/Workspace.cpp @@ -332,7 +332,7 @@ bool CWorkspace::matchesStaticSelector(const std::string& selector_) { const auto SHOULDBESPECIAL = configStringToInt(prop); - if ((bool)SHOULDBESPECIAL != m_bIsSpecialWorkspace) + if (SHOULDBESPECIAL && (bool)*SHOULDBESPECIAL != m_bIsSpecialWorkspace) return false; continue; } @@ -367,7 +367,7 @@ bool CWorkspace::matchesStaticSelector(const std::string& selector_) { const auto WANTSNAMED = configStringToInt(prop); - if (WANTSNAMED != (m_iID <= -1337)) + if (WANTSNAMED && *WANTSNAMED != (m_iID <= -1337)) return false; continue; } diff --git a/src/managers/KeybindManager.cpp b/src/managers/KeybindManager.cpp index 75e2a7b3..be1e9534 100644 --- a/src/managers/KeybindManager.cpp +++ b/src/managers/KeybindManager.cpp @@ -2961,13 +2961,13 @@ SDispatchResult CKeybindManager::setProp(std::string args) { CWindowOverridableVar(SAlphaValue{std::stof(VAL), PWINDOW->m_sWindowData.alphaFullscreen.valueOrDefault().m_bOverride}, PRIORITY_SET_PROP); } else if (PROP == "alphaoverride") { PWINDOW->m_sWindowData.alpha = - CWindowOverridableVar(SAlphaValue{PWINDOW->m_sWindowData.alpha.valueOrDefault().m_fAlpha, (bool)configStringToInt(VAL)}, PRIORITY_SET_PROP); + CWindowOverridableVar(SAlphaValue{PWINDOW->m_sWindowData.alpha.valueOrDefault().m_fAlpha, (bool)configStringToInt(VAL).value_or(0)}, PRIORITY_SET_PROP); } else if (PROP == "alphainactiveoverride") { PWINDOW->m_sWindowData.alphaInactive = - CWindowOverridableVar(SAlphaValue{PWINDOW->m_sWindowData.alphaInactive.valueOrDefault().m_fAlpha, (bool)configStringToInt(VAL)}, PRIORITY_SET_PROP); + CWindowOverridableVar(SAlphaValue{PWINDOW->m_sWindowData.alphaInactive.valueOrDefault().m_fAlpha, (bool)configStringToInt(VAL).value_or(0)}, PRIORITY_SET_PROP); } else if (PROP == "alphafullscreenoverride") { PWINDOW->m_sWindowData.alphaFullscreen = - CWindowOverridableVar(SAlphaValue{PWINDOW->m_sWindowData.alphaFullscreen.valueOrDefault().m_fAlpha, (bool)configStringToInt(VAL)}, PRIORITY_SET_PROP); + CWindowOverridableVar(SAlphaValue{PWINDOW->m_sWindowData.alphaFullscreen.valueOrDefault().m_fAlpha, (bool)configStringToInt(VAL).value_or(0)}, PRIORITY_SET_PROP); } else if (PROP == "activebordercolor" || PROP == "inactivebordercolor") { CGradientValueData colorData = {}; if (vars.size() > 4) { @@ -2998,7 +2998,7 @@ SDispatchResult CKeybindManager::setProp(std::string args) { else if (VAL == "unset") pWindowDataElement->unset(PRIORITY_SET_PROP); else - *pWindowDataElement = CWindowOverridableVar((bool)configStringToInt(VAL), PRIORITY_SET_PROP); + *pWindowDataElement = CWindowOverridableVar((bool)configStringToInt(VAL).value_or(0), PRIORITY_SET_PROP); } else if (auto search = g_pConfigManager->miWindowProperties.find(PROP); search != g_pConfigManager->miWindowProperties.end()) { if (VAL == "unset") search->second(PWINDOW)->unset(PRIORITY_SET_PROP); From 940f7aa990dbc99815bab8d355999d8277534b17 Mon Sep 17 00:00:00 2001 From: vaxerski Date: Wed, 20 Nov 2024 11:02:21 +0000 Subject: [PATCH 0666/2181] renderer: fixup blur optimization considitons fixes #8531 --- src/render/Renderer.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/render/Renderer.cpp b/src/render/Renderer.cpp index fc17ef9f..42545bc1 100644 --- a/src/render/Renderer.cpp +++ b/src/render/Renderer.cpp @@ -174,7 +174,6 @@ static void renderSurface(SP surface, int x, int y, void* da } const auto RDATA = (SRenderData*)data; - const bool BLUR = RDATA->blur && !TEXTURE->m_bOpaque; const auto INTERACTIVERESIZEINPROGRESS = RDATA->pWindow && g_pInputManager->currentlyDraggedWindow && g_pInputManager->dragMode == MBIND_RESIZE; TRACY_GPU_ZONE("RenderSurface"); @@ -183,6 +182,7 @@ static void renderSurface(SP surface, int x, int y, void* da auto PSURFACE = CWLSurface::fromResource(surface); const float ALPHA = RDATA->alpha * RDATA->fadeAlpha * (PSURFACE ? PSURFACE->m_pAlphaModifier : 1.F); + const bool BLUR = RDATA->blur && (!TEXTURE->m_bOpaque || ALPHA < 1.F); CBox windowBox; if (RDATA->surface && surface == RDATA->surface) { From 943b3d467b0a77a6b67df01e78f5e4977486824f Mon Sep 17 00:00:00 2001 From: Tom Englund Date: Fri, 22 Nov 2024 02:47:51 +0100 Subject: [PATCH 0667/2181] bezier: optimize setup of bezier curves (#8528) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit avoid reallocations by resizing and copy the pVec into the resized m_dPoints, reduce the amount of calculations in baking to only do it once per iteration instead of twice. precompute in getYforT and getXforT return early in getYForPoint if x is equal or below 0. and use const references where we can. these changes we are now down to an average of "time to bake: 2.50µs." on my machine compared to before average of "time to bake: 11.15µs" --- src/helpers/BezierCurve.cpp | 39 ++++++++++++++++++++++++------------- src/helpers/BezierCurve.hpp | 8 ++++---- 2 files changed, 29 insertions(+), 18 deletions(-) diff --git a/src/helpers/BezierCurve.cpp b/src/helpers/BezierCurve.cpp index ea567ad6..23fcd691 100644 --- a/src/helpers/BezierCurve.cpp +++ b/src/helpers/BezierCurve.cpp @@ -6,24 +6,27 @@ #include void CBezierCurve::setup(std::vector* pVec) { - m_dPoints.clear(); - const auto BEGIN = std::chrono::high_resolution_clock::now(); - m_dPoints.emplace_back(Vector2D(0, 0)); - - for (auto const& p : *pVec) { - m_dPoints.push_back(p); + // Avoid reallocations by reserving enough memory upfront + m_dPoints.resize(pVec->size() + 2); + m_dPoints[0] = Vector2D(0, 0); // Start point + size_t index = 1; // Start after the first element + for (const auto& vec : *pVec) { + if (index < m_dPoints.size() - 1) { // Bounds check to ensure safety + m_dPoints[index] = vec; + ++index; + } } - - m_dPoints.emplace_back(Vector2D(1, 1)); + m_dPoints.back() = Vector2D(1, 1); // End point RASSERT(m_dPoints.size() == 4, "CBezierCurve only supports cubic beziers! (points num: {})", m_dPoints.size()); // bake BAKEDPOINTS points for faster lookups // T -> X ( / BAKEDPOINTS ) for (int i = 0; i < BAKEDPOINTS; ++i) { - m_aPointsBaked[i] = Vector2D(getXForT((i + 1) / (float)BAKEDPOINTS), getYForT((i + 1) / (float)BAKEDPOINTS)); + float const t = (i + 1) / (float)BAKEDPOINTS; + m_aPointsBaked[i] = Vector2D(getXForT(t), getYForT(t)); } const auto ELAPSEDUS = std::chrono::duration_cast(std::chrono::high_resolution_clock::now() - BEGIN).count() / 1000.f; @@ -40,18 +43,26 @@ void CBezierCurve::setup(std::vector* pVec) { ELAPSEDUS, ELAPSEDCALCAVG); } -float CBezierCurve::getYForT(float t) { - return 3 * t * pow(1 - t, 2) * m_dPoints[1].y + 3 * pow(t, 2) * (1 - t) * m_dPoints[2].y + pow(t, 3); +float CBezierCurve::getXForT(float const& t) { + float t2 = t * t; + float t3 = t2 * t; + + return 3 * t * (1 - t) * (1 - t) * m_dPoints[1].x + 3 * t2 * (1 - t) * m_dPoints[2].x + t3 * m_dPoints[3].x; } -float CBezierCurve::getXForT(float t) { - return 3 * t * pow(1 - t, 2) * m_dPoints[1].x + 3 * pow(t, 2) * (1 - t) * m_dPoints[2].x + pow(t, 3); +float CBezierCurve::getYForT(float const& t) { + float t2 = t * t; + float t3 = t2 * t; + + return 3 * t * (1 - t) * (1 - t) * m_dPoints[1].y + 3 * t2 * (1 - t) * m_dPoints[2].y + t3 * m_dPoints[3].y; } // Todo: this probably can be done better and faster -float CBezierCurve::getYForPoint(float x) { +float CBezierCurve::getYForPoint(float const& x) { if (x >= 1.f) return 1.f; + if (x <= 0.f) + return 0.f; int index = 0; bool below = true; diff --git a/src/helpers/BezierCurve.hpp b/src/helpers/BezierCurve.hpp index 54af46a6..1a842f5a 100644 --- a/src/helpers/BezierCurve.hpp +++ b/src/helpers/BezierCurve.hpp @@ -16,13 +16,13 @@ class CBezierCurve { // this EXCLUDES the 0,0 and 1,1 points, void setup(std::vector* points); - float getYForT(float t); - float getXForT(float t); - float getYForPoint(float x); + float getYForT(float const& t); + float getXForT(float const& t); + float getYForPoint(float const& x); private: // this INCLUDES the 0,0 and 1,1 points. - std::deque m_dPoints; + std::vector m_dPoints; std::array m_aPointsBaked; }; From b1003445953474b967464d4d0878955d37498647 Mon Sep 17 00:00:00 2001 From: may <63159454+m4rch3n1ng@users.noreply.github.com> Date: Fri, 22 Nov 2024 03:31:42 +0100 Subject: [PATCH 0668/2181] keybinds: actually suppress internal keybinds instead of passing them along (#8538) --- src/managers/KeybindManager.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/managers/KeybindManager.cpp b/src/managers/KeybindManager.cpp index be1e9534..8cf39c1b 100644 --- a/src/managers/KeybindManager.cpp +++ b/src/managers/KeybindManager.cpp @@ -423,8 +423,10 @@ bool CKeybindManager::onKeyEvent(std::any event, SP pKeyboard) { const xkb_keysym_t keysym = xkb_state_key_get_one_sym(pKeyboard->resolveBindsBySym ? pKeyboard->xkbSymState : m_pXKBTranslationState, KEYCODE); const xkb_keysym_t internalKeysym = xkb_state_key_get_one_sym(pKeyboard->xkbState, KEYCODE); + // handleInternalKeybinds returns true when the key should be suppressed, + // while this function returns true when the key event should be sent if (handleInternalKeybinds(internalKeysym)) - return true; + return false; const auto MODS = g_pInputManager->accumulateModsFromAllKBs(); From a847bc67b1efcf3a0fa9c8a3a1da1a79743940c1 Mon Sep 17 00:00:00 2001 From: Vaxry Date: Fri, 22 Nov 2024 15:22:28 +0000 Subject: [PATCH 0669/2181] monitor: fix default focus when switching to a fs workspace --- src/helpers/Monitor.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/helpers/Monitor.cpp b/src/helpers/Monitor.cpp index 9ac48220..63268c8a 100644 --- a/src/helpers/Monitor.cpp +++ b/src/helpers/Monitor.cpp @@ -629,7 +629,7 @@ void CMonitor::changeWorkspace(const PHLWORKSPACE& pWorkspace, bool internal, bo if (!noFocus && !g_pCompositor->m_pLastMonitor->activeSpecialWorkspace && !(g_pCompositor->m_pLastWindow.lock() && g_pCompositor->m_pLastWindow->m_bPinned && g_pCompositor->m_pLastWindow->m_pMonitor == self)) { static auto PFOLLOWMOUSE = CConfigValue("input:follow_mouse"); - auto pWindow = pWorkspace->getLastFocusedWindow(); + auto pWindow = pWorkspace->m_bHasFullscreenWindow ? g_pCompositor->getFullscreenWindowOnWorkspace(pWorkspace->m_iID) : pWorkspace->getLastFocusedWindow(); if (!pWindow) { if (*PFOLLOWMOUSE == 1) From 745a82ce8ab19d958e344f5925bb1dc8ea7d6a53 Mon Sep 17 00:00:00 2001 From: Vaxry Date: Fri, 22 Nov 2024 16:01:02 +0000 Subject: [PATCH 0670/2181] core: workspace-related function cleanup / refactor CCompositor is massive, and has a lot of functions that could be better optimized if in CWorkspace --- src/Compositor.cpp | 182 ++++----------------------- src/Compositor.hpp | 13 -- src/config/ConfigManager.cpp | 4 +- src/debug/HyprCtl.cpp | 10 +- src/desktop/Window.cpp | 38 +++--- src/desktop/Workspace.cpp | 149 ++++++++++++++++++++-- src/desktop/Workspace.hpp | 20 +-- src/events/Windows.cpp | 12 +- src/helpers/MiscFunctions.cpp | 2 +- src/helpers/Monitor.cpp | 6 +- src/layout/DwindleLayout.cpp | 6 +- src/layout/IHyprLayout.cpp | 10 +- src/layout/MasterLayout.cpp | 2 +- src/managers/AnimationManager.cpp | 2 +- src/managers/KeybindManager.cpp | 30 +++-- src/managers/input/IdleInhibitor.cpp | 2 +- src/managers/input/InputManager.cpp | 8 +- src/managers/input/Swipe.cpp | 13 +- src/render/Renderer.cpp | 18 +-- 19 files changed, 267 insertions(+), 260 deletions(-) diff --git a/src/Compositor.cpp b/src/Compositor.cpp index 0e0c75a1..3fe5acec 100644 --- a/src/Compositor.cpp +++ b/src/Compositor.cpp @@ -833,6 +833,9 @@ PHLWINDOW CCompositor::vectorToWindowUnified(const Vector2D& pos, uint8_t proper if (special && !w->onSpecialWorkspace()) // because special floating may creep up into regular continue; + if (!w->m_pWorkspace) + continue; + const auto PWINDOWMONITOR = w->m_pMonitor.lock(); // to avoid focusing windows behind special workspaces from other monitors @@ -844,7 +847,7 @@ PHLWINDOW CCompositor::vectorToWindowUnified(const Vector2D& pos, uint8_t proper continue; } - if (w->m_bIsFloating && w->m_bIsMapped && isWorkspaceVisible(w->m_pWorkspace) && !w->isHidden() && !w->m_bPinned && !w->m_sWindowData.noFocus.valueOrDefault() && + if (w->m_bIsFloating && w->m_bIsMapped && w->m_pWorkspace->isVisible() && !w->isHidden() && !w->m_bPinned && !w->m_sWindowData.noFocus.valueOrDefault() && w != pIgnoreWindow && (!aboveFullscreen || w->m_bCreatedOverFullscreen)) { // OR windows should add focus to parent if (w->m_bX11ShouldntFocus && !w->isX11OverrideRedirect()) @@ -887,7 +890,7 @@ PHLWINDOW CCompositor::vectorToWindowUnified(const Vector2D& pos, uint8_t proper const auto PWORKSPACE = getWorkspaceByID(WSPID); if (PWORKSPACE->m_bHasFullscreenWindow) - return getFullscreenWindowOnWorkspace(PWORKSPACE->m_iID); + return PWORKSPACE->getFullscreenWindow(); auto found = floating(false); if (found) @@ -898,6 +901,9 @@ PHLWINDOW CCompositor::vectorToWindowUnified(const Vector2D& pos, uint8_t proper if (special != w->onSpecialWorkspace()) continue; + if (!w->m_pWorkspace) + continue; + if (!w->m_bIsX11 && !w->m_bIsFloating && w->m_bIsMapped && w->workspaceID() == WSPID && !w->isHidden() && !w->m_bX11ShouldntFocus && !w->m_sWindowData.noFocus.valueOrDefault() && w != pIgnoreWindow) { if (w->hasPopupAt(pos)) @@ -909,6 +915,9 @@ PHLWINDOW CCompositor::vectorToWindowUnified(const Vector2D& pos, uint8_t proper if (special != w->onSpecialWorkspace()) continue; + if (!w->m_pWorkspace) + continue; + if (!w->m_bIsFloating && w->m_bIsMapped && w->workspaceID() == WSPID && !w->isHidden() && !w->m_bX11ShouldntFocus && !w->m_sWindowData.noFocus.valueOrDefault() && w != pIgnoreWindow) { CBox box = (properties & USE_PROP_TILED) ? w->getWindowBoxUnified(properties) : CBox{w->m_vPosition, w->m_vSize}; @@ -1070,7 +1079,7 @@ void CCompositor::focusWindow(PHLWINDOW pWindow, SP pSurface const auto PMONITOR = pWindow->m_pMonitor.lock(); - if (!isWorkspaceVisible(pWindow->m_pWorkspace)) { + if (!pWindow->m_pWorkspace || !pWindow->m_pWorkspace->isVisible()) { const auto PWORKSPACE = pWindow->m_pWorkspace; // This is to fix incorrect feedback on the focus history. PWORKSPACE->m_pLastFocusedWindow = pWindow; @@ -1247,30 +1256,6 @@ PHLWINDOW CCompositor::getWindowFromHandle(uint32_t handle) { return nullptr; } -PHLWINDOW CCompositor::getFullscreenWindowOnWorkspace(const WORKSPACEID& ID) { - for (auto const& w : m_vWindows) { - if (w->workspaceID() == ID && w->isFullscreen()) - return w; - } - - return nullptr; -} - -bool CCompositor::isWorkspaceVisible(PHLWORKSPACE w) { - return valid(w) && w->m_bVisible; -} - -bool CCompositor::isWorkspaceVisibleNotCovered(PHLWORKSPACE w) { - if (!valid(w)) - return false; - - const auto PMONITOR = w->m_pMonitor.lock(); - if (PMONITOR->activeSpecialWorkspace) - return PMONITOR->activeSpecialWorkspace->m_iID == w->m_iID; - - return PMONITOR->activeWorkspace->m_iID == w->m_iID; -} - PHLWORKSPACE CCompositor::getWorkspaceByID(const WORKSPACEID& id) { for (auto const& w : m_vWorkspaces) { if (w->m_iID == id && !w->inert()) @@ -1295,37 +1280,6 @@ void CCompositor::sanityCheckWorkspaces() { } } -int CCompositor::getWindowsOnWorkspace(const WORKSPACEID& id, std::optional onlyTiled, std::optional onlyVisible) { - int no = 0; - for (auto const& w : m_vWindows) { - if (w->workspaceID() != id || !w->m_bIsMapped) - continue; - if (onlyTiled.has_value() && w->m_bIsFloating == onlyTiled.value()) - continue; - if (onlyVisible.has_value() && w->isHidden() == onlyVisible.value()) - continue; - no++; - } - - return no; -} - -int CCompositor::getGroupsOnWorkspace(const WORKSPACEID& id, std::optional onlyTiled, std::optional onlyVisible) { - int no = 0; - for (auto const& w : m_vWindows) { - if (w->workspaceID() != id || !w->m_bIsMapped) - continue; - if (!w->m_sGroupData.head) - continue; - if (onlyTiled.has_value() && w->m_bIsFloating == onlyTiled.value()) - continue; - if (onlyVisible.has_value() && w->isHidden() == onlyVisible.value()) - continue; - no++; - } - return no; -} - PHLWINDOW CCompositor::getUrgentWindow() { for (auto const& w : m_vWindows) { if (w->m_bIsMapped && w->m_bIsUrgent) @@ -1335,44 +1289,6 @@ PHLWINDOW CCompositor::getUrgentWindow() { return nullptr; } -bool CCompositor::hasUrgentWindowOnWorkspace(const WORKSPACEID& id) { - for (auto const& w : m_vWindows) { - if (w->workspaceID() == id && w->m_bIsMapped && w->m_bIsUrgent) - return true; - } - - return false; -} - -PHLWINDOW CCompositor::getFirstWindowOnWorkspace(const WORKSPACEID& id) { - for (auto const& w : m_vWindows) { - if (w->workspaceID() == id && w->m_bIsMapped && !w->isHidden()) - return w; - } - - return nullptr; -} - -PHLWINDOW CCompositor::getTopLeftWindowOnWorkspace(const WORKSPACEID& id) { - const auto PWORKSPACE = getWorkspaceByID(id); - - if (!PWORKSPACE) - return nullptr; - - const auto PMONITOR = PWORKSPACE->m_pMonitor.lock(); - - for (auto const& w : m_vWindows) { - if (w->workspaceID() != id || !w->m_bIsMapped || w->isHidden()) - continue; - - const auto WINDOWIDEALBB = w->getWindowIdealBoundingBoxIgnoreReserved(); - - if (WINDOWIDEALBB.x <= PMONITOR->vecPosition.x + 1 && WINDOWIDEALBB.y <= PMONITOR->vecPosition.y + 1) - return w; - } - return nullptr; -} - bool CCompositor::isWindowActive(PHLWINDOW pWindow) { if (m_pLastWindow.expired() && !m_pLastFocus) return false; @@ -1560,7 +1476,7 @@ PHLWINDOW CCompositor::getWindowInDirection(PHLWINDOW pWindow, char dir) { // for tiled windows, we calc edges for (auto const& w : m_vWindows) { - if (w == pWindow || !w->m_bIsMapped || w->isHidden() || (!w->isFullscreen() && w->m_bIsFloating) || !isWorkspaceVisible(w->m_pWorkspace)) + if (w == pWindow || !w->m_pWorkspace || !w->m_bIsMapped || w->isHidden() || (!w->isFullscreen() && w->m_bIsFloating) || !w->m_pWorkspace->isVisible()) continue; if (pWindow->m_pMonitor == w->m_pMonitor && pWindow->m_pWorkspace != w->m_pWorkspace) @@ -1652,7 +1568,7 @@ PHLWINDOW CCompositor::getWindowInDirection(PHLWINDOW pWindow, char dir) { constexpr float THRESHOLD = 0.3 * M_PI; for (auto const& w : m_vWindows) { - if (w == pWindow || !w->m_bIsMapped || w->isHidden() || (!w->isFullscreen() && !w->m_bIsFloating) || !isWorkspaceVisible(w->m_pWorkspace)) + if (w == pWindow || !w->m_bIsMapped || !w->m_pWorkspace || w->isHidden() || (!w->isFullscreen() && !w->m_bIsFloating) || !w->m_pWorkspace->isVisible()) continue; if (pWindow->m_pMonitor == w->m_pMonitor && pWindow->m_pWorkspace != w->m_pWorkspace) @@ -1678,7 +1594,7 @@ PHLWINDOW CCompositor::getWindowInDirection(PHLWINDOW pWindow, char dir) { } if (!leaderWindow && PWORKSPACE->m_bHasFullscreenWindow) - leaderWindow = g_pCompositor->getFullscreenWindowOnWorkspace(PWORKSPACE->m_iID); + leaderWindow = PWORKSPACE->getFullscreenWindow(); } if (leaderValue != -1) @@ -1871,15 +1787,6 @@ void CCompositor::updateAllWindowsAnimatedDecorationValues() { } } -void CCompositor::updateWorkspaceWindows(const int64_t& id) { - for (auto const& w : m_vWindows) { - if (!w->m_bIsMapped || w->workspaceID() != id) - continue; - - w->updateDynamicRules(); - } -} - void CCompositor::updateWindowAnimatedDecorationValues(PHLWINDOW pWindow) { // optimization static auto PACTIVECOL = CConfigValue("general:col.active_border"); @@ -2391,7 +2298,7 @@ void CCompositor::setWindowFullscreenState(const PHLWINDOW PWINDOW, sFullscreenS g_pXWaylandManager->setWindowSize(PWINDOW, PWINDOW->m_vRealSize.goal(), true); - forceReportSizesToWindowsOnWorkspace(PWINDOW->workspaceID()); + PWORKSPACE->forceReportSizesToWindows(); g_pInputManager->recheckIdleInhibitorStatus(); @@ -2422,27 +2329,6 @@ PHLWINDOW CCompositor::getX11Parent(PHLWINDOW pWindow) { return nullptr; } -void CCompositor::updateWorkspaceWindowDecos(const WORKSPACEID& id) { - for (auto const& w : m_vWindows) { - if (w->workspaceID() != id) - continue; - - w->updateWindowDecos(); - } -} - -void CCompositor::updateWorkspaceWindowData(const WORKSPACEID& id) { - const auto PWORKSPACE = getWorkspaceByID(id); - const auto WORKSPACERULE = PWORKSPACE ? g_pConfigManager->getWorkspaceRuleFor(PWORKSPACE) : SWorkspaceRule{}; - - for (auto const& w : m_vWindows) { - if (w->workspaceID() != id) - continue; - - w->updateWindowData(WORKSPACERULE); - } -} - void CCompositor::scheduleFrameForMonitor(PHLMONITOR pMonitor, IOutput::scheduleFrameReason reason) { if ((m_pAqBackend->hasSession() && !m_pAqBackend->session->active) || !m_bSessionActive) return; @@ -2654,14 +2540,6 @@ Vector2D CCompositor::parseWindowVectorArgsRelative(const std::string& args, con return Vector2D(X, Y); } -void CCompositor::forceReportSizesToWindowsOnWorkspace(const WORKSPACEID& wid) { - for (auto const& w : m_vWindows) { - if (w->workspaceID() == wid && w->m_bIsMapped && !w->isHidden()) { - g_pXWaylandManager->setWindowSize(w, w->m_vRealSize.value(), true); - } - } -} - PHLWORKSPACE CCompositor::createNewWorkspace(const WORKSPACEID& id, const MONITORID& monid, const std::string& name, bool isEmpty) { const auto NAME = name == "" ? std::to_string(id) : name; auto monID = monid; @@ -2679,21 +2557,6 @@ PHLWORKSPACE CCompositor::createNewWorkspace(const WORKSPACEID& id, const MONITO return PWORKSPACE; } -void CCompositor::renameWorkspace(const WORKSPACEID& id, const std::string& name) { - const auto PWORKSPACE = getWorkspaceByID(id); - - if (!PWORKSPACE) - return; - - if (isWorkspaceSpecial(id)) - return; - - Debug::log(LOG, "renameWorkspace: Renaming workspace {} to '{}'", id, name); - PWORKSPACE->m_szName = name; - - g_pEventManager->postEvent({"renameworkspace", std::to_string(PWORKSPACE->m_iID) + "," + PWORKSPACE->m_szName}); -} - void CCompositor::setActiveMonitor(PHLMONITOR pMonitor) { if (m_pLastMonitor == pMonitor) return; @@ -2758,8 +2621,8 @@ void CCompositor::moveWindowToWorkspaceSafe(PHLWINDOW pWindow, PHLWORKSPACE pWor if (FULLSCREEN) setWindowFullscreenInternal(pWindow, FSMODE_NONE); - const PHLWINDOW pFirstWindowOnWorkspace = g_pCompositor->getFirstWindowOnWorkspace(pWorkspace->m_iID); - const int visibleWindowsOnWorkspace = g_pCompositor->getWindowsOnWorkspace(pWorkspace->m_iID, std::nullopt, true); + const PHLWINDOW pFirstWindowOnWorkspace = pWorkspace->getFirstWindow(); + const int visibleWindowsOnWorkspace = pWorkspace->getWindows(std::nullopt, true); const auto PWINDOWMONITOR = pWindow->m_pMonitor.lock(); const auto POSTOMON = pWindow->m_vRealPosition.goal() - PWINDOWMONITOR->vecPosition; const auto PWORKSPACEMONITOR = pWorkspace->m_pMonitor.lock(); @@ -2817,14 +2680,15 @@ void CCompositor::moveWindowToWorkspaceSafe(PHLWINDOW pWindow, PHLWORKSPACE pWor if (FULLSCREEN) setWindowFullscreenInternal(pWindow, FULLSCREENMODE); - g_pCompositor->updateWorkspaceWindows(pWorkspace->m_iID); - g_pCompositor->updateWorkspaceWindows(pWindow->workspaceID()); + pWorkspace->updateWindows(); + if (pWindow->m_pWorkspace) + pWindow->m_pWorkspace->updateWindows(); g_pCompositor->updateSuspendedStates(); } PHLWINDOW CCompositor::getForceFocus() { for (auto const& w : m_vWindows) { - if (!w->m_bIsMapped || w->isHidden() || !isWorkspaceVisible(w->m_pWorkspace)) + if (!w->m_bIsMapped || w->isHidden() || !w->m_pWorkspace || !w->m_pWorkspace->isVisible()) continue; if (!w->m_bStayFocused) @@ -3002,7 +2866,7 @@ void CCompositor::updateSuspendedStates() { if (!w->m_bIsMapped) continue; - w->setSuspended(w->isHidden() || !isWorkspaceVisible(w->m_pWorkspace)); + w->setSuspended(w->isHidden() || !w->m_pWorkspace || !w->m_pWorkspace->isVisible()); } } diff --git a/src/Compositor.hpp b/src/Compositor.hpp index 208b6ecf..c02be579 100644 --- a/src/Compositor.hpp +++ b/src/Compositor.hpp @@ -115,21 +115,11 @@ class CCompositor { PHLMONITOR getRealMonitorFromOutput(SP); PHLWINDOW getWindowFromSurface(SP); PHLWINDOW getWindowFromHandle(uint32_t); - bool isWorkspaceVisible(PHLWORKSPACE); - bool isWorkspaceVisibleNotCovered(PHLWORKSPACE); PHLWORKSPACE getWorkspaceByID(const WORKSPACEID&); PHLWORKSPACE getWorkspaceByName(const std::string&); PHLWORKSPACE getWorkspaceByString(const std::string&); void sanityCheckWorkspaces(); - void updateWorkspaceWindowDecos(const WORKSPACEID&); - void updateWorkspaceWindowData(const WORKSPACEID&); - int getWindowsOnWorkspace(const WORKSPACEID& id, std::optional onlyTiled = {}, std::optional onlyVisible = {}); - int getGroupsOnWorkspace(const WORKSPACEID& id, std::optional onlyTiled = {}, std::optional onlyVisible = {}); PHLWINDOW getUrgentWindow(); - bool hasUrgentWindowOnWorkspace(const WORKSPACEID&); - PHLWINDOW getFirstWindowOnWorkspace(const WORKSPACEID&); - PHLWINDOW getTopLeftWindowOnWorkspace(const WORKSPACEID&); - PHLWINDOW getFullscreenWindowOnWorkspace(const WORKSPACEID&); bool isWindowActive(PHLWINDOW); void changeWindowZOrder(PHLWINDOW, bool); void cleanupFadingOut(const MONITORID& monid); @@ -142,7 +132,6 @@ class CCompositor { PHLMONITOR getMonitorInDirection(const char&); PHLMONITOR getMonitorInDirection(PHLMONITOR, const char&); void updateAllWindowsAnimatedDecorationValues(); - void updateWorkspaceWindows(const WORKSPACEID& id); void updateWindowAnimatedDecorationValues(PHLWINDOW); MONITORID getNextAvailableMonitorID(std::string const& name); void moveWorkspaceToMonitor(PHLWORKSPACE, PHLMONITOR, bool noWarpCursor = false); @@ -165,10 +154,8 @@ class CCompositor { PHLLS getLayerSurfaceFromSurface(SP); void closeWindow(PHLWINDOW); Vector2D parseWindowVectorArgsRelative(const std::string&, const Vector2D&); - void forceReportSizesToWindowsOnWorkspace(const WORKSPACEID&); PHLWORKSPACE createNewWorkspace(const WORKSPACEID&, const MONITORID&, const std::string& name = "", bool isEmpty = true); // will be deleted next frame if left empty and unfocused! - void renameWorkspace(const WORKSPACEID&, const std::string& name = ""); void setActiveMonitor(PHLMONITOR); bool isWorkspaceSpecial(const WORKSPACEID&); WORKSPACEID getNewSpecialID(); diff --git a/src/config/ConfigManager.cpp b/src/config/ConfigManager.cpp index 357e7a60..f6734011 100644 --- a/src/config/ConfigManager.cpp +++ b/src/config/ConfigManager.cpp @@ -927,8 +927,8 @@ void CConfigManager::postConfigReload(const Hyprlang::CParseResult& result) { for (auto const& w : g_pCompositor->m_vWorkspaces) { if (w->inert()) continue; - g_pCompositor->updateWorkspaceWindows(w->m_iID); - g_pCompositor->updateWorkspaceWindowData(w->m_iID); + w->updateWindows(); + w->updateWindowData(); } // Update window border colors diff --git a/src/debug/HyprCtl.cpp b/src/debug/HyprCtl.cpp index 7c0a9417..11c16f0e 100644 --- a/src/debug/HyprCtl.cpp +++ b/src/debug/HyprCtl.cpp @@ -306,12 +306,12 @@ std::string CHyprCtl::getWorkspaceData(PHLWORKSPACE w, eHyprCtlOutputFormat form "lastwindowtitle": "{}" }})#", w->m_iID, escapeJSONStrings(w->m_szName), escapeJSONStrings(PMONITOR ? PMONITOR->szName : "?"), - escapeJSONStrings(PMONITOR ? std::to_string(PMONITOR->ID) : "null"), g_pCompositor->getWindowsOnWorkspace(w->m_iID), - ((int)w->m_bHasFullscreenWindow == 1 ? "true" : "false"), (uintptr_t)PLASTW.get(), PLASTW ? escapeJSONStrings(PLASTW->m_szTitle) : ""); + escapeJSONStrings(PMONITOR ? std::to_string(PMONITOR->ID) : "null"), w->getWindows(), ((int)w->m_bHasFullscreenWindow == 1 ? "true" : "false"), + (uintptr_t)PLASTW.get(), PLASTW ? escapeJSONStrings(PLASTW->m_szTitle) : ""); } else { return std::format("workspace ID {} ({}) on monitor {}:\n\tmonitorID: {}\n\twindows: {}\n\thasfullscreen: {}\n\tlastwindow: 0x{:x}\n\tlastwindowtitle: {}\n\n", w->m_iID, - w->m_szName, PMONITOR ? PMONITOR->szName : "?", PMONITOR ? std::to_string(PMONITOR->ID) : "null", g_pCompositor->getWindowsOnWorkspace(w->m_iID), - (int)w->m_bHasFullscreenWindow, (uintptr_t)PLASTW.get(), PLASTW ? PLASTW->m_szTitle : ""); + w->m_szName, PMONITOR ? PMONITOR->szName : "?", PMONITOR ? std::to_string(PMONITOR->ID) : "null", w->getWindows(), (int)w->m_bHasFullscreenWindow, + (uintptr_t)PLASTW.get(), PLASTW ? PLASTW->m_szTitle : ""); } } @@ -1764,7 +1764,7 @@ std::string CHyprCtl::getReply(std::string request) { } for (auto const& w : g_pCompositor->m_vWindows) { - if (!w->m_bIsMapped || !g_pCompositor->isWorkspaceVisible(w->m_pWorkspace)) + if (!w->m_bIsMapped || !w->m_pWorkspace || !w->m_pWorkspace->isVisible()) continue; w->updateDynamicRules(); diff --git a/src/desktop/Window.cpp b/src/desktop/Window.cpp index 117d301c..12e81b76 100644 --- a/src/desktop/Window.cpp +++ b/src/desktop/Window.cpp @@ -413,12 +413,12 @@ void CWindow::moveToWorkspace(PHLWORKSPACE pWorkspace) { setAnimationsToMove(); - g_pCompositor->updateWorkspaceWindows(OLDWORKSPACE->m_iID); - g_pCompositor->updateWorkspaceWindowData(OLDWORKSPACE->m_iID); + OLDWORKSPACE->updateWindows(); + OLDWORKSPACE->updateWindowData(); g_pLayoutManager->getCurrentLayout()->recalculateMonitor(OLDWORKSPACE->monitorID()); - g_pCompositor->updateWorkspaceWindows(workspaceID()); - g_pCompositor->updateWorkspaceWindowData(workspaceID()); + pWorkspace->updateWindows(); + pWorkspace->updateWindowData(); g_pLayoutManager->getCurrentLayout()->recalculateMonitor(monitorID()); g_pCompositor->updateAllWindowsAnimatedDecorationValues(); @@ -437,7 +437,7 @@ void CWindow::moveToWorkspace(PHLWORKSPACE pWorkspace) { // update xwayland coords g_pXWaylandManager->setWindowSize(m_pSelf.lock(), m_vRealSize.value()); - if (OLDWORKSPACE && g_pCompositor->isWorkspaceSpecial(OLDWORKSPACE->m_iID) && g_pCompositor->getWindowsOnWorkspace(OLDWORKSPACE->m_iID) == 0 && *PCLOSEONLASTSPECIAL) { + if (OLDWORKSPACE && g_pCompositor->isWorkspaceSpecial(OLDWORKSPACE->m_iID) && OLDWORKSPACE->getWindows() == 0 && *PCLOSEONLASTSPECIAL) { if (const auto PMONITOR = OLDWORKSPACE->m_pMonitor.lock(); PMONITOR) PMONITOR->setSpecialWorkspace(nullptr); } @@ -516,7 +516,7 @@ void CWindow::onUnmap() { std::erase_if(g_pCompositor->m_vWindowFocusHistory, [&](const auto& other) { return other.expired() || other.lock().get() == this; }); - if (*PCLOSEONLASTSPECIAL && g_pCompositor->getWindowsOnWorkspace(workspaceID()) == 0 && onSpecialWorkspace()) { + if (*PCLOSEONLASTSPECIAL && m_pWorkspace && m_pWorkspace->getWindows() == 0 && onSpecialWorkspace()) { const auto PMONITOR = m_pMonitor.lock(); if (PMONITOR && PMONITOR->activeSpecialWorkspace && PMONITOR->activeSpecialWorkspace == m_pWorkspace) PMONITOR->setSpecialWorkspace(nullptr); @@ -527,8 +527,10 @@ void CWindow::onUnmap() { if (PMONITOR && PMONITOR->solitaryClient.lock().get() == this) PMONITOR->solitaryClient.reset(); - g_pCompositor->updateWorkspaceWindows(workspaceID()); - g_pCompositor->updateWorkspaceWindowData(workspaceID()); + if (m_pWorkspace) { + m_pWorkspace->updateWindows(); + m_pWorkspace->updateWindowData(); + } g_pLayoutManager->getCurrentLayout()->recalculateMonitor(monitorID()); g_pCompositor->updateAllWindowsAnimatedDecorationValues(); @@ -855,8 +857,10 @@ void CWindow::createGroup() { addWindowDeco(std::make_unique(m_pSelf.lock())); - g_pCompositor->updateWorkspaceWindows(workspaceID()); - g_pCompositor->updateWorkspaceWindowData(workspaceID()); + if (m_pWorkspace) { + m_pWorkspace->updateWindows(); + m_pWorkspace->updateWindowData(); + } g_pLayoutManager->getCurrentLayout()->recalculateMonitor(monitorID()); g_pCompositor->updateAllWindowsAnimatedDecorationValues(); @@ -873,8 +877,10 @@ void CWindow::destroyGroup() { m_sGroupData.pNextWindow.reset(); m_sGroupData.head = false; updateWindowDecos(); - g_pCompositor->updateWorkspaceWindows(workspaceID()); - g_pCompositor->updateWorkspaceWindowData(workspaceID()); + if (m_pWorkspace) { + m_pWorkspace->updateWindows(); + m_pWorkspace->updateWindowData(); + } g_pLayoutManager->getCurrentLayout()->recalculateMonitor(monitorID()); g_pCompositor->updateAllWindowsAnimatedDecorationValues(); @@ -909,8 +915,10 @@ void CWindow::destroyGroup() { } g_pKeybindManager->m_bGroupsLocked = GROUPSLOCKEDPREV; - g_pCompositor->updateWorkspaceWindows(workspaceID()); - g_pCompositor->updateWorkspaceWindowData(workspaceID()); + if (m_pWorkspace) { + m_pWorkspace->updateWindows(); + m_pWorkspace->updateWindowData(); + } g_pLayoutManager->getCurrentLayout()->recalculateMonitor(monitorID()); g_pCompositor->updateAllWindowsAnimatedDecorationValues(); @@ -1507,7 +1515,7 @@ void CWindow::onX11Configure(CBox box) { updateWindowDecos(); - if (!g_pCompositor->isWorkspaceVisible(m_pWorkspace)) + if (!m_pWorkspace || !m_pWorkspace->isVisible()) return; // further things are only for visible windows m_pWorkspace = g_pCompositor->getMonitorFromVector(m_vRealPosition.value() + m_vRealSize.value() / 2.f)->activeWorkspace; diff --git a/src/desktop/Workspace.cpp b/src/desktop/Workspace.cpp index 8cddbb6b..7c3d47d7 100644 --- a/src/desktop/Workspace.cpp +++ b/src/desktop/Workspace.cpp @@ -422,11 +422,11 @@ bool CWorkspace::matchesStaticSelector(const std::string& selector_) { int count; if (wantsCountGroup) - count = g_pCompositor->getGroupsOnWorkspace(m_iID, wantsOnlyTiled == -1 ? std::nullopt : std::optional((bool)wantsOnlyTiled), - wantsCountVisible ? std::optional(wantsCountVisible) : std::nullopt); + count = getGroups(wantsOnlyTiled == -1 ? std::nullopt : std::optional((bool)wantsOnlyTiled), + wantsCountVisible ? std::optional(wantsCountVisible) : std::nullopt); else - count = g_pCompositor->getWindowsOnWorkspace(m_iID, wantsOnlyTiled == -1 ? std::nullopt : std::optional((bool)wantsOnlyTiled), - wantsCountVisible ? std::optional(wantsCountVisible) : std::nullopt); + count = getWindows(wantsOnlyTiled == -1 ? std::nullopt : std::optional((bool)wantsOnlyTiled), + wantsCountVisible ? std::optional(wantsCountVisible) : std::nullopt); if (count != from) return false; @@ -456,11 +456,11 @@ bool CWorkspace::matchesStaticSelector(const std::string& selector_) { WORKSPACEID count; if (wantsCountGroup) - count = g_pCompositor->getGroupsOnWorkspace(m_iID, wantsOnlyTiled == -1 ? std::nullopt : std::optional((bool)wantsOnlyTiled), - wantsCountVisible ? std::optional(wantsCountVisible) : std::nullopt); + count = getGroups(wantsOnlyTiled == -1 ? std::nullopt : std::optional((bool)wantsOnlyTiled), + wantsCountVisible ? std::optional(wantsCountVisible) : std::nullopt); else - count = g_pCompositor->getWindowsOnWorkspace(m_iID, wantsOnlyTiled == -1 ? std::nullopt : std::optional((bool)wantsOnlyTiled), - wantsCountVisible ? std::optional(wantsCountVisible) : std::nullopt); + count = getWindows(wantsOnlyTiled == -1 ? std::nullopt : std::optional((bool)wantsOnlyTiled), + wantsCountVisible ? std::optional(wantsCountVisible) : std::nullopt); if (std::clamp(count, from, to) != count) return false; @@ -525,3 +525,136 @@ bool CWorkspace::inert() { MONITORID CWorkspace::monitorID() { return m_pMonitor ? m_pMonitor->ID : MONITOR_INVALID; } + +PHLWINDOW CWorkspace::getFullscreenWindow() { + for (auto const& w : g_pCompositor->m_vWindows) { + if (w->m_pWorkspace == m_pSelf && w->isFullscreen()) + return w; + } + + return nullptr; +} + +bool CWorkspace::isVisible() { + return m_bVisible; +} + +bool CWorkspace::isVisibleNotCovered() { + const auto PMONITOR = m_pMonitor.lock(); + if (PMONITOR->activeSpecialWorkspace) + return PMONITOR->activeSpecialWorkspace->m_iID == m_iID; + + return PMONITOR->activeWorkspace->m_iID == m_iID; +} + +int CWorkspace::getWindows(std::optional onlyTiled, std::optional onlyVisible) { + int no = 0; + for (auto const& w : g_pCompositor->m_vWindows) { + if (w->workspaceID() != m_iID || !w->m_bIsMapped) + continue; + if (onlyTiled.has_value() && w->m_bIsFloating == onlyTiled.value()) + continue; + if (onlyVisible.has_value() && w->isHidden() == onlyVisible.value()) + continue; + no++; + } + + return no; +} + +int CWorkspace::getGroups(std::optional onlyTiled, std::optional onlyVisible) { + int no = 0; + for (auto const& w : g_pCompositor->m_vWindows) { + if (w->workspaceID() != m_iID || !w->m_bIsMapped) + continue; + if (!w->m_sGroupData.head) + continue; + if (onlyTiled.has_value() && w->m_bIsFloating == onlyTiled.value()) + continue; + if (onlyVisible.has_value() && w->isHidden() == onlyVisible.value()) + continue; + no++; + } + return no; +} + +PHLWINDOW CWorkspace::getFirstWindow() { + for (auto const& w : g_pCompositor->m_vWindows) { + if (w->m_pWorkspace == m_pSelf && w->m_bIsMapped && !w->isHidden()) + return w; + } + + return nullptr; +} + +PHLWINDOW CWorkspace::getTopLeftWindow() { + const auto PMONITOR = m_pMonitor.lock(); + + for (auto const& w : g_pCompositor->m_vWindows) { + if (w->m_pWorkspace != m_pSelf || !w->m_bIsMapped || w->isHidden()) + continue; + + const auto WINDOWIDEALBB = w->getWindowIdealBoundingBoxIgnoreReserved(); + + if (WINDOWIDEALBB.x <= PMONITOR->vecPosition.x + 1 && WINDOWIDEALBB.y <= PMONITOR->vecPosition.y + 1) + return w; + } + return nullptr; +} + +bool CWorkspace::hasUrgentWindow() { + for (auto const& w : g_pCompositor->m_vWindows) { + if (w->m_pWorkspace == m_pSelf && w->m_bIsMapped && w->m_bIsUrgent) + return true; + } + + return false; +} + +void CWorkspace::updateWindowDecos() { + for (auto const& w : g_pCompositor->m_vWindows) { + if (w->m_pWorkspace != m_pSelf) + continue; + + w->updateWindowDecos(); + } +} + +void CWorkspace::updateWindowData() { + const auto WORKSPACERULE = g_pConfigManager->getWorkspaceRuleFor(m_pSelf.lock()); + + for (auto const& w : g_pCompositor->m_vWindows) { + if (w->m_pWorkspace != m_pSelf) + continue; + + w->updateWindowData(WORKSPACERULE); + } +} + +void CWorkspace::forceReportSizesToWindows() { + for (auto const& w : g_pCompositor->m_vWindows) { + if (w->m_pWorkspace != m_pSelf || !w->m_bIsMapped || w->isHidden()) + continue; + + g_pXWaylandManager->setWindowSize(w, w->m_vRealSize.value(), true); + } +} + +void CWorkspace::rename(const std::string& name) { + if (g_pCompositor->isWorkspaceSpecial(m_iID)) + return; + + Debug::log(LOG, "CWorkspace::rename: Renaming workspace {} to '{}'", m_iID, name); + m_szName = name; + + g_pEventManager->postEvent({"renameworkspace", std::to_string(m_iID) + "," + m_szName}); +} + +void CWorkspace::updateWindows() { + for (auto const& w : g_pCompositor->m_vWindows) { + if (!w->m_bIsMapped || w->m_pWorkspace != m_pSelf) + continue; + + w->updateDynamicRules(); + } +} diff --git a/src/desktop/Workspace.hpp b/src/desktop/Workspace.hpp index 3ed9f50c..606485a2 100644 --- a/src/desktop/Workspace.hpp +++ b/src/desktop/Workspace.hpp @@ -63,23 +63,29 @@ class CWorkspace { // Inert: destroyed and invalid. If this is true, release the ptr you have. bool inert(); - void startAnim(bool in, bool left, bool instant = false); void setActive(bool on); - void moveToMonitor(const MONITORID&); MONITORID monitorID(); - PHLWINDOW getLastFocusedWindow(); void rememberPrevWorkspace(const PHLWORKSPACE& prevWorkspace); - std::string getConfigName(); - bool matchesStaticSelector(const std::string& selector); - void markInert(); - SWorkspaceIDName getPrevWorkspaceIDName(bool perMonitor) const; + void updateWindowDecos(); + void updateWindowData(); + int getWindows(std::optional onlyTiled = {}, std::optional onlyVisible = {}); + int getGroups(std::optional onlyTiled = {}, std::optional onlyVisible = {}); + bool hasUrgentWindow(); + PHLWINDOW getFirstWindow(); + PHLWINDOW getTopLeftWindow(); + PHLWINDOW getFullscreenWindow(); + bool isVisible(); + bool isVisibleNotCovered(); + void rename(const std::string& name = ""); + void forceReportSizesToWindows(); + void updateWindows(); private: void init(PHLWORKSPACE self); diff --git a/src/events/Windows.cpp b/src/events/Windows.cpp index 73ab45c1..a607d7ce 100644 --- a/src/events/Windows.cpp +++ b/src/events/Windows.cpp @@ -509,7 +509,7 @@ void Events::listener_mapWindow(void* owner, void* data) { else if (*PNEWTAKESOVERFS == 1) requestedInternalFSMode = PWINDOW->m_pWorkspace->m_efFullscreenMode; else if (*PNEWTAKESOVERFS == 2) - g_pCompositor->setWindowFullscreenInternal(g_pCompositor->getFullscreenWindowOnWorkspace(PWINDOW->m_pWorkspace->m_iID), FSMODE_NONE); + g_pCompositor->setWindowFullscreenInternal(PWINDOW->m_pWorkspace->getFullscreenWindow(), FSMODE_NONE); } if (!PWINDOW->m_sWindowData.noFocus.valueOrDefault() && !PWINDOW->m_bNoInitialFocus && @@ -531,7 +531,7 @@ void Events::listener_mapWindow(void* owner, void* data) { if (!PWINDOW->m_bNoInitialFocus && (requestedInternalFSMode.has_value() || requestedClientFSMode.has_value() || requestedFSState.has_value())) { // fix fullscreen on requested (basically do a switcheroo) if (PWINDOW->m_pWorkspace->m_bHasFullscreenWindow) - g_pCompositor->setWindowFullscreenInternal(g_pCompositor->getFullscreenWindowOnWorkspace(PWINDOW->m_pWorkspace->m_iID), FSMODE_NONE); + g_pCompositor->setWindowFullscreenInternal(PWINDOW->m_pWorkspace->getFullscreenWindow(), FSMODE_NONE); PWINDOW->m_vRealPosition.warp(); PWINDOW->m_vRealSize.warp(); @@ -603,7 +603,8 @@ void Events::listener_mapWindow(void* owner, void* data) { // fix some xwayland apps that don't behave nicely PWINDOW->m_vReportedSize = PWINDOW->m_vPendingReportedSize; - g_pCompositor->updateWorkspaceWindows(PWINDOW->workspaceID()); + if (PWINDOW->m_pWorkspace) + PWINDOW->m_pWorkspace->updateWindows(); if (PMONITOR && PWINDOW->isX11OverrideRedirect()) PWINDOW->m_fX11SurfaceScaledBy = PMONITOR->scale; @@ -699,7 +700,7 @@ void Events::listener_unmapWindow(void* owner, void* data) { g_pCompositor->setWindowFullscreenInternal(PWINDOWCANDIDATE, CURRENTFSMODE); } - if (!PWINDOWCANDIDATE && g_pCompositor->getWindowsOnWorkspace(PWINDOW->workspaceID()) == 0) + if (!PWINDOWCANDIDATE && PWINDOW->m_pWorkspace && PWINDOW->m_pWorkspace->getWindows() == 0) g_pInputManager->refocus(); g_pInputManager->sendMotionEventsToFocused(); @@ -729,7 +730,8 @@ void Events::listener_unmapWindow(void* owner, void* data) { g_pInputManager->recheckIdleInhibitorStatus(); // force report all sizes (QT sometimes has an issue with this) - g_pCompositor->forceReportSizesToWindowsOnWorkspace(PWINDOW->workspaceID()); + if (PWINDOW->m_pWorkspace) + PWINDOW->m_pWorkspace->forceReportSizesToWindows(); // update lastwindow after focus PWINDOW->onUnmap(); diff --git a/src/helpers/MiscFunctions.cpp b/src/helpers/MiscFunctions.cpp index fa2f84ab..dc181d4f 100644 --- a/src/helpers/MiscFunctions.cpp +++ b/src/helpers/MiscFunctions.cpp @@ -264,7 +264,7 @@ SWorkspaceIDName getWorkspaceIDNameFromString(const std::string& in) { WORKSPACEID id = next ? g_pCompositor->m_pLastMonitor->activeWorkspaceID() : 0; while (++id < LONG_MAX) { const auto PWORKSPACE = g_pCompositor->getWorkspaceByID(id); - if (!invalidWSes.contains(id) && (!PWORKSPACE || g_pCompositor->getWindowsOnWorkspace(id) == 0)) { + if (!invalidWSes.contains(id) && (!PWORKSPACE || PWORKSPACE->getWindows() == 0)) { result.id = id; return result; } diff --git a/src/helpers/Monitor.cpp b/src/helpers/Monitor.cpp index 63268c8a..cbad959e 100644 --- a/src/helpers/Monitor.cpp +++ b/src/helpers/Monitor.cpp @@ -629,17 +629,17 @@ void CMonitor::changeWorkspace(const PHLWORKSPACE& pWorkspace, bool internal, bo if (!noFocus && !g_pCompositor->m_pLastMonitor->activeSpecialWorkspace && !(g_pCompositor->m_pLastWindow.lock() && g_pCompositor->m_pLastWindow->m_bPinned && g_pCompositor->m_pLastWindow->m_pMonitor == self)) { static auto PFOLLOWMOUSE = CConfigValue("input:follow_mouse"); - auto pWindow = pWorkspace->m_bHasFullscreenWindow ? g_pCompositor->getFullscreenWindowOnWorkspace(pWorkspace->m_iID) : pWorkspace->getLastFocusedWindow(); + auto pWindow = pWorkspace->m_bHasFullscreenWindow ? pWorkspace->getFullscreenWindow() : pWorkspace->getLastFocusedWindow(); if (!pWindow) { if (*PFOLLOWMOUSE == 1) pWindow = g_pCompositor->vectorToWindowUnified(g_pInputManager->getMouseCoordsInternal(), RESERVED_EXTENTS | INPUT_EXTENTS | ALLOW_FLOATING); if (!pWindow) - pWindow = g_pCompositor->getTopLeftWindowOnWorkspace(pWorkspace->m_iID); + pWindow = pWorkspace->getTopLeftWindow(); if (!pWindow) - pWindow = g_pCompositor->getFirstWindowOnWorkspace(pWorkspace->m_iID); + pWindow = pWorkspace->getFirstWindow(); } g_pCompositor->focusWindow(pWindow); diff --git a/src/layout/DwindleLayout.cpp b/src/layout/DwindleLayout.cpp index c3e394f3..864c8564 100644 --- a/src/layout/DwindleLayout.cpp +++ b/src/layout/DwindleLayout.cpp @@ -514,7 +514,7 @@ void CHyprDwindleLayout::calculateWorkspace(const PHLWORKSPACE& pWorkspace) { if (pWorkspace->m_bHasFullscreenWindow) { // massive hack from the fullscreen func - const auto PFULLWINDOW = g_pCompositor->getFullscreenWindowOnWorkspace(pWorkspace->m_iID); + const auto PFULLWINDOW = pWorkspace->getFullscreenWindow(); if (pWorkspace->m_efFullscreenMode == FSMODE_FULLSCREEN) { PFULLWINDOW->m_vRealPosition = PMONITOR->vecPosition; @@ -1054,7 +1054,7 @@ void CHyprDwindleLayout::moveToRoot(PHLWINDOW pWindow, bool stable) { std::swap(pRoot->children[0], pRoot->children[1]); // if the workspace is visible, recalculate layout - if (g_pCompositor->isWorkspaceVisible(pWindow->m_pWorkspace)) + if (pWindow->m_pWorkspace && pWindow->m_pWorkspace->isVisible()) pRoot->recalcSizePosRecursive(); } @@ -1094,7 +1094,7 @@ Vector2D CHyprDwindleLayout::predictSizeForNewWindowTiled() { PHLWINDOW candidate = g_pCompositor->m_pLastWindow.lock(); if (!candidate) - candidate = g_pCompositor->getFirstWindowOnWorkspace(g_pCompositor->m_pLastMonitor->activeWorkspace->m_iID); + candidate = g_pCompositor->m_pLastMonitor->activeWorkspace->getFirstWindow(); // create a fake node SDwindleNodeData node; diff --git a/src/layout/IHyprLayout.cpp b/src/layout/IHyprLayout.cpp index af8b907c..22e1d947 100644 --- a/src/layout/IHyprLayout.cpp +++ b/src/layout/IHyprLayout.cpp @@ -187,7 +187,7 @@ bool IHyprLayout::onWindowCreatedAutoGroup(PHLWINDOW pWindow) { static auto PAUTOGROUP = CConfigValue("group:auto_group"); const PHLWINDOW OPENINGON = g_pCompositor->m_pLastWindow.lock() && g_pCompositor->m_pLastWindow->m_pWorkspace == pWindow->m_pWorkspace ? g_pCompositor->m_pLastWindow.lock() : - g_pCompositor->getFirstWindowOnWorkspace(pWindow->workspaceID()); + (pWindow->m_pWorkspace ? pWindow->m_pWorkspace->getFirstWindow() : nullptr); const bool FLOATEDINTOTILED = pWindow->m_bIsFloating && !OPENINGON->m_bIsFloating; const bool SWALLOWING = pWindow->m_pSwallowed || pWindow->m_bGroupSwallowed; @@ -714,7 +714,7 @@ void IHyprLayout::changeWindowFloatingMode(PHLWINDOW pWindow) { const auto PWORKSPACE = PNEWMON->activeSpecialWorkspace ? PNEWMON->activeSpecialWorkspace : PNEWMON->activeWorkspace; if (PWORKSPACE->m_bHasFullscreenWindow) - g_pCompositor->setWindowFullscreenInternal(g_pCompositor->getFullscreenWindowOnWorkspace(PWORKSPACE->m_iID), FSMODE_NONE); + g_pCompositor->setWindowFullscreenInternal(PWORKSPACE->getFullscreenWindow(), FSMODE_NONE); // save real pos cuz the func applies the default 5,5 mid const auto PSAVEDPOS = pWindow->m_vRealPosition.goal(); @@ -803,7 +803,7 @@ PHLWINDOW IHyprLayout::getNextWindowCandidate(PHLWINDOW pWindow) { // first of all, if this is a fullscreen workspace, if (PWORKSPACE->m_bHasFullscreenWindow) - return g_pCompositor->getFullscreenWindowOnWorkspace(pWindow->workspaceID()); + return PWORKSPACE->getFullscreenWindow(); if (pWindow->m_bIsFloating) { @@ -842,10 +842,10 @@ PHLWINDOW IHyprLayout::getNextWindowCandidate(PHLWINDOW pWindow) { auto pWindowCandidate = g_pCompositor->vectorToWindowUnified(pWindow->middle(), RESERVED_EXTENTS | INPUT_EXTENTS | ALLOW_FLOATING); if (!pWindowCandidate) - pWindowCandidate = g_pCompositor->getTopLeftWindowOnWorkspace(pWindow->workspaceID()); + pWindowCandidate = PWORKSPACE->getTopLeftWindow(); if (!pWindowCandidate) - pWindowCandidate = g_pCompositor->getFirstWindowOnWorkspace(pWindow->workspaceID()); + pWindowCandidate = PWORKSPACE->getFirstWindow(); if (!pWindowCandidate || pWindow == pWindowCandidate || !pWindowCandidate->m_bIsMapped || pWindowCandidate->isHidden() || pWindowCandidate->m_bX11ShouldntFocus || pWindowCandidate->isX11OverrideRedirect() || pWindowCandidate->m_pMonitor != g_pCompositor->m_pLastMonitor) diff --git a/src/layout/MasterLayout.cpp b/src/layout/MasterLayout.cpp index 695dcc99..bf808627 100644 --- a/src/layout/MasterLayout.cpp +++ b/src/layout/MasterLayout.cpp @@ -298,7 +298,7 @@ void CHyprMasterLayout::calculateWorkspace(PHLWORKSPACE pWorkspace) { if (pWorkspace->m_bHasFullscreenWindow) { // massive hack from the fullscreen func - const auto PFULLWINDOW = g_pCompositor->getFullscreenWindowOnWorkspace(pWorkspace->m_iID); + const auto PFULLWINDOW = pWorkspace->getFullscreenWindow(); if (pWorkspace->m_efFullscreenMode == FSMODE_FULLSCREEN) { PFULLWINDOW->m_vRealPosition = PMONITOR->vecPosition; diff --git a/src/managers/AnimationManager.cpp b/src/managers/AnimationManager.cpp index ceb594aa..68dbdda1 100644 --- a/src/managers/AnimationManager.cpp +++ b/src/managers/AnimationManager.cpp @@ -149,7 +149,7 @@ void CAnimationManager::tick() { animationsDisabled = animationsDisabled || PLAYER->noAnimations; } - const bool VISIBLE = PWINDOW && PWINDOW->m_pWorkspace ? g_pCompositor->isWorkspaceVisible(PWINDOW->m_pWorkspace) : true; + const bool VISIBLE = PWINDOW && PWINDOW->m_pWorkspace ? PWINDOW->m_pWorkspace->isVisible() : true; // beziers are with a switch unforto // TODO: maybe do something cleaner diff --git a/src/managers/KeybindManager.cpp b/src/managers/KeybindManager.cpp index 8cf39c1b..a5327149 100644 --- a/src/managers/KeybindManager.cpp +++ b/src/managers/KeybindManager.cpp @@ -1036,8 +1036,12 @@ static SDispatchResult toggleActiveFloatingCore(std::string args, std::optional< g_pLayoutManager->getCurrentLayout()->changeWindowFloatingMode(PWINDOW); } - g_pCompositor->updateWorkspaceWindows(PWINDOW->workspaceID()); - g_pCompositor->updateWorkspaceWindowData(PWINDOW->workspaceID()); + + if (PWINDOW->m_pWorkspace) { + PWINDOW->m_pWorkspace->updateWindows(); + PWINDOW->m_pWorkspace->updateWindowData(); + } + g_pLayoutManager->getCurrentLayout()->recalculateMonitor(PWINDOW->monitorID()); g_pCompositor->updateAllWindowsAnimatedDecorationValues(); @@ -1305,7 +1309,7 @@ SDispatchResult CKeybindManager::moveActiveToWorkspace(std::string args) { g_pCompositor->moveWindowToWorkspaceSafe(PWINDOW, pWorkspace); } - POLDWS->m_pLastFocusedWindow = g_pCompositor->getFirstWindowOnWorkspace(POLDWS->m_iID); + POLDWS->m_pLastFocusedWindow = POLDWS->getFirstWindow(); if (pWorkspace->m_bIsSpecialWorkspace) pMonitor->setSpecialWorkspace(pWorkspace); @@ -1799,10 +1803,14 @@ SDispatchResult CKeybindManager::renameWorkspace(std::string args) { if (FIRSTSPACEPOS != std::string::npos) { int workspace = std::stoi(args.substr(0, FIRSTSPACEPOS)); std::string name = args.substr(FIRSTSPACEPOS + 1); - g_pCompositor->renameWorkspace(workspace, name); - } else { - g_pCompositor->renameWorkspace(std::stoi(args), ""); - } + if (const auto& PWS = g_pCompositor->getWorkspaceByID(workspace); PWS) + PWS->rename(name); + else + return {.success = false, .error = "No such workspace"}; + } else if (const auto& PWS = g_pCompositor->getWorkspaceByID(std::stoi(args)); PWS) + PWS->rename(""); + else + return {.success = false, .error = "No such workspace"}; } catch (std::exception& e) { Debug::log(ERR, "Invalid arg in renameWorkspace, expected numeric id only or a numeric id and string name. \"{}\": \"{}\"", args, e.what()); return {.success = false, .error = std::format("Invalid arg in renameWorkspace, expected numeric id only or a numeric id and string name. \"{}\": \"{}\"", args, e.what())}; @@ -2069,9 +2077,9 @@ SDispatchResult CKeybindManager::circleNext(std::string arg) { if (g_pCompositor->m_pLastWindow.expired()) { // if we have a clear focus, find the first window and get the next focusable. - if (g_pCompositor->getWindowsOnWorkspace(g_pCompositor->m_pLastMonitor->activeWorkspaceID()) > 0) { - const auto PWINDOW = g_pCompositor->getFirstWindowOnWorkspace(g_pCompositor->m_pLastMonitor->activeWorkspaceID()); - + const auto PWS = g_pCompositor->m_pLastMonitor->activeWorkspace; + if (PWS && PWS->getWindows() > 0) { + const auto PWINDOW = PWS->getFirstWindow(); switchToWindow(PWINDOW); } @@ -2117,7 +2125,7 @@ SDispatchResult CKeybindManager::focusWindow(std::string regexp) { } if (PWORKSPACE->m_bHasFullscreenWindow) { - const auto FSWINDOW = g_pCompositor->getFullscreenWindowOnWorkspace(PWORKSPACE->m_iID); + const auto FSWINDOW = PWORKSPACE->getFullscreenWindow(); const auto FSMODE = PWORKSPACE->m_efFullscreenMode; if (PWINDOW->m_bIsFloating) { diff --git a/src/managers/input/IdleInhibitor.cpp b/src/managers/input/IdleInhibitor.cpp index a6f25142..7c91258e 100644 --- a/src/managers/input/IdleInhibitor.cpp +++ b/src/managers/input/IdleInhibitor.cpp @@ -63,7 +63,7 @@ void CInputManager::recheckIdleInhibitorStatus() { return; } - if (w->m_eIdleInhibitMode == IDLEINHIBIT_FULLSCREEN && w->isFullscreen() && g_pCompositor->isWorkspaceVisible(w->m_pWorkspace)) { + if (w->m_eIdleInhibitMode == IDLEINHIBIT_FULLSCREEN && w->isFullscreen() && w->m_pWorkspace && w->m_pWorkspace->isVisible()) { PROTO::idle->setInhibit(true); return; } diff --git a/src/managers/input/InputManager.cpp b/src/managers/input/InputManager.cpp index 9110cd15..525ca954 100644 --- a/src/managers/input/InputManager.cpp +++ b/src/managers/input/InputManager.cpp @@ -294,7 +294,7 @@ void CInputManager::mouseMoveUnified(uint32_t time, bool refocus) { const auto PWORKSPACE = PMONITOR->activeWorkspace; const auto PWINDOWIDEAL = g_pCompositor->vectorToWindowUnified(mouseCoords, RESERVED_EXTENTS | INPUT_EXTENTS | ALLOW_FLOATING); if (PWORKSPACE->m_bHasFullscreenWindow && !foundSurface && PWORKSPACE->m_efFullscreenMode == FSMODE_FULLSCREEN) { - pFoundWindow = g_pCompositor->getFullscreenWindowOnWorkspace(PWORKSPACE->m_iID); + pFoundWindow = PWORKSPACE->getFullscreenWindow(); if (!pFoundWindow) { // what the fuck, somehow happens occasionally?? @@ -325,7 +325,7 @@ void CInputManager::mouseMoveUnified(uint32_t time, bool refocus) { pFoundWindow = g_pCompositor->vectorToWindowUnified(mouseCoords, RESERVED_EXTENTS | INPUT_EXTENTS | ALLOW_FLOATING); if (pFoundWindow && !pFoundWindow->onSpecialWorkspace()) { - pFoundWindow = g_pCompositor->getFullscreenWindowOnWorkspace(PWORKSPACE->m_iID); + pFoundWindow = PWORKSPACE->getFullscreenWindow(); } } else { // if we have a maximized window, allow focusing on a bar or something if in reserved area. @@ -339,7 +339,7 @@ void CInputManager::mouseMoveUnified(uint32_t time, bool refocus) { pFoundWindow = g_pCompositor->vectorToWindowUnified(mouseCoords, RESERVED_EXTENTS | INPUT_EXTENTS | ALLOW_FLOATING); if (!(pFoundWindow && pFoundWindow->m_bIsFloating && pFoundWindow->m_bCreatedOverFullscreen)) - pFoundWindow = g_pCompositor->getFullscreenWindowOnWorkspace(PWORKSPACE->m_iID); + pFoundWindow = PWORKSPACE->getFullscreenWindow(); } } } @@ -1402,7 +1402,7 @@ void CInputManager::refocusLastWindow(PHLMONITOR pMonitor) { foundSurface = nullptr; } - if (!foundSurface && g_pCompositor->m_pLastWindow.lock() && g_pCompositor->isWorkspaceVisibleNotCovered(g_pCompositor->m_pLastWindow->m_pWorkspace)) { + if (!foundSurface && g_pCompositor->m_pLastWindow.lock() && g_pCompositor->m_pLastWindow->m_pWorkspace && g_pCompositor->m_pLastWindow->m_pWorkspace->isVisibleNotCovered()) { // then the last focused window if we're on the same workspace as it const auto PLASTWINDOW = g_pCompositor->m_pLastWindow.lock(); g_pCompositor->focusWindow(PLASTWINDOW); diff --git a/src/managers/input/Swipe.cpp b/src/managers/input/Swipe.cpp index ba0783fa..6cfe5a24 100644 --- a/src/managers/input/Swipe.cpp +++ b/src/managers/input/Swipe.cpp @@ -243,8 +243,7 @@ void CInputManager::updateWorkspaceSwipe(double delta) { m_sActiveSwipe.delta = std::clamp(m_sActiveSwipe.delta, (double)-SWIPEDISTANCE, (double)SWIPEDISTANCE); if ((m_sActiveSwipe.pWorkspaceBegin->m_iID == workspaceIDLeft && *PSWIPENEW && (m_sActiveSwipe.delta < 0)) || - (m_sActiveSwipe.delta > 0 && g_pCompositor->getWindowsOnWorkspace(m_sActiveSwipe.pWorkspaceBegin->m_iID) == 0 && - workspaceIDRight <= m_sActiveSwipe.pWorkspaceBegin->m_iID) || + (m_sActiveSwipe.delta > 0 && m_sActiveSwipe.pWorkspaceBegin->getWindows() == 0 && workspaceIDRight <= m_sActiveSwipe.pWorkspaceBegin->m_iID) || (m_sActiveSwipe.delta < 0 && m_sActiveSwipe.pWorkspaceBegin->m_iID <= workspaceIDLeft)) { m_sActiveSwipe.delta = 0; @@ -270,7 +269,7 @@ void CInputManager::updateWorkspaceSwipe(double delta) { else m_sActiveSwipe.pWorkspaceBegin->m_vRenderOffset.setValueAndWarp(Vector2D(((-m_sActiveSwipe.delta) / SWIPEDISTANCE) * XDISTANCE, 0.0)); - g_pCompositor->updateWorkspaceWindowDecos(m_sActiveSwipe.pWorkspaceBegin->m_iID); + m_sActiveSwipe.pWorkspaceBegin->updateWindowDecos(); return; } m_sActiveSwipe.delta = 0; @@ -297,7 +296,7 @@ void CInputManager::updateWorkspaceSwipe(double delta) { m_sActiveSwipe.pWorkspaceBegin->m_vRenderOffset.setValueAndWarp(Vector2D(((-m_sActiveSwipe.delta) / SWIPEDISTANCE) * XDISTANCE, 0.0)); } - g_pCompositor->updateWorkspaceWindowDecos(workspaceIDLeft); + PWORKSPACE->updateWindowDecos(); } else { const auto PWORKSPACE = g_pCompositor->getWorkspaceByID(workspaceIDRight); @@ -310,7 +309,7 @@ void CInputManager::updateWorkspaceSwipe(double delta) { else m_sActiveSwipe.pWorkspaceBegin->m_vRenderOffset.setValueAndWarp(Vector2D(((-m_sActiveSwipe.delta) / SWIPEDISTANCE) * XDISTANCE, 0.0)); - g_pCompositor->updateWorkspaceWindowDecos(m_sActiveSwipe.pWorkspaceBegin->m_iID); + m_sActiveSwipe.pWorkspaceBegin->updateWindowDecos(); return; } m_sActiveSwipe.delta = 0; @@ -337,12 +336,12 @@ void CInputManager::updateWorkspaceSwipe(double delta) { m_sActiveSwipe.pWorkspaceBegin->m_vRenderOffset.setValueAndWarp(Vector2D(((-m_sActiveSwipe.delta) / SWIPEDISTANCE) * XDISTANCE, 0.0)); } - g_pCompositor->updateWorkspaceWindowDecos(workspaceIDRight); + PWORKSPACE->updateWindowDecos(); } g_pHyprRenderer->damageMonitor(m_sActiveSwipe.pMonitor.lock()); - g_pCompositor->updateWorkspaceWindowDecos(m_sActiveSwipe.pWorkspaceBegin->m_iID); + m_sActiveSwipe.pWorkspaceBegin->updateWindowDecos(); if (*PSWIPEFOREVER) { if (abs(m_sActiveSwipe.delta) >= SWIPEDISTANCE) { diff --git a/src/render/Renderer.cpp b/src/render/Renderer.cpp index 42545bc1..57490d23 100644 --- a/src/render/Renderer.cpp +++ b/src/render/Renderer.cpp @@ -310,8 +310,8 @@ bool CHyprRenderer::shouldRenderWindow(PHLWINDOW pWindow, PHLMONITOR pMonitor) { return true; // if the window is being moved to a workspace that is not invisible, and the alpha is > 0.F, render it. - if (pWindow->m_iMonitorMovedFrom != -1 && pWindow->m_fMovingToWorkspaceAlpha.isBeingAnimated() && pWindow->m_fMovingToWorkspaceAlpha.value() > 0.F && - !g_pCompositor->isWorkspaceVisible(pWindow->m_pWorkspace)) + if (pWindow->m_iMonitorMovedFrom != -1 && pWindow->m_fMovingToWorkspaceAlpha.isBeingAnimated() && pWindow->m_fMovingToWorkspaceAlpha.value() > 0.F && pWindow->m_pWorkspace && + !pWindow->m_pWorkspace->isVisible()) return true; const auto PWINDOWWORKSPACE = pWindow->m_pWorkspace; @@ -324,18 +324,18 @@ bool CHyprRenderer::shouldRenderWindow(PHLWINDOW pWindow, PHLMONITOR pMonitor) { pWindow->m_fAlpha.value() == 0) return false; - if (!PWINDOWWORKSPACE->m_vRenderOffset.isBeingAnimated() && !PWINDOWWORKSPACE->m_fAlpha.isBeingAnimated() && !g_pCompositor->isWorkspaceVisible(pWindow->m_pWorkspace)) + if (!PWINDOWWORKSPACE->m_vRenderOffset.isBeingAnimated() && !PWINDOWWORKSPACE->m_fAlpha.isBeingAnimated() && !PWINDOWWORKSPACE->isVisible()) return false; } if (pWindow->m_pMonitor == pMonitor) return true; - if (!g_pCompositor->isWorkspaceVisible(pWindow->m_pWorkspace) && pWindow->m_pMonitor != pMonitor) + if (!(!pWindow->m_pWorkspace || !pWindow->m_pWorkspace->isVisible()) && pWindow->m_pMonitor != pMonitor) return false; // if not, check if it maybe is active on a different monitor. - if (g_pCompositor->isWorkspaceVisible(pWindow->m_pWorkspace) && pWindow->m_bIsFloating /* tiled windows can't be multi-ws */) + if (pWindow->m_pWorkspace && pWindow->m_pWorkspace->isVisible() && pWindow->m_bIsFloating /* tiled windows can't be multi-ws */) return !pWindow->isFullscreen(); // Do not draw fullscreen windows on other monitors if (pMonitor->activeSpecialWorkspace == pWindow->m_pWorkspace) @@ -376,7 +376,7 @@ bool CHyprRenderer::shouldRenderWindow(PHLWINDOW pWindow) { if (pWindow->m_bPinned || PWORKSPACE->m_bForceRendering) return true; - if (g_pCompositor->isWorkspaceVisible(pWindow->m_pWorkspace)) + if (PWORKSPACE && PWORKSPACE->isVisible()) return true; for (auto const& m : g_pCompositor->m_vMonitors) { @@ -591,7 +591,7 @@ void CHyprRenderer::renderWindow(PHLWINDOW pWindow, PHLMONITOR pMonitor, timespe decorate = false; // whether to use m_fMovingToWorkspaceAlpha, only if fading out into an invisible ws - const bool USE_WORKSPACE_FADE_ALPHA = pWindow->m_iMonitorMovedFrom != -1 && !g_pCompositor->isWorkspaceVisible(pWindow->m_pWorkspace); + const bool USE_WORKSPACE_FADE_ALPHA = pWindow->m_iMonitorMovedFrom != -1 && (!PWORKSPACE || !PWORKSPACE->isVisible()); const bool DONT_BLUR = pWindow->m_sWindowData.noBlur.valueOrDefault() || pWindow->m_sWindowData.RGBX.valueOrDefault() || pWindow->opaque(); renderdata.surface = pWindow->m_pWLSurface->resource(); @@ -933,7 +933,7 @@ void CHyprRenderer::renderAllClientsForWorkspace(PHLMONITOR pMonitor, PHLWORKSPA // Render layer surfaces below windows for monitor // if we have a fullscreen, opaque window that convers the screen, we can skip this. // TODO: check better with solitary after MR for tearing. - const auto PFULLWINDOW = pWorkspace ? g_pCompositor->getFullscreenWindowOnWorkspace(pWorkspace->m_iID) : nullptr; + const auto PFULLWINDOW = pWorkspace ? pWorkspace->getFullscreenWindow() : nullptr; if (!pWorkspace->m_bHasFullscreenWindow || pWorkspace->m_efFullscreenMode != FSMODE_FULLSCREEN || !PFULLWINDOW || PFULLWINDOW->m_vRealSize.isBeingAnimated() || !PFULLWINDOW->opaque() || pWorkspace->m_vRenderOffset.value() != Vector2D{} || g_pHyprOpenGL->preBlurQueued()) { @@ -2639,7 +2639,7 @@ void CHyprRenderer::recheckSolitaryForMonitor(PHLMONITOR pMonitor) { PWORKSPACE->m_vRenderOffset.value() != Vector2D{}) return; - const auto PCANDIDATE = g_pCompositor->getFullscreenWindowOnWorkspace(PWORKSPACE->m_iID); + const auto PCANDIDATE = PWORKSPACE->getFullscreenWindow(); if (!PCANDIDATE) return; // ???? From 00d6261cc06716eac6bdfc9d4426c3a54597098c Mon Sep 17 00:00:00 2001 From: Vaxry Date: Sat, 23 Nov 2024 14:18:13 +0000 Subject: [PATCH 0671/2181] hyprpm: move temp files to XDG_RUNTIME_DIR avoid /tmp, it's cringe --- hyprpm/src/core/PluginManager.cpp | 44 ++++++++++++++++++++----------- 1 file changed, 28 insertions(+), 16 deletions(-) diff --git a/hyprpm/src/core/PluginManager.cpp b/hyprpm/src/core/PluginManager.cpp index db315193..fb3065b4 100644 --- a/hyprpm/src/core/PluginManager.cpp +++ b/hyprpm/src/core/PluginManager.cpp @@ -38,6 +38,18 @@ static std::string execAndGet(std::string cmd) { return proc.stdOut(); } +static std::string getTempRoot() { + static auto ENV = getenv("XDG_RUNTIME_DIR"); + if (!ENV) { + std::cerr << "\nERROR: XDG_RUNTIME_DIR not set!\n"; + exit(1); + } + + const auto STR = ENV + std::string{"/hyprpm/"}; + + return STR; +} + SHyprlandVersion CPluginManager::getHyprlandVersion() { static SHyprlandVersion ver; static bool once = false; @@ -84,7 +96,7 @@ SHyprlandVersion CPluginManager::getHyprlandVersion() { } bool CPluginManager::createSafeDirectory(const std::string& path) { - if (path.empty() || !path.starts_with("/tmp")) + if (path.empty() || !path.starts_with(getTempRoot())) return false; if (std::filesystem::exists(path)) @@ -142,17 +154,17 @@ bool CPluginManager::addNewPluginRepo(const std::string& url, const std::string& progress.print(); - if (!std::filesystem::exists("/tmp/hyprpm")) { - std::filesystem::create_directory("/tmp/hyprpm"); - std::filesystem::permissions("/tmp/hyprpm", std::filesystem::perms::all, std::filesystem::perm_options::replace); - } else if (!std::filesystem::is_directory("/tmp/hyprpm")) { + if (!std::filesystem::exists(getTempRoot())) { + std::filesystem::create_directory(getTempRoot()); + std::filesystem::permissions(getTempRoot(), std::filesystem::perms::owner_all, std::filesystem::perm_options::replace); + } else if (!std::filesystem::is_directory(getTempRoot())) { std::println(stderr, "\n{}", failureString("Could not prepare working dir for hyprpm")); return false; } const std::string USERNAME = getpwuid(getuid())->pw_name; - m_szWorkingPluginDirectory = "/tmp/hyprpm/" + USERNAME; + m_szWorkingPluginDirectory = getTempRoot() + USERNAME; if (!createSafeDirectory(m_szWorkingPluginDirectory)) { std::println(stderr, "\n{}", failureString("Could not prepare working dir for repo")); @@ -161,7 +173,7 @@ bool CPluginManager::addNewPluginRepo(const std::string& url, const std::string& progress.printMessageAbove(infoString("Cloning {}", url)); - std::string ret = execAndGet("cd /tmp/hyprpm && git clone --recursive " + url + " " + USERNAME); + std::string ret = execAndGet(std::format("cd {} && git clone --recursive {} {}", getTempRoot(), url, USERNAME)); if (!std::filesystem::exists(m_szWorkingPluginDirectory + "/.git")) { std::println(stderr, "\n{}", failureString("Could not clone the plugin repository. shell returned:\n{}", ret)); @@ -413,9 +425,9 @@ bool CPluginManager::updateHeaders(bool force) { return false; } - if (!std::filesystem::exists("/tmp/hyprpm")) { - std::filesystem::create_directory("/tmp/hyprpm"); - std::filesystem::permissions("/tmp/hyprpm", std::filesystem::perms::all, std::filesystem::perm_options::replace); + if (!std::filesystem::exists(getTempRoot())) { + std::filesystem::create_directory(getTempRoot()); + std::filesystem::permissions(getTempRoot(), std::filesystem::perms::owner_all, std::filesystem::perm_options::replace); } if (!force && headersValid() == HEADERS_OK) { @@ -430,7 +442,7 @@ bool CPluginManager::updateHeaders(bool force) { progress.print(); const std::string USERNAME = getpwuid(getuid())->pw_name; - const auto WORKINGDIR = "/tmp/hyprpm/hyprland-" + USERNAME; + const auto WORKINGDIR = getTempRoot() + "hyprland-" + USERNAME; if (!createSafeDirectory(WORKINGDIR)) { std::println("\n{}", failureString("Could not prepare working dir for hl")); @@ -448,12 +460,12 @@ bool CPluginManager::updateHeaders(bool force) { if (m_bVerbose && bShallow) progress.printMessageAbove(verboseString("will shallow since: {}", SHALLOW_DATE)); - std::string ret = - execAndGet("cd /tmp/hyprpm && git clone --recursive https://github.com/hyprwm/Hyprland hyprland-" + USERNAME + (bShallow ? " --shallow-since='" + SHALLOW_DATE + "'" : "")); + std::string ret = execAndGet(std::format("cd {} && git clone --recursive https://github.com/hyprwm/Hyprland hyprland-{}{}", getTempRoot(), USERNAME, + (bShallow ? " --shallow-since='" + SHALLOW_DATE + "'" : ""))); if (!std::filesystem::exists(WORKINGDIR)) { progress.printMessageAbove(failureString("Clone failed. Retrying without shallow.")); - ret = execAndGet("cd /tmp/hyprpm && git clone --recursive https://github.com/hyprwm/hyprland hyprland-" + USERNAME); + ret = execAndGet(std::format("cd {} && git clone --recursive https://github.com/hyprwm/hyprland hyprland-{}", getTempRoot(), USERNAME)); } if (!std::filesystem::exists(WORKINGDIR + "/.git")) { @@ -577,7 +589,7 @@ bool CPluginManager::updatePlugins(bool forceUpdateAll) { progress.print(); const std::string USERNAME = getpwuid(getuid())->pw_name; - m_szWorkingPluginDirectory = "/tmp/hyprpm/" + USERNAME; + m_szWorkingPluginDirectory = getTempRoot() + USERNAME; for (auto const& repo : REPOS) { bool update = forceUpdateAll; @@ -592,7 +604,7 @@ bool CPluginManager::updatePlugins(bool forceUpdateAll) { progress.printMessageAbove(infoString("Cloning {}", repo.url)); - std::string ret = execAndGet("cd /tmp/hyprpm && git clone --recursive " + repo.url + " " + USERNAME); + std::string ret = execAndGet(std::format("cd {} && git clone --recursive {} {}", getTempRoot(), repo.url, USERNAME)); if (!std::filesystem::exists(m_szWorkingPluginDirectory + "/.git")) { std::println("{}", failureString("could not clone repo: shell returned: {}", ret)); From 451d7a41fc87529854c4116c96a7c6a46568a1ee Mon Sep 17 00:00:00 2001 From: Ryan Date: Sat, 23 Nov 2024 09:29:29 -0500 Subject: [PATCH 0672/2181] renderer: add option to blur IME popups (#8521) --- src/config/ConfigDescriptions.hpp | 12 ++++++++++++ src/config/ConfigManager.cpp | 2 ++ src/render/Renderer.cpp | 11 ++++++++++- 3 files changed, 24 insertions(+), 1 deletion(-) diff --git a/src/config/ConfigDescriptions.hpp b/src/config/ConfigDescriptions.hpp index 2e3a6720..45379140 100644 --- a/src/config/ConfigDescriptions.hpp +++ b/src/config/ConfigDescriptions.hpp @@ -331,6 +331,18 @@ inline static const std::vector CONFIG_OPTIONS = { .type = CONFIG_OPTION_FLOAT, .data = SConfigOptionDescription::SFloatData{0.2, 0, 1}, }, + SConfigOptionDescription{ + .value = "blur:input_methods", + .description = "whether to blur input methods (e.g. fcitx5)", + .type = CONFIG_OPTION_BOOL, + .data = SConfigOptionDescription::SBoolData{false}, + }, + SConfigOptionDescription{ + .value = "blur:input_methods_ignorealpha", + .description = "works like ignorealpha in layer rules. If pixel opacity is below set value, will not blur. [0.0 - 1.0]", + .type = CONFIG_OPTION_FLOAT, + .data = SConfigOptionDescription::SFloatData{0.2, 0, 1}, + }, /* * animations: diff --git a/src/config/ConfigManager.cpp b/src/config/ConfigManager.cpp index f6734011..32f64f0a 100644 --- a/src/config/ConfigManager.cpp +++ b/src/config/ConfigManager.cpp @@ -429,6 +429,8 @@ CConfigManager::CConfigManager() { m_pConfig->addConfigValue("decoration:blur:special", Hyprlang::INT{0}); m_pConfig->addConfigValue("decoration:blur:popups", Hyprlang::INT{0}); m_pConfig->addConfigValue("decoration:blur:popups_ignorealpha", {0.2F}); + m_pConfig->addConfigValue("decoration:blur:input_methods", Hyprlang::INT{0}); + m_pConfig->addConfigValue("decoration:blur:input_methods_ignorealpha", {0.2F}); m_pConfig->addConfigValue("decoration:active_opacity", {1.F}); m_pConfig->addConfigValue("decoration:inactive_opacity", {1.F}); m_pConfig->addConfigValue("decoration:fullscreen_opacity", {1.F}); diff --git a/src/render/Renderer.cpp b/src/render/Renderer.cpp index 57490d23..dae62851 100644 --- a/src/render/Renderer.cpp +++ b/src/render/Renderer.cpp @@ -850,12 +850,21 @@ void CHyprRenderer::renderIMEPopup(CInputPopup* pPopup, PHLMONITOR pMonitor, tim const auto SURF = pPopup->getSurface(); - renderdata.blur = false; renderdata.surface = SURF; renderdata.decorate = false; renderdata.w = SURF->current.size.x; renderdata.h = SURF->current.size.y; + static auto PBLUR = CConfigValue("decoration:blur:enabled"); + static auto PBLURIMES = CConfigValue("decoration:blur:input_methods"); + static auto PBLURIGNOREA = CConfigValue("decoration:blur:input_methods_ignorealpha"); + + renderdata.blur = *PBLURIMES && *PBLUR; + if (renderdata.blur) { + g_pHyprOpenGL->m_RenderData.discardMode |= DISCARD_ALPHA; + g_pHyprOpenGL->m_RenderData.discardOpacity = *PBLURIGNOREA; + } + SURF->breadthfirst([](SP s, const Vector2D& offset, void* data) { renderSurface(s, offset.x, offset.y, data); }, &renderdata); } From 65f66dcf0d38533a383212ca440fdea0163be276 Mon Sep 17 00:00:00 2001 From: littleblack111 Date: Sat, 23 Nov 2024 22:32:13 +0800 Subject: [PATCH 0673/2181] binds: add option to allow fullscreening a pinned window (#8526) --- src/Compositor.cpp | 15 +++++++++++++-- src/config/ConfigDescriptions.hpp | 6 ++++++ src/config/ConfigManager.cpp | 1 + src/desktop/Window.hpp | 3 +++ 4 files changed, 23 insertions(+), 2 deletions(-) diff --git a/src/Compositor.cpp b/src/Compositor.cpp index 3fe5acec..53eaa467 100644 --- a/src/Compositor.cpp +++ b/src/Compositor.cpp @@ -2245,7 +2245,8 @@ void CCompositor::setWindowFullscreenClient(const PHLWINDOW PWINDOW, const eFull } void CCompositor::setWindowFullscreenState(const PHLWINDOW PWINDOW, sFullscreenState state) { - static auto PDIRECTSCANOUT = CConfigValue("render:direct_scanout"); + static auto PDIRECTSCANOUT = CConfigValue("render:direct_scanout"); + static auto PALLOWPINFULLSCREEN = CConfigValue("binds:allow_pin_fullscreen"); if (!validMapped(PWINDOW) || g_pCompositor->m_bUnsafeState) return; @@ -2259,7 +2260,17 @@ void CCompositor::setWindowFullscreenState(const PHLWINDOW PWINDOW, sFullscreenS const eFullscreenMode CURRENT_EFFECTIVE_MODE = (eFullscreenMode)std::bit_floor((uint8_t)PWINDOW->m_sFullscreenState.internal); const eFullscreenMode EFFECTIVE_MODE = (eFullscreenMode)std::bit_floor((uint8_t)state.internal); - const bool CHANGEINTERNAL = !(PWINDOW->m_bPinned || CURRENT_EFFECTIVE_MODE == EFFECTIVE_MODE || (PWORKSPACE->m_bHasFullscreenWindow && !PWINDOW->isFullscreen())); + if (*PALLOWPINFULLSCREEN && !PWINDOW->m_bPinFullscreened && !PWINDOW->isFullscreen() && PWINDOW->m_bPinned) { + PWINDOW->m_bPinned = false; + PWINDOW->m_bPinFullscreened = true; + } + + const bool CHANGEINTERNAL = !(PWINDOW->m_bPinned || CURRENT_EFFECTIVE_MODE == EFFECTIVE_MODE || (PWORKSPACE->m_bHasFullscreenWindow && !PWINDOW->isFullscreen())); + + if (*PALLOWPINFULLSCREEN && PWINDOW->m_bPinFullscreened && PWINDOW->isFullscreen() && !PWINDOW->m_bPinned && state.internal == FSMODE_NONE) { + PWINDOW->m_bPinned = true; + PWINDOW->m_bPinFullscreened = false; + } // TODO: update the state on syncFullscreen changes if (!CHANGEINTERNAL && PWINDOW->m_sWindowData.syncFullscreen.valueOrDefault()) diff --git a/src/config/ConfigDescriptions.hpp b/src/config/ConfigDescriptions.hpp index 45379140..bb3d4e0e 100644 --- a/src/config/ConfigDescriptions.hpp +++ b/src/config/ConfigDescriptions.hpp @@ -1206,6 +1206,12 @@ inline static const std::vector CONFIG_OPTIONS = { .type = CONFIG_OPTION_BOOL, .data = SConfigOptionDescription::SBoolData{true}, }, + SConfigOptionDescription{ + .value = "binds:allow_pin_fullscreen", + .description = "Allows fullscreen to pinned windows, and restore their pinned status afterwards", + .type = CONFIG_OPTION_BOOL, + .data = SConfigOptionDescription::SBoolData{true}, + }, /* * xwayland: diff --git a/src/config/ConfigManager.cpp b/src/config/ConfigManager.cpp index 32f64f0a..3429db24 100644 --- a/src/config/ConfigManager.cpp +++ b/src/config/ConfigManager.cpp @@ -536,6 +536,7 @@ CConfigManager::CConfigManager() { m_pConfig->addConfigValue("binds:movefocus_cycles_fullscreen", Hyprlang::INT{1}); m_pConfig->addConfigValue("binds:disable_keybind_grabbing", Hyprlang::INT{0}); m_pConfig->addConfigValue("binds:window_direction_monitor_fallback", Hyprlang::INT{1}); + m_pConfig->addConfigValue("binds:allow_pin_fullscreen", Hyprlang::INT{0}); m_pConfig->addConfigValue("gestures:workspace_swipe", Hyprlang::INT{0}); m_pConfig->addConfigValue("gestures:workspace_swipe_fingers", Hyprlang::INT{3}); diff --git a/src/desktop/Window.hpp b/src/desktop/Window.hpp index ac81e5ef..5dd59437 100644 --- a/src/desktop/Window.hpp +++ b/src/desktop/Window.hpp @@ -332,6 +332,9 @@ class CWindow { // For pinned (sticky) windows bool m_bPinned = false; + // For preserving pinned state when fullscreening a pinned window + bool m_bPinFullscreened = false; + // urgency hint bool m_bIsUrgent = false; From 54f57797e9d025db72777ccf4adb0ddb25125016 Mon Sep 17 00:00:00 2001 From: Mike Will Date: Sat, 23 Nov 2024 09:36:28 -0500 Subject: [PATCH 0674/2181] snap: account for position of multiple monitors (#8543) --- src/layout/IHyprLayout.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/layout/IHyprLayout.cpp b/src/layout/IHyprLayout.cpp index 22e1d947..8ff55d10 100644 --- a/src/layout/IHyprLayout.cpp +++ b/src/layout/IHyprLayout.cpp @@ -484,8 +484,8 @@ static void performSnap(Vector2D& sourcePos, Vector2D& sourceSize, PHLWINDOW DRA const double BORDERDIFF = DRAGGINGBORDERSIZE - BORDERSIZE; const auto MON = DRAGGINGWINDOW->m_pMonitor.lock(); - SRange monX = {MON->vecPosition.x + BORDERSIZE, MON->vecSize.x - BORDERSIZE}; - SRange monY = {MON->vecPosition.y + BORDERSIZE, MON->vecSize.y - BORDERSIZE}; + SRange monX = {MON->vecPosition.x + BORDERSIZE, MON->vecPosition.x + MON->vecSize.x - BORDERSIZE}; + SRange monY = {MON->vecPosition.y + BORDERSIZE, MON->vecPosition.y + MON->vecSize.y - BORDERSIZE}; if (canSnap(sourceX.start, monX.start, GAPSIZE) || canSnap(sourceX.start, (monX.start += MON->vecReservedTopLeft.x + BORDERDIFF), GAPSIZE)) { SNAP(sourceX.start, sourceX.end, monX.start); From 55ec8bd512605a014cc322d3419a9cfa72178340 Mon Sep 17 00:00:00 2001 From: Vaxry Date: Sun, 24 Nov 2024 02:46:24 +0000 Subject: [PATCH 0675/2181] config: throw an error explicitly when parsing colors in gradients ref #8552 --- src/config/ConfigManager.cpp | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/config/ConfigManager.cpp b/src/config/ConfigManager.cpp index 3429db24..ba0fdd9d 100644 --- a/src/config/ConfigManager.cpp +++ b/src/config/ConfigManager.cpp @@ -67,7 +67,10 @@ static Hyprlang::CParseResult configHandleGradientSet(const char* VALUE, void** } try { - DATA->m_vColors.push_back(CColor(*configStringToInt(var))); + const auto COL = configStringToInt(var); + if (!COL) + throw std::runtime_error(std::format("failed to parse {} as a color", var)); + DATA->m_vColors.push_back(CColor(COL.value())); } catch (std::exception& e) { Debug::log(WARN, "Error parsing gradient {}", V); parseError = "Error parsing gradient " + V + ": " + e.what(); From cc38e7e18fd762d5cdb34d06335223b7d7874106 Mon Sep 17 00:00:00 2001 From: Vaxry Date: Sun, 24 Nov 2024 14:53:36 +0000 Subject: [PATCH 0676/2181] config: don't overwrite errors in gradients --- src/config/ConfigManager.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/config/ConfigManager.cpp b/src/config/ConfigManager.cpp index ba0fdd9d..c0f212cf 100644 --- a/src/config/ConfigManager.cpp +++ b/src/config/ConfigManager.cpp @@ -79,7 +79,8 @@ static Hyprlang::CParseResult configHandleGradientSet(const char* VALUE, void** if (DATA->m_vColors.size() == 0) { Debug::log(WARN, "Error parsing gradient {}", V); - parseError = "Error parsing gradient " + V + ": No colors?"; + if (parseError.empty()) + parseError = "Error parsing gradient " + V + ": No colors?"; DATA->m_vColors.push_back(0); // transparent } From 1930a95000d336b76d18c0c95ef77e138c9a4cd0 Mon Sep 17 00:00:00 2001 From: Nabil Otsmane <44232317+nabil-otsmane@users.noreply.github.com> Date: Mon, 25 Nov 2024 01:50:35 +0100 Subject: [PATCH 0677/2181] shm: fix shm fd size check before creating or resizing shm_pool (#8572) * protocols: fix shm fd size check before creating or resizing shm_pool * added static to function --- src/protocols/core/Shm.cpp | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/src/protocols/core/Shm.cpp b/src/protocols/core/Shm.cpp index a8c98bb0..708d41c3 100644 --- a/src/protocols/core/Shm.cpp +++ b/src/protocols/core/Shm.cpp @@ -1,6 +1,7 @@ #include "Shm.hpp" #include #include +#include #include #include "../../render/Texture.hpp" #include "../types/WLBuffer.hpp" @@ -99,10 +100,25 @@ void CSHMPool::resize(size_t size_) { LOGM(ERR, "Couldn't mmap {} bytes from fd {} of shm client", size, fd); } +static int shmIsSizeValid(int fd, size_t size) { + struct stat st; + if (fstat(fd, &st) == -1) { + LOGM(ERR, "Couldn't get stat for fd {} of shm client", fd); + return 0; + } + + return (size_t)st.st_size >= size; +} + CWLSHMPoolResource::CWLSHMPoolResource(SP resource_, int fd_, size_t size_) : resource(resource_) { if (!good()) return; + if (!shmIsSizeValid(fd_, size_)) { + resource_->error(-1, "The size of the file is not big enough for the shm pool"); + return; + } + pool = makeShared(fd_, size_); resource->setDestroy([this](CWlShmPool* r) { PROTO::shm->destroyResource(this); }); @@ -113,6 +129,11 @@ CWLSHMPoolResource::CWLSHMPoolResource(SP resource_, int fd_, size_t r->error(-1, "Shrinking a shm pool is illegal"); return; } + if (!shmIsSizeValid(pool->fd, size_)) { + r->error(-1, "The size of the file is not big enough for the shm pool"); + return; + } + pool->resize(size_); }); From 0ddb952d7a3d102e160eea93c68f0d366186cf73 Mon Sep 17 00:00:00 2001 From: Vladimir-csp <4061903+Vladimir-csp@users.noreply.github.com> Date: Mon, 25 Nov 2024 17:18:50 +0300 Subject: [PATCH 0678/2181] hyprland-uwsm.desktop: Just reference plain entry (#8553) --- systemd/hyprland-uwsm.desktop | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/systemd/hyprland-uwsm.desktop b/systemd/hyprland-uwsm.desktop index 2ed1031b..e00f4aa2 100644 --- a/systemd/hyprland-uwsm.desktop +++ b/systemd/hyprland-uwsm.desktop @@ -1,6 +1,6 @@ [Desktop Entry] Name=Hyprland (uwsm-managed) Comment=An intelligent dynamic tiling Wayland compositor -Exec=uwsm start -N Hyprland -D Hyprland -C An_intelligent_dynamic_tiling_Wayland_compositor -- Hyprland +Exec=uwsm start -- hyprland.desktop DesktopNames=Hyprland Type=Application From 268778823676ef2bbda42050d78946e1fc27fc31 Mon Sep 17 00:00:00 2001 From: Vaxry Date: Mon, 25 Nov 2024 14:42:06 +0000 Subject: [PATCH 0679/2181] hyprctl: verify runtime dir exists in instances() ref #8579 --- hyprctl/main.cpp | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/hyprctl/main.cpp b/hyprctl/main.cpp index 1f7f8d74..4ee2d598 100644 --- a/hyprctl/main.cpp +++ b/hyprctl/main.cpp @@ -66,6 +66,11 @@ std::string getRuntimeDir() { std::vector instances() { std::vector result; + try { + if (!std::filesystem::exists(getRuntimeDir())) + return {}; + } catch (std::exception& e) { return {}; } + for (const auto& el : std::filesystem::directory_iterator(getRuntimeDir())) { if (!el.is_directory() || !std::filesystem::exists(el.path().string() + "/hyprland.lock")) continue; From 1fb720b62aeb474873ba43426ddc53afde1e6cdd Mon Sep 17 00:00:00 2001 From: Ikalco <73481042+ikalco@users.noreply.github.com> Date: Tue, 26 Nov 2024 07:52:43 -0600 Subject: [PATCH 0680/2181] seat: fix double scrolling in some applications (#8583) --- src/managers/SeatManager.cpp | 6 ++++-- src/protocols/core/Seat.cpp | 4 ++++ src/protocols/core/Seat.hpp | 1 + 3 files changed, 9 insertions(+), 2 deletions(-) diff --git a/src/managers/SeatManager.cpp b/src/managers/SeatManager.cpp index b40d6cad..665805f6 100644 --- a/src/managers/SeatManager.cpp +++ b/src/managers/SeatManager.cpp @@ -332,8 +332,10 @@ void CSeatManager::sendPointerAxis(uint32_t timeMs, wl_pointer_axis axis, double p->sendAxisRelativeDirection(axis, relative); if (source == 0) { - p->sendAxisValue120(axis, value120); - p->sendAxisDiscrete(axis, discrete); + if (p->version() >= 8) + p->sendAxisValue120(axis, value120); + else + p->sendAxisDiscrete(axis, discrete); } else if (value == 0) p->sendAxisStop(timeMs, axis); } diff --git a/src/protocols/core/Seat.cpp b/src/protocols/core/Seat.cpp index d95e0e12..7c31b67c 100644 --- a/src/protocols/core/Seat.cpp +++ b/src/protocols/core/Seat.cpp @@ -136,6 +136,10 @@ CWLPointerResource::CWLPointerResource(SP resource_, SPstate.pointerFocus.lock(), {-1, -1} /* Coords don't really matter that much, they will be updated next move */); } +int CWLPointerResource::version() { + return resource->version(); +} + bool CWLPointerResource::good() { return resource->resource(); } diff --git a/src/protocols/core/Seat.hpp b/src/protocols/core/Seat.hpp index 1b43dd04..b5670237 100644 --- a/src/protocols/core/Seat.hpp +++ b/src/protocols/core/Seat.hpp @@ -73,6 +73,7 @@ class CWLPointerResource { CWLPointerResource(SP resource_, SP owner_); bool good(); + int version(); void sendEnter(SP surface, const Vector2D& local); void sendLeave(); void sendMotion(uint32_t timeMs, const Vector2D& local); From e9a7fb8f91d23f1ac2671e55f74234dcec2ee1c6 Mon Sep 17 00:00:00 2001 From: Agent00Ming <107314235+Agent00Ming@users.noreply.github.com> Date: Wed, 27 Nov 2024 09:17:45 -0500 Subject: [PATCH 0681/2181] renderer: fix incorrect early return (#8590) Co-authored-by: Agent_00Ming --- src/render/Renderer.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/render/Renderer.cpp b/src/render/Renderer.cpp index dae62851..ca6ceba1 100644 --- a/src/render/Renderer.cpp +++ b/src/render/Renderer.cpp @@ -331,7 +331,7 @@ bool CHyprRenderer::shouldRenderWindow(PHLWINDOW pWindow, PHLMONITOR pMonitor) { if (pWindow->m_pMonitor == pMonitor) return true; - if (!(!pWindow->m_pWorkspace || !pWindow->m_pWorkspace->isVisible()) && pWindow->m_pMonitor != pMonitor) + if ((!pWindow->m_pWorkspace || !pWindow->m_pWorkspace->isVisible()) && pWindow->m_pMonitor != pMonitor) return false; // if not, check if it maybe is active on a different monitor. From 5329298b522e3cc1201894909443775b00aeb336 Mon Sep 17 00:00:00 2001 From: Andre Toerien Date: Wed, 27 Nov 2024 21:59:00 +0200 Subject: [PATCH 0682/2181] sessionLock: don't send motion events on every surface commit (#8584) --- src/managers/SessionLockManager.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/managers/SessionLockManager.cpp b/src/managers/SessionLockManager.cpp index c7a5934a..b7110990 100644 --- a/src/managers/SessionLockManager.cpp +++ b/src/managers/SessionLockManager.cpp @@ -31,7 +31,7 @@ SSessionLockSurface::SSessionLockSurface(SP surface_) : sur listeners.commit = surface_->events.commit.registerListener([this](std::any data) { const auto PMONITOR = g_pCompositor->getMonitorFromID(iMonitorID); - if (mapped && pWlrSurface != g_pCompositor->m_pLastFocus) + if (mapped && !g_pCompositor->m_pLastFocus) g_pInputManager->simulateMouseMovement(); if (PMONITOR) From 8b51eeb7aef8b25de35a0d460f28f4d67c017866 Mon Sep 17 00:00:00 2001 From: Vaxry Date: Thu, 28 Nov 2024 14:31:38 +0000 Subject: [PATCH 0683/2181] core: fix compilation outside stdlibc++ fixes #8603 --- src/managers/KeybindManager.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/managers/KeybindManager.cpp b/src/managers/KeybindManager.cpp index a5327149..7f10249a 100644 --- a/src/managers/KeybindManager.cpp +++ b/src/managers/KeybindManager.cpp @@ -2988,13 +2988,13 @@ SDispatchResult CKeybindManager::setProp(std::string args) { else configStringToInt(TOKEN).and_then([&colorData](const auto& e) { colorData.m_vColors.push_back(e); - return std::result_of::type(1); + return std::invoke_result_t(1); }); } } else if (VAL != "-1") configStringToInt(VAL).and_then([&colorData](const auto& e) { colorData.m_vColors.push_back(e); - return std::result_of::type(1); + return std::invoke_result_t(1); }); if (PROP == "activebordercolor") From 5963970be54c92fdebdbcebdeb76cf6de5e7e717 Mon Sep 17 00:00:00 2001 From: nyx Date: Thu, 28 Nov 2024 10:25:24 -0500 Subject: [PATCH 0684/2181] descriptions: change allow_pin_fullscreen value to false (#8592) --- src/config/ConfigDescriptions.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/config/ConfigDescriptions.hpp b/src/config/ConfigDescriptions.hpp index bb3d4e0e..e5918691 100644 --- a/src/config/ConfigDescriptions.hpp +++ b/src/config/ConfigDescriptions.hpp @@ -1210,7 +1210,7 @@ inline static const std::vector CONFIG_OPTIONS = { .value = "binds:allow_pin_fullscreen", .description = "Allows fullscreen to pinned windows, and restore their pinned status afterwards", .type = CONFIG_OPTION_BOOL, - .data = SConfigOptionDescription::SBoolData{true}, + .data = SConfigOptionDescription::SBoolData{false}, }, /* From 22bf2853e6271932f073961f3dbeb0f9ff48493e Mon Sep 17 00:00:00 2001 From: Daringcuteseal Date: Thu, 28 Nov 2024 21:21:55 +0700 Subject: [PATCH 0685/2181] hyprpm: fix incomplete unmet dependencies message --- hyprpm/src/core/PluginManager.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/hyprpm/src/core/PluginManager.cpp b/hyprpm/src/core/PluginManager.cpp index fb3065b4..db3893b5 100644 --- a/hyprpm/src/core/PluginManager.cpp +++ b/hyprpm/src/core/PluginManager.cpp @@ -115,7 +115,7 @@ bool CPluginManager::addNewPluginRepo(const std::string& url, const std::string& const auto HLVER = getHyprlandVersion(); if (!hasDeps()) { - std::println(stderr, "\n{}", failureString("Could not clone the plugin repository. Dependencies not satisfied. Hyprpm requires: cmake, meson, cpio")); + std::println(stderr, "\n{}", failureString("Could not clone the plugin repository. Dependencies not satisfied. Hyprpm requires: cmake, meson, cpio, pkg-config")); return false; } @@ -421,7 +421,7 @@ bool CPluginManager::updateHeaders(bool force) { const auto HLVER = getHyprlandVersion(); if (!hasDeps()) { - std::println("\n{}", failureString("Could not update. Dependencies not satisfied. Hyprpm requires: cmake, meson, cpio")); + std::println("\n{}", failureString("Could not update. Dependencies not satisfied. Hyprpm requires: cmake, meson, cpio, pkg-config")); return false; } From 8f83d29f00bfa89d1e8fe94b4dda98fe898b6b0e Mon Sep 17 00:00:00 2001 From: Vaxry Date: Thu, 28 Nov 2024 23:51:53 +0000 Subject: [PATCH 0686/2181] renderer: restore discard mode after IME render pass ref #8555 --- src/render/Renderer.cpp | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/src/render/Renderer.cpp b/src/render/Renderer.cpp index ca6ceba1..bba133d9 100644 --- a/src/render/Renderer.cpp +++ b/src/render/Renderer.cpp @@ -859,6 +859,10 @@ void CHyprRenderer::renderIMEPopup(CInputPopup* pPopup, PHLMONITOR pMonitor, tim static auto PBLURIMES = CConfigValue("decoration:blur:input_methods"); static auto PBLURIGNOREA = CConfigValue("decoration:blur:input_methods_ignorealpha"); + // TODO: make push/pop methods for this. + const auto DM = g_pHyprOpenGL->m_RenderData.discardMode; + const auto DA = g_pHyprOpenGL->m_RenderData.discardOpacity; + renderdata.blur = *PBLURIMES && *PBLUR; if (renderdata.blur) { g_pHyprOpenGL->m_RenderData.discardMode |= DISCARD_ALPHA; @@ -866,6 +870,9 @@ void CHyprRenderer::renderIMEPopup(CInputPopup* pPopup, PHLMONITOR pMonitor, tim } SURF->breadthfirst([](SP s, const Vector2D& offset, void* data) { renderSurface(s, offset.x, offset.y, data); }, &renderdata); + + g_pHyprOpenGL->m_RenderData.discardMode = DM; + g_pHyprOpenGL->m_RenderData.discardOpacity = DA; } void CHyprRenderer::renderSessionLockSurface(SSessionLockSurface* pSurface, PHLMONITOR pMonitor, timespec* time) { From ef6b0c81c914bdc9b56c2674273698f065518993 Mon Sep 17 00:00:00 2001 From: littleblack111 Date: Sun, 1 Dec 2024 00:40:23 +0800 Subject: [PATCH 0687/2181] cleanup: remove leftover var in ThreadManager.cpp (#8611) --- src/managers/ThreadManager.cpp | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/src/managers/ThreadManager.cpp b/src/managers/ThreadManager.cpp index 6f8e0c9a..8666b3a6 100644 --- a/src/managers/ThreadManager.cpp +++ b/src/managers/ThreadManager.cpp @@ -3,8 +3,6 @@ #include "../Compositor.hpp" #include "../config/ConfigValue.hpp" -int slowUpdate = 0; - int handleTimer(void* data) { const auto PTM = (CThreadManager*)data; @@ -27,4 +25,4 @@ CThreadManager::CThreadManager() { CThreadManager::~CThreadManager() { if (m_esConfigTimer) wl_event_source_remove(m_esConfigTimer); -} \ No newline at end of file +} From d26439a0fe5594fb26d5a3c01571f9490a9a2d2c Mon Sep 17 00:00:00 2001 From: Vaxry Date: Sat, 30 Nov 2024 17:42:40 +0000 Subject: [PATCH 0688/2181] nix: update flake --- flake.lock | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/flake.lock b/flake.lock index 969bc157..0db2ee60 100644 --- a/flake.lock +++ b/flake.lock @@ -16,11 +16,11 @@ ] }, "locked": { - "lastModified": 1731774881, - "narHash": "sha256-1Dxryiw8u2ejntxrrv3sMtIE8WHKxmlN4KeH+uMGbmc=", + "lastModified": 1731959031, + "narHash": "sha256-TGcvIjftziC1CjuiHCzrYDwmOoSFYIhdiKmLetzB5L0=", "owner": "hyprwm", "repo": "aquamarine", - "rev": "b31a6a4da8199ae3489057db7d36069a70749a56", + "rev": "4468981c1c50999f315baa1508f0e53c4ee70c52", "type": "github" }, "original": { @@ -151,11 +151,11 @@ ] }, "locked": { - "lastModified": 1731702627, - "narHash": "sha256-+JeO9gevnXannQxMfR5xzZtF4sYmSlWkX/BPmPx0mWk=", + "lastModified": 1732288281, + "narHash": "sha256-XTU9B53IjGeJiJ7LstOhuxcRjCOFkQFl01H78sT9Lg4=", "owner": "hyprwm", "repo": "hyprutils", - "rev": "e911361a687753bbbdfe3b6a9eab755ecaf1d9e1", + "rev": "b26f33cc1c8a7fd5076e19e2cce3f062dca6351c", "type": "github" }, "original": { @@ -189,11 +189,11 @@ }, "nixpkgs": { "locked": { - "lastModified": 1731676054, - "narHash": "sha256-OZiZ3m8SCMfh3B6bfGC/Bm4x3qc1m2SVEAlkV6iY7Yg=", + "lastModified": 1732758367, + "narHash": "sha256-RzaI1RO0UXqLjydtz3GAXSTzHkpb/lLD1JD8a0W4Wpo=", "owner": "NixOS", "repo": "nixpkgs", - "rev": "5e4fbfb6b3de1aa2872b76d49fafc942626e2add", + "rev": "fa42b5a5f401aab8a32bd33c9a4de0738180dc59", "type": "github" }, "original": { @@ -229,11 +229,11 @@ "nixpkgs-stable": "nixpkgs-stable" }, "locked": { - "lastModified": 1731363552, - "narHash": "sha256-vFta1uHnD29VUY4HJOO/D6p6rxyObnf+InnSMT4jlMU=", + "lastModified": 1732021966, + "narHash": "sha256-mnTbjpdqF0luOkou8ZFi2asa1N3AA2CchR/RqCNmsGE=", "owner": "cachix", "repo": "git-hooks.nix", - "rev": "cd1af27aa85026ac759d5d3fccf650abe7e1bbf0", + "rev": "3308484d1a443fc5bc92012435d79e80458fe43c", "type": "github" }, "original": { From 6d7544458d0fafcae410c1978a0cabce2fb4a346 Mon Sep 17 00:00:00 2001 From: Ikalco <73481042+ikalco@users.noreply.github.com> Date: Sun, 1 Dec 2024 11:14:35 -0600 Subject: [PATCH 0689/2181] cleanup: use doLater instead of adding idle event handlers (#8624) --- src/protocols/Tablet.cpp | 26 ++++++++++++-------------- src/protocols/Tablet.hpp | 7 +++---- src/protocols/XDGShell.cpp | 18 +++++++++--------- src/protocols/XDGShell.hpp | 8 ++++---- src/xwayland/Server.cpp | 12 ++++-------- 5 files changed, 32 insertions(+), 39 deletions(-) diff --git a/src/protocols/Tablet.cpp b/src/protocols/Tablet.cpp index d7f741b9..7768402b 100644 --- a/src/protocols/Tablet.cpp +++ b/src/protocols/Tablet.cpp @@ -2,6 +2,7 @@ #include "../devices/Tablet.hpp" #include "../Compositor.hpp" #include "../managers/SeatManager.hpp" +#include "../managers/eventLoop/EventLoopManager.hpp" #include "core/Seat.hpp" #include "core/Compositor.hpp" #include @@ -162,11 +163,6 @@ CTabletToolV2Resource::CTabletToolV2Resource(SP resource_, SP< }); } -CTabletToolV2Resource::~CTabletToolV2Resource() { - if (frameSource) - wl_event_source_remove(frameSource); -} - bool CTabletToolV2Resource::good() { return resource->resource(); } @@ -205,20 +201,22 @@ void CTabletToolV2Resource::sendData() { } void CTabletToolV2Resource::queueFrame() { - if (frameSource) + if (frameQueued) return; - frameSource = wl_event_loop_add_idle(g_pCompositor->m_sWLEventLoop, [](void* data) { ((CTabletToolV2Resource*)data)->sendFrame(false); }, this); + frameQueued = true; + g_pEventLoopManager->doLater([this]() { + if (!frameQueued || tool.expired() || inert) + return; + + sendFrame(); + }); } -void CTabletToolV2Resource::sendFrame(bool removeSource) { - if (frameSource) { - if (removeSource) - wl_event_source_remove(frameSource); - frameSource = nullptr; - } +void CTabletToolV2Resource::sendFrame() { + frameQueued = false; - if (!current) + if (!current || !resource) return; timespec now; diff --git a/src/protocols/Tablet.hpp b/src/protocols/Tablet.hpp index 1ebcb1e5..8c99bee0 100644 --- a/src/protocols/Tablet.hpp +++ b/src/protocols/Tablet.hpp @@ -112,21 +112,20 @@ class CTabletV2Resource { class CTabletToolV2Resource { public: CTabletToolV2Resource(SP resource_, SP tool_, SP seat_); - ~CTabletToolV2Resource(); bool good(); void sendData(); void queueFrame(); - void sendFrame(bool removeSource = true); + void sendFrame(); bool current = false; WP lastSurf; WP tool; WP seat; - wl_event_source* frameSource = nullptr; - bool inert = false; // removed was sent + bool frameQueued = false; + bool inert = false; // removed was sent private: SP resource; diff --git a/src/protocols/XDGShell.cpp b/src/protocols/XDGShell.cpp index 688d0006..a542c394 100644 --- a/src/protocols/XDGShell.cpp +++ b/src/protocols/XDGShell.cpp @@ -3,6 +3,7 @@ #include #include "../Compositor.hpp" #include "../managers/SeatManager.hpp" +#include "../managers/eventLoop/EventLoopManager.hpp" #include "core/Seat.hpp" #include "core/Compositor.hpp" #include @@ -469,8 +470,6 @@ CXDGSurfaceResource::CXDGSurfaceResource(SP resource_, SPresetRole(); } @@ -484,22 +483,23 @@ SP CXDGSurfaceResource::fromResource(wl_resource* res) { return data ? data->self.lock() : nullptr; } -static void onConfigure(void* data) { - ((CXDGSurfaceResource*)data)->configure(); -} - uint32_t CXDGSurfaceResource::scheduleConfigure() { - if (configureSource) + if (configureScheduled) return scheduledSerial; - configureSource = wl_event_loop_add_idle(g_pCompositor->m_sWLEventLoop, onConfigure, this); scheduledSerial = wl_display_next_serial(g_pCompositor->m_sWLDisplay); + configureScheduled = true; + g_pEventLoopManager->doLater([this]() { configure(); }); + return scheduledSerial; } void CXDGSurfaceResource::configure() { - configureSource = nullptr; + if (!resource) + return; + + configureScheduled = false; resource->sendConfigure(scheduledSerial); } diff --git a/src/protocols/XDGShell.hpp b/src/protocols/XDGShell.hpp index ef847f3b..3b7d2d11 100644 --- a/src/protocols/XDGShell.hpp +++ b/src/protocols/XDGShell.hpp @@ -199,12 +199,12 @@ class CXDGSurfaceResource { void configure(); private: - SP resource; + SP resource; - uint32_t lastConfigureSerial = 0; - uint32_t scheduledSerial = 0; + uint32_t lastConfigureSerial = 0; + uint32_t scheduledSerial = 0; - wl_event_source* configureSource = nullptr; + bool configureScheduled = false; // std::vector> popups; diff --git a/src/xwayland/Server.cpp b/src/xwayland/Server.cpp index f356af18..390ce1f6 100644 --- a/src/xwayland/Server.cpp +++ b/src/xwayland/Server.cpp @@ -176,11 +176,6 @@ static bool openSockets(std::array& sockets, int display) { return true; } -static void startServer(void* data) { - if (!g_pXWayland->pServer->start()) - Debug::log(ERR, "The XWayland server could not start! XWayland will not work..."); -} - static int xwaylandReady(int fd, uint32_t mask, void* data) { return g_pXWayland->pServer->ready(fd, mask); } @@ -308,9 +303,10 @@ bool CXWaylandServer::create() { setenv("DISPLAY", displayName.c_str(), true); - // TODO: lazy mode - - idleSource = wl_event_loop_add_idle(g_pCompositor->m_sWLEventLoop, ::startServer, nullptr); + g_pEventLoopManager->doLater([this]() { + if (!start()) + Debug::log(ERR, "The XWayland server could not start! XWayland will not work..."); + }); return true; } From 10a9fec7fc8e77479a599985c776a8a184311cd6 Mon Sep 17 00:00:00 2001 From: UjinT34 <41110182+UjinT34@users.noreply.github.com> Date: Mon, 2 Dec 2024 18:32:32 +0300 Subject: [PATCH 0690/2181] master: make center ignore reserved areas (#8625) --- src/config/ConfigDescriptions.hpp | 6 ++++++ src/config/ConfigManager.cpp | 1 + src/layout/MasterLayout.cpp | 13 +++++++------ 3 files changed, 14 insertions(+), 6 deletions(-) diff --git a/src/config/ConfigDescriptions.hpp b/src/config/ConfigDescriptions.hpp index e5918691..b95eeab1 100644 --- a/src/config/ConfigDescriptions.hpp +++ b/src/config/ConfigDescriptions.hpp @@ -1596,6 +1596,12 @@ inline static const std::vector CONFIG_OPTIONS = { .type = CONFIG_OPTION_BOOL, .data = SConfigOptionDescription::SBoolData{false}, }, + SConfigOptionDescription{ + .value = "master:center_ignores_reserved", + .description = "centers the master window on monitor ignoring reserved areas", + .type = CONFIG_OPTION_BOOL, + .data = SConfigOptionDescription::SBoolData{false}, + }, SConfigOptionDescription{ .value = "master:smart_resizing", .description = diff --git a/src/config/ConfigManager.cpp b/src/config/ConfigManager.cpp index c0f212cf..07de8c24 100644 --- a/src/config/ConfigManager.cpp +++ b/src/config/ConfigManager.cpp @@ -470,6 +470,7 @@ CConfigManager::CConfigManager() { m_pConfig->addConfigValue("master:mfact", {0.55f}); m_pConfig->addConfigValue("master:new_status", {"slave"}); m_pConfig->addConfigValue("master:always_center_master", Hyprlang::INT{0}); + m_pConfig->addConfigValue("master:center_ignores_reserved", Hyprlang::INT{0}); m_pConfig->addConfigValue("master:new_on_active", {"none"}); m_pConfig->addConfigValue("master:new_on_top", Hyprlang::INT{0}); m_pConfig->addConfigValue("master:orientation", {"left"}); diff --git a/src/layout/MasterLayout.cpp b/src/layout/MasterLayout.cpp index bf808627..4f761973 100644 --- a/src/layout/MasterLayout.cpp +++ b/src/layout/MasterLayout.cpp @@ -328,6 +328,7 @@ void CHyprMasterLayout::calculateWorkspace(PHLWORKSPACE pWorkspace) { eOrientation orientation = getDynamicOrientation(pWorkspace); bool centerMasterWindow = false; static auto ALWAYSCENTER = CConfigValue("master:always_center_master"); + static auto PIGNORERESERVED = CConfigValue("master:center_ignores_reserved"); static auto PSMARTRESIZING = CConfigValue("master:smart_resizing"); const auto MASTERS = getMastersOnWorkspace(pWorkspace->m_iID); @@ -402,7 +403,7 @@ void CHyprMasterLayout::calculateWorkspace(PHLWORKSPACE pWorkspace) { nextX += WIDTH; } } else { // orientation left, right or center - float WIDTH = WSSIZE.x; + float WIDTH = *PIGNORERESERVED && centerMasterWindow ? PMONITOR->vecSize.x : WSSIZE.x; float heightLeft = WSSIZE.y; int mastersLeft = MASTERS; float nextX = 0; @@ -414,7 +415,7 @@ void CHyprMasterLayout::calculateWorkspace(PHLWORKSPACE pWorkspace) { if (orientation == ORIENTATION_RIGHT) { nextX = WSSIZE.x - WIDTH; } else if (centerMasterWindow) { - nextX = (WSSIZE.x - WIDTH) / 2; + nextX = ((*PIGNORERESERVED && centerMasterWindow ? PMONITOR->vecSize.x : WSSIZE.x) - WIDTH) / 2; } for (auto& nd : m_lMasterNodesData) { @@ -431,7 +432,7 @@ void CHyprMasterLayout::calculateWorkspace(PHLWORKSPACE pWorkspace) { } nd.size = Vector2D(WIDTH, HEIGHT); - nd.position = WSPOS + Vector2D(nextX, nextY); + nd.position = (*PIGNORERESERVED && centerMasterWindow ? PMONITOR->vecPosition : WSPOS) + Vector2D(nextX, nextY); applyNodeDataToWindow(&nd); mastersLeft--; @@ -506,7 +507,7 @@ void CHyprMasterLayout::calculateWorkspace(PHLWORKSPACE pWorkspace) { nextY += HEIGHT; } } else { // slaves for centered master window(s) - const float WIDTH = (WSSIZE.x - PMASTERNODE->size.x) / 2.0; + const float WIDTH = ((*PIGNORERESERVED ? PMONITOR->vecSize.x : WSSIZE.x) - PMASTERNODE->size.x) / 2.0; float heightLeft = 0; float heightLeftL = WSSIZE.y; float heightLeftR = WSSIZE.y; @@ -543,7 +544,7 @@ void CHyprMasterLayout::calculateWorkspace(PHLWORKSPACE pWorkspace) { continue; if (onRight) { - nextX = WIDTH + PMASTERNODE->size.x; + nextX = WIDTH + PMASTERNODE->size.x - (*PIGNORERESERVED ? PMONITOR->vecReservedTopLeft.x : 0); nextY = nextYR; heightLeft = heightLeftR; slavesLeft = slavesLeftR; @@ -568,7 +569,7 @@ void CHyprMasterLayout::calculateWorkspace(PHLWORKSPACE pWorkspace) { } } - nd.size = Vector2D(WIDTH, HEIGHT); + nd.size = Vector2D(*PIGNORERESERVED ? (WIDTH - (onRight ? PMONITOR->vecReservedBottomRight.x : PMONITOR->vecReservedTopLeft.x)) : WIDTH, HEIGHT); nd.position = WSPOS + Vector2D(nextX, nextY); applyNodeDataToWindow(&nd); From 92186898c0ca1b3f72922b72c4af1723f0d9b888 Mon Sep 17 00:00:00 2001 From: Vaxry <43317083+vaxerski@users.noreply.github.com> Date: Mon, 2 Dec 2024 16:31:22 +0000 Subject: [PATCH 0691/2181] version: add link versions for other utils (#8619) --------- Co-authored-by: Mihai Fufezan --- CMakeLists.txt | 13 ++++++++----- hyprpm/CMakeLists.txt | 4 ++-- meson.build | 6 ++++++ src/debug/HyprCtl.cpp | 10 +++++++--- src/meson.build | 6 +++--- 5 files changed, 26 insertions(+), 13 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 1cbd8b0a..7e2a1fe6 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -104,8 +104,14 @@ find_package(OpenGL REQUIRED COMPONENTS ${GLES_VERSION}) pkg_check_modules(hyprctl_deps REQUIRED IMPORTED_TARGET hyprutils>=0.2.4) pkg_check_modules(aquamarine_dep REQUIRED IMPORTED_TARGET aquamarine>=0.4.5) +pkg_check_modules(hyprlang_dep REQUIRED IMPORTED_TARGET hyprlang>=0.3.2) +pkg_check_modules(hyprcursor_dep REQUIRED IMPORTED_TARGET hyprcursor>=0.1.7) +pkg_check_modules(hyprutils_dep REQUIRED IMPORTED_TARGET hyprutils>=0.2.3) add_compile_definitions(AQUAMARINE_VERSION="${aquamarine_dep_VERSION}") +add_compile_definitions(HYPRLANG_VERSION="${hyprlang_dep_VERSION}") +add_compile_definitions(HYPRUTILS_VERSION="${hyprutils_dep_VERSION}") +add_compile_definitions(HYPRCURSOR_VERSION="${hyprcursor_dep_VERSION}") pkg_check_modules( deps @@ -123,10 +129,7 @@ pkg_check_modules( libdrm libinput gbm - gio-2.0 - hyprlang>=0.3.2 - hyprcursor>=0.1.7 - hyprutils>=0.2.3) + gio-2.0) find_package(hyprwayland-scanner 0.3.10 REQUIRED) @@ -244,7 +247,7 @@ target_precompile_headers(Hyprland PRIVATE message(STATUS "Setting link libraries") -target_link_libraries(Hyprland rt PkgConfig::aquamarine_dep PkgConfig::deps) +target_link_libraries(Hyprland rt PkgConfig::aquamarine_dep PkgConfig::hyprlang_dep PkgConfig::hyprutils_dep PkgConfig::hyprcursor_dep PkgConfig::deps) if(udis_dep_FOUND) target_link_libraries(Hyprland PkgConfig::udis_dep) else() diff --git a/hyprpm/CMakeLists.txt b/hyprpm/CMakeLists.txt index 65935638..22cb8caa 100644 --- a/hyprpm/CMakeLists.txt +++ b/hyprpm/CMakeLists.txt @@ -9,11 +9,11 @@ file(GLOB_RECURSE SRCFILES CONFIGURE_DEPENDS "src/*.cpp") set(CMAKE_CXX_STANDARD 23) -pkg_check_modules(deps REQUIRED IMPORTED_TARGET tomlplusplus hyprutils>=0.2.4) +pkg_check_modules(hyprpm_deps REQUIRED IMPORTED_TARGET tomlplusplus hyprutils>=0.2.4) add_executable(hyprpm ${SRCFILES}) -target_link_libraries(hyprpm PUBLIC PkgConfig::deps) +target_link_libraries(hyprpm PUBLIC PkgConfig::hyprpm_deps) # binary install(TARGETS hyprpm) diff --git a/meson.build b/meson.build index d825f184..39a5a6d0 100644 --- a/meson.build +++ b/meson.build @@ -32,7 +32,13 @@ if cpp_compiler.check_header('execinfo.h') endif aquamarine = dependency('aquamarine', version: '>=0.4.5') +hyprcursor = dependency('hyprcursor', version: '>=0.1.7') +hyprlang = dependency('hyprlang', version: '>= 0.3.2') +hyprutils = dependency('hyprutils', version: '>= 0.2.3') add_project_arguments(['-DAQUAMARINE_VERSION="@0@"'.format(aquamarine.version())], language: 'cpp') +add_project_arguments(['-DHYPRCURSOR_VERSION="@0@"'.format(hyprcursor.version())], language: 'cpp') +add_project_arguments(['-DHYPRLANG_VERSION="@0@"'.format(hyprlang.version())], language: 'cpp') +add_project_arguments(['-DHYPRUTILS_VERSION="@0@"'.format(hyprutils.version())], language: 'cpp') xcb_dep = dependency('xcb', required: get_option('xwayland')) xcb_composite_dep = dependency('xcb-composite', required: get_option('xwayland')) diff --git a/src/debug/HyprCtl.cpp b/src/debug/HyprCtl.cpp index 11c16f0e..6b62ec8d 100644 --- a/src/debug/HyprCtl.cpp +++ b/src/debug/HyprCtl.cpp @@ -875,8 +875,9 @@ std::string versionRequest(eHyprCtlOutputFormat format, std::string request) { std::string result = std::format("Hyprland {} built from branch {} at commit {} {} ({}).\n" "Date: {}\n" "Tag: {}, commits: {}\n" - "built against aquamarine {}\n\n\n", - HYPRLAND_VERSION, GIT_BRANCH, GIT_COMMIT_HASH, GIT_DIRTY, commitMsg, GIT_COMMIT_DATE, GIT_TAG, GIT_COMMITS, AQUAMARINE_VERSION); + "built against:\n aquamarine {}\n hyprlang {}\n hyprutils {}\n hyprcursor {}\n\n\n", + HYPRLAND_VERSION, GIT_BRANCH, GIT_COMMIT_HASH, GIT_DIRTY, commitMsg, GIT_COMMIT_DATE, GIT_TAG, GIT_COMMITS, AQUAMARINE_VERSION, + HYPRLANG_VERSION, HYPRUTILS_VERSION, HYPRCURSOR_VERSION); #if (!defined(LEGACY_RENDERER) && !defined(ISDEBUG) && !defined(NO_XWAYLAND)) result += "no flags were set\n"; @@ -905,9 +906,12 @@ std::string versionRequest(eHyprCtlOutputFormat format, std::string request) { "tag": "{}", "commits": "{}", "buildAquamarine": "{}", + "buildHyprlang": "{}", + "buildHyprutils": "{}", + "buildHyprcursor": "{}", "flags": [)#", GIT_BRANCH, GIT_COMMIT_HASH, HYPRLAND_VERSION, (strcmp(GIT_DIRTY, "dirty") == 0 ? "true" : "false"), escapeJSONStrings(commitMsg), GIT_COMMIT_DATE, GIT_TAG, - GIT_COMMITS, AQUAMARINE_VERSION); + GIT_COMMITS, AQUAMARINE_VERSION, HYPRLANG_VERSION, HYPRUTILS_VERSION, HYPRCURSOR_VERSION); #ifdef LEGACY_RENDERER result += "\"legacyrenderer\","; diff --git a/src/meson.build b/src/meson.build index 2dbe2f44..61ca06d5 100644 --- a/src/meson.build +++ b/src/meson.build @@ -9,14 +9,14 @@ executable( dependencies: [ server_protos, aquamarine, + hyprcursor, + hyprlang, + hyprutils, dependency('gbm'), dependency('xcursor'), dependency('wayland-server'), dependency('wayland-client'), dependency('cairo'), - dependency('hyprcursor', version: '>=0.1.7'), - dependency('hyprlang', version: '>= 0.3.2'), - dependency('hyprutils', version: '>= 0.2.3'), dependency('libdrm'), dependency('egl'), dependency('xkbcommon'), From 320144ae7288fe23686935ebb235d9fe0c900862 Mon Sep 17 00:00:00 2001 From: Vaxry <43317083+vaxerski@users.noreply.github.com> Date: Tue, 3 Dec 2024 18:58:24 +0000 Subject: [PATCH 0692/2181] core: move colorspace handling to oklab (#8635) * Meson: add hyprgraphics * Nix: add hyprgraphics * CI/setup_base: get hyprgraphics-git --------- Co-authored-by: Mihai Fufezan --- .github/actions/setup_base/action.yml | 7 + CMakeLists.txt | 4 +- flake.lock | 27 +++ flake.nix | 7 + meson.build | 2 + nix/default.nix | 2 + nix/overlays.nix | 1 + src/Compositor.cpp | 10 +- src/config/ConfigDataValues.hpp | 22 ++- src/config/ConfigManager.cpp | 23 +-- src/config/ConfigManager.hpp | 2 +- src/debug/HyprCtl.cpp | 15 +- src/debug/HyprNotificationOverlay.cpp | 4 +- src/debug/HyprNotificationOverlay.hpp | 18 +- src/desktop/Window.cpp | 4 +- src/desktop/Window.hpp | 2 +- src/helpers/AnimatedVariable.hpp | 4 +- src/helpers/Color.cpp | 56 +++++-- src/helpers/Color.hpp | 48 ++++-- src/hyprerror/HyprError.cpp | 6 +- src/hyprerror/HyprError.hpp | 4 +- src/managers/AnimationManager.cpp | 55 +++++- src/managers/AnimationManager.hpp | 4 +- src/managers/KeybindManager.cpp | 2 +- src/managers/PointerManager.cpp | 2 +- src/meson.build | 1 + src/plugins/PluginAPI.cpp | 4 +- src/plugins/PluginAPI.hpp | 4 +- src/protocols/SinglePixel.cpp | 8 +- src/protocols/SinglePixel.hpp | 4 +- src/protocols/ToplevelExport.cpp | 4 +- src/render/OpenGL.cpp | 157 +++++++++++++++--- src/render/OpenGL.hpp | 13 +- src/render/Renderer.cpp | 20 +-- src/render/Shader.hpp | 10 +- .../decorations/CHyprBorderDecoration.cpp | 11 +- .../decorations/CHyprDropShadowDecoration.cpp | 10 +- .../decorations/CHyprDropShadowDecoration.hpp | 2 +- .../decorations/CHyprGroupBarDecoration.cpp | 24 +-- src/render/shaders/Border.hpp | 62 ++++++- 40 files changed, 492 insertions(+), 173 deletions(-) diff --git a/.github/actions/setup_base/action.yml b/.github/actions/setup_base/action.yml index 26660ce6..e22f514e 100644 --- a/.github/actions/setup_base/action.yml +++ b/.github/actions/setup_base/action.yml @@ -33,7 +33,9 @@ runs: libfontenc \ libglvnd \ libinput \ + libjxl \ libliftoff \ + libwebp \ libxcursor \ libxcvt \ libxfont2 \ @@ -69,6 +71,11 @@ runs: cmake --build ./build --config Release --target all -j`nproc 2>/dev/null || getconf NPROCESSORS_CONF` cmake --install build + - name: Get hyprgraphics-git + shell: bash + run: | + git clone https://github.com/hyprwm/hyprgraphics && cd hyprgraphics && cmake -DCMAKE_BUILD_TYPE:STRING=Release -DCMAKE_INSTALL_PREFIX:PATH=/usr -B build && cmake --build build --target hyprgraphics && cmake --install build + - name: Get hyprutils-git shell: bash run: | diff --git a/CMakeLists.txt b/CMakeLists.txt index 7e2a1fe6..aa0d4b03 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -107,11 +107,13 @@ pkg_check_modules(aquamarine_dep REQUIRED IMPORTED_TARGET aquamarine>=0.4.5) pkg_check_modules(hyprlang_dep REQUIRED IMPORTED_TARGET hyprlang>=0.3.2) pkg_check_modules(hyprcursor_dep REQUIRED IMPORTED_TARGET hyprcursor>=0.1.7) pkg_check_modules(hyprutils_dep REQUIRED IMPORTED_TARGET hyprutils>=0.2.3) +pkg_check_modules(hyprgraphics_dep REQUIRED IMPORTED_TARGET hyprgraphics>=0.1.1) add_compile_definitions(AQUAMARINE_VERSION="${aquamarine_dep_VERSION}") add_compile_definitions(HYPRLANG_VERSION="${hyprlang_dep_VERSION}") add_compile_definitions(HYPRUTILS_VERSION="${hyprutils_dep_VERSION}") add_compile_definitions(HYPRCURSOR_VERSION="${hyprcursor_dep_VERSION}") +add_compile_definitions(HYPRGRAPHICS_VERSION="${hyprgraphics_dep_VERSION}") pkg_check_modules( deps @@ -247,7 +249,7 @@ target_precompile_headers(Hyprland PRIVATE message(STATUS "Setting link libraries") -target_link_libraries(Hyprland rt PkgConfig::aquamarine_dep PkgConfig::hyprlang_dep PkgConfig::hyprutils_dep PkgConfig::hyprcursor_dep PkgConfig::deps) +target_link_libraries(Hyprland rt PkgConfig::aquamarine_dep PkgConfig::hyprlang_dep PkgConfig::hyprutils_dep PkgConfig::hyprcursor_dep PkgConfig::hyprgraphics_dep PkgConfig::deps) if(udis_dep_FOUND) target_link_libraries(Hyprland PkgConfig::udis_dep) else() diff --git a/flake.lock b/flake.lock index 0db2ee60..23bd37a9 100644 --- a/flake.lock +++ b/flake.lock @@ -92,6 +92,32 @@ "type": "github" } }, + "hyprgraphics": { + "inputs": { + "hyprutils": [ + "hyprutils" + ], + "nixpkgs": [ + "nixpkgs" + ], + "systems": [ + "systems" + ] + }, + "locked": { + "lastModified": 1733248371, + "narHash": "sha256-FFLJzFTyNhS7tBEEECx0B8Ye/bpmxhFVEKlECgMLc6c=", + "owner": "hyprwm", + "repo": "hyprgraphics", + "rev": "cc95e5babc6065bc3ab4cd195429a9900836ef13", + "type": "github" + }, + "original": { + "owner": "hyprwm", + "repo": "hyprgraphics", + "type": "github" + } + }, "hyprland-protocols": { "inputs": { "nixpkgs": [ @@ -246,6 +272,7 @@ "inputs": { "aquamarine": "aquamarine", "hyprcursor": "hyprcursor", + "hyprgraphics": "hyprgraphics", "hyprland-protocols": "hyprland-protocols", "hyprlang": "hyprlang", "hyprutils": "hyprutils", diff --git a/flake.nix b/flake.nix index e3419ef8..f26f1c31 100644 --- a/flake.nix +++ b/flake.nix @@ -22,6 +22,13 @@ inputs.hyprlang.follows = "hyprlang"; }; + hyprgraphics = { + url = "github:hyprwm/hyprgraphics"; + inputs.nixpkgs.follows = "nixpkgs"; + inputs.systems.follows = "systems"; + inputs.hyprutils.follows = "hyprutils"; + }; + hyprland-protocols = { url = "github:hyprwm/hyprland-protocols"; inputs.nixpkgs.follows = "nixpkgs"; diff --git a/meson.build b/meson.build index 39a5a6d0..c46b199c 100644 --- a/meson.build +++ b/meson.build @@ -33,10 +33,12 @@ endif aquamarine = dependency('aquamarine', version: '>=0.4.5') hyprcursor = dependency('hyprcursor', version: '>=0.1.7') +hyprgraphics = dependency('hyprgraphics', version: '>= 0.1.1') hyprlang = dependency('hyprlang', version: '>= 0.3.2') hyprutils = dependency('hyprutils', version: '>= 0.2.3') add_project_arguments(['-DAQUAMARINE_VERSION="@0@"'.format(aquamarine.version())], language: 'cpp') add_project_arguments(['-DHYPRCURSOR_VERSION="@0@"'.format(hyprcursor.version())], language: 'cpp') +add_project_arguments(['-DHYPRGRAPHICS_VERSION="@0@"'.format(hyprgraphics.version())], language: 'cpp') add_project_arguments(['-DHYPRLANG_VERSION="@0@"'.format(hyprlang.version())], language: 'cpp') add_project_arguments(['-DHYPRUTILS_VERSION="@0@"'.format(hyprutils.version())], language: 'cpp') diff --git a/nix/default.nix b/nix/default.nix index 69174d4d..dbe4879e 100644 --- a/nix/default.nix +++ b/nix/default.nix @@ -12,6 +12,7 @@ cairo, git, hyprcursor, + hyprgraphics, hyprland-protocols, hyprlang, hyprutils, @@ -113,6 +114,7 @@ in cairo git hyprcursor + hyprgraphics hyprland-protocols hyprlang hyprutils diff --git a/nix/overlays.nix b/nix/overlays.nix index a7106315..c2103f31 100644 --- a/nix/overlays.nix +++ b/nix/overlays.nix @@ -22,6 +22,7 @@ in { # Dependencies inputs.aquamarine.overlays.default inputs.hyprcursor.overlays.default + inputs.hyprgraphics.overlays.default inputs.hyprland-protocols.overlays.default inputs.hyprlang.overlays.default inputs.hyprutils.overlays.default diff --git a/src/Compositor.cpp b/src/Compositor.cpp index 53eaa467..3573996d 100644 --- a/src/Compositor.cpp +++ b/src/Compositor.cpp @@ -1873,11 +1873,11 @@ void CCompositor::updateWindowAnimatedDecorationValues(PHLWINDOW pWindow) { // shadow if (!pWindow->isX11OverrideRedirect() && !pWindow->m_bX11DoesntWantBorders) { if (pWindow == m_pLastWindow) - pWindow->m_cRealShadowColor = CColor(*PSHADOWCOL); + pWindow->m_cRealShadowColor = CHyprColor(*PSHADOWCOL); else - pWindow->m_cRealShadowColor = CColor(*PSHADOWCOLINACTIVE != INT64_MAX ? *PSHADOWCOLINACTIVE : *PSHADOWCOL); + pWindow->m_cRealShadowColor = CHyprColor(*PSHADOWCOLINACTIVE != INT64_MAX ? *PSHADOWCOLINACTIVE : *PSHADOWCOL); } else { - pWindow->m_cRealShadowColor.setValueAndWarp(CColor(0, 0, 0, 0)); // no shadow + pWindow->m_cRealShadowColor.setValueAndWarp(CHyprColor(0, 0, 0, 0)); // no shadow } pWindow->updateWindowDecos(); @@ -2608,14 +2608,14 @@ void CCompositor::performUserChecks() { g_pHyprNotificationOverlay->addNotification( std::format("Your XDG_CURRENT_DESKTOP environment seems to be managed externally, and the current value is {}.\nThis might cause issues unless it's intentional.", CURRENT_DESKTOP_ENV ? CURRENT_DESKTOP_ENV : "unset"), - CColor{}, 15000, ICON_WARNING); + CHyprColor{}, 15000, ICON_WARNING); } } if (g_pHyprOpenGL->failedAssetsNo > 0) { g_pHyprNotificationOverlay->addNotification(std::format("Hyprland failed to load {} essential asset{}, blame your distro's packager for doing a bad job at packaging!", g_pHyprOpenGL->failedAssetsNo, g_pHyprOpenGL->failedAssetsNo > 1 ? "s" : ""), - CColor{1.0, 0.1, 0.1, 1.0}, 15000, ICON_ERROR); + CHyprColor{1.0, 0.1, 0.1, 1.0}, 15000, ICON_ERROR); } } diff --git a/src/config/ConfigDataValues.hpp b/src/config/ConfigDataValues.hpp index 37c9fc92..212f26fa 100644 --- a/src/config/ConfigDataValues.hpp +++ b/src/config/ConfigDataValues.hpp @@ -21,8 +21,9 @@ class ICustomConfigValueData { class CGradientValueData : public ICustomConfigValueData { public: CGradientValueData() {}; - CGradientValueData(CColor col) { + CGradientValueData(CHyprColor col) { m_vColors.push_back(col); + updateColorsOk(); }; virtual ~CGradientValueData() {}; @@ -30,14 +31,29 @@ class CGradientValueData : public ICustomConfigValueData { return CVD_TYPE_GRADIENT; } - void reset(CColor col) { + void reset(CHyprColor col) { m_vColors.clear(); m_vColors.emplace_back(col); m_fAngle = 0; + updateColorsOk(); + } + + void updateColorsOk() { + m_vColorsOkLabA.clear(); + for (auto& c : m_vColors) { + const auto OKLAB = c.asOkLab(); + m_vColorsOkLabA.emplace_back(OKLAB.l); + m_vColorsOkLabA.emplace_back(OKLAB.a); + m_vColorsOkLabA.emplace_back(OKLAB.b); + m_vColorsOkLabA.emplace_back(c.a); + } } /* Vector containing the colors */ - std::vector m_vColors; + std::vector m_vColors; + + /* Vector containing pure colors for shoving into opengl */ + std::vector m_vColorsOkLabA; /* Float corresponding to the angle (rad) */ float m_fAngle = 0; diff --git a/src/config/ConfigManager.cpp b/src/config/ConfigManager.cpp index 07de8c24..820844eb 100644 --- a/src/config/ConfigManager.cpp +++ b/src/config/ConfigManager.cpp @@ -70,7 +70,7 @@ static Hyprlang::CParseResult configHandleGradientSet(const char* VALUE, void** const auto COL = configStringToInt(var); if (!COL) throw std::runtime_error(std::format("failed to parse {} as a color", var)); - DATA->m_vColors.push_back(CColor(COL.value())); + DATA->m_vColors.push_back(CHyprColor(COL.value())); } catch (std::exception& e) { Debug::log(WARN, "Error parsing gradient {}", V); parseError = "Error parsing gradient " + V + ": " + e.what(); @@ -85,6 +85,8 @@ static Hyprlang::CParseResult configHandleGradientSet(const char* VALUE, void** DATA->m_vColors.push_back(0); // transparent } + DATA->updateColorsOk(); + Hyprlang::CParseResult result; if (!parseError.empty()) result.setError(parseError.c_str()); @@ -676,7 +678,7 @@ CConfigManager::CConfigManager() { Debug::disableTime = reinterpret_cast(m_pConfig->getConfigValuePtr("debug:disable_time")->getDataStaticPtr()); if (ERR.has_value()) - g_pHyprError->queueCreate(ERR.value(), CColor{1.0, 0.1, 0.1, 1.0}); + g_pHyprError->queueCreate(ERR.value(), CHyprColor{1.0, 0.1, 0.1, 1.0}); } std::optional CConfigManager::generateConfig(std::string configPath) { @@ -883,14 +885,14 @@ void CConfigManager::postConfigReload(const Hyprlang::CParseResult& result) { m_szConfigErrors = ""; if (result.error && !std::any_cast(m_pConfig->getConfigValue("debug:suppress_errors"))) - g_pHyprError->queueCreate(result.getError(), CColor(1.0, 50.0 / 255.0, 50.0 / 255.0, 1.0)); + g_pHyprError->queueCreate(result.getError(), CHyprColor(1.0, 50.0 / 255.0, 50.0 / 255.0, 1.0)); else if (std::any_cast(m_pConfig->getConfigValue("autogenerated")) == 1) g_pHyprError->queueCreate( "Warning: You're using an autogenerated config! (config file: " + getMainConfigPath() + " )\nSUPER+Q -> kitty (if it doesn't launch, make sure it's installed or choose a different terminal in the config)\nSUPER+M -> exit Hyprland", - CColor(1.0, 1.0, 70.0 / 255.0, 1.0)); + CHyprColor(1.0, 1.0, 70.0 / 255.0, 1.0)); else if (*PENABLEEXPLICIT != prevEnabledExplicit) - g_pHyprError->queueCreate("Warning: You changed the render:explicit_sync option, this requires you to restart Hyprland.", CColor(0.9, 0.76, 0.221, 1.0)); + g_pHyprError->queueCreate("Warning: You changed the render:explicit_sync option, this requires you to restart Hyprland.", CHyprColor(0.9, 0.76, 0.221, 1.0)); else g_pHyprError->destroy(); @@ -948,7 +950,8 @@ void CConfigManager::postConfigReload(const Hyprlang::CParseResult& result) { // manual crash if (std::any_cast(m_pConfig->getConfigValue("debug:manual_crash")) && !m_bManualCrashInitiated) { m_bManualCrashInitiated = true; - g_pHyprNotificationOverlay->addNotification("Manual crash has been set up. Set debug:manual_crash back to 0 in order to crash the compositor.", CColor(0), 5000, ICON_INFO); + g_pHyprNotificationOverlay->addNotification("Manual crash has been set up. Set debug:manual_crash back to 0 in order to crash the compositor.", CHyprColor(0), 5000, + ICON_INFO); } else if (m_bManualCrashInitiated && !std::any_cast(m_pConfig->getConfigValue("debug:manual_crash"))) { // cowabunga it is g_pHyprRenderer->initiateManualCrash(); @@ -1015,7 +1018,7 @@ std::string CConfigManager::parseKeyword(const std::string& COMMAND, const std:: if (COMMAND.contains("explicit")) { if (*PENABLEEXPLICIT != prevEnabledExplicit) - g_pHyprError->queueCreate("Warning: You changed the render:explicit_sync option, this requires you to restart Hyprland.", CColor(0.9, 0.76, 0.221, 1.0)); + g_pHyprError->queueCreate("Warning: You changed the render:explicit_sync option, this requires you to restart Hyprland.", CHyprColor(0.9, 0.76, 0.221, 1.0)); else g_pHyprError->destroy(); } @@ -1027,7 +1030,7 @@ std::string CConfigManager::parseKeyword(const std::string& COMMAND, const std:: if (std::any_cast(m_pConfig->getConfigValue("debug:manual_crash")) && !m_bManualCrashInitiated) { m_bManualCrashInitiated = true; if (g_pHyprNotificationOverlay) { - g_pHyprNotificationOverlay->addNotification("Manual crash has been set up. Set debug:manual_crash back to 0 in order to crash the compositor.", CColor(0), 5000, + g_pHyprNotificationOverlay->addNotification("Manual crash has been set up. Set debug:manual_crash back to 0 in order to crash the compositor.", CHyprColor(0), 5000, ICON_INFO); } } else if (m_bManualCrashInitiated && !std::any_cast(m_pConfig->getConfigValue("debug:manual_crash"))) { @@ -1671,7 +1674,7 @@ SAnimationPropertyConfig* CConfigManager::getAnimationPropertyConfig(const std:: } void CConfigManager::addParseError(const std::string& err) { - g_pHyprError->queueCreate(err + "\nHyprland may not work correctly.", CColor(1.0, 50.0 / 255.0, 50.0 / 255.0, 1.0)); + g_pHyprError->queueCreate(err + "\nHyprland may not work correctly.", CHyprColor(1.0, 50.0 / 255.0, 50.0 / 255.0, 1.0)); } PHLMONITOR CConfigManager::getBoundMonitorForWS(const std::string& wsname) { @@ -1716,7 +1719,7 @@ void CConfigManager::handlePluginLoads() { error << "\n" << path; } - g_pHyprError->queueCreate(error.str(), CColor(1.0, 50.0 / 255.0, 50.0 / 255.0, 1.0)); + g_pHyprError->queueCreate(error.str(), CHyprColor(1.0, 50.0 / 255.0, 50.0 / 255.0, 1.0)); } if (pluginsChanged) { diff --git a/src/config/ConfigManager.hpp b/src/config/ConfigManager.hpp index 88b74b6e..a3b86e69 100644 --- a/src/config/ConfigManager.hpp +++ b/src/config/ConfigManager.hpp @@ -119,7 +119,7 @@ struct SConfigOptionDescription { }; struct SColorData { - CColor color; + CHyprColor color; }; struct SChoiceData { diff --git a/src/debug/HyprCtl.cpp b/src/debug/HyprCtl.cpp index 6b62ec8d..74b2a3a1 100644 --- a/src/debug/HyprCtl.cpp +++ b/src/debug/HyprCtl.cpp @@ -875,9 +875,9 @@ std::string versionRequest(eHyprCtlOutputFormat format, std::string request) { std::string result = std::format("Hyprland {} built from branch {} at commit {} {} ({}).\n" "Date: {}\n" "Tag: {}, commits: {}\n" - "built against:\n aquamarine {}\n hyprlang {}\n hyprutils {}\n hyprcursor {}\n\n\n", + "built against:\n aquamarine {}\n hyprlang {}\n hyprutils {}\n hyprcursor {}\n hyprgraphics {}\n\n\n", HYPRLAND_VERSION, GIT_BRANCH, GIT_COMMIT_HASH, GIT_DIRTY, commitMsg, GIT_COMMIT_DATE, GIT_TAG, GIT_COMMITS, AQUAMARINE_VERSION, - HYPRLANG_VERSION, HYPRUTILS_VERSION, HYPRCURSOR_VERSION); + HYPRLANG_VERSION, HYPRUTILS_VERSION, HYPRCURSOR_VERSION, HYPRGRAPHICS_VERSION); #if (!defined(LEGACY_RENDERER) && !defined(ISDEBUG) && !defined(NO_XWAYLAND)) result += "no flags were set\n"; @@ -909,9 +909,10 @@ std::string versionRequest(eHyprCtlOutputFormat format, std::string request) { "buildHyprlang": "{}", "buildHyprutils": "{}", "buildHyprcursor": "{}", + "buildHyprgraphics": "{}", "flags": [)#", GIT_BRANCH, GIT_COMMIT_HASH, HYPRLAND_VERSION, (strcmp(GIT_DIRTY, "dirty") == 0 ? "true" : "false"), escapeJSONStrings(commitMsg), GIT_COMMIT_DATE, GIT_TAG, - GIT_COMMITS, AQUAMARINE_VERSION, HYPRLANG_VERSION, HYPRUTILS_VERSION, HYPRCURSOR_VERSION); + GIT_COMMITS, AQUAMARINE_VERSION, HYPRLANG_VERSION, HYPRUTILS_VERSION, HYPRCURSOR_VERSION, HYPRGRAPHICS_VERSION); #ifdef LEGACY_RENDERER result += "\"legacyrenderer\","; @@ -1290,7 +1291,7 @@ std::string dispatchSeterror(eHyprCtlOutputFormat format, std::string request) { return "ok"; } - const CColor COLOR = configStringToInt(vars[1]).value_or(0); + const CHyprColor COLOR = configStringToInt(vars[1]).value_or(0); for (size_t i = 2; i < vars.size(); ++i) errorMessage += vars[i] + ' '; @@ -1545,10 +1546,10 @@ std::string dispatchNotify(eHyprCtlOutputFormat format, std::string request) { const auto COLOR_RESULT = configStringToInt(vars[3]); if (!COLOR_RESULT) return "invalid arg 3"; - CColor color = *COLOR_RESULT; + CHyprColor color = *COLOR_RESULT; - size_t msgidx = 4; - float fontsize = 13.f; + size_t msgidx = 4; + float fontsize = 13.f; if (vars[msgidx].length() > 9 && vars[msgidx].compare(0, 9, "fontsize:") == 0) { const auto FONTSIZE = vars[msgidx].substr(9); diff --git a/src/debug/HyprNotificationOverlay.cpp b/src/debug/HyprNotificationOverlay.cpp index e46999e6..482db541 100644 --- a/src/debug/HyprNotificationOverlay.cpp +++ b/src/debug/HyprNotificationOverlay.cpp @@ -34,11 +34,11 @@ CHyprNotificationOverlay::~CHyprNotificationOverlay() { cairo_surface_destroy(m_pCairoSurface); } -void CHyprNotificationOverlay::addNotification(const std::string& text, const CColor& color, const float timeMs, const eIcons icon, const float fontSize) { +void CHyprNotificationOverlay::addNotification(const std::string& text, const CHyprColor& color, const float timeMs, const eIcons icon, const float fontSize) { const auto PNOTIF = m_dNotifications.emplace_back(std::make_unique()).get(); PNOTIF->text = icon != eIcons::ICON_NONE ? " " + text /* tiny bit of padding otherwise icon touches text */ : text; - PNOTIF->color = color == CColor(0) ? ICONS_COLORS[icon] : color; + PNOTIF->color = color == CHyprColor(0) ? ICONS_COLORS[icon] : color; PNOTIF->started.reset(); PNOTIF->timeMs = timeMs; PNOTIF->icon = icon; diff --git a/src/debug/HyprNotificationOverlay.hpp b/src/debug/HyprNotificationOverlay.hpp index 0bba8b04..67603e49 100644 --- a/src/debug/HyprNotificationOverlay.hpp +++ b/src/debug/HyprNotificationOverlay.hpp @@ -19,17 +19,17 @@ enum eIconBackend { static const std::array, 3 /* backends */> ICONS_ARRAY = { std::array{"[!]", "[i]", "[Hint]", "[Err]", "[?]", "[ok]", ""}, std::array{"", "", "", "", "", "󰸞", ""}, std::array{"", "", "", "", "", ""}}; -static const std::array ICONS_COLORS = {CColor{255.0 / 255.0, 204 / 255.0, 102 / 255.0, 1.0}, - CColor{128 / 255.0, 255 / 255.0, 255 / 255.0, 1.0}, - CColor{179 / 255.0, 255 / 255.0, 204 / 255.0, 1.0}, - CColor{255 / 255.0, 77 / 255.0, 77 / 255.0, 1.0}, - CColor{255 / 255.0, 204 / 255.0, 153 / 255.0, 1.0}, - CColor{128 / 255.0, 255 / 255.0, 128 / 255.0, 1.0}, - CColor{0, 0, 0, 1.0}}; +static const std::array ICONS_COLORS = {CHyprColor{255.0 / 255.0, 204 / 255.0, 102 / 255.0, 1.0}, + CHyprColor{128 / 255.0, 255 / 255.0, 255 / 255.0, 1.0}, + CHyprColor{179 / 255.0, 255 / 255.0, 204 / 255.0, 1.0}, + CHyprColor{255 / 255.0, 77 / 255.0, 77 / 255.0, 1.0}, + CHyprColor{255 / 255.0, 204 / 255.0, 153 / 255.0, 1.0}, + CHyprColor{128 / 255.0, 255 / 255.0, 128 / 255.0, 1.0}, + CHyprColor{0, 0, 0, 1.0}}; struct SNotification { std::string text = ""; - CColor color; + CHyprColor color; CTimer started; float timeMs = 0; eIcons icon = ICON_NONE; @@ -42,7 +42,7 @@ class CHyprNotificationOverlay { ~CHyprNotificationOverlay(); void draw(PHLMONITOR pMonitor); - void addNotification(const std::string& text, const CColor& color, const float timeMs, const eIcons icon = ICON_NONE, const float fontSize = 13.f); + void addNotification(const std::string& text, const CHyprColor& color, const float timeMs, const eIcons icon = ICON_NONE, const float fontSize = 13.f); void dismissNotifications(const int amount); bool hasAny(); diff --git a/src/desktop/Window.cpp b/src/desktop/Window.cpp index 12e81b76..b015d61f 100644 --- a/src/desktop/Window.cpp +++ b/src/desktop/Window.cpp @@ -674,8 +674,8 @@ void CWindow::applyDynamicRule(const SWindowRule& r) { // Basic form has only two colors, everything else can be parsed as a gradient if (colorsAndAngles.size() == 2 && !colorsAndAngles[1].contains("deg")) { - m_sWindowData.activeBorderColor = CWindowOverridableVar(CGradientValueData(CColor(configStringToInt(colorsAndAngles[0]).value_or(0))), priority); - m_sWindowData.inactiveBorderColor = CWindowOverridableVar(CGradientValueData(CColor(configStringToInt(colorsAndAngles[1]).value_or(0))), priority); + m_sWindowData.activeBorderColor = CWindowOverridableVar(CGradientValueData(CHyprColor(configStringToInt(colorsAndAngles[0]).value_or(0))), priority); + m_sWindowData.inactiveBorderColor = CWindowOverridableVar(CGradientValueData(CHyprColor(configStringToInt(colorsAndAngles[1]).value_or(0))), priority); return; } diff --git a/src/desktop/Window.hpp b/src/desktop/Window.hpp index 5dd59437..672ff6ec 100644 --- a/src/desktop/Window.hpp +++ b/src/desktop/Window.hpp @@ -356,7 +356,7 @@ class CWindow { CAnimatedVariable m_fActiveInactiveAlpha; // animated shadow color - CAnimatedVariable m_cRealShadowColor; + CAnimatedVariable m_cRealShadowColor; // animated tint CAnimatedVariable m_fDimPercent; diff --git a/src/helpers/AnimatedVariable.hpp b/src/helpers/AnimatedVariable.hpp index 6310afb7..7cea72a0 100644 --- a/src/helpers/AnimatedVariable.hpp +++ b/src/helpers/AnimatedVariable.hpp @@ -34,7 +34,7 @@ struct typeToANIMATEDVARTYPE_t { }; template <> -struct typeToANIMATEDVARTYPE_t { +struct typeToANIMATEDVARTYPE_t { static constexpr ANIMATEDVARTYPE value = AVARTYPE_COLOR; }; @@ -63,7 +63,7 @@ concept OneOf = (... or std::same_as); // This is mainly to get better errors if we put a type that's not supported // Otherwise template errors are ugly template -concept Animable = OneOf; +concept Animable = OneOf; class CBaseAnimatedVariable { public: diff --git a/src/helpers/Color.cpp b/src/helpers/Color.cpp index f9a207bb..fe217c0f 100644 --- a/src/helpers/Color.cpp +++ b/src/helpers/Color.cpp @@ -5,22 +5,52 @@ #define GREEN(c) ((double)(((c) >> 8) & 0xff) / 255.0) #define BLUE(c) ((double)(((c)) & 0xff) / 255.0) -CColor::CColor() {} +CHyprColor::CHyprColor() {} -CColor::CColor(float r, float g, float b, float a) { - this->r = r; - this->g = g; - this->b = b; - this->a = a; +CHyprColor::CHyprColor(float r_, float g_, float b_, float a_) { + r = r_; + g = g_; + b = b_; + a = a_; + + okLab = Hyprgraphics::CColor(Hyprgraphics::CColor::SSRGB{r, g, b}).asOkLab(); } -CColor::CColor(uint64_t hex) { - this->r = RED(hex); - this->g = GREEN(hex); - this->b = BLUE(hex); - this->a = ALPHA(hex); +CHyprColor::CHyprColor(uint64_t hex) { + r = RED(hex); + g = GREEN(hex); + b = BLUE(hex); + a = ALPHA(hex); + + okLab = Hyprgraphics::CColor(Hyprgraphics::CColor::SSRGB{r, g, b}).asOkLab(); } -uint32_t CColor::getAsHex() const { +CHyprColor::CHyprColor(const Hyprgraphics::CColor& color, float a_) { + const auto SRGB = color.asRgb(); + r = SRGB.r; + g = SRGB.g; + b = SRGB.b; + a = a_; + + okLab = color.asOkLab(); +} + +uint32_t CHyprColor::getAsHex() const { return (uint32_t)(a * 255.f) * 0x1000000 + (uint32_t)(r * 255.f) * 0x10000 + (uint32_t)(g * 255.f) * 0x100 + (uint32_t)(b * 255.f) * 0x1; -} \ No newline at end of file +} + +Hyprgraphics::CColor::SSRGB CHyprColor::asRGB() const { + return {r, g, b}; +} + +Hyprgraphics::CColor::SOkLab CHyprColor::asOkLab() const { + return okLab; +} + +Hyprgraphics::CColor::SHSL CHyprColor::asHSL() const { + return Hyprgraphics::CColor(okLab).asHSL(); +} + +CHyprColor CHyprColor::stripA() const { + return {r, g, b, 1.F}; +} diff --git a/src/helpers/Color.hpp b/src/helpers/Color.hpp index 32ed39ee..cf7f7943 100644 --- a/src/helpers/Color.hpp +++ b/src/helpers/Color.hpp @@ -1,35 +1,47 @@ #pragma once #include +#include +#include "../debug/Log.hpp" +#include "../macros.hpp" -class CColor { +class CHyprColor { public: - CColor(); - CColor(float r, float g, float b, float a); - CColor(uint64_t); - - float r = 0, g = 0, b = 0, a = 1.f; + CHyprColor(); + CHyprColor(float r, float g, float b, float a); + CHyprColor(const Hyprgraphics::CColor& col, float a); + CHyprColor(uint64_t); // AR32 - uint32_t getAsHex() const; + uint32_t getAsHex() const; + Hyprgraphics::CColor::SSRGB asRGB() const; + Hyprgraphics::CColor::SOkLab asOkLab() const; + Hyprgraphics::CColor::SHSL asHSL() const; + CHyprColor stripA() const; - CColor operator-(const CColor& c2) const { - return CColor(r - c2.r, g - c2.g, b - c2.b, a - c2.a); + // + bool operator==(const CHyprColor& c2) const { + return c2.r == r && c2.g == g && c2.b == b && c2.a == a; } - CColor operator+(const CColor& c2) const { - return CColor(r + c2.r, g + c2.g, b + c2.b, a + c2.a); + // stubs for the AnimationMgr + CHyprColor operator-(const CHyprColor& c2) const { + RASSERT(false, "CHyprColor: - is a STUB"); + return {}; } - CColor operator*(const float& v) const { - return CColor(r * v, g * v, b * v, a * v); + CHyprColor operator+(const CHyprColor& c2) const { + RASSERT(false, "CHyprColor: + is a STUB"); + return {}; } - bool operator==(const CColor& c2) const { - return r == c2.r && g == c2.g && b == c2.b && a == c2.a; + CHyprColor operator*(const float& c2) const { + RASSERT(false, "CHyprColor: * is a STUB"); + return {}; } - CColor stripA() const { - return {r, g, b, 1}; - } + double r = 0, g = 0, b = 0, a = 0; + + private: + Hyprgraphics::CColor::SOkLab okLab; // cache for the OkLab representation }; diff --git a/src/hyprerror/HyprError.cpp b/src/hyprerror/HyprError.cpp index 4761346e..74a3030c 100644 --- a/src/hyprerror/HyprError.cpp +++ b/src/hyprerror/HyprError.cpp @@ -33,7 +33,7 @@ CHyprError::~CHyprError() { m_fFadeOpacity.unregister(); } -void CHyprError::queueCreate(std::string message, const CColor& color) { +void CHyprError::queueCreate(std::string message, const CHyprColor& color) { m_szQueued = message; m_cQueued = color; } @@ -98,7 +98,7 @@ void CHyprError::createQueued() { cairo_stroke(CAIRO); // draw the text with a common font - const CColor textColor = CColor(0.9, 0.9, 0.9, 1.0); + const CHyprColor textColor = CHyprColor(0.9, 0.9, 0.9, 1.0); cairo_set_source_rgba(CAIRO, textColor.r, textColor.g, textColor.b, textColor.a); static auto fontFamily = CConfigValue("misc:font_family"); @@ -160,7 +160,7 @@ void CHyprError::createQueued() { m_bIsCreated = true; m_szQueued = ""; - m_cQueued = CColor(); + m_cQueued = CHyprColor(); g_pHyprRenderer->damageMonitor(PMONITOR); diff --git a/src/hyprerror/HyprError.hpp b/src/hyprerror/HyprError.hpp index a553614c..042dccd0 100644 --- a/src/hyprerror/HyprError.hpp +++ b/src/hyprerror/HyprError.hpp @@ -11,7 +11,7 @@ class CHyprError { CHyprError(); ~CHyprError(); - void queueCreate(std::string message, const CColor& color); + void queueCreate(std::string message, const CHyprColor& color); void draw(); void destroy(); @@ -21,7 +21,7 @@ class CHyprError { private: void createQueued(); std::string m_szQueued = ""; - CColor m_cQueued; + CHyprColor m_cQueued; bool m_bQueuedDestroy = false; bool m_bIsCreated = false; SP m_pTexture; diff --git a/src/managers/AnimationManager.cpp b/src/managers/AnimationManager.cpp index 68dbdda1..7525bf6b 100644 --- a/src/managers/AnimationManager.cpp +++ b/src/managers/AnimationManager.cpp @@ -8,6 +8,8 @@ #include "eventLoop/EventLoopManager.hpp" #include "../helpers/varlist/VarList.hpp" +#include + int wlTick(SP self, void* data) { if (g_pAnimationManager) g_pAnimationManager->onTicked(); @@ -154,7 +156,7 @@ void CAnimationManager::tick() { // beziers are with a switch unforto // TODO: maybe do something cleaner - auto updateVariable = [&](CAnimatedVariable& av) { + static const auto updateVariable = [&](CAnimatedVariable& av) { // for disabled anims just warp if (av.m_pConfig->pValues->internalEnabled == 0 || animationsDisabled) { av.warp(false); @@ -166,13 +168,50 @@ void CAnimationManager::tick() { return; } - const auto DELTA = av.m_Goal - av.m_Begun; const auto BEZIER = m_mBezierCurves.find(av.m_pConfig->pValues->internalBezier); + const auto POINTY = BEZIER != m_mBezierCurves.end() ? BEZIER->second.getYForPoint(SPENT) : DEFAULTBEZIER->second.getYForPoint(SPENT); + + const auto DELTA = av.m_Goal - av.m_Begun; if (BEZIER != m_mBezierCurves.end()) - av.m_Value = av.m_Begun + DELTA * BEZIER->second.getYForPoint(SPENT); + av.m_Value = av.m_Begun + DELTA * POINTY; else - av.m_Value = av.m_Begun + DELTA * DEFAULTBEZIER->second.getYForPoint(SPENT); + av.m_Value = av.m_Begun + DELTA * POINTY; + }; + + static const auto updateColorVariable = [&](CAnimatedVariable& av) { + // for disabled anims just warp + if (av.m_pConfig->pValues->internalEnabled == 0 || animationsDisabled) { + av.warp(false); + return; + } + + if (SPENT >= 1.f || av.m_Begun == av.m_Goal) { + av.warp(false); + return; + } + + const auto BEZIER = m_mBezierCurves.find(av.m_pConfig->pValues->internalBezier); + const auto POINTY = BEZIER != m_mBezierCurves.end() ? BEZIER->second.getYForPoint(SPENT) : DEFAULTBEZIER->second.getYForPoint(SPENT); + + // convert both to OkLab, then lerp that, and convert back. + // This is not as fast as just lerping rgb, but it's WAY more precise... + // Use the CHyprColor cache for OkLab + + const auto& L1 = av.m_Begun.asOkLab(); + const auto& L2 = av.m_Goal.asOkLab(); + + static const auto lerp = [](const float one, const float two, const float progress) -> float { return one + (two - one) * progress; }; + + const Hyprgraphics::CColor lerped = Hyprgraphics::CColor::SOkLab{ + .l = lerp(L1.l, L2.l, POINTY), + .a = lerp(L1.a, L2.a, POINTY), + .b = lerp(L1.b, L2.b, POINTY), + }; + + av.m_Value = {lerped, lerp(av.m_Begun.a, av.m_Goal.a, POINTY)}; + + return; }; switch (av->m_Type) { @@ -187,8 +226,8 @@ void CAnimationManager::tick() { break; } case AVARTYPE_COLOR: { - auto typedAv = static_cast*>(av); - updateVariable(*typedAv); + auto typedAv = static_cast*>(av); + updateColorVariable(*typedAv); break; } default: UNREACHABLE(); @@ -272,7 +311,7 @@ bool CAnimationManager::deltaSmallToFlip(const Vector2D& a, const Vector2D& b) { return std::abs(a.x - b.x) < 0.5f && std::abs(a.y - b.y) < 0.5f; } -bool CAnimationManager::deltaSmallToFlip(const CColor& a, const CColor& b) { +bool CAnimationManager::deltaSmallToFlip(const CHyprColor& a, const CHyprColor& b) { return std::abs(a.r - b.r) < 0.5f && std::abs(a.g - b.g) < 0.5f && std::abs(a.b - b.b) < 0.5f && std::abs(a.a - b.a) < 0.5f; } @@ -288,7 +327,7 @@ bool CAnimationManager::deltazero(const float& a, const float& b) { return a == b; } -bool CAnimationManager::deltazero(const CColor& a, const CColor& b) { +bool CAnimationManager::deltazero(const CHyprColor& a, const CHyprColor& b) { return a.r == b.r && a.g == b.g && a.b == b.b && a.a == b.a; } diff --git a/src/managers/AnimationManager.hpp b/src/managers/AnimationManager.hpp index 601a38b3..3960f261 100644 --- a/src/managers/AnimationManager.hpp +++ b/src/managers/AnimationManager.hpp @@ -39,10 +39,10 @@ class CAnimationManager { private: bool deltaSmallToFlip(const Vector2D& a, const Vector2D& b); - bool deltaSmallToFlip(const CColor& a, const CColor& b); + bool deltaSmallToFlip(const CHyprColor& a, const CHyprColor& b); bool deltaSmallToFlip(const float& a, const float& b); bool deltazero(const Vector2D& a, const Vector2D& b); - bool deltazero(const CColor& a, const CColor& b); + bool deltazero(const CHyprColor& a, const CHyprColor& b); bool deltazero(const float& a, const float& b); std::unordered_map m_mBezierCurves; diff --git a/src/managers/KeybindManager.cpp b/src/managers/KeybindManager.cpp index 7f10249a..cfb7453c 100644 --- a/src/managers/KeybindManager.cpp +++ b/src/managers/KeybindManager.cpp @@ -275,7 +275,7 @@ void CKeybindManager::updateXKBTranslationState() { if (!PKEYMAP) { g_pHyprError->queueCreate("[Runtime Error] Invalid keyboard layout passed. ( rules: " + RULES + ", model: " + MODEL + ", variant: " + VARIANT + ", options: " + OPTIONS + ", layout: " + LAYOUT + " )", - CColor(1.0, 50.0 / 255.0, 50.0 / 255.0, 1.0)); + CHyprColor(1.0, 50.0 / 255.0, 50.0 / 255.0, 1.0)); Debug::log(ERR, "[XKBTranslationState] Keyboard layout {} with variant {} (rules: {}, model: {}, options: {}) couldn't have been loaded.", rules.layout, rules.variant, rules.rules, rules.model, rules.options); diff --git a/src/managers/PointerManager.cpp b/src/managers/PointerManager.cpp index 0580c9be..c0c190dd 100644 --- a/src/managers/PointerManager.cpp +++ b/src/managers/PointerManager.cpp @@ -505,7 +505,7 @@ SP CPointerManager::renderHWCursorBuffer(SPbind(); g_pHyprOpenGL->beginSimple(state->monitor.lock(), {0, 0, INT16_MAX, INT16_MAX}, RBO); - g_pHyprOpenGL->clear(CColor{0.F, 0.F, 0.F, 0.F}); + g_pHyprOpenGL->clear(CHyprColor{0.F, 0.F, 0.F, 0.F}); CBox xbox = {{}, Vector2D{currentCursorImage.size / currentCursorImage.scale * state->monitor->scale}.round()}; Debug::log(TRACE, "[pointer] monitor: {}, size: {}, hw buf: {}, scale: {:.2f}, monscale: {:.2f}, xbox: {}", state->monitor->szName, currentCursorImage.size, cursorSize, diff --git a/src/meson.build b/src/meson.build index 61ca06d5..754cd55a 100644 --- a/src/meson.build +++ b/src/meson.build @@ -10,6 +10,7 @@ executable( server_protos, aquamarine, hyprcursor, + hyprgraphics, hyprlang, hyprutils, dependency('gbm'), diff --git a/src/plugins/PluginAPI.cpp b/src/plugins/PluginAPI.cpp index ef3ae06a..1a7f25ab 100644 --- a/src/plugins/PluginAPI.cpp +++ b/src/plugins/PluginAPI.cpp @@ -71,7 +71,7 @@ APICALL bool HyprlandAPI::reloadConfig() { return true; } -APICALL bool HyprlandAPI::addNotification(HANDLE handle, const std::string& text, const CColor& color, const float timeMs) { +APICALL bool HyprlandAPI::addNotification(HANDLE handle, const std::string& text, const CHyprColor& color, const float timeMs) { auto* const PLUGIN = g_pPluginSystem->getPluginByHandle(handle); if (!PLUGIN) @@ -244,7 +244,7 @@ APICALL bool addNotificationV2(HANDLE handle, const std::unordered_map(iterator->second); + const auto COLOR = std::any_cast(iterator->second); // optional eIcons icon = ICON_NONE; diff --git a/src/plugins/PluginAPI.hpp b/src/plugins/PluginAPI.hpp index 4dcf4ba5..bd257699 100644 --- a/src/plugins/PluginAPI.hpp +++ b/src/plugins/PluginAPI.hpp @@ -187,7 +187,7 @@ namespace HyprlandAPI { returns: true on success. False otherwise. */ - APICALL bool addNotification(HANDLE handle, const std::string& text, const CColor& color, const float timeMs); + APICALL bool addNotification(HANDLE handle, const std::string& text, const CHyprColor& color, const float timeMs); /* Creates a trampoline function hook to an internal hl func. @@ -251,7 +251,7 @@ namespace HyprlandAPI { data has to contain: - text: std::string or const char* - time: uint64_t - - color: CColor -> CColor(0) will apply the default color for the notification icon + - color: CHyprColor -> CHyprColor(0) will apply the default color for the notification icon data may contain: - icon: eIcons diff --git a/src/protocols/SinglePixel.cpp b/src/protocols/SinglePixel.cpp index d800539d..41771ce2 100644 --- a/src/protocols/SinglePixel.cpp +++ b/src/protocols/SinglePixel.cpp @@ -2,7 +2,7 @@ #include #include "render/Renderer.hpp" -CSinglePixelBuffer::CSinglePixelBuffer(uint32_t id, wl_client* client, CColor col_) { +CSinglePixelBuffer::CSinglePixelBuffer(uint32_t id, wl_client* client, CHyprColor col_) { LOGM(LOG, "New single-pixel buffer with color 0x{:x}", col_.getAsHex()); color = col_.getAsHex(); @@ -59,7 +59,7 @@ bool CSinglePixelBuffer::good() { return resource->good(); } -CSinglePixelBufferResource::CSinglePixelBufferResource(uint32_t id, wl_client* client, CColor color) { +CSinglePixelBufferResource::CSinglePixelBufferResource(uint32_t id, wl_client* client, CHyprColor color) { buffer = makeShared(id, client, color); if (!buffer->good()) @@ -89,8 +89,8 @@ CSinglePixelBufferManagerResource::CSinglePixelBufferManagerResource(SPsetOnDestroy([this](CWpSinglePixelBufferManagerV1* r) { PROTO::singlePixel->destroyResource(this); }); resource->setCreateU32RgbaBuffer([this](CWpSinglePixelBufferManagerV1* res, uint32_t id, uint32_t r, uint32_t g, uint32_t b, uint32_t a) { - CColor color{r / (float)std::numeric_limits::max(), g / (float)std::numeric_limits::max(), b / (float)std::numeric_limits::max(), - a / (float)std::numeric_limits::max()}; + CHyprColor color{r / (float)std::numeric_limits::max(), g / (float)std::numeric_limits::max(), b / (float)std::numeric_limits::max(), + a / (float)std::numeric_limits::max()}; const auto RESOURCE = PROTO::singlePixel->m_vBuffers.emplace_back(makeShared(id, resource->client(), color)); if (!RESOURCE->good()) { diff --git a/src/protocols/SinglePixel.hpp b/src/protocols/SinglePixel.hpp index ab74825c..b20f582a 100644 --- a/src/protocols/SinglePixel.hpp +++ b/src/protocols/SinglePixel.hpp @@ -9,7 +9,7 @@ class CSinglePixelBuffer : public IHLBuffer { public: - CSinglePixelBuffer(uint32_t id, wl_client* client, CColor col); + CSinglePixelBuffer(uint32_t id, wl_client* client, CHyprColor col); virtual ~CSinglePixelBuffer(); virtual Aquamarine::eBufferCapability caps(); @@ -33,7 +33,7 @@ class CSinglePixelBuffer : public IHLBuffer { class CSinglePixelBufferResource { public: - CSinglePixelBufferResource(uint32_t id, wl_client* client, CColor color); + CSinglePixelBufferResource(uint32_t id, wl_client* client, CHyprColor color); ~CSinglePixelBufferResource(); bool good(); diff --git a/src/protocols/ToplevelExport.cpp b/src/protocols/ToplevelExport.cpp index 04c089d7..d00e9dce 100644 --- a/src/protocols/ToplevelExport.cpp +++ b/src/protocols/ToplevelExport.cpp @@ -255,7 +255,7 @@ bool CToplevelExportFrame::copyShm(timespec* now) { if (!g_pHyprRenderer->beginRender(PMONITOR, fakeDamage, RENDER_MODE_FULL_FAKE, nullptr, &outFB)) return false; - g_pHyprOpenGL->clear(CColor(0, 0, 0, 1.0)); + g_pHyprOpenGL->clear(CHyprColor(0, 0, 0, 1.0)); // render client at 0,0 g_pHyprRenderer->m_bBlockSurfaceFeedback = g_pHyprRenderer->shouldRenderWindow(pWindow); // block the feedback to avoid spamming the surface if it's visible @@ -308,7 +308,7 @@ bool CToplevelExportFrame::copyDmabuf(timespec* now) { if (!g_pHyprRenderer->beginRender(PMONITOR, fakeDamage, RENDER_MODE_TO_BUFFER, buffer.lock())) return false; - g_pHyprOpenGL->clear(CColor(0, 0, 0, 1.0)); + g_pHyprOpenGL->clear(CHyprColor(0, 0, 0, 1.0)); g_pHyprRenderer->m_bBlockSurfaceFeedback = g_pHyprRenderer->shouldRenderWindow(pWindow); // block the feedback to avoid spamming the surface if it's visible g_pHyprRenderer->renderWindow(pWindow, PMONITOR, now, false, RENDER_PASS_ALL, true, true); diff --git a/src/render/OpenGL.cpp b/src/render/OpenGL.cpp index 9c00daee..9b878317 100644 --- a/src/render/OpenGL.cpp +++ b/src/render/OpenGL.cpp @@ -566,7 +566,11 @@ void CHyprOpenGLImpl::logShaderError(const GLuint& shader, bool program) { glGetShaderInfoLog(shader, maxLength, &maxLength, errorLog.data()); std::string errorStr(errorLog.begin(), errorLog.end()); - g_pConfigManager->addParseError((program ? "Screen shader parser: Error linking program:" : "Screen shader parser: Error compiling shader: ") + errorStr); + const auto FULLERROR = (program ? "Screen shader parser: Error linking program:" : "Screen shader parser: Error compiling shader: ") + errorStr; + + Debug::log(ERR, "Failed to link shader: {}", FULLERROR); + + g_pConfigManager->addParseError(FULLERROR); } GLuint CHyprOpenGLImpl::createProgram(const std::string& vert, const std::string& frag, bool dynamic) { @@ -604,6 +608,8 @@ GLuint CHyprOpenGLImpl::createProgram(const std::string& vert, const std::string return 0; } } else { + if (ok != GL_TRUE) + logShaderError(prog, true); RASSERT(ok != GL_FALSE, "createProgram() failed! GL_LINK_STATUS not OK!"); } @@ -627,6 +633,8 @@ GLuint CHyprOpenGLImpl::compileShader(const GLuint& type, std::string src, bool return 0; } } else { + if (ok != GL_TRUE) + logShaderError(shader, false); RASSERT(ok != GL_FALSE, "compileShader() failed! GL_COMPILE_STATUS not OK!"); } @@ -1114,8 +1122,12 @@ void CHyprOpenGLImpl::initShaders() { m_RenderData.pCurrentMonData->m_shBORDER1.radius = glGetUniformLocation(prog, "radius"); m_RenderData.pCurrentMonData->m_shBORDER1.radiusOuter = glGetUniformLocation(prog, "radiusOuter"); m_RenderData.pCurrentMonData->m_shBORDER1.gradient = glGetUniformLocation(prog, "gradient"); + m_RenderData.pCurrentMonData->m_shBORDER1.gradient2 = glGetUniformLocation(prog, "gradient2"); m_RenderData.pCurrentMonData->m_shBORDER1.gradientLength = glGetUniformLocation(prog, "gradientLength"); + m_RenderData.pCurrentMonData->m_shBORDER1.gradient2Length = glGetUniformLocation(prog, "gradient2Length"); m_RenderData.pCurrentMonData->m_shBORDER1.angle = glGetUniformLocation(prog, "angle"); + m_RenderData.pCurrentMonData->m_shBORDER1.angle2 = glGetUniformLocation(prog, "angle2"); + m_RenderData.pCurrentMonData->m_shBORDER1.gradientLerp = glGetUniformLocation(prog, "gradientLerp"); m_RenderData.pCurrentMonData->m_shBORDER1.alpha = glGetUniformLocation(prog, "alpha"); m_RenderData.pCurrentMonData->m_bShadersInitialized = true; @@ -1167,7 +1179,7 @@ void CHyprOpenGLImpl::applyScreenShader(const std::string& path) { m_sFinalScreenShader.posAttrib = glGetAttribLocation(m_sFinalScreenShader.program, "pos"); } -void CHyprOpenGLImpl::clear(const CColor& color) { +void CHyprOpenGLImpl::clear(const CHyprColor& color) { RASSERT(m_RenderData.pMonitor, "Tried to render without begin()!"); TRACY_GPU_ZONE("RenderClear"); @@ -1231,12 +1243,12 @@ void CHyprOpenGLImpl::scissor(const int x, const int y, const int w, const int h scissor(&box, transform); } -void CHyprOpenGLImpl::renderRect(CBox* box, const CColor& col, int round) { +void CHyprOpenGLImpl::renderRect(CBox* box, const CHyprColor& col, int round) { if (!m_RenderData.damage.empty()) renderRectWithDamage(box, col, &m_RenderData.damage, round); } -void CHyprOpenGLImpl::renderRectWithBlur(CBox* box, const CColor& col, int round, float blurA, bool xray) { +void CHyprOpenGLImpl::renderRectWithBlur(CBox* box, const CHyprColor& col, int round, float blurA, bool xray) { if (m_RenderData.damage.empty()) return; @@ -1258,7 +1270,7 @@ void CHyprOpenGLImpl::renderRectWithBlur(CBox* box, const CColor& col, int round glStencilOp(GL_KEEP, GL_KEEP, GL_REPLACE); glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE); - renderRect(box, CColor(0, 0, 0, 0), round); + renderRect(box, CHyprColor(0, 0, 0, 0), round); glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE); glStencilFunc(GL_EQUAL, 1, 0xFF); @@ -1283,7 +1295,7 @@ void CHyprOpenGLImpl::renderRectWithBlur(CBox* box, const CColor& col, int round renderRectWithDamage(box, col, &m_RenderData.damage, round); } -void CHyprOpenGLImpl::renderRectWithDamage(CBox* box, const CColor& col, CRegion* damage, int round) { +void CHyprOpenGLImpl::renderRectWithDamage(CBox* box, const CHyprColor& col, CRegion* damage, int round) { RASSERT((box->width > 0 && box->height > 0), "Tried to render rect with width/height < 0!"); RASSERT(m_RenderData.pMonitor, "Tried to render rect without begin()!"); @@ -1981,7 +1993,7 @@ void CHyprOpenGLImpl::preBlurForCurrentMonitor() { m_RenderData.pMonitor->output->state->state().drmFormat); m_RenderData.pCurrentMonData->blurFB.bind(); - clear(CColor(0, 0, 0, 0)); + clear(CHyprColor(0, 0, 0, 0)); m_bEndFrame = true; // fix transformed renderTextureInternalWithDamage(POUTFB->getTexture(), &wholeMonitor, 1, &fakeDamage, 0, false, true, false); @@ -2100,7 +2112,7 @@ void CHyprOpenGLImpl::renderTextureWithBlur(SP tex, CBox* pBox, float glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE); if (USENEWOPTIMIZE && !(m_RenderData.discardMode & DISCARD_ALPHA)) - renderRect(pBox, CColor(0, 0, 0, 0), round); + renderRect(pBox, CHyprColor(0, 0, 0, 0), round); else renderTexture(tex, pBox, a, round, true, true); // discard opaque glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE); @@ -2184,12 +2196,107 @@ void CHyprOpenGLImpl::renderBorder(CBox* box, const CGradientValueData& grad, in glUniformMatrix3fv(m_RenderData.pCurrentMonData->m_shBORDER1.proj, 1, GL_FALSE, glMatrix.getMatrix().data()); #endif - static_assert(sizeof(CColor) == 4 * sizeof(float)); // otherwise the line below this will fail - - glUniform4fv(m_RenderData.pCurrentMonData->m_shBORDER1.gradient, grad.m_vColors.size(), (float*)grad.m_vColors.data()); - glUniform1i(m_RenderData.pCurrentMonData->m_shBORDER1.gradientLength, grad.m_vColors.size()); + glUniform4fv(m_RenderData.pCurrentMonData->m_shBORDER1.gradient, grad.m_vColorsOkLabA.size(), (float*)grad.m_vColorsOkLabA.data()); + glUniform1i(m_RenderData.pCurrentMonData->m_shBORDER1.gradientLength, grad.m_vColorsOkLabA.size() / 4); glUniform1f(m_RenderData.pCurrentMonData->m_shBORDER1.angle, (int)(grad.m_fAngle / (PI / 180.0)) % 360 * (PI / 180.0)); glUniform1f(m_RenderData.pCurrentMonData->m_shBORDER1.alpha, a); + glUniform1i(m_RenderData.pCurrentMonData->m_shBORDER1.gradient2Length, 0); + + CBox transformedBox = *box; + transformedBox.transform(wlTransformToHyprutils(invertTransform(m_RenderData.pMonitor->transform)), m_RenderData.pMonitor->vecTransformedSize.x, + m_RenderData.pMonitor->vecTransformedSize.y); + + const auto TOPLEFT = Vector2D(transformedBox.x, transformedBox.y); + const auto FULLSIZE = Vector2D(transformedBox.width, transformedBox.height); + + glUniform2f(m_RenderData.pCurrentMonData->m_shBORDER1.topLeft, (float)TOPLEFT.x, (float)TOPLEFT.y); + glUniform2f(m_RenderData.pCurrentMonData->m_shBORDER1.fullSize, (float)FULLSIZE.x, (float)FULLSIZE.y); + glUniform2f(m_RenderData.pCurrentMonData->m_shBORDER1.fullSizeUntransformed, (float)box->width, (float)box->height); + glUniform1f(m_RenderData.pCurrentMonData->m_shBORDER1.radius, round); + glUniform1f(m_RenderData.pCurrentMonData->m_shBORDER1.radiusOuter, outerRound == -1 ? round : outerRound); + glUniform1f(m_RenderData.pCurrentMonData->m_shBORDER1.thick, scaledBorderSize); + + glVertexAttribPointer(m_RenderData.pCurrentMonData->m_shBORDER1.posAttrib, 2, GL_FLOAT, GL_FALSE, 0, fullVerts); + glVertexAttribPointer(m_RenderData.pCurrentMonData->m_shBORDER1.texAttrib, 2, GL_FLOAT, GL_FALSE, 0, fullVerts); + + glEnableVertexAttribArray(m_RenderData.pCurrentMonData->m_shBORDER1.posAttrib); + glEnableVertexAttribArray(m_RenderData.pCurrentMonData->m_shBORDER1.texAttrib); + + if (m_RenderData.clipBox.width != 0 && m_RenderData.clipBox.height != 0) { + CRegion damageClip{m_RenderData.clipBox.x, m_RenderData.clipBox.y, m_RenderData.clipBox.width, m_RenderData.clipBox.height}; + damageClip.intersect(m_RenderData.damage); + + if (!damageClip.empty()) { + for (auto const& RECT : damageClip.getRects()) { + scissor(&RECT); + glDrawArrays(GL_TRIANGLE_STRIP, 0, 4); + } + } + } else { + for (auto const& RECT : m_RenderData.damage.getRects()) { + scissor(&RECT); + glDrawArrays(GL_TRIANGLE_STRIP, 0, 4); + } + } + + glDisableVertexAttribArray(m_RenderData.pCurrentMonData->m_shBORDER1.posAttrib); + glDisableVertexAttribArray(m_RenderData.pCurrentMonData->m_shBORDER1.texAttrib); + + blend(BLEND); +} + +void CHyprOpenGLImpl::renderBorder(CBox* box, const CGradientValueData& grad1, const CGradientValueData& grad2, float lerp, int round, int borderSize, float a, int outerRound) { + RASSERT((box->width > 0 && box->height > 0), "Tried to render rect with width/height < 0!"); + RASSERT(m_RenderData.pMonitor, "Tried to render rect without begin()!"); + + TRACY_GPU_ZONE("RenderBorder2"); + + if (m_RenderData.damage.empty() || (m_pCurrentWindow.lock() && m_pCurrentWindow->m_sWindowData.noBorder.valueOrDefault())) + return; + + CBox newBox = *box; + m_RenderData.renderModif.applyToBox(newBox); + + box = &newBox; + + if (borderSize < 1) + return; + + int scaledBorderSize = std::round(borderSize * m_RenderData.pMonitor->scale); + scaledBorderSize = std::round(scaledBorderSize * m_RenderData.renderModif.combinedScale()); + + // adjust box + box->x -= scaledBorderSize; + box->y -= scaledBorderSize; + box->width += 2 * scaledBorderSize; + box->height += 2 * scaledBorderSize; + + round += round == 0 ? 0 : scaledBorderSize; + + Mat3x3 matrix = m_RenderData.monitorProjection.projectBox( + newBox, wlTransformToHyprutils(invertTransform(!m_bEndFrame ? WL_OUTPUT_TRANSFORM_NORMAL : m_RenderData.pMonitor->transform)), newBox.rot); + Mat3x3 glMatrix = m_RenderData.projection.copy().multiply(matrix); + + const auto BLEND = m_bBlend; + blend(true); + + glUseProgram(m_RenderData.pCurrentMonData->m_shBORDER1.program); + +#ifndef GLES2 + glUniformMatrix3fv(m_RenderData.pCurrentMonData->m_shBORDER1.proj, 1, GL_TRUE, glMatrix.getMatrix().data()); +#else + glMatrix.transpose(); + glUniformMatrix3fv(m_RenderData.pCurrentMonData->m_shBORDER1.proj, 1, GL_FALSE, glMatrix.getMatrix().data()); +#endif + + glUniform4fv(m_RenderData.pCurrentMonData->m_shBORDER1.gradient, grad1.m_vColorsOkLabA.size(), (float*)grad1.m_vColorsOkLabA.data()); + glUniform1i(m_RenderData.pCurrentMonData->m_shBORDER1.gradientLength, grad1.m_vColorsOkLabA.size() / 4); + glUniform1f(m_RenderData.pCurrentMonData->m_shBORDER1.angle, (int)(grad1.m_fAngle / (PI / 180.0)) % 360 * (PI / 180.0)); + glUniform4fv(m_RenderData.pCurrentMonData->m_shBORDER1.gradient2, grad2.m_vColorsOkLabA.size(), (float*)grad2.m_vColorsOkLabA.data()); + glUniform1i(m_RenderData.pCurrentMonData->m_shBORDER1.gradient2Length, grad2.m_vColorsOkLabA.size() / 4); + glUniform1f(m_RenderData.pCurrentMonData->m_shBORDER1.angle2, (int)(grad2.m_fAngle / (PI / 180.0)) % 360 * (PI / 180.0)); + glUniform1f(m_RenderData.pCurrentMonData->m_shBORDER1.alpha, a); + glUniform1f(m_RenderData.pCurrentMonData->m_shBORDER1.gradientLerp, lerp); CBox transformedBox = *box; transformedBox.transform(wlTransformToHyprutils(invertTransform(m_RenderData.pMonitor->transform)), m_RenderData.pMonitor->vecTransformedSize.x, @@ -2253,7 +2360,7 @@ void CHyprOpenGLImpl::makeRawWindowSnapshot(PHLWINDOW pWindow, CFramebuffer* pFr g_pHyprRenderer->beginRender(PMONITOR, fakeDamage, RENDER_MODE_FULL_FAKE, nullptr, pFramebuffer); - clear(CColor(0, 0, 0, 0)); // JIC + clear(CHyprColor(0, 0, 0, 0)); // JIC timespec now; clock_gettime(CLOCK_MONOTONIC, &now); @@ -2272,7 +2379,7 @@ void CHyprOpenGLImpl::makeRawWindowSnapshot(PHLWINDOW pWindow, CFramebuffer* pFr m_RenderData.currentFB = pFramebuffer; - clear(CColor(0, 0, 0, 0)); // JIC + clear(CHyprColor(0, 0, 0, 0)); // JIC g_pHyprRenderer->renderWindow(pWindow, PMONITOR, &now, false, RENDER_PASS_ALL, true); @@ -2308,7 +2415,7 @@ void CHyprOpenGLImpl::makeWindowSnapshot(PHLWINDOW pWindow) { g_pHyprRenderer->m_bRenderingSnapshot = true; - clear(CColor(0, 0, 0, 0)); // JIC + clear(CHyprColor(0, 0, 0, 0)); // JIC timespec now; clock_gettime(CLOCK_MONOTONIC, &now); @@ -2322,7 +2429,7 @@ void CHyprOpenGLImpl::makeWindowSnapshot(PHLWINDOW pWindow) { const auto BLURVAL = **PBLUR; **PBLUR = 0; - clear(CColor(0, 0, 0, 0)); // JIC + clear(CHyprColor(0, 0, 0, 0)); // JIC g_pHyprRenderer->renderWindow(pWindow, PMONITOR, &now, !pWindow->m_bX11DoesntWantBorders, RENDER_PASS_ALL); @@ -2355,7 +2462,7 @@ void CHyprOpenGLImpl::makeLayerSnapshot(PHLLS pLayer) { g_pHyprRenderer->m_bRenderingSnapshot = true; - clear(CColor(0, 0, 0, 0)); // JIC + clear(CHyprColor(0, 0, 0, 0)); // JIC timespec now; clock_gettime(CLOCK_MONOTONIC, &now); @@ -2405,7 +2512,7 @@ void CHyprOpenGLImpl::renderSnapshot(PHLWINDOW pWindow) { if (*PDIMAROUND && pWindow->m_sWindowData.dimAround.valueOrDefault()) { CBox monbox = {0, 0, g_pHyprOpenGL->m_RenderData.pMonitor->vecPixelSize.x, g_pHyprOpenGL->m_RenderData.pMonitor->vecPixelSize.y}; - g_pHyprOpenGL->renderRect(&monbox, CColor(0, 0, 0, *PDIMAROUND * pWindow->m_fAlpha.value())); + g_pHyprOpenGL->renderRect(&monbox, CHyprColor(0, 0, 0, *PDIMAROUND * pWindow->m_fAlpha.value())); g_pHyprRenderer->damageMonitor(PMONITOR); } @@ -2449,7 +2556,7 @@ void CHyprOpenGLImpl::renderSnapshot(PHLLS pLayer) { m_bEndFrame = false; } -void CHyprOpenGLImpl::renderRoundedShadow(CBox* box, int round, int range, const CColor& color, float a) { +void CHyprOpenGLImpl::renderRoundedShadow(CBox* box, int round, int range, const CHyprColor& color, float a) { RASSERT(m_RenderData.pMonitor, "Tried to render shadow without begin()!"); RASSERT((box->width > 0 && box->height > 0), "Tried to render shadow with width/height < 0!"); RASSERT(m_pCurrentWindow.lock(), "Tried to render shadow without a window!"); @@ -2568,7 +2675,7 @@ void CHyprOpenGLImpl::renderMirrored() { .translate(-monitor->vecTransformedSize / 2.0); // clear stuff outside of mirrored area (e.g. when changing to mirrored) - clear(CColor(0, 0, 0, 0)); + clear(CHyprColor(0, 0, 0, 0)); renderTexture(PFB->getTexture(), &monbox, 1.f, 0, false, false); @@ -2583,7 +2690,7 @@ void CHyprOpenGLImpl::renderSplash(cairo_t* const CAIRO, cairo_surface_t* const const auto FONTFAMILY = *PSPLASHFONT != STRVAL_EMPTY ? *PSPLASHFONT : *FALLBACKFONT; const auto FONTSIZE = (int)(size.y / 76); - const auto COLOR = CColor(*PSPLASHCOLOR); + const auto COLOR = CHyprColor(*PSPLASHCOLOR); PangoLayout* layoutText = pango_cairo_create_layout(CAIRO); PangoFontDescription* pangoFD = pango_font_description_new(); @@ -2671,7 +2778,7 @@ SP CHyprOpenGLImpl::loadAsset(const std::string& filename) { return tex; } -SP CHyprOpenGLImpl::renderText(const std::string& text, CColor col, int pt, bool italic) { +SP CHyprOpenGLImpl::renderText(const std::string& text, CHyprColor col, int pt, bool italic) { SP tex = makeShared(); static auto FONT = CConfigValue("misc:font_family"); @@ -2804,7 +2911,7 @@ void CHyprOpenGLImpl::initAssets() { g_pCompositor->m_pAqBackend->hasSession() && g_pCompositor->m_pAqBackend->session->vt > 0 ? std::to_string(g_pCompositor->m_pAqBackend->session->vt) : "unknown"), - CColor{0.9F, 0.9F, 0.9F, 0.7F}, 20, true); + CHyprColor{0.9F, 0.9F, 0.9F, 0.7F}, 20, true); // create the default background texture { @@ -2889,7 +2996,7 @@ void CHyprOpenGLImpl::createBGTextureForMonitor(PHLMONITOR pMonitor) { CRegion fakeDamage{0, 0, INT16_MAX, INT16_MAX}; blend(true); - clear(CColor{0, 0, 0, 1}); + clear(CHyprColor{0, 0, 0, 1}); // first render the background if (m_pBackgroundTexture) { @@ -2981,7 +3088,7 @@ void CHyprOpenGLImpl::restoreMatrix() { void CHyprOpenGLImpl::bindOffMain() { m_RenderData.pCurrentMonData->offMainFB.bind(); - clear(CColor(0, 0, 0, 0)); + clear(CHyprColor(0, 0, 0, 0)); m_RenderData.currentFB = &m_RenderData.pCurrentMonData->offMainFB; } diff --git a/src/render/OpenGL.hpp b/src/render/OpenGL.hpp index c594a7cc..6c0632dd 100644 --- a/src/render/OpenGL.hpp +++ b/src/render/OpenGL.hpp @@ -153,15 +153,16 @@ class CHyprOpenGLImpl { void beginSimple(PHLMONITOR, const CRegion& damage, SP rb = nullptr, CFramebuffer* fb = nullptr); void end(); - void renderRect(CBox*, const CColor&, int round = 0); - void renderRectWithBlur(CBox*, const CColor&, int round = 0, float blurA = 1.f, bool xray = false); - void renderRectWithDamage(CBox*, const CColor&, CRegion* damage, int round = 0); + void renderRect(CBox*, const CHyprColor&, int round = 0); + void renderRectWithBlur(CBox*, const CHyprColor&, int round = 0, float blurA = 1.f, bool xray = false); + void renderRectWithDamage(CBox*, const CHyprColor&, CRegion* damage, int round = 0); void renderTexture(SP, CBox*, float a, int round = 0, bool discardActive = false, bool allowCustomUV = false); void renderTextureWithDamage(SP, CBox*, CRegion* damage, float a, int round = 0, bool discardActive = false, bool allowCustomUV = false, SP waitTimeline = nullptr, uint64_t waitPoint = 0); void renderTextureWithBlur(SP, CBox*, float a, SP pSurface, int round = 0, bool blockBlurOptimization = false, float blurA = 1.f); - void renderRoundedShadow(CBox*, int round, int range, const CColor& color, float a = 1.0); + void renderRoundedShadow(CBox*, int round, int range, const CHyprColor& color, float a = 1.0); void renderBorder(CBox*, const CGradientValueData&, int round, int borderSize, float a = 1.0, int outerRound = -1 /* use round */); + void renderBorder(CBox*, const CGradientValueData&, const CGradientValueData&, float lerp, int round, int borderSize, float a = 1.0, int outerRound = -1 /* use round */); void renderTextureMatte(SP tex, CBox* pBox, CFramebuffer& matte); void setMonitorTransformEnabled(bool enabled); @@ -180,7 +181,7 @@ class CHyprOpenGLImpl { void renderSnapshot(PHLLS); bool shouldUseNewBlurOptimizations(PHLLS pLayer, PHLWINDOW pWindow); - void clear(const CColor&); + void clear(const CHyprColor&); void clearWithTex(); void scissor(const CBox*, bool transform = true); void scissor(const pixman_box32*, bool transform = true); @@ -289,7 +290,7 @@ class CHyprOpenGLImpl { void initEGL(bool gbm); EGLDeviceEXT eglDeviceFromDRMFD(int drmFD); SP loadAsset(const std::string& file); - SP renderText(const std::string& text, CColor col, int pt, bool italic = false); + SP renderText(const std::string& text, CHyprColor col, int pt, bool italic = false); void initAssets(); void initMissingAssetTexture(); diff --git a/src/render/Renderer.cpp b/src/render/Renderer.cpp index bba133d9..7e44e64e 100644 --- a/src/render/Renderer.cpp +++ b/src/render/Renderer.cpp @@ -619,7 +619,7 @@ void CHyprRenderer::renderWindow(PHLWINDOW pWindow, PHLMONITOR pMonitor, timespe if (*PDIMAROUND && pWindow->m_sWindowData.dimAround.valueOrDefault() && !m_bRenderingSnapshot && mode != RENDER_PASS_POPUP) { CBox monbox = {0, 0, g_pHyprOpenGL->m_RenderData.pMonitor->vecTransformedSize.x, g_pHyprOpenGL->m_RenderData.pMonitor->vecTransformedSize.y}; - g_pHyprOpenGL->renderRect(&monbox, CColor(0, 0, 0, *PDIMAROUND * renderdata.alpha * renderdata.fadeAlpha)); + g_pHyprOpenGL->renderRect(&monbox, CHyprColor(0, 0, 0, *PDIMAROUND * renderdata.alpha * renderdata.fadeAlpha)); } renderdata.x += pWindow->m_vFloatingOffset.x; @@ -668,7 +668,7 @@ void CHyprRenderer::renderWindow(PHLWINDOW pWindow, PHLMONITOR pMonitor, timespe if (!pWindow->m_sWindowData.noBlur.valueOrDefault() && pWindow->m_pWLSurface->small() && !pWindow->m_pWLSurface->m_bFillIgnoreSmall && renderdata.blur && *PBLUR) { CBox wb = {renderdata.x - pMonitor->vecPosition.x, renderdata.y - pMonitor->vecPosition.y, renderdata.w, renderdata.h}; wb.scale(pMonitor->scale).round(); - g_pHyprOpenGL->renderRectWithBlur(&wb, CColor(0, 0, 0, 0), renderdata.dontRound ? 0 : renderdata.rounding - 1, renderdata.fadeAlpha, + g_pHyprOpenGL->renderRectWithBlur(&wb, CHyprColor(0, 0, 0, 0), renderdata.dontRound ? 0 : renderdata.rounding - 1, renderdata.fadeAlpha, g_pHyprOpenGL->shouldUseNewBlurOptimizations(nullptr, pWindow)); renderdata.blur = false; } @@ -780,7 +780,7 @@ void CHyprRenderer::renderLayer(PHLLS pLayer, PHLMONITOR pMonitor, timespec* tim if (*PDIMAROUND && pLayer->dimAround && !m_bRenderingSnapshot && !popups) { CBox monbox = {0, 0, g_pHyprOpenGL->m_RenderData.pMonitor->vecTransformedSize.x, g_pHyprOpenGL->m_RenderData.pMonitor->vecTransformedSize.y}; - g_pHyprOpenGL->renderRect(&monbox, CColor(0, 0, 0, *PDIMAROUND * pLayer->alpha.value())); + g_pHyprOpenGL->renderRect(&monbox, CHyprColor(0, 0, 0, *PDIMAROUND * pLayer->alpha.value())); } if (pLayer->fadingOut) { @@ -919,7 +919,7 @@ void CHyprRenderer::renderAllClientsForWorkspace(PHLMONITOR pMonitor, PHLWORKSPA g_pHyprOpenGL->blend(false); if (!canSkipBackBufferClear(pMonitor)) { if (*PRENDERTEX /* inverted cfg flag */) - g_pHyprOpenGL->clear(CColor(*PBACKGROUNDCOLOR)); + g_pHyprOpenGL->clear(CHyprColor(*PBACKGROUNDCOLOR)); else g_pHyprOpenGL->clearWithTex(); // will apply the hypr "wallpaper" } @@ -959,7 +959,7 @@ void CHyprRenderer::renderAllClientsForWorkspace(PHLMONITOR pMonitor, PHLWORKSPA g_pHyprOpenGL->blend(false); if (!canSkipBackBufferClear(pMonitor)) { if (*PRENDERTEX /* inverted cfg flag */) - g_pHyprOpenGL->clear(CColor(*PBACKGROUNDCOLOR)); + g_pHyprOpenGL->clear(CHyprColor(*PBACKGROUNDCOLOR)); else g_pHyprOpenGL->clearWithTex(); // will apply the hypr "wallpaper" } @@ -995,12 +995,12 @@ void CHyprRenderer::renderAllClientsForWorkspace(PHLMONITOR pMonitor, PHLWORKSPA if (*PDIMSPECIAL != 0.f) { CBox monbox = {translate.x, translate.y, pMonitor->vecTransformedSize.x * scale, pMonitor->vecTransformedSize.y * scale}; - g_pHyprOpenGL->renderRect(&monbox, CColor(0, 0, 0, *PDIMSPECIAL * (ANIMOUT ? (1.0 - SPECIALANIMPROGRS) : SPECIALANIMPROGRS))); + g_pHyprOpenGL->renderRect(&monbox, CHyprColor(0, 0, 0, *PDIMSPECIAL * (ANIMOUT ? (1.0 - SPECIALANIMPROGRS) : SPECIALANIMPROGRS))); } if (*PBLURSPECIAL && *PBLUR) { CBox monbox = {translate.x, translate.y, pMonitor->vecTransformedSize.x * scale, pMonitor->vecTransformedSize.y * scale}; - g_pHyprOpenGL->renderRectWithBlur(&monbox, CColor(0, 0, 0, 0), 0, (ANIMOUT ? (1.0 - SPECIALANIMPROGRS) : SPECIALANIMPROGRS)); + g_pHyprOpenGL->renderRectWithBlur(&monbox, CHyprColor(0, 0, 0, 0), 0, (ANIMOUT ? (1.0 - SPECIALANIMPROGRS) : SPECIALANIMPROGRS)); } break; @@ -1447,7 +1447,7 @@ void CHyprRenderer::renderMonitor(PHLMONITOR pMonitor) { if (*PDAMAGEBLINK && damageBlinkCleanup == 0) { CBox monrect = {0, 0, pMonitor->vecTransformedSize.x, pMonitor->vecTransformedSize.y}; - g_pHyprOpenGL->renderRect(&monrect, CColor(1.0, 0.0, 1.0, 100.0 / 255.0), 0); + g_pHyprOpenGL->renderRect(&monrect, CHyprColor(1.0, 0.0, 1.0, 100.0 / 255.0), 0); damageBlinkCleanup = 1; } else if (*PDAMAGEBLINK) { damageBlinkCleanup++; @@ -2526,7 +2526,7 @@ std::tuple CHyprRenderer::getRenderTimes(PHLMONITOR pMonito static int handleCrashLoop(void* data) { - g_pHyprNotificationOverlay->addNotification("Hyprland will crash in " + std::to_string(10 - (int)(g_pHyprRenderer->m_fCrashingDistort * 2.f)) + "s.", CColor(0), 5000, + g_pHyprNotificationOverlay->addNotification("Hyprland will crash in " + std::to_string(10 - (int)(g_pHyprRenderer->m_fCrashingDistort * 2.f)) + "s.", CHyprColor(0), 5000, ICON_INFO); g_pHyprRenderer->m_fCrashingDistort += 0.5f; @@ -2540,7 +2540,7 @@ static int handleCrashLoop(void* data) { } void CHyprRenderer::initiateManualCrash() { - g_pHyprNotificationOverlay->addNotification("Manual crash initiated. Farewell...", CColor(0), 5000, ICON_INFO); + g_pHyprNotificationOverlay->addNotification("Manual crash initiated. Farewell...", CHyprColor(0), 5000, ICON_INFO); m_pCrashingLoop = wl_event_loop_add_timer(g_pCompositor->m_sWLEventLoop, handleCrashLoop, nullptr); wl_event_source_timer_update(m_pCrashingLoop, 1000); diff --git a/src/render/Shader.hpp b/src/render/Shader.hpp index d5a312c3..eaf9da96 100644 --- a/src/render/Shader.hpp +++ b/src/render/Shader.hpp @@ -38,9 +38,13 @@ class CShader { GLint applyTint = -1; GLint tint = -1; - GLint gradient = -1; - GLint gradientLength = -1; - GLint angle = -1; + GLint gradient = -1; + GLint gradientLength = -1; + GLint angle = -1; + GLint gradient2 = -1; + GLint gradient2Length = -1; + GLint angle2 = -1; + GLint gradientLerp = -1; float initialTime = 0; GLint time = -1; diff --git a/src/render/decorations/CHyprBorderDecoration.cpp b/src/render/decorations/CHyprBorderDecoration.cpp index d62e67c4..b0de4a64 100644 --- a/src/render/decorations/CHyprBorderDecoration.cpp +++ b/src/render/decorations/CHyprBorderDecoration.cpp @@ -60,7 +60,6 @@ void CHyprBorderDecoration::draw(PHLMONITOR pMonitor, float const& a) { auto grad = m_pWindow->m_cRealBorderColor; const bool ANIMATED = m_pWindow->m_fBorderFadeAnimationProgress.isBeingAnimated(); - float a1 = a * (ANIMATED ? m_pWindow->m_fBorderFadeAnimationProgress.value() : 1.f); if (m_pWindow->m_fBorderAngleAnimationProgress.getConfig()->pValues->internalEnabled) { grad.m_fAngle += m_pWindow->m_fBorderAngleAnimationProgress.value() * M_PI * 2; @@ -70,12 +69,10 @@ void CHyprBorderDecoration::draw(PHLMONITOR pMonitor, float const& a) { int borderSize = m_pWindow->getRealBorderSize(); const auto ROUNDING = m_pWindow->rounding() * pMonitor->scale; - g_pHyprOpenGL->renderBorder(&windowBox, grad, ROUNDING, borderSize, a1); - - if (ANIMATED) { - float a2 = a * (1.f - m_pWindow->m_fBorderFadeAnimationProgress.value()); - g_pHyprOpenGL->renderBorder(&windowBox, m_pWindow->m_cRealBorderColorPrevious, ROUNDING, borderSize, a2); - } + if (ANIMATED) + g_pHyprOpenGL->renderBorder(&windowBox, m_pWindow->m_cRealBorderColorPrevious, grad, m_pWindow->m_fBorderFadeAnimationProgress.value(), ROUNDING, borderSize, a); + else + g_pHyprOpenGL->renderBorder(&windowBox, grad, ROUNDING, borderSize, a); } eDecorationType CHyprBorderDecoration::getDecorationType() { diff --git a/src/render/decorations/CHyprDropShadowDecoration.cpp b/src/render/decorations/CHyprDropShadowDecoration.cpp index 893ad498..39398878 100644 --- a/src/render/decorations/CHyprDropShadowDecoration.cpp +++ b/src/render/decorations/CHyprDropShadowDecoration.cpp @@ -93,7 +93,7 @@ void CHyprDropShadowDecoration::draw(PHLMONITOR pMonitor, float const& a) { if (!validMapped(PWINDOW)) return; - if (PWINDOW->m_cRealShadowColor.value() == CColor(0, 0, 0, 0)) + if (PWINDOW->m_cRealShadowColor.value() == CHyprColor(0, 0, 0, 0)) return; // don't draw invisible shadows if (!PWINDOW->m_sWindowData.decorate.valueOrDefault()) @@ -181,13 +181,13 @@ void CHyprDropShadowDecoration::draw(PHLMONITOR pMonitor, float const& a) { // build the matte // 10-bit formats have dogshit alpha channels, so we have to use the matte to its fullest. // first, clear region of interest with black (fully transparent) - g_pHyprOpenGL->renderRect(&fullBox, CColor(0, 0, 0, 1), 0); + g_pHyprOpenGL->renderRect(&fullBox, CHyprColor(0, 0, 0, 1), 0); // render white shadow with the alpha of the shadow color (otherwise we clear with alpha later and shit it to 2 bit) - drawShadowInternal(&fullBox, ROUNDING * pMonitor->scale, *PSHADOWSIZE * pMonitor->scale, CColor(1, 1, 1, PWINDOW->m_cRealShadowColor.value().a), a); + drawShadowInternal(&fullBox, ROUNDING * pMonitor->scale, *PSHADOWSIZE * pMonitor->scale, CHyprColor(1, 1, 1, PWINDOW->m_cRealShadowColor.value().a), a); // render black window box ("clip") - g_pHyprOpenGL->renderRect(&windowBox, CColor(0, 0, 0, 1.0), (ROUNDING + 1 /* This fixes small pixel gaps. */) * pMonitor->scale); + g_pHyprOpenGL->renderRect(&windowBox, CHyprColor(0, 0, 0, 1.0), (ROUNDING + 1 /* This fixes small pixel gaps. */) * pMonitor->scale); alphaSwapFB.bind(); @@ -215,7 +215,7 @@ eDecorationLayer CHyprDropShadowDecoration::getDecorationLayer() { return DECORATION_LAYER_BOTTOM; } -void CHyprDropShadowDecoration::drawShadowInternal(CBox* box, int round, int range, CColor color, float a) { +void CHyprDropShadowDecoration::drawShadowInternal(CBox* box, int round, int range, CHyprColor color, float a) { static auto PSHADOWSHARP = CConfigValue("decoration:shadow:sharp"); g_pHyprOpenGL->blend(true); diff --git a/src/render/decorations/CHyprDropShadowDecoration.hpp b/src/render/decorations/CHyprDropShadowDecoration.hpp index 933ee0ef..650f8c92 100644 --- a/src/render/decorations/CHyprDropShadowDecoration.hpp +++ b/src/render/decorations/CHyprDropShadowDecoration.hpp @@ -34,7 +34,7 @@ class CHyprDropShadowDecoration : public IHyprWindowDecoration { Vector2D m_vLastWindowPos; Vector2D m_vLastWindowSize; - void drawShadowInternal(CBox* box, int round, int range, CColor color, float a); + void drawShadowInternal(CBox* box, int round, int range, CHyprColor color, float a); CBox m_bLastWindowBox = {0}; CBox m_bLastWindowBoxWithDecos = {0}; diff --git a/src/render/decorations/CHyprGroupBarDecoration.cpp b/src/render/decorations/CHyprGroupBarDecoration.cpp index b5189be5..937c913d 100644 --- a/src/render/decorations/CHyprGroupBarDecoration.cpp +++ b/src/render/decorations/CHyprGroupBarDecoration.cpp @@ -147,7 +147,7 @@ void CHyprGroupBarDecoration::draw(PHLMONITOR pMonitor, float const& a) { const auto* const PCOLACTIVE = GROUPLOCKED ? GROUPCOLACTIVELOCKED : GROUPCOLACTIVE; const auto* const PCOLINACTIVE = GROUPLOCKED ? GROUPCOLINACTIVELOCKED : GROUPCOLINACTIVE; - CColor color = m_dwGroupMembers[WINDOWINDEX].lock() == g_pCompositor->m_pLastWindow.lock() ? PCOLACTIVE->m_vColors[0] : PCOLINACTIVE->m_vColors[0]; + CHyprColor color = m_dwGroupMembers[WINDOWINDEX].lock() == g_pCompositor->m_pLastWindow.lock() ? PCOLACTIVE->m_vColors[0] : PCOLINACTIVE->m_vColors[0]; color.a *= a; g_pHyprOpenGL->renderRect(&rect, color); @@ -205,19 +205,19 @@ void CHyprGroupBarDecoration::invalidateTextures() { } CTitleTex::CTitleTex(PHLWINDOW pWindow, const Vector2D& bufferSize, const float monitorScale) { - tex = makeShared(); - szContent = pWindow->m_szTitle; - pWindowOwner = pWindow; - const auto LAYOUTSURFACE = cairo_image_surface_create(CAIRO_FORMAT_ARGB32, 0, 0); - const auto LAYOUTCAIRO = cairo_create(LAYOUTSURFACE); + tex = makeShared(); + szContent = pWindow->m_szTitle; + pWindowOwner = pWindow; + const auto LAYOUTSURFACE = cairo_image_surface_create(CAIRO_FORMAT_ARGB32, 0, 0); + const auto LAYOUTCAIRO = cairo_create(LAYOUTSURFACE); - static auto FALLBACKFONT = CConfigValue("misc:font_family"); - static auto PTITLEFONTFAMILY = CConfigValue("group:groupbar:font_family"); - static auto PTITLEFONTSIZE = CConfigValue("group:groupbar:font_size"); - static auto PTEXTCOLOR = CConfigValue("group:groupbar:text_color"); + static auto FALLBACKFONT = CConfigValue("misc:font_family"); + static auto PTITLEFONTFAMILY = CConfigValue("group:groupbar:font_family"); + static auto PTITLEFONTSIZE = CConfigValue("group:groupbar:font_size"); + static auto PTEXTCOLOR = CConfigValue("group:groupbar:text_color"); - const CColor COLOR = CColor(*PTEXTCOLOR); - const auto FONTFAMILY = *PTITLEFONTFAMILY != STRVAL_EMPTY ? *PTITLEFONTFAMILY : *FALLBACKFONT; + const CHyprColor COLOR = CHyprColor(*PTEXTCOLOR); + const auto FONTFAMILY = *PTITLEFONTFAMILY != STRVAL_EMPTY ? *PTITLEFONTFAMILY : *FALLBACKFONT; cairo_surface_destroy(LAYOUTSURFACE); diff --git a/src/render/shaders/Border.hpp b/src/render/shaders/Border.hpp index 1f4a1d97..acd3f3ff 100644 --- a/src/render/shaders/Border.hpp +++ b/src/render/shaders/Border.hpp @@ -17,12 +17,32 @@ uniform float radius; uniform float radiusOuter; uniform float thick; +// Gradients are in OkLabA!!!! {l, a, b, alpha} uniform vec4 gradient[10]; +uniform vec4 gradient2[10]; uniform int gradientLength; +uniform int gradient2Length; uniform float angle; +uniform float angle2; +uniform float gradientLerp; uniform float alpha; -vec4 getColorForCoord(vec2 normalizedCoord) { +float linearToGamma(float x) { + return x >= 0.0031308 ? 1.055 * pow(x, 0.416666666) - 0.055 : 12.92 * x; +} + +vec4 okLabAToSrgb(vec4 lab) { + float l = pow(lab[0] + lab[1] * 0.3963377774 + lab[2] * 0.2158037573, 3.0); + float m = pow(lab[0] + lab[1] * (-0.1055613458) + lab[2] * (-0.0638541728), 3.0); + float s = pow(lab[0] + lab[1] * (-0.0894841775) + lab[2] * (-1.2914855480), 3.0); + + return vec4(linearToGamma(l * 4.0767416621 + m * -3.3077115913 + s * 0.2309699292), + linearToGamma(l * (-1.2684380046) + m * 2.6097574011 + s * (-0.3413193965)), + linearToGamma(l * (-0.0041960863) + m * (-0.7034186147) + s * 1.7076147010), + lab[3]); +} + +vec4 getOkColorForCoordArray1(vec2 normalizedCoord) { if (gradientLength < 2) return gradient[0]; @@ -51,6 +71,46 @@ vec4 getColorForCoord(vec2 normalizedCoord) { return gradient[top] * (progress - float(bottom)) + gradient[bottom] * (float(top) - progress); } +vec4 getOkColorForCoordArray2(vec2 normalizedCoord) { + if (gradient2Length < 2) + return gradient2[0]; + + float finalAng = 0.0; + + if (angle2 > 4.71 /* 270 deg */) { + normalizedCoord[1] = 1.0 - normalizedCoord[1]; + finalAng = 6.28 - angle; + } else if (angle2 > 3.14 /* 180 deg */) { + normalizedCoord[0] = 1.0 - normalizedCoord[0]; + normalizedCoord[1] = 1.0 - normalizedCoord[1]; + finalAng = angle - 3.14; + } else if (angle2 > 1.57 /* 90 deg */) { + normalizedCoord[0] = 1.0 - normalizedCoord[0]; + finalAng = 3.14 - angle2; + } else { + finalAng = angle2; + } + + float sine = sin(finalAng); + + float progress = (normalizedCoord[1] * sine + normalizedCoord[0] * (1.0 - sine)) * float(gradient2Length - 1); + int bottom = int(floor(progress)); + int top = bottom + 1; + + return gradient2[top] * (progress - float(bottom)) + gradient2[bottom] * (float(top) - progress); +} + +vec4 getColorForCoord(vec2 normalizedCoord) { + vec4 result1 = getOkColorForCoordArray1(normalizedCoord); + + if (gradient2Length <= 0) + return okLabAToSrgb(result1); + + vec4 result2 = getOkColorForCoordArray2(normalizedCoord); + + return okLabAToSrgb(mix(result1, result2, gradientLerp)); +} + void main() { highp vec2 pixCoord = vec2(gl_FragCoord); From f6ac755cf76750b8ee53389c54ef653590462c1c Mon Sep 17 00:00:00 2001 From: vaxerski Date: Tue, 3 Dec 2024 21:15:25 +0000 Subject: [PATCH 0693/2181] cleanup: Revert use doLater instead of adding idle event handlers (#8624) This reverts commit 6d7544458d0fafcae410c1978a0cabce2fb4a346. --- src/protocols/Tablet.cpp | 26 ++++++++++++++------------ src/protocols/Tablet.hpp | 7 ++++--- src/protocols/XDGShell.cpp | 18 +++++++++--------- src/protocols/XDGShell.hpp | 8 ++++---- src/xwayland/Server.cpp | 12 ++++++++---- 5 files changed, 39 insertions(+), 32 deletions(-) diff --git a/src/protocols/Tablet.cpp b/src/protocols/Tablet.cpp index 7768402b..d7f741b9 100644 --- a/src/protocols/Tablet.cpp +++ b/src/protocols/Tablet.cpp @@ -2,7 +2,6 @@ #include "../devices/Tablet.hpp" #include "../Compositor.hpp" #include "../managers/SeatManager.hpp" -#include "../managers/eventLoop/EventLoopManager.hpp" #include "core/Seat.hpp" #include "core/Compositor.hpp" #include @@ -163,6 +162,11 @@ CTabletToolV2Resource::CTabletToolV2Resource(SP resource_, SP< }); } +CTabletToolV2Resource::~CTabletToolV2Resource() { + if (frameSource) + wl_event_source_remove(frameSource); +} + bool CTabletToolV2Resource::good() { return resource->resource(); } @@ -201,22 +205,20 @@ void CTabletToolV2Resource::sendData() { } void CTabletToolV2Resource::queueFrame() { - if (frameQueued) + if (frameSource) return; - frameQueued = true; - g_pEventLoopManager->doLater([this]() { - if (!frameQueued || tool.expired() || inert) - return; - - sendFrame(); - }); + frameSource = wl_event_loop_add_idle(g_pCompositor->m_sWLEventLoop, [](void* data) { ((CTabletToolV2Resource*)data)->sendFrame(false); }, this); } -void CTabletToolV2Resource::sendFrame() { - frameQueued = false; +void CTabletToolV2Resource::sendFrame(bool removeSource) { + if (frameSource) { + if (removeSource) + wl_event_source_remove(frameSource); + frameSource = nullptr; + } - if (!current || !resource) + if (!current) return; timespec now; diff --git a/src/protocols/Tablet.hpp b/src/protocols/Tablet.hpp index 8c99bee0..1ebcb1e5 100644 --- a/src/protocols/Tablet.hpp +++ b/src/protocols/Tablet.hpp @@ -112,20 +112,21 @@ class CTabletV2Resource { class CTabletToolV2Resource { public: CTabletToolV2Resource(SP resource_, SP tool_, SP seat_); + ~CTabletToolV2Resource(); bool good(); void sendData(); void queueFrame(); - void sendFrame(); + void sendFrame(bool removeSource = true); bool current = false; WP lastSurf; WP tool; WP seat; + wl_event_source* frameSource = nullptr; - bool frameQueued = false; - bool inert = false; // removed was sent + bool inert = false; // removed was sent private: SP resource; diff --git a/src/protocols/XDGShell.cpp b/src/protocols/XDGShell.cpp index a542c394..688d0006 100644 --- a/src/protocols/XDGShell.cpp +++ b/src/protocols/XDGShell.cpp @@ -3,7 +3,6 @@ #include #include "../Compositor.hpp" #include "../managers/SeatManager.hpp" -#include "../managers/eventLoop/EventLoopManager.hpp" #include "core/Seat.hpp" #include "core/Compositor.hpp" #include @@ -470,6 +469,8 @@ CXDGSurfaceResource::CXDGSurfaceResource(SP resource_, SPresetRole(); } @@ -483,23 +484,22 @@ SP CXDGSurfaceResource::fromResource(wl_resource* res) { return data ? data->self.lock() : nullptr; } +static void onConfigure(void* data) { + ((CXDGSurfaceResource*)data)->configure(); +} + uint32_t CXDGSurfaceResource::scheduleConfigure() { - if (configureScheduled) + if (configureSource) return scheduledSerial; + configureSource = wl_event_loop_add_idle(g_pCompositor->m_sWLEventLoop, onConfigure, this); scheduledSerial = wl_display_next_serial(g_pCompositor->m_sWLDisplay); - configureScheduled = true; - g_pEventLoopManager->doLater([this]() { configure(); }); - return scheduledSerial; } void CXDGSurfaceResource::configure() { - if (!resource) - return; - - configureScheduled = false; + configureSource = nullptr; resource->sendConfigure(scheduledSerial); } diff --git a/src/protocols/XDGShell.hpp b/src/protocols/XDGShell.hpp index 3b7d2d11..ef847f3b 100644 --- a/src/protocols/XDGShell.hpp +++ b/src/protocols/XDGShell.hpp @@ -199,12 +199,12 @@ class CXDGSurfaceResource { void configure(); private: - SP resource; + SP resource; - uint32_t lastConfigureSerial = 0; - uint32_t scheduledSerial = 0; + uint32_t lastConfigureSerial = 0; + uint32_t scheduledSerial = 0; - bool configureScheduled = false; + wl_event_source* configureSource = nullptr; // std::vector> popups; diff --git a/src/xwayland/Server.cpp b/src/xwayland/Server.cpp index 390ce1f6..f356af18 100644 --- a/src/xwayland/Server.cpp +++ b/src/xwayland/Server.cpp @@ -176,6 +176,11 @@ static bool openSockets(std::array& sockets, int display) { return true; } +static void startServer(void* data) { + if (!g_pXWayland->pServer->start()) + Debug::log(ERR, "The XWayland server could not start! XWayland will not work..."); +} + static int xwaylandReady(int fd, uint32_t mask, void* data) { return g_pXWayland->pServer->ready(fd, mask); } @@ -303,10 +308,9 @@ bool CXWaylandServer::create() { setenv("DISPLAY", displayName.c_str(), true); - g_pEventLoopManager->doLater([this]() { - if (!start()) - Debug::log(ERR, "The XWayland server could not start! XWayland will not work..."); - }); + // TODO: lazy mode + + idleSource = wl_event_loop_add_idle(g_pCompositor->m_sWLEventLoop, ::startServer, nullptr); return true; } From 3c617ce33c64cb43049489598b6391911eed7070 Mon Sep 17 00:00:00 2001 From: Vaxry Date: Tue, 3 Dec 2024 22:58:30 +0000 Subject: [PATCH 0694/2181] internal: fixup some missed updateColorsOk() calls --- src/desktop/Window.cpp | 2 ++ src/managers/KeybindManager.cpp | 2 ++ 2 files changed, 4 insertions(+) diff --git a/src/desktop/Window.cpp b/src/desktop/Window.cpp index b015d61f..34682b32 100644 --- a/src/desktop/Window.cpp +++ b/src/desktop/Window.cpp @@ -692,6 +692,8 @@ void CWindow::applyDynamicRule(const SWindowRule& r) { inactiveBorderGradient.m_vColors.push_back(configStringToInt(token).value_or(0)); } + activeBorderGradient.updateColorsOk(); + // Includes sanity checks for the number of colors in each gradient if (activeBorderGradient.m_vColors.size() > 10 || inactiveBorderGradient.m_vColors.size() > 10) Debug::log(WARN, "Bordercolor rule \"{}\" has more than 10 colors in one gradient, ignoring", r.szRule); diff --git a/src/managers/KeybindManager.cpp b/src/managers/KeybindManager.cpp index cfb7453c..153c3c0d 100644 --- a/src/managers/KeybindManager.cpp +++ b/src/managers/KeybindManager.cpp @@ -2997,6 +2997,8 @@ SDispatchResult CKeybindManager::setProp(std::string args) { return std::invoke_result_t(1); }); + colorData.updateColorsOk(); + if (PROP == "activebordercolor") PWINDOW->m_sWindowData.activeBorderColor = CWindowOverridableVar(colorData, PRIORITY_SET_PROP); else From f9e4998a6d7713b19947b0db2c43ad88c5b71d80 Mon Sep 17 00:00:00 2001 From: Mike Will Date: Wed, 4 Dec 2024 13:12:04 -0500 Subject: [PATCH 0695/2181] snap: check which corner is being grabbed for monitor snapping (#8637) --- src/layout/IHyprLayout.cpp | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/src/layout/IHyprLayout.cpp b/src/layout/IHyprLayout.cpp index 8ff55d10..cb1f064b 100644 --- a/src/layout/IHyprLayout.cpp +++ b/src/layout/IHyprLayout.cpp @@ -487,19 +487,23 @@ static void performSnap(Vector2D& sourcePos, Vector2D& sourceSize, PHLWINDOW DRA SRange monX = {MON->vecPosition.x + BORDERSIZE, MON->vecPosition.x + MON->vecSize.x - BORDERSIZE}; SRange monY = {MON->vecPosition.y + BORDERSIZE, MON->vecPosition.y + MON->vecSize.y - BORDERSIZE}; - if (canSnap(sourceX.start, monX.start, GAPSIZE) || canSnap(sourceX.start, (monX.start += MON->vecReservedTopLeft.x + BORDERDIFF), GAPSIZE)) { + if (CORNER & (CORNER_TOPLEFT | CORNER_BOTTOMLEFT) && + (canSnap(sourceX.start, monX.start, GAPSIZE) || canSnap(sourceX.start, (monX.start += MON->vecReservedTopLeft.x + BORDERDIFF), GAPSIZE))) { SNAP(sourceX.start, sourceX.end, monX.start); snaps |= SNAP_LEFT; } - if (canSnap(sourceX.end, monX.end, GAPSIZE) || canSnap(sourceX.end, (monX.end -= MON->vecReservedBottomRight.x + BORDERDIFF), GAPSIZE)) { + if (CORNER & (CORNER_TOPRIGHT | CORNER_BOTTOMRIGHT) && + (canSnap(sourceX.end, monX.end, GAPSIZE) || canSnap(sourceX.end, (monX.end -= MON->vecReservedBottomRight.x + BORDERDIFF), GAPSIZE))) { SNAP(sourceX.end, sourceX.start, monX.end); snaps |= SNAP_RIGHT; } - if (canSnap(sourceY.start, monY.start, GAPSIZE) || canSnap(sourceY.start, (monY.start += MON->vecReservedTopLeft.y + BORDERDIFF), GAPSIZE)) { + if (CORNER & (CORNER_TOPLEFT | CORNER_TOPRIGHT) && + (canSnap(sourceY.start, monY.start, GAPSIZE) || canSnap(sourceY.start, (monY.start += MON->vecReservedTopLeft.y + BORDERDIFF), GAPSIZE))) { SNAP(sourceY.start, sourceY.end, monY.start); snaps |= SNAP_UP; } - if (canSnap(sourceY.end, monY.end, GAPSIZE) || canSnap(sourceY.end, (monY.end -= MON->vecReservedBottomRight.y + BORDERDIFF), GAPSIZE)) { + if (CORNER & (CORNER_BOTTOMLEFT | CORNER_BOTTOMRIGHT) && + (canSnap(sourceY.end, monY.end, GAPSIZE) || canSnap(sourceY.end, (monY.end -= MON->vecReservedBottomRight.y + BORDERDIFF), GAPSIZE))) { SNAP(sourceY.end, sourceY.start, monY.end); snaps |= SNAP_DOWN; } From 22f7d6f1424c296b297df87bf2accdfefac4af33 Mon Sep 17 00:00:00 2001 From: Vaxry Date: Thu, 5 Dec 2024 01:59:29 +0000 Subject: [PATCH 0696/2181] core: add a few festive splashes adds two new 'special' splash types for xmas and new years. Activated based on local time. --- src/Compositor.cpp | 14 ++- src/helpers/Splashes.hpp | 184 +++++++++++++++++++++++---------------- 2 files changed, 120 insertions(+), 78 deletions(-) diff --git a/src/Compositor.cpp b/src/Compositor.cpp index 3573996d..1261d003 100644 --- a/src/Compositor.cpp +++ b/src/Compositor.cpp @@ -206,11 +206,21 @@ CCompositor::~CCompositor() { } void CCompositor::setRandomSplash() { + auto tt = std::chrono::system_clock::to_time_t(std::chrono::system_clock::now()); + auto local = *localtime(&tt); + + const auto* SPLASHES = &NSplashes::SPLASHES; + + if (local.tm_mon + 1 == 12 && local.tm_mday >= 23 && local.tm_mday <= 27) // dec 23-27 + SPLASHES = &NSplashes::SPLASHES_CHRISTMAS; + if ((local.tm_mon + 1 == 12 && local.tm_mday >= 29) || (local.tm_mon + 1 == 1 && local.tm_mday <= 3)) + SPLASHES = &NSplashes::SPLASHES_NEWYEAR; + std::random_device dev; std::mt19937 engine(dev()); - std::uniform_int_distribution<> distribution(0, SPLASHES.size() - 1); + std::uniform_int_distribution<> distribution(0, SPLASHES->size() - 1); - m_szCurrentSplash = SPLASHES[distribution(engine)]; + m_szCurrentSplash = SPLASHES->at(distribution(engine)); } static std::vector> pendingOutputs; diff --git a/src/helpers/Splashes.hpp b/src/helpers/Splashes.hpp index 4a4fd022..2c74abb1 100644 --- a/src/helpers/Splashes.hpp +++ b/src/helpers/Splashes.hpp @@ -3,80 +3,112 @@ #include #include -inline const std::vector SPLASHES = { - // clang-format off - "Woo, animations!", - "It's like Hypr, but better.", - "Release 1.0 when?", - "It's not awesome, it's Hyprland!", - "\"I commit too often, people can't catch up lmao\" - Vaxry", - "This text is random.", - "\"There are reasons to not use rust.\" - Boga", - "Read the wiki.", - "\"Hello everyone this is YOUR daily dose of ‘read the wiki’\" - Vaxry", - "h", - "\"‘why no work’, bro I haven't hacked your pc to get live feeds yet\" - Vaxry", - "Compile, wait for 20 minutes, notice a new commit, compile again.", - "To rice, or not to rice, that is the question.", - "Now available on Fedora!", - "\"Hyprland is so good it starts with a capital letter\" - Hazel", - "\"please make this message a splash\" - eriedaberrie", - "\"the only wayland compositor powered by fried chicken\" - raf", - "\"This will never get into Hyprland\" - Flafy", - "\"Hyprland only gives you up on -git\" - fazzi", - "Segmentation fault (core dumped)", - "\"disabling hyprland logo is a war crime\" - vaxry", - "some basic startup code", - "\"I think I am addicted to hyprland\" - mathisbuilder", - "\"hyprland is the most important package in the arch repos\" - jacekpoz", - "Thanks Brodie!", - "Thanks fufexan!", - "Thanks raf!", - "You can't use --splash to change this message :)", - "Hyprland will overtake Gnome in popularity by [insert year]", - // music reference / quote section - "J'remue le ciel, le jour, la nuit.", - "aezakmi, aezakmi, aezakmi, aezakmi, aezakmi, aezakmi, aezakmi!", - "Wir sind schon sehr lang zusammen...", - "I see a red door and I want it painted black.", - "Take on me, take me on...", - "You spin me right round baby right round", - "Stayin' alive, stayin' alive", - "Say no way, say no way ya, no way!", - "Ground control to Major Tom...", - "Alors on danse", - "And all that I can see, is just a yellow lemon tree.", - "Got a one-way ticket to the blues", - "Is this the real life, is this just fantasy", - "What's in your head, in your head?", - "We're all living in America, America, America.", - "I'm still standing, better than I ever did", - "Here comes the sun, bringing you love and shining on everyone", - "Two trailer park girls go round the outside", - "With the lights out, it's less dangerous", - "Here we go back, this is the moment, tonight is the night", - "Now you're just somebody that I used to know...", - "Black bird, black moon, black sky", - "Some legends are told, some turn to dust or to gold", - "Your brain gets smart, but your head gets dumb.", - "Save your mercy for someone who needs it more", - "You're gonna hear my voice when I shout it out loud", - "Ding ding pch n daa, bam-ba-ba-re-bam baram bom bom baba-bam-bam-bommm", - "Súbeme la radio que esta es mi canción", - "I'm beggin', beggin' you", - "Never gonna let you down (I am trying!)", - "\"I use Arch, btw\" - John Cena", - "\"Hyper\".replace(\"e\", \"\")", - "\"my win11 install runs hyprland that is true\" - raf", - "\"stop playing league loser\" - hyprBot", - "\"If it ain't broke, don't fix it\" - Lucascito_03", - "\"@vaxry how do i learn c++\" - flicko", - // - "Join the discord server!", - "Thanks ThatOneCalculator!", - "The AUR packages always work, except for the times they don't.", - "Funny animation compositor woo", - // - "2 years!" - // clang-format on +namespace NSplashes { + inline const std::vector SPLASHES = { + // clang-format off + "Woo, animations!", + "It's like Hypr, but better.", + "Release 1.0 when?", + "It's not awesome, it's Hyprland!", + "\"I commit too often, people can't catch up lmao\" - Vaxry", + "This text is random.", + "\"There are reasons to not use rust.\" - Boga", + "Read the wiki.", + "\"Hello everyone this is YOUR daily dose of ‘read the wiki’\" - Vaxry", + "h", + "\"‘why no work’, bro I haven't hacked your pc to get live feeds yet\" - Vaxry", + "Compile, wait for 20 minutes, notice a new commit, compile again.", + "To rice, or not to rice, that is the question.", + "Now available on Fedora!", + "\"Hyprland is so good it starts with a capital letter\" - Hazel", + "\"please make this message a splash\" - eriedaberrie", + "\"the only wayland compositor powered by fried chicken\" - raf", + "\"This will never get into Hyprland\" - Flafy", + "\"Hyprland only gives you up on -git\" - fazzi", + "Segmentation fault (core dumped)", + "\"disabling hyprland logo is a war crime\" - vaxry", + "some basic startup code", + "\"I think I am addicted to hyprland\" - mathisbuilder", + "\"hyprland is the most important package in the arch repos\" - jacekpoz", + "Thanks Brodie!", + "Thanks fufexan!", + "Thanks raf!", + "You can't use --splash to change this message :)", + "Hyprland will overtake Gnome in popularity by [insert year]", + // music reference / quote section + "J'remue le ciel, le jour, la nuit.", + "aezakmi, aezakmi, aezakmi, aezakmi, aezakmi, aezakmi, aezakmi!", + "Wir sind schon sehr lang zusammen...", + "I see a red door and I want it painted black.", + "Take on me, take me on...", + "You spin me right round baby right round", + "Stayin' alive, stayin' alive", + "Say no way, say no way ya, no way!", + "Ground control to Major Tom...", + "Alors on danse", + "And all that I can see, is just a yellow lemon tree.", + "Got a one-way ticket to the blues", + "Is this the real life, is this just fantasy", + "What's in your head, in your head?", + "We're all living in America, America, America.", + "I'm still standing, better than I ever did", + "Here comes the sun, bringing you love and shining on everyone", + "Two trailer park girls go round the outside", + "With the lights out, it's less dangerous", + "Here we go back, this is the moment, tonight is the night", + "Now you're just somebody that I used to know...", + "Black bird, black moon, black sky", + "Some legends are told, some turn to dust or to gold", + "Your brain gets smart, but your head gets dumb.", + "Save your mercy for someone who needs it more", + "You're gonna hear my voice when I shout it out loud", + "Ding ding pch n daa, bam-ba-ba-re-bam baram bom bom baba-bam-bam-bommm", + "Súbeme la radio que esta es mi canción", + "I'm beggin', beggin' you", + "Never gonna let you down (I am trying!)", + "\"I use Arch, btw\" - John Cena", + "\"Hyper\".replace(\"e\", \"\")", + "\"my win11 install runs hyprland that is true\" - raf", + "\"stop playing league loser\" - hyprBot", + "\"If it ain't broke, don't fix it\" - Lucascito_03", + "\"@vaxry how do i learn c++\" - flicko", + // + "Join the discord server!", + "Thanks ThatOneCalculator!", + "The AUR packages always work, except for the times they don't.", + "Funny animation compositor woo", + // + "2 years!" + // clang-format on + }; + + inline const std::vector SPLASHES_CHRISTMAS = { + // clang-format off + "Merry Christmas!", + "Merry Xmas!", + "Ho ho ho", + "Santa was here", + // clang-format on + }; + + // ONLY valid near new years. + inline static int newYear = []() -> int { + auto tt = std::chrono::system_clock::to_time_t(std::chrono::system_clock::now()); + auto local = *localtime(&tt); + + if (local.tm_mon < 8 /* decided with a fair die I promise. */) + return local.tm_year + 1900; + return local.tm_year + 1901; + }(); + + inline const std::vector SPLASHES_NEWYEAR = { + // clang-format off + "Happy new Year!", + "[New year] will be the year of the Linux desktop!", + "[New year] will be the year of the Hyprland desktop!", + std::format("{} will be the year of the Linux desktop!", newYear), + std::format("{} will be the year of the Hyprland desktop!", newYear), + std::format("Let's make {} even better than {}!", newYear, newYear - 1), + // clang-format on + }; }; \ No newline at end of file From ceef4fb3a5efe1617790f56e2701846a21c2533d Mon Sep 17 00:00:00 2001 From: Vaxry Date: Thu, 5 Dec 2024 03:36:50 +0000 Subject: [PATCH 0697/2181] core: feeling a bit quirky today. --- src/helpers/Splashes.hpp | 49 +++++++++++++++++++++++++++++----------- 1 file changed, 36 insertions(+), 13 deletions(-) diff --git a/src/helpers/Splashes.hpp b/src/helpers/Splashes.hpp index 2c74abb1..3ae59956 100644 --- a/src/helpers/Splashes.hpp +++ b/src/helpers/Splashes.hpp @@ -35,6 +35,30 @@ namespace NSplashes { "Thanks raf!", "You can't use --splash to change this message :)", "Hyprland will overtake Gnome in popularity by [insert year]", + "Designed in California - Assembled in China", + "\"something
System/Version info - ```sh - - + ``` + + ``` @@ -61,15 +62,56 @@ body: attributes: label: How to reproduce description: "How can someone else reproduce the issue?" + placeholder: | + 1. ... + 2. ... + 3. ... + validations: required: true + - type: markdown + attributes: + value: | + ## Additional info section + + In the section below you will be asked to upload some files. + + When including text files (such as logs or config), please **always ATTACH** them, and not paste them directly. + + This is important to avoid clutter, spam, and make the issues more readable. + Thanks for your understanding. + + # The main reason to disallow pasting directly or in a dropdown, is to not clutter + # the issue with unnecessary keywords, making the github issue search useless. + - type: checkboxes + attributes: + label: Attach not paste + options: + - label: I understand that all text files must be *attached*, and not pasted directly. If not respected, this issue will likely get closed as spam + required: true + + - type: markdown + attributes: + value: >- + Please be sure to upload the following files below if they are relevant to the issue: + + - Logs can be found in $XDG_RUNTIME_DIR/hypr (sort by date to grab the latest) + - Crash reports are stored in ~/.cache/hyprland or $XDG_CACHE_HOME/hyprland + - Hyprland config files - `hyprctl systeminfo -c > /tmp/hyprland_config_dump.txt` use this command to dump full configuration to a single file. + + - type: checkboxes + attributes: + label: Checklist of files to include below + options: + - label: Hyprland config - `hyprctl systeminfo -c` (always include) + - label: Crash report (always include in case of crash) + - label: Video (always include in case of a visual bug) + - label: Logs (might contain useful info such as errors) + - type: textarea id: logs attributes: - label: Crash reports, logs, images, videos + label: Additional info & File uploads description: | - Anything that can help. Please always ATTACH and not paste them. - Logs can be found in $XDG_RUNTIME_DIR/hypr - Crash reports are stored in ~/.cache/hyprland or $XDG_CACHE_HOME/hyprland - + Tip: You can attach files by clicking this area to highlight it and then dragging files in. From f69e72eca1a31e4780d06018fc7e09767a50969d Mon Sep 17 00:00:00 2001 From: davc0n Date: Fri, 3 Jan 2025 23:43:48 +0100 Subject: [PATCH 0805/2181] socket2: add focusedmonv2 event (#8921) * socket2: add focusedmonv2 event * socket2: remove workspace name from focusedmonv2 --- src/Compositor.cpp | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/src/Compositor.cpp b/src/Compositor.cpp index c8ed22df..aa6faa16 100644 --- a/src/Compositor.cpp +++ b/src/Compositor.cpp @@ -2588,7 +2588,12 @@ void CCompositor::setActiveMonitor(PHLMONITOR pMonitor) { const auto PWORKSPACE = pMonitor->activeWorkspace; - g_pEventManager->postEvent(SHyprIPCEvent{"focusedmon", pMonitor->szName + "," + (PWORKSPACE ? PWORKSPACE->m_szName : "?")}); + const auto WORKSPACE_ID = PWORKSPACE ? std::to_string(PWORKSPACE->m_iID) : std::to_string(WORKSPACE_INVALID); + const auto WORKSPACE_NAME = PWORKSPACE ? PWORKSPACE->m_szName : "?"; + + g_pEventManager->postEvent(SHyprIPCEvent{"focusedmon", pMonitor->szName + "," + WORKSPACE_NAME}); + g_pEventManager->postEvent(SHyprIPCEvent{"focusedmonv2", pMonitor->szName + "," + WORKSPACE_ID}); + EMIT_HOOK_EVENT("focusedMon", pMonitor); m_pLastMonitor = pMonitor->self; } From 2e6e0e9278614406979f63692cdb3a015e54c248 Mon Sep 17 00:00:00 2001 From: vaxerski Date: Sat, 4 Jan 2025 00:10:10 +0100 Subject: [PATCH 0806/2181] core: guard workspace and monitor in moveWorkspaceToMonitor ref #7822 --- src/Compositor.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/Compositor.cpp b/src/Compositor.cpp index aa6faa16..c80f05e6 100644 --- a/src/Compositor.cpp +++ b/src/Compositor.cpp @@ -2076,7 +2076,8 @@ PHLMONITOR CCompositor::getMonitorFromString(const std::string& name) { void CCompositor::moveWorkspaceToMonitor(PHLWORKSPACE pWorkspace, PHLMONITOR pMonitor, bool noWarpCursor) { - // We trust the monitor to be correct. + if (!pWorkspace || !pMonitor) + return; if (pWorkspace->m_pMonitor == pMonitor) return; From 60f069d54015fec66e63f1ff7e6ff26ddb349976 Mon Sep 17 00:00:00 2001 From: vaxerski Date: Sat, 4 Jan 2025 00:25:01 +0100 Subject: [PATCH 0807/2181] groupbar: fix missing ellipsize for text fixes #8938 --- src/render/OpenGL.cpp | 8 +++- src/render/OpenGL.hpp | 38 +++++++++---------- .../decorations/CHyprGroupBarDecoration.cpp | 2 +- 3 files changed, 27 insertions(+), 21 deletions(-) diff --git a/src/render/OpenGL.cpp b/src/render/OpenGL.cpp index 68baf48e..1b51acbf 100644 --- a/src/render/OpenGL.cpp +++ b/src/render/OpenGL.cpp @@ -2555,7 +2555,7 @@ SP CHyprOpenGLImpl::loadAsset(const std::string& filename) { return tex; } -SP CHyprOpenGLImpl::renderText(const std::string& text, CHyprColor col, int pt, bool italic, const std::string& fontFamily) { +SP CHyprOpenGLImpl::renderText(const std::string& text, CHyprColor col, int pt, bool italic, const std::string& fontFamily, int maxWidth) { SP tex = makeShared(); static auto FONT = CConfigValue("misc:font_family"); @@ -2580,6 +2580,12 @@ SP CHyprOpenGLImpl::renderText(const std::string& text, CHyprColor col int textW = 0, textH = 0; pango_layout_set_text(layoutText, text.c_str(), -1); + + if (maxWidth > 0) { + pango_layout_set_width(layoutText, maxWidth * PANGO_SCALE); + pango_layout_set_ellipsize(layoutText, PANGO_ELLIPSIZE_END); + } + pango_layout_get_size(layoutText, &textW, &textH); textW /= PANGO_SCALE; textH /= PANGO_SCALE; diff --git a/src/render/OpenGL.hpp b/src/render/OpenGL.hpp index 281ee09a..713816bc 100644 --- a/src/render/OpenGL.hpp +++ b/src/render/OpenGL.hpp @@ -217,32 +217,32 @@ class CHyprOpenGLImpl { void renderOffToMain(CFramebuffer* off); void bindBackOnMain(); - SP loadAsset(const std::string& file); - SP renderText(const std::string& text, CHyprColor col, int pt, bool italic = false, const std::string& fontFamily = ""); + SP loadAsset(const std::string& file); + SP renderText(const std::string& text, CHyprColor col, int pt, bool italic = false, const std::string& fontFamily = "", int maxWidth = 0); - void setDamage(const CRegion& damage, std::optional finalDamage = {}); + void setDamage(const CRegion& damage, std::optional finalDamage = {}); - uint32_t getPreferredReadFormat(PHLMONITOR pMonitor); - std::vector getDRMFormats(); - EGLImageKHR createEGLImage(const Aquamarine::SDMABUFAttrs& attrs); - SP createEGLSync(int fenceFD); - bool waitForTimelinePoint(SP timeline, uint64_t point); + uint32_t getPreferredReadFormat(PHLMONITOR pMonitor); + std::vector getDRMFormats(); + EGLImageKHR createEGLImage(const Aquamarine::SDMABUFAttrs& attrs); + SP createEGLSync(int fenceFD); + bool waitForTimelinePoint(SP timeline, uint64_t point); - SCurrentRenderData m_RenderData; + SCurrentRenderData m_RenderData; - GLint m_iCurrentOutputFb = 0; + GLint m_iCurrentOutputFb = 0; - int m_iGBMFD = -1; - gbm_device* m_pGbmDevice = nullptr; - EGLContext m_pEglContext = nullptr; - EGLDisplay m_pEglDisplay = nullptr; - EGLDeviceEXT m_pEglDevice = nullptr; - uint failedAssetsNo = 0; + int m_iGBMFD = -1; + gbm_device* m_pGbmDevice = nullptr; + EGLContext m_pEglContext = nullptr; + EGLDisplay m_pEglDisplay = nullptr; + EGLDeviceEXT m_pEglDevice = nullptr; + uint failedAssetsNo = 0; - bool m_bReloadScreenShader = true; // at launch it can be set + bool m_bReloadScreenShader = true; // at launch it can be set - std::map m_mWindowFramebuffers; - std::map m_mLayerFramebuffers; + std::map m_mWindowFramebuffers; + std::map m_mLayerFramebuffers; std::map m_mMonitorRenderResources; std::map m_mMonitorBGFBs; diff --git a/src/render/decorations/CHyprGroupBarDecoration.cpp b/src/render/decorations/CHyprGroupBarDecoration.cpp index 53d35a64..c6dc5779 100644 --- a/src/render/decorations/CHyprGroupBarDecoration.cpp +++ b/src/render/decorations/CHyprGroupBarDecoration.cpp @@ -223,7 +223,7 @@ CTitleTex::CTitleTex(PHLWINDOW pWindow, const Vector2D& bufferSize, const float const CHyprColor COLOR = CHyprColor(*PTEXTCOLOR); const auto FONTFAMILY = *PTITLEFONTFAMILY != STRVAL_EMPTY ? *PTITLEFONTFAMILY : *FALLBACKFONT; - tex = g_pHyprOpenGL->renderText(pWindow->m_szTitle, COLOR, *PTITLEFONTSIZE, false, FONTFAMILY); + tex = g_pHyprOpenGL->renderText(pWindow->m_szTitle, COLOR, *PTITLEFONTSIZE, false, FONTFAMILY, bufferSize.x - 2 /* some padding yk */); if (tex) texSize = tex->m_vSize; From a25d228840dfac88160b6f6c9513b5a587119f67 Mon Sep 17 00:00:00 2001 From: vaxerski Date: Sat, 4 Jan 2025 17:21:02 +0100 Subject: [PATCH 0808/2181] windows: minor initial workspace improvements ref #8942 --- src/events/Windows.cpp | 26 +++++++++++++------------- 1 file changed, 13 insertions(+), 13 deletions(-) diff --git a/src/events/Windows.cpp b/src/events/Windows.cpp index c17c425b..a20cbcad 100644 --- a/src/events/Windows.cpp +++ b/src/events/Windows.cpp @@ -121,16 +121,6 @@ void Events::listener_mapWindow(void* owner, void* data) { PWINDOW->m_bX11ShouldntFocus = PWINDOW->m_bX11ShouldntFocus || (PWINDOW->m_bIsX11 && PWINDOW->isX11OverrideRedirect() && !PWINDOW->m_pXWaylandSurface->wantsFocus()); - if (PWORKSPACE->m_bDefaultFloating) - PWINDOW->m_bIsFloating = true; - - if (PWORKSPACE->m_bDefaultPseudo) { - PWINDOW->m_bIsPseudotiled = true; - CBox desiredGeometry = {0}; - g_pXWaylandManager->getGeometryForWindow(PWINDOW, &desiredGeometry); - PWINDOW->m_vPseudoSize = Vector2D(desiredGeometry.width, desiredGeometry.height); - } - // window rules PWINDOW->m_vMatchedRules = g_pConfigManager->getMatchingRules(PWINDOW, false); std::optional requestedInternalFSMode, requestedClientFSMode; @@ -171,6 +161,7 @@ void Events::listener_mapWindow(void* owner, void* data) { PMONITOR = PMONITORFROMID; } PWINDOW->m_pWorkspace = PMONITOR->activeSpecialWorkspace ? PMONITOR->activeSpecialWorkspace : PMONITOR->activeWorkspace; + PWORKSPACE = PWINDOW->m_pWorkspace; Debug::log(LOG, "Rule monitor, applying to {:mw}", PWINDOW); } catch (std::exception& e) { Debug::log(ERR, "Rule monitor failed, rule: {} -> {} | err: {}", r->szRule, r->szValue, e.what()); } @@ -180,11 +171,10 @@ void Events::listener_mapWindow(void* owner, void* data) { // check if it isnt unset const auto WORKSPACERQ = r->szRule.substr(r->szRule.find_first_of(' ') + 1); - if (WORKSPACERQ == "unset") { + if (WORKSPACERQ == "unset") requestedWorkspace = ""; - } else { + else requestedWorkspace = WORKSPACERQ; - } const auto JUSTWORKSPACE = WORKSPACERQ.contains(' ') ? WORKSPACERQ.substr(0, WORKSPACERQ.find_first_of(' ')) : WORKSPACERQ; @@ -347,6 +337,16 @@ void Events::listener_mapWindow(void* owner, void* data) { workspaceSilent = false; } + if (PWORKSPACE->m_bDefaultFloating) + PWINDOW->m_bIsFloating = true; + + if (PWORKSPACE->m_bDefaultPseudo) { + PWINDOW->m_bIsPseudotiled = true; + CBox desiredGeometry = {0}; + g_pXWaylandManager->getGeometryForWindow(PWINDOW, &desiredGeometry); + PWINDOW->m_vPseudoSize = Vector2D(desiredGeometry.width, desiredGeometry.height); + } + PWINDOW->updateWindowData(); // Verify window swallowing. Get the swallower before calling onWindowCreated(PWINDOW) because getSwallower() wouldn't get it after if PWINDOW gets auto grouped. From e8317ae34d635b6055c4ab3e42325a9e50b6f5a0 Mon Sep 17 00:00:00 2001 From: vaxerski Date: Sat, 4 Jan 2025 17:35:11 +0100 Subject: [PATCH 0809/2181] xwayland: don't define atoms on no_xwayland builds fixes #8661 --- src/xwayland/XWayland.hpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/xwayland/XWayland.hpp b/src/xwayland/XWayland.hpp index 96253d19..113ca4d4 100644 --- a/src/xwayland/XWayland.hpp +++ b/src/xwayland/XWayland.hpp @@ -34,6 +34,7 @@ class CXWayland { inline std::unique_ptr g_pXWayland; inline std::unordered_map HYPRATOMS = { +#ifndef NO_XWAYLAND HYPRATOM("_NET_SUPPORTED"), HYPRATOM("_NET_SUPPORTING_WM_CHECK"), HYPRATOM("_NET_WM_NAME"), @@ -126,4 +127,5 @@ inline std::unordered_map HYPRATOMS = { HYPRATOM("DELETE"), HYPRATOM("TEXT"), HYPRATOM("INCR"), +#endif }; From b0bae15499ad57bbfeae8be958df8c022201e583 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sergio=20Migu=C3=A9ns?= Date: Sat, 4 Jan 2025 17:40:33 +0100 Subject: [PATCH 0810/2181] master: make loop around optional when cycling (#8926) --- src/layout/MasterLayout.cpp | 21 ++++++++++++++++----- src/layout/MasterLayout.hpp | 2 +- 2 files changed, 17 insertions(+), 6 deletions(-) diff --git a/src/layout/MasterLayout.cpp b/src/layout/MasterLayout.cpp index 05a2a707..fb7df84f 100644 --- a/src/layout/MasterLayout.cpp +++ b/src/layout/MasterLayout.cpp @@ -978,7 +978,7 @@ void CHyprMasterLayout::alterSplitRatio(PHLWINDOW pWindow, float ratio, bool exa recalculateMonitor(pWindow->monitorID()); } -PHLWINDOW CHyprMasterLayout::getNextWindow(PHLWINDOW pWindow, bool next) { +PHLWINDOW CHyprMasterLayout::getNextWindow(PHLWINDOW pWindow, bool next, bool loop) { if (!isWindowTiled(pWindow)) return nullptr; @@ -997,6 +997,13 @@ PHLWINDOW CHyprMasterLayout::getNextWindow(PHLWINDOW pWindow, bool next) { CANDIDATE = std::find_if(nodes.begin(), nodes.end(), [&](const auto& other) { return other != *PNODE && ISMASTER != other.isMaster && other.workspaceID == PNODE->workspaceID; }); + if (CANDIDATE != nodes.end() && !loop) { + if (CANDIDATE->isMaster && next) + return nullptr; + if (!CANDIDATE->isMaster && ISMASTER && !next) + return nullptr; + } + return CANDIDATE == nodes.end() ? nullptr : CANDIDATE->pWindow.lock(); } @@ -1110,7 +1117,8 @@ std::any CHyprMasterLayout::layoutMessage(SLayoutMessageHeader header, std::stri if (!PWINDOW) return 0; - const auto PNEXTWINDOW = getNextWindow(PWINDOW, true); + const bool NOLOOP = vars.size() >= 2 && vars[1] == "noloop"; + const auto PNEXTWINDOW = getNextWindow(PWINDOW, true, !NOLOOP); switchToWindow(PNEXTWINDOW); } else if (command == "cycleprev") { const auto PWINDOW = header.pWindow; @@ -1118,7 +1126,8 @@ std::any CHyprMasterLayout::layoutMessage(SLayoutMessageHeader header, std::stri if (!PWINDOW) return 0; - const auto PPREVWINDOW = getNextWindow(PWINDOW, false); + const bool NOLOOP = vars.size() >= 2 && vars[1] == "noloop"; + const auto PPREVWINDOW = getNextWindow(PWINDOW, false, !NOLOOP); switchToWindow(PPREVWINDOW); } else if (command == "swapnext") { if (!validMapped(header.pWindow)) @@ -1129,7 +1138,8 @@ std::any CHyprMasterLayout::layoutMessage(SLayoutMessageHeader header, std::stri return 0; } - const auto PWINDOWTOSWAPWITH = getNextWindow(header.pWindow, true); + const bool NOLOOP = vars.size() >= 2 && vars[1] == "noloop"; + const auto PWINDOWTOSWAPWITH = getNextWindow(header.pWindow, true, !NOLOOP); if (PWINDOWTOSWAPWITH) { g_pCompositor->setWindowFullscreenInternal(header.pWindow, FSMODE_NONE); @@ -1145,7 +1155,8 @@ std::any CHyprMasterLayout::layoutMessage(SLayoutMessageHeader header, std::stri return 0; } - const auto PWINDOWTOSWAPWITH = getNextWindow(header.pWindow, false); + const bool NOLOOP = vars.size() >= 2 && vars[1] == "noloop"; + const auto PWINDOWTOSWAPWITH = getNextWindow(header.pWindow, false, !NOLOOP); if (PWINDOWTOSWAPWITH) { g_pCompositor->setWindowFullscreenClient(header.pWindow, FSMODE_NONE); diff --git a/src/layout/MasterLayout.hpp b/src/layout/MasterLayout.hpp index 4841ef08..03ca3c3b 100644 --- a/src/layout/MasterLayout.hpp +++ b/src/layout/MasterLayout.hpp @@ -87,7 +87,7 @@ class CHyprMasterLayout : public IHyprLayout { SMasterNodeData* getMasterNodeOnWorkspace(const WORKSPACEID&); SMasterWorkspaceData* getMasterWorkspaceData(const WORKSPACEID&); void calculateWorkspace(PHLWORKSPACE); - PHLWINDOW getNextWindow(PHLWINDOW, bool); + PHLWINDOW getNextWindow(PHLWINDOW, bool, bool); int getMastersOnWorkspace(const WORKSPACEID&); friend struct SMasterNodeData; From a5c14370c11287cbf520c8f427179c665ac9c891 Mon Sep 17 00:00:00 2001 From: Pollux Date: Sun, 5 Jan 2025 12:38:49 -0600 Subject: [PATCH 0811/2181] renderer: Add supercircular window corners (#8943) renderer: Add supercircular shadows and borders config: Add rounding_power to default and example configs rule: add `roundingpower` window rule --- example/hyprland.conf | 1 + src/config/ConfigDescriptions.hpp | 6 + src/config/ConfigManager.cpp | 1 + src/config/ConfigManager.hpp | 1 + src/config/defaultConfig.hpp | 1 + src/desktop/Window.cpp | 23 ++-- src/desktop/Window.hpp | 2 + src/desktop/WindowRule.cpp | 6 +- src/render/OpenGL.cpp | 106 +++++++++------- src/render/OpenGL.hpp | 119 +++++++++--------- src/render/Renderer.cpp | 11 +- src/render/Shader.hpp | 1 + .../decorations/CHyprBorderDecoration.cpp | 16 +-- .../decorations/CHyprDropShadowDecoration.cpp | 14 ++- .../decorations/CHyprDropShadowDecoration.hpp | 2 +- src/render/pass/BorderPassElement.cpp | 6 +- src/render/pass/BorderPassElement.hpp | 1 + src/render/pass/RectPassElement.cpp | 4 +- src/render/pass/RectPassElement.hpp | 5 +- src/render/pass/SurfacePassElement.cpp | 17 +-- src/render/pass/SurfacePassElement.hpp | 5 +- src/render/pass/TexPassElement.cpp | 3 +- src/render/pass/TexPassElement.hpp | 7 +- src/render/shaders/Border.hpp | 7 +- src/render/shaders/Shadow.hpp | 13 +- src/render/shaders/Textures.hpp | 23 ++-- 26 files changed, 228 insertions(+), 173 deletions(-) diff --git a/example/hyprland.conf b/example/hyprland.conf index fe1a831a..c2b1a071 100644 --- a/example/hyprland.conf +++ b/example/hyprland.conf @@ -81,6 +81,7 @@ general { # https://wiki.hyprland.org/Configuring/Variables/#decoration decoration { rounding = 10 + rounding_power = 2 # Change transparency of focused and unfocused windows active_opacity = 1.0 diff --git a/src/config/ConfigDescriptions.hpp b/src/config/ConfigDescriptions.hpp index 17657983..46f91a21 100644 --- a/src/config/ConfigDescriptions.hpp +++ b/src/config/ConfigDescriptions.hpp @@ -139,6 +139,12 @@ inline static const std::vector CONFIG_OPTIONS = { .type = CONFIG_OPTION_INT, .data = SConfigOptionDescription::SRangeData{0, 0, 20}, }, + SConfigOptionDescription{ + .value = "decoration:rounding_power", + .description = "rouding power of corners (2 is a circle)", + .type = CONFIG_OPTION_FLOAT, + .data = SConfigOptionDescription::SFloatData{2, 2, 10}, + }, SConfigOptionDescription{ .value = "decoration:active_opacity", .description = "opacity of active windows. [0.0 - 1.0]", diff --git a/src/config/ConfigManager.cpp b/src/config/ConfigManager.cpp index bdce573f..732d12e5 100644 --- a/src/config/ConfigManager.cpp +++ b/src/config/ConfigManager.cpp @@ -427,6 +427,7 @@ CConfigManager::CConfigManager() { m_pConfig->addConfigValue("debug:colored_stdout_logs", Hyprlang::INT{1}); m_pConfig->addConfigValue("decoration:rounding", Hyprlang::INT{0}); + m_pConfig->addConfigValue("decoration:rounding_power", {2.F}); m_pConfig->addConfigValue("decoration:blur:enabled", Hyprlang::INT{1}); m_pConfig->addConfigValue("decoration:blur:size", Hyprlang::INT{8}); m_pConfig->addConfigValue("decoration:blur:passes", Hyprlang::INT{1}); diff --git a/src/config/ConfigManager.hpp b/src/config/ConfigManager.hpp index 0cd0a0a4..436362ae 100644 --- a/src/config/ConfigManager.hpp +++ b/src/config/ConfigManager.hpp @@ -259,6 +259,7 @@ class CConfigManager { }; std::unordered_map*(PHLWINDOW)>> mfWindowProperties = { + {"roundingpower", [](const PHLWINDOW& pWindow) { return &pWindow->m_sWindowData.roundingPower; }}, {"scrollmouse", [](const PHLWINDOW& pWindow) { return &pWindow->m_sWindowData.scrollMouse; }}, {"scrolltouchpad", [](const PHLWINDOW& pWindow) { return &pWindow->m_sWindowData.scrollTouchpad; }}}; diff --git a/src/config/defaultConfig.hpp b/src/config/defaultConfig.hpp index c4eb3385..851e11f2 100644 --- a/src/config/defaultConfig.hpp +++ b/src/config/defaultConfig.hpp @@ -94,6 +94,7 @@ general { # https://wiki.hyprland.org/Configuring/Variables/#decoration decoration { rounding = 10 + rounding_power = 2 # Change transparency of focused and unfocused windows active_opacity = 1.0 diff --git a/src/desktop/Window.cpp b/src/desktop/Window.cpp index 4104c737..60914198 100644 --- a/src/desktop/Window.cpp +++ b/src/desktop/Window.cpp @@ -824,7 +824,8 @@ void CWindow::updateDynamicRules() { // it is assumed that the point is within the real window box (m_vRealPosition, m_vRealSize) // otherwise behaviour is undefined bool CWindow::isInCurvedCorner(double x, double y) { - const int ROUNDING = rounding(); + const int ROUNDING = rounding(); + const int ROUNDINGPOWER = roundingPower(); if (getRealBorderSize() >= ROUNDING) return false; @@ -835,16 +836,16 @@ bool CWindow::isInCurvedCorner(double x, double y) { double y1 = m_vRealPosition.value().y + m_vRealSize.value().y - ROUNDING; if (x < x0 && y < y0) { - return Vector2D{x0, y0}.distance(Vector2D{x, y}) > (double)ROUNDING; + return std::pow(x0 - x, ROUNDINGPOWER) + std::pow(y0 - y, ROUNDINGPOWER) > std::pow((double)ROUNDING, ROUNDINGPOWER); } if (x > x1 && y < y0) { - return Vector2D{x1, y0}.distance(Vector2D{x, y}) > (double)ROUNDING; + return std::pow(x - x1, ROUNDINGPOWER) + std::pow(y0 - y, ROUNDINGPOWER) > std::pow((double)ROUNDING, ROUNDINGPOWER); } if (x < x0 && y > y1) { - return Vector2D{x0, y1}.distance(Vector2D{x, y}) > (double)ROUNDING; + return std::pow(x0 - x, ROUNDINGPOWER) + std::pow(y - y1, ROUNDINGPOWER) > std::pow((double)ROUNDING, ROUNDINGPOWER); } if (x > x1 && y > y1) { - return Vector2D{x1, y1}.distance(Vector2D{x, y}) > (double)ROUNDING; + return std::pow(x - x1, ROUNDINGPOWER) + std::pow(y - y1, ROUNDINGPOWER) > std::pow((double)ROUNDING, ROUNDINGPOWER); } return false; @@ -1164,13 +1165,21 @@ bool CWindow::opaque() { } float CWindow::rounding() { - static auto PROUNDING = CConfigValue("decoration:rounding"); + static auto PROUNDING = CConfigValue("decoration:rounding"); + static auto PROUNDINGPOWER = CConfigValue("decoration:rounding_power"); - float rounding = m_sWindowData.rounding.valueOr(*PROUNDING); + float roundingPower = m_sWindowData.roundingPower.valueOr(*PROUNDINGPOWER); + float rounding = m_sWindowData.rounding.valueOr(*PROUNDING) * (roundingPower / 2.0); /* Make perceived roundness consistent. */ return m_sWindowData.noRounding.valueOrDefault() ? 0 : rounding; } +float CWindow::roundingPower() { + static auto PROUNDINGPOWER = CConfigValue("decoration:rounding_power"); + + return m_sWindowData.roundingPower.valueOr(*PROUNDINGPOWER); +} + void CWindow::updateWindowData() { const auto PWORKSPACE = m_pWorkspace; const auto WORKSPACERULE = PWORKSPACE ? g_pConfigManager->getWorkspaceRuleFor(PWORKSPACE) : SWorkspaceRule{}; diff --git a/src/desktop/Window.hpp b/src/desktop/Window.hpp index 6ed9a525..3ceaf594 100644 --- a/src/desktop/Window.hpp +++ b/src/desktop/Window.hpp @@ -183,6 +183,7 @@ struct SWindowData { CWindowOverridableVar renderUnfocused = false; CWindowOverridableVar rounding; + CWindowOverridableVar roundingPower; CWindowOverridableVar borderSize; CWindowOverridableVar scrollMouse; @@ -414,6 +415,7 @@ class CWindow { Vector2D middle(); bool opaque(); float rounding(); + float roundingPower(); bool canBeTorn(); void setSuspended(bool suspend); bool visibleOnMonitor(PHLMONITOR pMonitor); diff --git a/src/desktop/WindowRule.cpp b/src/desktop/WindowRule.cpp index 7db6c3db..306a25ce 100644 --- a/src/desktop/WindowRule.cpp +++ b/src/desktop/WindowRule.cpp @@ -8,8 +8,8 @@ static const auto RULES = std::unordered_set{ "float", "fullscreen", "maximize", "noinitialfocus", "pin", "stayfocused", "tile", "renderunfocused", }; static const auto RULES_PREFIX = std::unordered_set{ - "animation", "bordercolor", "bordersize", "center", "fullscreenstate", "group", "idleinhibit", "maxsize", "minsize", "monitor", "move", "opacity", - "plugin:", "prop", "pseudo", "rounding", "scrollmouse", "scrolltouchpad", "size", "suppressevent", "tag", "workspace", "xray", + "animation", "bordercolor", "bordersize", "center", "fullscreenstate", "group", "idleinhibit", "maxsize", "minsize", "monitor", "move", "opacity", + "plugin:", "prop", "pseudo", "rounding", "roundingpower", "scrollmouse", "scrolltouchpad", "size", "suppressevent", "tag", "workspace", "xray", }; CWindowRule::CWindowRule(const std::string& rule, const std::string& value, bool isV2, bool isExecRule) : szValue(value), szRule(rule), v2(isV2), execRule(isExecRule) { @@ -88,4 +88,4 @@ CWindowRule::CWindowRule(const std::string& rule, const std::string& value, bool ruleType = RULE_INVALID; } } -} \ No newline at end of file +} diff --git a/src/render/OpenGL.cpp b/src/render/OpenGL.cpp index 1b51acbf..94b70acf 100644 --- a/src/render/OpenGL.cpp +++ b/src/render/OpenGL.cpp @@ -971,14 +971,15 @@ void CHyprOpenGLImpl::setDamage(const CRegion& damage_, std::optional f } void CHyprOpenGLImpl::initShaders() { - GLuint prog = createProgram(QUADVERTSRC, QUADFRAGSRC); - m_RenderData.pCurrentMonData->m_shQUAD.program = prog; - m_RenderData.pCurrentMonData->m_shQUAD.proj = glGetUniformLocation(prog, "proj"); - m_RenderData.pCurrentMonData->m_shQUAD.color = glGetUniformLocation(prog, "color"); - m_RenderData.pCurrentMonData->m_shQUAD.posAttrib = glGetAttribLocation(prog, "pos"); - m_RenderData.pCurrentMonData->m_shQUAD.topLeft = glGetUniformLocation(prog, "topLeft"); - m_RenderData.pCurrentMonData->m_shQUAD.fullSize = glGetUniformLocation(prog, "fullSize"); - m_RenderData.pCurrentMonData->m_shQUAD.radius = glGetUniformLocation(prog, "radius"); + GLuint prog = createProgram(QUADVERTSRC, QUADFRAGSRC); + m_RenderData.pCurrentMonData->m_shQUAD.program = prog; + m_RenderData.pCurrentMonData->m_shQUAD.proj = glGetUniformLocation(prog, "proj"); + m_RenderData.pCurrentMonData->m_shQUAD.color = glGetUniformLocation(prog, "color"); + m_RenderData.pCurrentMonData->m_shQUAD.posAttrib = glGetAttribLocation(prog, "pos"); + m_RenderData.pCurrentMonData->m_shQUAD.topLeft = glGetUniformLocation(prog, "topLeft"); + m_RenderData.pCurrentMonData->m_shQUAD.fullSize = glGetUniformLocation(prog, "fullSize"); + m_RenderData.pCurrentMonData->m_shQUAD.radius = glGetUniformLocation(prog, "radius"); + m_RenderData.pCurrentMonData->m_shQUAD.roundingPower = glGetUniformLocation(prog, "roundingPower"); prog = createProgram(TEXVERTSRC, TEXFRAGSRCRGBA); m_RenderData.pCurrentMonData->m_shRGBA.program = prog; @@ -995,6 +996,7 @@ void CHyprOpenGLImpl::initShaders() { m_RenderData.pCurrentMonData->m_shRGBA.topLeft = glGetUniformLocation(prog, "topLeft"); m_RenderData.pCurrentMonData->m_shRGBA.fullSize = glGetUniformLocation(prog, "fullSize"); m_RenderData.pCurrentMonData->m_shRGBA.radius = glGetUniformLocation(prog, "radius"); + m_RenderData.pCurrentMonData->m_shRGBA.roundingPower = glGetUniformLocation(prog, "roundingPower"); m_RenderData.pCurrentMonData->m_shRGBA.applyTint = glGetUniformLocation(prog, "applyTint"); m_RenderData.pCurrentMonData->m_shRGBA.tint = glGetUniformLocation(prog, "tint"); m_RenderData.pCurrentMonData->m_shRGBA.useAlphaMatte = glGetUniformLocation(prog, "useAlphaMatte"); @@ -1037,6 +1039,7 @@ void CHyprOpenGLImpl::initShaders() { m_RenderData.pCurrentMonData->m_shRGBX.topLeft = glGetUniformLocation(prog, "topLeft"); m_RenderData.pCurrentMonData->m_shRGBX.fullSize = glGetUniformLocation(prog, "fullSize"); m_RenderData.pCurrentMonData->m_shRGBX.radius = glGetUniformLocation(prog, "radius"); + m_RenderData.pCurrentMonData->m_shRGBX.roundingPower = glGetUniformLocation(prog, "roundingPower"); m_RenderData.pCurrentMonData->m_shRGBX.applyTint = glGetUniformLocation(prog, "applyTint"); m_RenderData.pCurrentMonData->m_shRGBX.tint = glGetUniformLocation(prog, "tint"); @@ -1053,6 +1056,7 @@ void CHyprOpenGLImpl::initShaders() { m_RenderData.pCurrentMonData->m_shEXT.topLeft = glGetUniformLocation(prog, "topLeft"); m_RenderData.pCurrentMonData->m_shEXT.fullSize = glGetUniformLocation(prog, "fullSize"); m_RenderData.pCurrentMonData->m_shEXT.radius = glGetUniformLocation(prog, "radius"); + m_RenderData.pCurrentMonData->m_shEXT.roundingPower = glGetUniformLocation(prog, "roundingPower"); m_RenderData.pCurrentMonData->m_shEXT.applyTint = glGetUniformLocation(prog, "applyTint"); m_RenderData.pCurrentMonData->m_shEXT.tint = glGetUniformLocation(prog, "tint"); @@ -1097,18 +1101,19 @@ void CHyprOpenGLImpl::initShaders() { m_RenderData.pCurrentMonData->m_shBLURFINISH.brightness = glGetUniformLocation(prog, "brightness"); m_RenderData.pCurrentMonData->m_shBLURFINISH.noise = glGetUniformLocation(prog, "noise"); - prog = createProgram(QUADVERTSRC, FRAGSHADOW); - m_RenderData.pCurrentMonData->m_shSHADOW.program = prog; - m_RenderData.pCurrentMonData->m_shSHADOW.proj = glGetUniformLocation(prog, "proj"); - m_RenderData.pCurrentMonData->m_shSHADOW.posAttrib = glGetAttribLocation(prog, "pos"); - m_RenderData.pCurrentMonData->m_shSHADOW.texAttrib = glGetAttribLocation(prog, "texcoord"); - m_RenderData.pCurrentMonData->m_shSHADOW.topLeft = glGetUniformLocation(prog, "topLeft"); - m_RenderData.pCurrentMonData->m_shSHADOW.bottomRight = glGetUniformLocation(prog, "bottomRight"); - m_RenderData.pCurrentMonData->m_shSHADOW.fullSize = glGetUniformLocation(prog, "fullSize"); - m_RenderData.pCurrentMonData->m_shSHADOW.radius = glGetUniformLocation(prog, "radius"); - m_RenderData.pCurrentMonData->m_shSHADOW.range = glGetUniformLocation(prog, "range"); - m_RenderData.pCurrentMonData->m_shSHADOW.shadowPower = glGetUniformLocation(prog, "shadowPower"); - m_RenderData.pCurrentMonData->m_shSHADOW.color = glGetUniformLocation(prog, "color"); + prog = createProgram(QUADVERTSRC, FRAGSHADOW); + m_RenderData.pCurrentMonData->m_shSHADOW.program = prog; + m_RenderData.pCurrentMonData->m_shSHADOW.proj = glGetUniformLocation(prog, "proj"); + m_RenderData.pCurrentMonData->m_shSHADOW.posAttrib = glGetAttribLocation(prog, "pos"); + m_RenderData.pCurrentMonData->m_shSHADOW.texAttrib = glGetAttribLocation(prog, "texcoord"); + m_RenderData.pCurrentMonData->m_shSHADOW.topLeft = glGetUniformLocation(prog, "topLeft"); + m_RenderData.pCurrentMonData->m_shSHADOW.bottomRight = glGetUniformLocation(prog, "bottomRight"); + m_RenderData.pCurrentMonData->m_shSHADOW.fullSize = glGetUniformLocation(prog, "fullSize"); + m_RenderData.pCurrentMonData->m_shSHADOW.radius = glGetUniformLocation(prog, "radius"); + m_RenderData.pCurrentMonData->m_shSHADOW.roundingPower = glGetUniformLocation(prog, "roundingPower"); + m_RenderData.pCurrentMonData->m_shSHADOW.range = glGetUniformLocation(prog, "range"); + m_RenderData.pCurrentMonData->m_shSHADOW.shadowPower = glGetUniformLocation(prog, "shadowPower"); + m_RenderData.pCurrentMonData->m_shSHADOW.color = glGetUniformLocation(prog, "color"); prog = createProgram(QUADVERTSRC, FRAGBORDER1); m_RenderData.pCurrentMonData->m_shBORDER1.program = prog; @@ -1122,6 +1127,7 @@ void CHyprOpenGLImpl::initShaders() { m_RenderData.pCurrentMonData->m_shBORDER1.fullSizeUntransformed = glGetUniformLocation(prog, "fullSizeUntransformed"); m_RenderData.pCurrentMonData->m_shBORDER1.radius = glGetUniformLocation(prog, "radius"); m_RenderData.pCurrentMonData->m_shBORDER1.radiusOuter = glGetUniformLocation(prog, "radiusOuter"); + m_RenderData.pCurrentMonData->m_shBORDER1.roundingPower = glGetUniformLocation(prog, "roundingPower"); m_RenderData.pCurrentMonData->m_shBORDER1.gradient = glGetUniformLocation(prog, "gradient"); m_RenderData.pCurrentMonData->m_shBORDER1.gradient2 = glGetUniformLocation(prog, "gradient2"); m_RenderData.pCurrentMonData->m_shBORDER1.gradientLength = glGetUniformLocation(prog, "gradientLength"); @@ -1244,12 +1250,12 @@ void CHyprOpenGLImpl::scissor(const int x, const int y, const int w, const int h scissor(&box, transform); } -void CHyprOpenGLImpl::renderRect(CBox* box, const CHyprColor& col, int round) { +void CHyprOpenGLImpl::renderRect(CBox* box, const CHyprColor& col, int round, float roundingPower) { if (!m_RenderData.damage.empty()) - renderRectWithDamage(box, col, m_RenderData.damage, round); + renderRectWithDamage(box, col, m_RenderData.damage, round, roundingPower); } -void CHyprOpenGLImpl::renderRectWithBlur(CBox* box, const CHyprColor& col, int round, float blurA, bool xray) { +void CHyprOpenGLImpl::renderRectWithBlur(CBox* box, const CHyprColor& col, int round, float roundingPower, float blurA, bool xray) { if (m_RenderData.damage.empty()) return; @@ -1271,7 +1277,7 @@ void CHyprOpenGLImpl::renderRectWithBlur(CBox* box, const CHyprColor& col, int r glStencilOp(GL_KEEP, GL_KEEP, GL_REPLACE); glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE); - renderRect(box, CHyprColor(0, 0, 0, 0), round); + renderRect(box, CHyprColor(0, 0, 0, 0), round, roundingPower); glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE); glStencilFunc(GL_EQUAL, 1, 0xFF); @@ -1282,7 +1288,7 @@ void CHyprOpenGLImpl::renderRectWithBlur(CBox* box, const CHyprColor& col, int r m_bEndFrame = true; // fix transformed const auto SAVEDRENDERMODIF = m_RenderData.renderModif; m_RenderData.renderModif = {}; // fix shit - renderTextureInternalWithDamage(POUTFB->getTexture(), &MONITORBOX, blurA, damage, 0, false, false, false); + renderTextureInternalWithDamage(POUTFB->getTexture(), &MONITORBOX, blurA, damage, 0, 2.0f, false, false, false); m_bEndFrame = false; m_RenderData.renderModif = SAVEDRENDERMODIF; @@ -1293,10 +1299,10 @@ void CHyprOpenGLImpl::renderRectWithBlur(CBox* box, const CHyprColor& col, int r glStencilFunc(GL_ALWAYS, 1, 0xFF); scissor((CBox*)nullptr); - renderRectWithDamage(box, col, m_RenderData.damage, round); + renderRectWithDamage(box, col, m_RenderData.damage, round, roundingPower); } -void CHyprOpenGLImpl::renderRectWithDamage(CBox* box, const CHyprColor& col, const CRegion& damage, int round) { +void CHyprOpenGLImpl::renderRectWithDamage(CBox* box, const CHyprColor& col, const CRegion& damage, int round, float roundingPower) { RASSERT((box->width > 0 && box->height > 0), "Tried to render rect with width/height < 0!"); RASSERT(m_RenderData.pMonitor, "Tried to render rect without begin()!"); @@ -1334,6 +1340,7 @@ void CHyprOpenGLImpl::renderRectWithDamage(CBox* box, const CHyprColor& col, con glUniform2f(m_RenderData.pCurrentMonData->m_shQUAD.topLeft, (float)TOPLEFT.x, (float)TOPLEFT.y); glUniform2f(m_RenderData.pCurrentMonData->m_shQUAD.fullSize, (float)FULLSIZE.x, (float)FULLSIZE.y); glUniform1f(m_RenderData.pCurrentMonData->m_shQUAD.radius, round); + glUniform1f(m_RenderData.pCurrentMonData->m_shQUAD.roundingPower, roundingPower); glVertexAttribPointer(m_RenderData.pCurrentMonData->m_shQUAD.posAttrib, 2, GL_FLOAT, GL_FALSE, 0, fullVerts); @@ -1361,25 +1368,25 @@ void CHyprOpenGLImpl::renderRectWithDamage(CBox* box, const CHyprColor& col, con scissor((CBox*)nullptr); } -void CHyprOpenGLImpl::renderTexture(SP tex, CBox* pBox, float alpha, int round, bool discardActive, bool allowCustomUV) { +void CHyprOpenGLImpl::renderTexture(SP tex, CBox* pBox, float alpha, int round, float roundingPower, bool discardActive, bool allowCustomUV) { RASSERT(m_RenderData.pMonitor, "Tried to render texture without begin()!"); - renderTextureInternalWithDamage(tex, pBox, alpha, m_RenderData.damage, round, discardActive, false, allowCustomUV, true); + renderTextureInternalWithDamage(tex, pBox, alpha, m_RenderData.damage, round, roundingPower, discardActive, false, allowCustomUV, true); scissor((CBox*)nullptr); } -void CHyprOpenGLImpl::renderTextureWithDamage(SP tex, CBox* pBox, const CRegion& damage, float alpha, int round, bool discardActive, bool allowCustomUV, - SP waitTimeline, uint64_t waitPoint) { +void CHyprOpenGLImpl::renderTextureWithDamage(SP tex, CBox* pBox, const CRegion& damage, float alpha, int round, float roundingPower, bool discardActive, + bool allowCustomUV, SP waitTimeline, uint64_t waitPoint) { RASSERT(m_RenderData.pMonitor, "Tried to render texture without begin()!"); - renderTextureInternalWithDamage(tex, pBox, alpha, damage, round, discardActive, false, allowCustomUV, true, waitTimeline, waitPoint); + renderTextureInternalWithDamage(tex, pBox, alpha, damage, round, roundingPower, discardActive, false, allowCustomUV, true, waitTimeline, waitPoint); scissor((CBox*)nullptr); } -void CHyprOpenGLImpl::renderTextureInternalWithDamage(SP tex, CBox* pBox, float alpha, const CRegion& damage, int round, bool discardActive, bool noAA, - bool allowCustomUV, bool allowDim, SP waitTimeline, uint64_t waitPoint) { +void CHyprOpenGLImpl::renderTextureInternalWithDamage(SP tex, CBox* pBox, float alpha, const CRegion& damage, int round, float roundingPower, bool discardActive, + bool noAA, bool allowCustomUV, bool allowDim, SP waitTimeline, uint64_t waitPoint) { RASSERT(m_RenderData.pMonitor, "Tried to render texture without begin()!"); RASSERT((tex->m_iTexID > 0), "Attempted to draw nullptr texture!"); @@ -1506,6 +1513,7 @@ void CHyprOpenGLImpl::renderTextureInternalWithDamage(SP tex, CBox* pB glUniform2f(shader->topLeft, TOPLEFT.x, TOPLEFT.y); glUniform2f(shader->fullSize, FULLSIZE.x, FULLSIZE.y); glUniform1f(shader->radius, round); + glUniform1f(shader->roundingPower, roundingPower); if (allowDim && m_RenderData.currentWindow) { glUniform1i(shader->applyTint, 1); @@ -1997,7 +2005,7 @@ void CHyprOpenGLImpl::preBlurForCurrentMonitor() { clear(CHyprColor(0, 0, 0, 0)); m_bEndFrame = true; // fix transformed - renderTextureInternalWithDamage(POUTFB->getTexture(), &wholeMonitor, 1, fakeDamage, 0, false, true, false); + renderTextureInternalWithDamage(POUTFB->getTexture(), &wholeMonitor, 1, fakeDamage, 0, 2.0f, false, true, false); m_bEndFrame = false; m_RenderData.currentFB->bind(); @@ -2045,8 +2053,8 @@ bool CHyprOpenGLImpl::shouldUseNewBlurOptimizations(PHLLS pLayer, PHLWINDOW pWin return false; } -void CHyprOpenGLImpl::renderTextureWithBlur(SP tex, CBox* pBox, float a, SP pSurface, int round, bool blockBlurOptimization, float blurA, - float overallA) { +void CHyprOpenGLImpl::renderTextureWithBlur(SP tex, CBox* pBox, float a, SP pSurface, int round, float roundingPower, bool blockBlurOptimization, + float blurA, float overallA) { RASSERT(m_RenderData.pMonitor, "Tried to render texture with blur without begin()!"); static auto PNOBLUROVERSIZED = CConfigValue("decoration:no_blur_on_oversized"); @@ -2063,7 +2071,7 @@ void CHyprOpenGLImpl::renderTextureWithBlur(SP tex, CBox* pBox, float m_RenderData.renderModif.applyToRegion(texDamage); if (*PNOBLUROVERSIZED && m_RenderData.primarySurfaceUVTopLeft != Vector2D(-1, -1)) { - renderTexture(tex, pBox, a, round, false, true); + renderTexture(tex, pBox, a, round, roundingPower, false, true); return; } @@ -2076,7 +2084,7 @@ void CHyprOpenGLImpl::renderTextureWithBlur(SP tex, CBox* pBox, float inverseOpaque.invert(&surfbox).intersect(0, 0, pSurface->current.size.x * pSurface->current.scale, pSurface->current.size.y * pSurface->current.scale); if (inverseOpaque.empty()) { - renderTexture(tex, pBox, a, round, false, true); + renderTexture(tex, pBox, a, round, roundingPower, false, true); return; } } else { @@ -2112,9 +2120,9 @@ void CHyprOpenGLImpl::renderTextureWithBlur(SP tex, CBox* pBox, float glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE); if (USENEWOPTIMIZE && !(m_RenderData.discardMode & DISCARD_ALPHA)) - renderRect(pBox, CHyprColor(0, 0, 0, 0), round); + renderRect(pBox, CHyprColor(0, 0, 0, 0), round, roundingPower); else - renderTexture(tex, pBox, a, round, true, true); // discard opaque + renderTexture(tex, pBox, a, round, roundingPower, true, true); // discard opaque glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE); glStencilFunc(GL_EQUAL, 1, 0xFF); @@ -2127,7 +2135,7 @@ void CHyprOpenGLImpl::renderTextureWithBlur(SP tex, CBox* pBox, float setMonitorTransformEnabled(true); if (!USENEWOPTIMIZE) setRenderModifEnabled(false); - renderTextureInternalWithDamage(POUTFB->getTexture(), &MONITORBOX, (*PBLURIGNOREOPACITY ? blurA : a * blurA) * overallA, texDamage, 0, false, false, false); + renderTextureInternalWithDamage(POUTFB->getTexture(), &MONITORBOX, (*PBLURIGNOREOPACITY ? blurA : a * blurA) * overallA, texDamage, 0, 2.0f, false, false, false); if (!USENEWOPTIMIZE) setRenderModifEnabled(true); setMonitorTransformEnabled(false); @@ -2138,14 +2146,14 @@ void CHyprOpenGLImpl::renderTextureWithBlur(SP tex, CBox* pBox, float // draw window glDisable(GL_STENCIL_TEST); - renderTextureInternalWithDamage(tex, pBox, a * overallA, texDamage, round, false, false, true, true); + renderTextureInternalWithDamage(tex, pBox, a * overallA, texDamage, round, roundingPower, false, false, true, true); glStencilMask(0xFF); glStencilFunc(GL_ALWAYS, 1, 0xFF); scissor((CBox*)nullptr); } -void CHyprOpenGLImpl::renderBorder(CBox* box, const CGradientValueData& grad, int round, int borderSize, float a, int outerRound) { +void CHyprOpenGLImpl::renderBorder(CBox* box, const CGradientValueData& grad, int round, float roundingPower, int borderSize, float a, int outerRound) { RASSERT((box->width > 0 && box->height > 0), "Tried to render rect with width/height < 0!"); RASSERT(m_RenderData.pMonitor, "Tried to render rect without begin()!"); @@ -2207,6 +2215,7 @@ void CHyprOpenGLImpl::renderBorder(CBox* box, const CGradientValueData& grad, in glUniform2f(m_RenderData.pCurrentMonData->m_shBORDER1.fullSizeUntransformed, (float)box->width, (float)box->height); glUniform1f(m_RenderData.pCurrentMonData->m_shBORDER1.radius, round); glUniform1f(m_RenderData.pCurrentMonData->m_shBORDER1.radiusOuter, outerRound == -1 ? round : outerRound); + glUniform1f(m_RenderData.pCurrentMonData->m_shBORDER1.roundingPower, roundingPower); glUniform1f(m_RenderData.pCurrentMonData->m_shBORDER1.thick, scaledBorderSize); glVertexAttribPointer(m_RenderData.pCurrentMonData->m_shBORDER1.posAttrib, 2, GL_FLOAT, GL_FALSE, 0, fullVerts); @@ -2238,7 +2247,8 @@ void CHyprOpenGLImpl::renderBorder(CBox* box, const CGradientValueData& grad, in blend(BLEND); } -void CHyprOpenGLImpl::renderBorder(CBox* box, const CGradientValueData& grad1, const CGradientValueData& grad2, float lerp, int round, int borderSize, float a, int outerRound) { +void CHyprOpenGLImpl::renderBorder(CBox* box, const CGradientValueData& grad1, const CGradientValueData& grad2, float lerp, int round, float roundingPower, int borderSize, float a, + int outerRound) { RASSERT((box->width > 0 && box->height > 0), "Tried to render rect with width/height < 0!"); RASSERT(m_RenderData.pMonitor, "Tried to render rect without begin()!"); @@ -2304,6 +2314,7 @@ void CHyprOpenGLImpl::renderBorder(CBox* box, const CGradientValueData& grad1, c glUniform2f(m_RenderData.pCurrentMonData->m_shBORDER1.fullSizeUntransformed, (float)box->width, (float)box->height); glUniform1f(m_RenderData.pCurrentMonData->m_shBORDER1.radius, round); glUniform1f(m_RenderData.pCurrentMonData->m_shBORDER1.radiusOuter, outerRound == -1 ? round : outerRound); + glUniform1f(m_RenderData.pCurrentMonData->m_shBORDER1.roundingPower, roundingPower); glUniform1f(m_RenderData.pCurrentMonData->m_shBORDER1.thick, scaledBorderSize); glVertexAttribPointer(m_RenderData.pCurrentMonData->m_shBORDER1.posAttrib, 2, GL_FLOAT, GL_FALSE, 0, fullVerts); @@ -2335,7 +2346,7 @@ void CHyprOpenGLImpl::renderBorder(CBox* box, const CGradientValueData& grad1, c blend(BLEND); } -void CHyprOpenGLImpl::renderRoundedShadow(CBox* box, int round, int range, const CHyprColor& color, float a) { +void CHyprOpenGLImpl::renderRoundedShadow(CBox* box, int round, float roundingPower, int range, const CHyprColor& color, float a) { RASSERT(m_RenderData.pMonitor, "Tried to render shadow without begin()!"); RASSERT((box->width > 0 && box->height > 0), "Tried to render shadow with width/height < 0!"); RASSERT(m_RenderData.currentWindow, "Tried to render shadow without a window!"); @@ -2381,6 +2392,7 @@ void CHyprOpenGLImpl::renderRoundedShadow(CBox* box, int round, int range, const glUniform2f(m_RenderData.pCurrentMonData->m_shSHADOW.bottomRight, (float)BOTTOMRIGHT.x, (float)BOTTOMRIGHT.y); glUniform2f(m_RenderData.pCurrentMonData->m_shSHADOW.fullSize, (float)FULLSIZE.x, (float)FULLSIZE.y); glUniform1f(m_RenderData.pCurrentMonData->m_shSHADOW.radius, range + round); + glUniform1f(m_RenderData.pCurrentMonData->m_shSHADOW.roundingPower, roundingPower); glUniform1f(m_RenderData.pCurrentMonData->m_shSHADOW.range, range); glUniform1f(m_RenderData.pCurrentMonData->m_shSHADOW.shadowPower, SHADOWPOWER); @@ -2421,7 +2433,7 @@ void CHyprOpenGLImpl::saveBufferForMirror(CBox* box) { blend(false); - renderTexture(m_RenderData.currentFB->getTexture(), box, 1.f, 0, false, false); + renderTexture(m_RenderData.currentFB->getTexture(), box, 1.f, 0, 2.0f, false, false); blend(true); diff --git a/src/render/OpenGL.hpp b/src/render/OpenGL.hpp index 713816bc..3f117a5a 100644 --- a/src/render/OpenGL.hpp +++ b/src/render/OpenGL.hpp @@ -166,83 +166,84 @@ class CHyprOpenGLImpl { CHyprOpenGLImpl(); ~CHyprOpenGLImpl(); - void begin(PHLMONITOR, const CRegion& damage, CFramebuffer* fb = nullptr, std::optional finalDamage = {}); - void beginSimple(PHLMONITOR, const CRegion& damage, SP rb = nullptr, CFramebuffer* fb = nullptr); - void end(); + void begin(PHLMONITOR, const CRegion& damage, CFramebuffer* fb = nullptr, std::optional finalDamage = {}); + void beginSimple(PHLMONITOR, const CRegion& damage, SP rb = nullptr, CFramebuffer* fb = nullptr); + void end(); - void renderRect(CBox*, const CHyprColor&, int round = 0); - void renderRectWithBlur(CBox*, const CHyprColor&, int round = 0, float blurA = 1.f, bool xray = false); - void renderRectWithDamage(CBox*, const CHyprColor&, const CRegion& damage, int round = 0); - void renderTexture(SP, CBox*, float a, int round = 0, bool discardActive = false, bool allowCustomUV = false); - void renderTextureWithDamage(SP, CBox*, const CRegion& damage, float a, int round = 0, bool discardActive = false, bool allowCustomUV = false, - SP waitTimeline = nullptr, uint64_t waitPoint = 0); - void renderTextureWithBlur(SP, CBox*, float a, SP pSurface, int round = 0, bool blockBlurOptimization = false, float blurA = 1.f, - float overallA = 1.f); - void renderRoundedShadow(CBox*, int round, int range, const CHyprColor& color, float a = 1.0); - void renderBorder(CBox*, const CGradientValueData&, int round, int borderSize, float a = 1.0, int outerRound = -1 /* use round */); - void renderBorder(CBox*, const CGradientValueData&, const CGradientValueData&, float lerp, int round, int borderSize, float a = 1.0, int outerRound = -1 /* use round */); - void renderTextureMatte(SP tex, CBox* pBox, CFramebuffer& matte); + void renderRect(CBox*, const CHyprColor&, int round = 0, float roundingPower = 2.0f); + void renderRectWithBlur(CBox*, const CHyprColor&, int round = 0, float roundingPower = 2.0f, float blurA = 1.f, bool xray = false); + void renderRectWithDamage(CBox*, const CHyprColor&, const CRegion& damage, int round = 0, float roundingPower = 2.0f); + void renderTexture(SP, CBox*, float a, int round = 0, float roundingPower = 2.0f, bool discardActive = false, bool allowCustomUV = false); + void renderTextureWithDamage(SP, CBox*, const CRegion& damage, float a, int round = 0, float roundingPower = 2.0f, bool discardActive = false, + bool allowCustomUV = false, SP waitTimeline = nullptr, uint64_t waitPoint = 0); + void renderTextureWithBlur(SP, CBox*, float a, SP pSurface, int round = 0, float roundingPower = 2.0f, bool blockBlurOptimization = false, + float blurA = 1.f, float overallA = 1.f); + void renderRoundedShadow(CBox*, int round, float roundingPower, int range, const CHyprColor& color, float a = 1.0); + void renderBorder(CBox*, const CGradientValueData&, int round, float roundingPower, int borderSize, float a = 1.0, int outerRound = -1 /* use round */); + void renderBorder(CBox*, const CGradientValueData&, const CGradientValueData&, float lerp, int round, float roundingPower, int borderSize, float a = 1.0, + int outerRound = -1 /* use round */); + void renderTextureMatte(SP tex, CBox* pBox, CFramebuffer& matte); - void setMonitorTransformEnabled(bool enabled); - void setRenderModifEnabled(bool enabled); + void setMonitorTransformEnabled(bool enabled); + void setRenderModifEnabled(bool enabled); - void saveMatrix(); - void setMatrixScaleTranslate(const Vector2D& translate, const float& scale); - void restoreMatrix(); + void saveMatrix(); + void setMatrixScaleTranslate(const Vector2D& translate, const float& scale); + void restoreMatrix(); - void blend(bool enabled); + void blend(bool enabled); - bool shouldUseNewBlurOptimizations(PHLLS pLayer, PHLWINDOW pWindow); + bool shouldUseNewBlurOptimizations(PHLLS pLayer, PHLWINDOW pWindow); - void clear(const CHyprColor&); - void clearWithTex(); - void scissor(const CBox*, bool transform = true); - void scissor(const pixman_box32*, bool transform = true); - void scissor(const int x, const int y, const int w, const int h, bool transform = true); + void clear(const CHyprColor&); + void clearWithTex(); + void scissor(const CBox*, bool transform = true); + void scissor(const pixman_box32*, bool transform = true); + void scissor(const int x, const int y, const int w, const int h, bool transform = true); - void destroyMonitorResources(PHLMONITOR); + void destroyMonitorResources(PHLMONITOR); - void markBlurDirtyForMonitor(PHLMONITOR); + void markBlurDirtyForMonitor(PHLMONITOR); - void preWindowPass(); - bool preBlurQueued(); - void preRender(PHLMONITOR); + void preWindowPass(); + bool preBlurQueued(); + void preRender(PHLMONITOR); - void saveBufferForMirror(CBox*); - void renderMirrored(); + void saveBufferForMirror(CBox*); + void renderMirrored(); - void applyScreenShader(const std::string& path); + void applyScreenShader(const std::string& path); - void bindOffMain(); - void renderOffToMain(CFramebuffer* off); - void bindBackOnMain(); + void bindOffMain(); + void renderOffToMain(CFramebuffer* off); + void bindBackOnMain(); - SP loadAsset(const std::string& file); - SP renderText(const std::string& text, CHyprColor col, int pt, bool italic = false, const std::string& fontFamily = "", int maxWidth = 0); + SP loadAsset(const std::string& file); + SP renderText(const std::string& text, CHyprColor col, int pt, bool italic = false, const std::string& fontFamily = "", int maxWidth = 0); - void setDamage(const CRegion& damage, std::optional finalDamage = {}); + void setDamage(const CRegion& damage, std::optional finalDamage = {}); - uint32_t getPreferredReadFormat(PHLMONITOR pMonitor); - std::vector getDRMFormats(); - EGLImageKHR createEGLImage(const Aquamarine::SDMABUFAttrs& attrs); - SP createEGLSync(int fenceFD); - bool waitForTimelinePoint(SP timeline, uint64_t point); + uint32_t getPreferredReadFormat(PHLMONITOR pMonitor); + std::vector getDRMFormats(); + EGLImageKHR createEGLImage(const Aquamarine::SDMABUFAttrs& attrs); + SP createEGLSync(int fenceFD); + bool waitForTimelinePoint(SP timeline, uint64_t point); - SCurrentRenderData m_RenderData; + SCurrentRenderData m_RenderData; - GLint m_iCurrentOutputFb = 0; + GLint m_iCurrentOutputFb = 0; - int m_iGBMFD = -1; - gbm_device* m_pGbmDevice = nullptr; - EGLContext m_pEglContext = nullptr; - EGLDisplay m_pEglDisplay = nullptr; - EGLDeviceEXT m_pEglDevice = nullptr; - uint failedAssetsNo = 0; + int m_iGBMFD = -1; + gbm_device* m_pGbmDevice = nullptr; + EGLContext m_pEglContext = nullptr; + EGLDisplay m_pEglDisplay = nullptr; + EGLDeviceEXT m_pEglDevice = nullptr; + uint failedAssetsNo = 0; - bool m_bReloadScreenShader = true; // at launch it can be set + bool m_bReloadScreenShader = true; // at launch it can be set - std::map m_mWindowFramebuffers; - std::map m_mLayerFramebuffers; + std::map m_mWindowFramebuffers; + std::map m_mLayerFramebuffers; std::map m_mMonitorRenderResources; std::map m_mMonitorBGFBs; @@ -311,8 +312,8 @@ class CHyprOpenGLImpl { // returns the out FB, can be either Mirror or MirrorSwap CFramebuffer* blurMainFramebufferWithDamage(float a, CRegion* damage); - void renderTextureInternalWithDamage(SP, CBox* pBox, float a, const CRegion& damage, int round = 0, bool discardOpaque = false, bool noAA = false, - bool allowCustomUV = false, bool allowDim = false, SP = nullptr, uint64_t waitPoint = 0); + void renderTextureInternalWithDamage(SP, CBox* pBox, float a, const CRegion& damage, int round = 0, float roundingPower = 2.0f, bool discardOpaque = false, + bool noAA = false, bool allowCustomUV = false, bool allowDim = false, SP = nullptr, uint64_t waitPoint = 0); void renderTexturePrimitive(SP tex, CBox* pBox); void renderSplash(cairo_t* const, cairo_surface_t* const, double offset, const Vector2D& size); diff --git a/src/render/Renderer.cpp b/src/render/Renderer.cpp index 35150ce2..d154e64a 100644 --- a/src/render/Renderer.cpp +++ b/src/render/Renderer.cpp @@ -460,11 +460,12 @@ void CHyprRenderer::renderWindow(PHLWINDOW pWindow, PHLMONITOR pMonitor, timespe renderdata.dontRound = pWindow->isEffectiveInternalFSMode(FSMODE_FULLSCREEN) || pWindow->m_sWindowData.noRounding.valueOrDefault(); renderdata.fadeAlpha = pWindow->m_fAlpha.value() * (pWindow->m_bPinned || USE_WORKSPACE_FADE_ALPHA ? 1.f : PWORKSPACE->m_fAlpha.value()) * (USE_WORKSPACE_FADE_ALPHA ? pWindow->m_fMovingToWorkspaceAlpha.value() : 1.F) * pWindow->m_fMovingFromWorkspaceAlpha.value(); - renderdata.alpha = pWindow->m_fActiveInactiveAlpha.value(); - renderdata.decorate = decorate && !pWindow->m_bX11DoesntWantBorders && !pWindow->isEffectiveInternalFSMode(FSMODE_FULLSCREEN); - renderdata.rounding = ignoreAllGeometry || renderdata.dontRound ? 0 : pWindow->rounding() * pMonitor->scale; - renderdata.blur = !ignoreAllGeometry && *PBLUR && !DONT_BLUR; - renderdata.pWindow = pWindow; + renderdata.alpha = pWindow->m_fActiveInactiveAlpha.value(); + renderdata.decorate = decorate && !pWindow->m_bX11DoesntWantBorders && !pWindow->isEffectiveInternalFSMode(FSMODE_FULLSCREEN); + renderdata.rounding = ignoreAllGeometry || renderdata.dontRound ? 0 : pWindow->rounding() * pMonitor->scale; + renderdata.roundingPower = ignoreAllGeometry || renderdata.dontRound ? 2.0f : pWindow->roundingPower(); + renderdata.blur = !ignoreAllGeometry && *PBLUR && !DONT_BLUR; + renderdata.pWindow = pWindow; if (ignoreAllGeometry) { renderdata.alpha = 1.f; diff --git a/src/render/Shader.hpp b/src/render/Shader.hpp index eaf9da96..666ee9d4 100644 --- a/src/render/Shader.hpp +++ b/src/render/Shader.hpp @@ -26,6 +26,7 @@ class CShader { GLint fullSizeUntransformed = -1; GLint radius = -1; GLint radiusOuter = -1; + GLfloat roundingPower = -1; GLint thick = -1; diff --git a/src/render/decorations/CHyprBorderDecoration.cpp b/src/render/decorations/CHyprBorderDecoration.cpp index 4a793eab..2bc894ef 100644 --- a/src/render/decorations/CHyprBorderDecoration.cpp +++ b/src/render/decorations/CHyprBorderDecoration.cpp @@ -67,15 +67,17 @@ void CHyprBorderDecoration::draw(PHLMONITOR pMonitor, float const& a) { grad.m_fAngle = normalizeAngleRad(grad.m_fAngle); } - int borderSize = m_pWindow->getRealBorderSize(); - const auto ROUNDING = m_pWindow->rounding() * pMonitor->scale; + int borderSize = m_pWindow->getRealBorderSize(); + const auto ROUNDING = m_pWindow->rounding() * pMonitor->scale; + const auto ROUNDINGPOWER = m_pWindow->roundingPower(); CBorderPassElement::SBorderData data; - data.box = windowBox; - data.grad1 = grad; - data.round = ROUNDING; - data.a = a; - data.borderSize = borderSize; + data.box = windowBox; + data.grad1 = grad; + data.round = ROUNDING; + data.roundingPower = ROUNDINGPOWER; + data.a = a; + data.borderSize = borderSize; if (ANIMATED) { data.hasGrad2 = true; diff --git a/src/render/decorations/CHyprDropShadowDecoration.cpp b/src/render/decorations/CHyprDropShadowDecoration.cpp index 21242b57..07dbb436 100644 --- a/src/render/decorations/CHyprDropShadowDecoration.cpp +++ b/src/render/decorations/CHyprDropShadowDecoration.cpp @@ -55,6 +55,7 @@ void CHyprDropShadowDecoration::damageEntire() { static auto PSHADOWIGNOREWINDOW = CConfigValue("decoration:shadow:ignore_window"); const auto ROUNDING = PWINDOW->rounding(); + const auto ROUNDINGPOWER = PWINDOW->roundingPower(); const auto ROUNDINGSIZE = ROUNDING - M_SQRT1_2 * ROUNDING + 1; CRegion shadowRegion(shadowBox); @@ -119,6 +120,7 @@ void CHyprDropShadowDecoration::render(PHLMONITOR pMonitor, float const& a) { return; // disabled const auto ROUNDINGBASE = PWINDOW->rounding(); + const auto ROUNDINGPOWER = PWINDOW->roundingPower(); const auto ROUNDING = ROUNDINGBASE > 0 ? ROUNDINGBASE + PWINDOW->getRealBorderSize() : 0; const auto PWORKSPACE = PWINDOW->m_pWorkspace; const auto WORKSPACEOFFSET = PWORKSPACE && !PWINDOW->m_bPinned ? PWORKSPACE->m_vRenderOffset.value() : Vector2D(); @@ -192,10 +194,10 @@ void CHyprDropShadowDecoration::render(PHLMONITOR pMonitor, float const& a) { g_pHyprOpenGL->renderRect(&fullBox, CHyprColor(0, 0, 0, 1), 0); // render white shadow with the alpha of the shadow color (otherwise we clear with alpha later and shit it to 2 bit) - drawShadowInternal(&fullBox, ROUNDING * pMonitor->scale, *PSHADOWSIZE * pMonitor->scale, CHyprColor(1, 1, 1, PWINDOW->m_cRealShadowColor.value().a), a); + drawShadowInternal(&fullBox, ROUNDING * pMonitor->scale, ROUNDINGPOWER, *PSHADOWSIZE * pMonitor->scale, CHyprColor(1, 1, 1, PWINDOW->m_cRealShadowColor.value().a), a); // render black window box ("clip") - g_pHyprOpenGL->renderRect(&windowBox, CHyprColor(0, 0, 0, 1.0), (ROUNDING + 1 /* This fixes small pixel gaps. */) * pMonitor->scale); + g_pHyprOpenGL->renderRect(&windowBox, CHyprColor(0, 0, 0, 1.0), (ROUNDING + 1 /* This fixes small pixel gaps. */) * pMonitor->scale, ROUNDINGPOWER); alphaSwapFB.bind(); @@ -214,7 +216,7 @@ void CHyprDropShadowDecoration::render(PHLMONITOR pMonitor, float const& a) { g_pHyprOpenGL->m_RenderData.damage = saveDamage; } else - drawShadowInternal(&fullBox, ROUNDING * pMonitor->scale, *PSHADOWSIZE * pMonitor->scale, PWINDOW->m_cRealShadowColor.value(), a); + drawShadowInternal(&fullBox, ROUNDING * pMonitor->scale, ROUNDINGPOWER, *PSHADOWSIZE * pMonitor->scale, PWINDOW->m_cRealShadowColor.value(), a); if (m_seExtents != m_seReportedExtents) g_pDecorationPositioner->repositionDeco(this); @@ -226,7 +228,7 @@ eDecorationLayer CHyprDropShadowDecoration::getDecorationLayer() { return DECORATION_LAYER_BOTTOM; } -void CHyprDropShadowDecoration::drawShadowInternal(CBox* box, int round, int range, CHyprColor color, float a) { +void CHyprDropShadowDecoration::drawShadowInternal(CBox* box, int round, float roundingPower, int range, CHyprColor color, float a) { static auto PSHADOWSHARP = CConfigValue("decoration:shadow:sharp"); g_pHyprOpenGL->blend(true); @@ -234,7 +236,7 @@ void CHyprDropShadowDecoration::drawShadowInternal(CBox* box, int round, int ran color.a *= a; if (*PSHADOWSHARP) - g_pHyprOpenGL->renderRect(box, color, round); + g_pHyprOpenGL->renderRect(box, color, round, roundingPower); else - g_pHyprOpenGL->renderRoundedShadow(box, round, range, color, 1.F); + g_pHyprOpenGL->renderRoundedShadow(box, round, roundingPower, range, color, 1.F); } diff --git a/src/render/decorations/CHyprDropShadowDecoration.hpp b/src/render/decorations/CHyprDropShadowDecoration.hpp index fe0f8952..93fa3d1a 100644 --- a/src/render/decorations/CHyprDropShadowDecoration.hpp +++ b/src/render/decorations/CHyprDropShadowDecoration.hpp @@ -36,7 +36,7 @@ class CHyprDropShadowDecoration : public IHyprWindowDecoration { Vector2D m_vLastWindowPos; Vector2D m_vLastWindowSize; - void drawShadowInternal(CBox* box, int round, int range, CHyprColor color, float a); + void drawShadowInternal(CBox* box, int round, float roundingPower, int range, CHyprColor color, float a); CBox m_bLastWindowBox = {0}; CBox m_bLastWindowBoxWithDecos = {0}; diff --git a/src/render/pass/BorderPassElement.cpp b/src/render/pass/BorderPassElement.cpp index 635533d0..ceeec6f3 100644 --- a/src/render/pass/BorderPassElement.cpp +++ b/src/render/pass/BorderPassElement.cpp @@ -7,9 +7,9 @@ CBorderPassElement::CBorderPassElement(const CBorderPassElement::SBorderData& da void CBorderPassElement::draw(const CRegion& damage) { if (data.hasGrad2) - g_pHyprOpenGL->renderBorder(&data.box, data.grad1, data.grad2, data.lerp, data.round, data.borderSize, data.a, data.outerRound); + g_pHyprOpenGL->renderBorder(&data.box, data.grad1, data.grad2, data.lerp, data.round, data.roundingPower, data.borderSize, data.a, data.outerRound); else - g_pHyprOpenGL->renderBorder(&data.box, data.grad1, data.round, data.borderSize, data.a, data.outerRound); + g_pHyprOpenGL->renderBorder(&data.box, data.grad1, data.round, data.roundingPower, data.borderSize, data.a, data.outerRound); } bool CBorderPassElement::needsLiveBlur() { @@ -18,4 +18,4 @@ bool CBorderPassElement::needsLiveBlur() { bool CBorderPassElement::needsPrecomputeBlur() { return false; -} \ No newline at end of file +} diff --git a/src/render/pass/BorderPassElement.hpp b/src/render/pass/BorderPassElement.hpp index 3a529640..785653ab 100644 --- a/src/render/pass/BorderPassElement.hpp +++ b/src/render/pass/BorderPassElement.hpp @@ -12,6 +12,7 @@ class CBorderPassElement : public IPassElement { bool hasGrad2 = false; float lerp = 0.F, a = 1.F; int round = 0, borderSize = 1, outerRound = -1; + float roundingPower = 2.F; }; CBorderPassElement(const SBorderData& data_); diff --git a/src/render/pass/RectPassElement.cpp b/src/render/pass/RectPassElement.cpp index 25a550b3..a57c959e 100644 --- a/src/render/pass/RectPassElement.cpp +++ b/src/render/pass/RectPassElement.cpp @@ -10,9 +10,9 @@ void CRectPassElement::draw(const CRegion& damage) { return; if (data.color.a == 1.F || !data.blur) - g_pHyprOpenGL->renderRectWithDamage(&data.box, data.color, damage, data.round); + g_pHyprOpenGL->renderRectWithDamage(&data.box, data.color, damage, data.round, data.roundingPower); else - g_pHyprOpenGL->renderRectWithBlur(&data.box, data.color, data.round, data.blurA, data.xray); + g_pHyprOpenGL->renderRectWithBlur(&data.box, data.color, data.round, data.roundingPower, data.blurA, data.xray); } bool CRectPassElement::needsLiveBlur() { diff --git a/src/render/pass/RectPassElement.hpp b/src/render/pass/RectPassElement.hpp index 32111a43..d27abdcc 100644 --- a/src/render/pass/RectPassElement.hpp +++ b/src/render/pass/RectPassElement.hpp @@ -6,7 +6,8 @@ class CRectPassElement : public IPassElement { struct SRectData { CBox box; CHyprColor color; - int round = 0; + int round = 0; + float roundingPower = 2.0f; bool blur = false, xray = false; float blurA = 1.F; }; @@ -26,4 +27,4 @@ class CRectPassElement : public IPassElement { private: SRectData data; -}; \ No newline at end of file +}; diff --git a/src/render/pass/SurfacePassElement.cpp b/src/render/pass/SurfacePassElement.cpp index bdb21338..13e9e741 100644 --- a/src/render/pass/SurfacePassElement.cpp +++ b/src/render/pass/SurfacePassElement.cpp @@ -88,12 +88,15 @@ void CSurfacePassElement::draw(const CRegion& damage) { if (MISALIGNEDFSV1) g_pHyprOpenGL->m_RenderData.useNearestNeighbor = true; - float rounding = data.rounding; + float rounding = data.rounding; + float roundingPower = data.roundingPower; rounding -= 1; // to fix a border issue - if (data.dontRound) - rounding = 0; + if (data.dontRound) { + rounding = 0; + roundingPower = 2.0f; + } const bool WINDOWOPAQUE = data.pWindow && data.pWindow->m_pWLSurface->resource() == data.surface ? data.pWindow->opaque() : false; const bool CANDISABLEBLEND = ALPHA >= 1.f && OVERALL_ALPHA >= 1.f && rounding == 0 && WINDOWOPAQUE; @@ -108,14 +111,14 @@ void CSurfacePassElement::draw(const CRegion& damage) { // to what we do for misaligned surfaces (blur the entire thing and then render shit without blur) if (data.surfaceCounter == 0 && !data.popup) { if (BLUR) - g_pHyprOpenGL->renderTextureWithBlur(TEXTURE, &windowBox, ALPHA, data.surface, rounding, data.blockBlurOptimization, data.fadeAlpha, OVERALL_ALPHA); + g_pHyprOpenGL->renderTextureWithBlur(TEXTURE, &windowBox, ALPHA, data.surface, rounding, roundingPower, data.blockBlurOptimization, data.fadeAlpha, OVERALL_ALPHA); else - g_pHyprOpenGL->renderTexture(TEXTURE, &windowBox, ALPHA * OVERALL_ALPHA, rounding, false, true); + g_pHyprOpenGL->renderTexture(TEXTURE, &windowBox, ALPHA * OVERALL_ALPHA, rounding, roundingPower, false, true); } else { if (BLUR && data.popup) - g_pHyprOpenGL->renderTextureWithBlur(TEXTURE, &windowBox, ALPHA, data.surface, rounding, true, data.fadeAlpha, OVERALL_ALPHA); + g_pHyprOpenGL->renderTextureWithBlur(TEXTURE, &windowBox, ALPHA, data.surface, rounding, roundingPower, true, data.fadeAlpha, OVERALL_ALPHA); else - g_pHyprOpenGL->renderTexture(TEXTURE, &windowBox, ALPHA * OVERALL_ALPHA, rounding, false, true); + g_pHyprOpenGL->renderTexture(TEXTURE, &windowBox, ALPHA * OVERALL_ALPHA, rounding, roundingPower, false, true); } if (!g_pHyprRenderer->m_bBlockSurfaceFeedback) diff --git a/src/render/pass/SurfacePassElement.hpp b/src/render/pass/SurfacePassElement.hpp index 746c5a64..14d8ef14 100644 --- a/src/render/pass/SurfacePassElement.hpp +++ b/src/render/pass/SurfacePassElement.hpp @@ -35,6 +35,9 @@ class CSurfacePassElement : public IPassElement { // for custom round values int rounding = -1; // -1 means not set + // for custom rounding powers + float roundingPower = 2.0f; + // for blurring bool blur = false; bool blockBlurOptimization = false; @@ -79,4 +82,4 @@ class CSurfacePassElement : public IPassElement { SRenderData data; CBox getTexBox(); -}; \ No newline at end of file +}; diff --git a/src/render/pass/TexPassElement.cpp b/src/render/pass/TexPassElement.cpp index 05f756dc..0624a786 100644 --- a/src/render/pass/TexPassElement.cpp +++ b/src/render/pass/TexPassElement.cpp @@ -18,7 +18,8 @@ void CTexPassElement::draw(const CRegion& damage) { if (data.replaceProjection) g_pHyprOpenGL->m_RenderData.monitorProjection = *data.replaceProjection; - g_pHyprOpenGL->renderTextureInternalWithDamage(data.tex, &data.box, data.a, data.damage.empty() ? damage : data.damage, data.round, data.syncTimeline, data.syncPoint); + g_pHyprOpenGL->renderTextureInternalWithDamage(data.tex, &data.box, data.a, data.damage.empty() ? damage : data.damage, data.round, data.roundingPower, data.syncTimeline, + data.syncPoint); if (data.replaceProjection) g_pHyprOpenGL->m_RenderData.monitorProjection = g_pHyprOpenGL->m_RenderData.pMonitor->projMatrix; } diff --git a/src/render/pass/TexPassElement.hpp b/src/render/pass/TexPassElement.hpp index bf896951..036b89fe 100644 --- a/src/render/pass/TexPassElement.hpp +++ b/src/render/pass/TexPassElement.hpp @@ -13,8 +13,9 @@ class CTexPassElement : public IPassElement { CBox box; float a = 1.F; CRegion damage; - int round = 0; - bool flipEndFrame = false; + int round = 0; + float roundingPower = 2.0f; + bool flipEndFrame = false; SP syncTimeline; int64_t syncPoint = 0; std::optional replaceProjection; @@ -36,4 +37,4 @@ class CTexPassElement : public IPassElement { private: SRenderData data; -}; \ No newline at end of file +}; diff --git a/src/render/shaders/Border.hpp b/src/render/shaders/Border.hpp index acd3f3ff..3b9a91f0 100644 --- a/src/render/shaders/Border.hpp +++ b/src/render/shaders/Border.hpp @@ -15,6 +15,7 @@ uniform vec2 fullSize; uniform vec2 fullSizeUntransformed; uniform float radius; uniform float radiusOuter; +uniform float roundingPower; uniform float thick; // Gradients are in OkLabA!!!! {l, a, b, alpha} @@ -138,9 +139,9 @@ void main() { const float SMOOTHING_CONSTANT = )#" + std::format("{:.7f}", SHADER_ROUNDED_SMOOTHING_FACTOR) + R"#(; - float dist = length(pixCoord); - float distOuter = length(pixCoordOuter); - float h = (thick / 2.0); + float dist = pow(pow(pixCoord.x,roundingPower)+pow(pixCoord.y,roundingPower),1.0/roundingPower); + float distOuter = pow(pow(pixCoordOuter.x,roundingPower)+pow(pixCoordOuter.y,roundingPower),1.0/roundingPower); + float h = (thick / 2.0); if (dist < radius - h) { // lower diff --git a/src/render/shaders/Shadow.hpp b/src/render/shaders/Shadow.hpp index 0acab6b7..c04d4bf3 100644 --- a/src/render/shaders/Shadow.hpp +++ b/src/render/shaders/Shadow.hpp @@ -11,6 +11,7 @@ uniform vec2 topLeft; uniform vec2 bottomRight; uniform vec2 fullSize; uniform float radius; +uniform float roundingPower; uniform float range; uniform float shadowPower; @@ -26,6 +27,10 @@ float pixAlphaRoundedDistance(float distanceToCorner) { return 1.0; } +float modifiedLength(vec2 a) { + return pow(pow(abs(a.x),roundingPower)+pow(abs(a.y),roundingPower),1.0/roundingPower); +} + void main() { vec4 pixColor = v_color; @@ -40,21 +45,21 @@ void main() { if (pixCoord[0] < topLeft[0]) { if (pixCoord[1] < topLeft[1]) { // top left - pixColor[3] = pixColor[3] * pixAlphaRoundedDistance(distance(pixCoord, topLeft)); + pixColor[3] = pixColor[3] * pixAlphaRoundedDistance(modifiedLength(pixCoord - topLeft)); done = true; } else if (pixCoord[1] > bottomRight[1]) { // bottom left - pixColor[3] = pixColor[3] * pixAlphaRoundedDistance(distance(pixCoord, vec2(topLeft[0], bottomRight[1]))); + pixColor[3] = pixColor[3] * pixAlphaRoundedDistance(modifiedLength(pixCoord - vec2(topLeft[0], bottomRight[1]))); done = true; } } else if (pixCoord[0] > bottomRight[0]) { if (pixCoord[1] < topLeft[1]) { // top right - pixColor[3] = pixColor[3] * pixAlphaRoundedDistance(distance(pixCoord, vec2(bottomRight[0], topLeft[1]))); + pixColor[3] = pixColor[3] * pixAlphaRoundedDistance(modifiedLength(pixCoord - vec2(bottomRight[0], topLeft[1]))); done = true; } else if (pixCoord[1] > bottomRight[1]) { // bottom right - pixColor[3] = pixColor[3] * pixAlphaRoundedDistance(distance(pixCoord, bottomRight)); + pixColor[3] = pixColor[3] * pixAlphaRoundedDistance(modifiedLength(pixCoord - bottomRight)); done = true; } } diff --git a/src/render/shaders/Textures.hpp b/src/render/shaders/Textures.hpp index b203ad04..49d27b4c 100644 --- a/src/render/shaders/Textures.hpp +++ b/src/render/shaders/Textures.hpp @@ -19,23 +19,18 @@ inline static constexpr auto ROUNDED_SHADER_FUNC = [](const std::string colorVar const float SMOOTHING_CONSTANT = )#" + std::format("{:.7f}", SHADER_ROUNDED_SMOOTHING_FACTOR) + R"#(; - if (pixCoord.x + pixCoord.y > radius) { + //if (pixCoord.x + pixCoord.y > radius) { - float dist = length(pixCoord); + float dist = pow(pow(pixCoord.x, roundingPower) + pow(pixCoord.y, roundingPower), 1.0/roundingPower); - if (dist > radius + SMOOTHING_CONSTANT * 2.0) - discard; + if (dist > radius + SMOOTHING_CONSTANT) + discard; - if (dist > radius - SMOOTHING_CONSTANT * 2.0) { - float dist = length(pixCoord); + float normalized = 1.0 - smoothstep(0.0, 1.0, (dist - radius + SMOOTHING_CONSTANT) / (SMOOTHING_CONSTANT * 2.0)); - float normalized = 1.0 - smoothstep(0.0, 1.0, (dist - radius + SMOOTHING_CONSTANT) / (SMOOTHING_CONSTANT * 2.0)); - - )#" + + )#" + colorVarName + R"#( = )#" + colorVarName + R"#( * normalized; - } - - } + //} )#"; }; @@ -63,6 +58,7 @@ varying vec4 v_color; uniform vec2 topLeft; uniform vec2 fullSize; uniform float radius; +uniform float roundingPower; void main() { @@ -107,6 +103,7 @@ uniform float alpha; uniform vec2 topLeft; uniform vec2 fullSize; uniform float radius; +uniform float roundingPower; uniform int discardOpaque; uniform int discardAlpha; @@ -167,6 +164,7 @@ uniform float alpha; uniform vec2 topLeft; uniform vec2 fullSize; uniform float radius; +uniform float roundingPower; uniform int discardOpaque; uniform int discardAlpha; @@ -440,6 +438,7 @@ uniform float alpha; uniform vec2 topLeft; uniform vec2 fullSize; uniform float radius; +uniform float roundingPower; uniform int discardOpaque; uniform int discardAlpha; From 391ff29110e3fb9711b98e92cee44182dda2e2ba Mon Sep 17 00:00:00 2001 From: vaxerski Date: Sun, 5 Jan 2025 19:49:27 +0100 Subject: [PATCH 0812/2181] pass: improve pass debug mode --- src/render/pass/Pass.cpp | 42 +++++++++++++++++++++++++++++++++++----- src/render/pass/Pass.hpp | 6 +++--- 2 files changed, 40 insertions(+), 8 deletions(-) diff --git a/src/render/pass/Pass.cpp b/src/render/pass/Pass.cpp index 3e1282f0..0489e985 100644 --- a/src/render/pass/Pass.cpp +++ b/src/render/pass/Pass.cpp @@ -88,7 +88,7 @@ void CRenderPass::simplify() { } newDamage.subtract(opaque); if (*PDEBUGPASS) - occludedRegion.add(opaque); + occludedRegions.emplace_back(opaque); } } @@ -114,9 +114,11 @@ CRegion CRenderPass::render(const CRegion& damage_) { const auto WILLBLUR = std::ranges::any_of(m_vPassElements, [](const auto& el) { return el->element->needsLiveBlur(); }); - damage = *PDEBUGPASS ? CRegion{CBox{{}, {INT32_MAX, INT32_MAX}}} : damage_.copy(); - occludedRegion = CRegion{}; - totalLiveBlurRegion = CRegion{}; + damage = *PDEBUGPASS ? CRegion{CBox{{}, {INT32_MAX, INT32_MAX}}} : damage_.copy(); + if (*PDEBUGPASS) { + occludedRegions.clear(); + totalLiveBlurRegion = CRegion{}; + } if (damage.empty()) { g_pHyprOpenGL->m_RenderData.damage = damage; @@ -198,7 +200,9 @@ CRegion CRenderPass::render(const CRegion& damage_) { void CRenderPass::renderDebugData() { CBox box = {{}, g_pHyprOpenGL->m_RenderData.pMonitor->vecTransformedSize}; - g_pHyprOpenGL->renderRectWithDamage(&box, Colors::RED.modifyA(0.1F), occludedRegion); + for (const auto& rg : occludedRegions) { + g_pHyprOpenGL->renderRectWithDamage(&box, Colors::RED.modifyA(0.1F), rg); + } g_pHyprOpenGL->renderRectWithDamage(&box, Colors::GREEN.modifyA(0.1F), totalLiveBlurRegion); std::unordered_map offsets; @@ -239,6 +243,34 @@ void CRenderPass::renderDebugData() { renderHLSurface(debugData.pointerFocusText, g_pSeatManager->state.pointerFocus.lock(), Colors::ORANGE.modifyA(0.1F)); if (g_pCompositor->m_pLastWindow) renderHLSurface(debugData.lastWindowText, g_pCompositor->m_pLastWindow->m_pWLSurface->resource(), Colors::LIGHT_BLUE.modifyA(0.1F)); + + const auto DISCARDED_ELEMENTS = std::count_if(m_vPassElements.begin(), m_vPassElements.end(), [](const auto& e) { return e->discard; }); + auto tex = g_pHyprOpenGL->renderText(std::format("occlusion layers: {}\npass elements: {} ({} discarded)\nviewport: {:X0}", occludedRegions.size(), m_vPassElements.size(), + DISCARDED_ELEMENTS, g_pHyprOpenGL->m_RenderData.pMonitor->vecPixelSize), + Colors::WHITE, 12); + + if (tex) { + box = CBox{{0.F, g_pHyprOpenGL->m_RenderData.pMonitor->vecSize.y - tex->m_vSize.y}, tex->m_vSize}.scale(g_pHyprOpenGL->m_RenderData.pMonitor->scale); + g_pHyprOpenGL->renderTexture(tex, &box, 1.F); + } + + std::string passStructure; + auto yn = [](const bool val) -> const char* { return val ? "yes" : "no"; }; + auto tick = [](const bool val) -> const char* { return val ? "✔" : "✖"; }; + for (const auto& el : m_vPassElements | std::views::reverse) { + passStructure += std::format("{} {} (bb: {} op: {})\n", tick(!el->discard), el->element->passName(), yn(el->element->boundingBox().has_value()), + yn(!el->element->opaqueRegion().empty())); + } + + if (!passStructure.empty()) + passStructure.pop_back(); + + tex = g_pHyprOpenGL->renderText(passStructure, Colors::WHITE, 12); + if (tex) { + box = CBox{{g_pHyprOpenGL->m_RenderData.pMonitor->vecSize.x - tex->m_vSize.x, g_pHyprOpenGL->m_RenderData.pMonitor->vecSize.y - tex->m_vSize.y}, tex->m_vSize}.scale( + g_pHyprOpenGL->m_RenderData.pMonitor->scale); + g_pHyprOpenGL->renderTexture(tex, &box, 1.F); + } } float CRenderPass::oneBlurRadius() { diff --git a/src/render/pass/Pass.hpp b/src/render/pass/Pass.hpp index 5fa25fc3..a0810155 100644 --- a/src/render/pass/Pass.hpp +++ b/src/render/pass/Pass.hpp @@ -19,9 +19,9 @@ class CRenderPass { CRegion render(const CRegion& damage_); private: - CRegion damage; - CRegion occludedRegion; - CRegion totalLiveBlurRegion; + CRegion damage; + std::vector occludedRegions; + CRegion totalLiveBlurRegion; struct SPassElementData { CRegion elementDamage; From 1b06d222cf5abfc9802f7787315a8190f011d43e Mon Sep 17 00:00:00 2001 From: vaxerski Date: Sun, 5 Jan 2025 20:35:24 +0100 Subject: [PATCH 0813/2181] pass/surface: fixup invalid expansion by old -1 rounding param fixes #8889 --- src/render/pass/SurfacePassElement.hpp | 36 +++++++------------------- 1 file changed, 10 insertions(+), 26 deletions(-) diff --git a/src/render/pass/SurfacePassElement.hpp b/src/render/pass/SurfacePassElement.hpp index 14d8ef14..12387367 100644 --- a/src/render/pass/SurfacePassElement.hpp +++ b/src/render/pass/SurfacePassElement.hpp @@ -9,38 +9,22 @@ class CSyncTimeline; class CSurfacePassElement : public IPassElement { public: struct SRenderData { - PHLMONITORREF pMonitor; - timespec* when = nullptr; - Vector2D pos, localPos; + PHLMONITORREF pMonitor; + timespec* when = nullptr; + Vector2D pos, localPos; - // for iters void* data = nullptr; SP surface = nullptr; SP texture = nullptr; bool mainSurface = true; double w = 0, h = 0; - - // for rounding - bool dontRound = true; - - // for fade - float fadeAlpha = 1.f; - - // for alpha settings - float alpha = 1.f; - - // for decorations (border) - bool decorate = false; - - // for custom round values - int rounding = -1; // -1 means not set - - // for custom rounding powers - float roundingPower = 2.0f; - - // for blurring - bool blur = false; - bool blockBlurOptimization = false; + int rounding = 0; + bool dontRound = true; + float roundingPower = 2.0F; + bool decorate = false; + float alpha = 1.F, fadeAlpha = 1.F; + bool blur = false; + bool blockBlurOptimization = false; // only for windows, not popups bool squishOversized = true; From f390f48a07d117e24acec59dcf6791bcb3a81110 Mon Sep 17 00:00:00 2001 From: vaxerski Date: Sun, 5 Jan 2025 23:19:13 +0100 Subject: [PATCH 0814/2181] pass: fixup debug mode rendering of input boxes --- src/render/pass/Pass.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/render/pass/Pass.cpp b/src/render/pass/Pass.cpp index 0489e985..b72248c2 100644 --- a/src/render/pass/Pass.cpp +++ b/src/render/pass/Pass.cpp @@ -226,12 +226,13 @@ void CRenderPass::renderDebugData() { if (box.intersection(CBox{{}, g_pHyprOpenGL->m_RenderData.pMonitor->vecSize}).empty()) return; + g_pHyprOpenGL->renderRectWithDamage(&box, color, CRegion{0, 0, INT32_MAX, INT32_MAX}); + if (offsets.contains(surface.get())) box.translate(Vector2D{0.F, offsets[surface.get()]}); else offsets[surface.get()] = 0; - g_pHyprOpenGL->renderRectWithDamage(&box, Colors::PURPLE.modifyA(0.1F), CRegion{0, 0, INT32_MAX, INT32_MAX}); box = {box.pos(), texture->m_vSize}; g_pHyprOpenGL->renderRectWithDamage(&box, CHyprColor{0.F, 0.F, 0.F, 0.2F}, CRegion{0, 0, INT32_MAX, INT32_MAX}, std::min(5.0, box.size().y)); g_pHyprOpenGL->renderTexture(texture, &box, 1.F); From f1a7a7497e9b058092e915acd5164dcc162a8260 Mon Sep 17 00:00:00 2001 From: vaxerski Date: Mon, 6 Jan 2025 15:27:57 +0100 Subject: [PATCH 0815/2181] datadevice: guard XWayland server against crashes The server might be dead or restarting, and we'd deref null ref #7822 --- src/protocols/core/DataDevice.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/protocols/core/DataDevice.cpp b/src/protocols/core/DataDevice.cpp index 6ad17d7b..722eb9fd 100644 --- a/src/protocols/core/DataDevice.cpp +++ b/src/protocols/core/DataDevice.cpp @@ -417,7 +417,7 @@ void CWLDataDeviceProtocol::destroyResource(CWLDataOfferResource* resource) { SP CWLDataDeviceProtocol::dataDeviceForClient(wl_client* c) { #ifndef NO_XWAYLAND - if (c == g_pXWayland->pServer->xwaylandClient) + if (g_pXWayland->pServer && c == g_pXWayland->pServer->xwaylandClient) return g_pXWayland->pWM->getDataDevice(); #endif From 780e3dd542c9706dd37b715f95eb1134b14e6624 Mon Sep 17 00:00:00 2001 From: vaxerski Date: Mon, 6 Jan 2025 14:29:29 +0000 Subject: [PATCH 0816/2181] [gha] Nix: update inputs --- flake.lock | 73 +++++++++++++++++++++--------------------------------- 1 file changed, 28 insertions(+), 45 deletions(-) diff --git a/flake.lock b/flake.lock index 76d371bc..f16ecaa7 100644 --- a/flake.lock +++ b/flake.lock @@ -16,11 +16,11 @@ ] }, "locked": { - "lastModified": 1734906446, - "narHash": "sha256-6OWluVE2A8xi+8V3jN9KA72RCgJjYdyyuLBUjxZ2q2U=", + "lastModified": 1736102453, + "narHash": "sha256-5qb4kb7Xbt8jJFL/oDqOor9Z2+E+A+ql3PiyDvsfWZ0=", "owner": "hyprwm", "repo": "aquamarine", - "rev": "eecb74dc79bb6752a2a507e6edee3042390a6091", + "rev": "4846091641f3be0ad7542086d52769bb7932bde6", "type": "github" }, "original": { @@ -105,11 +105,11 @@ ] }, "locked": { - "lastModified": 1734906236, - "narHash": "sha256-vH/ysV2ONGQgYZPtcJKwc8jJivzyVxru2aaOxC20ZOE=", + "lastModified": 1736115290, + "narHash": "sha256-Jcn6yAzfUMcxy3tN/iZRbi/QgrYm7XLyVRl9g/nbUl4=", "owner": "hyprwm", "repo": "hyprgraphics", - "rev": "6dea3fba08fd704dd624b6d4b261638fb4003c9c", + "rev": "52202272d89da32a9f866c0d10305a5e3d954c50", "type": "github" }, "original": { @@ -128,11 +128,11 @@ ] }, "locked": { - "lastModified": 1735734474, - "narHash": "sha256-9OV4lOqrEJVLdOrpNN/9msNwAhI6FQTu4N7fufilG08=", + "lastModified": 1735774328, + "narHash": "sha256-vIRwLS9w+N99EU1aJ+XNOU6mJTxrUBa31i1r82l0V7s=", "owner": "hyprwm", "repo": "hyprland-protocols", - "rev": "271df559dd30e4bc5ec6af02d017ac0aaabd63a7", + "rev": "e3b6af97ddcfaafbda8e2828c719a5af84f662cb", "type": "github" }, "original": { @@ -154,11 +154,11 @@ ] }, "locked": { - "lastModified": 1734906472, - "narHash": "sha256-pWPRv/GA/X/iAwoE6gMNUqn/ZeJX1IeLPRpZI0tTPK0=", + "lastModified": 1736114838, + "narHash": "sha256-FxbuGQExtN37ToWYnGmO6weOYN6WPHN/RAqbr7gNPek=", "owner": "hyprwm", "repo": "hyprland-qtutils", - "rev": "c77109d7e1ddbcdb87cafd32ce411f76328ae152", + "rev": "6997fe382dcf396704227d2b98ffdd5066da6959", "type": "github" }, "original": { @@ -180,11 +180,11 @@ ] }, "locked": { - "lastModified": 1734906259, - "narHash": "sha256-P79t/7HbACO4/PuJBroGpTptvCWJtXTv+gWsF+sM6MI=", + "lastModified": 1735393019, + "narHash": "sha256-NPpqA8rtmDLsEmZOmz+qR67zsB6Y503Jnv+nSFLKJZ8=", "owner": "hyprwm", "repo": "hyprlang", - "rev": "0404833ea18d543df44df935ebf1b497310eb046", + "rev": "55608efdaa387af7bfdc0eddb404c409958efa43", "type": "github" }, "original": { @@ -203,11 +203,11 @@ ] }, "locked": { - "lastModified": 1735316583, - "narHash": "sha256-AiiUwHWHfEdpFzXy7l1x3zInCUa1xcRMrbZ1XRSkzwU=", + "lastModified": 1736164519, + "narHash": "sha256-1LimBKvDpBbeX+qW7T240WEyw+DBVpDotZB4JYm8Aps=", "owner": "hyprwm", "repo": "hyprutils", - "rev": "8f15d45b120b33712f6db477fe5ffb18034d0ea8", + "rev": "3c895da64b0eb19870142196fa48c07090b441c4", "type": "github" }, "original": { @@ -226,11 +226,11 @@ ] }, "locked": { - "lastModified": 1734793513, - "narHash": "sha256-rrrHcXapXJvGFqX+L/Bb0182L25jofAZ0fm1FInvrTQ=", + "lastModified": 1735493474, + "narHash": "sha256-fktzv4NaqKm94VAkAoVqO/nqQlw+X0/tJJNAeCSfzK4=", "owner": "hyprwm", "repo": "hyprwayland-scanner", - "rev": "4d7367b6eee87397e2dbca2e78078dd0a4ef4c61", + "rev": "de913476b59ee88685fdc018e77b8f6637a2ae0b", "type": "github" }, "original": { @@ -241,11 +241,11 @@ }, "nixpkgs": { "locked": { - "lastModified": 1735291276, - "narHash": "sha256-NYVcA06+blsLG6wpAbSPTCyLvxD/92Hy4vlY9WxFI1M=", + "lastModified": 1736012469, + "narHash": "sha256-/qlNWm/IEVVH7GfgAIyP6EsVZI6zjAx1cV5zNyrs+rI=", "owner": "NixOS", "repo": "nixpkgs", - "rev": "634fd46801442d760e09493a794c4f15db2d0cbb", + "rev": "8f3e1f807051e32d8c95cd12b9b421623850a34d", "type": "github" }, "original": { @@ -255,37 +255,20 @@ "type": "github" } }, - "nixpkgs-stable": { - "locked": { - "lastModified": 1730741070, - "narHash": "sha256-edm8WG19kWozJ/GqyYx2VjW99EdhjKwbY3ZwdlPAAlo=", - "owner": "NixOS", - "repo": "nixpkgs", - "rev": "d063c1dd113c91ab27959ba540c0d9753409edf3", - "type": "github" - }, - "original": { - "owner": "NixOS", - "ref": "nixos-24.05", - "repo": "nixpkgs", - "type": "github" - } - }, "pre-commit-hooks": { "inputs": { "flake-compat": "flake-compat", "gitignore": "gitignore", "nixpkgs": [ "nixpkgs" - ], - "nixpkgs-stable": "nixpkgs-stable" + ] }, "locked": { - "lastModified": 1734797603, - "narHash": "sha256-ulZN7ps8nBV31SE+dwkDvKIzvN6hroRY8sYOT0w+E28=", + "lastModified": 1735882644, + "narHash": "sha256-3FZAG+pGt3OElQjesCAWeMkQ7C/nB1oTHLRQ8ceP110=", "owner": "cachix", "repo": "git-hooks.nix", - "rev": "f0f0dc4920a903c3e08f5bdb9246bb572fcae498", + "rev": "a5a961387e75ae44cc20f0a57ae463da5e959656", "type": "github" }, "original": { From 602d6b73563e56fe003bbf3d25b45a53c51bad24 Mon Sep 17 00:00:00 2001 From: Mike Will Date: Mon, 6 Jan 2025 11:37:13 -0500 Subject: [PATCH 0817/2181] snap: don't snap to any windows if workspace has a fullscreen window (#8870) --- src/layout/IHyprLayout.cpp | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/src/layout/IHyprLayout.cpp b/src/layout/IHyprLayout.cpp index e90ab0f0..f875b99c 100644 --- a/src/layout/IHyprLayout.cpp +++ b/src/layout/IHyprLayout.cpp @@ -421,11 +421,13 @@ static void performSnap(Vector2D& sourcePos, Vector2D& sourceSize, PHLWINDOW DRA SRange sourceY = {sourcePos.y, sourcePos.y + sourceSize.y}; if (*SNAPWINDOWGAP) { - const double GAPSIZE = *SNAPWINDOWGAP; - const auto WSID = DRAGGINGWINDOW->workspaceID(); + const double GAPSIZE = *SNAPWINDOWGAP; + const auto WSID = DRAGGINGWINDOW->workspaceID(); + const bool HASFULLSCREEN = DRAGGINGWINDOW->m_pWorkspace && DRAGGINGWINDOW->m_pWorkspace->m_bHasFullscreenWindow; for (auto& other : g_pCompositor->m_vWindows) { - if (other == DRAGGINGWINDOW || other->workspaceID() != WSID || !other->m_bIsMapped || other->m_bFadingOut || other->isX11OverrideRedirect()) + if ((HASFULLSCREEN && !other->m_bCreatedOverFullscreen) || other == DRAGGINGWINDOW || other->workspaceID() != WSID || !other->m_bIsMapped || other->m_bFadingOut || + other->isX11OverrideRedirect()) continue; const int OTHERBORDERSIZE = other->getRealBorderSize(); From 6a90b505456cc708ec2779e0943eb9764e7630a5 Mon Sep 17 00:00:00 2001 From: UjinT34 <41110182+UjinT34@users.noreply.github.com> Date: Mon, 6 Jan 2025 19:52:35 +0300 Subject: [PATCH 0818/2181] core/compositor: fix too early buffer release (#8966) --- src/protocols/core/Compositor.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/protocols/core/Compositor.cpp b/src/protocols/core/Compositor.cpp index ee1e6224..6213f987 100644 --- a/src/protocols/core/Compositor.cpp +++ b/src/protocols/core/Compositor.cpp @@ -428,6 +428,7 @@ void CWLSurfaceResource::commitPendingState() { pending.damage.clear(); pending.bufferDamage.clear(); pending.newBuffer = false; + dropPendingBuffer(); // at this point current.buffer holds the same SP and we don't use pending anymore events.roleCommit.emit(); @@ -448,10 +449,9 @@ void CWLSurfaceResource::commitPendingState() { // release the buffer if it's synchronous as update() has done everything thats needed // so we can let the app know we're done. - if (current.buffer->buffer->isSynchronous()) { - dropCurrentBuffer(); - dropPendingBuffer(); // pending atm is just a copied ref of the current, drop it too to send a release - } + // Some clients aren't ready to receive a release this early. Should be fine to release it on the next commitPendingState. + // if (current.buffer->buffer->isSynchronous()) + // dropCurrentBuffer(); } // TODO: we should _accumulate_ and not replace above if sync From 1bf4937b0292dc156e2530185c231608280be27f Mon Sep 17 00:00:00 2001 From: Byso Date: Mon, 6 Jan 2025 17:52:59 +0100 Subject: [PATCH 0819/2181] hyprctl: fix hyprctl --batch not working with exec rules (#8952) --- src/debug/HyprCtl.cpp | 42 +++++++++++++++++------------------------- 1 file changed, 17 insertions(+), 25 deletions(-) diff --git a/src/debug/HyprCtl.cpp b/src/debug/HyprCtl.cpp index b946da6e..8724d2c7 100644 --- a/src/debug/HyprCtl.cpp +++ b/src/debug/HyprCtl.cpp @@ -1150,34 +1150,26 @@ static std::string cursorPosRequest(eHyprCtlOutputFormat format, std::string req } static std::string dispatchBatch(eHyprCtlOutputFormat format, std::string request) { - // split by ; - - request = request.substr(9); - std::string curitem = ""; - std::string reply = ""; - - auto nextItem = [&]() { - auto idx = request.find_first_of(';'); - - if (idx != std::string::npos) { - curitem = request.substr(0, idx); - request = request.substr(idx + 1); - } else { - curitem = request; - request = ""; - } - - curitem = trim(curitem); - }; - - nextItem(); + // split by ; ignores ; inside [] and adds ; on last command + request = request.substr(9); + std::string reply = ""; const std::string DELIMITER = "\n\n\n"; + int bracket = 0; + size_t idx = 0; - while (curitem != "" || request != "") { - reply += g_pHyprCtl->getReply(curitem) + DELIMITER; - - nextItem(); + for (size_t i = 0; i <= request.size(); ++i) { + char ch = (i < request.size()) ? request[i] : ';'; + if (ch == '[') + ++bracket; + else if (ch == ']') + --bracket; + else if (ch == ';' && bracket == 0) { + if (idx < i) + reply += g_pHyprCtl->getReply(trim(request.substr(idx, i - idx))).append(DELIMITER); + idx = i + 1; + continue; + } } return reply.substr(0, std::max(static_cast(reply.size() - DELIMITER.size()), 0)); From b9f110ef8726fcba2b4ee69856027731e73003a5 Mon Sep 17 00:00:00 2001 From: Pollux Date: Mon, 6 Jan 2025 13:30:57 -0600 Subject: [PATCH 0820/2181] shaders: fix blank windows when using corner rounding (#8969) (#8971) --- src/render/shaders/Textures.hpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/render/shaders/Textures.hpp b/src/render/shaders/Textures.hpp index 49d27b4c..78845322 100644 --- a/src/render/shaders/Textures.hpp +++ b/src/render/shaders/Textures.hpp @@ -19,7 +19,7 @@ inline static constexpr auto ROUNDED_SHADER_FUNC = [](const std::string colorVar const float SMOOTHING_CONSTANT = )#" + std::format("{:.7f}", SHADER_ROUNDED_SMOOTHING_FACTOR) + R"#(; - //if (pixCoord.x + pixCoord.y > radius) { + if (pixCoord.x + pixCoord.y > radius) { float dist = pow(pow(pixCoord.x, roundingPower) + pow(pixCoord.y, roundingPower), 1.0/roundingPower); @@ -30,7 +30,7 @@ inline static constexpr auto ROUNDED_SHADER_FUNC = [](const std::string colorVar )#" + colorVarName + R"#( = )#" + colorVarName + R"#( * normalized; - //} + } )#"; }; From c7086f936a06abebcc863c35f634760ca1ee90c0 Mon Sep 17 00:00:00 2001 From: Zetta1 Reid0 <79805086+Zetta1Reid0@users.noreply.github.com> Date: Tue, 7 Jan 2025 19:50:34 +0200 Subject: [PATCH 0821/2181] master: add option to show slaves on left in center orientation (#8940) Co-authored-by: Zetta1_Reid0 <11255-Zetta1_Reid0@users.noreply.gitlab.xfce.org> --- src/config/ConfigDescriptions.hpp | 6 ++++++ src/config/ConfigManager.cpp | 1 + src/layout/MasterLayout.cpp | 20 +++++++++++++++----- 3 files changed, 22 insertions(+), 5 deletions(-) diff --git a/src/config/ConfigDescriptions.hpp b/src/config/ConfigDescriptions.hpp index 46f91a21..8c35a3b1 100644 --- a/src/config/ConfigDescriptions.hpp +++ b/src/config/ConfigDescriptions.hpp @@ -1632,6 +1632,12 @@ inline static const std::vector CONFIG_OPTIONS = { .type = CONFIG_OPTION_INT, .data = SConfigOptionDescription::SRangeData{2, 0, 10}, //##TODO RANGE? }, + SConfigOptionDescription{ + .value = "master:center_master_slaves_on_right", + .description = "set if the slaves should appear on right of master when slave_count_for_center_master > 2", + .type = CONFIG_OPTION_BOOL, + .data = SConfigOptionDescription::SBoolData{true}, + }, SConfigOptionDescription{ .value = "master:center_ignores_reserved", .description = "centers the master window on monitor ignoring reserved areas", diff --git a/src/config/ConfigManager.cpp b/src/config/ConfigManager.cpp index 732d12e5..927cee9f 100644 --- a/src/config/ConfigManager.cpp +++ b/src/config/ConfigManager.cpp @@ -479,6 +479,7 @@ CConfigManager::CConfigManager() { m_pConfig->addConfigValue("master:mfact", {0.55f}); m_pConfig->addConfigValue("master:new_status", {"slave"}); m_pConfig->addConfigValue("master:slave_count_for_center_master", Hyprlang::INT{2}); + m_pConfig->addConfigValue("master:center_master_slaves_on_right", Hyprlang::INT{1}); m_pConfig->addConfigValue("master:center_ignores_reserved", Hyprlang::INT{0}); m_pConfig->addConfigValue("master:new_on_active", {"none"}); m_pConfig->addConfigValue("master:new_on_top", Hyprlang::INT{0}); diff --git a/src/layout/MasterLayout.cpp b/src/layout/MasterLayout.cpp index fb7df84f..225246f0 100644 --- a/src/layout/MasterLayout.cpp +++ b/src/layout/MasterLayout.cpp @@ -328,6 +328,7 @@ void CHyprMasterLayout::calculateWorkspace(PHLWORKSPACE pWorkspace) { eOrientation orientation = getDynamicOrientation(pWorkspace); bool centerMasterWindow = false; static auto SLAVECOUNTFORCENTER = CConfigValue("master:slave_count_for_center_master"); + static auto CMSLAVESONRIGHT = CConfigValue("master:center_master_slaves_on_right"); static auto PIGNORERESERVED = CConfigValue("master:center_ignores_reserved"); static auto PSMARTRESIZING = CConfigValue("master:smart_resizing"); @@ -341,7 +342,10 @@ void CHyprMasterLayout::calculateWorkspace(PHLWORKSPACE pWorkspace) { if (STACKWINDOWS >= *SLAVECOUNTFORCENTER) { centerMasterWindow = true; } else { - orientation = ORIENTATION_LEFT; + if (*CMSLAVESONRIGHT) + orientation = ORIENTATION_LEFT; + else + orientation = ORIENTATION_RIGHT; } } @@ -515,15 +519,20 @@ void CHyprMasterLayout::calculateWorkspace(PHLWORKSPACE pWorkspace) { float nextY = 0; float nextYL = 0; float nextYR = 0; - bool onRight = true; + bool onRight = *CMSLAVESONRIGHT; + int slavesLeftL = 1 + (slavesLeft - 1) / 2; + int slavesLeftR = slavesLeft - slavesLeftL; - int slavesLeftR = 1 + (slavesLeft - 1) / 2; - int slavesLeftL = slavesLeft - slavesLeftR; + if (*CMSLAVESONRIGHT) { + slavesLeftR = 1 + (slavesLeft - 1) / 2; + slavesLeftL = slavesLeft - slavesLeftR; + } const float slaveAverageHeightL = WSSIZE.y / slavesLeftL; const float slaveAverageHeightR = WSSIZE.y / slavesLeftR; float slaveAccumulatedHeightL = 0; float slaveAccumulatedHeightR = 0; + if (*PSMARTRESIZING) { for (auto const& nd : m_lMasterNodesData) { if (nd.workspaceID != pWorkspace->m_iID || nd.isMaster) @@ -536,7 +545,8 @@ void CHyprMasterLayout::calculateWorkspace(PHLWORKSPACE pWorkspace) { } onRight = !onRight; } - onRight = true; + + onRight = *CMSLAVESONRIGHT; } for (auto& nd : m_lMasterNodesData) { From 5642ed331df56375c55cd8d56a14054af8bdf8f2 Mon Sep 17 00:00:00 2001 From: Maximilian Seidler <78690852+PaideiaDilemma@users.noreply.github.com> Date: Tue, 7 Jan 2025 17:55:14 +0000 Subject: [PATCH 0822/2181] core: move parts of the animation system to hyprutils (#8868) * core: change animation manager to use Hyprutils::Animation * config: move animation config to hyprutils animation tree * use g_pAnimationManager->createAnimation and the new PHLANIMVAR template * core: use CGenericAnimatedVariabled::{enabled,setConfig,getStyle} and adapt callbacks * core: adapt animated variable usage (dereference the shared pointer) * misc: bump CMakeLists to hyprutils 0.3.3 --- CMakeLists.txt | 2 +- src/Compositor.cpp | 78 +-- src/config/ConfigManager.cpp | 156 ++--- src/config/ConfigManager.hpp | 87 ++- src/debug/HyprCtl.cpp | 23 +- src/desktop/LayerSurface.cpp | 88 ++- src/desktop/LayerSurface.hpp | 18 +- src/desktop/Popup.cpp | 4 +- src/desktop/Subsurface.cpp | 2 +- src/desktop/WLSurface.cpp | 2 +- src/desktop/Window.cpp | 198 +++--- src/desktop/Window.hpp | 42 +- src/desktop/Workspace.cpp | 99 ++- src/desktop/Workspace.hpp | 6 +- src/events/Windows.cpp | 100 +-- src/helpers/AnimatedVariable.cpp | 87 --- src/helpers/AnimatedVariable.hpp | 275 +-------- src/helpers/BezierCurve.cpp | 90 --- src/helpers/BezierCurve.hpp | 28 - src/helpers/Monitor.cpp | 8 +- src/helpers/WLClasses.hpp | 1 - src/hyprerror/HyprError.cpp | 30 +- src/hyprerror/HyprError.hpp | 20 +- src/layout/DwindleLayout.cpp | 38 +- src/layout/IHyprLayout.cpp | 100 +-- src/layout/MasterLayout.cpp | 36 +- src/managers/AnimationManager.cpp | 584 +++++++----------- src/managers/AnimationManager.hpp | 75 ++- src/managers/KeybindManager.cpp | 64 +- src/managers/XWaylandManager.cpp | 6 +- src/managers/input/InputManager.cpp | 12 +- src/managers/input/Swipe.cpp | 120 ++-- src/managers/input/Tablets.cpp | 2 +- src/managers/input/Touch.cpp | 16 +- src/protocols/CTMControl.cpp | 14 +- src/protocols/CTMControl.hpp | 4 +- src/protocols/ToplevelExport.cpp | 8 +- src/render/OpenGL.cpp | 8 +- src/render/Renderer.cpp | 94 +-- .../decorations/CHyprBorderDecoration.cpp | 14 +- .../decorations/CHyprDropShadowDecoration.cpp | 28 +- .../decorations/CHyprGroupBarDecoration.cpp | 10 +- .../decorations/DecorationPositioner.cpp | 6 +- src/render/pass/SurfacePassElement.cpp | 12 +- 44 files changed, 1031 insertions(+), 1664 deletions(-) delete mode 100644 src/helpers/AnimatedVariable.cpp delete mode 100644 src/helpers/BezierCurve.cpp delete mode 100644 src/helpers/BezierCurve.hpp diff --git a/CMakeLists.txt b/CMakeLists.txt index 9d5c58b7..aa746d2e 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -104,7 +104,7 @@ find_package(OpenGL REQUIRED COMPONENTS ${GLES_VERSION}) pkg_check_modules(aquamarine_dep REQUIRED IMPORTED_TARGET aquamarine>=0.4.5) pkg_check_modules(hyprlang_dep REQUIRED IMPORTED_TARGET hyprlang>=0.3.2) pkg_check_modules(hyprcursor_dep REQUIRED IMPORTED_TARGET hyprcursor>=0.1.7) -pkg_check_modules(hyprutils_dep REQUIRED IMPORTED_TARGET hyprutils>=0.2.3) +pkg_check_modules(hyprutils_dep REQUIRED IMPORTED_TARGET hyprutils>=0.3.3) pkg_check_modules(hyprgraphics_dep REQUIRED IMPORTED_TARGET hyprgraphics>=0.1.1) add_compile_definitions(AQUAMARINE_VERSION="${aquamarine_dep_VERSION}") diff --git a/src/Compositor.cpp b/src/Compositor.cpp index c80f05e6..5805eff9 100644 --- a/src/Compositor.cpp +++ b/src/Compositor.cpp @@ -569,7 +569,7 @@ void CCompositor::initManagers(eManagersInitStage stage) { g_pKeybindManager = std::make_unique(); Debug::log(LOG, "Creating the AnimationManager!"); - g_pAnimationManager = std::make_unique(); + g_pAnimationManager = std::make_unique(); Debug::log(LOG, "Creating the ConfigManager!"); g_pConfigManager = std::make_unique(); @@ -964,11 +964,11 @@ SP CCompositor::vectorWindowToSurface(const Vector2D& pos, P if (PPOPUP) { const auto OFF = PPOPUP->coordsRelativeToParent(); - sl = pos - pWindow->m_vRealPosition.goal() - OFF; + sl = pos - pWindow->m_vRealPosition->goal() - OFF; return PPOPUP->m_pWLSurface->resource(); } - auto [surf, local] = pWindow->m_pWLSurface->resource()->at(pos - pWindow->m_vRealPosition.goal(), true); + auto [surf, local] = pWindow->m_pWLSurface->resource()->at(pos - pWindow->m_vRealPosition->goal(), true); if (surf) { sl = local; return surf; @@ -982,7 +982,7 @@ Vector2D CCompositor::vectorToSurfaceLocal(const Vector2D& vec, PHLWINDOW pWindo return {}; if (pWindow->m_bIsX11) - return vec - pWindow->m_vRealPosition.goal(); + return vec - pWindow->m_vRealPosition->goal(); const auto PPOPUP = pWindow->m_pPopupHead->at(vec); if (PPOPUP) @@ -1001,9 +1001,9 @@ Vector2D CCompositor::vectorToSurfaceLocal(const Vector2D& vec, PHLWINDOW pWindo CBox geom = pWindow->m_pXDGSurface->current.geometry; if (std::get<1>(iterData) == Vector2D{-1337, -1337}) - return vec - pWindow->m_vRealPosition.goal(); + return vec - pWindow->m_vRealPosition->goal(); - return vec - pWindow->m_vRealPosition.goal() - std::get<1>(iterData) + Vector2D{geom.x, geom.y}; + return vec - pWindow->m_vRealPosition->goal() - std::get<1>(iterData) + Vector2D{geom.x, geom.y}; } PHLMONITOR CCompositor::getMonitorFromOutput(SP out) { @@ -1211,7 +1211,7 @@ void CCompositor::focusSurface(SP pSurface, PHLWINDOW pWindo SP CCompositor::vectorToLayerPopupSurface(const Vector2D& pos, PHLMONITOR monitor, Vector2D* sCoords, PHLLS* ppLayerSurfaceFound) { for (auto const& lsl : monitor->m_aLayerSurfaceLayers | std::views::reverse) { for (auto const& ls : lsl | std::views::reverse) { - if (ls->fadingOut || !ls->layerSurface || (ls->layerSurface && !ls->layerSurface->mapped) || ls->alpha.value() == 0.f) + if (ls->fadingOut || !ls->layerSurface || (ls->layerSurface && !ls->layerSurface->mapped) || ls->alpha->value() == 0.f) continue; auto SURFACEAT = ls->popupHead->at(pos, true); @@ -1229,7 +1229,7 @@ SP CCompositor::vectorToLayerPopupSurface(const Vector2D& po SP CCompositor::vectorToLayerSurface(const Vector2D& pos, std::vector* layerSurfaces, Vector2D* sCoords, PHLLS* ppLayerSurfaceFound) { for (auto const& ls : *layerSurfaces | std::views::reverse) { - if (ls->fadingOut || !ls->layerSurface || (ls->layerSurface && !ls->layerSurface->surface->mapped) || ls->alpha.value() == 0.f) + if (ls->fadingOut || !ls->layerSurface || (ls->layerSurface && !ls->layerSurface->surface->mapped) || ls->alpha->value() == 0.f) continue; auto [surf, local] = ls->layerSurface->surface->at(pos - ls->geometry.pos(), true); @@ -1378,7 +1378,7 @@ void CCompositor::cleanupFadingOut(const MONITORID& monid) { if (w->monitorID() != monid && w->m_pMonitor) continue; - if (!w->m_bFadingOut || w->m_fAlpha.value() == 0.f) { + if (!w->m_bFadingOut || w->m_fAlpha->value() == 0.f) { w->m_bFadingOut = false; @@ -1831,8 +1831,8 @@ void CCompositor::updateWindowAnimatedDecorationValues(PHLWINDOW pWindow) { pWindow->m_cRealBorderColorPrevious = pWindow->m_cRealBorderColor; pWindow->m_cRealBorderColor = grad; - pWindow->m_fBorderFadeAnimationProgress.setValueAndWarp(0.f); - pWindow->m_fBorderFadeAnimationProgress = 1.f; + pWindow->m_fBorderFadeAnimationProgress->setValueAndWarp(0.f); + *pWindow->m_fBorderFadeAnimationProgress = 1.f; }; const bool IS_SHADOWED_BY_MODAL = pWindow->m_pXDGSurface && pWindow->m_pXDGSurface->toplevel && pWindow->m_pXDGSurface->toplevel->anyChildModal(); @@ -1855,18 +1855,18 @@ void CCompositor::updateWindowAnimatedDecorationValues(PHLWINDOW pWindow) { } // tick angle if it's not running (aka dead) - if (!pWindow->m_fBorderAngleAnimationProgress.isBeingAnimated()) - pWindow->m_fBorderAngleAnimationProgress.setValueAndWarp(0.f); + if (!pWindow->m_fBorderAngleAnimationProgress->isBeingAnimated()) + pWindow->m_fBorderAngleAnimationProgress->setValueAndWarp(0.f); // opacity const auto PWORKSPACE = pWindow->m_pWorkspace; if (pWindow->isEffectiveInternalFSMode(FSMODE_FULLSCREEN)) { - pWindow->m_fActiveInactiveAlpha = pWindow->m_sWindowData.alphaFullscreen.valueOrDefault().applyAlpha(*PFULLSCREENALPHA); + *pWindow->m_fActiveInactiveAlpha = pWindow->m_sWindowData.alphaFullscreen.valueOrDefault().applyAlpha(*PFULLSCREENALPHA); } else { if (pWindow == m_pLastWindow) - pWindow->m_fActiveInactiveAlpha = pWindow->m_sWindowData.alpha.valueOrDefault().applyAlpha(*PACTIVEALPHA); + *pWindow->m_fActiveInactiveAlpha = pWindow->m_sWindowData.alpha.valueOrDefault().applyAlpha(*PACTIVEALPHA); else - pWindow->m_fActiveInactiveAlpha = pWindow->m_sWindowData.alphaInactive.valueOrDefault().applyAlpha(*PINACTIVEALPHA); + *pWindow->m_fActiveInactiveAlpha = pWindow->m_sWindowData.alphaInactive.valueOrDefault().applyAlpha(*PINACTIVEALPHA); } // dim @@ -1879,16 +1879,16 @@ void CCompositor::updateWindowAnimatedDecorationValues(PHLWINDOW pWindow) { if (IS_SHADOWED_BY_MODAL) goalDim += (1.F - goalDim) / 2.F; - pWindow->m_fDimPercent = goalDim; + *pWindow->m_fDimPercent = goalDim; // shadow if (!pWindow->isX11OverrideRedirect() && !pWindow->m_bX11DoesntWantBorders) { if (pWindow == m_pLastWindow) - pWindow->m_cRealShadowColor = CHyprColor(*PSHADOWCOL); + *pWindow->m_cRealShadowColor = CHyprColor(*PSHADOWCOL); else - pWindow->m_cRealShadowColor = CHyprColor(*PSHADOWCOLINACTIVE != INT64_MAX ? *PSHADOWCOLINACTIVE : *PSHADOWCOL); + *pWindow->m_cRealShadowColor = CHyprColor(*PSHADOWCOLINACTIVE != INT64_MAX ? *PSHADOWCOLINACTIVE : *PSHADOWCOL); } else { - pWindow->m_cRealShadowColor.setValueAndWarp(CHyprColor(0, 0, 0, 0)); // no shadow + pWindow->m_cRealShadowColor->setValueAndWarp(CHyprColor(0, 0, 0, 0)); // no shadow } pWindow->updateWindowDecos(); @@ -1932,11 +1932,11 @@ void CCompositor::swapActiveWorkspaces(PHLMONITOR pMonitorA, PHLMONITOR pMonitor // additionally, move floating and fs windows manually if (w->m_bIsFloating) - w->m_vRealPosition = w->m_vRealPosition.goal() - pMonitorA->vecPosition + pMonitorB->vecPosition; + *w->m_vRealPosition = w->m_vRealPosition->goal() - pMonitorA->vecPosition + pMonitorB->vecPosition; if (w->isFullscreen()) { - w->m_vRealPosition = pMonitorB->vecPosition; - w->m_vRealSize = pMonitorB->vecSize; + *w->m_vRealPosition = pMonitorB->vecPosition; + *w->m_vRealSize = pMonitorB->vecSize; } w->updateToplevel(); @@ -1957,11 +1957,11 @@ void CCompositor::swapActiveWorkspaces(PHLMONITOR pMonitorA, PHLMONITOR pMonitor // additionally, move floating and fs windows manually if (w->m_bIsFloating) - w->m_vRealPosition = w->m_vRealPosition.goal() - pMonitorB->vecPosition + pMonitorA->vecPosition; + *w->m_vRealPosition = w->m_vRealPosition->goal() - pMonitorB->vecPosition + pMonitorA->vecPosition; if (w->isFullscreen()) { - w->m_vRealPosition = pMonitorA->vecPosition; - w->m_vRealSize = pMonitorA->vecSize; + *w->m_vRealPosition = pMonitorA->vecPosition; + *w->m_vRealSize = pMonitorA->vecSize; } w->updateToplevel(); @@ -2135,14 +2135,14 @@ void CCompositor::moveWorkspaceToMonitor(PHLWORKSPACE pWorkspace, PHLMONITOR pMo if (w->m_bIsMapped && !w->isHidden()) { if (POLDMON) { if (w->m_bIsFloating) - w->m_vRealPosition = w->m_vRealPosition.goal() - POLDMON->vecPosition + pMonitor->vecPosition; + *w->m_vRealPosition = w->m_vRealPosition->goal() - POLDMON->vecPosition + pMonitor->vecPosition; if (w->isFullscreen()) { - w->m_vRealPosition = pMonitor->vecPosition; - w->m_vRealSize = pMonitor->vecSize; + *w->m_vRealPosition = pMonitor->vecPosition; + *w->m_vRealSize = pMonitor->vecSize; } } else { - w->m_vRealPosition = Vector2D{(int)w->m_vRealPosition.goal().x % (int)pMonitor->vecSize.x, (int)w->m_vRealPosition.goal().y % (int)pMonitor->vecSize.y}; + *w->m_vRealPosition = Vector2D{(int)w->m_vRealPosition->goal().x % (int)pMonitor->vecSize.x, (int)w->m_vRealPosition->goal().y % (int)pMonitor->vecSize.y}; } } @@ -2216,9 +2216,9 @@ void CCompositor::updateFullscreenFadeOnWorkspace(PHLWORKSPACE pWorkspace) { continue; if (!FULLSCREEN) - w->m_fAlpha = 1.f; + *w->m_fAlpha = 1.f; else if (!w->isFullscreen()) - w->m_fAlpha = !w->m_bCreatedOverFullscreen ? 0.f : 1.f; + *w->m_fAlpha = !w->m_bCreatedOverFullscreen ? 0.f : 1.f; } } @@ -2227,7 +2227,7 @@ void CCompositor::updateFullscreenFadeOnWorkspace(PHLWORKSPACE pWorkspace) { if (pWorkspace->m_iID == PMONITOR->activeWorkspaceID() || pWorkspace->m_iID == PMONITOR->activeSpecialWorkspaceID()) { for (auto const& ls : PMONITOR->m_aLayerSurfaceLayers[ZWLR_LAYER_SHELL_V1_LAYER_TOP]) { if (!ls->fadingOut) - ls->alpha = FULLSCREEN && pWorkspace->m_efFullscreenMode == FSMODE_FULLSCREEN ? 0.f : 1.f; + *ls->alpha = FULLSCREEN && pWorkspace->m_efFullscreenMode == FSMODE_FULLSCREEN ? 0.f : 1.f; } } } @@ -2317,7 +2317,7 @@ void CCompositor::setWindowFullscreenState(const PHLWINDOW PWINDOW, SFullscreenS updateFullscreenFadeOnWorkspace(PWORKSPACE); - g_pXWaylandManager->setWindowSize(PWINDOW, PWINDOW->m_vRealSize.goal(), true); + g_pXWaylandManager->setWindowSize(PWINDOW, PWINDOW->m_vRealSize->goal(), true); PWORKSPACE->forceReportSizesToWindows(); @@ -2573,7 +2573,7 @@ PHLWORKSPACE CCompositor::createNewWorkspace(const WORKSPACEID& id, const MONITO const auto PWORKSPACE = m_vWorkspaces.emplace_back(CWorkspace::create(id, getMonitorFromID(monID), NAME, SPECIAL, isEmpty)); - PWORKSPACE->m_fAlpha.setValueAndWarp(0); + PWORKSPACE->m_fAlpha->setValueAndWarp(0); return PWORKSPACE; } @@ -2659,7 +2659,7 @@ void CCompositor::moveWindowToWorkspaceSafe(PHLWINDOW pWindow, PHLWORKSPACE pWor const PHLWINDOW pFirstWindowOnWorkspace = pWorkspace->getFirstWindow(); const int visibleWindowsOnWorkspace = pWorkspace->getWindows(std::nullopt, true); const auto PWINDOWMONITOR = pWindow->m_pMonitor.lock(); - const auto POSTOMON = pWindow->m_vRealPosition.goal() - PWINDOWMONITOR->vecPosition; + const auto POSTOMON = pWindow->m_vRealPosition->goal() - PWINDOWMONITOR->vecPosition; const auto PWORKSPACEMONITOR = pWorkspace->m_pMonitor.lock(); if (!pWindow->m_bIsFloating) @@ -2696,7 +2696,7 @@ void CCompositor::moveWindowToWorkspaceSafe(PHLWINDOW pWindow, PHLWORKSPACE pWor g_pLayoutManager->getCurrentLayout()->onWindowCreatedTiling(pWindow); if (pWindow->m_bIsFloating) - pWindow->m_vRealPosition = POSTOMON + PWORKSPACEMONITOR->vecPosition; + *pWindow->m_vRealPosition = POSTOMON + PWORKSPACEMONITOR->vecPosition; } pWindow->updateToplevel(); @@ -2721,8 +2721,8 @@ void CCompositor::moveWindowToWorkspaceSafe(PHLWINDOW pWindow, PHLWORKSPACE pWor g_pCompositor->updateSuspendedStates(); if (!WASVISIBLE && pWindow->m_pWorkspace && pWindow->m_pWorkspace->isVisible()) { - pWindow->m_fMovingFromWorkspaceAlpha.setValueAndWarp(0.F); - pWindow->m_fMovingFromWorkspaceAlpha = 1.F; + pWindow->m_fMovingFromWorkspaceAlpha->setValueAndWarp(0.F); + *pWindow->m_fMovingFromWorkspaceAlpha = 1.F; } } diff --git a/src/config/ConfigManager.cpp b/src/config/ConfigManager.cpp index 927cee9f..1ab29b1f 100644 --- a/src/config/ConfigManager.cpp +++ b/src/config/ConfigManager.cpp @@ -11,6 +11,7 @@ #include "../protocols/LayerShell.hpp" #include "../xwayland/XWayland.hpp" #include "../protocols/OutputManagement.hpp" +#include "managers/AnimationManager.hpp" #include #include @@ -32,6 +33,7 @@ #include #include using namespace Hyprutils::String; +using namespace Hyprutils::Animation; //NOLINTNEXTLINE extern "C" char** environ; @@ -681,7 +683,6 @@ CConfigManager::CConfigManager() { m_pConfig->commence(); - setDefaultAnimationVars(); resetHLConfig(); Debug::log(INFO, @@ -780,76 +781,46 @@ void CConfigManager::reload() { } void CConfigManager::setDefaultAnimationVars() { - if (isFirstLaunch) { - INITANIMCFG("__internal_fadeCTM"); + m_AnimationTree.createNode("__internal_fadeCTM"); + m_AnimationTree.createNode("global"); - INITANIMCFG("global"); - INITANIMCFG("windows"); - INITANIMCFG("layers"); - INITANIMCFG("fade"); - INITANIMCFG("border"); - INITANIMCFG("borderangle"); + // global + m_AnimationTree.createNode("windows", "global"); + m_AnimationTree.createNode("layers", "global"); + m_AnimationTree.createNode("fade", "global"); + m_AnimationTree.createNode("border", "global"); + m_AnimationTree.createNode("borderangle", "global"); + m_AnimationTree.createNode("workspaces", "global"); - // windows - INITANIMCFG("windowsIn"); - INITANIMCFG("windowsOut"); - INITANIMCFG("windowsMove"); + // layer + m_AnimationTree.createNode("layersIn", "layers"); + m_AnimationTree.createNode("layersOut", "layers"); - // layers - INITANIMCFG("layersIn"); - INITANIMCFG("layersOut"); + // windows + m_AnimationTree.createNode("windowsIn", "windows"); + m_AnimationTree.createNode("windowsOut", "windows"); + m_AnimationTree.createNode("windowsMove", "windows"); - // fade - INITANIMCFG("fadeIn"); - INITANIMCFG("fadeOut"); - INITANIMCFG("fadeSwitch"); - INITANIMCFG("fadeShadow"); - INITANIMCFG("fadeDim"); + // fade + m_AnimationTree.createNode("fadeIn", "fade"); + m_AnimationTree.createNode("fadeOut", "fade"); + m_AnimationTree.createNode("fadeSwitch", "fade"); + m_AnimationTree.createNode("fadeShadow", "fade"); + m_AnimationTree.createNode("fadeDim", "fade"); + m_AnimationTree.createNode("fadeLayers", "fade"); + m_AnimationTree.createNode("fadeLayersIn", "fadeLayers"); + m_AnimationTree.createNode("fadeLayersOut", "fadeLayers"); - // border + // workspaces + m_AnimationTree.createNode("workspacesIn", "workspaces"); + m_AnimationTree.createNode("workspacesOut", "workspaces"); + m_AnimationTree.createNode("specialWorkspace", "workspaces"); + m_AnimationTree.createNode("specialWorkspaceIn", "specialWorkspace"); + m_AnimationTree.createNode("specialWorkspaceOut", "specialWorkspace"); - // workspaces - INITANIMCFG("workspaces"); - INITANIMCFG("workspacesIn"); - INITANIMCFG("workspacesOut"); - INITANIMCFG("specialWorkspace"); - INITANIMCFG("specialWorkspaceIn"); - INITANIMCFG("specialWorkspaceOut"); - } - - // init the values - animationConfig["global"] = {false, "default", "", 8.f, 1, &animationConfig["general"], nullptr}; - - animationConfig["__internal_fadeCTM"] = {false, "linear", "", 5.F, 1, &animationConfig["__internal_fadeCTM"], nullptr}; - - CREATEANIMCFG("windows", "global"); - CREATEANIMCFG("layers", "global"); - CREATEANIMCFG("fade", "global"); - CREATEANIMCFG("border", "global"); - CREATEANIMCFG("borderangle", "global"); - CREATEANIMCFG("workspaces", "global"); - - CREATEANIMCFG("layersIn", "layers"); - CREATEANIMCFG("layersOut", "layers"); - - CREATEANIMCFG("windowsIn", "windows"); - CREATEANIMCFG("windowsOut", "windows"); - CREATEANIMCFG("windowsMove", "windows"); - - CREATEANIMCFG("fadeIn", "fade"); - CREATEANIMCFG("fadeOut", "fade"); - CREATEANIMCFG("fadeSwitch", "fade"); - CREATEANIMCFG("fadeShadow", "fade"); - CREATEANIMCFG("fadeDim", "fade"); - CREATEANIMCFG("fadeLayers", "fade"); - CREATEANIMCFG("fadeLayersIn", "fadeLayers"); - CREATEANIMCFG("fadeLayersOut", "fadeLayers"); - - CREATEANIMCFG("workspacesIn", "workspaces"); - CREATEANIMCFG("workspacesOut", "workspaces"); - CREATEANIMCFG("specialWorkspace", "workspaces"); - CREATEANIMCFG("specialWorkspaceIn", "specialWorkspace"); - CREATEANIMCFG("specialWorkspaceOut", "specialWorkspace"); + // init the root nodes + m_AnimationTree.setConfigForNode("global", 1, 8.f, "", "default"); + m_AnimationTree.setConfigForNode("__internal_fadeCTM", 1, 5.f, "", "linear"); } std::optional CConfigManager::resetHLConfig() { @@ -857,6 +828,8 @@ std::optional CConfigManager::resetHLConfig() { m_vWindowRules.clear(); g_pKeybindManager->clearKeybinds(); g_pAnimationManager->removeAllBeziers(); + g_pAnimationManager->addBezierWithName("linear", Vector2D(0.0, 0.0), Vector2D(1.0, 1.0)); + m_mAdditionalReservedAreas.clear(); m_dBlurLSNamespaces.clear(); m_vWorkspaceRules.clear(); @@ -1647,8 +1620,8 @@ void CConfigManager::ensureVRR(PHLMONITOR pMonitor) { } } -SAnimationPropertyConfig* CConfigManager::getAnimationPropertyConfig(const std::string& name) { - return &animationConfig[name]; +SP CConfigManager::getAnimationPropertyConfig(const std::string& name) { + return m_AnimationTree.getConfig(name); } void CConfigManager::addParseError(const std::string& err) { @@ -1711,8 +1684,8 @@ ICustomConfigValueData::~ICustomConfigValueData() { ; // empty } -std::unordered_map CConfigManager::getAnimationConfig() { - return animationConfig; +const std::unordered_map>& CConfigManager::getAnimationConfig() { + return m_AnimationTree.getFullConfig(); } void CConfigManager::addPluginConfigVar(HANDLE handle, const std::string& name, const Hyprlang::CConfigValue& value) { @@ -2058,17 +2031,6 @@ std::optional CConfigManager::handleBezier(const std::string& comma return {}; } -void CConfigManager::setAnimForChildren(SAnimationPropertyConfig* const ANIM) { - for (auto& [name, anim] : animationConfig) { - if (anim.pParentAnimation == ANIM && !anim.overridden) { - // if a child isnt overridden, set the values of the parent - anim.pValues = ANIM->pValues; - - setAnimForChildren(&anim); - } - } -}; - std::optional CConfigManager::handleAnimation(const std::string& command, const std::string& args) { const auto ARGS = CVarList(args); @@ -2077,14 +2039,9 @@ std::optional CConfigManager::handleAnimation(const std::string& co // anim name const auto ANIMNAME = ARGS[0]; - const auto PANIM = animationConfig.find(ANIMNAME); - - if (PANIM == animationConfig.end()) + if (!m_AnimationTree.nodeExists(ANIMNAME)) return "no such animation"; - PANIM->second.overridden = true; - PANIM->second.pValues = &PANIM->second; - // This helper casts strings like "1", "true", "off", "yes"... to int. int64_t enabledInt = configStringToInt(ARGS[1]).value_or(0) == 1; @@ -2092,33 +2049,31 @@ std::optional CConfigManager::handleAnimation(const std::string& co if (enabledInt != 0 && enabledInt != 1) return "invalid animation on/off state"; - PANIM->second.internalEnabled = configStringToInt(ARGS[1]).value_or(0) == 1; + if (enabledInt) { + int64_t speed = -1; - if (PANIM->second.internalEnabled) { // speed if (isNumber(ARGS[2], true)) { - PANIM->second.internalSpeed = std::stof(ARGS[2]); + speed = std::stof(ARGS[2]); - if (PANIM->second.internalSpeed <= 0) { - PANIM->second.internalSpeed = 1.f; + if (speed <= 0) { + speed = 1.f; return "invalid speed"; } } else { - PANIM->second.internalSpeed = 10.f; + speed = 10.f; return "invalid speed"; } - // curve - PANIM->second.internalBezier = ARGS[3]; + std::string bezierName = ARGS[3]; + m_AnimationTree.setConfigForNode(ANIMNAME, enabledInt, speed, ARGS[3], ARGS[4]); - if (!g_pAnimationManager->bezierExists(ARGS[3])) { - PANIM->second.internalBezier = "default"; + if (!g_pAnimationManager->bezierExists(bezierName)) { + const auto PANIMNODE = m_AnimationTree.getConfig(ANIMNAME); + PANIMNODE->internalBezier = "default"; return "no such bezier"; } - // style - PANIM->second.internalStyle = ARGS[4]; - if (ARGS[4] != "") { auto ERR = g_pAnimationManager->styleValidInConfigVar(ANIMNAME, ARGS[4]); @@ -2127,9 +2082,6 @@ std::optional CConfigManager::handleAnimation(const std::string& co } } - // now, check for children, recursively - setAnimForChildren(&PANIM->second); - return {}; } diff --git a/src/config/ConfigManager.hpp b/src/config/ConfigManager.hpp index 436362ae..53772401 100644 --- a/src/config/ConfigManager.hpp +++ b/src/config/ConfigManager.hpp @@ -1,5 +1,6 @@ #pragma once +#include #define CONFIG_MANAGER_H #include @@ -23,9 +24,6 @@ #include -#define INITANIMCFG(name) animationConfig[name] = {} -#define CREATEANIMCFG(name, parent) animationConfig[name] = {false, "", "", 0.f, -1, &animationConfig["global"], &animationConfig[parent]} - #define HANDLE void* struct SWorkspaceRule { @@ -54,18 +52,6 @@ struct SMonitorAdditionalReservedArea { int right = 0; }; -struct SAnimationPropertyConfig { - bool overridden = true; - - std::string internalBezier = ""; - std::string internalStyle = ""; - float internalSpeed = 0.f; - int internalEnabled = -1; - - SAnimationPropertyConfig* pValues = nullptr; - SAnimationPropertyConfig* pParentAnimation = nullptr; -}; - struct SPluginKeyword { HANDLE handle = nullptr; std::string name = ""; @@ -181,32 +167,32 @@ class CConfigManager { std::unordered_map m_mAdditionalReservedAreas; - std::unordered_map getAnimationConfig(); + const std::unordered_map>& getAnimationConfig(); - void addPluginConfigVar(HANDLE handle, const std::string& name, const Hyprlang::CConfigValue& value); + void addPluginConfigVar(HANDLE handle, const std::string& name, const Hyprlang::CConfigValue& value); void addPluginKeyword(HANDLE handle, const std::string& name, Hyprlang::PCONFIGHANDLERFUNC fun, Hyprlang::SHandlerOptions opts = {}); void removePluginConfig(HANDLE handle); // no-op when done. - void dispatchExecOnce(); - void dispatchExecShutdown(); + void dispatchExecOnce(); + void dispatchExecShutdown(); - void performMonitorReload(); - void ensureMonitorStatus(); - void ensureVRR(PHLMONITOR pMonitor = nullptr); + void performMonitorReload(); + void ensureMonitorStatus(); + void ensureVRR(PHLMONITOR pMonitor = nullptr); - bool shouldUseSoftwareCursors(); + bool shouldUseSoftwareCursors(); - std::string parseKeyword(const std::string&, const std::string&); + std::string parseKeyword(const std::string&, const std::string&); - void addParseError(const std::string&); + void addParseError(const std::string&); - SAnimationPropertyConfig* getAnimationPropertyConfig(const std::string&); + SP getAnimationPropertyConfig(const std::string&); - void addExecRule(const SExecRequestedRule&); + void addExecRule(const SExecRequestedRule&); - void handlePluginLoads(); - std::string getErrors(); + void handlePluginLoads(); + std::string getErrors(); // keywords std::optional handleRawExec(const std::string&, const std::string&); @@ -269,39 +255,38 @@ class CConfigManager { bool isLaunchingExecOnce = false; // For exec-once to skip initial ws tracking private: - std::unique_ptr m_pConfig; + std::unique_ptr m_pConfig; - std::vector configPaths; // stores all the config paths - std::unordered_map configModifyTimes; // stores modify times + std::vector configPaths; // stores all the config paths + std::unordered_map configModifyTimes; // stores modify times - std::unordered_map animationConfig; // stores all the animations with their set values + Hyprutils::Animation::CAnimationConfigTree m_AnimationTree; - std::string m_szCurrentSubmap = ""; // For storing the current keybind submap + std::string m_szCurrentSubmap = ""; // For storing the current keybind submap - std::vector execRequestedRules; // rules requested with exec, e.g. [workspace 2] kitty + std::vector execRequestedRules; // rules requested with exec, e.g. [workspace 2] kitty - std::vector m_vDeclaredPlugins; - std::vector pluginKeywords; - std::vector pluginVariables; + std::vector m_vDeclaredPlugins; + std::vector pluginKeywords; + std::vector pluginVariables; - bool isFirstLaunch = true; // For exec-once + bool isFirstLaunch = true; // For exec-once - std::vector m_vMonitorRules; - std::vector m_vWorkspaceRules; - std::vector> m_vWindowRules; - std::vector> m_vLayerRules; - std::vector m_dBlurLSNamespaces; + std::vector m_vMonitorRules; + std::vector m_vWorkspaceRules; + std::vector> m_vWindowRules; + std::vector> m_vLayerRules; + std::vector m_dBlurLSNamespaces; - bool firstExecDispatched = false; - bool m_bManualCrashInitiated = false; - std::vector firstExecRequests; - std::vector finalExecRequests; + bool firstExecDispatched = false; + bool m_bManualCrashInitiated = false; + std::vector firstExecRequests; + std::vector finalExecRequests; - std::vector> m_vFailedPluginConfigValues; // for plugin values of unloaded plugins - std::string m_szConfigErrors = ""; + std::vector> m_vFailedPluginConfigValues; // for plugin values of unloaded plugins + std::string m_szConfigErrors = ""; // internal methods - void setAnimForChildren(SAnimationPropertyConfig* const); void updateBlurredLS(const std::string&, const bool); void setDefaultAnimationVars(); std::optional resetHLConfig(); diff --git a/src/debug/HyprCtl.cpp b/src/debug/HyprCtl.cpp index 8724d2c7..7edace21 100644 --- a/src/debug/HyprCtl.cpp +++ b/src/debug/HyprCtl.cpp @@ -248,8 +248,8 @@ std::string CHyprCtl::getWindowData(PHLWINDOW w, eHyprCtlOutputFormat format) { "focusHistoryID": {}, "inhibitingIdle": {} }},)#", - (uintptr_t)w.get(), (w->m_bIsMapped ? "true" : "false"), (w->isHidden() ? "true" : "false"), (int)w->m_vRealPosition.goal().x, (int)w->m_vRealPosition.goal().y, - (int)w->m_vRealSize.goal().x, (int)w->m_vRealSize.goal().y, w->m_pWorkspace ? w->workspaceID() : WORKSPACE_INVALID, + (uintptr_t)w.get(), (w->m_bIsMapped ? "true" : "false"), (w->isHidden() ? "true" : "false"), (int)w->m_vRealPosition->goal().x, (int)w->m_vRealPosition->goal().y, + (int)w->m_vRealSize->goal().x, (int)w->m_vRealSize->goal().y, w->m_pWorkspace ? w->workspaceID() : WORKSPACE_INVALID, escapeJSONStrings(!w->m_pWorkspace ? "" : w->m_pWorkspace->m_szName), ((int)w->m_bIsFloating == 1 ? "true" : "false"), (w->m_bIsPseudotiled ? "true" : "false"), (int64_t)w->monitorID(), escapeJSONStrings(w->m_szClass), escapeJSONStrings(w->m_szTitle), escapeJSONStrings(w->m_szInitialClass), escapeJSONStrings(w->m_szInitialTitle), w->getPID(), ((int)w->m_bIsX11 == 1 ? "true" : "false"), (w->m_bPinned ? "true" : "false"), @@ -261,11 +261,12 @@ std::string CHyprCtl::getWindowData(PHLWINDOW w, eHyprCtlOutputFormat format) { "{}\n\tinitialClass: {}\n\tinitialTitle: {}\n\tpid: " "{}\n\txwayland: {}\n\tpinned: " "{}\n\tfullscreen: {}\n\tfullscreenClient: {}\n\tgrouped: {}\n\ttags: {}\n\tswallowing: {:x}\n\tfocusHistoryID: {}\n\tinhibitingIdle: {}\n\n", - (uintptr_t)w.get(), w->m_szTitle, (int)w->m_bIsMapped, (int)w->isHidden(), (int)w->m_vRealPosition.goal().x, (int)w->m_vRealPosition.goal().y, - (int)w->m_vRealSize.goal().x, (int)w->m_vRealSize.goal().y, w->m_pWorkspace ? w->workspaceID() : WORKSPACE_INVALID, (!w->m_pWorkspace ? "" : w->m_pWorkspace->m_szName), - (int)w->m_bIsFloating, (int)w->m_bIsPseudotiled, (int64_t)w->monitorID(), w->m_szClass, w->m_szTitle, w->m_szInitialClass, w->m_szInitialTitle, w->getPID(), - (int)w->m_bIsX11, (int)w->m_bPinned, (uint8_t)w->m_sFullscreenState.internal, (uint8_t)w->m_sFullscreenState.client, getGroupedData(w, format), getTagsData(w, format), - (uintptr_t)w->m_pSwallowed.lock().get(), getFocusHistoryID(w), (int)g_pInputManager->isWindowInhibiting(w, false)); + (uintptr_t)w.get(), w->m_szTitle, (int)w->m_bIsMapped, (int)w->isHidden(), (int)w->m_vRealPosition->goal().x, (int)w->m_vRealPosition->goal().y, + (int)w->m_vRealSize->goal().x, (int)w->m_vRealSize->goal().y, w->m_pWorkspace ? w->workspaceID() : WORKSPACE_INVALID, + (!w->m_pWorkspace ? "" : w->m_pWorkspace->m_szName), (int)w->m_bIsFloating, (int)w->m_bIsPseudotiled, (int64_t)w->monitorID(), w->m_szClass, w->m_szTitle, + w->m_szInitialClass, w->m_szInitialTitle, w->getPID(), (int)w->m_bIsX11, (int)w->m_bPinned, (uint8_t)w->m_sFullscreenState.internal, + (uint8_t)w->m_sFullscreenState.client, getGroupedData(w, format), getTagsData(w, format), (uintptr_t)w->m_pSwallowed.lock().get(), getFocusHistoryID(w), + (int)g_pInputManager->isWindowInhibiting(w, false)); } } @@ -732,8 +733,8 @@ static std::string animationsRequest(eHyprCtlOutputFormat format, std::string re ret += "animations:\n"; for (auto const& ac : g_pConfigManager->getAnimationConfig()) { - ret += std::format("\n\tname: {}\n\t\toverriden: {}\n\t\tbezier: {}\n\t\tenabled: {}\n\t\tspeed: {:.2f}\n\t\tstyle: {}\n", ac.first, (int)ac.second.overridden, - ac.second.internalBezier, ac.second.internalEnabled, ac.second.internalSpeed, ac.second.internalStyle); + ret += std::format("\n\tname: {}\n\t\toverriden: {}\n\t\tbezier: {}\n\t\tenabled: {}\n\t\tspeed: {:.2f}\n\t\tstyle: {}\n", ac.first, (int)ac.second->overridden, + ac.second->internalBezier, ac.second->internalEnabled, ac.second->internalSpeed, ac.second->internalStyle); } ret += "beziers:\n"; @@ -755,8 +756,8 @@ static std::string animationsRequest(eHyprCtlOutputFormat format, std::string re "speed": {:.2f}, "style": "{}" }},)#", - ac.first, ac.second.overridden ? "true" : "false", escapeJSONStrings(ac.second.internalBezier), ac.second.internalEnabled ? "true" : "false", - ac.second.internalSpeed, escapeJSONStrings(ac.second.internalStyle)); + ac.first, ac.second->overridden ? "true" : "false", escapeJSONStrings(ac.second->internalBezier), ac.second->internalEnabled ? "true" : "false", + ac.second->internalSpeed, escapeJSONStrings(ac.second->internalStyle)); } ret[ret.length() - 1] = ']'; diff --git a/src/desktop/LayerSurface.cpp b/src/desktop/LayerSurface.cpp index 05ea4473..fe11f3f3 100644 --- a/src/desktop/LayerSurface.cpp +++ b/src/desktop/LayerSurface.cpp @@ -4,6 +4,7 @@ #include "../protocols/LayerShell.hpp" #include "../protocols/core/Compositor.hpp" #include "../managers/SeatManager.hpp" +#include "../managers/AnimationManager.hpp" PHLLS CLayerSurface::create(SP resource) { PHLLS pLS = SP(new CLayerSurface(resource)); @@ -31,16 +32,13 @@ PHLLS CLayerSurface::create(SP resource) { pLS->forceBlur = g_pConfigManager->shouldBlurLS(pLS->szNamespace); - pLS->alpha.create(g_pConfigManager->getAnimationPropertyConfig("fadeLayersIn"), pLS, AVARDAMAGE_ENTIRE); - pLS->realPosition.create(g_pConfigManager->getAnimationPropertyConfig("layersIn"), pLS, AVARDAMAGE_ENTIRE); - pLS->realSize.create(g_pConfigManager->getAnimationPropertyConfig("layersIn"), pLS, AVARDAMAGE_ENTIRE); - pLS->alpha.registerVar(); - pLS->realPosition.registerVar(); - pLS->realSize.registerVar(); + g_pAnimationManager->createAnimation(0.f, pLS->alpha, g_pConfigManager->getAnimationPropertyConfig("fadeLayersIn"), pLS, AVARDAMAGE_ENTIRE); + g_pAnimationManager->createAnimation(Vector2D(0, 0), pLS->realPosition, g_pConfigManager->getAnimationPropertyConfig("layersIn"), pLS, AVARDAMAGE_ENTIRE); + g_pAnimationManager->createAnimation(Vector2D(0, 0), pLS->realSize, g_pConfigManager->getAnimationPropertyConfig("layersIn"), pLS, AVARDAMAGE_ENTIRE); pLS->registerCallbacks(); - pLS->alpha.setValueAndWarp(0.f); + pLS->alpha->setValueAndWarp(0.f); Debug::log(LOG, "LayerSurface {:x} (namespace {} layer {}) created on monitor {}", (uintptr_t)resource.get(), resource->layerNamespace, (int)pLS->layer, pMonitor->szName); @@ -48,7 +46,7 @@ PHLLS CLayerSurface::create(SP resource) { } void CLayerSurface::registerCallbacks() { - alpha.setUpdateCallback([this](void*) { + alpha->setUpdateCallback([this](auto) { if (dimAround) g_pHyprRenderer->damageMonitor(monitor.lock()); }); @@ -93,7 +91,7 @@ void CLayerSurface::onDestroy() { onUnmap(); } else { Debug::log(LOG, "Removing LayerSurface that wasn't mapped."); - alpha.setValueAndWarp(0.f); + alpha->setValueAndWarp(0.f); fadingOut = true; g_pCompositor->addToFadingOutSafe(self.lock()); } @@ -307,17 +305,17 @@ void CLayerSurface::onCommit() { } } - if (realPosition.goal() != geometry.pos()) { - if (realPosition.isBeingAnimated()) - realPosition = geometry.pos(); + if (realPosition->goal() != geometry.pos()) { + if (realPosition->isBeingAnimated()) + *realPosition = geometry.pos(); else - realPosition.setValueAndWarp(geometry.pos()); + realPosition->setValueAndWarp(geometry.pos()); } - if (realSize.goal() != geometry.size()) { - if (realSize.isBeingAnimated()) - realSize = geometry.size(); + if (realSize->goal() != geometry.size()) { + if (realSize->isBeingAnimated()) + *realSize = geometry.size(); else - realSize.setValueAndWarp(geometry.size()); + realSize->setValueAndWarp(geometry.size()); } if (mapped && (layerSurface->current.committed & CLayerShellResource::eCommittedState::STATE_INTERACTIVITY)) { @@ -434,17 +432,17 @@ void CLayerSurface::applyRules() { } void CLayerSurface::startAnimation(bool in, bool instant) { - const auto ANIMSTYLE = animationStyle.value_or(realPosition.m_pConfig->pValues->internalStyle); if (in) { - realPosition.m_pConfig = g_pConfigManager->getAnimationPropertyConfig("layersIn"); - realSize.m_pConfig = g_pConfigManager->getAnimationPropertyConfig("layersIn"); - alpha.m_pConfig = g_pConfigManager->getAnimationPropertyConfig("fadeLayersIn"); + realPosition->setConfig(g_pConfigManager->getAnimationPropertyConfig("layersIn")); + realSize->setConfig(g_pConfigManager->getAnimationPropertyConfig("layersIn")); + alpha->setConfig(g_pConfigManager->getAnimationPropertyConfig("fadeLayersIn")); } else { - realPosition.m_pConfig = g_pConfigManager->getAnimationPropertyConfig("layersOut"); - realSize.m_pConfig = g_pConfigManager->getAnimationPropertyConfig("layersOut"); - alpha.m_pConfig = g_pConfigManager->getAnimationPropertyConfig("fadeLayersOut"); + realPosition->setConfig(g_pConfigManager->getAnimationPropertyConfig("layersOut")); + realSize->setConfig(g_pConfigManager->getAnimationPropertyConfig("layersOut")); + alpha->setConfig(g_pConfigManager->getAnimationPropertyConfig("fadeLayersOut")); } + const auto ANIMSTYLE = animationStyle.value_or(realPosition->getStyle()); if (ANIMSTYLE.starts_with("slide")) { // get closest edge const auto MIDDLE = geometry.middle(); @@ -485,9 +483,9 @@ void CLayerSurface::startAnimation(bool in, bool instant) { } } - realSize.setValueAndWarp(geometry.size()); - alpha.setValueAndWarp(in ? 0.f : 1.f); - alpha = in ? 1.f : 0.f; + realSize->setValueAndWarp(geometry.size()); + alpha->setValueAndWarp(in ? 0.f : 1.f); + *alpha = in ? 1.f : 0.f; Vector2D prePos; @@ -512,11 +510,11 @@ void CLayerSurface::startAnimation(bool in, bool instant) { } if (in) { - realPosition.setValueAndWarp(prePos); - realPosition = geometry.pos(); + realPosition->setValueAndWarp(prePos); + *realPosition = geometry.pos(); } else { - realPosition.setValueAndWarp(geometry.pos()); - realPosition = prePos; + realPosition->setValueAndWarp(geometry.pos()); + *realPosition = prePos; } } else if (ANIMSTYLE.starts_with("popin")) { @@ -535,25 +533,25 @@ void CLayerSurface::startAnimation(bool in, bool instant) { const auto GOALSIZE = (geometry.size() * minPerc).clamp({5, 5}); const auto GOALPOS = geometry.pos() + (geometry.size() - GOALSIZE) / 2.f; - alpha.setValueAndWarp(in ? 0.f : 1.f); - alpha = in ? 1.f : 0.f; + alpha->setValueAndWarp(in ? 0.f : 1.f); + *alpha = in ? 1.f : 0.f; if (in) { - realSize.setValueAndWarp(GOALSIZE); - realPosition.setValueAndWarp(GOALPOS); - realSize = geometry.size(); - realPosition = geometry.pos(); + realSize->setValueAndWarp(GOALSIZE); + realPosition->setValueAndWarp(GOALPOS); + *realSize = geometry.size(); + *realPosition = geometry.pos(); } else { - realSize.setValueAndWarp(geometry.size()); - realPosition.setValueAndWarp(geometry.pos()); - realSize = GOALSIZE; - realPosition = GOALPOS; + realSize->setValueAndWarp(geometry.size()); + realPosition->setValueAndWarp(geometry.pos()); + *realSize = GOALSIZE; + *realPosition = GOALPOS; } } else { // fade - realPosition.setValueAndWarp(geometry.pos()); - realSize.setValueAndWarp(geometry.size()); - alpha = in ? 1.f : 0.f; + realPosition->setValueAndWarp(geometry.pos()); + realSize->setValueAndWarp(geometry.size()); + *alpha = in ? 1.f : 0.f; } if (!in) @@ -564,7 +562,7 @@ bool CLayerSurface::isFadedOut() { if (!fadingOut) return false; - return !realPosition.isBeingAnimated() && !realSize.isBeingAnimated() && !alpha.isBeingAnimated(); + return !realPosition->isBeingAnimated() && !realSize->isBeingAnimated() && !alpha->isBeingAnimated(); } int CLayerSurface::popupsCount() { diff --git a/src/desktop/LayerSurface.hpp b/src/desktop/LayerSurface.hpp index e906fc6f..3a03e57e 100644 --- a/src/desktop/LayerSurface.hpp +++ b/src/desktop/LayerSurface.hpp @@ -18,17 +18,17 @@ class CLayerSurface { public: ~CLayerSurface(); - void applyRules(); - void startAnimation(bool in, bool instant = false); - bool isFadedOut(); - int popupsCount(); + void applyRules(); + void startAnimation(bool in, bool instant = false); + bool isFadedOut(); + int popupsCount(); - CAnimatedVariable realPosition; - CAnimatedVariable realSize; - CAnimatedVariable alpha; + PHLANIMVAR realPosition; + PHLANIMVAR realSize; + PHLANIMVAR alpha; - WP layerSurface; - wl_list link; + WP layerSurface; + wl_list link; // the header providing the enum type cannot be imported here int interactivity = 0; diff --git a/src/desktop/Popup.cpp b/src/desktop/Popup.cpp index 692a75e3..ce286b28 100644 --- a/src/desktop/Popup.cpp +++ b/src/desktop/Popup.cpp @@ -243,9 +243,9 @@ Vector2D CPopup::localToGlobal(const Vector2D& rel) { Vector2D CPopup::t1ParentCoords() { if (!m_pWindowOwner.expired()) - return m_pWindowOwner->m_vRealPosition.value(); + return m_pWindowOwner->m_vRealPosition->value(); if (!m_pLayerOwner.expired()) - return m_pLayerOwner->realPosition.value(); + return m_pLayerOwner->realPosition->value(); ASSERT(false); return {}; diff --git a/src/desktop/Subsurface.cpp b/src/desktop/Subsurface.cpp index 893411bd..62854f80 100644 --- a/src/desktop/Subsurface.cpp +++ b/src/desktop/Subsurface.cpp @@ -169,7 +169,7 @@ Vector2D CSubsurface::coordsGlobal() { Vector2D coords = coordsRelativeToParent(); if (!m_pWindowParent.expired()) - coords += m_pWindowParent->m_vRealPosition.value(); + coords += m_pWindowParent->m_vRealPosition->value(); else if (m_pPopupParent) coords += m_pPopupParent->coordsGlobal(); diff --git a/src/desktop/WLSurface.cpp b/src/desktop/WLSurface.cpp index 5e88f507..9ed8ec49 100644 --- a/src/desktop/WLSurface.cpp +++ b/src/desktop/WLSurface.cpp @@ -72,7 +72,7 @@ Vector2D CWLSurface::correctSmallVec() const { const auto SIZE = getViewporterCorrectedSize(); const auto O = m_pWindowOwner.lock(); - return Vector2D{(O->m_vReportedSize.x - SIZE.x) / 2, (O->m_vReportedSize.y - SIZE.y) / 2}.clamp({}, {INFINITY, INFINITY}) * (O->m_vRealSize.value() / O->m_vReportedSize); + return Vector2D{(O->m_vReportedSize.x - SIZE.x) / 2, (O->m_vReportedSize.y - SIZE.y) / 2}.clamp({}, {INFINITY, INFINITY}) * (O->m_vRealSize->value() / O->m_vReportedSize); } Vector2D CWLSurface::correctSmallVecBuf() const { diff --git a/src/desktop/Window.cpp b/src/desktop/Window.cpp index 60914198..8175fc57 100644 --- a/src/desktop/Window.cpp +++ b/src/desktop/Window.cpp @@ -1,3 +1,4 @@ +#include #include #include @@ -11,12 +12,16 @@ #include "../render/decorations/CHyprBorderDecoration.hpp" #include "../config/ConfigValue.hpp" #include "../managers/TokenManager.hpp" +#include "../managers/AnimationManager.hpp" #include "../protocols/XDGShell.hpp" #include "../protocols/core/Compositor.hpp" #include "../xwayland/XWayland.hpp" +#include "../helpers/Color.hpp" #include + using namespace Hyprutils::String; +using namespace Hyprutils::Animation; PHLWINDOW CWindow::create(SP surface) { PHLWINDOW pWindow = SP(new CWindow(surface)); @@ -24,16 +29,16 @@ PHLWINDOW CWindow::create(SP surface) { pWindow->m_pSelf = pWindow; pWindow->m_bIsX11 = true; - pWindow->m_vRealPosition.create(g_pConfigManager->getAnimationPropertyConfig("windowsIn"), pWindow, AVARDAMAGE_ENTIRE); - pWindow->m_vRealSize.create(g_pConfigManager->getAnimationPropertyConfig("windowsIn"), pWindow, AVARDAMAGE_ENTIRE); - pWindow->m_fBorderFadeAnimationProgress.create(g_pConfigManager->getAnimationPropertyConfig("border"), pWindow, AVARDAMAGE_BORDER); - pWindow->m_fBorderAngleAnimationProgress.create(g_pConfigManager->getAnimationPropertyConfig("borderangle"), pWindow, AVARDAMAGE_BORDER); - pWindow->m_fAlpha.create(g_pConfigManager->getAnimationPropertyConfig("fadeIn"), pWindow, AVARDAMAGE_ENTIRE); - pWindow->m_fActiveInactiveAlpha.create(g_pConfigManager->getAnimationPropertyConfig("fadeSwitch"), pWindow, AVARDAMAGE_ENTIRE); - pWindow->m_cRealShadowColor.create(g_pConfigManager->getAnimationPropertyConfig("fadeShadow"), pWindow, AVARDAMAGE_SHADOW); - pWindow->m_fDimPercent.create(g_pConfigManager->getAnimationPropertyConfig("fadeDim"), pWindow, AVARDAMAGE_ENTIRE); - pWindow->m_fMovingToWorkspaceAlpha.create(g_pConfigManager->getAnimationPropertyConfig("fadeOut"), pWindow, AVARDAMAGE_ENTIRE); - pWindow->m_fMovingFromWorkspaceAlpha.create(g_pConfigManager->getAnimationPropertyConfig("fadeIn"), pWindow, AVARDAMAGE_ENTIRE); + g_pAnimationManager->createAnimation(Vector2D(0, 0), pWindow->m_vRealPosition, g_pConfigManager->getAnimationPropertyConfig("windowsIn"), pWindow, AVARDAMAGE_ENTIRE); + g_pAnimationManager->createAnimation(Vector2D(0, 0), pWindow->m_vRealSize, g_pConfigManager->getAnimationPropertyConfig("windowsIn"), pWindow, AVARDAMAGE_ENTIRE); + g_pAnimationManager->createAnimation(0.f, pWindow->m_fBorderFadeAnimationProgress, g_pConfigManager->getAnimationPropertyConfig("border"), pWindow, AVARDAMAGE_BORDER); + g_pAnimationManager->createAnimation(0.f, pWindow->m_fBorderAngleAnimationProgress, g_pConfigManager->getAnimationPropertyConfig("borderangle"), pWindow, AVARDAMAGE_BORDER); + g_pAnimationManager->createAnimation(1.f, pWindow->m_fAlpha, g_pConfigManager->getAnimationPropertyConfig("fadeIn"), pWindow, AVARDAMAGE_ENTIRE); + g_pAnimationManager->createAnimation(1.f, pWindow->m_fActiveInactiveAlpha, g_pConfigManager->getAnimationPropertyConfig("fadeSwitch"), pWindow, AVARDAMAGE_ENTIRE); + g_pAnimationManager->createAnimation(CHyprColor(), pWindow->m_cRealShadowColor, g_pConfigManager->getAnimationPropertyConfig("fadeShadow"), pWindow, AVARDAMAGE_SHADOW); + g_pAnimationManager->createAnimation(0.f, pWindow->m_fDimPercent, g_pConfigManager->getAnimationPropertyConfig("fadeDim"), pWindow, AVARDAMAGE_ENTIRE); + g_pAnimationManager->createAnimation(0.f, pWindow->m_fMovingToWorkspaceAlpha, g_pConfigManager->getAnimationPropertyConfig("fadeOut"), pWindow, AVARDAMAGE_ENTIRE); + g_pAnimationManager->createAnimation(0.f, pWindow->m_fMovingFromWorkspaceAlpha, g_pConfigManager->getAnimationPropertyConfig("fadeIn"), pWindow, AVARDAMAGE_ENTIRE); pWindow->addWindowDeco(std::make_unique(pWindow)); pWindow->addWindowDeco(std::make_unique(pWindow)); @@ -47,16 +52,16 @@ PHLWINDOW CWindow::create(SP resource) { pWindow->m_pSelf = pWindow; resource->toplevel->window = pWindow; - pWindow->m_vRealPosition.create(g_pConfigManager->getAnimationPropertyConfig("windowsIn"), pWindow, AVARDAMAGE_ENTIRE); - pWindow->m_vRealSize.create(g_pConfigManager->getAnimationPropertyConfig("windowsIn"), pWindow, AVARDAMAGE_ENTIRE); - pWindow->m_fBorderFadeAnimationProgress.create(g_pConfigManager->getAnimationPropertyConfig("border"), pWindow, AVARDAMAGE_BORDER); - pWindow->m_fBorderAngleAnimationProgress.create(g_pConfigManager->getAnimationPropertyConfig("borderangle"), pWindow, AVARDAMAGE_BORDER); - pWindow->m_fAlpha.create(g_pConfigManager->getAnimationPropertyConfig("fadeIn"), pWindow, AVARDAMAGE_ENTIRE); - pWindow->m_fActiveInactiveAlpha.create(g_pConfigManager->getAnimationPropertyConfig("fadeSwitch"), pWindow, AVARDAMAGE_ENTIRE); - pWindow->m_cRealShadowColor.create(g_pConfigManager->getAnimationPropertyConfig("fadeShadow"), pWindow, AVARDAMAGE_SHADOW); - pWindow->m_fDimPercent.create(g_pConfigManager->getAnimationPropertyConfig("fadeDim"), pWindow, AVARDAMAGE_ENTIRE); - pWindow->m_fMovingToWorkspaceAlpha.create(g_pConfigManager->getAnimationPropertyConfig("fadeOut"), pWindow, AVARDAMAGE_ENTIRE); - pWindow->m_fMovingFromWorkspaceAlpha.create(g_pConfigManager->getAnimationPropertyConfig("fadeIn"), pWindow, AVARDAMAGE_ENTIRE); + g_pAnimationManager->createAnimation(Vector2D(0, 0), pWindow->m_vRealPosition, g_pConfigManager->getAnimationPropertyConfig("windowsIn"), pWindow, AVARDAMAGE_ENTIRE); + g_pAnimationManager->createAnimation(Vector2D(0, 0), pWindow->m_vRealSize, g_pConfigManager->getAnimationPropertyConfig("windowsIn"), pWindow, AVARDAMAGE_ENTIRE); + g_pAnimationManager->createAnimation(0.f, pWindow->m_fBorderFadeAnimationProgress, g_pConfigManager->getAnimationPropertyConfig("border"), pWindow, AVARDAMAGE_BORDER); + g_pAnimationManager->createAnimation(0.f, pWindow->m_fBorderAngleAnimationProgress, g_pConfigManager->getAnimationPropertyConfig("borderangle"), pWindow, AVARDAMAGE_BORDER); + g_pAnimationManager->createAnimation(1.f, pWindow->m_fAlpha, g_pConfigManager->getAnimationPropertyConfig("fadeIn"), pWindow, AVARDAMAGE_ENTIRE); + g_pAnimationManager->createAnimation(1.f, pWindow->m_fActiveInactiveAlpha, g_pConfigManager->getAnimationPropertyConfig("fadeSwitch"), pWindow, AVARDAMAGE_ENTIRE); + g_pAnimationManager->createAnimation(CHyprColor(), pWindow->m_cRealShadowColor, g_pConfigManager->getAnimationPropertyConfig("fadeShadow"), pWindow, AVARDAMAGE_SHADOW); + g_pAnimationManager->createAnimation(0.f, pWindow->m_fDimPercent, g_pConfigManager->getAnimationPropertyConfig("fadeDim"), pWindow, AVARDAMAGE_ENTIRE); + g_pAnimationManager->createAnimation(0.f, pWindow->m_fMovingToWorkspaceAlpha, g_pConfigManager->getAnimationPropertyConfig("fadeOut"), pWindow, AVARDAMAGE_ENTIRE); + g_pAnimationManager->createAnimation(0.f, pWindow->m_fMovingFromWorkspaceAlpha, g_pConfigManager->getAnimationPropertyConfig("fadeIn"), pWindow, AVARDAMAGE_ENTIRE); pWindow->addWindowDeco(std::make_unique(pWindow)); pWindow->addWindowDeco(std::make_unique(pWindow)); @@ -118,8 +123,8 @@ SBoxExtents CWindow::getFullWindowExtents() { if (m_sWindowData.dimAround.valueOrDefault()) { if (const auto PMONITOR = m_pMonitor.lock(); PMONITOR) - return {{m_vRealPosition.value().x - PMONITOR->vecPosition.x, m_vRealPosition.value().y - PMONITOR->vecPosition.y}, - {PMONITOR->vecSize.x - (m_vRealPosition.value().x - PMONITOR->vecPosition.x), PMONITOR->vecSize.y - (m_vRealPosition.value().y - PMONITOR->vecPosition.y)}}; + return {{m_vRealPosition->value().x - PMONITOR->vecPosition.x, m_vRealPosition->value().y - PMONITOR->vecPosition.y}, + {PMONITOR->vecSize.x - (m_vRealPosition->value().x - PMONITOR->vecPosition.x), PMONITOR->vecSize.y - (m_vRealPosition->value().y - PMONITOR->vecPosition.y)}}; } SBoxExtents maxExtents = {{BORDERSIZE + 2, BORDERSIZE + 2}, {BORDERSIZE + 2, BORDERSIZE + 2}}; @@ -183,8 +188,8 @@ CBox CWindow::getFullWindowBoundingBox() { auto maxExtents = getFullWindowExtents(); - CBox finalBox = {m_vRealPosition.value().x - maxExtents.topLeft.x, m_vRealPosition.value().y - maxExtents.topLeft.y, - m_vRealSize.value().x + maxExtents.topLeft.x + maxExtents.bottomRight.x, m_vRealSize.value().y + maxExtents.topLeft.y + maxExtents.bottomRight.y}; + CBox finalBox = {m_vRealPosition->value().x - maxExtents.topLeft.x, m_vRealPosition->value().y - maxExtents.topLeft.y, + m_vRealSize->value().x + maxExtents.topLeft.x + maxExtents.bottomRight.x, m_vRealSize->value().y + maxExtents.topLeft.y + maxExtents.bottomRight.y}; return finalBox; } @@ -238,7 +243,7 @@ CBox CWindow::getWindowBoxUnified(uint64_t properties) { if (properties & FULL_EXTENTS) EXTENTS.addExtents(g_pDecorationPositioner->getWindowDecorationExtents(m_pSelf.lock(), false)); - CBox box = {m_vRealPosition.value().x, m_vRealPosition.value().y, m_vRealSize.value().x, m_vRealSize.value().y}; + CBox box = {m_vRealPosition->value().x, m_vRealPosition->value().y, m_vRealSize->value().x, m_vRealSize->value().y}; box.addExtents(EXTENTS); return box; @@ -409,9 +414,9 @@ void CWindow::moveToWorkspace(PHLWORKSPACE pWorkspace) { const auto OLDWORKSPACE = m_pWorkspace; m_iMonitorMovedFrom = OLDWORKSPACE ? OLDWORKSPACE->monitorID() : -1; - m_fMovingToWorkspaceAlpha.setValueAndWarp(1.F); - m_fMovingToWorkspaceAlpha = 0.F; - m_fMovingToWorkspaceAlpha.setCallbackOnEnd([this](void* thisptr) { m_iMonitorMovedFrom = -1; }); + m_fMovingToWorkspaceAlpha->setCallbackOnEnd([this](auto) { m_iMonitorMovedFrom = -1; }); + m_fMovingToWorkspaceAlpha->setValueAndWarp(1.F); + *m_fMovingToWorkspaceAlpha = 0.F; m_pWorkspace = pWorkspace; @@ -439,7 +444,7 @@ void CWindow::moveToWorkspace(PHLWORKSPACE pWorkspace) { } // update xwayland coords - g_pXWaylandManager->setWindowSize(m_pSelf.lock(), m_vRealSize.value()); + g_pXWaylandManager->setWindowSize(m_pSelf.lock(), m_vRealSize->value()); if (OLDWORKSPACE && g_pCompositor->isWorkspaceSpecial(OLDWORKSPACE->m_iID) && OLDWORKSPACE->getWindows() == 0 && *PCLOSEONLASTSPECIAL) { if (const auto PMONITOR = OLDWORKSPACE->m_pMonitor.lock(); PMONITOR) @@ -475,10 +480,6 @@ PHLWINDOW CWindow::x11TransientFor() { return nullptr; } -static void unregisterVar(void* ptr) { - ((CBaseAnimatedVariable*)ptr)->unregister(); -} - void CWindow::onUnmap() { static auto PCLOSEONLASTSPECIAL = CConfigValue("misc:close_special_on_empty"); static auto PINITIALWSTRACKING = CConfigValue("misc:initial_workspace_tracking"); @@ -497,19 +498,6 @@ void CWindow::onUnmap() { m_iLastWorkspace = m_pWorkspace->m_iID; - m_vRealPosition.setCallbackOnEnd(unregisterVar); - m_vRealSize.setCallbackOnEnd(unregisterVar); - m_fBorderFadeAnimationProgress.setCallbackOnEnd(unregisterVar); - m_fBorderAngleAnimationProgress.setCallbackOnEnd(unregisterVar); - m_fActiveInactiveAlpha.setCallbackOnEnd(unregisterVar); - m_fAlpha.setCallbackOnEnd(unregisterVar); - m_cRealShadowColor.setCallbackOnEnd(unregisterVar); - m_fDimPercent.setCallbackOnEnd(unregisterVar); - m_fMovingToWorkspaceAlpha.setCallbackOnEnd(unregisterVar); - m_fMovingFromWorkspaceAlpha.setCallbackOnEnd(unregisterVar); - - m_vRealSize.setCallbackOnBegin(nullptr); - std::erase_if(g_pCompositor->m_vWindowFocusHistory, [&](const auto& other) { return other.expired() || other.lock().get() == this; }); if (*PCLOSEONLASTSPECIAL && m_pWorkspace && m_pWorkspace->getWindows() == 0 && onSpecialWorkspace()) { @@ -541,34 +529,24 @@ void CWindow::onUnmap() { void CWindow::onMap() { // JIC, reset the callbacks. If any are set, we'll make sure they are cleared so we don't accidentally unset them. (In case a window got remapped) - m_vRealPosition.resetAllCallbacks(); - m_vRealSize.resetAllCallbacks(); - m_fBorderFadeAnimationProgress.resetAllCallbacks(); - m_fBorderAngleAnimationProgress.resetAllCallbacks(); - m_fActiveInactiveAlpha.resetAllCallbacks(); - m_fAlpha.resetAllCallbacks(); - m_cRealShadowColor.resetAllCallbacks(); - m_fDimPercent.resetAllCallbacks(); - m_fMovingToWorkspaceAlpha.resetAllCallbacks(); - m_fMovingFromWorkspaceAlpha.resetAllCallbacks(); + m_vRealPosition->resetAllCallbacks(); + m_vRealSize->resetAllCallbacks(); + m_fBorderFadeAnimationProgress->resetAllCallbacks(); + m_fBorderAngleAnimationProgress->resetAllCallbacks(); + m_fActiveInactiveAlpha->resetAllCallbacks(); + m_fAlpha->resetAllCallbacks(); + m_cRealShadowColor->resetAllCallbacks(); + m_fDimPercent->resetAllCallbacks(); + m_fMovingToWorkspaceAlpha->resetAllCallbacks(); + m_fMovingFromWorkspaceAlpha->resetAllCallbacks(); - m_vRealPosition.registerVar(); - m_vRealSize.registerVar(); - m_fBorderFadeAnimationProgress.registerVar(); - m_fBorderAngleAnimationProgress.registerVar(); - m_fActiveInactiveAlpha.registerVar(); - m_fAlpha.registerVar(); - m_cRealShadowColor.registerVar(); - m_fDimPercent.registerVar(); - m_fMovingToWorkspaceAlpha.registerVar(); - m_fMovingFromWorkspaceAlpha.registerVar(); + m_fMovingFromWorkspaceAlpha->setValueAndWarp(1.F); + m_fBorderAngleAnimationProgress->setCallbackOnEnd([&](WP p) { onBorderAngleAnimEnd(p); }, false); - m_fBorderAngleAnimationProgress.setCallbackOnEnd([&](void* ptr) { onBorderAngleAnimEnd(ptr); }, false); + m_fBorderAngleAnimationProgress->setValueAndWarp(0.f); + *m_fBorderAngleAnimationProgress = 1.f; - m_fBorderAngleAnimationProgress.setValueAndWarp(0.f); - m_fBorderAngleAnimationProgress = 1.f; - - m_fMovingFromWorkspaceAlpha.setValueAndWarp(1.F); + m_fMovingFromWorkspaceAlpha->setValueAndWarp(1.F); g_pCompositor->m_vWindowFocusHistory.push_back(m_pSelf); @@ -584,20 +562,22 @@ void CWindow::onMap() { m_pPopupHead = std::make_unique(m_pSelf.lock()); } -void CWindow::onBorderAngleAnimEnd(void* ptr) { - const auto PANIMVAR = (CAnimatedVariable*)ptr; - - const std::string STYLE = PANIMVAR->getConfig()->pValues->internalStyle; - - if (STYLE != "loop" || !PANIMVAR->getConfig()->pValues->internalEnabled) +void CWindow::onBorderAngleAnimEnd(WP pav) { + const auto PAV = pav.lock(); + if (!PAV) return; + if (PAV->getStyle() != "loop" || !PAV->enabled()) + return; + + const auto PANIMVAR = dynamic_cast*>(PAV.get()); + PANIMVAR->setCallbackOnEnd(nullptr); // we remove the callback here because otherwise setvalueandwarp will recurse this PANIMVAR->setValueAndWarp(0); *PANIMVAR = 1.f; - PANIMVAR->setCallbackOnEnd([&](void* ptr) { onBorderAngleAnimEnd(ptr); }, false); + PANIMVAR->setCallbackOnEnd([&](WP pav) { onBorderAngleAnimEnd(pav); }, false); } void CWindow::setHidden(bool hidden) { @@ -830,10 +810,10 @@ bool CWindow::isInCurvedCorner(double x, double y) { return false; // (x0, y0), (x0, y1), ... are the center point of rounding at each corner - double x0 = m_vRealPosition.value().x + ROUNDING; - double y0 = m_vRealPosition.value().y + ROUNDING; - double x1 = m_vRealPosition.value().x + m_vRealSize.value().x - ROUNDING; - double y1 = m_vRealPosition.value().y + m_vRealSize.value().y - ROUNDING; + double x0 = m_vRealPosition->value().x + ROUNDING; + double y0 = m_vRealPosition->value().y + ROUNDING; + double x1 = m_vRealPosition->value().x + m_vRealSize->value().x - ROUNDING; + double y1 = m_vRealPosition->value().y + m_vRealSize->value().y - ROUNDING; if (x < x0 && y < y0) { return std::pow(x0 - x, ROUNDINGPOWER) + std::pow(y0 - y, ROUNDINGPOWER) > std::pow((double)ROUNDING, ROUNDINGPOWER); @@ -1032,8 +1012,8 @@ void CWindow::setGroupCurrent(PHLWINDOW pWindow) { if (FULLSCREEN) g_pCompositor->setWindowFullscreenInternal(PCURRENT, FSMODE_NONE); - const auto PWINDOWSIZE = PCURRENT->m_vRealSize.goal(); - const auto PWINDOWPOS = PCURRENT->m_vRealPosition.goal(); + const auto PWINDOWSIZE = PCURRENT->m_vRealSize->goal(); + const auto PWINDOWPOS = PCURRENT->m_vRealPosition->goal(); PCURRENT->setHidden(true); pWindow->setHidden(false); // can remove m_pLastWindow @@ -1041,8 +1021,8 @@ void CWindow::setGroupCurrent(PHLWINDOW pWindow) { g_pLayoutManager->getCurrentLayout()->replaceWindowDataWith(PCURRENT, pWindow); if (PCURRENT->m_bIsFloating) { - pWindow->m_vRealPosition.setValueAndWarp(PWINDOWPOS); - pWindow->m_vRealSize.setValueAndWarp(PWINDOWSIZE); + pWindow->m_vRealPosition->setValueAndWarp(PWINDOWPOS); + pWindow->m_vRealSize->setValueAndWarp(PWINDOWSIZE); } g_pCompositor->updateAllWindowsAnimatedDecorationValues(); @@ -1124,22 +1104,22 @@ void CWindow::updateGroupOutputs() { curr->m_pMonitor = m_pMonitor; curr->moveToWorkspace(WS); - curr->m_vRealPosition = m_vRealPosition.goal(); - curr->m_vRealSize = m_vRealSize.goal(); + *curr->m_vRealPosition = m_vRealPosition->goal(); + *curr->m_vRealSize = m_vRealSize->goal(); curr = curr->m_sGroupData.pNextWindow.lock(); } } Vector2D CWindow::middle() { - return m_vRealPosition.goal() + m_vRealSize.goal() / 2.f; + return m_vRealPosition->goal() + m_vRealSize->goal() / 2.f; } bool CWindow::opaque() { - if (m_fAlpha.value() != 1.f || m_fActiveInactiveAlpha.value() != 1.f) + if (m_fAlpha->value() != 1.f || m_fActiveInactiveAlpha->value() != 1.f) return false; - if (m_vRealSize.goal().floor() != m_vReportedSize) + if (m_vRealSize->goal().floor() != m_vReportedSize) return false; const auto PWORKSPACE = m_pWorkspace; @@ -1147,7 +1127,7 @@ bool CWindow::opaque() { if (m_pWLSurface->small() && !m_pWLSurface->m_bFillIgnoreSmall) return false; - if (PWORKSPACE->m_fAlpha.value() != 1.f) + if (PWORKSPACE->m_fAlpha->value() != 1.f) return false; if (m_bIsX11 && m_pXWaylandSurface && m_pXWaylandSurface->surface && m_pXWaylandSurface->surface->current.texture) @@ -1237,15 +1217,13 @@ void CWindow::setSuspended(bool suspend) { } bool CWindow::visibleOnMonitor(PHLMONITOR pMonitor) { - CBox wbox = {m_vRealPosition.value(), m_vRealSize.value()}; + CBox wbox = {m_vRealPosition->value(), m_vRealSize->value()}; return !wbox.intersection({pMonitor->vecPosition, pMonitor->vecSize}).empty(); } void CWindow::setAnimationsToMove() { - auto* const PANIMCFG = g_pConfigManager->getAnimationPropertyConfig("windowsMove"); - m_vRealPosition.setConfig(PANIMCFG); - m_vRealSize.setConfig(PANIMCFG); + m_vRealPosition->setConfig(g_pConfigManager->getAnimationPropertyConfig("windowsMove")); m_bAnimatingIn = false; } @@ -1266,16 +1244,16 @@ void CWindow::onWorkspaceAnimUpdate() { return; const auto WINBB = getFullWindowBoundingBox(); - if (PWORKSPACE->m_vRenderOffset.value().x != 0) { - const auto PROGRESS = PWORKSPACE->m_vRenderOffset.value().x / PWSMON->vecSize.x; + if (PWORKSPACE->m_vRenderOffset->value().x != 0) { + const auto PROGRESS = PWORKSPACE->m_vRenderOffset->value().x / PWSMON->vecSize.x; if (WINBB.x < PWSMON->vecPosition.x) offset.x += (PWSMON->vecPosition.x - WINBB.x) * PROGRESS; if (WINBB.x + WINBB.width > PWSMON->vecPosition.x + PWSMON->vecSize.x) offset.x += (WINBB.x + WINBB.width - PWSMON->vecPosition.x - PWSMON->vecSize.x) * PROGRESS; - } else if (PWORKSPACE->m_vRenderOffset.value().y != 0) { - const auto PROGRESS = PWORKSPACE->m_vRenderOffset.value().y / PWSMON->vecSize.y; + } else if (PWORKSPACE->m_vRenderOffset->value().y != 0) { + const auto PROGRESS = PWORKSPACE->m_vRenderOffset->value().y / PWSMON->vecSize.y; if (WINBB.y < PWSMON->vecPosition.y) offset.y += (PWSMON->vecPosition.y - WINBB.y) * PROGRESS; @@ -1306,12 +1284,12 @@ int CWindow::surfacesCount() { } void CWindow::clampWindowSize(const std::optional minSize, const std::optional maxSize) { - const Vector2D REALSIZE = m_vRealSize.goal(); + const Vector2D REALSIZE = m_vRealSize->goal(); const Vector2D NEWSIZE = REALSIZE.clamp(minSize.value_or(Vector2D{MIN_WINDOW_SIZE, MIN_WINDOW_SIZE}), maxSize.value_or(Vector2D{INFINITY, INFINITY})); const Vector2D DELTA = REALSIZE - NEWSIZE; - m_vRealPosition = m_vRealPosition.goal() + DELTA / 2.0; - m_vRealSize = NEWSIZE; + *m_vRealPosition = m_vRealPosition->goal() + DELTA / 2.0; + *m_vRealSize = NEWSIZE; g_pXWaylandManager->setWindowSize(m_pSelf.lock(), NEWSIZE); } @@ -1525,7 +1503,7 @@ void CWindow::onX11Configure(CBox box) { g_pHyprRenderer->damageWindow(m_pSelf.lock()); if (!m_bIsFloating || isFullscreen() || g_pInputManager->currentlyDraggedWindow == m_pSelf) { - g_pXWaylandManager->setWindowSize(m_pSelf.lock(), m_vRealSize.goal(), true); + g_pXWaylandManager->setWindowSize(m_pSelf.lock(), m_vRealSize->goal(), true); g_pInputManager->refocus(); g_pHyprRenderer->damageWindow(m_pSelf.lock()); return; @@ -1538,19 +1516,19 @@ void CWindow::onX11Configure(CBox box) { const auto LOGICALPOS = g_pXWaylandManager->xwaylandToWaylandCoords(box.pos()); - m_vRealPosition.setValueAndWarp(LOGICALPOS); - m_vRealSize.setValueAndWarp(box.size()); + m_vRealPosition->setValueAndWarp(LOGICALPOS); + m_vRealSize->setValueAndWarp(box.size()); static auto PXWLFORCESCALEZERO = CConfigValue("xwayland:force_zero_scaling"); if (*PXWLFORCESCALEZERO) { if (const auto PMONITOR = m_pMonitor.lock(); PMONITOR) { - m_vRealSize.setValueAndWarp(m_vRealSize.goal() / PMONITOR->scale); + m_vRealSize->setValueAndWarp(m_vRealSize->goal() / PMONITOR->scale); m_fX11SurfaceScaledBy = PMONITOR->scale; } } - m_vPosition = m_vRealPosition.value(); - m_vSize = m_vRealSize.value(); + m_vPosition = m_vRealPosition->value(); + m_vSize = m_vRealSize->value(); m_pXWaylandSurface->configure(box); @@ -1562,7 +1540,7 @@ void CWindow::onX11Configure(CBox box) { if (!m_pWorkspace || !m_pWorkspace->isVisible()) return; // further things are only for visible windows - m_pWorkspace = g_pCompositor->getMonitorFromVector(m_vRealPosition.value() + m_vRealSize.value() / 2.f)->activeWorkspace; + m_pWorkspace = g_pCompositor->getMonitorFromVector(m_vRealPosition->value() + m_vRealSize->value() / 2.f)->activeWorkspace; g_pCompositor->changeWindowZOrder(m_pSelf.lock(), true); diff --git a/src/desktop/Window.hpp b/src/desktop/Window.hpp index 3ceaf594..37189a00 100644 --- a/src/desktop/Window.hpp +++ b/src/desktop/Window.hpp @@ -233,8 +233,8 @@ class CWindow { Vector2D m_vSize = Vector2D(0, 0); // this is the real position and size used to draw the thing - CAnimatedVariable m_vRealPosition; - CAnimatedVariable m_vRealSize; + PHLANIMVAR m_vRealPosition; + PHLANIMVAR m_vRealSize; // for not spamming the protocols Vector2D m_vReportedPosition; @@ -298,19 +298,19 @@ class CWindow { std::unique_ptr m_pPopupHead; // Animated border - CGradientValueData m_cRealBorderColor = {0}; - CGradientValueData m_cRealBorderColorPrevious = {0}; - CAnimatedVariable m_fBorderFadeAnimationProgress; - CAnimatedVariable m_fBorderAngleAnimationProgress; + CGradientValueData m_cRealBorderColor = {0}; + CGradientValueData m_cRealBorderColorPrevious = {0}; + PHLANIMVAR m_fBorderFadeAnimationProgress; + PHLANIMVAR m_fBorderAngleAnimationProgress; // Fade in-out - CAnimatedVariable m_fAlpha; - bool m_bFadingOut = false; - bool m_bReadyToDelete = false; - Vector2D m_vOriginalClosedPos; // these will be used for calculations later on in - Vector2D m_vOriginalClosedSize; // drawing the closing animations - SBoxExtents m_eOriginalClosedExtents; - bool m_bAnimatingIn = false; + PHLANIMVAR m_fAlpha; + bool m_bFadingOut = false; + bool m_bReadyToDelete = false; + Vector2D m_vOriginalClosedPos; // these will be used for calculations later on in + Vector2D m_vOriginalClosedSize; // drawing the closing animations + SBoxExtents m_eOriginalClosedExtents; + bool m_bAnimatingIn = false; // For pinned (sticky) windows bool m_bPinned = false; @@ -336,18 +336,18 @@ class CWindow { std::vector> m_vTransformers; // for alpha - CAnimatedVariable m_fActiveInactiveAlpha; - CAnimatedVariable m_fMovingFromWorkspaceAlpha; + PHLANIMVAR m_fActiveInactiveAlpha; + PHLANIMVAR m_fMovingFromWorkspaceAlpha; // animated shadow color - CAnimatedVariable m_cRealShadowColor; + PHLANIMVAR m_cRealShadowColor; // animated tint - CAnimatedVariable m_fDimPercent; + PHLANIMVAR m_fDimPercent; // animate moving to an invisible workspace - int m_iMonitorMovedFrom = -1; // -1 means not moving - CAnimatedVariable m_fMovingToWorkspaceAlpha; + int m_iMonitorMovedFrom = -1; // -1 means not moving + PHLANIMVAR m_fMovingToWorkspaceAlpha; // swallowing PHLWINDOWREF m_pSwallowed; @@ -432,7 +432,7 @@ class CWindow { float getScrollTouchpad(); void updateWindowData(); void updateWindowData(const struct SWorkspaceRule&); - void onBorderAngleAnimEnd(void* ptr); + void onBorderAngleAnimEnd(WP pav); bool isInCurvedCorner(double x, double y); bool hasPopupAt(const Vector2D& pos); int popupsCount(); @@ -467,7 +467,7 @@ class CWindow { Vector2D requestedMaxSize(); CBox getWindowMainSurfaceBox() const { - return {m_vRealPosition.value().x, m_vRealPosition.value().y, m_vRealSize.value().x, m_vRealSize.value().y}; + return {m_vRealPosition->value().x, m_vRealPosition->value().y, m_vRealSize->value().x, m_vRealSize->value().y}; } // listeners diff --git a/src/desktop/Workspace.cpp b/src/desktop/Workspace.cpp index 0930ef00..cab19254 100644 --- a/src/desktop/Workspace.cpp +++ b/src/desktop/Workspace.cpp @@ -1,7 +1,10 @@ #include "Workspace.hpp" #include "../Compositor.hpp" #include "../config/ConfigValue.hpp" +#include "config/ConfigManager.hpp" +#include "managers/AnimationManager.hpp" +#include #include using namespace Hyprutils::String; @@ -19,16 +22,10 @@ CWorkspace::CWorkspace(WORKSPACEID id, PHLMONITOR monitor, std::string name, boo void CWorkspace::init(PHLWORKSPACE self) { m_pSelf = self; - m_vRenderOffset.create(m_bIsSpecialWorkspace ? g_pConfigManager->getAnimationPropertyConfig("specialWorkspaceIn") : - g_pConfigManager->getAnimationPropertyConfig("workspacesIn"), - self, AVARDAMAGE_ENTIRE); - m_fAlpha.create(AVARTYPE_FLOAT, - m_bIsSpecialWorkspace ? g_pConfigManager->getAnimationPropertyConfig("specialWorkspaceIn") : g_pConfigManager->getAnimationPropertyConfig("workspacesIn"), self, - AVARDAMAGE_ENTIRE); - m_fAlpha.setValueAndWarp(1.f); - - m_vRenderOffset.registerVar(); - m_fAlpha.registerVar(); + g_pAnimationManager->createAnimation(Vector2D(0, 0), m_vRenderOffset, + g_pConfigManager->getAnimationPropertyConfig(m_bIsSpecialWorkspace ? "specialWorkspaceIn" : "workspacesIn"), self, AVARDAMAGE_ENTIRE); + g_pAnimationManager->createAnimation(1.f, m_fAlpha, g_pConfigManager->getAnimationPropertyConfig(m_bIsSpecialWorkspace ? "specialWorkspaceIn" : "workspacesIn"), self, + AVARDAMAGE_ENTIRE); const auto RULEFORTHIS = g_pConfigManager->getWorkspaceRuleFor(self); if (RULEFORTHIS.defaultName.has_value()) @@ -63,8 +60,6 @@ SWorkspaceIDName CWorkspace::getPrevWorkspaceIDName(bool perMonitor) const { } CWorkspace::~CWorkspace() { - m_vRenderOffset.unregister(); - Debug::log(LOG, "Destroying workspace ID {}", m_iID); // check if g_pHookSystem and g_pEventManager exist, they might be destroyed as in when the compositor is closing. @@ -82,15 +77,15 @@ void CWorkspace::startAnim(bool in, bool left, bool instant) { if (!instant) { const std::string ANIMNAME = std::format("{}{}", m_bIsSpecialWorkspace ? "specialWorkspace" : "workspaces", in ? "In" : "Out"); - m_fAlpha.m_pConfig = g_pConfigManager->getAnimationPropertyConfig(ANIMNAME); - m_vRenderOffset.m_pConfig = g_pConfigManager->getAnimationPropertyConfig(ANIMNAME); + m_fAlpha->setConfig(g_pConfigManager->getAnimationPropertyConfig(ANIMNAME)); + m_vRenderOffset->setConfig(g_pConfigManager->getAnimationPropertyConfig(ANIMNAME)); } - const auto ANIMSTYLE = m_fAlpha.m_pConfig->pValues->internalStyle; + const auto ANIMSTYLE = m_fAlpha->getStyle(); static auto PWORKSPACEGAP = CConfigValue("general:gaps_workspaces"); // set floating windows offset callbacks - m_vRenderOffset.setUpdateCallback([&](void*) { + m_vRenderOffset->setUpdateCallback([&](auto) { for (auto const& w : g_pCompositor->m_vWindows) { if (!validMapped(w) || w->workspaceID() != m_iID) continue; @@ -110,84 +105,84 @@ void CWorkspace::startAnim(bool in, bool left, bool instant) { } catch (std::exception& e) { Debug::log(ERR, "Error in startAnim: invalid percentage"); } } - m_fAlpha.setValueAndWarp(1.f); - m_vRenderOffset.setValueAndWarp(Vector2D(0, 0)); + m_fAlpha->setValueAndWarp(1.f); + m_vRenderOffset->setValueAndWarp(Vector2D(0, 0)); if (ANIMSTYLE.starts_with("slidefadevert")) { if (in) { - m_fAlpha.setValueAndWarp(0.f); - m_vRenderOffset.setValueAndWarp(Vector2D(0.0, (left ? PMONITOR->vecSize.y : -PMONITOR->vecSize.y) * (movePerc / 100.f))); - m_fAlpha = 1.f; - m_vRenderOffset = Vector2D(0, 0); + m_fAlpha->setValueAndWarp(0.f); + m_vRenderOffset->setValueAndWarp(Vector2D(0.0, (left ? PMONITOR->vecSize.y : -PMONITOR->vecSize.y) * (movePerc / 100.f))); + *m_fAlpha = 1.f; + *m_vRenderOffset = Vector2D(0, 0); } else { - m_fAlpha.setValueAndWarp(1.f); - m_fAlpha = 0.f; - m_vRenderOffset = Vector2D(0.0, (left ? -PMONITOR->vecSize.y : PMONITOR->vecSize.y) * (movePerc / 100.f)); + m_fAlpha->setValueAndWarp(1.f); + *m_fAlpha = 0.f; + *m_vRenderOffset = Vector2D(0.0, (left ? -PMONITOR->vecSize.y : PMONITOR->vecSize.y) * (movePerc / 100.f)); } } else { if (in) { - m_fAlpha.setValueAndWarp(0.f); - m_vRenderOffset.setValueAndWarp(Vector2D((left ? PMONITOR->vecSize.x : -PMONITOR->vecSize.x) * (movePerc / 100.f), 0.0)); - m_fAlpha = 1.f; - m_vRenderOffset = Vector2D(0, 0); + m_fAlpha->setValueAndWarp(0.f); + m_vRenderOffset->setValueAndWarp(Vector2D((left ? PMONITOR->vecSize.x : -PMONITOR->vecSize.x) * (movePerc / 100.f), 0.0)); + *m_fAlpha = 1.f; + *m_vRenderOffset = Vector2D(0, 0); } else { - m_fAlpha.setValueAndWarp(1.f); - m_fAlpha = 0.f; - m_vRenderOffset = Vector2D((left ? -PMONITOR->vecSize.x : PMONITOR->vecSize.x) * (movePerc / 100.f), 0.0); + m_fAlpha->setValueAndWarp(1.f); + *m_fAlpha = 0.f; + *m_vRenderOffset = Vector2D((left ? -PMONITOR->vecSize.x : PMONITOR->vecSize.x) * (movePerc / 100.f), 0.0); } } } else if (ANIMSTYLE == "fade") { - m_vRenderOffset.setValueAndWarp(Vector2D(0, 0)); // fix a bug, if switching from slide -> fade. + m_vRenderOffset->setValueAndWarp(Vector2D(0, 0)); // fix a bug, if switching from slide -> fade. if (in) { - m_fAlpha.setValueAndWarp(0.f); - m_fAlpha = 1.f; + m_fAlpha->setValueAndWarp(0.f); + *m_fAlpha = 1.f; } else { - m_fAlpha.setValueAndWarp(1.f); - m_fAlpha = 0.f; + m_fAlpha->setValueAndWarp(1.f); + *m_fAlpha = 0.f; } } else if (ANIMSTYLE == "slidevert") { // fallback is slide const auto PMONITOR = m_pMonitor.lock(); const auto YDISTANCE = PMONITOR->vecSize.y + *PWORKSPACEGAP; - m_fAlpha.setValueAndWarp(1.f); // fix a bug, if switching from fade -> slide. + m_fAlpha->setValueAndWarp(1.f); // fix a bug, if switching from fade -> slide. if (in) { - m_vRenderOffset.setValueAndWarp(Vector2D(0.0, left ? YDISTANCE : -YDISTANCE)); - m_vRenderOffset = Vector2D(0, 0); + m_vRenderOffset->setValueAndWarp(Vector2D(0.0, left ? YDISTANCE : -YDISTANCE)); + *m_vRenderOffset = Vector2D(0, 0); } else { - m_vRenderOffset = Vector2D(0.0, left ? -YDISTANCE : YDISTANCE); + *m_vRenderOffset = Vector2D(0.0, left ? -YDISTANCE : YDISTANCE); } } else { // fallback is slide const auto PMONITOR = m_pMonitor.lock(); const auto XDISTANCE = PMONITOR->vecSize.x + *PWORKSPACEGAP; - m_fAlpha.setValueAndWarp(1.f); // fix a bug, if switching from fade -> slide. + m_fAlpha->setValueAndWarp(1.f); // fix a bug, if switching from fade -> slide. if (in) { - m_vRenderOffset.setValueAndWarp(Vector2D(left ? XDISTANCE : -XDISTANCE, 0.0)); - m_vRenderOffset = Vector2D(0, 0); + m_vRenderOffset->setValueAndWarp(Vector2D(left ? XDISTANCE : -XDISTANCE, 0.0)); + *m_vRenderOffset = Vector2D(0, 0); } else { - m_vRenderOffset = Vector2D(left ? -XDISTANCE : XDISTANCE, 0.0); + *m_vRenderOffset = Vector2D(left ? -XDISTANCE : XDISTANCE, 0.0); } } if (m_bIsSpecialWorkspace) { // required for open/close animations if (in) { - m_fAlpha.setValueAndWarp(0.f); - m_fAlpha = 1.f; + m_fAlpha->setValueAndWarp(0.f); + *m_fAlpha = 1.f; } else { - m_fAlpha.setValueAndWarp(1.f); - m_fAlpha = 0.f; + m_fAlpha->setValueAndWarp(1.f); + *m_fAlpha = 0.f; } } if (instant) { - m_vRenderOffset.warp(); - m_fAlpha.warp(); + m_vRenderOffset->warp(); + m_fAlpha->warp(); } } @@ -633,7 +628,7 @@ void CWorkspace::forceReportSizesToWindows() { if (w->m_pWorkspace != m_pSelf || !w->m_bIsMapped || w->isHidden()) continue; - g_pXWaylandManager->setWindowSize(w, w->m_vRealSize.value(), true); + g_pXWaylandManager->setWindowSize(w, w->m_vRealSize->value(), true); } } diff --git a/src/desktop/Workspace.hpp b/src/desktop/Workspace.hpp index 606485a2..f86dd656 100644 --- a/src/desktop/Workspace.hpp +++ b/src/desktop/Workspace.hpp @@ -37,9 +37,9 @@ class CWorkspace { wl_array m_wlrCoordinateArr; // for animations - CAnimatedVariable m_vRenderOffset; - CAnimatedVariable m_fAlpha; - bool m_bForceRendering = false; + PHLANIMVAR m_vRenderOffset; + PHLANIMVAR m_fAlpha; + bool m_bForceRendering = false; // allows damage to propagate. bool m_bVisible = false; diff --git a/src/events/Windows.cpp b/src/events/Windows.cpp index a20cbcad..8082cdc9 100644 --- a/src/events/Windows.cpp +++ b/src/events/Windows.cpp @@ -12,10 +12,12 @@ #include "../protocols/core/Compositor.hpp" #include "../protocols/ToplevelExport.hpp" #include "../xwayland/XSurface.hpp" +#include "managers/AnimationManager.hpp" #include "managers/PointerManager.hpp" #include using namespace Hyprutils::String; +using namespace Hyprutils::Animation; // ------------------------------------------------------------ // // __ _______ _ _ _____ ______ _______ // @@ -27,15 +29,17 @@ using namespace Hyprutils::String; // // // ------------------------------------------------------------ // -static void setAnimToMove(void* data) { - auto* const PANIMCFG = g_pConfigManager->getAnimationPropertyConfig("windowsMove"); +static void setVector2DAnimToMove(WP pav) { + const auto PAV = pav.lock(); + if (!PAV) + return; - CBaseAnimatedVariable* animvar = (CBaseAnimatedVariable*)data; + CAnimatedVariable* animvar = dynamic_cast*>(PAV.get()); + animvar->setConfig(g_pConfigManager->getAnimationPropertyConfig("windowsMove")); - animvar->setConfig(PANIMCFG); - - if (animvar->getWindow() && !animvar->getWindow()->m_vRealPosition.isBeingAnimated() && !animvar->getWindow()->m_vRealSize.isBeingAnimated()) - animvar->getWindow()->m_bAnimatingIn = false; + const auto PHLWINDOW = animvar->m_Context.pWindow.lock(); + if (PHLWINDOW && PHLWINDOW->m_vRealPosition->isBeingAnimated() && PHLWINDOW->m_vRealSize->isBeingAnimated()) + PHLWINDOW->m_bAnimatingIn = false; } void Events::listener_mapWindow(void* owner, void* data) { @@ -378,10 +382,10 @@ void Events::listener_mapWindow(void* owner, void* data) { const auto MAXSIZE = PWINDOW->requestedMaxSize(); const float SIZEX = SIZEXSTR == "max" ? std::clamp(MAXSIZE.x, MIN_WINDOW_SIZE, PMONITOR->vecSize.x) : - stringToFloatClamp(SIZEXSTR, PWINDOW->m_vRealSize.goal().x, PMONITOR->vecSize.x); + stringToFloatClamp(SIZEXSTR, PWINDOW->m_vRealSize->goal().x, PMONITOR->vecSize.x); const float SIZEY = SIZEYSTR == "max" ? std::clamp(MAXSIZE.y, MIN_WINDOW_SIZE, PMONITOR->vecSize.y) : - stringToFloatClamp(SIZEYSTR, PWINDOW->m_vRealSize.goal().y, PMONITOR->vecSize.y); + stringToFloatClamp(SIZEYSTR, PWINDOW->m_vRealSize->goal().y, PMONITOR->vecSize.y); Debug::log(LOG, "Rule size, applying to {}", PWINDOW); @@ -418,7 +422,7 @@ void Events::listener_mapWindow(void* owner, void* data) { (!POSXRAW.contains('%') ? std::stoi(POSXRAW) : std::stof(POSXRAW.substr(0, POSXRAW.length() - 1)) * 0.01 * PMONITOR->vecSize.x); if (subtractWindow) - posX -= PWINDOW->m_vRealSize.goal().x; + posX -= PWINDOW->m_vRealSize->goal().x; if (CURSOR) Debug::log(ERR, "Cursor is not compatible with 100%-, ignoring cursor!"); @@ -430,7 +434,7 @@ void Events::listener_mapWindow(void* owner, void* data) { posX = g_pInputManager->getMouseCoordsInternal().x - PMONITOR->vecPosition.x; } else { posX = g_pInputManager->getMouseCoordsInternal().x - PMONITOR->vecPosition.x + - (!POSXSTR.contains('%') ? std::stoi(POSXSTR) : std::stof(POSXSTR.substr(0, POSXSTR.length() - 1)) * 0.01 * PWINDOW->m_vRealSize.goal().x); + (!POSXSTR.contains('%') ? std::stoi(POSXSTR) : std::stof(POSXSTR.substr(0, POSXSTR.length() - 1)) * 0.01 * PWINDOW->m_vRealSize->goal().x); } } @@ -441,7 +445,7 @@ void Events::listener_mapWindow(void* owner, void* data) { (!POSYRAW.contains('%') ? std::stoi(POSYRAW) : std::stof(POSYRAW.substr(0, POSYRAW.length() - 1)) * 0.01 * PMONITOR->vecSize.y); if (subtractWindow) - posY -= PWINDOW->m_vRealSize.goal().y; + posY -= PWINDOW->m_vRealSize->goal().y; if (CURSOR) Debug::log(ERR, "Cursor is not compatible with 100%-, ignoring cursor!"); @@ -453,7 +457,7 @@ void Events::listener_mapWindow(void* owner, void* data) { posY = g_pInputManager->getMouseCoordsInternal().y - PMONITOR->vecPosition.y; } else { posY = g_pInputManager->getMouseCoordsInternal().y - PMONITOR->vecPosition.y + - (!POSYSTR.contains('%') ? std::stoi(POSYSTR) : std::stof(POSYSTR.substr(0, POSYSTR.length() - 1)) * 0.01 * PWINDOW->m_vRealSize.goal().y); + (!POSYSTR.contains('%') ? std::stoi(POSYSTR) : std::stof(POSYSTR.substr(0, POSYSTR.length() - 1)) * 0.01 * PWINDOW->m_vRealSize->goal().y); } } @@ -461,15 +465,15 @@ void Events::listener_mapWindow(void* owner, void* data) { int borderSize = PWINDOW->getRealBorderSize(); posX = std::clamp(posX, (int)(PMONITOR->vecReservedTopLeft.x + borderSize), - (int)(PMONITOR->vecSize.x - PMONITOR->vecReservedBottomRight.x - PWINDOW->m_vRealSize.goal().x - borderSize)); + (int)(PMONITOR->vecSize.x - PMONITOR->vecReservedBottomRight.x - PWINDOW->m_vRealSize->goal().x - borderSize)); posY = std::clamp(posY, (int)(PMONITOR->vecReservedTopLeft.y + borderSize), - (int)(PMONITOR->vecSize.y - PMONITOR->vecReservedBottomRight.y - PWINDOW->m_vRealSize.goal().y - borderSize)); + (int)(PMONITOR->vecSize.y - PMONITOR->vecReservedBottomRight.y - PWINDOW->m_vRealSize->goal().y - borderSize)); } Debug::log(LOG, "Rule move, applying to {}", PWINDOW); - PWINDOW->m_vRealPosition = Vector2D(posX, posY) + PMONITOR->vecPosition; + *PWINDOW->m_vRealPosition = Vector2D(posX, posY) + PMONITOR->vecPosition; PWINDOW->setHidden(false); } catch (...) { Debug::log(LOG, "Rule move failed, rule: {} -> {}", r->szRule, r->szValue); } @@ -481,7 +485,7 @@ void Events::listener_mapWindow(void* owner, void* data) { if (ARGS[1] == "1") RESERVEDOFFSET = (PMONITOR->vecReservedTopLeft - PMONITOR->vecReservedBottomRight) / 2.f; - PWINDOW->m_vRealPosition = PMONITOR->middle() - PWINDOW->m_vRealSize.goal() / 2.f + RESERVEDOFFSET; + *PWINDOW->m_vRealPosition = PMONITOR->middle() - PWINDOW->m_vRealSize->goal() / 2.f + RESERVEDOFFSET; break; } @@ -491,7 +495,7 @@ void Events::listener_mapWindow(void* owner, void* data) { // set the pseudo size to the GOAL of our current size // because the windows are animated on RealSize - PWINDOW->m_vPseudoSize = PWINDOW->m_vRealSize.goal(); + PWINDOW->m_vPseudoSize = PWINDOW->m_vRealSize->goal(); g_pCompositor->changeWindowZOrder(PWINDOW, true); } else { @@ -524,7 +528,7 @@ void Events::listener_mapWindow(void* owner, void* data) { } if (!setPseudo) - PWINDOW->m_vPseudoSize = PWINDOW->m_vRealSize.goal() - Vector2D(10, 10); + PWINDOW->m_vPseudoSize = PWINDOW->m_vRealSize->goal() - Vector2D(10, 10); } const auto PFOCUSEDWINDOWPREV = g_pCompositor->m_pLastWindow.lock(); @@ -554,11 +558,11 @@ void Events::listener_mapWindow(void* owner, void* data) { (!PWINDOW->isX11OverrideRedirect() || (PWINDOW->m_bIsX11 && PWINDOW->m_pXWaylandSurface->wantsFocus())) && !workspaceSilent && (!PFORCEFOCUS || PFORCEFOCUS == PWINDOW) && !g_pInputManager->isConstrained()) { g_pCompositor->focusWindow(PWINDOW); - PWINDOW->m_fActiveInactiveAlpha.setValueAndWarp(*PACTIVEALPHA); - PWINDOW->m_fDimPercent.setValueAndWarp(PWINDOW->m_sWindowData.noDim.valueOrDefault() ? 0.f : *PDIMSTRENGTH); + PWINDOW->m_fActiveInactiveAlpha->setValueAndWarp(*PACTIVEALPHA); + PWINDOW->m_fDimPercent->setValueAndWarp(PWINDOW->m_sWindowData.noDim.valueOrDefault() ? 0.f : *PDIMSTRENGTH); } else { - PWINDOW->m_fActiveInactiveAlpha.setValueAndWarp(*PINACTIVEALPHA); - PWINDOW->m_fDimPercent.setValueAndWarp(0); + PWINDOW->m_fActiveInactiveAlpha->setValueAndWarp(*PINACTIVEALPHA); + PWINDOW->m_fDimPercent->setValueAndWarp(0); } if (requestedClientFSMode.has_value() && (PWINDOW->m_eSuppressedEvents & SUPPRESS_FULLSCREEN)) @@ -571,8 +575,8 @@ void Events::listener_mapWindow(void* owner, void* data) { if (PWINDOW->m_pWorkspace->m_bHasFullscreenWindow) g_pCompositor->setWindowFullscreenInternal(PWINDOW->m_pWorkspace->getFullscreenWindow(), FSMODE_NONE); - PWINDOW->m_vRealPosition.warp(); - PWINDOW->m_vRealSize.warp(); + PWINDOW->m_vRealPosition->warp(); + PWINDOW->m_vRealSize->warp(); if (requestedFSState.has_value()) { PWINDOW->m_sWindowData.syncFullscreen = CWindowOverridableVar(false, PRIORITY_WINDOW_RULE); g_pCompositor->setWindowFullscreenState(PWINDOW, requestedFSState.value()); @@ -607,7 +611,7 @@ void Events::listener_mapWindow(void* owner, void* data) { PWINDOW->m_bFirstMap = false; - Debug::log(LOG, "Map request dispatched, monitor {}, window pos: {:5j}, window size: {:5j}", PMONITOR->szName, PWINDOW->m_vRealPosition.goal(), PWINDOW->m_vRealSize.goal()); + Debug::log(LOG, "Map request dispatched, monitor {}, window pos: {:5j}, window size: {:5j}", PMONITOR->szName, PWINDOW->m_vRealPosition->goal(), PWINDOW->m_vRealSize->goal()); auto workspaceID = requestedWorkspace != "" ? requestedWorkspace : PWORKSPACE->m_szName; g_pEventManager->postEvent(SHyprIPCEvent{"openwindow", std::format("{:x},{},{},{}", PWINDOW, workspaceID, PWINDOW->m_szClass, PWINDOW->m_szTitle)}); @@ -620,17 +624,17 @@ void Events::listener_mapWindow(void* owner, void* data) { // do animations g_pAnimationManager->onWindowPostCreateClose(PWINDOW, false); - PWINDOW->m_fAlpha.setValueAndWarp(0.f); - PWINDOW->m_fAlpha = 1.f; + PWINDOW->m_fAlpha->setValueAndWarp(0.f); + *PWINDOW->m_fAlpha = 1.f; - PWINDOW->m_vRealPosition.setCallbackOnEnd(setAnimToMove); - PWINDOW->m_vRealSize.setCallbackOnEnd(setAnimToMove); + PWINDOW->m_vRealPosition->setCallbackOnEnd(setVector2DAnimToMove); + PWINDOW->m_vRealSize->setCallbackOnEnd(setVector2DAnimToMove); // recalc the values for this window g_pCompositor->updateWindowAnimatedDecorationValues(PWINDOW); // avoid this window being visible if (PWORKSPACE->m_bHasFullscreenWindow && !PWINDOW->isFullscreen() && !PWINDOW->m_bIsFloating) - PWINDOW->m_fAlpha.setValueAndWarp(0.f); + PWINDOW->m_fAlpha->setValueAndWarp(0.f); g_pCompositor->setPreferredScaleForSurface(PWINDOW->m_pWLSurface->resource(), PMONITOR->scale); g_pCompositor->setPreferredTransformForSurface(PWINDOW->m_pWLSurface->resource(), PMONITOR->transform); @@ -666,8 +670,8 @@ void Events::listener_unmapWindow(void* owner, void* data) { const auto PMONITOR = PWINDOW->m_pMonitor.lock(); if (PMONITOR) { - PWINDOW->m_vOriginalClosedPos = PWINDOW->m_vRealPosition.value() - PMONITOR->vecPosition; - PWINDOW->m_vOriginalClosedSize = PWINDOW->m_vRealSize.value(); + PWINDOW->m_vOriginalClosedPos = PWINDOW->m_vRealPosition->value() - PMONITOR->vecPosition; + PWINDOW->m_vOriginalClosedSize = PWINDOW->m_vRealSize->value(); PWINDOW->m_eOriginalClosedExtents = PWINDOW->getFullWindowExtents(); } @@ -757,12 +761,12 @@ void Events::listener_unmapWindow(void* owner, void* data) { g_pCompositor->addToFadingOutSafe(PWINDOW); - if (!PWINDOW->m_bX11DoesntWantBorders) // don't animate out if they weren't animated in. - PWINDOW->m_vRealPosition = PWINDOW->m_vRealPosition.value() + Vector2D(0.01f, 0.01f); // it has to be animated, otherwise onWindowPostCreateClose will ignore it + if (!PWINDOW->m_bX11DoesntWantBorders) // don't animate out if they weren't animated in. + *PWINDOW->m_vRealPosition = PWINDOW->m_vRealPosition->value() + Vector2D(0.01f, 0.01f); // it has to be animated, otherwise onWindowPostCreateClose will ignore it // anims g_pAnimationManager->onWindowPostCreateClose(PWINDOW, true); - PWINDOW->m_fAlpha = 0.f; + *PWINDOW->m_fAlpha = 0.f; // recheck idle inhibitors g_pInputManager->recheckIdleInhibitorStatus(); @@ -812,7 +816,7 @@ void Events::listener_commitWindow(void* owner, void* data) { g_pSeatManager->isPointerFrameSkipped = false; g_pSeatManager->isPointerFrameCommit = false; } else - g_pHyprRenderer->damageSurface(PWINDOW->m_pWLSurface->resource(), PWINDOW->m_vRealPosition.goal().x, PWINDOW->m_vRealPosition.goal().y, + g_pHyprRenderer->damageSurface(PWINDOW->m_pWLSurface->resource(), PWINDOW->m_vRealPosition->goal().x, PWINDOW->m_vRealPosition->goal().y, PWINDOW->m_bIsX11 ? 1.0 / PWINDOW->m_fX11SurfaceScaledBy : 1.0); if (g_pSeatManager->isPointerFrameSkipped) { @@ -903,8 +907,8 @@ void Events::listener_unmanagedSetGeometry(void* owner, void* data) { if (!PWINDOW->m_bIsMapped || !PWINDOW->m_pXWaylandSurface || !PWINDOW->m_pXWaylandSurface->overrideRedirect) return; - const auto POS = PWINDOW->m_vRealPosition.goal(); - const auto SIZ = PWINDOW->m_vRealSize.goal(); + const auto POS = PWINDOW->m_vRealPosition->goal(); + const auto SIZ = PWINDOW->m_vRealSize->goal(); if (PWINDOW->m_pXWaylandSurface->geometry.size() > Vector2D{1, 1}) PWINDOW->setHidden(false); @@ -912,7 +916,7 @@ void Events::listener_unmanagedSetGeometry(void* owner, void* data) { PWINDOW->setHidden(true); if (PWINDOW->isFullscreen() || !PWINDOW->m_bIsFloating) { - g_pXWaylandManager->setWindowSize(PWINDOW, PWINDOW->m_vRealSize.goal(), true); + g_pXWaylandManager->setWindowSize(PWINDOW, PWINDOW->m_vRealSize->goal(), true); g_pHyprRenderer->damageWindow(PWINDOW); return; } @@ -926,27 +930,27 @@ void Events::listener_unmanagedSetGeometry(void* owner, void* data) { Debug::log(LOG, "Unmanaged window {} requests geometry update to {:j} {:j}", PWINDOW, LOGICALPOS, PWINDOW->m_pXWaylandSurface->geometry.size()); g_pHyprRenderer->damageWindow(PWINDOW); - PWINDOW->m_vRealPosition.setValueAndWarp(Vector2D(LOGICALPOS.x, LOGICALPOS.y)); + PWINDOW->m_vRealPosition->setValueAndWarp(Vector2D(LOGICALPOS.x, LOGICALPOS.y)); if (abs(std::floor(SIZ.x) - PWINDOW->m_pXWaylandSurface->geometry.w) > 2 || abs(std::floor(SIZ.y) - PWINDOW->m_pXWaylandSurface->geometry.h) > 2) - PWINDOW->m_vRealSize.setValueAndWarp(PWINDOW->m_pXWaylandSurface->geometry.size()); + PWINDOW->m_vRealSize->setValueAndWarp(PWINDOW->m_pXWaylandSurface->geometry.size()); if (*PXWLFORCESCALEZERO) { if (const auto PMONITOR = PWINDOW->m_pMonitor.lock(); PMONITOR) { - PWINDOW->m_vRealSize.setValueAndWarp(PWINDOW->m_vRealSize.goal() / PMONITOR->scale); + PWINDOW->m_vRealSize->setValueAndWarp(PWINDOW->m_vRealSize->goal() / PMONITOR->scale); } } - PWINDOW->m_vPosition = PWINDOW->m_vRealPosition.goal(); - PWINDOW->m_vSize = PWINDOW->m_vRealSize.goal(); + PWINDOW->m_vPosition = PWINDOW->m_vRealPosition->goal(); + PWINDOW->m_vSize = PWINDOW->m_vRealSize->goal(); - PWINDOW->m_pWorkspace = g_pCompositor->getMonitorFromVector(PWINDOW->m_vRealPosition.value() + PWINDOW->m_vRealSize.value() / 2.f)->activeWorkspace; + PWINDOW->m_pWorkspace = g_pCompositor->getMonitorFromVector(PWINDOW->m_vRealPosition->value() + PWINDOW->m_vRealSize->value() / 2.f)->activeWorkspace; g_pCompositor->changeWindowZOrder(PWINDOW, true); PWINDOW->updateWindowDecos(); g_pHyprRenderer->damageWindow(PWINDOW); - PWINDOW->m_vReportedPosition = PWINDOW->m_vRealPosition.goal(); - PWINDOW->m_vPendingReportedSize = PWINDOW->m_vRealSize.goal(); + PWINDOW->m_vReportedPosition = PWINDOW->m_vRealPosition->goal(); + PWINDOW->m_vPendingReportedSize = PWINDOW->m_vRealSize->goal(); } } diff --git a/src/helpers/AnimatedVariable.cpp b/src/helpers/AnimatedVariable.cpp deleted file mode 100644 index ab5643a6..00000000 --- a/src/helpers/AnimatedVariable.cpp +++ /dev/null @@ -1,87 +0,0 @@ -#include "AnimatedVariable.hpp" -#include "../managers/AnimationManager.hpp" -#include "../config/ConfigManager.hpp" - -CBaseAnimatedVariable::CBaseAnimatedVariable(eAnimatedVarType type) : m_Type(type) { - ; // dummy var -} - -void CBaseAnimatedVariable::create(SAnimationPropertyConfig* pAnimConfig, PHLWINDOW pWindow, eAVarDamagePolicy policy) { - m_eDamagePolicy = policy; - m_pConfig = pAnimConfig; - m_pWindow = pWindow; - - m_bDummy = false; -} - -void CBaseAnimatedVariable::create(SAnimationPropertyConfig* pAnimConfig, PHLLS pLayer, eAVarDamagePolicy policy) { - m_eDamagePolicy = policy; - m_pConfig = pAnimConfig; - m_pLayer = pLayer; - - m_bDummy = false; -} - -void CBaseAnimatedVariable::create(SAnimationPropertyConfig* pAnimConfig, PHLWORKSPACE pWorkspace, eAVarDamagePolicy policy) { - m_eDamagePolicy = policy; - m_pConfig = pAnimConfig; - m_pWorkspace = pWorkspace; - - m_bDummy = false; -} - -void CBaseAnimatedVariable::create(SAnimationPropertyConfig* pAnimConfig, eAVarDamagePolicy policy) { - m_eDamagePolicy = policy; - m_pConfig = pAnimConfig; - - m_bDummy = false; -} - -CBaseAnimatedVariable::~CBaseAnimatedVariable() { - unregister(); -} - -void CBaseAnimatedVariable::unregister() { - if (!g_pAnimationManager) - return; - std::erase_if(g_pAnimationManager->m_vAnimatedVariables, [&](const auto& other) { return other == this; }); - m_bIsRegistered = false; - disconnectFromActive(); -} - -void CBaseAnimatedVariable::registerVar() { - if (!m_bIsRegistered) - g_pAnimationManager->m_vAnimatedVariables.push_back(this); - m_bIsRegistered = true; -} - -float CBaseAnimatedVariable::getPercent() { - const auto DURATIONPASSED = std::chrono::duration_cast(std::chrono::steady_clock::now() - animationBegin).count(); - return std::clamp((DURATIONPASSED / 100.f) / m_pConfig->pValues->internalSpeed, 0.f, 1.f); -} - -float CBaseAnimatedVariable::getCurveValue() { - if (!m_bIsBeingAnimated) - return 1.f; - - const auto SPENT = getPercent(); - - if (SPENT >= 1.f) - return 1.f; - - return g_pAnimationManager->getBezier(m_pConfig->pValues->internalBezier)->getYForPoint(SPENT); -} - -void CBaseAnimatedVariable::connectToActive() { - g_pAnimationManager->scheduleTick(); // otherwise the animation manager will never pick this up - - if (!m_bIsConnectedToActive) - g_pAnimationManager->m_vActiveAnimatedVariables.push_back(this); - - m_bIsConnectedToActive = true; -} - -void CBaseAnimatedVariable::disconnectFromActive() { - std::erase_if(g_pAnimationManager->m_vActiveAnimatedVariables, [&](const auto& other) { return other == this; }); - m_bIsConnectedToActive = false; -} diff --git a/src/helpers/AnimatedVariable.hpp b/src/helpers/AnimatedVariable.hpp index a1da00da..e7d5fd8c 100644 --- a/src/helpers/AnimatedVariable.hpp +++ b/src/helpers/AnimatedVariable.hpp @@ -1,15 +1,18 @@ #pragma once -#include -#include -#include -#include -#include "math/Math.hpp" +#include + #include "Color.hpp" #include "../defines.hpp" -#include "../debug/Log.hpp" #include "../desktop/DesktopTypes.hpp" +enum eAVarDamagePolicy : int8_t { + AVARDAMAGE_NONE = -1, + AVARDAMAGE_ENTIRE = 0, + AVARDAMAGE_BORDER, + AVARDAMAGE_SHADOW +}; + enum eAnimatedVarType : int8_t { AVARTYPE_INVALID = -1, AVARTYPE_FLOAT, @@ -42,20 +45,6 @@ struct STypeToAnimatedVarType_t { template inline constexpr eAnimatedVarType typeToeAnimatedVarType = STypeToAnimatedVarType_t::value; -enum eAVarDamagePolicy : int8_t { - AVARDAMAGE_NONE = -1, - AVARDAMAGE_ENTIRE = 0, - AVARDAMAGE_BORDER, - AVARDAMAGE_SHADOW -}; - -class CAnimationManager; -struct SAnimationPropertyConfig; -class CHyprRenderer; -class CWindow; -class CWorkspace; -class CLayerSurface; - // Utility to define a concept as a list of possible type template concept OneOf = (... or std::same_as); @@ -66,245 +55,19 @@ concept OneOf = (... or std::same_as); template concept Animable = OneOf; -class CBaseAnimatedVariable { - public: - CBaseAnimatedVariable(eAnimatedVarType type); - void create(SAnimationPropertyConfig* pAnimConfig, PHLWINDOW pWindow, eAVarDamagePolicy policy); - void create(SAnimationPropertyConfig* pAnimConfig, PHLLS pLayer, eAVarDamagePolicy policy); - void create(SAnimationPropertyConfig* pAnimConfig, PHLWORKSPACE pWorkspace, eAVarDamagePolicy policy); - void create(SAnimationPropertyConfig* pAnimConfig, eAVarDamagePolicy policy); +struct SAnimationContext { + PHLWINDOWREF pWindow; + PHLWORKSPACEREF pWorkspace; + PHLLSREF pLayer; - CBaseAnimatedVariable(const CBaseAnimatedVariable&) = delete; - CBaseAnimatedVariable(CBaseAnimatedVariable&&) = delete; - CBaseAnimatedVariable& operator=(const CBaseAnimatedVariable&) = delete; - CBaseAnimatedVariable& operator=(CBaseAnimatedVariable&&) = delete; - - virtual ~CBaseAnimatedVariable(); - - void unregister(); - void registerVar(); - - virtual void warp(bool endCallback = true) = 0; - - // - void setConfig(SAnimationPropertyConfig* pConfig) { - m_pConfig = pConfig; - } - - SAnimationPropertyConfig* getConfig() { - return m_pConfig; - } - - /* returns the spent (completion) % */ - float getPercent(); - - /* returns the current curve value */ - float getCurveValue(); - - // checks if an animation is in progress - bool isBeingAnimated() const { - return m_bIsBeingAnimated; - } - - /* sets a function to be ran when the animation finishes. - if an animation is not running, runs instantly. - if "remove" is set to true, will remove the callback when ran. */ - void setCallbackOnEnd(std::function func, bool remove = true) { - m_fEndCallback = std::move(func); - m_bRemoveEndAfterRan = remove; - - if (!isBeingAnimated()) - onAnimationEnd(); - } - - /* sets a function to be ran when an animation is started. - if "remove" is set to true, will remove the callback when ran. */ - void setCallbackOnBegin(std::function func, bool remove = true) { - m_fBeginCallback = std::move(func); - m_bRemoveBeginAfterRan = remove; - } - - /* Sets the update callback, called every time the value is animated and a step is done - Warning: calling unregisterVar/registerVar in this handler will cause UB */ - void setUpdateCallback(std::function func) { - m_fUpdateCallback = std::move(func); - } - - /* resets all callbacks. Does not call any. */ - void resetAllCallbacks() { - m_fBeginCallback = nullptr; - m_fEndCallback = nullptr; - m_fUpdateCallback = nullptr; - m_bRemoveBeginAfterRan = false; - m_bRemoveEndAfterRan = false; - } - - PHLWINDOW getWindow() { - return m_pWindow.lock(); - } - - protected: - PHLWINDOWREF m_pWindow; - PHLWORKSPACEREF m_pWorkspace; - PHLLSREF m_pLayer; - - SAnimationPropertyConfig* m_pConfig = nullptr; - - bool m_bDummy = true; - bool m_bIsRegistered = false; - bool m_bIsBeingAnimated = false; - - std::chrono::steady_clock::time_point animationBegin; - - eAVarDamagePolicy m_eDamagePolicy = AVARDAMAGE_NONE; - eAnimatedVarType m_Type; - - bool m_bRemoveEndAfterRan = true; - bool m_bRemoveBeginAfterRan = true; - std::function m_fEndCallback; - std::function m_fBeginCallback; - std::function m_fUpdateCallback; - - bool m_bIsConnectedToActive = false; - - void connectToActive(); - - void disconnectFromActive(); - - // methods - void onAnimationEnd() { - m_bIsBeingAnimated = false; - disconnectFromActive(); - - if (m_fEndCallback) { - // loading m_bRemoveEndAfterRan before calling the callback allows the callback to delete this animation safely if it is false. - auto removeEndCallback = m_bRemoveEndAfterRan; - m_fEndCallback(this); - if (removeEndCallback) - m_fEndCallback = nullptr; // reset - } - } - - void onAnimationBegin() { - m_bIsBeingAnimated = true; - connectToActive(); - - if (m_fBeginCallback) { - m_fBeginCallback(this); - if (m_bRemoveBeginAfterRan) - m_fBeginCallback = nullptr; // reset - } - } - - friend class CAnimationManager; - friend class CWorkspace; - friend class CLayerSurface; - friend class CHyprRenderer; + eAVarDamagePolicy eDamagePolicy = AVARDAMAGE_NONE; }; template -class CAnimatedVariable : public CBaseAnimatedVariable { - public: - CAnimatedVariable() : CBaseAnimatedVariable(typeToeAnimatedVarType) { - ; - } // dummy var +using CAnimatedVariable = Hyprutils::Animation::CGenericAnimatedVariable; - void create(const VarType& value, SAnimationPropertyConfig* pAnimConfig, PHLWINDOW pWindow, eAVarDamagePolicy policy) { - create(pAnimConfig, pWindow, policy); - m_Value = value; - m_Goal = value; - } - void create(const VarType& value, SAnimationPropertyConfig* pAnimConfig, PHLLS pLayer, eAVarDamagePolicy policy) { - create(pAnimConfig, pLayer, policy); - m_Value = value; - m_Goal = value; - } - void create(const VarType& value, SAnimationPropertyConfig* pAnimConfig, PHLWORKSPACE pWorkspace, eAVarDamagePolicy policy) { - create(pAnimConfig, pWorkspace, policy); - m_Value = value; - m_Goal = value; - } - void create(const VarType& value, SAnimationPropertyConfig* pAnimConfig, eAVarDamagePolicy policy) { - create(pAnimConfig, policy); - m_Value = value; - m_Goal = value; - } +template +using PHLANIMVAR = SP>; - using CBaseAnimatedVariable::create; - - CAnimatedVariable(const CAnimatedVariable&) = delete; - CAnimatedVariable(CAnimatedVariable&&) = delete; - CAnimatedVariable& operator=(const CAnimatedVariable&) = delete; - CAnimatedVariable& operator=(CAnimatedVariable&&) = delete; - - ~CAnimatedVariable() = default; - - // gets the current vector value (real time) - const VarType& value() const { - return m_Value; - } - - // gets the goal vector value - const VarType& goal() const { - return m_Goal; - } - - CAnimatedVariable& operator=(const VarType& v) { - if (v == m_Goal) - return *this; - - m_Goal = v; - animationBegin = std::chrono::steady_clock::now(); - m_Begun = m_Value; - - onAnimationBegin(); - - return *this; - } - - // Sets the actual stored value, without affecting the goal, but resets the timer - void setValue(const VarType& v) { - if (v == m_Value) - return; - - m_Value = v; - animationBegin = std::chrono::steady_clock::now(); - m_Begun = m_Value; - - onAnimationBegin(); - } - - // Sets the actual value and goal - void setValueAndWarp(const VarType& v) { - m_Goal = v; - m_bIsBeingAnimated = true; - warp(); - } - - void warp(bool endCallback = true) override { - if (!m_bIsBeingAnimated) - return; - - m_Value = m_Goal; - - m_bIsBeingAnimated = false; - - if (m_fUpdateCallback) - m_fUpdateCallback(this); - - if (endCallback) - onAnimationEnd(); - } - - private: - VarType m_Value{}; - VarType m_Goal{}; - VarType m_Begun{}; - - // owners - - friend class CAnimationManager; - friend class CWorkspace; - friend class CLayerSurface; - friend class CHyprRenderer; -}; +template +using PHLANIMVARREF = WP>; diff --git a/src/helpers/BezierCurve.cpp b/src/helpers/BezierCurve.cpp deleted file mode 100644 index a0610fc9..00000000 --- a/src/helpers/BezierCurve.cpp +++ /dev/null @@ -1,90 +0,0 @@ -#include "BezierCurve.hpp" -#include "../debug/Log.hpp" -#include "../macros.hpp" - -#include -#include - -void CBezierCurve::setup(std::vector* pVec) { - const auto BEGIN = std::chrono::high_resolution_clock::now(); - - // Avoid reallocations by reserving enough memory upfront - m_vPoints.resize(pVec->size() + 2); - m_vPoints[0] = Vector2D(0, 0); // Start point - size_t index = 1; // Start after the first element - for (const auto& vec : *pVec) { - if (index < m_vPoints.size() - 1) { // Bounds check to ensure safety - m_vPoints[index] = vec; - ++index; - } - } - m_vPoints.back() = Vector2D(1, 1); // End point - - RASSERT(m_vPoints.size() == 4, "CBezierCurve only supports cubic beziers! (points num: {})", m_vPoints.size()); - - // bake BAKEDPOINTS points for faster lookups - // T -> X ( / BAKEDPOINTS ) - for (int i = 0; i < BAKEDPOINTS; ++i) { - float const t = (i + 1) / (float)BAKEDPOINTS; - m_aPointsBaked[i] = Vector2D(getXForT(t), getYForT(t)); - } - - const auto ELAPSEDUS = std::chrono::duration_cast(std::chrono::high_resolution_clock::now() - BEGIN).count() / 1000.f; - const auto POINTSSIZE = m_aPointsBaked.size() * sizeof(m_aPointsBaked[0]) / 1000.f; - - const auto BEGINCALC = std::chrono::high_resolution_clock::now(); - for (int j = 1; j < 10; ++j) { - float i = j / 10.0f; - getYForPoint(i); - } - const auto ELAPSEDCALCAVG = std::chrono::duration_cast(std::chrono::high_resolution_clock::now() - BEGINCALC).count() / 1000.f / 10.f; - - Debug::log(LOG, "Created a bezier curve, baked {} points, mem usage: {:.2f}kB, time to bake: {:.2f}µs. Estimated average calc time: {:.2f}µs.", BAKEDPOINTS, POINTSSIZE, - ELAPSEDUS, ELAPSEDCALCAVG); -} - -float CBezierCurve::getXForT(float const& t) const { - float t2 = t * t; - float t3 = t2 * t; - - return 3 * t * (1 - t) * (1 - t) * m_vPoints[1].x + 3 * t2 * (1 - t) * m_vPoints[2].x + t3 * m_vPoints[3].x; -} - -float CBezierCurve::getYForT(float const& t) const { - float t2 = t * t; - float t3 = t2 * t; - - return 3 * t * (1 - t) * (1 - t) * m_vPoints[1].y + 3 * t2 * (1 - t) * m_vPoints[2].y + t3 * m_vPoints[3].y; -} - -// Todo: this probably can be done better and faster -float CBezierCurve::getYForPoint(float const& x) const { - if (x >= 1.f) - return 1.f; - if (x <= 0.f) - return 0.f; - - int index = 0; - bool below = true; - for (int step = (BAKEDPOINTS + 1) / 2; step > 0; step /= 2) { - if (below) - index += step; - else - index -= step; - - below = m_aPointsBaked[index].x < x; - } - - int lowerIndex = index - (!below || index == BAKEDPOINTS - 1); - - // in the name of performance i shall make a hack - const auto LOWERPOINT = &m_aPointsBaked[lowerIndex]; - const auto UPPERPOINT = &m_aPointsBaked[lowerIndex + 1]; - - const auto PERCINDELTA = (x - LOWERPOINT->x) / (UPPERPOINT->x - LOWERPOINT->x); - - if (std::isnan(PERCINDELTA) || std::isinf(PERCINDELTA)) // can sometimes happen for VERY small x - return 0.f; - - return LOWERPOINT->y + (UPPERPOINT->y - LOWERPOINT->y) * PERCINDELTA; -} diff --git a/src/helpers/BezierCurve.hpp b/src/helpers/BezierCurve.hpp deleted file mode 100644 index e643fb41..00000000 --- a/src/helpers/BezierCurve.hpp +++ /dev/null @@ -1,28 +0,0 @@ -#pragma once - -#include -#include -#include -#include "math/Math.hpp" - -constexpr int BAKEDPOINTS = 255; -constexpr float INVBAKEDPOINTS = 1.f / BAKEDPOINTS; - -// an implementation of a cubic bezier curve -// might do better later -class CBezierCurve { - public: - // sets up the bezier curve. - // this EXCLUDES the 0,0 and 1,1 points, - void setup(std::vector* points); - - float getYForT(float const& t) const; - float getXForT(float const& t) const; - float getYForPoint(float const& x) const; - - private: - // this INCLUDES the 0,0 and 1,1 points. - std::vector m_vPoints; - - std::array m_aPointsBaked; -}; diff --git a/src/helpers/Monitor.cpp b/src/helpers/Monitor.cpp index 76df00b3..e833e661 100644 --- a/src/helpers/Monitor.cpp +++ b/src/helpers/Monitor.cpp @@ -1127,16 +1127,16 @@ void CMonitor::setSpecialWorkspace(const PHLWORKSPACE& pWorkspace) { if (w->m_bIsFloating && !VECINRECT(MIDDLE, vecPosition.x, vecPosition.y, vecPosition.x + vecSize.x, vecPosition.y + vecSize.y) && !w->isX11OverrideRedirect()) { // if it's floating and the middle isnt on the current mon, move it to the center const auto PMONFROMMIDDLE = g_pCompositor->getMonitorFromVector(MIDDLE); - Vector2D pos = w->m_vRealPosition.goal(); + Vector2D pos = w->m_vRealPosition->goal(); if (!VECINRECT(MIDDLE, PMONFROMMIDDLE->vecPosition.x, PMONFROMMIDDLE->vecPosition.y, PMONFROMMIDDLE->vecPosition.x + PMONFROMMIDDLE->vecSize.x, PMONFROMMIDDLE->vecPosition.y + PMONFROMMIDDLE->vecSize.y)) { // not on any monitor, center - pos = middle() / 2.f - w->m_vRealSize.goal() / 2.f; + pos = middle() / 2.f - w->m_vRealSize->goal() / 2.f; } else pos = pos - PMONFROMMIDDLE->vecPosition + vecPosition; - w->m_vRealPosition = pos; - w->m_vPosition = pos; + *w->m_vRealPosition = pos; + w->m_vPosition = pos; } } } diff --git a/src/helpers/WLClasses.hpp b/src/helpers/WLClasses.hpp index 0a6ef55d..b6e3ac12 100644 --- a/src/helpers/WLClasses.hpp +++ b/src/helpers/WLClasses.hpp @@ -5,7 +5,6 @@ #include "../desktop/Window.hpp" #include "../desktop/Subsurface.hpp" #include "../desktop/Popup.hpp" -#include "AnimatedVariable.hpp" #include "../desktop/WLSurface.hpp" #include "signal/Signal.hpp" #include "math/Math.hpp" diff --git a/src/hyprerror/HyprError.cpp b/src/hyprerror/HyprError.cpp index d3cd8273..5e0dcf5e 100644 --- a/src/hyprerror/HyprError.cpp +++ b/src/hyprerror/HyprError.cpp @@ -3,13 +3,13 @@ #include "../Compositor.hpp" #include "../config/ConfigValue.hpp" #include "../render/pass/TexPassElement.hpp" +#include "../managers/AnimationManager.hpp" #include -using namespace Hyprutils::Utils; +using namespace Hyprutils::Animation; CHyprError::CHyprError() { - m_fFadeOpacity.create(AVARTYPE_FLOAT, g_pConfigManager->getAnimationPropertyConfig("fadeIn"), AVARDAMAGE_NONE); - m_fFadeOpacity.registerVar(); + g_pAnimationManager->createAnimation(0.f, m_fFadeOpacity, g_pConfigManager->getAnimationPropertyConfig("fadeIn"), AVARDAMAGE_NONE); static auto P = g_pHookSystem->hookDynamic("focusedMon", [&](void* self, SCallbackInfo& info, std::any param) { if (!m_bIsCreated) @@ -23,16 +23,14 @@ CHyprError::CHyprError() { if (!m_bIsCreated) return; - if (m_fFadeOpacity.isBeingAnimated() || m_bMonitorChanged) + if (m_fFadeOpacity->isBeingAnimated() || m_bMonitorChanged) g_pHyprRenderer->damageBox(&m_bDamageBox); }); m_pTexture = makeShared(); } -CHyprError::~CHyprError() { - m_fFadeOpacity.unregister(); -} +CHyprError::~CHyprError() = default; void CHyprError::queueCreate(std::string message, const CHyprColor& color) { m_szQueued = message; @@ -43,10 +41,10 @@ void CHyprError::createQueued() { if (m_bIsCreated) m_pTexture->destroyTexture(); - m_fFadeOpacity.setConfig(g_pConfigManager->getAnimationPropertyConfig("fadeIn")); + m_fFadeOpacity->setConfig(g_pConfigManager->getAnimationPropertyConfig("fadeIn")); - m_fFadeOpacity.setValueAndWarp(0.f); - m_fFadeOpacity = 1.f; + m_fFadeOpacity->setValueAndWarp(0.f); + *m_fFadeOpacity = 1.f; const auto PMONITOR = g_pCompositor->m_vMonitors.front(); @@ -176,8 +174,8 @@ void CHyprError::draw() { } if (m_bQueuedDestroy) { - if (!m_fFadeOpacity.isBeingAnimated()) { - if (m_fFadeOpacity.value() == 0.f) { + if (!m_fFadeOpacity->isBeingAnimated()) { + if (m_fFadeOpacity->value() == 0.f) { m_bQueuedDestroy = false; m_pTexture->destroyTexture(); m_bIsCreated = false; @@ -189,8 +187,8 @@ void CHyprError::draw() { return; } else { - m_fFadeOpacity.setConfig(g_pConfigManager->getAnimationPropertyConfig("fadeOut")); - m_fFadeOpacity = 0.f; + m_fFadeOpacity->setConfig(g_pConfigManager->getAnimationPropertyConfig("fadeOut")); + *m_fFadeOpacity = 0.f; } } } @@ -202,7 +200,7 @@ void CHyprError::draw() { m_bDamageBox.x = (int)PMONITOR->vecPosition.x; m_bDamageBox.y = (int)PMONITOR->vecPosition.y; - if (m_fFadeOpacity.isBeingAnimated() || m_bMonitorChanged) + if (m_fFadeOpacity->isBeingAnimated() || m_bMonitorChanged) g_pHyprRenderer->damageBox(&m_bDamageBox); m_bMonitorChanged = false; @@ -210,7 +208,7 @@ void CHyprError::draw() { CTexPassElement::SRenderData data; data.tex = m_pTexture; data.box = monbox; - data.a = m_fFadeOpacity.value(); + data.a = m_fFadeOpacity->value(); g_pHyprRenderer->m_sRenderPass.add(makeShared(data)); } diff --git a/src/hyprerror/HyprError.hpp b/src/hyprerror/HyprError.hpp index 042dccd0..9a662423 100644 --- a/src/hyprerror/HyprError.hpp +++ b/src/hyprerror/HyprError.hpp @@ -19,17 +19,17 @@ class CHyprError { float height(); // logical private: - void createQueued(); - std::string m_szQueued = ""; - CHyprColor m_cQueued; - bool m_bQueuedDestroy = false; - bool m_bIsCreated = false; - SP m_pTexture; - CAnimatedVariable m_fFadeOpacity; - CBox m_bDamageBox = {0, 0, 0, 0}; - float m_fLastHeight = 0.F; + void createQueued(); + std::string m_szQueued = ""; + CHyprColor m_cQueued; + bool m_bQueuedDestroy = false; + bool m_bIsCreated = false; + SP m_pTexture; + PHLANIMVAR m_fFadeOpacity; + CBox m_bDamageBox = {0, 0, 0, 0}; + float m_fLastHeight = 0.F; - bool m_bMonitorChanged = false; + bool m_bMonitorChanged = false; }; inline std::unique_ptr g_pHyprError; // This is a full-screen error. Treat it with respect, and there can only be one at a time. diff --git a/src/layout/DwindleLayout.cpp b/src/layout/DwindleLayout.cpp index dc6e37dd..2ee41eba 100644 --- a/src/layout/DwindleLayout.cpp +++ b/src/layout/DwindleLayout.cpp @@ -192,16 +192,16 @@ void CHyprDwindleLayout::applyNodeDataToWindow(SDwindleNodeData* pNode, bool for CBox wb = {calcPos + (calcSize - calcSize * *PSCALEFACTOR) / 2.f, calcSize * *PSCALEFACTOR}; wb.round(); // avoid rounding mess - PWINDOW->m_vRealPosition = wb.pos(); - PWINDOW->m_vRealSize = wb.size(); + *PWINDOW->m_vRealPosition = wb.pos(); + *PWINDOW->m_vRealSize = wb.size(); g_pXWaylandManager->setWindowSize(PWINDOW, wb.size()); } else { CBox wb = {calcPos, calcSize}; wb.round(); // avoid rounding mess - PWINDOW->m_vRealSize = wb.size(); - PWINDOW->m_vRealPosition = wb.pos(); + *PWINDOW->m_vRealSize = wb.size(); + *PWINDOW->m_vRealPosition = wb.pos(); g_pXWaylandManager->setWindowSize(PWINDOW, wb.size()); } @@ -209,8 +209,8 @@ void CHyprDwindleLayout::applyNodeDataToWindow(SDwindleNodeData* pNode, bool for if (force) { g_pHyprRenderer->damageWindow(PWINDOW); - PWINDOW->m_vRealPosition.warp(); - PWINDOW->m_vRealSize.warp(); + PWINDOW->m_vRealPosition->warp(); + PWINDOW->m_vRealSize->warp(); g_pHyprRenderer->damageWindow(PWINDOW); } @@ -508,8 +508,8 @@ void CHyprDwindleLayout::calculateWorkspace(const PHLWORKSPACE& pWorkspace) { const auto PFULLWINDOW = pWorkspace->getFullscreenWindow(); if (pWorkspace->m_efFullscreenMode == FSMODE_FULLSCREEN) { - PFULLWINDOW->m_vRealPosition = PMONITOR->vecPosition; - PFULLWINDOW->m_vRealSize = PMONITOR->vecSize; + *PFULLWINDOW->m_vRealPosition = PMONITOR->vecPosition; + *PFULLWINDOW->m_vRealSize = PMONITOR->vecSize; } else if (pWorkspace->m_efFullscreenMode == FSMODE_MAXIMIZED) { SDwindleNodeData fakeNode; fakeNode.pWindow = PFULLWINDOW; @@ -554,8 +554,8 @@ void CHyprDwindleLayout::resizeActiveWindow(const Vector2D& pixResize, eRectCorn const auto PNODE = getNodeFromWindow(PWINDOW); if (!PNODE) { - PWINDOW->m_vRealSize = - (PWINDOW->m_vRealSize.goal() + pixResize) + *PWINDOW->m_vRealSize = + (PWINDOW->m_vRealSize->goal() + pixResize) .clamp(PWINDOW->m_sWindowData.minSize.valueOr(Vector2D{MIN_WINDOW_SIZE, MIN_WINDOW_SIZE}), PWINDOW->m_sWindowData.maxSize.valueOr(Vector2D{INFINITY, INFINITY})); PWINDOW->updateWindowDecos(); return; @@ -575,7 +575,7 @@ void CHyprDwindleLayout::resizeActiveWindow(const Vector2D& pixResize, eRectCorn if (!m_PseudoDragFlags.started) { m_PseudoDragFlags.started = true; - const auto pseudoSize = PWINDOW->m_vRealSize.goal(); + const auto pseudoSize = PWINDOW->m_vRealSize->goal(); const auto mouseOffset = g_pInputManager->getMouseCoordsInternal() - (PNODE->box.pos() + ((PNODE->box.size() / 2) - (pseudoSize / 2))); if (mouseOffset.x > 0 && mouseOffset.x < pseudoSize.x && mouseOffset.y > 0 && mouseOffset.y < pseudoSize.y) { @@ -743,10 +743,10 @@ void CHyprDwindleLayout::fullscreenRequestForWindow(PHLWINDOW pWindow, const eFu // save position and size if floating if (pWindow->m_bIsFloating && CURRENT_EFFECTIVE_MODE == FSMODE_NONE) { - pWindow->m_vLastFloatingSize = pWindow->m_vRealSize.goal(); - pWindow->m_vLastFloatingPosition = pWindow->m_vRealPosition.goal(); - pWindow->m_vPosition = pWindow->m_vRealPosition.goal(); - pWindow->m_vSize = pWindow->m_vRealSize.goal(); + pWindow->m_vLastFloatingSize = pWindow->m_vRealSize->goal(); + pWindow->m_vLastFloatingPosition = pWindow->m_vRealPosition->goal(); + pWindow->m_vPosition = pWindow->m_vRealPosition->goal(); + pWindow->m_vSize = pWindow->m_vRealSize->goal(); } if (EFFECTIVE_MODE == FSMODE_NONE) { @@ -756,8 +756,8 @@ void CHyprDwindleLayout::fullscreenRequestForWindow(PHLWINDOW pWindow, const eFu applyNodeDataToWindow(PNODE); else { // get back its' dimensions from position and size - pWindow->m_vRealPosition = pWindow->m_vLastFloatingPosition; - pWindow->m_vRealSize = pWindow->m_vLastFloatingSize; + *pWindow->m_vRealPosition = pWindow->m_vLastFloatingPosition; + *pWindow->m_vRealSize = pWindow->m_vLastFloatingSize; pWindow->unsetWindowData(PRIORITY_LAYOUT); pWindow->updateWindowData(); @@ -765,8 +765,8 @@ void CHyprDwindleLayout::fullscreenRequestForWindow(PHLWINDOW pWindow, const eFu } else { // apply new pos and size being monitors' box if (EFFECTIVE_MODE == FSMODE_FULLSCREEN) { - pWindow->m_vRealPosition = PMONITOR->vecPosition; - pWindow->m_vRealSize = PMONITOR->vecSize; + *pWindow->m_vRealPosition = PMONITOR->vecPosition; + *pWindow->m_vRealSize = PMONITOR->vecSize; } else { // This is a massive hack. // We make a fake "only" node and apply diff --git a/src/layout/IHyprLayout.cpp b/src/layout/IHyprLayout.cpp index f875b99c..eeebd815 100644 --- a/src/layout/IHyprLayout.cpp +++ b/src/layout/IHyprLayout.cpp @@ -106,7 +106,7 @@ void IHyprLayout::onWindowCreatedFloating(PHLWINDOW pWindow) { if (desiredGeometry.width <= 5 || desiredGeometry.height <= 5) { const auto PWINDOWSURFACE = pWindow->m_pWLSurface->resource(); - pWindow->m_vRealSize = PWINDOWSURFACE->current.size; + *pWindow->m_vRealSize = PWINDOWSURFACE->current.size; if ((desiredGeometry.width <= 1 || desiredGeometry.height <= 1) && pWindow->m_bIsX11 && pWindow->isX11OverrideRedirect()) { // XDG windows should be fine. TODO: check for weird atoms? @@ -115,23 +115,23 @@ void IHyprLayout::onWindowCreatedFloating(PHLWINDOW pWindow) { } // reject any windows with size <= 5x5 - if (pWindow->m_vRealSize.goal().x <= 5 || pWindow->m_vRealSize.goal().y <= 5) - pWindow->m_vRealSize = PMONITOR->vecSize / 2.f; + if (pWindow->m_vRealSize->goal().x <= 5 || pWindow->m_vRealSize->goal().y <= 5) + *pWindow->m_vRealSize = PMONITOR->vecSize / 2.f; if (pWindow->m_bIsX11 && pWindow->isX11OverrideRedirect()) { if (pWindow->m_pXWaylandSurface->geometry.x != 0 && pWindow->m_pXWaylandSurface->geometry.y != 0) - pWindow->m_vRealPosition = g_pXWaylandManager->xwaylandToWaylandCoords(pWindow->m_pXWaylandSurface->geometry.pos()); + *pWindow->m_vRealPosition = g_pXWaylandManager->xwaylandToWaylandCoords(pWindow->m_pXWaylandSurface->geometry.pos()); else - pWindow->m_vRealPosition = Vector2D(PMONITOR->vecPosition.x + (PMONITOR->vecSize.x - pWindow->m_vRealSize.goal().x) / 2.f, - PMONITOR->vecPosition.y + (PMONITOR->vecSize.y - pWindow->m_vRealSize.goal().y) / 2.f); + *pWindow->m_vRealPosition = Vector2D(PMONITOR->vecPosition.x + (PMONITOR->vecSize.x - pWindow->m_vRealSize->goal().x) / 2.f, + PMONITOR->vecPosition.y + (PMONITOR->vecSize.y - pWindow->m_vRealSize->goal().y) / 2.f); } else { - pWindow->m_vRealPosition = Vector2D(PMONITOR->vecPosition.x + (PMONITOR->vecSize.x - pWindow->m_vRealSize.goal().x) / 2.f, - PMONITOR->vecPosition.y + (PMONITOR->vecSize.y - pWindow->m_vRealSize.goal().y) / 2.f); + *pWindow->m_vRealPosition = Vector2D(PMONITOR->vecPosition.x + (PMONITOR->vecSize.x - pWindow->m_vRealSize->goal().x) / 2.f, + PMONITOR->vecPosition.y + (PMONITOR->vecSize.y - pWindow->m_vRealSize->goal().y) / 2.f); } } else { // we respect the size. - pWindow->m_vRealSize = Vector2D(desiredGeometry.width, desiredGeometry.height); + *pWindow->m_vRealSize = Vector2D(desiredGeometry.width, desiredGeometry.height); // check if it's on the correct monitor! Vector2D middlePoint = Vector2D(desiredGeometry.x, desiredGeometry.y) + Vector2D(desiredGeometry.width, desiredGeometry.height) / 2.f; @@ -150,35 +150,35 @@ void IHyprLayout::onWindowCreatedFloating(PHLWINDOW pWindow) { if ((desiredGeometry.x == 0 && desiredGeometry.y == 0) || !visible || !pWindow->m_bIsX11) { // if the pos isn't set, fall back to the center placement if it's not a child, otherwise middle of parent if available if (!pWindow->m_bIsX11 && pWindow->m_pXDGSurface->toplevel->parent && validMapped(pWindow->m_pXDGSurface->toplevel->parent->window)) - pWindow->m_vRealPosition = pWindow->m_pXDGSurface->toplevel->parent->window->m_vRealPosition.goal() + - pWindow->m_pXDGSurface->toplevel->parent->window->m_vRealSize.goal() / 2.F - desiredGeometry.size() / 2.F; + *pWindow->m_vRealPosition = pWindow->m_pXDGSurface->toplevel->parent->window->m_vRealPosition->goal() + + pWindow->m_pXDGSurface->toplevel->parent->window->m_vRealSize->goal() / 2.F - desiredGeometry.size() / 2.F; else - pWindow->m_vRealPosition = PMONITOR->vecPosition + PMONITOR->vecSize / 2.F - desiredGeometry.size() / 2.F; + *pWindow->m_vRealPosition = PMONITOR->vecPosition + PMONITOR->vecSize / 2.F - desiredGeometry.size() / 2.F; } else { // if it is, we respect where it wants to put itself, but apply monitor offset if outside // most of these are popups if (const auto POPENMON = g_pCompositor->getMonitorFromVector(middlePoint); POPENMON->ID != PMONITOR->ID) - pWindow->m_vRealPosition = Vector2D(desiredGeometry.x, desiredGeometry.y) - POPENMON->vecPosition + PMONITOR->vecPosition; + *pWindow->m_vRealPosition = Vector2D(desiredGeometry.x, desiredGeometry.y) - POPENMON->vecPosition + PMONITOR->vecPosition; else - pWindow->m_vRealPosition = Vector2D(desiredGeometry.x, desiredGeometry.y); + *pWindow->m_vRealPosition = Vector2D(desiredGeometry.x, desiredGeometry.y); } } if (*PXWLFORCESCALEZERO && pWindow->m_bIsX11) - pWindow->m_vRealSize = pWindow->m_vRealSize.goal() / PMONITOR->scale; + *pWindow->m_vRealSize = pWindow->m_vRealSize->goal() / PMONITOR->scale; if (pWindow->m_bX11DoesntWantBorders || (pWindow->m_bIsX11 && pWindow->isX11OverrideRedirect())) { - pWindow->m_vRealPosition.warp(); - pWindow->m_vRealSize.warp(); + pWindow->m_vRealPosition->warp(); + pWindow->m_vRealSize->warp(); } if (!pWindow->isX11OverrideRedirect()) { - g_pXWaylandManager->setWindowSize(pWindow, pWindow->m_vRealSize.goal()); + g_pXWaylandManager->setWindowSize(pWindow, pWindow->m_vRealSize->goal()); g_pCompositor->changeWindowZOrder(pWindow, true); } else { - pWindow->m_vPendingReportedSize = pWindow->m_vRealSize.goal(); + pWindow->m_vPendingReportedSize = pWindow->m_vRealSize->goal(); pWindow->m_vReportedSize = pWindow->m_vPendingReportedSize; } } @@ -250,18 +250,18 @@ void IHyprLayout::onBeginDragWindow() { if (!DRAGGINGWINDOW->m_bIsFloating) { if (g_pInputManager->dragMode == MBIND_MOVE) { - DRAGGINGWINDOW->m_vLastFloatingSize = (DRAGGINGWINDOW->m_vRealSize.goal() * 0.8489).clamp(Vector2D{5, 5}, Vector2D{}).floor(); + DRAGGINGWINDOW->m_vLastFloatingSize = (DRAGGINGWINDOW->m_vRealSize->goal() * 0.8489).clamp(Vector2D{5, 5}, Vector2D{}).floor(); changeWindowFloatingMode(DRAGGINGWINDOW); DRAGGINGWINDOW->m_bIsFloating = true; DRAGGINGWINDOW->m_bDraggingTiled = true; - DRAGGINGWINDOW->m_vRealPosition = g_pInputManager->getMouseCoordsInternal() - DRAGGINGWINDOW->m_vRealSize.goal() / 2.f; + *DRAGGINGWINDOW->m_vRealPosition = g_pInputManager->getMouseCoordsInternal() - DRAGGINGWINDOW->m_vRealSize->goal() / 2.f; } } m_vBeginDragXY = g_pInputManager->getMouseCoordsInternal(); - m_vBeginDragPositionXY = DRAGGINGWINDOW->m_vRealPosition.goal(); - m_vBeginDragSizeXY = DRAGGINGWINDOW->m_vRealSize.goal(); + m_vBeginDragPositionXY = DRAGGINGWINDOW->m_vRealPosition->goal(); + m_vBeginDragSizeXY = DRAGGINGWINDOW->m_vRealSize->goal(); m_vLastDragXY = m_vBeginDragXY; // get the grab corner @@ -348,10 +348,10 @@ void IHyprLayout::onEndDragWindow() { if (DRAGGINGWINDOW->m_sGroupData.pNextWindow) { PHLWINDOW next = DRAGGINGWINDOW->m_sGroupData.pNextWindow.lock(); while (next != DRAGGINGWINDOW) { - next->m_bIsFloating = pWindow->m_bIsFloating; // match the floating state of group members - next->m_vRealSize = pWindow->m_vRealSize.goal(); // match the size of group members - next->m_vRealPosition = pWindow->m_vRealPosition.goal(); // match the position of group members - next = next->m_sGroupData.pNextWindow.lock(); + next->m_bIsFloating = pWindow->m_bIsFloating; // match the floating state of group members + *next->m_vRealSize = pWindow->m_vRealSize->goal(); // match the size of group members + *next->m_vRealPosition = pWindow->m_vRealPosition->goal(); // match the position of group members + next = next->m_sGroupData.pNextWindow.lock(); } } @@ -360,7 +360,7 @@ void IHyprLayout::onEndDragWindow() { DRAGGINGWINDOW->m_bDraggingTiled = false; if (pWindow->m_bIsFloating) - g_pXWaylandManager->setWindowSize(DRAGGINGWINDOW, pWindow->m_vRealSize.goal()); // match the size of the window + g_pXWaylandManager->setWindowSize(DRAGGINGWINDOW, pWindow->m_vRealSize->goal()); // match the size of the window static auto USECURRPOS = CConfigValue("group:insert_after_current"); (*USECURRPOS ? pWindow : pWindow->getGroupTail())->insertWindowToGroup(DRAGGINGWINDOW); @@ -593,7 +593,7 @@ void IHyprLayout::onMouseMove(const Vector2D& mousePos) { if (g_pInputManager->dragMode == MBIND_MOVE) { Vector2D newPos = m_vBeginDragPositionXY + DELTA; - Vector2D newSize = DRAGGINGWINDOW->m_vRealSize.goal(); + Vector2D newSize = DRAGGINGWINDOW->m_vRealSize->goal(); if (*SNAPENABLED && !DRAGGINGWINDOW->m_bDraggingTiled) performSnap(newPos, newSize, DRAGGINGWINDOW, MBIND_MOVE, -1, m_vBeginDragSizeXY); @@ -602,11 +602,11 @@ void IHyprLayout::onMouseMove(const Vector2D& mousePos) { wb.round(); if (*PANIMATEMOUSE) - DRAGGINGWINDOW->m_vRealPosition = wb.pos(); + *DRAGGINGWINDOW->m_vRealPosition = wb.pos(); else - DRAGGINGWINDOW->m_vRealPosition.setValueAndWarp(wb.pos()); + DRAGGINGWINDOW->m_vRealPosition->setValueAndWarp(wb.pos()); - g_pXWaylandManager->setWindowSize(DRAGGINGWINDOW, DRAGGINGWINDOW->m_vRealSize.goal()); + g_pXWaylandManager->setWindowSize(DRAGGINGWINDOW, DRAGGINGWINDOW->m_vRealSize->goal()); } else if (g_pInputManager->dragMode == MBIND_RESIZE || g_pInputManager->dragMode == MBIND_RESIZE_FORCE_RATIO || g_pInputManager->dragMode == MBIND_RESIZE_BLOCK_RATIO) { if (DRAGGINGWINDOW->m_bIsFloating) { @@ -671,21 +671,21 @@ void IHyprLayout::onMouseMove(const Vector2D& mousePos) { wb.round(); if (*PANIMATE) { - DRAGGINGWINDOW->m_vRealSize = wb.size(); - DRAGGINGWINDOW->m_vRealPosition = wb.pos(); + *DRAGGINGWINDOW->m_vRealSize = wb.size(); + *DRAGGINGWINDOW->m_vRealPosition = wb.pos(); } else { - DRAGGINGWINDOW->m_vRealSize.setValueAndWarp(wb.size()); - DRAGGINGWINDOW->m_vRealPosition.setValueAndWarp(wb.pos()); + DRAGGINGWINDOW->m_vRealSize->setValueAndWarp(wb.size()); + DRAGGINGWINDOW->m_vRealPosition->setValueAndWarp(wb.pos()); } - g_pXWaylandManager->setWindowSize(DRAGGINGWINDOW, DRAGGINGWINDOW->m_vRealSize.goal()); + g_pXWaylandManager->setWindowSize(DRAGGINGWINDOW, DRAGGINGWINDOW->m_vRealSize->goal()); } else { resizeActiveWindow(TICKDELTA, m_eGrabbedCorner, DRAGGINGWINDOW); } } // get middle point - Vector2D middle = DRAGGINGWINDOW->m_vRealPosition.value() + DRAGGINGWINDOW->m_vRealSize.value() / 2.f; + Vector2D middle = DRAGGINGWINDOW->m_vRealPosition->value() + DRAGGINGWINDOW->m_vRealSize->value() / 2.f; // and check its monitor const auto PMONITOR = g_pCompositor->getMonitorFromVector(middle); @@ -719,7 +719,7 @@ void IHyprLayout::changeWindowFloatingMode(PHLWINDOW pWindow) { EMIT_HOOK_EVENT("changeFloatingMode", pWindow); if (!TILED) { - const auto PNEWMON = g_pCompositor->getMonitorFromVector(pWindow->m_vRealPosition.value() + pWindow->m_vRealSize.value() / 2.f); + const auto PNEWMON = g_pCompositor->getMonitorFromVector(pWindow->m_vRealPosition->value() + pWindow->m_vRealSize->value() / 2.f); pWindow->m_pMonitor = PNEWMON; pWindow->moveToWorkspace(PNEWMON->activeSpecialWorkspace ? PNEWMON->activeSpecialWorkspace : PNEWMON->activeWorkspace); pWindow->updateGroupOutputs(); @@ -730,12 +730,12 @@ void IHyprLayout::changeWindowFloatingMode(PHLWINDOW pWindow) { g_pCompositor->setWindowFullscreenInternal(PWORKSPACE->getFullscreenWindow(), FSMODE_NONE); // save real pos cuz the func applies the default 5,5 mid - const auto PSAVEDPOS = pWindow->m_vRealPosition.goal(); - const auto PSAVEDSIZE = pWindow->m_vRealSize.goal(); + const auto PSAVEDPOS = pWindow->m_vRealPosition->goal(); + const auto PSAVEDSIZE = pWindow->m_vRealSize->goal(); // if the window is pseudo, update its size if (!pWindow->m_bDraggingTiled) - pWindow->m_vPseudoSize = pWindow->m_vRealSize.goal(); + pWindow->m_vPseudoSize = pWindow->m_vRealSize->goal(); pWindow->m_vLastFloatingSize = PSAVEDSIZE; @@ -744,8 +744,8 @@ void IHyprLayout::changeWindowFloatingMode(PHLWINDOW pWindow) { onWindowCreatedTiling(pWindow); - pWindow->m_vRealPosition.setValue(PSAVEDPOS); - pWindow->m_vRealSize.setValue(PSAVEDSIZE); + pWindow->m_vRealPosition->setValue(PSAVEDPOS); + pWindow->m_vRealSize->setValue(PSAVEDSIZE); // fix pseudo leaving artifacts g_pHyprRenderer->damageMonitor(pWindow->m_pMonitor.lock()); @@ -757,16 +757,16 @@ void IHyprLayout::changeWindowFloatingMode(PHLWINDOW pWindow) { g_pCompositor->changeWindowZOrder(pWindow, true); - CBox wb = {pWindow->m_vRealPosition.goal() + (pWindow->m_vRealSize.goal() - pWindow->m_vLastFloatingSize) / 2.f, pWindow->m_vLastFloatingSize}; + CBox wb = {pWindow->m_vRealPosition->goal() + (pWindow->m_vRealSize->goal() - pWindow->m_vLastFloatingSize) / 2.f, pWindow->m_vLastFloatingSize}; wb.round(); - if (!(pWindow->m_bIsFloating && pWindow->m_bIsPseudotiled) && DELTALESSTHAN(pWindow->m_vRealSize.value().x, pWindow->m_vLastFloatingSize.x, 10) && - DELTALESSTHAN(pWindow->m_vRealSize.value().y, pWindow->m_vLastFloatingSize.y, 10)) { + if (!(pWindow->m_bIsFloating && pWindow->m_bIsPseudotiled) && DELTALESSTHAN(pWindow->m_vRealSize->value().x, pWindow->m_vLastFloatingSize.x, 10) && + DELTALESSTHAN(pWindow->m_vRealSize->value().y, pWindow->m_vLastFloatingSize.y, 10)) { wb = {wb.pos() + Vector2D{10, 10}, wb.size() - Vector2D{20, 20}}; } - pWindow->m_vRealPosition = wb.pos(); - pWindow->m_vRealSize = wb.size(); + *pWindow->m_vRealPosition = wb.pos(); + *pWindow->m_vRealSize = wb.size(); pWindow->m_vSize = wb.pos(); pWindow->m_vPosition = wb.size(); @@ -798,7 +798,7 @@ void IHyprLayout::moveActiveWindow(const Vector2D& delta, PHLWINDOW pWindow) { PWINDOW->setAnimationsToMove(); - PWINDOW->m_vRealPosition = PWINDOW->m_vRealPosition.goal() + delta; + *PWINDOW->m_vRealPosition = PWINDOW->m_vRealPosition->goal() + delta; g_pHyprRenderer->damageWindow(PWINDOW); } diff --git a/src/layout/MasterLayout.cpp b/src/layout/MasterLayout.cpp index 225246f0..e6e22326 100644 --- a/src/layout/MasterLayout.cpp +++ b/src/layout/MasterLayout.cpp @@ -301,8 +301,8 @@ void CHyprMasterLayout::calculateWorkspace(PHLWORKSPACE pWorkspace) { const auto PFULLWINDOW = pWorkspace->getFullscreenWindow(); if (pWorkspace->m_efFullscreenMode == FSMODE_FULLSCREEN) { - PFULLWINDOW->m_vRealPosition = PMONITOR->vecPosition; - PFULLWINDOW->m_vRealSize = PMONITOR->vecSize; + *PFULLWINDOW->m_vRealPosition = PMONITOR->vecPosition; + *PFULLWINDOW->m_vRealSize = PMONITOR->vecSize; } else if (pWorkspace->m_efFullscreenMode == FSMODE_MAXIMIZED) { SMasterNodeData fakeNode; fakeNode.pWindow = PFULLWINDOW; @@ -672,16 +672,16 @@ void CHyprMasterLayout::applyNodeDataToWindow(SMasterNodeData* pNode) { CBox wb = {calcPos + (calcSize - calcSize * *PSCALEFACTOR) / 2.f, calcSize * *PSCALEFACTOR}; wb.round(); // avoid rounding mess - PWINDOW->m_vRealPosition = wb.pos(); - PWINDOW->m_vRealSize = wb.size(); + *PWINDOW->m_vRealPosition = wb.pos(); + *PWINDOW->m_vRealSize = wb.size(); g_pXWaylandManager->setWindowSize(PWINDOW, wb.size()); } else { CBox wb = {calcPos, calcSize}; wb.round(); // avoid rounding mess - PWINDOW->m_vRealPosition = wb.pos(); - PWINDOW->m_vRealSize = wb.size(); + *PWINDOW->m_vRealPosition = wb.pos(); + *PWINDOW->m_vRealSize = wb.size(); g_pXWaylandManager->setWindowSize(PWINDOW, wb.size()); } @@ -689,8 +689,8 @@ void CHyprMasterLayout::applyNodeDataToWindow(SMasterNodeData* pNode) { if (m_bForceWarps && !*PANIMATE) { g_pHyprRenderer->damageWindow(PWINDOW); - PWINDOW->m_vRealPosition.warp(); - PWINDOW->m_vRealSize.warp(); + PWINDOW->m_vRealPosition->warp(); + PWINDOW->m_vRealSize->warp(); g_pHyprRenderer->damageWindow(PWINDOW); } @@ -711,8 +711,8 @@ void CHyprMasterLayout::resizeActiveWindow(const Vector2D& pixResize, eRectCorne const auto PNODE = getNodeFromWindow(PWINDOW); if (!PNODE) { - PWINDOW->m_vRealSize = - (PWINDOW->m_vRealSize.goal() + pixResize) + *PWINDOW->m_vRealSize = + (PWINDOW->m_vRealSize->goal() + pixResize) .clamp(PWINDOW->m_sWindowData.minSize.valueOr(Vector2D{MIN_WINDOW_SIZE, MIN_WINDOW_SIZE}), PWINDOW->m_sWindowData.maxSize.valueOr(Vector2D{INFINITY, INFINITY})); PWINDOW->updateWindowDecos(); return; @@ -852,10 +852,10 @@ void CHyprMasterLayout::fullscreenRequestForWindow(PHLWINDOW pWindow, const eFul // save position and size if floating if (pWindow->m_bIsFloating && CURRENT_EFFECTIVE_MODE == FSMODE_NONE) { - pWindow->m_vLastFloatingSize = pWindow->m_vRealSize.goal(); - pWindow->m_vLastFloatingPosition = pWindow->m_vRealPosition.goal(); - pWindow->m_vPosition = pWindow->m_vRealPosition.goal(); - pWindow->m_vSize = pWindow->m_vRealSize.goal(); + pWindow->m_vLastFloatingSize = pWindow->m_vRealSize->goal(); + pWindow->m_vLastFloatingPosition = pWindow->m_vRealPosition->goal(); + pWindow->m_vPosition = pWindow->m_vRealPosition->goal(); + pWindow->m_vSize = pWindow->m_vRealSize->goal(); } if (EFFECTIVE_MODE == FSMODE_NONE) { @@ -865,8 +865,8 @@ void CHyprMasterLayout::fullscreenRequestForWindow(PHLWINDOW pWindow, const eFul applyNodeDataToWindow(PNODE); else { // get back its' dimensions from position and size - pWindow->m_vRealPosition = pWindow->m_vLastFloatingPosition; - pWindow->m_vRealSize = pWindow->m_vLastFloatingSize; + *pWindow->m_vRealPosition = pWindow->m_vLastFloatingPosition; + *pWindow->m_vRealSize = pWindow->m_vLastFloatingSize; pWindow->unsetWindowData(PRIORITY_LAYOUT); pWindow->updateWindowData(); @@ -874,8 +874,8 @@ void CHyprMasterLayout::fullscreenRequestForWindow(PHLWINDOW pWindow, const eFul } else { // apply new pos and size being monitors' box if (EFFECTIVE_MODE == FSMODE_FULLSCREEN) { - pWindow->m_vRealPosition = PMONITOR->vecPosition; - pWindow->m_vRealSize = PMONITOR->vecSize; + *pWindow->m_vRealPosition = PMONITOR->vecPosition; + *pWindow->m_vRealSize = PMONITOR->vecSize; } else { // This is a massive hack. // We make a fake "only" node and apply diff --git a/src/managers/AnimationManager.cpp b/src/managers/AnimationManager.cpp index cff438b1..6bfeed83 100644 --- a/src/managers/AnimationManager.cpp +++ b/src/managers/AnimationManager.cpp @@ -1,6 +1,9 @@ #include "AnimationManager.hpp" #include "../Compositor.hpp" #include "HookSystemManager.hpp" +#include "config/ConfigManager.hpp" +#include "desktop/DesktopTypes.hpp" +#include "helpers/AnimatedVariable.hpp" #include "macros.hpp" #include "../config/ConfigValue.hpp" #include "../desktop/Window.hpp" @@ -9,6 +12,8 @@ #include "../helpers/varlist/VarList.hpp" #include +#include +#include static int wlTick(SP self, void* data) { if (g_pAnimationManager) @@ -26,324 +31,245 @@ static int wlTick(SP self, void* data) { return 0; } -CAnimationManager::CAnimationManager() { - std::vector points = {Vector2D(0.0, 0.75), Vector2D(0.15, 1.0)}; - m_mBezierCurves["default"].setup(&points); - - points = {Vector2D(0.0, 0.0), Vector2D(1.0, 1.0)}; - m_mBezierCurves["linear"].setup(&points); - +CHyprAnimationManager::CHyprAnimationManager() { m_pAnimationTimer = SP(new CEventLoopTimer(std::chrono::microseconds(500), wlTick, nullptr)); g_pEventLoopManager->addTimer(m_pAnimationTimer); + + addBezierWithName("linear", Vector2D(0.0, 0.0), Vector2D(1.0, 1.0)); } -void CAnimationManager::removeAllBeziers() { - m_mBezierCurves.clear(); +template +void updateVariable(CAnimatedVariable& av, const float POINTY, bool warp = false) { + if (POINTY >= 1.f || warp || av.value() == av.goal()) { + av.warp(); + return; + } - // add the default one - std::vector points = {Vector2D(0.0, 0.75), Vector2D(0.15, 1.0)}; - m_mBezierCurves["default"].setup(&points); - - points = {Vector2D(0.0, 0.0), Vector2D(1.0, 1.0)}; - m_mBezierCurves["linear"].setup(&points); + const auto DELTA = av.goal() - av.begun(); + av.value() = av.begun() + DELTA * POINTY; } -void CAnimationManager::addBezierWithName(std::string name, const Vector2D& p1, const Vector2D& p2) { - std::vector points = {p1, p2}; - m_mBezierCurves[name].setup(&points); +void updateColorVariable(CAnimatedVariable& av, const float POINTY, bool warp) { + if (POINTY >= 1.f || warp || av.value() == av.goal()) { + av.warp(); + return; + } + + // convert both to OkLab, then lerp that, and convert back. + // This is not as fast as just lerping rgb, but it's WAY more precise... + // Use the CHyprColor cache for OkLab + + const auto& L1 = av.begun().asOkLab(); + const auto& L2 = av.goal().asOkLab(); + + static const auto lerp = [](const float one, const float two, const float progress) -> float { return one + (two - one) * progress; }; + + const Hyprgraphics::CColor lerped = Hyprgraphics::CColor::SOkLab{ + .l = lerp(L1.l, L2.l, POINTY), + .a = lerp(L1.a, L2.a, POINTY), + .b = lerp(L1.b, L2.b, POINTY), + }; + + av.value() = {lerped, lerp(av.begun().a, av.goal().a, POINTY)}; } -void CAnimationManager::onTicked() { - m_bTickScheduled = false; +template +static void handleUpdate(CAnimatedVariable& av, bool warp) { + PHLWINDOW PWINDOW = av.m_Context.pWindow.lock(); + PHLWORKSPACE PWORKSPACE = av.m_Context.pWorkspace.lock(); + PHLLS PLAYER = av.m_Context.pLayer.lock(); + PHLMONITOR PMONITOR = nullptr; + bool animationsDisabled = warp; + + if (PWINDOW) { + if (av.m_Context.eDamagePolicy == AVARDAMAGE_ENTIRE) + g_pHyprRenderer->damageWindow(PWINDOW); + else if (av.m_Context.eDamagePolicy == AVARDAMAGE_BORDER) { + const auto PDECO = PWINDOW->getDecorationByType(DECORATION_BORDER); + PDECO->damageEntire(); + } else if (av.m_Context.eDamagePolicy == AVARDAMAGE_SHADOW) { + const auto PDECO = PWINDOW->getDecorationByType(DECORATION_SHADOW); + PDECO->damageEntire(); + } + + PMONITOR = PWINDOW->m_pMonitor.lock(); + if (!PMONITOR) + return; + + animationsDisabled = PWINDOW->m_sWindowData.noAnim.valueOr(animationsDisabled); + } else if (PWORKSPACE) { + PMONITOR = PWORKSPACE->m_pMonitor.lock(); + if (!PMONITOR) + return; + + // dont damage the whole monitor on workspace change, unless it's a special workspace, because dim/blur etc + if (PWORKSPACE->m_bIsSpecialWorkspace) + g_pHyprRenderer->damageMonitor(PMONITOR); + + // TODO: just make this into a damn callback already vax... + for (auto const& w : g_pCompositor->m_vWindows) { + if (!w->m_bIsMapped || w->isHidden() || w->m_pWorkspace != PWORKSPACE) + continue; + + if (w->m_bIsFloating && !w->m_bPinned) { + // still doing the full damage hack for floating because sometimes when the window + // goes through multiple monitors the last rendered frame is missing damage somehow?? + const CBox windowBoxNoOffset = w->getFullWindowBoundingBox(); + const CBox monitorBox = {PMONITOR->vecPosition, PMONITOR->vecSize}; + if (windowBoxNoOffset.intersection(monitorBox) != windowBoxNoOffset) // on edges between multiple monitors + g_pHyprRenderer->damageWindow(w, true); + } + + if (PWORKSPACE->m_bIsSpecialWorkspace) + g_pHyprRenderer->damageWindow(w, true); // hack for special too because it can cross multiple monitors + } + + // damage any workspace window that is on any monitor + for (auto const& w : g_pCompositor->m_vWindows) { + if (!validMapped(w) || w->m_pWorkspace != PWORKSPACE || w->m_bPinned) + continue; + + g_pHyprRenderer->damageWindow(w); + } + } else if (PLAYER) { + // "some fucking layers miss 1 pixel???" -- vaxry + CBox expandBox = CBox{PLAYER->realPosition->value(), PLAYER->realSize->value()}; + expandBox.expand(5); + g_pHyprRenderer->damageBox(&expandBox); + + PMONITOR = g_pCompositor->getMonitorFromVector(PLAYER->realPosition->goal() + PLAYER->realSize->goal() / 2.F); + if (!PMONITOR) + return; + animationsDisabled = animationsDisabled || PLAYER->noAnimations; + } + + const auto SPENT = av.getPercent(); + const auto PBEZIER = g_pAnimationManager->getBezier(av.getBezierName()); + const auto POINTY = PBEZIER->getYForPoint(SPENT); + + if constexpr (std::same_as) { + updateColorVariable(av, POINTY, animationsDisabled); + } else { + updateVariable(av, POINTY, animationsDisabled); + } + + av.onUpdate(); + + switch (av.m_Context.eDamagePolicy) { + case AVARDAMAGE_ENTIRE: { + if (PWINDOW) { + PWINDOW->updateWindowDecos(); + g_pHyprRenderer->damageWindow(PWINDOW); + } else if (PWORKSPACE) { + for (auto const& w : g_pCompositor->m_vWindows) { + if (!validMapped(w) || w->m_pWorkspace != PWORKSPACE) + continue; + + w->updateWindowDecos(); + + // damage any workspace window that is on any monitor + if (!w->m_bPinned) + g_pHyprRenderer->damageWindow(w); + } + } else if (PLAYER) { + if (PLAYER->layer <= 1) + g_pHyprOpenGL->markBlurDirtyForMonitor(PMONITOR); + + // some fucking layers miss 1 pixel??? + CBox expandBox = CBox{PLAYER->realPosition->value(), PLAYER->realSize->value()}; + expandBox.expand(5); + g_pHyprRenderer->damageBox(&expandBox); + } + break; + } + case AVARDAMAGE_BORDER: { + RASSERT(PWINDOW, "Tried to AVARDAMAGE_BORDER a non-window AVAR!"); + + const auto PDECO = PWINDOW->getDecorationByType(DECORATION_BORDER); + PDECO->damageEntire(); + + break; + } + case AVARDAMAGE_SHADOW: { + RASSERT(PWINDOW, "Tried to AVARDAMAGE_SHADOW a non-window AVAR!"); + + const auto PDECO = PWINDOW->getDecorationByType(DECORATION_SHADOW); + + PDECO->damageEntire(); + + break; + } + default: { + break; + } + } + + // manually schedule a frame + if (PMONITOR) + g_pCompositor->scheduleFrameForMonitor(PMONITOR, Aquamarine::IOutput::AQ_SCHEDULE_ANIMATION); } -void CAnimationManager::tick() { +void CHyprAnimationManager::tick() { static std::chrono::time_point lastTick = std::chrono::high_resolution_clock::now(); m_fLastTickTime = std::chrono::duration_cast(std::chrono::high_resolution_clock::now() - lastTick).count() / 1000.0; lastTick = std::chrono::high_resolution_clock::now(); - if (m_vActiveAnimatedVariables.empty()) - return; - - bool animGlobalDisabled = false; - static auto PANIMENABLED = CConfigValue("animations:enabled"); - - if (!*PANIMENABLED) - animGlobalDisabled = true; - - static auto* const PSHADOWSENABLED = (Hyprlang::INT* const*)g_pConfigManager->getConfigValuePtr("decoration:shadow:enabled"); - - const auto DEFAULTBEZIER = m_mBezierCurves.find("default"); - - std::vector animationEndedVars; - - for (auto const& av : m_vActiveAnimatedVariables) { - - if (av->m_eDamagePolicy == AVARDAMAGE_SHADOW && !*PSHADOWSENABLED) { - av->warp(false); - animationEndedVars.push_back(av); + for (auto const& pav : m_vActiveAnimatedVariables) { + const auto PAV = pav.lock(); + if (!PAV) continue; - } - // get the spent % (0 - 1) - const float SPENT = av->getPercent(); + // for disabled anims just warp + bool warp = !*PANIMENABLED || !PAV->enabled(); - // window stuff - PHLWINDOW PWINDOW = av->m_pWindow.lock(); - PHLWORKSPACE PWORKSPACE = av->m_pWorkspace.lock(); - PHLLS PLAYER = av->m_pLayer.lock(); - PHLMONITOR PMONITOR = nullptr; - bool animationsDisabled = animGlobalDisabled; - - if (PWINDOW) { - if (av->m_eDamagePolicy == AVARDAMAGE_ENTIRE) { - g_pHyprRenderer->damageWindow(PWINDOW); - } else if (av->m_eDamagePolicy == AVARDAMAGE_BORDER) { - const auto PDECO = PWINDOW->getDecorationByType(DECORATION_BORDER); - PDECO->damageEntire(); - } else if (av->m_eDamagePolicy == AVARDAMAGE_SHADOW) { - const auto PDECO = PWINDOW->getDecorationByType(DECORATION_SHADOW); - PDECO->damageEntire(); - } - - PMONITOR = PWINDOW->m_pMonitor.lock(); - if (!PMONITOR) - continue; - animationsDisabled = PWINDOW->m_sWindowData.noAnim.valueOr(animationsDisabled); - } else if (PWORKSPACE) { - PMONITOR = PWORKSPACE->m_pMonitor.lock(); - if (!PMONITOR) - continue; - - // dont damage the whole monitor on workspace change, unless it's a special workspace, because dim/blur etc - if (PWORKSPACE->m_bIsSpecialWorkspace) - g_pHyprRenderer->damageMonitor(PMONITOR); - - // TODO: just make this into a damn callback already vax... - for (auto const& w : g_pCompositor->m_vWindows) { - if (!w->m_bIsMapped || w->isHidden() || w->m_pWorkspace != PWORKSPACE) - continue; - - if (w->m_bIsFloating && !w->m_bPinned) { - // still doing the full damage hack for floating because sometimes when the window - // goes through multiple monitors the last rendered frame is missing damage somehow?? - const CBox windowBoxNoOffset = w->getFullWindowBoundingBox(); - const CBox monitorBox = {PMONITOR->vecPosition, PMONITOR->vecSize}; - if (windowBoxNoOffset.intersection(monitorBox) != windowBoxNoOffset) // on edges between multiple monitors - g_pHyprRenderer->damageWindow(w, true); - } - - if (PWORKSPACE->m_bIsSpecialWorkspace) - g_pHyprRenderer->damageWindow(w, true); // hack for special too because it can cross multiple monitors - } - - // damage any workspace window that is on any monitor - for (auto const& w : g_pCompositor->m_vWindows) { - if (!validMapped(w) || w->m_pWorkspace != PWORKSPACE || w->m_bPinned) - continue; - - g_pHyprRenderer->damageWindow(w); - } - } else if (PLAYER) { - // "some fucking layers miss 1 pixel???" -- vaxry - CBox expandBox = CBox{PLAYER->realPosition.value(), PLAYER->realSize.value()}; - expandBox.expand(5); - g_pHyprRenderer->damageBox(&expandBox); - - PMONITOR = g_pCompositor->getMonitorFromVector(PLAYER->realPosition.goal() + PLAYER->realSize.goal() / 2.F); - if (!PMONITOR) - continue; - animationsDisabled = animationsDisabled || PLAYER->noAnimations; - } - - const bool VISIBLE = PWINDOW && PWINDOW->m_pWorkspace ? PWINDOW->m_pWorkspace->isVisible() : true; - - // beziers are with a switch unforto - // TODO: maybe do something cleaner - - static const auto updateVariable = [this](CAnimatedVariable& av, const float SPENT, const CBezierCurve& DEFAULTBEZIER, const bool DISABLED) { - // for disabled anims just warp - if (av.m_pConfig->pValues->internalEnabled == 0 || DISABLED) { - av.warp(false); - return; - } - - if (SPENT >= 1.f || av.m_Begun == av.m_Goal) { - av.warp(false); - return; - } - - const auto BEZIER = m_mBezierCurves.find(av.m_pConfig->pValues->internalBezier); - const auto POINTY = BEZIER != m_mBezierCurves.end() ? BEZIER->second.getYForPoint(SPENT) : DEFAULTBEZIER.getYForPoint(SPENT); - - const auto DELTA = av.m_Goal - av.m_Begun; - - if (BEZIER != m_mBezierCurves.end()) - av.m_Value = av.m_Begun + DELTA * POINTY; - else - av.m_Value = av.m_Begun + DELTA * POINTY; - }; - - static const auto updateColorVariable = [this](CAnimatedVariable& av, const float SPENT, const CBezierCurve& DEFAULTBEZIER, const bool DISABLED) { - // for disabled anims just warp - if (av.m_pConfig->pValues->internalEnabled == 0 || DISABLED) { - av.warp(false); - return; - } - - if (SPENT >= 1.f || av.m_Begun == av.m_Goal) { - av.warp(false); - return; - } - - const auto BEZIER = m_mBezierCurves.find(av.m_pConfig->pValues->internalBezier); - const auto POINTY = BEZIER != m_mBezierCurves.end() ? BEZIER->second.getYForPoint(SPENT) : DEFAULTBEZIER.getYForPoint(SPENT); - - // convert both to OkLab, then lerp that, and convert back. - // This is not as fast as just lerping rgb, but it's WAY more precise... - // Use the CHyprColor cache for OkLab - - const auto& L1 = av.m_Begun.asOkLab(); - const auto& L2 = av.m_Goal.asOkLab(); - - static const auto lerp = [](const float one, const float two, const float progress) -> float { return one + (two - one) * progress; }; - - const Hyprgraphics::CColor lerped = Hyprgraphics::CColor::SOkLab{ - .l = lerp(L1.l, L2.l, POINTY), - .a = lerp(L1.a, L2.a, POINTY), - .b = lerp(L1.b, L2.b, POINTY), - }; - - av.m_Value = {lerped, lerp(av.m_Begun.a, av.m_Goal.a, POINTY)}; - - return; - }; - - switch (av->m_Type) { + switch (PAV->m_Type) { case AVARTYPE_FLOAT: { - auto typedAv = dynamic_cast*>(av); - updateVariable(*typedAv, SPENT, DEFAULTBEZIER->second, animationsDisabled); - break; - } + auto pTypedAV = dynamic_cast*>(PAV.get()); + RASSERT(pTypedAV, "Failed to upcast animated float"); + handleUpdate(*pTypedAV, warp); + } break; case AVARTYPE_VECTOR: { - auto typedAv = dynamic_cast*>(av); - updateVariable(*typedAv, SPENT, DEFAULTBEZIER->second, animationsDisabled); - break; - } + auto pTypedAV = dynamic_cast*>(PAV.get()); + RASSERT(pTypedAV, "Failed to upcast animated Vector2D"); + handleUpdate(*pTypedAV, warp); + } break; case AVARTYPE_COLOR: { - auto typedAv = dynamic_cast*>(av); - updateColorVariable(*typedAv, SPENT, DEFAULTBEZIER->second, animationsDisabled); - break; - } + auto pTypedAV = dynamic_cast*>(PAV.get()); + RASSERT(pTypedAV, "Failed to upcast animated CHyprColor"); + handleUpdate(*pTypedAV, warp); + } break; default: UNREACHABLE(); } - // set size and pos if valid, but only if damage policy entire (dont if border for example) - if (validMapped(PWINDOW) && av->m_eDamagePolicy == AVARDAMAGE_ENTIRE && !PWINDOW->isX11OverrideRedirect()) - g_pXWaylandManager->setWindowSize(PWINDOW, PWINDOW->m_vRealSize.goal()); - - // check if we did not finish animating. If so, trigger onAnimationEnd. - if (!av->isBeingAnimated()) - animationEndedVars.push_back(av); - - // lastly, handle damage, but only if whatever we are animating is visible. - if (!VISIBLE) - continue; - - if (av->m_fUpdateCallback) - av->m_fUpdateCallback(av); - - switch (av->m_eDamagePolicy) { - case AVARDAMAGE_ENTIRE: { - if (PWINDOW) { - PWINDOW->updateWindowDecos(); - g_pHyprRenderer->damageWindow(PWINDOW); - } else if (PWORKSPACE) { - for (auto const& w : g_pCompositor->m_vWindows) { - if (!validMapped(w) || w->m_pWorkspace != PWORKSPACE) - continue; - - w->updateWindowDecos(); - - // damage any workspace window that is on any monitor - if (!w->m_bPinned) - g_pHyprRenderer->damageWindow(w); - } - } else if (PLAYER) { - if (PLAYER->layer <= 1) - g_pHyprOpenGL->markBlurDirtyForMonitor(PMONITOR); - - // some fucking layers miss 1 pixel??? - CBox expandBox = CBox{PLAYER->realPosition.value(), PLAYER->realSize.value()}; - expandBox.expand(5); - g_pHyprRenderer->damageBox(&expandBox); - } - break; - } - case AVARDAMAGE_BORDER: { - RASSERT(PWINDOW, "Tried to AVARDAMAGE_BORDER a non-window AVAR!"); - - const auto PDECO = PWINDOW->getDecorationByType(DECORATION_BORDER); - PDECO->damageEntire(); - - break; - } - case AVARDAMAGE_SHADOW: { - RASSERT(PWINDOW, "Tried to AVARDAMAGE_SHADOW a non-window AVAR!"); - - const auto PDECO = PWINDOW->getDecorationByType(DECORATION_SHADOW); - - PDECO->damageEntire(); - - break; - } - default: { - break; - } - } - - // manually schedule a frame - if (PMONITOR) - g_pCompositor->scheduleFrameForMonitor(PMONITOR, Aquamarine::IOutput::AQ_SCHEDULE_ANIMATION); } - // do it here, because if this alters the animation vars vec we would be in trouble above. - for (auto const& ave : animationEndedVars) { - ave->onAnimationEnd(); - } + tickDone(); } -bool CAnimationManager::deltaSmallToFlip(const Vector2D& a, const Vector2D& b) { - return std::abs(a.x - b.x) < 0.5f && std::abs(a.y - b.y) < 0.5f; -} +void CHyprAnimationManager::scheduleTick() { + if (m_bTickScheduled) + return; -bool CAnimationManager::deltaSmallToFlip(const CHyprColor& a, const CHyprColor& b) { - return std::abs(a.r - b.r) < 0.5f && std::abs(a.g - b.g) < 0.5f && std::abs(a.b - b.b) < 0.5f && std::abs(a.a - b.a) < 0.5f; -} + m_bTickScheduled = true; -bool CAnimationManager::deltaSmallToFlip(const float& a, const float& b) { - return std::abs(a - b) < 0.5f; -} + const auto PMOSTHZ = g_pHyprRenderer->m_pMostHzMonitor; -bool CAnimationManager::deltazero(const Vector2D& a, const Vector2D& b) { - return a.x == b.x && a.y == b.y; -} - -bool CAnimationManager::deltazero(const float& a, const float& b) { - return a == b; -} - -bool CAnimationManager::deltazero(const CHyprColor& a, const CHyprColor& b) { - return a.r == b.r && a.g == b.g && a.b == b.b && a.a == b.a; -} - -bool CAnimationManager::bezierExists(const std::string& bezier) { - for (auto const& [bc, bz] : m_mBezierCurves) { - if (bc == bezier) - return true; + if (!PMOSTHZ) { + m_pAnimationTimer->updateTimeout(std::chrono::milliseconds(16)); + return; } - return false; + float refreshDelayMs = std::floor(1000.f / PMOSTHZ->refreshRate); + + const float SINCEPRES = std::chrono::duration_cast(std::chrono::steady_clock::now() - PMOSTHZ->lastPresentationTimer.chrono()).count() / 1000.f; + + const auto TOPRES = std::clamp(refreshDelayMs - SINCEPRES, 1.1f, 1000.f); // we can't send 0, that will disarm it + + m_pAnimationTimer->updateTimeout(std::chrono::milliseconds((int)std::floor(TOPRES))); +} + +void CHyprAnimationManager::onTicked() { + m_bTickScheduled = false; } // @@ -351,24 +277,24 @@ bool CAnimationManager::bezierExists(const std::string& bezier) { // // -void CAnimationManager::animationPopin(PHLWINDOW pWindow, bool close, float minPerc) { - const auto GOALPOS = pWindow->m_vRealPosition.goal(); - const auto GOALSIZE = pWindow->m_vRealSize.goal(); +void CHyprAnimationManager::animationPopin(PHLWINDOW pWindow, bool close, float minPerc) { + const auto GOALPOS = pWindow->m_vRealPosition->goal(); + const auto GOALSIZE = pWindow->m_vRealSize->goal(); if (!close) { - pWindow->m_vRealSize.setValue((GOALSIZE * minPerc).clamp({5, 5}, {GOALSIZE.x, GOALSIZE.y})); - pWindow->m_vRealPosition.setValue(GOALPOS + GOALSIZE / 2.f - pWindow->m_vRealSize.m_Value / 2.f); + pWindow->m_vRealSize->setValue((GOALSIZE * minPerc).clamp({5, 5}, {GOALSIZE.x, GOALSIZE.y})); + pWindow->m_vRealPosition->setValue(GOALPOS + GOALSIZE / 2.f - pWindow->m_vRealSize->value() / 2.f); } else { - pWindow->m_vRealSize = (GOALSIZE * minPerc).clamp({5, 5}, {GOALSIZE.x, GOALSIZE.y}); - pWindow->m_vRealPosition = GOALPOS + GOALSIZE / 2.f - pWindow->m_vRealSize.m_Goal / 2.f; + *pWindow->m_vRealSize = (GOALSIZE * minPerc).clamp({5, 5}, {GOALSIZE.x, GOALSIZE.y}); + *pWindow->m_vRealPosition = GOALPOS + GOALSIZE / 2.f - pWindow->m_vRealSize->goal() / 2.f; } } -void CAnimationManager::animationSlide(PHLWINDOW pWindow, std::string force, bool close) { - pWindow->m_vRealSize.warp(false); // size we preserve in slide +void CHyprAnimationManager::animationSlide(PHLWINDOW pWindow, std::string force, bool close) { + pWindow->m_vRealSize->warp(false); // size we preserve in slide - const auto GOALPOS = pWindow->m_vRealPosition.goal(); - const auto GOALSIZE = pWindow->m_vRealSize.goal(); + const auto GOALPOS = pWindow->m_vRealPosition->goal(); + const auto GOALSIZE = pWindow->m_vRealSize->goal(); const auto PMONITOR = pWindow->m_pMonitor.lock(); @@ -388,9 +314,9 @@ void CAnimationManager::animationSlide(PHLWINDOW pWindow, std::string force, boo posOffset = Vector2D(GOALPOS.x, PMONITOR->vecPosition.y - GOALSIZE.y); if (!close) - pWindow->m_vRealPosition.setValue(posOffset); + pWindow->m_vRealPosition->setValue(posOffset); else - pWindow->m_vRealPosition = posOffset; + *pWindow->m_vRealPosition = posOffset; return; } @@ -423,33 +349,33 @@ void CAnimationManager::animationSlide(PHLWINDOW pWindow, std::string force, boo } if (!close) - pWindow->m_vRealPosition.setValue(posOffset); + pWindow->m_vRealPosition->setValue(posOffset); else - pWindow->m_vRealPosition = posOffset; + *pWindow->m_vRealPosition = posOffset; } -void CAnimationManager::onWindowPostCreateClose(PHLWINDOW pWindow, bool close) { +void CHyprAnimationManager::onWindowPostCreateClose(PHLWINDOW pWindow, bool close) { if (!close) { - pWindow->m_vRealPosition.m_pConfig = g_pConfigManager->getAnimationPropertyConfig("windowsIn"); - pWindow->m_vRealSize.m_pConfig = g_pConfigManager->getAnimationPropertyConfig("windowsIn"); - pWindow->m_fAlpha.m_pConfig = g_pConfigManager->getAnimationPropertyConfig("fadeIn"); + pWindow->m_vRealPosition->setConfig(g_pConfigManager->getAnimationPropertyConfig("windowsIn")); + pWindow->m_vRealSize->setConfig(g_pConfigManager->getAnimationPropertyConfig("windowsIn")); + pWindow->m_fAlpha->setConfig(g_pConfigManager->getAnimationPropertyConfig("fadeIn")); } else { - pWindow->m_vRealPosition.m_pConfig = g_pConfigManager->getAnimationPropertyConfig("windowsOut"); - pWindow->m_vRealSize.m_pConfig = g_pConfigManager->getAnimationPropertyConfig("windowsOut"); - pWindow->m_fAlpha.m_pConfig = g_pConfigManager->getAnimationPropertyConfig("fadeOut"); + pWindow->m_vRealPosition->setConfig(g_pConfigManager->getAnimationPropertyConfig("windowsOut")); + pWindow->m_vRealSize->setConfig(g_pConfigManager->getAnimationPropertyConfig("windowsOut")); + pWindow->m_fAlpha->setConfig(g_pConfigManager->getAnimationPropertyConfig("fadeOut")); } - auto ANIMSTYLE = pWindow->m_vRealPosition.m_pConfig->pValues->internalStyle; + std::string ANIMSTYLE = pWindow->m_vRealPosition->getStyle(); transform(ANIMSTYLE.begin(), ANIMSTYLE.end(), ANIMSTYLE.begin(), ::tolower); CVarList animList(ANIMSTYLE, 0, 's'); // if the window is not being animated, that means the layout set a fixed size for it, don't animate. - if (!pWindow->m_vRealPosition.isBeingAnimated() && !pWindow->m_vRealSize.isBeingAnimated()) + if (!pWindow->m_vRealPosition->isBeingAnimated() && !pWindow->m_vRealSize->isBeingAnimated()) return; // if the animation is disabled and we are leaving, ignore the anim to prevent the snapshot being fucked - if (!pWindow->m_vRealPosition.m_pConfig->pValues->internalEnabled) + if (!pWindow->m_vRealPosition->enabled()) return; if (pWindow->m_sWindowData.animationStyle.hasValue()) { @@ -494,7 +420,7 @@ void CAnimationManager::onWindowPostCreateClose(PHLWINDOW pWindow, bool close) { } } -std::string CAnimationManager::styleValidInConfigVar(const std::string& config, const std::string& style) { +std::string CHyprAnimationManager::styleValidInConfigVar(const std::string& config, const std::string& style) { if (config.starts_with("window")) { if (style.starts_with("slide")) return ""; @@ -568,39 +494,3 @@ std::string CAnimationManager::styleValidInConfigVar(const std::string& config, return ""; } - -CBezierCurve* CAnimationManager::getBezier(const std::string& name) { - const auto BEZIER = std::find_if(m_mBezierCurves.begin(), m_mBezierCurves.end(), [&](const auto& other) { return other.first == name; }); - - return BEZIER == m_mBezierCurves.end() ? &m_mBezierCurves["default"] : &BEZIER->second; -} - -std::unordered_map CAnimationManager::getAllBeziers() { - return m_mBezierCurves; -} - -bool CAnimationManager::shouldTickForNext() { - return !m_vActiveAnimatedVariables.empty(); -} - -void CAnimationManager::scheduleTick() { - if (m_bTickScheduled) - return; - - m_bTickScheduled = true; - - const auto PMOSTHZ = g_pHyprRenderer->m_pMostHzMonitor; - - if (!PMOSTHZ) { - m_pAnimationTimer->updateTimeout(std::chrono::milliseconds(16)); - return; - } - - float refreshDelayMs = std::floor(1000.f / PMOSTHZ->refreshRate); - - const float SINCEPRES = std::chrono::duration_cast(std::chrono::steady_clock::now() - PMOSTHZ->lastPresentationTimer.chrono()).count() / 1000.f; - - const auto TOPRES = std::clamp(refreshDelayMs - SINCEPRES, 1.1f, 1000.f); // we can't send 0, that will disarm it - - m_pAnimationTimer->updateTimeout(std::chrono::milliseconds((int)std::floor(TOPRES))); -} diff --git a/src/managers/AnimationManager.hpp b/src/managers/AnimationManager.hpp index 3960f261..7bf73f97 100644 --- a/src/managers/AnimationManager.hpp +++ b/src/managers/AnimationManager.hpp @@ -1,57 +1,64 @@ #pragma once +#include +#include + #include "../defines.hpp" -#include -#include #include "../helpers/AnimatedVariable.hpp" -#include "../helpers/BezierCurve.hpp" -#include "../helpers/Timer.hpp" +#include "desktop/DesktopTypes.hpp" #include "eventLoop/EventLoopTimer.hpp" -class CWindow; - -class CAnimationManager { +class CHyprAnimationManager : public Hyprutils::Animation::CAnimationManager { public: - CAnimationManager(); + CHyprAnimationManager(); - void tick(); - bool shouldTickForNext(); - void onTicked(); - void scheduleTick(); - void addBezierWithName(std::string, const Vector2D&, const Vector2D&); - void removeAllBeziers(); + void tick(); + virtual void scheduleTick(); + virtual void onTicked(); - void onWindowPostCreateClose(PHLWINDOW, bool close = false); + using SAnimationPropertyConfig = Hyprutils::Animation::SAnimationPropertyConfig; + template + void createAnimation(const VarType& v, PHLANIMVAR& pav, SP pConfig, eAVarDamagePolicy policy) { + constexpr const eAnimatedVarType EAVTYPE = typeToeAnimatedVarType; + const auto PAV = makeShared>(); - bool bezierExists(const std::string&); - CBezierCurve* getBezier(const std::string&); + PAV->create(EAVTYPE, static_cast(this), PAV, v); + PAV->setConfig(pConfig); + PAV->m_Context.eDamagePolicy = policy; - std::string styleValidInConfigVar(const std::string&, const std::string&); + pav = std::move(PAV); + } - std::unordered_map getAllBeziers(); + template + void createAnimation(const VarType& v, PHLANIMVAR& pav, SP pConfig, PHLWINDOW pWindow, eAVarDamagePolicy policy) { + createAnimation(v, pav, pConfig, policy); + pav->m_Context.pWindow = pWindow; + } + template + void createAnimation(const VarType& v, PHLANIMVAR& pav, SP pConfig, PHLWORKSPACE pWorkspace, eAVarDamagePolicy policy) { + createAnimation(v, pav, pConfig, policy); + pav->m_Context.pWorkspace = pWorkspace; + } + template + void createAnimation(const VarType& v, PHLANIMVAR& pav, SP pConfig, PHLLS pLayer, eAVarDamagePolicy policy) { + createAnimation(v, pav, pConfig, policy); + pav->m_Context.pLayer = pLayer; + } - std::vector m_vAnimatedVariables; - std::vector m_vActiveAnimatedVariables; + void onWindowPostCreateClose(PHLWINDOW, bool close = false); - SP m_pAnimationTimer; + std::string styleValidInConfigVar(const std::string&, const std::string&); - float m_fLastTickTime; // in ms + SP m_pAnimationTimer; + + float m_fLastTickTime; // in ms private: - bool deltaSmallToFlip(const Vector2D& a, const Vector2D& b); - bool deltaSmallToFlip(const CHyprColor& a, const CHyprColor& b); - bool deltaSmallToFlip(const float& a, const float& b); - bool deltazero(const Vector2D& a, const Vector2D& b); - bool deltazero(const CHyprColor& a, const CHyprColor& b); - bool deltazero(const float& a, const float& b); - - std::unordered_map m_mBezierCurves; - - bool m_bTickScheduled = false; + bool m_bTickScheduled = false; // Anim stuff void animationPopin(PHLWINDOW, bool close = false, float minPerc = 0.f); void animationSlide(PHLWINDOW, std::string force = "", bool close = false); }; -inline std::unique_ptr g_pAnimationManager; +inline std::unique_ptr g_pAnimationManager; diff --git a/src/managers/KeybindManager.cpp b/src/managers/KeybindManager.cpp index d368d14c..fd4992eb 100644 --- a/src/managers/KeybindManager.cpp +++ b/src/managers/KeybindManager.cpp @@ -377,8 +377,8 @@ void CKeybindManager::switchToWindow(PHLWINDOW PWINDOWTOCHANGETO) { g_pCompositor->setWindowFullscreenInternal(PWINDOWTOCHANGETO, MODE); // warp the position + size animation, otherwise it looks weird. - PWINDOWTOCHANGETO->m_vRealPosition.warp(); - PWINDOWTOCHANGETO->m_vRealSize.warp(); + PWINDOWTOCHANGETO->m_vRealPosition->warp(); + PWINDOWTOCHANGETO->m_vRealSize->warp(); } else { updateRelativeCursorCoords(); g_pCompositor->focusWindow(PWINDOWTOCHANGETO); @@ -1070,8 +1070,8 @@ SDispatchResult CKeybindManager::centerWindow(std::string args) { if (args == "1") RESERVEDOFFSET = (PMONITOR->vecReservedTopLeft - PMONITOR->vecReservedBottomRight) / 2.f; - PWINDOW->m_vRealPosition = PMONITOR->middle() - PWINDOW->m_vRealSize.goal() / 2.f + RESERVEDOFFSET; - PWINDOW->m_vPosition = PWINDOW->m_vRealPosition.goal(); + *PWINDOW->m_vRealPosition = PMONITOR->middle() - PWINDOW->m_vRealSize->goal() / 2.f + RESERVEDOFFSET; + PWINDOW->m_vPosition = PWINDOW->m_vRealPosition->goal(); return {}; } @@ -1557,14 +1557,14 @@ SDispatchResult CKeybindManager::moveActiveTo(std::string args) { switch (arg) { case 'l': vPosx = PMONITOR->vecReservedTopLeft.x + BORDERSIZE + PMONITOR->vecPosition.x; break; - case 'r': vPosx = PMONITOR->vecSize.x - PMONITOR->vecReservedBottomRight.x - PLASTWINDOW->m_vRealSize.goal().x - BORDERSIZE + PMONITOR->vecPosition.x; break; + case 'r': vPosx = PMONITOR->vecSize.x - PMONITOR->vecReservedBottomRight.x - PLASTWINDOW->m_vRealSize->goal().x - BORDERSIZE + PMONITOR->vecPosition.x; break; case 't': case 'u': vPosy = PMONITOR->vecReservedTopLeft.y + BORDERSIZE + PMONITOR->vecPosition.y; break; case 'b': - case 'd': vPosy = PMONITOR->vecSize.y - PMONITOR->vecReservedBottomRight.y - PLASTWINDOW->m_vRealSize.goal().y - BORDERSIZE + PMONITOR->vecPosition.y; break; + case 'd': vPosy = PMONITOR->vecSize.y - PMONITOR->vecReservedBottomRight.y - PLASTWINDOW->m_vRealSize->goal().y - BORDERSIZE + PMONITOR->vecPosition.y; break; } - PLASTWINDOW->m_vRealPosition = Vector2D(vPosx.value_or(PLASTWINDOW->m_vRealPosition.goal().x), vPosy.value_or(PLASTWINDOW->m_vRealPosition.goal().y)); + *PLASTWINDOW->m_vRealPosition = Vector2D(vPosx.value_or(PLASTWINDOW->m_vRealPosition->goal().x), vPosy.value_or(PLASTWINDOW->m_vRealPosition->goal().y)); return {}; } @@ -1735,20 +1735,20 @@ SDispatchResult CKeybindManager::moveCursorToCorner(std::string arg) { switch (CORNER) { case 0: // bottom left - g_pCompositor->warpCursorTo({PWINDOW->m_vRealPosition.value().x, PWINDOW->m_vRealPosition.value().y + PWINDOW->m_vRealSize.value().y}, true); + g_pCompositor->warpCursorTo({PWINDOW->m_vRealPosition->value().x, PWINDOW->m_vRealPosition->value().y + PWINDOW->m_vRealSize->value().y}, true); break; case 1: // bottom right - g_pCompositor->warpCursorTo({PWINDOW->m_vRealPosition.value().x + PWINDOW->m_vRealSize.value().x, PWINDOW->m_vRealPosition.value().y + PWINDOW->m_vRealSize.value().y}, - true); + g_pCompositor->warpCursorTo( + {PWINDOW->m_vRealPosition->value().x + PWINDOW->m_vRealSize->value().x, PWINDOW->m_vRealPosition->value().y + PWINDOW->m_vRealSize->value().y}, true); break; case 2: // top right - g_pCompositor->warpCursorTo({PWINDOW->m_vRealPosition.value().x + PWINDOW->m_vRealSize.value().x, PWINDOW->m_vRealPosition.value().y}, true); + g_pCompositor->warpCursorTo({PWINDOW->m_vRealPosition->value().x + PWINDOW->m_vRealSize->value().x, PWINDOW->m_vRealPosition->value().y}, true); break; case 3: // top left - g_pCompositor->warpCursorTo({PWINDOW->m_vRealPosition.value().x, PWINDOW->m_vRealPosition.value().y}, true); + g_pCompositor->warpCursorTo({PWINDOW->m_vRealPosition->value().x, PWINDOW->m_vRealPosition->value().y}, true); break; } @@ -1817,18 +1817,18 @@ SDispatchResult CKeybindManager::workspaceOpt(std::string args) { continue; if (!w->m_bRequestsFloat && w->m_bIsFloating != PWORKSPACE->m_bDefaultFloating) { - const auto SAVEDPOS = w->m_vRealPosition.value(); - const auto SAVEDSIZE = w->m_vRealSize.value(); + const auto SAVEDPOS = w->m_vRealPosition->value(); + const auto SAVEDSIZE = w->m_vRealSize->value(); w->m_bIsFloating = PWORKSPACE->m_bDefaultFloating; g_pLayoutManager->getCurrentLayout()->changeWindowFloatingMode(w); if (PWORKSPACE->m_bDefaultFloating) { - w->m_vRealPosition.setValueAndWarp(SAVEDPOS); - w->m_vRealSize.setValueAndWarp(SAVEDSIZE); + w->m_vRealPosition->setValueAndWarp(SAVEDPOS); + w->m_vRealSize->setValueAndWarp(SAVEDSIZE); g_pXWaylandManager->setWindowSize(w, SAVEDSIZE); - w->m_vRealSize = w->m_vRealSize.value() + Vector2D(4, 4); - w->m_vRealPosition = w->m_vRealPosition.value() - Vector2D(2, 2); + *w->m_vRealSize = w->m_vRealSize->value() + Vector2D(4, 4); + *w->m_vRealPosition = w->m_vRealPosition->value() - Vector2D(2, 2); } } } @@ -2043,14 +2043,14 @@ SDispatchResult CKeybindManager::resizeActive(std::string args) { if (!PLASTWINDOW || PLASTWINDOW->isFullscreen()) return {}; - const auto SIZ = g_pCompositor->parseWindowVectorArgsRelative(args, PLASTWINDOW->m_vRealSize.goal()); + const auto SIZ = g_pCompositor->parseWindowVectorArgsRelative(args, PLASTWINDOW->m_vRealSize->goal()); if (SIZ.x < 1 || SIZ.y < 1) return {}; - g_pLayoutManager->getCurrentLayout()->resizeActiveWindow(SIZ - PLASTWINDOW->m_vRealSize.goal()); + g_pLayoutManager->getCurrentLayout()->resizeActiveWindow(SIZ - PLASTWINDOW->m_vRealSize->goal()); - if (PLASTWINDOW->m_vRealSize.goal().x > 1 && PLASTWINDOW->m_vRealSize.goal().y > 1) + if (PLASTWINDOW->m_vRealSize->goal().x > 1 && PLASTWINDOW->m_vRealSize->goal().y > 1) PLASTWINDOW->setHidden(false); return {}; @@ -2062,9 +2062,9 @@ SDispatchResult CKeybindManager::moveActive(std::string args) { if (!PLASTWINDOW || PLASTWINDOW->isFullscreen()) return {}; - const auto POS = g_pCompositor->parseWindowVectorArgsRelative(args, PLASTWINDOW->m_vRealPosition.goal()); + const auto POS = g_pCompositor->parseWindowVectorArgsRelative(args, PLASTWINDOW->m_vRealPosition->goal()); - g_pLayoutManager->getCurrentLayout()->moveActiveWindow(POS - PLASTWINDOW->m_vRealPosition.goal()); + g_pLayoutManager->getCurrentLayout()->moveActiveWindow(POS - PLASTWINDOW->m_vRealPosition->goal()); return {}; } @@ -2084,9 +2084,9 @@ SDispatchResult CKeybindManager::moveWindow(std::string args) { if (PWINDOW->isFullscreen()) return {}; - const auto POS = g_pCompositor->parseWindowVectorArgsRelative(MOVECMD, PWINDOW->m_vRealPosition.goal()); + const auto POS = g_pCompositor->parseWindowVectorArgsRelative(MOVECMD, PWINDOW->m_vRealPosition->goal()); - g_pLayoutManager->getCurrentLayout()->moveActiveWindow(POS - PWINDOW->m_vRealPosition.goal(), PWINDOW); + g_pLayoutManager->getCurrentLayout()->moveActiveWindow(POS - PWINDOW->m_vRealPosition->goal(), PWINDOW); return {}; } @@ -2106,14 +2106,14 @@ SDispatchResult CKeybindManager::resizeWindow(std::string args) { if (PWINDOW->isFullscreen()) return {}; - const auto SIZ = g_pCompositor->parseWindowVectorArgsRelative(MOVECMD, PWINDOW->m_vRealSize.goal()); + const auto SIZ = g_pCompositor->parseWindowVectorArgsRelative(MOVECMD, PWINDOW->m_vRealSize->goal()); if (SIZ.x < 1 || SIZ.y < 1) return {}; - g_pLayoutManager->getCurrentLayout()->resizeActiveWindow(SIZ - PWINDOW->m_vRealSize.goal(), CORNER_NONE, PWINDOW); + g_pLayoutManager->getCurrentLayout()->resizeActiveWindow(SIZ - PWINDOW->m_vRealSize->goal(), CORNER_NONE, PWINDOW); - if (PWINDOW->m_vRealSize.goal().x > 1 && PWINDOW->m_vRealSize.goal().y > 1) + if (PWINDOW->m_vRealSize->goal().x > 1 && PWINDOW->m_vRealSize->goal().y > 1) PWINDOW->setHidden(false); return {}; @@ -2192,8 +2192,8 @@ SDispatchResult CKeybindManager::focusWindow(std::string regexp) { g_pCompositor->setWindowFullscreenClient(PWINDOW, FSMODE); // warp the position + size animation, otherwise it looks weird. - PWINDOW->m_vRealPosition.warp(); - PWINDOW->m_vRealSize.warp(); + PWINDOW->m_vRealPosition->warp(); + PWINDOW->m_vRealSize->warp(); } } else g_pCompositor->focusWindow(PWINDOW); @@ -2311,7 +2311,7 @@ SDispatchResult CKeybindManager::pass(std::string regexp) { } } - const auto SL = PWINDOW->m_vRealPosition.goal() - g_pInputManager->getMouseCoordsInternal(); + const auto SL = PWINDOW->m_vRealPosition->goal() - g_pInputManager->getMouseCoordsInternal(); if (g_pKeybindManager->m_uLastCode != 0) g_pSeatManager->setKeyboardFocus(LASTKBSURF); @@ -2466,7 +2466,7 @@ SDispatchResult CKeybindManager::sendshortcut(std::string args) { } } - const auto SL = PWINDOW->m_vRealPosition.goal() - g_pInputManager->getMouseCoordsInternal(); + const auto SL = PWINDOW->m_vRealPosition->goal() - g_pInputManager->getMouseCoordsInternal(); if (!isMouse) g_pSeatManager->setKeyboardFocus(LASTSURFACE); diff --git a/src/managers/XWaylandManager.cpp b/src/managers/XWaylandManager.cpp index ca31752d..bc988f39 100644 --- a/src/managers/XWaylandManager.cpp +++ b/src/managers/XWaylandManager.cpp @@ -55,7 +55,7 @@ void CHyprXWaylandManager::activateWindow(PHLWINDOW pWindow, bool activate) { if (pWindow->m_bIsX11) { if (activate) { - setWindowSize(pWindow, pWindow->m_vRealSize.value()); // update xwayland output pos + setWindowSize(pWindow, pWindow->m_vRealSize->value()); // update xwayland output pos pWindow->m_pXWaylandSurface->setMinimized(false); if (!pWindow->isX11OverrideRedirect()) @@ -123,7 +123,7 @@ void CHyprXWaylandManager::setWindowSize(PHLWINDOW pWindow, Vector2D size, bool // calculate pos // TODO: this should be decoupled from setWindowSize IMO - Vector2D windowPos = pWindow->m_vRealPosition.value(); + Vector2D windowPos = pWindow->m_vRealPosition->value(); if (pWindow->m_bIsX11 && PMONITOR) { windowPos -= PMONITOR->vecPosition; // normalize to monitor @@ -273,4 +273,4 @@ Vector2D CHyprXWaylandManager::xwaylandToWaylandCoords(const Vector2D& coord) { result += pMonitor->vecPosition; return result; -} \ No newline at end of file +} diff --git a/src/managers/input/InputManager.cpp b/src/managers/input/InputManager.cpp index cccaa43e..8a50a7bf 100644 --- a/src/managers/input/InputManager.cpp +++ b/src/managers/input/InputManager.cpp @@ -137,7 +137,7 @@ void CInputManager::sendMotionEventsToFocused() { timespec now; clock_gettime(CLOCK_MONOTONIC, &now); - const auto LOCAL = getMouseCoordsInternal() - (PWINDOW ? PWINDOW->m_vRealPosition.goal() : (PLS ? Vector2D{PLS->geometry.x, PLS->geometry.y} : Vector2D{})); + const auto LOCAL = getMouseCoordsInternal() - (PWINDOW ? PWINDOW->m_vRealPosition->goal() : (PLS ? Vector2D{PLS->geometry.x, PLS->geometry.y} : Vector2D{})); m_bEmptyFocusCursorSet = false; @@ -243,7 +243,7 @@ void CInputManager::mouseMoveUnified(uint32_t time, bool refocus, bool mouse) { if (forcedFocus) { pFoundWindow = forcedFocus; - surfacePos = pFoundWindow->m_vRealPosition.value(); + surfacePos = pFoundWindow->m_vRealPosition->value(); foundSurface = pFoundWindow->m_pWLSurface->resource(); } @@ -320,7 +320,7 @@ void CInputManager::mouseMoveUnified(uint32_t time, bool refocus, bool mouse) { surfacePos = Vector2D(-1337, -1337); } else { foundSurface = pFoundWindow->m_pWLSurface->resource(); - surfacePos = pFoundWindow->m_vRealPosition.value(); + surfacePos = pFoundWindow->m_vRealPosition->value(); } } @@ -362,11 +362,11 @@ void CInputManager::mouseMoveUnified(uint32_t time, bool refocus, bool mouse) { foundSurface = g_pCompositor->vectorWindowToSurface(mouseCoords, pFoundWindow, surfaceCoords); if (!foundSurface) { foundSurface = pFoundWindow->m_pWLSurface->resource(); - surfacePos = pFoundWindow->m_vRealPosition.value(); + surfacePos = pFoundWindow->m_vRealPosition->value(); } } else { foundSurface = pFoundWindow->m_pWLSurface->resource(); - surfacePos = pFoundWindow->m_vRealPosition.value(); + surfacePos = pFoundWindow->m_vRealPosition->value(); } } } @@ -689,7 +689,7 @@ void CInputManager::processMouseDownNormal(const IPointer::SButtonEvent& e) { // TODO detect click on LS properly if (*PRESIZEONBORDER && !m_bLastFocusOnLS && e.state == WL_POINTER_BUTTON_STATE_PRESSED && (!w || !w->isX11OverrideRedirect())) { if (w && !w->isFullscreen()) { - const CBox real = {w->m_vRealPosition.value().x, w->m_vRealPosition.value().y, w->m_vRealSize.value().x, w->m_vRealSize.value().y}; + const CBox real = {w->m_vRealPosition->value().x, w->m_vRealPosition->value().y, w->m_vRealSize->value().x, w->m_vRealSize->value().y}; const CBox grab = {real.x - BORDER_GRAB_AREA, real.y - BORDER_GRAB_AREA, real.width + 2 * BORDER_GRAB_AREA, real.height + 2 * BORDER_GRAB_AREA}; if ((grab.containsPoint(mouseCoords) && (!real.containsPoint(mouseCoords) || w->isInCurvedCorner(mouseCoords.x, mouseCoords.y))) && !w->hasPopupAt(mouseCoords)) { diff --git a/src/managers/input/Swipe.cpp b/src/managers/input/Swipe.cpp index 6cfe5a24..3e03c4c7 100644 --- a/src/managers/input/Swipe.cpp +++ b/src/managers/input/Swipe.cpp @@ -38,7 +38,7 @@ void CInputManager::beginWorkspaceSwipe() { if (PWORKSPACE->m_bHasFullscreenWindow) { for (auto const& ls : g_pCompositor->m_pLastMonitor->m_aLayerSurfaceLayers[2]) { - ls->alpha = 1.f; + *ls->alpha = 1.f; } } } @@ -58,8 +58,8 @@ void CInputManager::endWorkspaceSwipe() { static auto PSWIPENEW = CConfigValue("gestures:workspace_swipe_create_new"); static auto PSWIPEUSER = CConfigValue("gestures:workspace_swipe_use_r"); static auto PWORKSPACEGAP = CConfigValue("general:gaps_workspaces"); - const bool VERTANIMS = m_sActiveSwipe.pWorkspaceBegin->m_vRenderOffset.getConfig()->pValues->internalStyle == "slidevert" || - m_sActiveSwipe.pWorkspaceBegin->m_vRenderOffset.getConfig()->pValues->internalStyle.starts_with("slidefadevert"); + const auto ANIMSTYLE = m_sActiveSwipe.pWorkspaceBegin->m_vRenderOffset->getStyle(); + const bool VERTANIMS = ANIMSTYLE == "slidevert" || ANIMSTYLE.starts_with("slidefadevert"); // commit auto workspaceIDLeft = getWorkspaceIDNameFromString((*PSWIPEUSER ? "r-1" : "m-1")).id; @@ -86,7 +86,7 @@ void CInputManager::endWorkspaceSwipe() { auto PWORKSPACER = g_pCompositor->getWorkspaceByID(workspaceIDRight); // not guaranteed if PSWIPENEW || PSWIPENUMBER auto PWORKSPACEL = g_pCompositor->getWorkspaceByID(workspaceIDLeft); // not guaranteed if PSWIPENUMBER - const auto RENDEROFFSETMIDDLE = m_sActiveSwipe.pWorkspaceBegin->m_vRenderOffset.value(); + const auto RENDEROFFSETMIDDLE = m_sActiveSwipe.pWorkspaceBegin->m_vRenderOffset->value(); const auto XDISTANCE = m_sActiveSwipe.pMonitor->vecSize.x + *PWORKSPACEGAP; const auto YDISTANCE = m_sActiveSwipe.pMonitor->vecSize.y + *PWORKSPACEGAP; @@ -97,35 +97,35 @@ void CInputManager::endWorkspaceSwipe() { // revert if (abs(m_sActiveSwipe.delta) < 2) { if (PWORKSPACEL) - PWORKSPACEL->m_vRenderOffset.setValueAndWarp(Vector2D(0, 0)); + PWORKSPACEL->m_vRenderOffset->setValueAndWarp(Vector2D(0, 0)); if (PWORKSPACER) - PWORKSPACER->m_vRenderOffset.setValueAndWarp(Vector2D(0, 0)); - m_sActiveSwipe.pWorkspaceBegin->m_vRenderOffset.setValueAndWarp(Vector2D(0, 0)); + PWORKSPACER->m_vRenderOffset->setValueAndWarp(Vector2D(0, 0)); + m_sActiveSwipe.pWorkspaceBegin->m_vRenderOffset->setValueAndWarp(Vector2D(0, 0)); } else { if (m_sActiveSwipe.delta < 0) { // to left if (PWORKSPACEL) { if (VERTANIMS) - PWORKSPACEL->m_vRenderOffset = Vector2D{0.0, -YDISTANCE}; + *PWORKSPACEL->m_vRenderOffset = Vector2D{0.0, -YDISTANCE}; else - PWORKSPACEL->m_vRenderOffset = Vector2D{-XDISTANCE, 0.0}; + *PWORKSPACEL->m_vRenderOffset = Vector2D{-XDISTANCE, 0.0}; } } else if (PWORKSPACER) { // to right if (VERTANIMS) - PWORKSPACER->m_vRenderOffset = Vector2D{0.0, YDISTANCE}; + *PWORKSPACER->m_vRenderOffset = Vector2D{0.0, YDISTANCE}; else - PWORKSPACER->m_vRenderOffset = Vector2D{XDISTANCE, 0.0}; + *PWORKSPACER->m_vRenderOffset = Vector2D{XDISTANCE, 0.0}; } - m_sActiveSwipe.pWorkspaceBegin->m_vRenderOffset = Vector2D(); + *m_sActiveSwipe.pWorkspaceBegin->m_vRenderOffset = Vector2D(); } pSwitchedTo = m_sActiveSwipe.pWorkspaceBegin; } else if (m_sActiveSwipe.delta < 0) { // switch to left - const auto RENDEROFFSET = PWORKSPACEL ? PWORKSPACEL->m_vRenderOffset.value() : Vector2D(); + const auto RENDEROFFSET = PWORKSPACEL ? PWORKSPACEL->m_vRenderOffset->value() : Vector2D(); if (PWORKSPACEL) m_sActiveSwipe.pMonitor->changeWorkspace(workspaceIDLeft); @@ -134,15 +134,15 @@ void CInputManager::endWorkspaceSwipe() { PWORKSPACEL = g_pCompositor->getWorkspaceByID(workspaceIDLeft); } - PWORKSPACEL->m_vRenderOffset.setValue(RENDEROFFSET); - PWORKSPACEL->m_fAlpha.setValueAndWarp(1.f); + PWORKSPACEL->m_vRenderOffset->setValue(RENDEROFFSET); + PWORKSPACEL->m_fAlpha->setValueAndWarp(1.f); - m_sActiveSwipe.pWorkspaceBegin->m_vRenderOffset.setValue(RENDEROFFSETMIDDLE); + m_sActiveSwipe.pWorkspaceBegin->m_vRenderOffset->setValue(RENDEROFFSETMIDDLE); if (VERTANIMS) - m_sActiveSwipe.pWorkspaceBegin->m_vRenderOffset = Vector2D(0.0, YDISTANCE); + *m_sActiveSwipe.pWorkspaceBegin->m_vRenderOffset = Vector2D(0.0, YDISTANCE); else - m_sActiveSwipe.pWorkspaceBegin->m_vRenderOffset = Vector2D(XDISTANCE, 0.0); - m_sActiveSwipe.pWorkspaceBegin->m_fAlpha.setValueAndWarp(1.f); + *m_sActiveSwipe.pWorkspaceBegin->m_vRenderOffset = Vector2D(XDISTANCE, 0.0); + m_sActiveSwipe.pWorkspaceBegin->m_fAlpha->setValueAndWarp(1.f); g_pInputManager->unconstrainMouse(); @@ -151,7 +151,7 @@ void CInputManager::endWorkspaceSwipe() { pSwitchedTo = PWORKSPACEL; } else { // switch to right - const auto RENDEROFFSET = PWORKSPACER ? PWORKSPACER->m_vRenderOffset.value() : Vector2D(); + const auto RENDEROFFSET = PWORKSPACER ? PWORKSPACER->m_vRenderOffset->value() : Vector2D(); if (PWORKSPACER) m_sActiveSwipe.pMonitor->changeWorkspace(workspaceIDRight); @@ -160,15 +160,15 @@ void CInputManager::endWorkspaceSwipe() { PWORKSPACER = g_pCompositor->getWorkspaceByID(workspaceIDRight); } - PWORKSPACER->m_vRenderOffset.setValue(RENDEROFFSET); - PWORKSPACER->m_fAlpha.setValueAndWarp(1.f); + PWORKSPACER->m_vRenderOffset->setValue(RENDEROFFSET); + PWORKSPACER->m_fAlpha->setValueAndWarp(1.f); - m_sActiveSwipe.pWorkspaceBegin->m_vRenderOffset.setValue(RENDEROFFSETMIDDLE); + m_sActiveSwipe.pWorkspaceBegin->m_vRenderOffset->setValue(RENDEROFFSETMIDDLE); if (VERTANIMS) - m_sActiveSwipe.pWorkspaceBegin->m_vRenderOffset = Vector2D(0.0, -YDISTANCE); + *m_sActiveSwipe.pWorkspaceBegin->m_vRenderOffset = Vector2D(0.0, -YDISTANCE); else - m_sActiveSwipe.pWorkspaceBegin->m_vRenderOffset = Vector2D(-XDISTANCE, 0.0); - m_sActiveSwipe.pWorkspaceBegin->m_fAlpha.setValueAndWarp(1.f); + *m_sActiveSwipe.pWorkspaceBegin->m_vRenderOffset = Vector2D(-XDISTANCE, 0.0); + m_sActiveSwipe.pWorkspaceBegin->m_fAlpha->setValueAndWarp(1.f); g_pInputManager->unconstrainMouse(); @@ -193,7 +193,7 @@ void CInputManager::endWorkspaceSwipe() { // apply alpha for (auto const& ls : g_pCompositor->m_pLastMonitor->m_aLayerSurfaceLayers[2]) { - ls->alpha = pSwitchedTo->m_bHasFullscreenWindow && pSwitchedTo->m_efFullscreenMode == FSMODE_FULLSCREEN ? 0.f : 1.f; + *ls->alpha = pSwitchedTo->m_bHasFullscreenWindow && pSwitchedTo->m_efFullscreenMode == FSMODE_FULLSCREEN ? 0.f : 1.f; } } @@ -202,30 +202,30 @@ void CInputManager::onSwipeUpdate(IPointer::SSwipeUpdateEvent e) { if (!m_sActiveSwipe.pWorkspaceBegin) return; - static auto PSWIPEINVR = CConfigValue("gestures:workspace_swipe_invert"); - const bool VERTANIMS = m_sActiveSwipe.pWorkspaceBegin->m_vRenderOffset.getConfig()->pValues->internalStyle == "slidevert" || - m_sActiveSwipe.pWorkspaceBegin->m_vRenderOffset.getConfig()->pValues->internalStyle.starts_with("slidefadevert"); + static auto PSWIPEINVR = CConfigValue("gestures:workspace_swipe_invert"); + const auto ANIMSTYLE = m_sActiveSwipe.pWorkspaceBegin->m_vRenderOffset->getStyle(); + const bool VERTANIMS = ANIMSTYLE == "slidevert" || ANIMSTYLE.starts_with("slidefadevert"); const double delta = m_sActiveSwipe.delta + (VERTANIMS ? (*PSWIPEINVR ? -e.delta.y : e.delta.y) : (*PSWIPEINVR ? -e.delta.x : e.delta.x)); updateWorkspaceSwipe(delta); } void CInputManager::updateWorkspaceSwipe(double delta) { - static auto PSWIPEDIST = CConfigValue("gestures:workspace_swipe_distance"); - static auto PSWIPENEW = CConfigValue("gestures:workspace_swipe_create_new"); - static auto PSWIPEDIRLOCK = CConfigValue("gestures:workspace_swipe_direction_lock"); - static auto PSWIPEDIRLOCKTHRESHOLD = CConfigValue("gestures:workspace_swipe_direction_lock_threshold"); - static auto PSWIPEFOREVER = CConfigValue("gestures:workspace_swipe_forever"); - static auto PSWIPEUSER = CConfigValue("gestures:workspace_swipe_use_r"); - static auto PWORKSPACEGAP = CConfigValue("general:gaps_workspaces"); + static auto PSWIPEDIST = CConfigValue("gestures:workspace_swipe_distance"); + static auto PSWIPENEW = CConfigValue("gestures:workspace_swipe_create_new"); + static auto PSWIPEDIRLOCK = CConfigValue("gestures:workspace_swipe_direction_lock"); + static auto PSWIPEDIRLOCKTHRESHOLD = CConfigValue("gestures:workspace_swipe_direction_lock_threshold"); + static auto PSWIPEFOREVER = CConfigValue("gestures:workspace_swipe_forever"); + static auto PSWIPEUSER = CConfigValue("gestures:workspace_swipe_use_r"); + static auto PWORKSPACEGAP = CConfigValue("general:gaps_workspaces"); - const auto SWIPEDISTANCE = std::clamp(*PSWIPEDIST, (int64_t)1LL, (int64_t)UINT32_MAX); - const auto XDISTANCE = m_sActiveSwipe.pMonitor->vecSize.x + *PWORKSPACEGAP; - const auto YDISTANCE = m_sActiveSwipe.pMonitor->vecSize.y + *PWORKSPACEGAP; - const bool VERTANIMS = m_sActiveSwipe.pWorkspaceBegin->m_vRenderOffset.getConfig()->pValues->internalStyle == "slidevert" || - m_sActiveSwipe.pWorkspaceBegin->m_vRenderOffset.getConfig()->pValues->internalStyle.starts_with("slidefadevert"); - const double d = m_sActiveSwipe.delta - delta; - m_sActiveSwipe.delta = delta; + const auto SWIPEDISTANCE = std::clamp(*PSWIPEDIST, (int64_t)1LL, (int64_t)UINT32_MAX); + const auto XDISTANCE = m_sActiveSwipe.pMonitor->vecSize.x + *PWORKSPACEGAP; + const auto YDISTANCE = m_sActiveSwipe.pMonitor->vecSize.y + *PWORKSPACEGAP; + const auto ANIMSTYLE = m_sActiveSwipe.pWorkspaceBegin->m_vRenderOffset->getStyle(); + const bool VERTANIMS = ANIMSTYLE == "slidevert" || ANIMSTYLE.starts_with("slidefadevert"); + const double d = m_sActiveSwipe.delta - delta; + m_sActiveSwipe.delta = delta; m_sActiveSwipe.avgSpeed = (m_sActiveSwipe.avgSpeed * m_sActiveSwipe.speedPoints + abs(d)) / (m_sActiveSwipe.speedPoints + 1); m_sActiveSwipe.speedPoints++; @@ -265,9 +265,9 @@ void CInputManager::updateWorkspaceSwipe(double delta) { g_pHyprRenderer->damageMonitor(m_sActiveSwipe.pMonitor.lock()); if (VERTANIMS) - m_sActiveSwipe.pWorkspaceBegin->m_vRenderOffset.setValueAndWarp(Vector2D(0.0, ((-m_sActiveSwipe.delta) / SWIPEDISTANCE) * YDISTANCE)); + m_sActiveSwipe.pWorkspaceBegin->m_vRenderOffset->setValueAndWarp(Vector2D(0.0, ((-m_sActiveSwipe.delta) / SWIPEDISTANCE) * YDISTANCE)); else - m_sActiveSwipe.pWorkspaceBegin->m_vRenderOffset.setValueAndWarp(Vector2D(((-m_sActiveSwipe.delta) / SWIPEDISTANCE) * XDISTANCE, 0.0)); + m_sActiveSwipe.pWorkspaceBegin->m_vRenderOffset->setValueAndWarp(Vector2D(((-m_sActiveSwipe.delta) / SWIPEDISTANCE) * XDISTANCE, 0.0)); m_sActiveSwipe.pWorkspaceBegin->updateWindowDecos(); return; @@ -277,23 +277,23 @@ void CInputManager::updateWorkspaceSwipe(double delta) { } PWORKSPACE->m_bForceRendering = true; - PWORKSPACE->m_fAlpha.setValueAndWarp(1.f); + PWORKSPACE->m_fAlpha->setValueAndWarp(1.f); if (workspaceIDLeft != workspaceIDRight && workspaceIDRight != m_sActiveSwipe.pWorkspaceBegin->m_iID) { const auto PWORKSPACER = g_pCompositor->getWorkspaceByID(workspaceIDRight); if (PWORKSPACER) { PWORKSPACER->m_bForceRendering = false; - PWORKSPACER->m_fAlpha.setValueAndWarp(0.f); + PWORKSPACER->m_fAlpha->setValueAndWarp(0.f); } } if (VERTANIMS) { - PWORKSPACE->m_vRenderOffset.setValueAndWarp(Vector2D(0.0, ((-m_sActiveSwipe.delta) / SWIPEDISTANCE) * YDISTANCE - YDISTANCE)); - m_sActiveSwipe.pWorkspaceBegin->m_vRenderOffset.setValueAndWarp(Vector2D(0.0, ((-m_sActiveSwipe.delta) / SWIPEDISTANCE) * YDISTANCE)); + PWORKSPACE->m_vRenderOffset->setValueAndWarp(Vector2D(0.0, ((-m_sActiveSwipe.delta) / SWIPEDISTANCE) * YDISTANCE - YDISTANCE)); + m_sActiveSwipe.pWorkspaceBegin->m_vRenderOffset->setValueAndWarp(Vector2D(0.0, ((-m_sActiveSwipe.delta) / SWIPEDISTANCE) * YDISTANCE)); } else { - PWORKSPACE->m_vRenderOffset.setValueAndWarp(Vector2D(((-m_sActiveSwipe.delta) / SWIPEDISTANCE) * XDISTANCE - XDISTANCE, 0.0)); - m_sActiveSwipe.pWorkspaceBegin->m_vRenderOffset.setValueAndWarp(Vector2D(((-m_sActiveSwipe.delta) / SWIPEDISTANCE) * XDISTANCE, 0.0)); + PWORKSPACE->m_vRenderOffset->setValueAndWarp(Vector2D(((-m_sActiveSwipe.delta) / SWIPEDISTANCE) * XDISTANCE - XDISTANCE, 0.0)); + m_sActiveSwipe.pWorkspaceBegin->m_vRenderOffset->setValueAndWarp(Vector2D(((-m_sActiveSwipe.delta) / SWIPEDISTANCE) * XDISTANCE, 0.0)); } PWORKSPACE->updateWindowDecos(); @@ -305,9 +305,9 @@ void CInputManager::updateWorkspaceSwipe(double delta) { g_pHyprRenderer->damageMonitor(m_sActiveSwipe.pMonitor.lock()); if (VERTANIMS) - m_sActiveSwipe.pWorkspaceBegin->m_vRenderOffset.setValueAndWarp(Vector2D(0.0, ((-m_sActiveSwipe.delta) / SWIPEDISTANCE) * YDISTANCE)); + m_sActiveSwipe.pWorkspaceBegin->m_vRenderOffset->setValueAndWarp(Vector2D(0.0, ((-m_sActiveSwipe.delta) / SWIPEDISTANCE) * YDISTANCE)); else - m_sActiveSwipe.pWorkspaceBegin->m_vRenderOffset.setValueAndWarp(Vector2D(((-m_sActiveSwipe.delta) / SWIPEDISTANCE) * XDISTANCE, 0.0)); + m_sActiveSwipe.pWorkspaceBegin->m_vRenderOffset->setValueAndWarp(Vector2D(((-m_sActiveSwipe.delta) / SWIPEDISTANCE) * XDISTANCE, 0.0)); m_sActiveSwipe.pWorkspaceBegin->updateWindowDecos(); return; @@ -317,23 +317,23 @@ void CInputManager::updateWorkspaceSwipe(double delta) { } PWORKSPACE->m_bForceRendering = true; - PWORKSPACE->m_fAlpha.setValueAndWarp(1.f); + PWORKSPACE->m_fAlpha->setValueAndWarp(1.f); if (workspaceIDLeft != workspaceIDRight && workspaceIDLeft != m_sActiveSwipe.pWorkspaceBegin->m_iID) { const auto PWORKSPACEL = g_pCompositor->getWorkspaceByID(workspaceIDLeft); if (PWORKSPACEL) { PWORKSPACEL->m_bForceRendering = false; - PWORKSPACEL->m_fAlpha.setValueAndWarp(0.f); + PWORKSPACEL->m_fAlpha->setValueAndWarp(0.f); } } if (VERTANIMS) { - PWORKSPACE->m_vRenderOffset.setValueAndWarp(Vector2D(0.0, ((-m_sActiveSwipe.delta) / SWIPEDISTANCE) * YDISTANCE + YDISTANCE)); - m_sActiveSwipe.pWorkspaceBegin->m_vRenderOffset.setValueAndWarp(Vector2D(0.0, ((-m_sActiveSwipe.delta) / SWIPEDISTANCE) * YDISTANCE)); + PWORKSPACE->m_vRenderOffset->setValueAndWarp(Vector2D(0.0, ((-m_sActiveSwipe.delta) / SWIPEDISTANCE) * YDISTANCE + YDISTANCE)); + m_sActiveSwipe.pWorkspaceBegin->m_vRenderOffset->setValueAndWarp(Vector2D(0.0, ((-m_sActiveSwipe.delta) / SWIPEDISTANCE) * YDISTANCE)); } else { - PWORKSPACE->m_vRenderOffset.setValueAndWarp(Vector2D(((-m_sActiveSwipe.delta) / SWIPEDISTANCE) * XDISTANCE + XDISTANCE, 0.0)); - m_sActiveSwipe.pWorkspaceBegin->m_vRenderOffset.setValueAndWarp(Vector2D(((-m_sActiveSwipe.delta) / SWIPEDISTANCE) * XDISTANCE, 0.0)); + PWORKSPACE->m_vRenderOffset->setValueAndWarp(Vector2D(((-m_sActiveSwipe.delta) / SWIPEDISTANCE) * XDISTANCE + XDISTANCE, 0.0)); + m_sActiveSwipe.pWorkspaceBegin->m_vRenderOffset->setValueAndWarp(Vector2D(((-m_sActiveSwipe.delta) / SWIPEDISTANCE) * XDISTANCE, 0.0)); } PWORKSPACE->updateWindowDecos(); diff --git a/src/managers/input/Tablets.cpp b/src/managers/input/Tablets.cpp index aba54387..d7ebfe87 100644 --- a/src/managers/input/Tablets.cpp +++ b/src/managers/input/Tablets.cpp @@ -69,7 +69,7 @@ static void refocusTablet(SP tab, SP tool, bool motion = f // yes, this technically ignores any regions set by the app. Too bad! if (LASTHLSURFACE->getWindow()) - local = tool->absolutePos * LASTHLSURFACE->getWindow()->m_vRealSize.goal(); + local = tool->absolutePos * LASTHLSURFACE->getWindow()->m_vRealSize->goal(); else local = tool->absolutePos * BOX->size(); diff --git a/src/managers/input/Touch.cpp b/src/managers/input/Touch.cpp index 4e3980aa..7212ba61 100644 --- a/src/managers/input/Touch.cpp +++ b/src/managers/input/Touch.cpp @@ -3,6 +3,7 @@ #include "../../config/ConfigValue.hpp" #include "../../devices/ITouch.hpp" #include "../SeatManager.hpp" +#include "managers/AnimationManager.hpp" void CInputManager::onTouchDown(ITouch::SDownEvent e) { m_bLastInputTouch = true; @@ -36,9 +37,9 @@ void CInputManager::onTouchDown(ITouch::SDownEvent e) { return; // TODO: Don't swipe if you touched a floating window. } else if (*PSWIPETOUCH && (m_pFoundLSToFocus.expired() || m_pFoundLSToFocus->layer <= 1)) { - const auto PWORKSPACE = PMONITOR->activeWorkspace; - const bool VERTANIMS = PWORKSPACE->m_vRenderOffset.getConfig()->pValues->internalStyle == "slidevert" || - PWORKSPACE->m_vRenderOffset.getConfig()->pValues->internalStyle.starts_with("slidefadevert"); + const auto PWORKSPACE = PMONITOR->activeWorkspace; + const auto STYLE = PWORKSPACE->m_vRenderOffset->getStyle(); + const bool VERTANIMS = STYLE == "slidevert" || STYLE.starts_with("slidefadevert"); const double TARGETLEFT = ((VERTANIMS ? gapsOut.top : gapsOut.left) + *PBORDERSIZE) / (VERTANIMS ? PMONITOR->vecSize.y : PMONITOR->vecSize.x); const double TARGETRIGHT = 1 - (((VERTANIMS ? gapsOut.bottom : gapsOut.right) + *PBORDERSIZE) / (VERTANIMS ? PMONITOR->vecSize.y : PMONITOR->vecSize.x)); const double POSITION = (VERTANIMS ? e.pos.y : e.pos.x); @@ -62,8 +63,8 @@ void CInputManager::onTouchDown(ITouch::SDownEvent e) { if (!m_sTouchData.touchFocusWindow.expired()) { if (m_sTouchData.touchFocusWindow->m_bIsX11) { - local = (g_pInputManager->getMouseCoordsInternal() - m_sTouchData.touchFocusWindow->m_vRealPosition.goal()) * m_sTouchData.touchFocusWindow->m_fX11SurfaceScaledBy; - m_sTouchData.touchSurfaceOrigin = m_sTouchData.touchFocusWindow->m_vRealPosition.goal(); + local = (g_pInputManager->getMouseCoordsInternal() - m_sTouchData.touchFocusWindow->m_vRealPosition->goal()) * m_sTouchData.touchFocusWindow->m_fX11SurfaceScaledBy; + m_sTouchData.touchSurfaceOrigin = m_sTouchData.touchFocusWindow->m_vRealPosition->goal(); } else { g_pCompositor->vectorWindowToSurface(g_pInputManager->getMouseCoordsInternal(), m_sTouchData.touchFocusWindow.lock(), local); m_sTouchData.touchSurfaceOrigin = g_pInputManager->getMouseCoordsInternal() - local; @@ -101,8 +102,9 @@ void CInputManager::onTouchMove(ITouch::SMotionEvent e) { // Do nothing if this is using a different finger. if (e.touchID != m_sActiveSwipe.touch_id) return; - const bool VERTANIMS = m_sActiveSwipe.pWorkspaceBegin->m_vRenderOffset.getConfig()->pValues->internalStyle == "slidevert" || - m_sActiveSwipe.pWorkspaceBegin->m_vRenderOffset.getConfig()->pValues->internalStyle.starts_with("slidefadevert"); + + const auto ANIMSTYLE = m_sActiveSwipe.pWorkspaceBegin->m_vRenderOffset->getStyle(); + const bool VERTANIMS = ANIMSTYLE == "slidevert" || ANIMSTYLE.starts_with("slidefadevert"); static auto PSWIPEINVR = CConfigValue("gestures:workspace_swipe_touch_invert"); static auto PSWIPEDIST = CConfigValue("gestures:workspace_swipe_distance"); const auto SWIPEDISTANCE = std::clamp(*PSWIPEDIST, (int64_t)1LL, (int64_t)UINT32_MAX); diff --git a/src/protocols/CTMControl.cpp b/src/protocols/CTMControl.cpp index 250c6326..fd7cdcd6 100644 --- a/src/protocols/CTMControl.cpp +++ b/src/protocols/CTMControl.cpp @@ -3,6 +3,7 @@ #include "../render/Renderer.hpp" #include "core/Output.hpp" #include "../config/ConfigValue.hpp" +#include "managers/AnimationManager.hpp" CHyprlandCTMControlResource::CHyprlandCTMControlResource(SP resource_) : resource(resource_) { if (!good()) @@ -92,8 +93,7 @@ bool CHyprlandCTMControlProtocol::isCTMAnimationEnabled() { } CHyprlandCTMControlProtocol::SCTMData::SCTMData() { - progress.create(g_pConfigManager->getAnimationPropertyConfig("__internal_fadeCTM"), AVARDAMAGE_NONE); - progress.setValueAndWarp(0.F); + g_pAnimationManager->createAnimation(0.f, progress, g_pConfigManager->getAnimationPropertyConfig("__internal_fadeCTM"), AVARDAMAGE_NONE); } void CHyprlandCTMControlProtocol::setCTM(PHLMONITOR monitor, const Mat3x3& ctm) { @@ -112,18 +112,18 @@ void CHyprlandCTMControlProtocol::setCTM(PHLMONITOR monitor, const Mat3x3& ctm) data->ctmFrom = data->ctmTo; data->ctmTo = ctm; - data->progress.setValueAndWarp(0.F); - data->progress = 1.F; + data->progress->setValueAndWarp(0.F); + *data->progress = 1.F; monitor->setCTM(data->ctmFrom); - data->progress.setUpdateCallback([monitor = PHLMONITORREF{monitor}, this](void* self) { + data->progress->setUpdateCallback([monitor = PHLMONITORREF{monitor}, this](auto) { if (!monitor || !m_mCTMDatas.contains(monitor)) return; auto& data = m_mCTMDatas.at(monitor); const auto from = data->ctmFrom.getMatrix(); const auto to = data->ctmTo.getMatrix(); - const auto PROGRESS = data->progress.getPercent(); + const auto PROGRESS = data->progress->getPercent(); static const auto lerp = [](const float one, const float two, const float progress) -> float { return one + (two - one) * progress; }; @@ -135,7 +135,7 @@ void CHyprlandCTMControlProtocol::setCTM(PHLMONITOR monitor, const Mat3x3& ctm) monitor->setCTM(mtx); }); - data->progress.setCallbackOnEnd([monitor = PHLMONITORREF{monitor}, this](void* self) { + data->progress->setCallbackOnEnd([monitor = PHLMONITORREF{monitor}, this](auto) { if (!monitor || !m_mCTMDatas.contains(monitor)) { monitor->setCTM(Mat3x3::identity()); return; diff --git a/src/protocols/CTMControl.hpp b/src/protocols/CTMControl.hpp index dea2c258..2639d176 100644 --- a/src/protocols/CTMControl.hpp +++ b/src/protocols/CTMControl.hpp @@ -42,8 +42,8 @@ class CHyprlandCTMControlProtocol : public IWaylandProtocol { // struct SCTMData { SCTMData(); - Mat3x3 ctmFrom = Mat3x3::identity(), ctmTo = Mat3x3::identity(); - CAnimatedVariable progress; + Mat3x3 ctmFrom = Mat3x3::identity(), ctmTo = Mat3x3::identity(); + PHLANIMVAR progress; }; std::map> m_mCTMDatas; diff --git a/src/protocols/ToplevelExport.cpp b/src/protocols/ToplevelExport.cpp index f5fbaa0c..2c934b40 100644 --- a/src/protocols/ToplevelExport.cpp +++ b/src/protocols/ToplevelExport.cpp @@ -119,7 +119,7 @@ CToplevelExportFrame::CToplevelExportFrame(SP re dmabufFormat = PMONITOR->output->state->state().drmFormat; - box = {0, 0, (int)(pWindow->m_vRealSize.value().x * PMONITOR->scale), (int)(pWindow->m_vRealSize.value().y * PMONITOR->scale)}; + box = {0, 0, (int)(pWindow->m_vRealSize->value().x * PMONITOR->scale), (int)(pWindow->m_vRealSize->value().y * PMONITOR->scale)}; box.transform(wlTransformToHyprutils(PMONITOR->transform), PMONITOR->vecTransformedSize.x, PMONITOR->vecTransformedSize.y).round(); @@ -263,7 +263,7 @@ bool CToplevelExportFrame::copyShm(timespec* now) { g_pHyprRenderer->m_bBlockSurfaceFeedback = false; if (overlayCursor) - g_pPointerManager->renderSoftwareCursorsFor(PMONITOR->self.lock(), now, fakeDamage, g_pInputManager->getMouseCoordsInternal() - pWindow->m_vRealPosition.value()); + g_pPointerManager->renderSoftwareCursorsFor(PMONITOR->self.lock(), now, fakeDamage, g_pInputManager->getMouseCoordsInternal() - pWindow->m_vRealPosition->value()); const auto PFORMAT = NFormatUtils::getPixelFormatFromDRM(shm.format); if (!PFORMAT) { @@ -315,7 +315,7 @@ bool CToplevelExportFrame::copyDmabuf(timespec* now) { g_pHyprRenderer->m_bBlockSurfaceFeedback = false; if (overlayCursor) - g_pPointerManager->renderSoftwareCursorsFor(PMONITOR->self.lock(), now, fakeDamage, g_pInputManager->getMouseCoordsInternal() - pWindow->m_vRealPosition.value()); + g_pPointerManager->renderSoftwareCursorsFor(PMONITOR->self.lock(), now, fakeDamage, g_pInputManager->getMouseCoordsInternal() - pWindow->m_vRealPosition->value()); g_pHyprOpenGL->m_RenderData.blockScreenShader = true; g_pHyprRenderer->endRender(); @@ -386,7 +386,7 @@ void CToplevelExportProtocol::onOutputCommit(PHLMONITOR pMonitor) { if (pMonitor != PWINDOW->m_pMonitor.lock()) continue; - CBox geometry = {PWINDOW->m_vRealPosition.value().x, PWINDOW->m_vRealPosition.value().y, PWINDOW->m_vRealSize.value().x, PWINDOW->m_vRealSize.value().y}; + CBox geometry = {PWINDOW->m_vRealPosition->value().x, PWINDOW->m_vRealPosition->value().y, PWINDOW->m_vRealSize->value().x, PWINDOW->m_vRealSize->value().y}; if (geometry.intersection({pMonitor->vecPosition, pMonitor->vecSize}).empty()) continue; diff --git a/src/render/OpenGL.cpp b/src/render/OpenGL.cpp index 94b70acf..93ab5fdf 100644 --- a/src/render/OpenGL.cpp +++ b/src/render/OpenGL.cpp @@ -713,7 +713,7 @@ bool CHyprOpenGLImpl::passRequiresIntrospection(PHLMONITOR pMonitor) { if (!ws->m_bIsSpecialWorkspace || ws->m_pMonitor != pMonitor) continue; - if (ws->m_fAlpha.value() == 0) + if (ws->m_fAlpha->value() == 0) continue; return true; @@ -1517,7 +1517,7 @@ void CHyprOpenGLImpl::renderTextureInternalWithDamage(SP tex, CBox* pB if (allowDim && m_RenderData.currentWindow) { glUniform1i(shader->applyTint, 1); - const auto DIM = m_RenderData.currentWindow->m_fDimPercent.value(); + const auto DIM = m_RenderData.currentWindow->m_fDimPercent->value(); glUniform3f(shader->tint, 1.f - DIM, 1.f - DIM, 1.f - DIM); } else { glUniform1i(shader->applyTint, 0); @@ -1931,7 +1931,7 @@ void CHyprOpenGLImpl::preRender(PHLMONITOR pMonitor) { const auto PSURFACE = pWindow->m_pWLSurface->resource(); const auto PWORKSPACE = pWindow->m_pWorkspace; - const float A = pWindow->m_fAlpha.value() * pWindow->m_fActiveInactiveAlpha.value() * PWORKSPACE->m_fAlpha.value(); + const float A = pWindow->m_fAlpha->value() * pWindow->m_fActiveInactiveAlpha->value() * PWORKSPACE->m_fAlpha->value(); if (A >= 1.f) { // if (PSURFACE->opaque) @@ -1969,7 +1969,7 @@ void CHyprOpenGLImpl::preRender(PHLMONITOR pMonitor) { if (!ls->layerSurface || ls->xray != 1) continue; - // if (ls->layerSurface->surface->opaque && ls->alpha.value() >= 1.f) + // if (ls->layerSurface->surface->opaque && ls->alpha->value() >= 1.f) // continue; hasWindows = true; diff --git a/src/render/Renderer.cpp b/src/render/Renderer.cpp index d154e64a..4d93d92f 100644 --- a/src/render/Renderer.cpp +++ b/src/render/Renderer.cpp @@ -172,21 +172,21 @@ bool CHyprRenderer::shouldRenderWindow(PHLWINDOW pWindow, PHLMONITOR pMonitor) { return true; // if the window is being moved to a workspace that is not invisible, and the alpha is > 0.F, render it. - if (pWindow->m_iMonitorMovedFrom != -1 && pWindow->m_fMovingToWorkspaceAlpha.isBeingAnimated() && pWindow->m_fMovingToWorkspaceAlpha.value() > 0.F && pWindow->m_pWorkspace && + if (pWindow->m_iMonitorMovedFrom != -1 && pWindow->m_fMovingToWorkspaceAlpha->isBeingAnimated() && pWindow->m_fMovingToWorkspaceAlpha->value() > 0.F && pWindow->m_pWorkspace && !pWindow->m_pWorkspace->isVisible()) return true; const auto PWINDOWWORKSPACE = pWindow->m_pWorkspace; if (PWINDOWWORKSPACE && PWINDOWWORKSPACE->m_pMonitor == pMonitor) { - if (PWINDOWWORKSPACE->m_vRenderOffset.isBeingAnimated() || PWINDOWWORKSPACE->m_fAlpha.isBeingAnimated() || PWINDOWWORKSPACE->m_bForceRendering) + if (PWINDOWWORKSPACE->m_vRenderOffset->isBeingAnimated() || PWINDOWWORKSPACE->m_fAlpha->isBeingAnimated() || PWINDOWWORKSPACE->m_bForceRendering) return true; // if hidden behind fullscreen if (PWINDOWWORKSPACE->m_bHasFullscreenWindow && !pWindow->isFullscreen() && (!pWindow->m_bIsFloating || !pWindow->m_bCreatedOverFullscreen) && - pWindow->m_fAlpha.value() == 0) + pWindow->m_fAlpha->value() == 0) return false; - if (!PWINDOWWORKSPACE->m_vRenderOffset.isBeingAnimated() && !PWINDOWWORKSPACE->m_fAlpha.isBeingAnimated() && !PWINDOWWORKSPACE->isVisible()) + if (!PWINDOWWORKSPACE->m_vRenderOffset->isBeingAnimated() && !PWINDOWWORKSPACE->m_fAlpha->isBeingAnimated() && !PWINDOWWORKSPACE->isVisible()) return false; } @@ -204,17 +204,17 @@ bool CHyprRenderer::shouldRenderWindow(PHLWINDOW pWindow, PHLMONITOR pMonitor) { return true; // if window is tiled and it's flying in, don't render on other mons (for slide) - if (!pWindow->m_bIsFloating && pWindow->m_vRealPosition.isBeingAnimated() && pWindow->m_bAnimatingIn && pWindow->m_pMonitor != pMonitor) + if (!pWindow->m_bIsFloating && pWindow->m_vRealPosition->isBeingAnimated() && pWindow->m_bAnimatingIn && pWindow->m_pMonitor != pMonitor) return false; - if (pWindow->m_vRealPosition.isBeingAnimated()) { - if (PWINDOWWORKSPACE && !PWINDOWWORKSPACE->m_bIsSpecialWorkspace && PWINDOWWORKSPACE->m_vRenderOffset.isBeingAnimated()) + if (pWindow->m_vRealPosition->isBeingAnimated()) { + if (PWINDOWWORKSPACE && !PWINDOWWORKSPACE->m_bIsSpecialWorkspace && PWINDOWWORKSPACE->m_vRenderOffset->isBeingAnimated()) return false; // render window if window and monitor intersect // (when moving out of or through a monitor) CBox windowBox = pWindow->getFullWindowBoundingBox(); - if (PWINDOWWORKSPACE && PWINDOWWORKSPACE->m_vRenderOffset.isBeingAnimated()) - windowBox.translate(PWINDOWWORKSPACE->m_vRenderOffset.value()); + if (PWINDOWWORKSPACE && PWINDOWWORKSPACE->m_vRenderOffset->isBeingAnimated()) + windowBox.translate(PWINDOWWORKSPACE->m_vRenderOffset->value()); windowBox.translate(pWindow->m_vFloatingOffset); const CBox monitorBox = {pMonitor->vecPosition, pMonitor->vecSize}; @@ -242,7 +242,7 @@ bool CHyprRenderer::shouldRenderWindow(PHLWINDOW pWindow) { return true; for (auto const& m : g_pCompositor->m_vMonitors) { - if (PWORKSPACE && PWORKSPACE->m_pMonitor == m && (PWORKSPACE->m_vRenderOffset.isBeingAnimated() || PWORKSPACE->m_fAlpha.isBeingAnimated())) + if (PWORKSPACE && PWORKSPACE->m_pMonitor == m && (PWORKSPACE->m_vRenderOffset->isBeingAnimated() || PWORKSPACE->m_fAlpha->isBeingAnimated())) return true; if (m->activeSpecialWorkspace && pWindow->onSpecialWorkspace()) @@ -262,7 +262,7 @@ void CHyprRenderer::renderWorkspaceWindowsFullscreen(PHLMONITOR pMonitor, PHLWOR if (!shouldRenderWindow(w, pMonitor)) continue; - if (w->m_fAlpha.value() == 0.f) + if (w->m_fAlpha->value() == 0.f) continue; if (w->isFullscreen() || w->m_bIsFloating) @@ -279,7 +279,7 @@ void CHyprRenderer::renderWorkspaceWindowsFullscreen(PHLMONITOR pMonitor, PHLWOR if (!shouldRenderWindow(w, pMonitor)) continue; - if (w->m_fAlpha.value() == 0.f) + if (w->m_fAlpha->value() == 0.f) continue; if (w->isFullscreen() || !w->m_bIsFloating) @@ -299,7 +299,7 @@ void CHyprRenderer::renderWorkspaceWindowsFullscreen(PHLMONITOR pMonitor, PHLWOR const auto PWORKSPACE = w->m_pWorkspace; if (w->m_pWorkspace != pWorkspace || !w->isFullscreen()) { - if (!(PWORKSPACE && (PWORKSPACE->m_vRenderOffset.isBeingAnimated() || PWORKSPACE->m_fAlpha.isBeingAnimated() || PWORKSPACE->m_bForceRendering))) + if (!(PWORKSPACE && (PWORKSPACE->m_vRenderOffset->isBeingAnimated() || PWORKSPACE->m_fAlpha->isBeingAnimated() || PWORKSPACE->m_bForceRendering))) continue; if (w->m_pMonitor != pMonitor) @@ -432,12 +432,12 @@ void CHyprRenderer::renderWindow(PHLWINDOW pWindow, PHLMONITOR pMonitor, timespe TRACY_GPU_ZONE("RenderWindow"); const auto PWORKSPACE = pWindow->m_pWorkspace; - const auto REALPOS = pWindow->m_vRealPosition.value() + (pWindow->m_bPinned ? Vector2D{} : PWORKSPACE->m_vRenderOffset.value()); + const auto REALPOS = pWindow->m_vRealPosition->value() + (pWindow->m_bPinned ? Vector2D{} : PWORKSPACE->m_vRenderOffset->value()); static auto PDIMAROUND = CConfigValue("decoration:dim_around"); static auto PBLUR = CConfigValue("decoration:blur:enabled"); CSurfacePassElement::SRenderData renderdata = {pMonitor, time}; - CBox textureBox = {REALPOS.x, REALPOS.y, std::max(pWindow->m_vRealSize.value().x, 5.0), std::max(pWindow->m_vRealSize.value().y, 5.0)}; + CBox textureBox = {REALPOS.x, REALPOS.y, std::max(pWindow->m_vRealSize->value().x, 5.0), std::max(pWindow->m_vRealSize->value().y, 5.0)}; renderdata.pos.x = textureBox.x; renderdata.pos.y = textureBox.y; @@ -458,9 +458,9 @@ void CHyprRenderer::renderWindow(PHLWINDOW pWindow, PHLMONITOR pMonitor, timespe renderdata.surface = pWindow->m_pWLSurface->resource(); renderdata.dontRound = pWindow->isEffectiveInternalFSMode(FSMODE_FULLSCREEN) || pWindow->m_sWindowData.noRounding.valueOrDefault(); - renderdata.fadeAlpha = pWindow->m_fAlpha.value() * (pWindow->m_bPinned || USE_WORKSPACE_FADE_ALPHA ? 1.f : PWORKSPACE->m_fAlpha.value()) * - (USE_WORKSPACE_FADE_ALPHA ? pWindow->m_fMovingToWorkspaceAlpha.value() : 1.F) * pWindow->m_fMovingFromWorkspaceAlpha.value(); - renderdata.alpha = pWindow->m_fActiveInactiveAlpha.value(); + renderdata.fadeAlpha = pWindow->m_fAlpha->value() * (pWindow->m_bPinned || USE_WORKSPACE_FADE_ALPHA ? 1.f : PWORKSPACE->m_fAlpha->value()) * + (USE_WORKSPACE_FADE_ALPHA ? pWindow->m_fMovingToWorkspaceAlpha->value() : 1.F) * pWindow->m_fMovingFromWorkspaceAlpha->value(); + renderdata.alpha = pWindow->m_fActiveInactiveAlpha->value(); renderdata.decorate = decorate && !pWindow->m_bX11DoesntWantBorders && !pWindow->isEffectiveInternalFSMode(FSMODE_FULLSCREEN); renderdata.rounding = ignoreAllGeometry || renderdata.dontRound ? 0 : pWindow->rounding() * pMonitor->scale; renderdata.roundingPower = ignoreAllGeometry || renderdata.dontRound ? 2.0f : pWindow->roundingPower(); @@ -492,9 +492,9 @@ void CHyprRenderer::renderWindow(PHLWINDOW pWindow, PHLMONITOR pMonitor, timespe renderdata.pos.y += pWindow->m_vFloatingOffset.y; // if window is floating and we have a slide animation, clip it to its full bb - if (!ignorePosition && pWindow->m_bIsFloating && !pWindow->isFullscreen() && PWORKSPACE->m_vRenderOffset.isBeingAnimated() && !pWindow->m_bPinned) { + if (!ignorePosition && pWindow->m_bIsFloating && !pWindow->isFullscreen() && PWORKSPACE->m_vRenderOffset->isBeingAnimated() && !pWindow->m_bPinned) { CRegion rg = - pWindow->getFullWindowBoundingBox().translate(-pMonitor->vecPosition + PWORKSPACE->m_vRenderOffset.value() + pWindow->m_vFloatingOffset).scale(pMonitor->scale); + pWindow->getFullWindowBoundingBox().translate(-pMonitor->vecPosition + PWORKSPACE->m_vRenderOffset->value() + pWindow->m_vFloatingOffset).scale(pMonitor->scale); renderdata.clipBox = rg.getExtents(); } @@ -657,7 +657,7 @@ void CHyprRenderer::renderLayer(PHLLS pLayer, PHLMONITOR pMonitor, timespec* tim if (*PDIMAROUND && pLayer->dimAround && !m_bRenderingSnapshot && !popups) { CRectPassElement::SRectData data; data.box = {0, 0, g_pHyprOpenGL->m_RenderData.pMonitor->vecTransformedSize.x, g_pHyprOpenGL->m_RenderData.pMonitor->vecTransformedSize.y}; - data.color = CHyprColor(0, 0, 0, *PDIMAROUND * pLayer->alpha.value()); + data.color = CHyprColor(0, 0, 0, *PDIMAROUND * pLayer->alpha->value()); m_sRenderPass.add(makeShared(data)); } @@ -671,11 +671,11 @@ void CHyprRenderer::renderLayer(PHLLS pLayer, PHLMONITOR pMonitor, timespec* tim TRACY_GPU_ZONE("RenderLayer"); - const auto REALPOS = pLayer->realPosition.value(); - const auto REALSIZ = pLayer->realSize.value(); + const auto REALPOS = pLayer->realPosition->value(); + const auto REALSIZ = pLayer->realSize->value(); CSurfacePassElement::SRenderData renderdata = {pMonitor, time, REALPOS}; - renderdata.fadeAlpha = pLayer->alpha.value(); + renderdata.fadeAlpha = pLayer->alpha->value(); renderdata.blur = pLayer->forceBlur && *PBLUR; renderdata.surface = pLayer->surface->resource(); renderdata.decorate = false; @@ -866,8 +866,8 @@ void CHyprRenderer::renderAllClientsForWorkspace(PHLMONITOR pMonitor, PHLWORKSPA // and then special for (auto const& ws : g_pCompositor->m_vWorkspaces) { - if (ws->m_pMonitor == pMonitor && ws->m_fAlpha.value() > 0.f && ws->m_bIsSpecialWorkspace) { - const auto SPECIALANIMPROGRS = ws->m_vRenderOffset.isBeingAnimated() ? ws->m_vRenderOffset.getCurveValue() : ws->m_fAlpha.getCurveValue(); + if (ws->m_pMonitor == pMonitor && ws->m_fAlpha->value() > 0.f && ws->m_bIsSpecialWorkspace) { + const auto SPECIALANIMPROGRS = ws->m_vRenderOffset->isBeingAnimated() ? ws->m_vRenderOffset->getCurveValue() : ws->m_fAlpha->getCurveValue(); const bool ANIMOUT = !pMonitor->activeSpecialWorkspace; if (*PDIMSPECIAL != 0.f) { @@ -894,7 +894,7 @@ void CHyprRenderer::renderAllClientsForWorkspace(PHLMONITOR pMonitor, PHLWORKSPA // special for (auto const& ws : g_pCompositor->m_vWorkspaces) { - if (ws->m_fAlpha.value() > 0.f && ws->m_bIsSpecialWorkspace) { + if (ws->m_fAlpha->value() > 0.f && ws->m_bIsSpecialWorkspace) { if (ws->m_bHasFullscreenWindow) renderWorkspaceWindowsFullscreen(pMonitor, ws, time); else @@ -1617,8 +1617,8 @@ void CHyprRenderer::arrangeLayerArray(PHLMONITOR pMonitor, const std::vectorlayerSurface->configure(box.size()); - ls->realPosition = box.pos(); - ls->realSize = box.size(); + *ls->realPosition = box.pos(); + *ls->realSize = box.size(); } } @@ -1727,8 +1727,8 @@ void CHyprRenderer::damageWindow(PHLWINDOW pWindow, bool forceFull) { CBox windowBox = pWindow->getFullWindowBoundingBox(); const auto PWINDOWWORKSPACE = pWindow->m_pWorkspace; - if (PWINDOWWORKSPACE && PWINDOWWORKSPACE->m_vRenderOffset.isBeingAnimated() && !pWindow->m_bPinned) - windowBox.translate(PWINDOWWORKSPACE->m_vRenderOffset.value()); + if (PWINDOWWORKSPACE && PWINDOWWORKSPACE->m_vRenderOffset->isBeingAnimated() && !pWindow->m_bPinned) + windowBox.translate(PWINDOWWORKSPACE->m_vRenderOffset->value()); windowBox.translate(pWindow->m_vFloatingOffset); for (auto const& m : g_pCompositor->m_vMonitors) { @@ -1977,8 +1977,8 @@ void CHyprRenderer::recheckSolitaryForMonitor(PHLMONITOR pMonitor) { const auto PWORKSPACE = pMonitor->activeWorkspace; - if (!PWORKSPACE || !PWORKSPACE->m_bHasFullscreenWindow || PROTO::data->dndActive() || pMonitor->activeSpecialWorkspace || PWORKSPACE->m_fAlpha.value() != 1.f || - PWORKSPACE->m_vRenderOffset.value() != Vector2D{}) + if (!PWORKSPACE || !PWORKSPACE->m_bHasFullscreenWindow || PROTO::data->dndActive() || pMonitor->activeSpecialWorkspace || PWORKSPACE->m_fAlpha->value() != 1.f || + PWORKSPACE->m_vRenderOffset->value() != Vector2D{}) return; const auto PCANDIDATE = PWORKSPACE->getFullscreenWindow(); @@ -1989,15 +1989,15 @@ void CHyprRenderer::recheckSolitaryForMonitor(PHLMONITOR pMonitor) { if (!PCANDIDATE->opaque()) return; - if (PCANDIDATE->m_vRealSize.value() != pMonitor->vecSize || PCANDIDATE->m_vRealPosition.value() != pMonitor->vecPosition || PCANDIDATE->m_vRealPosition.isBeingAnimated() || - PCANDIDATE->m_vRealSize.isBeingAnimated()) + if (PCANDIDATE->m_vRealSize->value() != pMonitor->vecSize || PCANDIDATE->m_vRealPosition->value() != pMonitor->vecPosition || PCANDIDATE->m_vRealPosition->isBeingAnimated() || + PCANDIDATE->m_vRealSize->isBeingAnimated()) return; if (!pMonitor->m_aLayerSurfaceLayers[ZWLR_LAYER_SHELL_V1_LAYER_OVERLAY].empty()) return; for (auto const& topls : pMonitor->m_aLayerSurfaceLayers[ZWLR_LAYER_SHELL_V1_LAYER_TOP]) { - if (topls->alpha.value() != 0.f) + if (topls->alpha->value() != 0.f) return; } @@ -2410,13 +2410,13 @@ void CHyprRenderer::renderSnapshot(PHLWINDOW pWindow) { CBox windowBox; // some mafs to figure out the correct box // the originalClosedPos is relative to the monitor's pos - Vector2D scaleXY = Vector2D((PMONITOR->scale * pWindow->m_vRealSize.value().x / (pWindow->m_vOriginalClosedSize.x * PMONITOR->scale)), - (PMONITOR->scale * pWindow->m_vRealSize.value().y / (pWindow->m_vOriginalClosedSize.y * PMONITOR->scale))); + Vector2D scaleXY = Vector2D((PMONITOR->scale * pWindow->m_vRealSize->value().x / (pWindow->m_vOriginalClosedSize.x * PMONITOR->scale)), + (PMONITOR->scale * pWindow->m_vRealSize->value().y / (pWindow->m_vOriginalClosedSize.y * PMONITOR->scale))); windowBox.width = PMONITOR->vecTransformedSize.x * scaleXY.x; windowBox.height = PMONITOR->vecTransformedSize.y * scaleXY.y; - windowBox.x = ((pWindow->m_vRealPosition.value().x - PMONITOR->vecPosition.x) * PMONITOR->scale) - ((pWindow->m_vOriginalClosedPos.x * PMONITOR->scale) * scaleXY.x); - windowBox.y = ((pWindow->m_vRealPosition.value().y - PMONITOR->vecPosition.y) * PMONITOR->scale) - ((pWindow->m_vOriginalClosedPos.y * PMONITOR->scale) * scaleXY.y); + windowBox.x = ((pWindow->m_vRealPosition->value().x - PMONITOR->vecPosition.x) * PMONITOR->scale) - ((pWindow->m_vOriginalClosedPos.x * PMONITOR->scale) * scaleXY.x); + windowBox.y = ((pWindow->m_vRealPosition->value().y - PMONITOR->vecPosition.y) * PMONITOR->scale) - ((pWindow->m_vOriginalClosedPos.y * PMONITOR->scale) * scaleXY.y); CRegion fakeDamage{0, 0, PMONITOR->vecTransformedSize.x, PMONITOR->vecTransformedSize.y}; @@ -2425,7 +2425,7 @@ void CHyprRenderer::renderSnapshot(PHLWINDOW pWindow) { CRectPassElement::SRectData data; data.box = {0, 0, g_pHyprOpenGL->m_RenderData.pMonitor->vecPixelSize.x, g_pHyprOpenGL->m_RenderData.pMonitor->vecPixelSize.y}; - data.color = CHyprColor(0, 0, 0, *PDIMAROUND * pWindow->m_fAlpha.value()); + data.color = CHyprColor(0, 0, 0, *PDIMAROUND * pWindow->m_fAlpha->value()); m_sRenderPass.add(makeShared(data)); damageMonitor(PMONITOR); @@ -2435,7 +2435,7 @@ void CHyprRenderer::renderSnapshot(PHLWINDOW pWindow) { data.flipEndFrame = true; data.tex = FBDATA->getTexture(); data.box = windowBox; - data.a = pWindow->m_fAlpha.value(); + data.a = pWindow->m_fAlpha->value(); data.damage = fakeDamage; m_sRenderPass.add(makeShared(data)); @@ -2455,13 +2455,13 @@ void CHyprRenderer::renderSnapshot(PHLLS pLayer) { CBox layerBox; // some mafs to figure out the correct box // the originalClosedPos is relative to the monitor's pos - Vector2D scaleXY = Vector2D((PMONITOR->scale * pLayer->realSize.value().x / (pLayer->geometry.w * PMONITOR->scale)), - (PMONITOR->scale * pLayer->realSize.value().y / (pLayer->geometry.h * PMONITOR->scale))); + Vector2D scaleXY = Vector2D((PMONITOR->scale * pLayer->realSize->value().x / (pLayer->geometry.w * PMONITOR->scale)), + (PMONITOR->scale * pLayer->realSize->value().y / (pLayer->geometry.h * PMONITOR->scale))); layerBox.width = PMONITOR->vecTransformedSize.x * scaleXY.x; layerBox.height = PMONITOR->vecTransformedSize.y * scaleXY.y; - layerBox.x = ((pLayer->realPosition.value().x - PMONITOR->vecPosition.x) * PMONITOR->scale) - (((pLayer->geometry.x - PMONITOR->vecPosition.x) * PMONITOR->scale) * scaleXY.x); - layerBox.y = ((pLayer->realPosition.value().y - PMONITOR->vecPosition.y) * PMONITOR->scale) - (((pLayer->geometry.y - PMONITOR->vecPosition.y) * PMONITOR->scale) * scaleXY.y); + layerBox.x = ((pLayer->realPosition->value().x - PMONITOR->vecPosition.x) * PMONITOR->scale) - (((pLayer->geometry.x - PMONITOR->vecPosition.x) * PMONITOR->scale) * scaleXY.x); + layerBox.y = ((pLayer->realPosition->value().y - PMONITOR->vecPosition.y) * PMONITOR->scale) - (((pLayer->geometry.y - PMONITOR->vecPosition.y) * PMONITOR->scale) * scaleXY.y); CRegion fakeDamage{0, 0, PMONITOR->vecTransformedSize.x, PMONITOR->vecTransformedSize.y}; @@ -2469,7 +2469,7 @@ void CHyprRenderer::renderSnapshot(PHLLS pLayer) { data.flipEndFrame = true; data.tex = FBDATA->getTexture(); data.box = layerBox; - data.a = pLayer->alpha.value(); + data.a = pLayer->alpha->value(); data.damage = fakeDamage; m_sRenderPass.add(makeShared(data)); diff --git a/src/render/decorations/CHyprBorderDecoration.cpp b/src/render/decorations/CHyprBorderDecoration.cpp index 2bc894ef..7261431f 100644 --- a/src/render/decorations/CHyprBorderDecoration.cpp +++ b/src/render/decorations/CHyprBorderDecoration.cpp @@ -43,7 +43,7 @@ CBox CHyprBorderDecoration::assignedBoxGlobal() { if (!PWORKSPACE) return box; - const auto WORKSPACEOFFSET = PWORKSPACE && !m_pWindow->m_bPinned ? PWORKSPACE->m_vRenderOffset.value() : Vector2D(); + const auto WORKSPACEOFFSET = PWORKSPACE && !m_pWindow->m_bPinned ? PWORKSPACE->m_vRenderOffset->value() : Vector2D(); return box.translate(WORKSPACEOFFSET); } @@ -60,10 +60,10 @@ void CHyprBorderDecoration::draw(PHLMONITOR pMonitor, float const& a) { return; auto grad = m_pWindow->m_cRealBorderColor; - const bool ANIMATED = m_pWindow->m_fBorderFadeAnimationProgress.isBeingAnimated(); + const bool ANIMATED = m_pWindow->m_fBorderFadeAnimationProgress->isBeingAnimated(); - if (m_pWindow->m_fBorderAngleAnimationProgress.getConfig()->pValues->internalEnabled) { - grad.m_fAngle += m_pWindow->m_fBorderAngleAnimationProgress.value() * M_PI * 2; + if (m_pWindow->m_fBorderAngleAnimationProgress->enabled()) { + grad.m_fAngle += m_pWindow->m_fBorderAngleAnimationProgress->value() * M_PI * 2; grad.m_fAngle = normalizeAngleRad(grad.m_fAngle); } @@ -83,7 +83,7 @@ void CHyprBorderDecoration::draw(PHLMONITOR pMonitor, float const& a) { data.hasGrad2 = true; data.grad1 = m_pWindow->m_cRealBorderColorPrevious; data.grad2 = grad; - data.lerp = m_pWindow->m_fBorderFadeAnimationProgress.value(); + data.lerp = m_pWindow->m_fBorderFadeAnimationProgress->value(); } g_pHyprRenderer->m_sRenderPass.add(makeShared(data)); @@ -117,8 +117,8 @@ void CHyprBorderDecoration::damageEntire() { const auto BORDERSIZE = m_pWindow->getRealBorderSize() + 1; const auto PWINDOWWORKSPACE = m_pWindow->m_pWorkspace; - if (PWINDOWWORKSPACE && PWINDOWWORKSPACE->m_vRenderOffset.isBeingAnimated() && !m_pWindow->m_bPinned) - surfaceBox.translate(PWINDOWWORKSPACE->m_vRenderOffset.value()); + if (PWINDOWWORKSPACE && PWINDOWWORKSPACE->m_vRenderOffset->isBeingAnimated() && !m_pWindow->m_bPinned) + surfaceBox.translate(PWINDOWWORKSPACE->m_vRenderOffset->value()); surfaceBox.translate(m_pWindow->m_vFloatingOffset); CBox surfaceBoxExpandedBorder = surfaceBox; diff --git a/src/render/decorations/CHyprDropShadowDecoration.cpp b/src/render/decorations/CHyprDropShadowDecoration.cpp index 07dbb436..ddd5198d 100644 --- a/src/render/decorations/CHyprDropShadowDecoration.cpp +++ b/src/render/decorations/CHyprDropShadowDecoration.cpp @@ -44,13 +44,13 @@ void CHyprDropShadowDecoration::damageEntire() { const auto PWINDOW = m_pWindow.lock(); - CBox shadowBox = {PWINDOW->m_vRealPosition.value().x - m_seExtents.topLeft.x, PWINDOW->m_vRealPosition.value().y - m_seExtents.topLeft.y, - PWINDOW->m_vRealSize.value().x + m_seExtents.topLeft.x + m_seExtents.bottomRight.x, - PWINDOW->m_vRealSize.value().y + m_seExtents.topLeft.y + m_seExtents.bottomRight.y}; + CBox shadowBox = {PWINDOW->m_vRealPosition->value().x - m_seExtents.topLeft.x, PWINDOW->m_vRealPosition->value().y - m_seExtents.topLeft.y, + PWINDOW->m_vRealSize->value().x + m_seExtents.topLeft.x + m_seExtents.bottomRight.x, + PWINDOW->m_vRealSize->value().y + m_seExtents.topLeft.y + m_seExtents.bottomRight.y}; const auto PWORKSPACE = PWINDOW->m_pWorkspace; - if (PWORKSPACE && PWORKSPACE->m_vRenderOffset.isBeingAnimated() && !PWINDOW->m_bPinned) - shadowBox.translate(PWORKSPACE->m_vRenderOffset.value()); + if (PWORKSPACE && PWORKSPACE->m_vRenderOffset->isBeingAnimated() && !PWINDOW->m_bPinned) + shadowBox.translate(PWORKSPACE->m_vRenderOffset->value()); shadowBox.translate(PWINDOW->m_vFloatingOffset); static auto PSHADOWIGNOREWINDOW = CConfigValue("decoration:shadow:ignore_window"); @@ -61,8 +61,8 @@ void CHyprDropShadowDecoration::damageEntire() { CRegion shadowRegion(shadowBox); if (*PSHADOWIGNOREWINDOW) { CBox surfaceBox = PWINDOW->getWindowMainSurfaceBox(); - if (PWORKSPACE && PWORKSPACE->m_vRenderOffset.isBeingAnimated() && !PWINDOW->m_bPinned) - surfaceBox.translate(PWORKSPACE->m_vRenderOffset.value()); + if (PWORKSPACE && PWORKSPACE->m_vRenderOffset->isBeingAnimated() && !PWINDOW->m_bPinned) + surfaceBox.translate(PWORKSPACE->m_vRenderOffset->value()); surfaceBox.translate(PWINDOW->m_vFloatingOffset); surfaceBox.expand(-ROUNDINGSIZE); shadowRegion.subtract(CRegion(surfaceBox)); @@ -81,8 +81,8 @@ void CHyprDropShadowDecoration::damageEntire() { void CHyprDropShadowDecoration::updateWindow(PHLWINDOW pWindow) { const auto PWINDOW = m_pWindow.lock(); - m_vLastWindowPos = PWINDOW->m_vRealPosition.value(); - m_vLastWindowSize = PWINDOW->m_vRealSize.value(); + m_vLastWindowPos = PWINDOW->m_vRealPosition->value(); + m_vLastWindowSize = PWINDOW->m_vRealSize->value(); m_bLastWindowBox = {m_vLastWindowPos.x, m_vLastWindowPos.y, m_vLastWindowSize.x, m_vLastWindowSize.y}; m_bLastWindowBoxWithDecos = g_pDecorationPositioner->getBoxWithIncludedDecos(pWindow); @@ -101,7 +101,7 @@ void CHyprDropShadowDecoration::render(PHLMONITOR pMonitor, float const& a) { if (!validMapped(PWINDOW)) return; - if (PWINDOW->m_cRealShadowColor.value() == CHyprColor(0, 0, 0, 0)) + if (PWINDOW->m_cRealShadowColor->value() == CHyprColor(0, 0, 0, 0)) return; // don't draw invisible shadows if (!PWINDOW->m_sWindowData.decorate.valueOrDefault()) @@ -123,7 +123,7 @@ void CHyprDropShadowDecoration::render(PHLMONITOR pMonitor, float const& a) { const auto ROUNDINGPOWER = PWINDOW->roundingPower(); const auto ROUNDING = ROUNDINGBASE > 0 ? ROUNDINGBASE + PWINDOW->getRealBorderSize() : 0; const auto PWORKSPACE = PWINDOW->m_pWorkspace; - const auto WORKSPACEOFFSET = PWORKSPACE && !PWINDOW->m_bPinned ? PWORKSPACE->m_vRenderOffset.value() : Vector2D(); + const auto WORKSPACEOFFSET = PWORKSPACE && !PWINDOW->m_bPinned ? PWORKSPACE->m_vRenderOffset->value() : Vector2D(); // draw the shadow CBox fullBox = m_bLastWindowBoxWithDecos; @@ -194,7 +194,7 @@ void CHyprDropShadowDecoration::render(PHLMONITOR pMonitor, float const& a) { g_pHyprOpenGL->renderRect(&fullBox, CHyprColor(0, 0, 0, 1), 0); // render white shadow with the alpha of the shadow color (otherwise we clear with alpha later and shit it to 2 bit) - drawShadowInternal(&fullBox, ROUNDING * pMonitor->scale, ROUNDINGPOWER, *PSHADOWSIZE * pMonitor->scale, CHyprColor(1, 1, 1, PWINDOW->m_cRealShadowColor.value().a), a); + drawShadowInternal(&fullBox, ROUNDING * pMonitor->scale, ROUNDINGPOWER, *PSHADOWSIZE * pMonitor->scale, CHyprColor(1, 1, 1, PWINDOW->m_cRealShadowColor->value().a), a); // render black window box ("clip") g_pHyprOpenGL->renderRect(&windowBox, CHyprColor(0, 0, 0, 1.0), (ROUNDING + 1 /* This fixes small pixel gaps. */) * pMonitor->scale, ROUNDINGPOWER); @@ -202,7 +202,7 @@ void CHyprDropShadowDecoration::render(PHLMONITOR pMonitor, float const& a) { alphaSwapFB.bind(); // alpha swap just has the shadow color. It will be the "texture" to render. - g_pHyprOpenGL->renderRect(&fullBox, PWINDOW->m_cRealShadowColor.value().stripA(), 0); + g_pHyprOpenGL->renderRect(&fullBox, PWINDOW->m_cRealShadowColor->value().stripA(), 0); LASTFB->bind(); @@ -216,7 +216,7 @@ void CHyprDropShadowDecoration::render(PHLMONITOR pMonitor, float const& a) { g_pHyprOpenGL->m_RenderData.damage = saveDamage; } else - drawShadowInternal(&fullBox, ROUNDING * pMonitor->scale, ROUNDINGPOWER, *PSHADOWSIZE * pMonitor->scale, PWINDOW->m_cRealShadowColor.value(), a); + drawShadowInternal(&fullBox, ROUNDING * pMonitor->scale, ROUNDINGPOWER, *PSHADOWSIZE * pMonitor->scale, PWINDOW->m_cRealShadowColor->value(), a); if (m_seExtents != m_seReportedExtents) g_pDecorationPositioner->repositionDeco(this); diff --git a/src/render/decorations/CHyprGroupBarDecoration.cpp b/src/render/decorations/CHyprGroupBarDecoration.cpp index c6dc5779..970273d7 100644 --- a/src/render/decorations/CHyprGroupBarDecoration.cpp +++ b/src/render/decorations/CHyprGroupBarDecoration.cpp @@ -390,9 +390,9 @@ bool CHyprGroupBarDecoration::onEndWindowDragOnDeco(const Vector2D& pos, PHLWIND // restores the group for (auto it = members.begin(); it != members.end(); ++it) { - (*it)->m_bIsFloating = pWindowInsertAfter->m_bIsFloating; // match the floating state of group members - (*it)->m_vRealSize = pWindowInsertAfter->m_vRealSize.goal(); // match the size of group members - (*it)->m_vRealPosition = pWindowInsertAfter->m_vRealPosition.goal(); // match the position of group members + (*it)->m_bIsFloating = pWindowInsertAfter->m_bIsFloating; // match the floating state of group members + *(*it)->m_vRealSize = pWindowInsertAfter->m_vRealSize->goal(); // match the size of group members + *(*it)->m_vRealPosition = pWindowInsertAfter->m_vRealPosition->goal(); // match the position of group members if (std::next(it) != members.end()) (*it)->m_sGroupData.pNextWindow = *std::next(it); else @@ -406,7 +406,7 @@ bool CHyprGroupBarDecoration::onEndWindowDragOnDeco(const Vector2D& pos, PHLWIND pDraggedWindow->m_bIsFloating = pWindowInsertAfter->m_bIsFloating; // match the floating state of the window if (pWindowInsertAfter->m_bIsFloating) - g_pXWaylandManager->setWindowSize(pDraggedWindow, pWindowInsertAfter->m_vRealSize.goal()); // match the size of the window + g_pXWaylandManager->setWindowSize(pDraggedWindow, pWindowInsertAfter->m_vRealSize->goal()); // match the size of the window pWindowInsertAfter->insertWindowToGroup(pDraggedWindow); @@ -515,7 +515,7 @@ CBox CHyprGroupBarDecoration::assignedBoxGlobal() { const auto PWORKSPACE = m_pWindow->m_pWorkspace; if (PWORKSPACE && !m_pWindow->m_bPinned) - box.translate(PWORKSPACE->m_vRenderOffset.value()); + box.translate(PWORKSPACE->m_vRenderOffset->value()); return box; } diff --git a/src/render/decorations/DecorationPositioner.cpp b/src/render/decorations/DecorationPositioner.cpp index 6a41cbdc..abfa19ec 100644 --- a/src/render/decorations/DecorationPositioner.cpp +++ b/src/render/decorations/DecorationPositioner.cpp @@ -124,7 +124,7 @@ void CDecorationPositioner::onWindowUpdate(PHLWINDOW pWindow) { datas.push_back(getDataFor(wd.get(), pWindow)); } - if (WINDOWDATA->lastWindowSize == pWindow->m_vRealSize.value() /* position not changed */ + if (WINDOWDATA->lastWindowSize == pWindow->m_vRealSize->value() /* position not changed */ && std::all_of(m_vWindowPositioningDatas.begin(), m_vWindowPositioningDatas.end(), [pWindow](const auto& data) { return pWindow != data->pWindow.lock() || !data->needsReposition; }) /* all window datas are either not for this window or don't need a reposition */ @@ -132,9 +132,9 @@ void CDecorationPositioner::onWindowUpdate(PHLWINDOW pWindow) { ) return; - WINDOWDATA->lastWindowSize = pWindow->m_vRealSize.value(); + WINDOWDATA->lastWindowSize = pWindow->m_vRealSize->value(); WINDOWDATA->needsRecalc = false; - const bool EPHEMERAL = pWindow->m_vRealSize.isBeingAnimated(); + const bool EPHEMERAL = pWindow->m_vRealSize->isBeingAnimated(); std::sort(datas.begin(), datas.end(), [](const auto& a, const auto& b) { return a->positioningInfo.priority > b->positioningInfo.priority; }); diff --git a/src/render/pass/SurfacePassElement.cpp b/src/render/pass/SurfacePassElement.cpp index 13e9e741..f2f2627a 100644 --- a/src/render/pass/SurfacePassElement.cpp +++ b/src/render/pass/SurfacePassElement.cpp @@ -77,7 +77,7 @@ void CSurfacePassElement::draw(const CRegion& damage) { const bool MISALIGNEDFSV1 = std::floor(data.pMonitor->scale) != data.pMonitor->scale /* Fractional */ && data.surface->current.scale == 1 /* fs protocol */ && windowBox.size() != data.surface->current.bufferSize /* misaligned */ && DELTALESSTHAN(windowBox.width, data.surface->current.bufferSize.x, 3) && DELTALESSTHAN(windowBox.height, data.surface->current.bufferSize.y, 3) /* off by one-or-two */ && - (!data.pWindow || (!data.pWindow->m_vRealSize.isBeingAnimated() && !INTERACTIVERESIZEINPROGRESS)) /* not window or not animated/resizing */; + (!data.pWindow || (!data.pWindow->m_vRealSize->isBeingAnimated() && !INTERACTIVERESIZEINPROGRESS)) /* not window or not animated/resizing */; g_pHyprRenderer->calculateUVForSurface(data.pWindow, data.surface, data.pMonitor->self.lock(), data.mainSurface, windowBox.size(), PROJSIZEUNSCALED, MISALIGNEDFSV1); @@ -148,8 +148,8 @@ CBox CSurfacePassElement::getTexBox() { if (!INTERACTIVERESIZEINPROGRESS) { windowBox.translate(CORRECT); - windowBox.width = SIZE.x * (PWINDOW->m_vRealSize.value().x / PWINDOW->m_vReportedSize.x); - windowBox.height = SIZE.y * (PWINDOW->m_vRealSize.value().y / PWINDOW->m_vReportedSize.y); + windowBox.width = SIZE.x * (PWINDOW->m_vRealSize->value().x / PWINDOW->m_vReportedSize.x); + windowBox.height = SIZE.y * (PWINDOW->m_vRealSize->value().y / PWINDOW->m_vReportedSize.y); } else { windowBox.width = SIZE.x; windowBox.height = SIZE.y; @@ -159,10 +159,10 @@ CBox CSurfacePassElement::getTexBox() { } else { // here we clamp to 2, these might be some tiny specks windowBox = {(int)outputX + data.pos.x + data.localPos.x, (int)outputY + data.pos.y + data.localPos.y, std::max((float)data.surface->current.size.x, 2.F), std::max((float)data.surface->current.size.y, 2.F)}; - if (data.pWindow && data.pWindow->m_vRealSize.isBeingAnimated() && data.surface && !data.mainSurface && data.squishOversized /* subsurface */) { + if (data.pWindow && data.pWindow->m_vRealSize->isBeingAnimated() && data.surface && !data.mainSurface && data.squishOversized /* subsurface */) { // adjust subsurfaces to the window - windowBox.width = (windowBox.width / data.pWindow->m_vReportedSize.x) * data.pWindow->m_vRealSize.value().x; - windowBox.height = (windowBox.height / data.pWindow->m_vReportedSize.y) * data.pWindow->m_vRealSize.value().y; + windowBox.width = (windowBox.width / data.pWindow->m_vReportedSize.x) * data.pWindow->m_vRealSize->value().x; + windowBox.height = (windowBox.height / data.pWindow->m_vReportedSize.y) * data.pWindow->m_vRealSize->value().y; } } From 95542e44884d2131a742f92013826a0b5f341b33 Mon Sep 17 00:00:00 2001 From: vaxerski Date: Tue, 7 Jan 2025 19:13:35 +0100 Subject: [PATCH 0823/2181] animationmgr: fix invalid include --- src/managers/AnimationManager.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/managers/AnimationManager.hpp b/src/managers/AnimationManager.hpp index 7bf73f97..10eeef05 100644 --- a/src/managers/AnimationManager.hpp +++ b/src/managers/AnimationManager.hpp @@ -5,7 +5,7 @@ #include "../defines.hpp" #include "../helpers/AnimatedVariable.hpp" -#include "desktop/DesktopTypes.hpp" +#include "../desktop/DesktopTypes.hpp" #include "eventLoop/EventLoopTimer.hpp" class CHyprAnimationManager : public Hyprutils::Animation::CAnimationManager { From 830350a1f7a5ad653f33f2c62dd1694249a2f1e2 Mon Sep 17 00:00:00 2001 From: UjinT34 <41110182+UjinT34@users.noreply.github.com> Date: Tue, 7 Jan 2025 21:32:50 +0300 Subject: [PATCH 0824/2181] core: Add support for HDR and color management protocols (#8715) --- CMakeLists.txt | 2 + protocols/frog-color-management-v1.xml | 366 ++++++ protocols/meson.build | 2 + protocols/xx-color-management-v4.xml | 1457 +++++++++++++++++++++++ src/Compositor.cpp | 19 + src/Compositor.hpp | 4 + src/config/ConfigDescriptions.hpp | 18 + src/config/ConfigManager.cpp | 4 + src/desktop/WLSurface.hpp | 1 + src/managers/ProtocolManager.cpp | 11 + src/protocols/ColorManagement.cpp | 571 +++++++++ src/protocols/ColorManagement.hpp | 182 +++ src/protocols/FrogColorManagement.cpp | 159 +++ src/protocols/FrogColorManagement.hpp | 55 + src/protocols/core/Compositor.hpp | 3 + src/protocols/types/ColorManagement.hpp | 47 + src/render/Renderer.cpp | 97 ++ src/render/pass/SurfacePassElement.cpp | 2 + 18 files changed, 3000 insertions(+) create mode 100644 protocols/frog-color-management-v1.xml create mode 100644 protocols/xx-color-management-v4.xml create mode 100644 src/protocols/ColorManagement.cpp create mode 100644 src/protocols/ColorManagement.hpp create mode 100644 src/protocols/FrogColorManagement.cpp create mode 100644 src/protocols/FrogColorManagement.hpp create mode 100644 src/protocols/types/ColorManagement.hpp diff --git a/CMakeLists.txt b/CMakeLists.txt index aa746d2e..c1ecb14c 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -316,6 +316,8 @@ protocolnew("protocols" "kde-server-decoration" true) protocolnew("protocols" "wlr-data-control-unstable-v1" true) protocolnew("${HYPRLAND_PROTOCOLS}/protocols" "hyprland-focus-grab-v1" true) protocolnew("protocols" "wlr-layer-shell-unstable-v1" true) +protocolnew("protocols" "xx-color-management-v4" true) +protocolnew("protocols" "frog-color-management-v1" true) protocolnew("protocols" "wayland-drm" true) protocolnew("${HYPRLAND_PROTOCOLS}/protocols" "hyprland-ctm-control-v1" true) protocolnew("${HYPRLAND_PROTOCOLS}/protocols" "hyprland-surface-v1" true) diff --git a/protocols/frog-color-management-v1.xml b/protocols/frog-color-management-v1.xml new file mode 100644 index 00000000..aab235a7 --- /dev/null +++ b/protocols/frog-color-management-v1.xml @@ -0,0 +1,366 @@ + + + + + Copyright © 2023 Joshua Ashton for Valve Software + Copyright © 2023 Xaver Hugl + + Permission is hereby granted, free of charge, to any person obtaining a + copy of this software and associated documentation files (the "Software"), + to deal in the Software without restriction, including without limitation + the rights to use, copy, modify, merge, publish, distribute, sublicense, + and/or sell copies of the Software, and to permit persons to whom the + Software is furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice (including the next + paragraph) shall be included in all copies or substantial portions of the + Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + DEALINGS IN THE SOFTWARE. + + + + The aim of this color management extension is to get HDR games working quickly, + and have an easy way to test implementations in the wild before the upstream + protocol is ready to be merged. + For that purpose it's intentionally limited and cut down and does not serve + all uses cases. + + + + + The color management factory singleton creates color managed surface objects. + + + + + + + + + + + + + + + + Interface for changing surface color management and HDR state. + + An implementation must: support every part of the version + of the frog_color_managed_surface interface it exposes. + Including all known enums associated with a given version. + + + + + Destroying the color managed surface resets all known color + state for the surface back to 'undefined' implementation-specific + values. + + + + + + Extended information on the transfer functions described + here can be found in the Khronos Data Format specification: + https://registry.khronos.org/DataFormat/specs/1.3/dataformat.1.3.html + + + + + + + + + + + + + + + + + + + + + + + + + + + + Extended information on render intents described + here can be found in ICC.1:2022: + + https://www.color.org/specification/ICC.1-2022-05.pdf + + + + + + + NOTE: On a surface with "perceptual" (default) render intent, handling of the container's + color volume + is implementation-specific, and may differ between different transfer functions it is paired + with: + ie. sRGB + 709 rendering may have it's primaries widened to more of the available display's + gamut + to be be more pleasing for the viewer. + Compared to scRGB Linear + 709 being treated faithfully as 709 + (including utilizing negatives out of the 709 gamut triangle) + + + + + + + Forwards HDR metadata from the client to the compositor. + + HDR Metadata Infoframe as per CTA 861.G spec. + + Usage of this HDR metadata is implementation specific and + outside of the scope of this protocol. + + + + Mastering Red Color Primary X Coordinate of the Data. + + Coded as unsigned 16-bit values in units of + 0.00002, where 0x0000 represents zero and 0xC350 + represents 1.0000. + + + + + Mastering Red Color Primary Y Coordinate of the Data. + + Coded as unsigned 16-bit values in units of + 0.00002, where 0x0000 represents zero and 0xC350 + represents 1.0000. + + + + + Mastering Green Color Primary X Coordinate of the Data. + + Coded as unsigned 16-bit values in units of + 0.00002, where 0x0000 represents zero and 0xC350 + represents 1.0000. + + + + + Mastering Green Color Primary Y Coordinate of the Data. + + Coded as unsigned 16-bit values in units of + 0.00002, where 0x0000 represents zero and 0xC350 + represents 1.0000. + + + + + Mastering Blue Color Primary X Coordinate of the Data. + + Coded as unsigned 16-bit values in units of + 0.00002, where 0x0000 represents zero and 0xC350 + represents 1.0000. + + + + + Mastering Blue Color Primary Y Coordinate of the Data. + + Coded as unsigned 16-bit values in units of + 0.00002, where 0x0000 represents zero and 0xC350 + represents 1.0000. + + + + + Mastering White Point X Coordinate of the Data. + + These are coded as unsigned 16-bit values in units of + 0.00002, where 0x0000 represents zero and 0xC350 + represents 1.0000. + + + + + Mastering White Point Y Coordinate of the Data. + + These are coded as unsigned 16-bit values in units of + 0.00002, where 0x0000 represents zero and 0xC350 + represents 1.0000. + + + + + Max Mastering Display Luminance. + This value is coded as an unsigned 16-bit value in units of 1 cd/m2, + where 0x0001 represents 1 cd/m2 and 0xFFFF represents 65535 cd/m2. + + + + + Min Mastering Display Luminance. + This value is coded as an unsigned 16-bit value in units of + 0.0001 cd/m2, where 0x0001 represents 0.0001 cd/m2 and 0xFFFF + represents 6.5535 cd/m2. + + + + + Max Content Light Level. + This value is coded as an unsigned 16-bit value in units of 1 cd/m2, + where 0x0001 represents 1 cd/m2 and 0xFFFF represents 65535 cd/m2. + + + + + Max Frame Average Light Level. + This value is coded as an unsigned 16-bit value in units of 1 cd/m2, + where 0x0001 represents 1 cd/m2 and 0xFFFF represents 65535 cd/m2. + + + + + + + Current preferred metadata for a surface. + The application should use this information to tone-map its buffers + to this target before committing. + + This metadata does not necessarily correspond to any physical output, but + rather what the compositor thinks would be best for a given surface. + + + + Specifies a known transfer function that corresponds to the + output the surface is targeting. + + + + + Output Red Color Primary X Coordinate of the Data. + + Coded as unsigned 16-bit values in units of + 0.00002, where 0x0000 represents zero and 0xC350 + represents 1.0000. + + + + + Output Red Color Primary Y Coordinate of the Data. + + Coded as unsigned 16-bit values in units of + 0.00002, where 0x0000 represents zero and 0xC350 + represents 1.0000. + + + + + Output Green Color Primary X Coordinate of the Data. + + Coded as unsigned 16-bit values in units of + 0.00002, where 0x0000 represents zero and 0xC350 + represents 1.0000. + + + + + Output Green Color Primary Y Coordinate of the Data. + + Coded as unsigned 16-bit values in units of + 0.00002, where 0x0000 represents zero and 0xC350 + represents 1.0000. + + + + + Output Blue Color Primary X Coordinate of the Data. + + Coded as unsigned 16-bit values in units of + 0.00002, where 0x0000 represents zero and 0xC350 + represents 1.0000. + + + + + Output Blue Color Primary Y Coordinate of the Data. + + Coded as unsigned 16-bit values in units of + 0.00002, where 0x0000 represents zero and 0xC350 + represents 1.0000. + + + + + Output White Point X Coordinate of the Data. + + These are coded as unsigned 16-bit values in units of + 0.00002, where 0x0000 represents zero and 0xC350 + represents 1.0000. + + + + + Output White Point Y Coordinate of the Data. + + These are coded as unsigned 16-bit values in units of + 0.00002, where 0x0000 represents zero and 0xC350 + represents 1.0000. + + + + + Max Output Luminance + The max luminance in nits that the output is capable of rendering in small areas. + Content should: not exceed this value to avoid clipping. + + This value is coded as an unsigned 16-bit value in units of 1 cd/m2, + where 0x0001 represents 1 cd/m2 and 0xFFFF represents 65535 cd/m2. + + + + + Min Output Luminance + The min luminance that the output is capable of rendering. + Content should: not exceed this value to avoid clipping. + + This value is coded as an unsigned 16-bit value in units of + 0.0001 cd/m2, where 0x0001 represents 0.0001 cd/m2 and 0xFFFF + represents 6.5535 cd/m2. + + + + + Max Full Frame Luminance + The max luminance in nits that the output is capable of rendering for the + full frame sustained. + + This value is coded as an unsigned 16-bit value in units of 1 cd/m2, + where 0x0001 represents 1 cd/m2 and 0xFFFF represents 65535 cd/m2. + + + + + \ No newline at end of file diff --git a/protocols/meson.build b/protocols/meson.build index a39602b7..fdbbf181 100644 --- a/protocols/meson.build +++ b/protocols/meson.build @@ -33,6 +33,8 @@ protocols = [ 'wayland-drm.xml', 'wlr-data-control-unstable-v1.xml', 'wlr-screencopy-unstable-v1.xml', + 'xx-color-management-v4.xml', + 'frog-color-management-v1.xml', hyprland_protocol_dir / 'protocols/hyprland-global-shortcuts-v1.xml', hyprland_protocol_dir / 'protocols/hyprland-toplevel-export-v1.xml', hyprland_protocol_dir / 'protocols/hyprland-focus-grab-v1.xml', diff --git a/protocols/xx-color-management-v4.xml b/protocols/xx-color-management-v4.xml new file mode 100644 index 00000000..23ff716e --- /dev/null +++ b/protocols/xx-color-management-v4.xml @@ -0,0 +1,1457 @@ + + + + Copyright 2019 Sebastian Wick + Copyright 2019 Erwin Burema + Copyright 2020 AMD + Copyright 2020-2024 Collabora, Ltd. + Copyright 2024 Xaver Hugl + + Permission is hereby granted, free of charge, to any person obtaining a + copy of this software and associated documentation files (the "Software"), + to deal in the Software without restriction, including without limitation + the rights to use, copy, modify, merge, publish, distribute, sublicense, + and/or sell copies of the Software, and to permit persons to whom the + Software is furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice (including the next + paragraph) shall be included in all copies or substantial portions of the + Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + DEALINGS IN THE SOFTWARE. + + + + The aim of the color management extension is to allow clients to know + the color properties of outputs, and to tell the compositor about the color + properties of their content on surfaces. Doing this enables a compositor + to perform automatic color management of content for different outputs + according to how content is intended to look like. + + The color properties are represented as an image description object which + is immutable after it has been created. A wl_output always has an + associated image description that clients can observe. A wl_surface + always has an associated preferred image description as a hint chosen by + the compositor that clients can also observe. Clients can set an image + description on a wl_surface to denote the color characteristics of the + surface contents. + + An image description includes SDR and HDR colorimetry and encoding, HDR + metadata, and viewing environment parameters. An image description does + not include the properties set through color-representation extension. + It is expected that the color-representation extension is used in + conjunction with the color management extension when necessary, + particularly with the YUV family of pixel formats. + + Recommendation ITU-T H.273 + "Coding-independent code points for video signal type identification" + shall be referred to as simply H.273 here. + + The color-and-hdr repository + (https://gitlab.freedesktop.org/pq/color-and-hdr) contains + background information on the protocol design and legacy color management. + It also contains a glossary, learning resources for digital color, tools, + samples and more. + + The terminology used in this protocol is based on common color science and + color encoding terminology where possible. The glossary in the color-and-hdr + repository shall be the authority on the definition of terms in this + protocol. + + + + + A global interface used for getting color management extensions for + wl_surface and wl_output objects, and for creating client defined image + description objects. The extension interfaces allow + getting the image description of outputs and setting the image + description of surfaces. + + + + + Destroy the xx_color_manager_v4 object. This does not affect any other + objects in any way. + + + + + + + + + + + See the ICC.1:2022 specification from the International Color Consortium + for more details about rendering intents. + + The principles of ICC defined rendering intents apply with all types of + image descriptions, not only those with ICC file profiles. + + Compositors must support the perceptual rendering intent. Other + rendering intents are optional. + + + + + + + + + + + + + + + + + + + + The compositor supports set_mastering_display_primaries request with a + target color volume fully contained inside the primary color volume. + + + + + The compositor additionally supports target color volumes that + extend outside of the primary color volume. + + This can only be advertised if feature set_mastering_display_primaries + is supported as well. + + + + + + + Named color primaries used to encode well-known sets of primaries. H.273 + is the authority, when it comes to the exact values of primaries and + authoritative specifications, where an equivalent code point exists. + + Descriptions do list the specifications for convenience. + + + + + Color primaries as defined by + - Rec. ITU-R BT.709-6 + - Rec. ITU-R BT.1361-0 conventional colour gamut system and extended + colour gamut system (historical) + - IEC 61966-2-1 sRGB or sYCC + - IEC 61966-2-4 + - Society of Motion Picture and Television Engineers (SMPTE) RP 177 + (1993) Annex B + Equivalent to H.273 ColourPrimaries code point 1. + + + + + Color primaries as defined by + - Rec. ITU-R BT.470-6 System M (historical) + - United States National Television System Committee 1953 + Recommendation for transmission standards for color television + - United States Federal Communications Commission (2003) Title 47 Code + of Federal Regulations 73.682 (a)(20) + Equivalent to H.273 ColourPrimaries code point 4. + + + + + Color primaries as defined by + - Rec. ITU-R BT.470-6 System B, G (historical) + - Rec. ITU-R BT.601-7 625 + - Rec. ITU-R BT.1358-0 625 (historical) + - Rec. ITU-R BT.1700-0 625 PAL and 625 SECAM + Equivalent to H.273 ColourPrimaries code point 5. + + + + + Color primaries as defined by + - Rec. ITU-R BT.601-7 525 + - Rec. ITU-R BT.1358-1 525 or 625 (historical) + - Rec. ITU-R BT.1700-0 NTSC + - SMPTE 170M (2004) + - SMPTE 240M (1999) (historical) + Equivalent to H.273 ColourPrimaries code point 6 and 7. + + + + + Color primaries as defined by H.273 for generic film. + Equivalent to H.273 ColourPrimaries code point 8. + + + + + Color primaries as defined by + - Rec. ITU-R BT.2020-2 + - Rec. ITU-R BT.2100-0 + Equivalent to H.273 ColourPrimaries code point 9. + + + + + Color primaries as defined as the maximum of the CIE 1931 XYZ color + space by + - SMPTE ST 428-1 + - (CIE 1931 XYZ as in ISO 11664-1) + Equivalent to H.273 ColourPrimaries code point 10. + + + + + Color primaries as defined by Digital Cinema System and published in + SMPTE RP 431-2 (2011). Equivalent to H.273 ColourPrimaries code point + 11. + + + + + Color primaries as defined by Digital Cinema System and published in + SMPTE EG 432-1 (2010). + Equivalent to H.273 ColourPrimaries code point 12. + + + + + Color primaries as defined by Adobe as "Adobe RGB" and later published + by ISO 12640-4 (2011). + + + + + + + Named transfer functions used to encode well-known transfer + characteristics. H.273 is the authority, when it comes to the exact + formulas and authoritative specifications, where an equivalent code + point exists. + + Descriptions do list the specifications for convenience. + + + + + Transfer characteristics as defined by + - Rec. ITU-R BT.709-6 + - Rec. ITU-R BT.1361-0 conventional colour gamut system (historical) + Equivalent to H.273 TransferCharacteristics code point 1, 6, 14, 15. + + + + + Transfer characteristics as defined by + - Rec. ITU-R BT.470-6 System M (historical) + - United States National Television System Committee 1953 + Recommendation for transmission standards for color television + - United States Federal Communications Commission (2003) Title 47 Code + of Federal Regulations 73.682 (a) (20) + - Rec. ITU-R BT.1700-0 625 PAL and 625 SECAM + Equivalent to H.273 TransferCharacteristics code point 4. + + + + + Transfer characteristics as defined by + - Rec. ITU-R BT.470-6 System B, G (historical) + Equivalent to H.273 TransferCharacteristics code point 5. + + + + + Transfer characteristics as defined by + - SMPTE ST 240 (1999) + Equivalent to H.273 TransferCharacteristics code point 7. + + + + + Linear transfer characteristics. + Equivalent to H.273 TransferCharacteristics code point 8. + + + + + Logarithmic transfer characteristic (100:1 range). + Equivalent to H.273 TransferCharacteristics code point 9. + + + + + Logarithmic transfer characteristic (100 * Sqrt(10) : 1 range). + Equivalent to H.273 TransferCharacteristics code point 10. + + + + + Transfer characteristics as defined by + - IEC 61966-2-4 + Equivalent to H.273 TransferCharacteristics code point 11. + + + + + Transfer characteristics as defined by + - Rec. ITU-R BT.1361-0 extended colour gamut system (historical) + Equivalent to H.273 TransferCharacteristics code point 12. + + + + + Transfer characteristics as defined by + - IEC 61966-2-1 sRGB + Equivalent to H.273 TransferCharacteristics code point 13 with + MatrixCoefficients set to 0. + + + + + Transfer characteristics as defined by + - IEC 61966-2-1 sYCC + Equivalent to H.273 TransferCharacteristics code point 13 with + MatrixCoefficients set to anything but 0. + + + + + Transfer characteristics as defined by + - SMPTE ST 2084 (2014) for 10-, 12-, 14- and 16-bit systems + - Rec. ITU-R BT.2100-2 perceptual quantization (PQ) system + Equivalent to H.273 TransferCharacteristics code point 16. + + This TF implies these default luminances + - primary color volume minimum: 0.005 cd/m² + - primary color volume maximum: 10000 cd/m² + - reference white: 203 cd/m² + + + + + Transfer characteristics as defined by + - SMPTE ST 428-1 (2019) + Equivalent to H.273 TransferCharacteristics code point 17. + + + + + Transfer characteristics as defined by + - ARIB STD-B67 (2015) + - Rec. ITU-R BT.2100-2 hybrid log-gamma (HLG) system + Equivalent to H.273 TransferCharacteristics code point 18. + + This TF implies these default luminances + - primary color volume minimum: 0.005 cd/m² + - primary color volume maximum: 1000 cd/m² + - reference white: 203 cd/m² + Note: HLG is a scene referred signal. All absolute luminance values + used here for HLG assume a 1000 cd/m² display. + + + + + + + This creates a new xx_color_management_output_v4 object for the + given wl_output. + + See the xx_color_management_output_v4 interface for more details. + + + + + + + + + If a xx_color_management_surface_v4 object already exists for the given + wl_surface, the protocol error surface_exists is raised. + + This creates a new color xx_color_management_surface_v4 object for the + given wl_surface. + + See the xx_color_management_surface_v4 interface for more details. + + + + + + + + + This creates a new color xx_color_management_feedback_surface_v4 object + for the given wl_surface. + + See the xx_color_management_feedback_surface_v4 interface for more + details. + + + + + + + + + Makes a new ICC-based image description creator object with all + properties initially unset. The client can then use the object's + interface to define all the required properties for an image description + and finally create a xx_image_description_v4 object. + + This request can be used when the compositor advertises + xx_color_manager_v4.feature.icc_v2_v4. + Otherwise this request raises the protocol error unsupported_feature. + + + + + + + + Makes a new parametric image description creator object with all + properties initially unset. The client can then use the object's + interface to define all the required properties for an image description + and finally create a xx_image_description_v4 object. + + This request can be used when the compositor advertises + xx_color_manager_v4.feature.parametric. + Otherwise this request raises the protocol error unsupported_feature. + + + + + + + + When this object is created, it shall immediately send this event once + for each rendering intent the compositor supports. + + + + + + + + When this object is created, it shall immediately send this event once + for each compositor supported feature listed in the enumeration. + + + + + + + + When this object is created, it shall immediately send this event once + for each named transfer function the compositor supports with the + parametric image description creator. + + + + + + + + When this object is created, it shall immediately send this event once + for each named set of primaries the compositor supports with the + parametric image description creator. + + + + + + + + + A xx_color_management_output_v4 describes the color properties of an + output. + + The xx_color_management_output_v4 is associated with the wl_output global + underlying the wl_output object. Therefore the client destroying the + wl_output object has no impact, but the compositor removing the output + global makes the xx_color_management_output_v4 object inert. + + + + + Destroy the color xx_color_management_output_v4 object. This does not + affect any remaining protocol objects. + + + + + + This event is sent whenever the image description of the output changed, + followed by one wl_output.done event common to output events across all + extensions. + + If the client wants to use the updated image description, it needs to do + get_image_description again, because image description objects are + immutable. + + + + + + This creates a new xx_image_description_v4 object for the current image + description of the output. There always is exactly one image description + active for an output so the client should destroy the image description + created by earlier invocations of this request. This request is usually + sent as a reaction to the image_description_changed event or when + creating a xx_color_management_output_v4 object. + + The image description of an output represents the color encoding the + output expects. There might be performance and power advantages, as well + as improved color reproduction, if a content update matches the image + description of the output it is being shown on. If a content update is + shown on any other output than the one it matches the image description + of, then the color reproduction on those outputs might be considerably + worse. + + The created xx_image_description_v4 object preserves the image + description of the output from the time the object was created. + + The resulting image description object allows get_information request. + + If this protocol object is inert, the resulting image description object + shall immediately deliver the xx_image_description_v4.failed event with + the no_output cause. + + If the interface version is inadequate for the output's image + description, meaning that the client does not support all the events + needed to deliver the crucial information, the resulting image + description object shall immediately deliver the + xx_image_description_v4.failed event with the low_version cause. + + Otherwise the object shall immediately deliver the ready event. + + + + + + + + + A xx_color_management_surface_v4 allows the client to set the color + space and HDR properties of a surface. + + If the wl_surface associated with the xx_color_management_surface_v4 is + destroyed, the xx_color_management_surface_v4 object becomes inert. + + + + + Destroy the xx_color_management_surface_v4 object and do the same as + unset_image_description. + + + + + + + + + + + + Set the image description of the underlying surface. The image + description and rendering intent are double-buffered state, see + wl_surface.commit. + + It is the client's responsibility to understand the image description + it sets on a surface, and to provide content that matches that image + description. Compositors might convert images to match their own or any + other image descriptions. + + Image description whose creation gracefully failed (received + xx_image_description_v4.failed) are forbidden in this request, and in + such case the protocol error image_description is raised. + + All image descriptions whose creation succeeded (received + xx_image_description_v4.ready) are allowed and must always be accepted + by the compositor. + + A rendering intent provides the client's preference on how content + colors should be mapped to each output. The render_intent value must + be one advertised by the compositor with + xx_color_manager_v4.render_intent event, otherwise the protocol error + render_intent is raised. + + By default, a surface does not have an associated image description + nor a rendering intent. The handling of color on such surfaces is + compositor implementation defined. Compositors should handle such + surfaces as sRGB but may handle them differently if they have specific + requirements. + + + + + + + + + This request removes any image description from the surface. See + set_image_description for how a compositor handles a surface without + an image description. This is double-buffered state, see + wl_surface.commit. + + + + + + + A xx_color_management_feedback_surface_v4 allows the client to get the + preferred color description of a surface. + + If the wl_surface associated with this object is destroyed, the + xx_color_management_feedback_surface_v4 object becomes inert. + + + + + Destroy the xx_color_management_feedback_surface_v4 object. + + + + + + + + + + + The preferred image description is the one which likely has the most + performance and/or quality benefits for the compositor if used by the + client for its wl_surface contents. This event is sent whenever the + compositor changes the wl_surface's preferred image description. + + This event is merely a notification. When the client wants to know + what the preferred image description is, it shall use the get_preferred + request. + + The preferred image description is not automatically used for anything. + It is only a hint, and clients may set any valid image description with + set_image_description but there might be performance and color accuracy + improvements by providing the wl_surface contents in the preferred + image description. Therefore clients that can, should render according + to the preferred image description + + + + + + If this protocol object is inert, the protocol error inert is raised. + + The preferred image description represents the compositor's preferred + color encoding for this wl_surface at the current time. There might be + performance and power advantages, as well as improved color + reproduction, if the image description of a content update matches the + preferred image description. + + This creates a new xx_image_description_v4 object for the currently + preferred image description for the wl_surface. The client should + stop using and destroy the image descriptions created by earlier + invocations of this request for the associated wl_surface. + This request is usually sent as a reaction to the preferred_changed + event or when creating a xx_color_management_feedback_surface_v4 object + if the client is capable of adapting to image descriptions. + + The created xx_image_description_v4 object preserves the preferred image + description of the wl_surface from the time the object was created. + + The resulting image description object allows get_information request. + + If the interface version is inadequate for the preferred image + description, meaning that the client does not support all the + events needed to deliver the crucial information, the resulting image + description object shall immediately deliver the + xx_image_description_v4.failed event with the low_version cause, + otherwise the object shall immediately deliver the ready event. + + + + + + + + + This type of object is used for collecting all the information required + to create a xx_image_description_v4 object from an ICC file. A complete + set of required parameters consists of these properties: + - ICC file + + Each required property must be set exactly once if the client is to create + an image description. The set requests verify that a property was not + already set. The create request verifies that all required properties are + set. There may be several alternative requests for setting each property, + and in that case the client must choose one of them. + + Once all properties have been set, the create request must be used to + create the image description object, destroying the creator in the + process. + + + + + + + + + + + + + + + Create an image description object based on the ICC information + previously set on this object. A compositor must parse the ICC data in + some undefined but finite amount of time. + + The completeness of the parameter set is verified. If the set is not + complete, the protocol error incomplete_set is raised. For the + definition of a complete set, see the description of this interface. + + If the particular combination of the information is not supported + by the compositor, the resulting image description object shall + immediately deliver the xx_image_description_v4.failed event with the + 'unsupported' cause. If a valid image description was created from the + information, the xx_image_description_v4.ready event will eventually + be sent instead. + + This request destroys the xx_image_description_creator_icc_v4 object. + + The resulting image description object does not allow get_information + request. + + + + + + + + Sets the ICC profile file to be used as the basis of the image + description. + + The data shall be found through the given fd at the given offset, having + the given length. The fd must seekable and readable. Violating these + requirements raises the bad_fd protocol error. + + If reading the data fails due to an error independent of the client, the + compositor shall send the xx_image_description_v4.failed event on the + created xx_image_description_v4 with the 'operating_system' cause. + + The maximum size of the ICC profile is 4 MB. If length is greater than + that or zero, the protocol error bad_size is raised. If offset + length + exceeds the file size, the protocol error out_of_file is raised. + + A compositor may read the file at any time starting from this request + and only until whichever happens first: + - If create request was issued, the xx_image_description_v4 object + delivers either failed or ready event; or + - if create request was not issued, this + xx_image_description_creator_icc_v4 object is destroyed. + + A compositor shall not modify the contents of the file, and the fd may + be sealed for writes and size changes. The client must ensure to its + best ability that the data does not change while the compositor is + reading it. + + The data must represent a valid ICC profile. The ICC profile version + must be 2 or 4, it must be a 3 channel profile and the class must be + Display or ColorSpace. Violating these requirements will not result in a + protocol error but will eventually send the + xx_image_description_v4.failed event on the created + xx_image_description_v4 with the 'unsupported' cause. + + See the International Color Consortium specification ICC.1:2022 for more + details about ICC profiles. + + If ICC file has already been set on this object, the protocol error + already_set is raised. + + + + + + + + + + + This type of object is used for collecting all the parameters required + to create a xx_image_description_v4 object. A complete set of required + parameters consists of these properties: + - transfer characteristic function (tf) + - chromaticities of primaries and white point (primary color volume) + + The following properties are optional and have a well-defined default + if not explicitly set: + - primary color volume luminance range + - reference white luminance level + - mastering display primaries and white point (target color volume) + - mastering luminance range + - maximum content light level + - maximum frame-average light level + + Each required property must be set exactly once if the client is to create + an image description. The set requests verify that a property was not + already set. The create request verifies that all required properties are + set. There may be several alternative requests for setting each property, + and in that case the client must choose one of them. + + Once all properties have been set, the create request must be used to + create the image description object, destroying the creator in the + process. + + + + + + + + + + + + + + + + + + Create an image description object based on the parameters previously + set on this object. + + The completeness of the parameter set is verified. If the set is not + complete, the protocol error incomplete_set is raised. For the + definition of a complete set, see the description of this interface. + + Also, the combination of the parameter set is verified. If the set is + not consistent, the protocol error inconsistent_set is raised. + + If the particular combination of the parameter set is not supported + by the compositor, the resulting image description object shall + immediately deliver the xx_image_description_v4.failed event with the + 'unsupported' cause. If a valid image description was created from the + parameter set, the xx_image_description_v4.ready event will eventually + be sent instead. + + This request destroys the xx_image_description_creator_params_v4 + object. + + The resulting image description object does not allow get_information + request. + + + + + + + + Sets the transfer characteristic using explicitly enumerated named + functions. + + When the resulting image description is attached to an image, the + content should be encoded and decoded according to the industry standard + practices for the transfer characteristic. + + Only names advertised with xx_color_manager_v4 event supported_tf_named + are allowed. Other values shall raise the protocol error invalid_tf. + + If transfer characteristic has already been set on this object, the + protocol error already_set is raised. + + + + + + + + Sets the color component transfer characteristic to a power curve with + the given exponent. This curve represents the conversion from electrical + to optical pixel or color values. + + When the resulting image description is attached to an image, the + content should be encoded with the inverse of the power curve. + + The curve exponent shall be multiplied by 10000 to get the argument eexp + value to carry the precision of 4 decimals. + + The curve exponent must be at least 1.0 and at most 10.0. Otherwise the + protocol error invalid_tf is raised. + + If transfer characteristic has already been set on this object, the + protocol error already_set is raised. + + This request can be used when the compositor advertises + xx_color_manager_v4.feature.set_tf_power. Otherwise this request raises + the protocol error unsupported_feature. + + + + + + + + Sets the color primaries and white point using explicitly named sets. + This describes the primary color volume which is the basis for color + value encoding. + + Only names advertised with xx_color_manager_v4 event + supported_primaries_named are allowed. Other values shall raise the + protocol error invalid_primaries. + + If primaries have already been set on this object, the protocol error + already_set is raised. + + + + + + + + Sets the color primaries and white point using CIE 1931 xy chromaticity + coordinates. This describes the primary color volume which is the basis + for color value encoding. + + Each coordinate value is multiplied by 10000 to get the argument value + to carry precision of 4 decimals. + + If primaries have already been set on this object, the protocol error + already_set is raised. + + This request can be used if the compositor advertises + xx_color_manager_v4.feature.set_primaries. Otherwise this request raises + the protocol error unsupported_feature. + + + + + + + + + + + + + + + Sets the primary color volume luminance range and the reference white + luminance level. + + The default luminances are + - primary color volume minimum: 0.2 cd/m² + - primary color volume maximum: 80 cd/m² + - reference white: 80 cd/m² + + Setting a named transfer characteristic can imply other default + luminances. + + The default luminances get overwritten when this request is used. + + 'min_lum' and 'max_lum' specify the minimum and maximum luminances of + the primary color volume as reproduced by the targeted display. + + 'reference_lum' specifies the luminance of the reference white as + reproduced by the targeted display, and reflects the targeted viewing + environment. + + Compositors should make sure that all content is anchored, meaning that + an input signal level of 'reference_lum' on one image description and + another input signal level of 'reference_lum' on another image + description should produce the same output level, even though the + 'reference_lum' on both image representations can be different. + + If 'max_lum' is less than the 'reference_lum', or 'reference_lum' is + less than or equal to 'min_lum', the protocol error invalid_luminance is + raised. + + The minimum luminance is multiplied by 10000 to get the argument + 'min_lum' value and carries precision of 4 decimals. The maximum + luminance and reference white luminance values are unscaled. + + If the primary color volume luminance range and the reference white + luminance level have already been set on this object, the protocol error + already_set is raised. + + This request can be used if the compositor advertises + xx_color_manager_v4.feature.set_luminances. Otherwise this request + raises the protocol error unsupported_feature. + + + + + + + + + + Provides the color primaries and white point of the mastering display + using CIE 1931 xy chromaticity coordinates. This is compatible with the + SMPTE ST 2086 definition of HDR static metadata. + + The mastering display primaries define the target color volume. + + If mastering display primaries are not explicitly set, the target color + volume is assumed to be equal to the primary color volume. + + The target color volume is defined by all tristimulus values between 0.0 + and 1.0 (inclusive) of the color space defined by the given mastering + display primaries and white point. The colorimetry is identical between + the container color space and the mastering display color space, + including that no chromatic adaptation is applied even if the white + points differ. + + The target color volume can exceed the primary color volume to allow for + a greater color volume with an existing color space definition (for + example scRGB). It can be smaller than the primary color volume to + minimize gamut and tone mapping distances for big color spaces (HDR + metadata). + + To make use of the entire target color volume a suitable pixel format + has to be chosen (e.g. floating point to exceed the primary color + volume, or abusing limited quantization range as with xvYCC). + + Each coordinate value is multiplied by 10000 to get the argument value + to carry precision of 4 decimals. + + If mastering display primaries have already been set on this object, the + protocol error already_set is raised. + + This request can be used if the compositor advertises + xx_color_manager_v4.feature.set_mastering_display_primaries. Otherwise + this request raises the protocol error unsupported_feature. The + advertisement implies support only for target color volumes fully + contained within the primary color volume. + + If a compositor additionally supports target color volume exceeding the + primary color volume, it must advertise + xx_color_manager_v4.feature.extended_target_volume. If a client uses + target color volume exceeding the primary color volume and the + compositor does not support it, the result is implementation defined. + Compositors are recommended to detect this case and fail the image + description gracefully, but it may as well result in color artifacts. + + + + + + + + + + + + + + + Sets the luminance range that was used during the content mastering + process as the minimum and maximum absolute luminance L. This is + compatible with the SMPTE ST 2086 definition of HDR static metadata. + + The mastering luminance range is undefined by default. + + If max L is less than or equal to min L, the protocol error + invalid_luminance is raised. + + Min L value is multiplied by 10000 to get the argument min_lum value + and carry precision of 4 decimals. Max L value is unscaled for max_lum. + + + + + + + + + Sets the maximum content light level (max_cll) as defined by CTA-861-H. + + This can only be set when set_tf_cicp is used to set the transfer + characteristic to Rec. ITU-R BT.2100-2 perceptual quantization system. + Otherwise, 'create' request shall raise inconsistent_set protocol + error. + + max_cll is undefined by default. + + + + + + + + Sets the maximum frame-average light level (max_fall) as defined by + CTA-861-H. + + This can only be set when set_tf_cicp is used to set the transfer + characteristic to Rec. ITU-R BT.2100-2 perceptual quantization system. + Otherwise, 'create' request shall raise inconsistent_set protocol error. + + max_fall is undefined by default. + + + + + + + + + An image description carries information about the color encoding used on + a surface when attached to a wl_surface via + xx_color_management_surface_v4.set_image_description. A compositor can use + this information to decode pixel values into colorimetrically meaningful + quantities. + + Note, that the xx_image_description_v4 object is not ready to be used + immediately after creation. The object eventually delivers either the + 'ready' or the 'failed' event, specified in all requests creating it. The + object is deemed "ready" after receiving the 'ready' event. + + An object which is not ready is illegal to use, it can only be destroyed. + Any other request in this interface shall result in the 'not_ready' + protocol error. Attempts to use an object which is not ready through other + interfaces shall raise protocol errors defined there. + + Once created and regardless of how it was created, a + xx_image_description_v4 object always refers to one fixed image + description. It cannot change after creation. + + + + + Destroy this object. It is safe to destroy an object which is not ready. + + Destroying a xx_image_description_v4 object has no side-effects, not + even if a xx_color_management_surface_v4.set_image_description has not + yet been followed by a wl_surface.commit. + + + + + + + + + + + + + + + + + + + + + + If creating a xx_image_description_v4 object fails for a reason that is + not defined as a protocol error, this event is sent. + + The requests that create image description objects define whether and + when this can occur. Only such creation requests can trigger this event. + This event cannot be triggered after the image description was + successfully formed. + + Once this event has been sent, the xx_image_description_v4 object will + never become ready and it can only be destroyed. + + + + + + + + + Once this event has been sent, the xx_image_description_v4 object is + deemed "ready". Ready objects can be used to send requests and can be + used through other interfaces. + + Every ready xx_image_description_v4 protocol object refers to an + underlying image description record in the compositor. Multiple protocol + objects may end up referring to the same record. Clients may identify + these "copies" by comparing their id numbers: if the numbers from two + protocol objects are identical, the protocol objects refer to the same + image description record. Two different image description records + cannot have the same id number simultaneously. The id number does not + change during the lifetime of the image description record. + + The id number is valid only as long as the protocol object is alive. If + all protocol objects referring to the same image description record are + destroyed, the id number may be recycled for a different image + description record. + + Image description id number is not a protocol object id. Zero is + reserved as an invalid id number. It shall not be possible for a client + to refer to an image description by its id number in protocol. The id + numbers might not be portable between Wayland connections. + + This identity allows clients to de-duplicate image description records + and avoid get_information request if they already have the image + description information. + + + + + + + + Creates a xx_image_description_info_v4 object which delivers the + information that makes up the image description. + + Not all image description protocol objects allow get_information + request. Whether it is allowed or not is defined by the request that + created the object. If get_information is not allowed, the protocol + error no_information is raised. + + + + + + + + + Sends all matching events describing an image description object exactly + once and finally sends the 'done' event. + + Once a xx_image_description_info_v4 object has delivered a 'done' event it + is automatically destroyed. + + Every xx_image_description_info_v4 created from the same + xx_image_description_v4 shall always return the exact same data. + + + + + Signals the end of information events and destroys the object. + + + + + + The icc argument provides a file descriptor to the client which may be + memory-mapped to provide the ICC profile matching the image description. + The fd is read-only, and if mapped then it must be mapped with + MAP_PRIVATE by the client. + + The ICC profile version and other details are determined by the + compositor. There is no provision for a client to ask for a specific + kind of a profile. + + + + + + + + + + Delivers the primary color volume primaries and white point using CIE + 1931 xy chromaticity coordinates. + + Each coordinate value is multiplied by 10000 to get the argument value + to carry precision of 4 decimals. + + + + + + + + + + + + + + + Delivers the primary color volume primaries and white point using an + explicitly enumerated named set. + + + + + + + + The color component transfer characteristic of this image description is + a pure power curve. This event provides the exponent of the power + function. This curve represents the conversion from electrical to + optical pixel or color values. + + The curve exponent has been multiplied by 10000 to get the argument eexp + value to carry the precision of 4 decimals. + + + + + + + + Delivers the transfer characteristic using an explicitly enumerated + named function. + + + + + + + + Delivers the primary color volume luminance range and the reference + white luminance level. + + The minimum luminance is multiplied by 10000 to get the argument + 'min_lum' value and carries precision of 4 decimals. The maximum + luminance and reference white luminance values are unscaled. + + + + + + + + + + Provides the color primaries and white point of the target color volume + using CIE 1931 xy chromaticity coordinates. This is compatible with the + SMPTE ST 2086 definition of HDR static metadata for mastering displays. + + While primary color volume is about how color is encoded, the target + color volume is the actually displayable color volume. If target color + volume is equal to the primary color volume, then this event is not + sent. + + Each coordinate value is multiplied by 10000 to get the argument value + to carry precision of 4 decimals. + + + + + + + + + + + + + + + Provides the luminance range that the image description is targeting as + the minimum and maximum absolute luminance L. This is compatible with + the SMPTE ST 2086 definition of HDR static metadata. + + This luminance range is only theoretical and may not correspond to the + luminance of light emitted on an actual display. + + Min L value is multiplied by 10000 to get the argument min_lum value and + carry precision of 4 decimals. Max L value is unscaled for max_lum. + + + + + + + + + Provides the targeted max_cll of the image description. max_cll is + defined by CTA-861-H. + + This luminance is only theoretical and may not correspond to the + luminance of light emitted on an actual display. + + + + + + + + Provides the targeted max_fall of the image description. max_fall is + defined by CTA-861-H. + + This luminance is only theoretical and may not correspond to the + luminance of light emitted on an actual display. + + + + + + \ No newline at end of file diff --git a/src/Compositor.cpp b/src/Compositor.cpp index 5805eff9..3d159042 100644 --- a/src/Compositor.cpp +++ b/src/Compositor.cpp @@ -31,6 +31,7 @@ #include "protocols/XDGShell.hpp" #include "protocols/XDGOutput.hpp" #include "protocols/SecurityContext.hpp" +#include "protocols/ColorManagement.hpp" #include "protocols/core/Compositor.hpp" #include "protocols/core/Subcompositor.hpp" #include "desktop/LayerSurface.hpp" @@ -2985,4 +2986,22 @@ void CCompositor::onNewMonitor(SP output) { g_pHyprRenderer->damageMonitor(PNEWMONITOR); PNEWMONITOR->onMonitorFrame(); + + if (PROTO::colorManagement && shouldChangePreferredImageDescription()) + PROTO::colorManagement->onImagePreferredChanged(); +} + +SImageDescription CCompositor::getPreferredImageDescription() { + if (!PROTO::colorManagement) { + Debug::log(ERR, "FIXME: color management protocol is not enabled, returning empty image description"); + return SImageDescription{}; + } + Debug::log(WARN, "FIXME: color management protocol is enabled, determine correct preferred image description"); + // should determine some common settings to avoid unnecessary transformations while keeping maximum displayable precision + return SImageDescription{.primaries = NColorPrimaries::BT709}; +} + +bool CCompositor::shouldChangePreferredImageDescription() { + Debug::log(WARN, "FIXME: color management protocol is enabled and outputs changed, check preferred image description changes"); + return false; } diff --git a/src/Compositor.hpp b/src/Compositor.hpp index 4c428fca..629b71bc 100644 --- a/src/Compositor.hpp +++ b/src/Compositor.hpp @@ -23,6 +23,7 @@ #include "helpers/Monitor.hpp" #include "desktop/Workspace.hpp" #include "desktop/Window.hpp" +#include "protocols/types/ColorManagement.hpp" #include "render/Renderer.hpp" #include "render/OpenGL.hpp" #include "hyprerror/HyprError.hpp" @@ -169,6 +170,9 @@ class CCompositor { void updateSuspendedStates(); void onNewMonitor(SP output); + SImageDescription getPreferredImageDescription(); + bool shouldChangePreferredImageDescription(); + std::string explicitConfigPath; private: diff --git a/src/config/ConfigDescriptions.hpp b/src/config/ConfigDescriptions.hpp index 8c35a3b1..686b996a 100644 --- a/src/config/ConfigDescriptions.hpp +++ b/src/config/ConfigDescriptions.hpp @@ -1658,4 +1658,22 @@ inline static const std::vector CONFIG_OPTIONS = { .type = CONFIG_OPTION_BOOL, .data = SConfigOptionDescription::SBoolData{true}, }, + SConfigOptionDescription{ + .value = "experimental:wide_color_gamut", + .description = "force wide color gamut for all supported outputs", + .type = CONFIG_OPTION_BOOL, + .data = SConfigOptionDescription::SBoolData{false}, + }, + SConfigOptionDescription{ + .value = "experimental:hdr", + .description = "force static hdr for all supported outputs", + .type = CONFIG_OPTION_BOOL, + .data = SConfigOptionDescription::SBoolData{false}, + }, + SConfigOptionDescription{ + .value = "experimental:xx_color_management_v4", + .description = "enable color management protocol", + .type = CONFIG_OPTION_BOOL, + .data = SConfigOptionDescription::SBoolData{false}, + }, }; diff --git a/src/config/ConfigManager.cpp b/src/config/ConfigManager.cpp index 1ab29b1f..bbb3e68f 100644 --- a/src/config/ConfigManager.cpp +++ b/src/config/ConfigManager.cpp @@ -622,6 +622,10 @@ CConfigManager::CConfigManager() { m_pConfig->addConfigValue("ecosystem:no_update_news", Hyprlang::INT{0}); + m_pConfig->addConfigValue("experimental:wide_color_gamut", Hyprlang::INT{0}); + m_pConfig->addConfigValue("experimental:hdr", Hyprlang::INT{0}); + m_pConfig->addConfigValue("experimental:xx_color_management_v4", Hyprlang::INT{0}); + // devices m_pConfig->addSpecialCategory("device", {"name"}); m_pConfig->addSpecialConfigValue("device", "sensitivity", {0.F}); diff --git a/src/desktop/WLSurface.hpp b/src/desktop/WLSurface.hpp index 07af13df..057a6f90 100644 --- a/src/desktop/WLSurface.hpp +++ b/src/desktop/WLSurface.hpp @@ -119,4 +119,5 @@ class CWLSurface { } listeners; friend class CPointerConstraint; + friend class CXxColorManagerV4; }; diff --git a/src/managers/ProtocolManager.cpp b/src/managers/ProtocolManager.cpp index 0e1c21f5..b7d61f67 100644 --- a/src/managers/ProtocolManager.cpp +++ b/src/managers/ProtocolManager.cpp @@ -55,6 +55,8 @@ #include "../protocols/core/Subcompositor.hpp" #include "../protocols/core/Output.hpp" #include "../protocols/core/Shm.hpp" +#include "../protocols/ColorManagement.hpp" +#include "../protocols/FrogColorManagement.hpp" #include "../helpers/Monitor.hpp" #include "../render/Renderer.hpp" @@ -77,11 +79,15 @@ void CProtocolManager::onMonitorModeChange(PHLMONITOR pMonitor) { PROTO::outputs.erase(pMonitor->szName); PROTO::outputs.emplace(pMonitor->szName, makeShared(&wl_output_interface, 4, std::format("WLOutput ({})", pMonitor->szName), pMonitor->self.lock())); } + + if (PROTO::colorManagement && g_pCompositor->shouldChangePreferredImageDescription()) + PROTO::colorManagement->onImagePreferredChanged(); } CProtocolManager::CProtocolManager() { static const auto PENABLEEXPLICIT = CConfigValue("render:explicit_sync"); + static const auto PENABLEXXCM = CConfigValue("experimental:xx_color_management_v4"); // Outputs are a bit dumb, we have to agree. static auto P = g_pHookSystem->hookDynamic("monitorAdded", [this](void* self, SCallbackInfo& info, std::any param) { @@ -162,6 +168,11 @@ CProtocolManager::CProtocolManager() { PROTO::ctm = std::make_unique(&hyprland_ctm_control_manager_v1_interface, 1, "CTMControl"); PROTO::hyprlandSurface = std::make_unique(&hyprland_surface_manager_v1_interface, 1, "HyprlandSurface"); + if (*PENABLEXXCM) { + PROTO::colorManagement = std::make_unique(&xx_color_manager_v4_interface, 1, "ColorManagement"); + PROTO::frogColorManagement = std::make_unique(&frog_color_management_factory_v1_interface, 1, "FrogColorManagement"); + } + for (auto const& b : g_pCompositor->m_pAqBackend->getImplementations()) { if (b->type() != Aquamarine::AQ_BACKEND_DRM) continue; diff --git a/src/protocols/ColorManagement.cpp b/src/protocols/ColorManagement.cpp new file mode 100644 index 00000000..7ff4db4f --- /dev/null +++ b/src/protocols/ColorManagement.cpp @@ -0,0 +1,571 @@ +#include "ColorManagement.hpp" +#include "Compositor.hpp" + +CColorManager::CColorManager(SP resource_) : resource(resource_) { + if (!good()) + return; + + resource->sendSupportedFeature(XX_COLOR_MANAGER_V4_FEATURE_PARAMETRIC); + resource->sendSupportedFeature(XX_COLOR_MANAGER_V4_FEATURE_EXTENDED_TARGET_VOLUME); + resource->sendSupportedFeature(XX_COLOR_MANAGER_V4_FEATURE_SET_MASTERING_DISPLAY_PRIMARIES); + resource->sendSupportedFeature(XX_COLOR_MANAGER_V4_FEATURE_SET_PRIMARIES); + resource->sendSupportedFeature(XX_COLOR_MANAGER_V4_FEATURE_SET_LUMINANCES); + + resource->sendSupportedPrimariesNamed(XX_COLOR_MANAGER_V4_PRIMARIES_SRGB); + // resource->sendSupportedPrimariesNamed(XX_COLOR_MANAGER_V4_PRIMARIES_PAL_M); + // resource->sendSupportedPrimariesNamed(XX_COLOR_MANAGER_V4_PRIMARIES_PAL); + // resource->sendSupportedPrimariesNamed(XX_COLOR_MANAGER_V4_PRIMARIES_NTSC); + // resource->sendSupportedPrimariesNamed(XX_COLOR_MANAGER_V4_PRIMARIES_GENERIC_FILM); + resource->sendSupportedPrimariesNamed(XX_COLOR_MANAGER_V4_PRIMARIES_BT2020); + // resource->sendSupportedPrimariesNamed(XX_COLOR_MANAGER_V4_PRIMARIES_CIE1931_XYZ); + // resource->sendSupportedPrimariesNamed(XX_COLOR_MANAGER_V4_PRIMARIES_DCI_P3); + // resource->sendSupportedPrimariesNamed(XX_COLOR_MANAGER_V4_PRIMARIES_DISPLAY_P3); + // resource->sendSupportedPrimariesNamed(XX_COLOR_MANAGER_V4_PRIMARIES_ADOBE_RGB); + + // resource->sendSupportedTfNamed(XX_COLOR_MANAGER_V4_TRANSFER_FUNCTION_GAMMA22); + resource->sendSupportedTfNamed(XX_COLOR_MANAGER_V4_TRANSFER_FUNCTION_SRGB); + resource->sendSupportedTfNamed(XX_COLOR_MANAGER_V4_TRANSFER_FUNCTION_ST2084_PQ); + // resource->sendSupportedTfNamed(XX_COLOR_MANAGER_V4_TRANSFER_FUNCTION_LINEAR); + + resource->sendSupportedIntent(XX_COLOR_MANAGER_V4_RENDER_INTENT_PERCEPTUAL); + // resource->sendSupportedIntent(XX_COLOR_MANAGER_V4_RENDER_INTENT_RELATIVE); + // resource->sendSupportedIntent(XX_COLOR_MANAGER_V4_RENDER_INTENT_ABSOLUTE); + // resource->sendSupportedIntent(XX_COLOR_MANAGER_V4_RENDER_INTENT_RELATIVE_BPC); + + resource->setDestroy([](CXxColorManagerV4* r) { LOGM(TRACE, "Destroy xx_color_manager at {:x} (generated default)", (uintptr_t)r); }); + resource->setGetOutput([](CXxColorManagerV4* r, uint32_t id, wl_resource* output) { + LOGM(TRACE, "Get output for id={}, output={}", id, (uintptr_t)output); + const auto RESOURCE = + PROTO::colorManagement->m_vOutputs.emplace_back(makeShared(makeShared(r->client(), r->version(), id))); + + if (!RESOURCE->good()) { + r->noMemory(); + PROTO::colorManagement->m_vOutputs.pop_back(); + return; + } + + RESOURCE->self = RESOURCE; + }); + resource->setGetSurface([](CXxColorManagerV4* r, uint32_t id, wl_resource* surface) { + LOGM(TRACE, "Get surface for id={}, surface={}", id, (uintptr_t)surface); + auto SURF = CWLSurfaceResource::fromResource(surface); + + if (!SURF) { + LOGM(ERR, "No surface for resource {}", (uintptr_t)surface); + r->error(-1, "Invalid surface (2)"); + return; + } + + if (SURF->colorManagement) { + r->error(XX_COLOR_MANAGER_V4_ERROR_SURFACE_EXISTS, "CM Surface already exists"); + return; + } + + const auto RESOURCE = + PROTO::colorManagement->m_vSurfaces.emplace_back(makeShared(makeShared(r->client(), r->version(), id), SURF)); + if (!RESOURCE->good()) { + r->noMemory(); + PROTO::colorManagement->m_vSurfaces.pop_back(); + return; + } + + RESOURCE->self = RESOURCE; + + SURF->colorManagement = RESOURCE; + }); + resource->setGetFeedbackSurface([](CXxColorManagerV4* r, uint32_t id, wl_resource* surface) { + LOGM(TRACE, "Get feedback surface for id={}, surface={}", id, (uintptr_t)surface); + auto SURF = CWLSurfaceResource::fromResource(surface); + + if (!SURF) { + LOGM(ERR, "No surface for resource {}", (uintptr_t)surface); + r->error(-1, "Invalid surface (2)"); + return; + } + + const auto RESOURCE = PROTO::colorManagement->m_vFeedbackSurfaces.emplace_back( + makeShared(makeShared(r->client(), r->version(), id), SURF)); + + if (!RESOURCE->good()) { + r->noMemory(); + PROTO::colorManagement->m_vFeedbackSurfaces.pop_back(); + return; + } + + RESOURCE->self = RESOURCE; + }); + resource->setNewIccCreator([](CXxColorManagerV4* r, uint32_t id) { + LOGM(WARN, "New ICC creator for id={} (unsupported)", id); + r->error(XX_COLOR_MANAGER_V4_ERROR_UNSUPPORTED_FEATURE, "ICC profiles are not supported"); + }); + resource->setNewParametricCreator([](CXxColorManagerV4* r, uint32_t id) { + LOGM(TRACE, "New parametric creator for id={}", id); + + const auto RESOURCE = PROTO::colorManagement->m_vParametricCreators.emplace_back( + makeShared(makeShared(r->client(), r->version(), id))); + + if (!RESOURCE->good()) { + r->noMemory(); + PROTO::colorManagement->m_vParametricCreators.pop_back(); + return; + } + + RESOURCE->self = RESOURCE; + }); + + resource->setOnDestroy([this](CXxColorManagerV4* r) { PROTO::colorManagement->destroyResource(this); }); +} + +bool CColorManager::good() { + return resource->resource(); +} + +CColorManagementOutput::CColorManagementOutput(SP resource_) : resource(resource_) { + if (!good()) + return; + + pClient = resource->client(); + + resource->setDestroy([this](CXxColorManagementOutputV4* r) { PROTO::colorManagement->destroyResource(this); }); + resource->setOnDestroy([this](CXxColorManagementOutputV4* r) { PROTO::colorManagement->destroyResource(this); }); + + resource->setGetImageDescription([this](CXxColorManagementOutputV4* r, uint32_t id) { + LOGM(TRACE, "Get image description for output={}, id={}", (uintptr_t)r, id); + if (imageDescription.valid()) + PROTO::colorManagement->destroyResource(imageDescription.get()); + + const auto RESOURCE = PROTO::colorManagement->m_vImageDescriptions.emplace_back( + makeShared(makeShared(r->client(), r->version(), id))); + + if (!RESOURCE->good()) { + r->noMemory(); + PROTO::colorManagement->m_vImageDescriptions.pop_back(); + return; + } + + RESOURCE->self = RESOURCE; + }); +} + +bool CColorManagementOutput::good() { + return resource->resource(); +} + +wl_client* CColorManagementOutput::client() { + return pClient; +} + +CColorManagementSurface::CColorManagementSurface(SP surface_) : surface(surface_) { + // only for frog cm untill wayland cm is adopted +} + +CColorManagementSurface::CColorManagementSurface(SP resource_, SP surface_) : surface(surface_), resource(resource_) { + if (!good()) + return; + + pClient = resource->client(); + + resource->setDestroy([this](CXxColorManagementSurfaceV4* r) { + LOGM(TRACE, "Destroy xx cm surface {}", (uintptr_t)surface); + PROTO::colorManagement->destroyResource(this); + }); + resource->setOnDestroy([this](CXxColorManagementSurfaceV4* r) { + LOGM(TRACE, "Destroy xx cm surface {}", (uintptr_t)surface); + PROTO::colorManagement->destroyResource(this); + }); + + resource->setSetImageDescription([this](CXxColorManagementSurfaceV4* r, wl_resource* image_description, uint32_t render_intent) { + LOGM(TRACE, "Set image description for surface={}, desc={}, intent={}", (uintptr_t)r, (uintptr_t)image_description, render_intent); + + const auto PO = (CXxImageDescriptionV4*)wl_resource_get_user_data(image_description); + if (!PO) { // FIXME check validity + r->error(XX_COLOR_MANAGEMENT_SURFACE_V4_ERROR_IMAGE_DESCRIPTION, "Image description creation failed"); + return; + } + if (render_intent != XX_COLOR_MANAGER_V4_RENDER_INTENT_PERCEPTUAL) { + r->error(XX_COLOR_MANAGEMENT_SURFACE_V4_ERROR_RENDER_INTENT, "Unsupported render intent"); + return; + } + + const auto imageDescription = std::find_if(PROTO::colorManagement->m_vImageDescriptions.begin(), PROTO::colorManagement->m_vImageDescriptions.end(), + [&](const auto& other) { return other->resource()->resource() == image_description; }); + if (imageDescription == PROTO::colorManagement->m_vImageDescriptions.end()) { + r->error(XX_COLOR_MANAGEMENT_SURFACE_V4_ERROR_IMAGE_DESCRIPTION, "Image description not found"); + return; + } + + m_hasImageDescription = true; + m_imageDescription = imageDescription->get()->settings; + }); + resource->setUnsetImageDescription([this](CXxColorManagementSurfaceV4* r) { + LOGM(TRACE, "Unset image description for surface={}", (uintptr_t)r); + m_imageDescription = SImageDescription{}; + m_hasImageDescription = false; + }); +} + +bool CColorManagementSurface::good() { + return resource && resource->resource(); +} + +wl_client* CColorManagementSurface::client() { + return pClient; +} + +const SImageDescription& CColorManagementSurface::imageDescription() { + if (!hasImageDescription()) + LOGM(WARN, "Reading imageDescription while none set. Returns default or empty values"); + return m_imageDescription; +} + +bool CColorManagementSurface::hasImageDescription() { + return m_hasImageDescription; +} + +CColorManagementFeedbackSurface::CColorManagementFeedbackSurface(SP resource_, SP surface_) : + surface(surface_), resource(resource_) { + if (!good()) + return; + + pClient = resource->client(); + + resource->setDestroy([this](CXxColorManagementFeedbackSurfaceV4* r) { + LOGM(TRACE, "Destroy xx cm feedback surface {}", (uintptr_t)surface); + if (m_currentPreferred.valid()) + PROTO::colorManagement->destroyResource(m_currentPreferred.get()); + PROTO::colorManagement->destroyResource(this); + }); + resource->setOnDestroy([this](CXxColorManagementFeedbackSurfaceV4* r) { + LOGM(TRACE, "Destroy xx cm feedback surface {}", (uintptr_t)surface); + if (m_currentPreferred.valid()) + PROTO::colorManagement->destroyResource(m_currentPreferred.get()); + PROTO::colorManagement->destroyResource(this); + }); + + resource->setGetPreferred([this](CXxColorManagementFeedbackSurfaceV4* r, uint32_t id) { + LOGM(TRACE, "Get preferred for id {}", id); + + if (m_currentPreferred.valid()) + PROTO::colorManagement->destroyResource(m_currentPreferred.get()); + + const auto RESOURCE = PROTO::colorManagement->m_vImageDescriptions.emplace_back( + makeShared(makeShared(r->client(), r->version(), id), true)); + + if (!RESOURCE->good()) { + r->noMemory(); + PROTO::colorManagement->m_vImageDescriptions.pop_back(); + return; + } + + RESOURCE->self = RESOURCE; + m_currentPreferred = RESOURCE; + + m_currentPreferred->settings = g_pCompositor->getPreferredImageDescription(); + + RESOURCE->resource()->sendReady(id); + }); +} + +bool CColorManagementFeedbackSurface::good() { + return resource->resource(); +} + +wl_client* CColorManagementFeedbackSurface::client() { + return pClient; +} + +CColorManagementParametricCreator::CColorManagementParametricCreator(SP resource_) : resource(resource_) { + if (!good()) + return; + // + pClient = resource->client(); + + resource->setOnDestroy([this](CXxImageDescriptionCreatorParamsV4* r) { PROTO::colorManagement->destroyResource(this); }); + + resource->setCreate([this](CXxImageDescriptionCreatorParamsV4* r, uint32_t id) { + LOGM(TRACE, "Create image description from params for id {}", id); + + // FIXME actually check completeness + if (!valuesSet) { + r->error(XX_IMAGE_DESCRIPTION_CREATOR_PARAMS_V4_ERROR_INCOMPLETE_SET, "Missing required settings"); + return; + } + + // FIXME actually check consistency + if (!valuesSet) { + r->error(XX_IMAGE_DESCRIPTION_CREATOR_PARAMS_V4_ERROR_INCONSISTENT_SET, "Set is not consistent"); + return; + } + + const auto RESOURCE = PROTO::colorManagement->m_vImageDescriptions.emplace_back( + makeShared(makeShared(r->client(), r->version(), id))); + + if (!RESOURCE->good()) { + r->noMemory(); + PROTO::colorManagement->m_vImageDescriptions.pop_back(); + return; + } + + // FIXME actually check support + if (!valuesSet) { + RESOURCE->resource()->sendFailed(XX_IMAGE_DESCRIPTION_V4_CAUSE_UNSUPPORTED, "unsupported"); + return; + } + + RESOURCE->self = RESOURCE; + RESOURCE->settings = settings; + RESOURCE->resource()->sendReady(id); + + PROTO::colorManagement->destroyResource(this); + }); + resource->setSetTfNamed([this](CXxImageDescriptionCreatorParamsV4* r, uint32_t tf) { + LOGM(TRACE, "Set image description transfer function to {}", tf); + if (valuesSet & PC_TF) { + r->error(XX_IMAGE_DESCRIPTION_CREATOR_PARAMS_V4_ERROR_ALREADY_SET, "Transfer function already set"); + return; + } + + switch (tf) { + case XX_COLOR_MANAGER_V4_TRANSFER_FUNCTION_SRGB: break; + case XX_COLOR_MANAGER_V4_TRANSFER_FUNCTION_ST2084_PQ: break; + default: r->error(XX_IMAGE_DESCRIPTION_CREATOR_PARAMS_V4_ERROR_INVALID_TF, "Unsupported transfer function"); return; + } + + settings.transferFunction = (xxColorManagerV4TransferFunction)tf; + valuesSet |= PC_TF; + }); + resource->setSetTfPower([this](CXxImageDescriptionCreatorParamsV4* r, uint32_t eexp) { + LOGM(TRACE, "Set image description tf power to {}", eexp); + if (valuesSet & PC_TF_POWER) { + r->error(XX_IMAGE_DESCRIPTION_CREATOR_PARAMS_V4_ERROR_ALREADY_SET, "Transfer function power already set"); + return; + } + settings.transferFunctionPower = eexp / 10000.0f; + valuesSet |= PC_TF_POWER; + }); + resource->setSetPrimariesNamed([this](CXxImageDescriptionCreatorParamsV4* r, uint32_t primaries) { + LOGM(TRACE, "Set image description primaries by name {}", primaries); + if (valuesSet & PC_PRIMARIES) { + r->error(XX_IMAGE_DESCRIPTION_CREATOR_PARAMS_V4_ERROR_ALREADY_SET, "Primaries already set"); + return; + } + + switch (primaries) { + case XX_COLOR_MANAGER_V4_PRIMARIES_SRGB: + settings.primariesNameSet = true; + settings.primariesNamed = XX_COLOR_MANAGER_V4_PRIMARIES_SRGB; + settings.primaries = NColorPrimaries::BT709; + valuesSet |= PC_PRIMARIES; + break; + case XX_COLOR_MANAGER_V4_PRIMARIES_BT2020: + settings.primariesNameSet = true; + settings.primariesNamed = XX_COLOR_MANAGER_V4_PRIMARIES_BT2020; + settings.primaries = NColorPrimaries::BT2020; + valuesSet |= PC_PRIMARIES; + break; + default: r->error(XX_IMAGE_DESCRIPTION_CREATOR_PARAMS_V4_ERROR_INVALID_PRIMARIES, "Unsupported primaries"); + } + }); + resource->setSetPrimaries( + [this](CXxImageDescriptionCreatorParamsV4* r, int32_t r_x, int32_t r_y, int32_t g_x, int32_t g_y, int32_t b_x, int32_t b_y, int32_t w_x, int32_t w_y) { + LOGM(TRACE, "Set image description primaries by values r:{},{} g:{},{} b:{},{} w:{},{}", r_x, r_y, g_x, g_y, b_x, b_y, w_x, w_y); + if (valuesSet & PC_PRIMARIES) { + r->error(XX_IMAGE_DESCRIPTION_CREATOR_PARAMS_V4_ERROR_ALREADY_SET, "Primaries already set"); + return; + } + settings.primariesNameSet = false; + settings.primaries = + SImageDescription::SPCPRimaries{.red = {.x = r_x, .y = r_y}, .green = {.x = g_x, .y = g_y}, .blue = {.x = b_x, .y = b_y}, .white = {.x = w_x, .y = w_y}}; + valuesSet |= PC_PRIMARIES; + }); + resource->setSetLuminances([this](CXxImageDescriptionCreatorParamsV4* r, uint32_t min_lum, uint32_t max_lum, uint32_t reference_lum) { + auto min = min_lum / 10000.0f; + LOGM(TRACE, "Set image description luminances to {} - {} ({})", min, max_lum, reference_lum); + if (valuesSet & PC_LUMINANCES) { + r->error(XX_IMAGE_DESCRIPTION_CREATOR_PARAMS_V4_ERROR_ALREADY_SET, "Luminances already set"); + return; + } + if (max_lum < reference_lum || reference_lum <= min) { + r->error(XX_IMAGE_DESCRIPTION_CREATOR_PARAMS_V4_ERROR_INVALID_LUMINANCE, "Invalid luminances"); + return; + } + settings.luminances = SImageDescription::SPCLuminances{.min = min, .max = max_lum, .reference = reference_lum}; + valuesSet |= PC_LUMINANCES; + }); + resource->setSetMasteringDisplayPrimaries( + [this](CXxImageDescriptionCreatorParamsV4* r, int32_t r_x, int32_t r_y, int32_t g_x, int32_t g_y, int32_t b_x, int32_t b_y, int32_t w_x, int32_t w_y) { + LOGM(TRACE, "Set image description mastering primaries by values r:{},{} g:{},{} b:{},{} w:{},{}", r_x, r_y, g_x, g_y, b_x, b_y, w_x, w_y); + // if (valuesSet & PC_MASTERING_PRIMARIES) { + // r->error(XX_IMAGE_DESCRIPTION_CREATOR_PARAMS_V4_ERROR_ALREADY_SET, "Mastering primaries already set"); + // return; + // } + settings.masteringPrimaries = + SImageDescription::SPCPRimaries{.red = {.x = r_x, .y = r_y}, .green = {.x = g_x, .y = g_y}, .blue = {.x = b_x, .y = b_y}, .white = {.x = w_x, .y = w_y}}; + valuesSet |= PC_MASTERING_PRIMARIES; + }); + resource->setSetMasteringLuminance([this](CXxImageDescriptionCreatorParamsV4* r, uint32_t min_lum, uint32_t max_lum) { + auto min = min_lum / 10000.0f; + LOGM(TRACE, "Set image description mastering luminances to {} - {}", min, max_lum); + // if (valuesSet & PC_MASTERING_LUMINANCES) { + // r->error(XX_IMAGE_DESCRIPTION_CREATOR_PARAMS_V4_ERROR_ALREADY_SET, "Mastering luminances already set"); + // return; + // } + if (min > 0 && max_lum > 0 && max_lum <= min) { + r->error(XX_IMAGE_DESCRIPTION_CREATOR_PARAMS_V4_ERROR_INVALID_LUMINANCE, "Invalid luminances"); + return; + } + settings.masteringLuminances = SImageDescription::SPCMasteringLuminances{.min = min, .max = max_lum}; + valuesSet |= PC_MASTERING_LUMINANCES; + }); + resource->setSetMaxCll([this](CXxImageDescriptionCreatorParamsV4* r, uint32_t max_cll) { + LOGM(TRACE, "Set image description max content light level to {}", max_cll); + // if (valuesSet & PC_CLL) { + // r->error(XX_IMAGE_DESCRIPTION_CREATOR_PARAMS_V4_ERROR_ALREADY_SET, "Max CLL already set"); + // return; + // } + settings.maxCLL = max_cll; + valuesSet |= PC_CLL; + }); + resource->setSetMaxFall([this](CXxImageDescriptionCreatorParamsV4* r, uint32_t max_fall) { + LOGM(TRACE, "Set image description max frame-average light level to {}", max_fall); + // if (valuesSet & PC_FALL) { + // r->error(XX_IMAGE_DESCRIPTION_CREATOR_PARAMS_V4_ERROR_ALREADY_SET, "Max FALL already set"); + // return; + // } + settings.maxFALL = max_fall; + valuesSet |= PC_FALL; + }); +} + +bool CColorManagementParametricCreator::good() { + return resource->resource(); +} + +wl_client* CColorManagementParametricCreator::client() { + return pClient; +} + +CColorManagementImageDescription::CColorManagementImageDescription(SP resource_, bool allowGetInformation) : + m_resource(resource_), m_allowGetInformation(allowGetInformation) { + if (!good()) + return; + + pClient = m_resource->client(); + + m_resource->setDestroy([this](CXxImageDescriptionV4* r) { PROTO::colorManagement->destroyResource(this); }); + m_resource->setOnDestroy([this](CXxImageDescriptionV4* r) { PROTO::colorManagement->destroyResource(this); }); + + m_resource->setGetInformation([this](CXxImageDescriptionV4* r, uint32_t id) { + LOGM(TRACE, "Get image information for image={}, id={}", (uintptr_t)r, id); + if (!m_allowGetInformation) { + r->error(XX_IMAGE_DESCRIPTION_V4_ERROR_NO_INFORMATION, "Image descriptions doesn't allow get_information request"); + return; + } + + auto RESOURCE = makeShared(makeShared(r->client(), r->version(), id), settings); + + if (!RESOURCE->good()) + r->noMemory(); + + // CColorManagementImageDescriptionInfo should send everything in the constructor and be ready for destroying at this point + RESOURCE.reset(); + }); +} + +bool CColorManagementImageDescription::good() { + return m_resource->resource(); +} + +wl_client* CColorManagementImageDescription::client() { + return pClient; +} + +SP CColorManagementImageDescription::resource() { + return m_resource; +} + +CColorManagementImageDescriptionInfo::CColorManagementImageDescriptionInfo(SP resource_, const SImageDescription& settings_) : + m_resource(resource_), settings(settings_) { + if (!good()) + return; + + pClient = m_resource->client(); + + const auto toProto = [](float value) { return int32_t(std::round(value * 10000)); }; + + if (settings.iccFd >= 0) + m_resource->sendIccFile(settings.iccFd, settings.iccSize); + + // send preferred client paramateres + m_resource->sendPrimaries(toProto(settings.primaries.red.x), toProto(settings.primaries.red.y), toProto(settings.primaries.green.x), toProto(settings.primaries.green.y), + toProto(settings.primaries.blue.x), toProto(settings.primaries.blue.y), toProto(settings.primaries.white.x), toProto(settings.primaries.white.y)); + if (settings.primariesNameSet) + m_resource->sendPrimariesNamed(settings.primariesNamed); + m_resource->sendTfPower(std::round(settings.transferFunctionPower * 10000)); + m_resource->sendTfNamed(settings.transferFunction); + m_resource->sendLuminances(std::round(settings.luminances.min * 10000), settings.luminances.max, settings.luminances.reference); + + // send expexted display paramateres + m_resource->sendTargetPrimaries(toProto(settings.masteringPrimaries.red.x), toProto(settings.masteringPrimaries.red.y), toProto(settings.masteringPrimaries.green.x), + toProto(settings.masteringPrimaries.green.y), toProto(settings.masteringPrimaries.blue.x), toProto(settings.masteringPrimaries.blue.y), + toProto(settings.masteringPrimaries.white.x), toProto(settings.masteringPrimaries.white.y)); + m_resource->sendTargetLuminance(std::round(settings.masteringLuminances.min * 10000), settings.masteringLuminances.max); + m_resource->sendTargetMaxCll(settings.maxCLL); + m_resource->sendTargetMaxFall(settings.maxFALL); + + m_resource->sendDone(); +} + +bool CColorManagementImageDescriptionInfo::good() { + return m_resource->resource(); +} + +wl_client* CColorManagementImageDescriptionInfo::client() { + return pClient; +} + +CColorManagementProtocol::CColorManagementProtocol(const wl_interface* iface, const int& ver, const std::string& name) : IWaylandProtocol(iface, ver, name) { + ; +} + +void CColorManagementProtocol::bindManager(wl_client* client, void* data, uint32_t ver, uint32_t id) { + const auto RESOURCE = m_vManagers.emplace_back(makeShared(makeShared(client, ver, id))); + + if (!RESOURCE->good()) { + wl_client_post_no_memory(client); + m_vManagers.pop_back(); + return; + } + + LOGM(TRACE, "New xx_color_manager at {:x}", (uintptr_t)RESOURCE.get()); +} + +void CColorManagementProtocol::onImagePreferredChanged() { + for (auto const& feedback : m_vFeedbackSurfaces) { + feedback->resource->sendPreferredChanged(); + } +} + +void CColorManagementProtocol::destroyResource(CColorManager* resource) { + std::erase_if(m_vManagers, [&](const auto& other) { return other.get() == resource; }); +} + +void CColorManagementProtocol::destroyResource(CColorManagementOutput* resource) { + std::erase_if(m_vOutputs, [&](const auto& other) { return other.get() == resource; }); +} + +void CColorManagementProtocol::destroyResource(CColorManagementSurface* resource) { + std::erase_if(m_vSurfaces, [&](const auto& other) { return other.get() == resource; }); +} + +void CColorManagementProtocol::destroyResource(CColorManagementFeedbackSurface* resource) { + std::erase_if(m_vFeedbackSurfaces, [&](const auto& other) { return other.get() == resource; }); +} + +void CColorManagementProtocol::destroyResource(CColorManagementParametricCreator* resource) { + std::erase_if(m_vParametricCreators, [&](const auto& other) { return other.get() == resource; }); +} + +void CColorManagementProtocol::destroyResource(CColorManagementImageDescription* resource) { + std::erase_if(m_vImageDescriptions, [&](const auto& other) { return other.get() == resource; }); +} diff --git a/src/protocols/ColorManagement.hpp b/src/protocols/ColorManagement.hpp new file mode 100644 index 00000000..573abf69 --- /dev/null +++ b/src/protocols/ColorManagement.hpp @@ -0,0 +1,182 @@ +#pragma once + +#include +#include +#include +#include "WaylandProtocol.hpp" +#include "protocols/core/Compositor.hpp" +#include "xx-color-management-v4.hpp" +#include "types/ColorManagement.hpp" + +class CColorManager; +class CColorManagementOutput; +class CColorManagementImageDescription; +class CColorManagementProtocol; + +class CColorManager { + public: + CColorManager(SP resource_); + + bool good(); + + private: + SP resource; +}; + +class CColorManagementOutput { + public: + CColorManagementOutput(SP resource_); + + bool good(); + wl_client* client(); + + WP self; + WP imageDescription; + + private: + SP resource; + wl_client* pClient = nullptr; + + friend class CColorManagementProtocol; + friend class CColorManagementImageDescription; +}; + +class CColorManagementSurface { + public: + CColorManagementSurface(SP surface_); // temporary interface for frog CM + CColorManagementSurface(SP resource_, SP surface_); + + bool good(); + wl_client* client(); + + WP self; + WP surface; + + const SImageDescription& imageDescription(); + bool hasImageDescription(); + + private: + SP resource; + wl_client* pClient = nullptr; + SImageDescription m_imageDescription; + bool m_hasImageDescription = false; + + friend class CFrogColorManagementSurface; +}; + +class CColorManagementFeedbackSurface { + public: + CColorManagementFeedbackSurface(SP resource_, SP surface_); + + bool good(); + wl_client* client(); + + WP self; + WP surface; + + private: + SP resource; + wl_client* pClient = nullptr; + + WP m_currentPreferred; + + friend class CColorManagementProtocol; +}; + +class CColorManagementParametricCreator { + public: + CColorManagementParametricCreator(SP resource_); + + bool good(); + wl_client* client(); + + WP self; + + SImageDescription settings; + + private: + enum eValuesSet : uint32_t { // NOLINT + PC_TF = (1 << 0), + PC_TF_POWER = (1 << 1), + PC_PRIMARIES = (1 << 2), + PC_LUMINANCES = (1 << 3), + PC_MASTERING_PRIMARIES = (1 << 4), + PC_MASTERING_LUMINANCES = (1 << 5), + PC_CLL = (1 << 6), + PC_FALL = (1 << 7), + }; + + SP resource; + wl_client* pClient = nullptr; + uint32_t valuesSet = 0; // enum eValuesSet +}; + +class CColorManagementImageDescription { + public: + CColorManagementImageDescription(SP resource_, bool allowGetInformation = false); + + bool good(); + wl_client* client(); + SP resource(); + + WP self; + + SImageDescription settings; + + private: + SP m_resource; + wl_client* pClient = nullptr; + bool m_allowGetInformation = false; + + friend class CColorManagementOutput; +}; + +class CColorManagementImageDescriptionInfo { + public: + CColorManagementImageDescriptionInfo(SP resource_, const SImageDescription& settings_); + + bool good(); + wl_client* client(); + + private: + SP m_resource; + wl_client* pClient = nullptr; + SImageDescription settings; +}; + +class CColorManagementProtocol : public IWaylandProtocol { + public: + CColorManagementProtocol(const wl_interface* iface, const int& ver, const std::string& name); + + virtual void bindManager(wl_client* client, void* data, uint32_t ver, uint32_t id); + + void onImagePreferredChanged(); + + private: + void destroyResource(CColorManager* resource); + void destroyResource(CColorManagementOutput* resource); + void destroyResource(CColorManagementSurface* resource); + void destroyResource(CColorManagementFeedbackSurface* resource); + void destroyResource(CColorManagementParametricCreator* resource); + void destroyResource(CColorManagementImageDescription* resource); + + std::vector> m_vManagers; + std::vector> m_vOutputs; + std::vector> m_vSurfaces; + std::vector> m_vFeedbackSurfaces; + std::vector> m_vParametricCreators; + std::vector> m_vImageDescriptions; + + friend class CColorManager; + friend class CColorManagementOutput; + friend class CColorManagementSurface; + friend class CColorManagementFeedbackSurface; + friend class CColorManagementParametricCreator; + friend class CColorManagementImageDescription; + + friend class CFrogColorManagementSurface; +}; + +namespace PROTO { + inline UP colorManagement; +}; diff --git a/src/protocols/FrogColorManagement.cpp b/src/protocols/FrogColorManagement.cpp new file mode 100644 index 00000000..3ea20405 --- /dev/null +++ b/src/protocols/FrogColorManagement.cpp @@ -0,0 +1,159 @@ +#include "FrogColorManagement.hpp" +#include "protocols/ColorManagement.hpp" +#include "protocols/core/Subcompositor.hpp" + +CFrogColorManager::CFrogColorManager(SP resource_) : resource(resource_) { + if (!good()) + return; + + resource->setDestroy([](CFrogColorManagementFactoryV1* r) { LOGM(TRACE, "Destroy frog_color_management at {:x} (generated default)", (uintptr_t)r); }); + resource->setOnDestroy([this](CFrogColorManagementFactoryV1* r) { PROTO::frogColorManagement->destroyResource(this); }); + + resource->setGetColorManagedSurface([](CFrogColorManagementFactoryV1* r, wl_resource* surface, uint32_t id) { + LOGM(TRACE, "Get surface for id={}, surface={}", id, (uintptr_t)surface); + auto SURF = CWLSurfaceResource::fromResource(surface); + + if (!SURF) { + LOGM(ERR, "No surface for resource {}", (uintptr_t)surface); + r->error(-1, "Invalid surface (2)"); + return; + } + + if (SURF->role->role() == SURFACE_ROLE_SUBSURFACE) + SURF = ((CSubsurfaceRole*)SURF->role.get())->subsurface->t1Parent(); + + const auto RESOURCE = PROTO::frogColorManagement->m_vSurfaces.emplace_back( + makeShared(makeShared(r->client(), r->version(), id), SURF)); + if (!RESOURCE->good()) { + r->noMemory(); + PROTO::frogColorManagement->m_vSurfaces.pop_back(); + return; + } + + RESOURCE->self = RESOURCE; + }); +} + +bool CFrogColorManager::good() { + return resource->resource(); +} + +CFrogColorManagementSurface::CFrogColorManagementSurface(SP resource_, SP surface_) : surface(surface_), resource(resource_) { + if (!good()) + return; + + pClient = resource->client(); + + if (!surface->colorManagement.valid()) { + const auto RESOURCE = PROTO::colorManagement->m_vSurfaces.emplace_back(makeShared(surface_)); + if (!RESOURCE) { + resource->noMemory(); + PROTO::colorManagement->m_vSurfaces.pop_back(); + return; + } + + RESOURCE->self = RESOURCE; + + surface->colorManagement = RESOURCE; + + resource->setOnDestroy([this](CFrogColorManagedSurface* r) { + LOGM(TRACE, "Destroy frog cm and xx cm for surface {}", (uintptr_t)surface); + if (surface.valid()) + PROTO::colorManagement->destroyResource(surface->colorManagement.get()); + PROTO::frogColorManagement->destroyResource(this); + }); + } else + resource->setOnDestroy([this](CFrogColorManagedSurface* r) { + LOGM(TRACE, "Destroy frog cm surface {}", (uintptr_t)surface); + PROTO::frogColorManagement->destroyResource(this); + }); + + resource->setDestroy([this](CFrogColorManagedSurface* r) { + LOGM(TRACE, "Destroy frog cm surface {}", (uintptr_t)surface); + PROTO::frogColorManagement->destroyResource(this); + }); + + resource->setSetKnownTransferFunction([this](CFrogColorManagedSurface* r, frogColorManagedSurfaceTransferFunction tf) { + LOGM(TRACE, "Set frog cm transfer function {} for {}", (uint32_t)tf, surface->id()); + switch (tf) { + case FROG_COLOR_MANAGED_SURFACE_TRANSFER_FUNCTION_ST2084_PQ: + surface->colorManagement->m_imageDescription.transferFunction = XX_COLOR_MANAGER_V4_TRANSFER_FUNCTION_ST2084_PQ; + break; + ; + case FROG_COLOR_MANAGED_SURFACE_TRANSFER_FUNCTION_GAMMA_22: + if (pqIntentSent) { + LOGM(TRACE, + "FIXME: assuming broken enum value 2 (FROG_COLOR_MANAGED_SURFACE_TRANSFER_FUNCTION_GAMMA_22) referring to eotf value 2 (TRANSFER_FUNCTION_ST2084_PQ)"); + surface->colorManagement->m_imageDescription.transferFunction = XX_COLOR_MANAGER_V4_TRANSFER_FUNCTION_ST2084_PQ; + break; + }; // intended fall through + case FROG_COLOR_MANAGED_SURFACE_TRANSFER_FUNCTION_UNDEFINED: + case FROG_COLOR_MANAGED_SURFACE_TRANSFER_FUNCTION_SCRGB_LINEAR: LOGM(TRACE, std::format("FIXME: add tf support for {}", (uint32_t)tf)); // intended fall through + case FROG_COLOR_MANAGED_SURFACE_TRANSFER_FUNCTION_SRGB: + surface->colorManagement->m_imageDescription.transferFunction = XX_COLOR_MANAGER_V4_TRANSFER_FUNCTION_SRGB; + + surface->colorManagement->m_hasImageDescription = true; + } + }); + resource->setSetKnownContainerColorVolume([this](CFrogColorManagedSurface* r, frogColorManagedSurfacePrimaries primariesName) { + LOGM(TRACE, "Set frog cm primaries {}", (uint32_t)primariesName); + switch (primariesName) { + case FROG_COLOR_MANAGED_SURFACE_PRIMARIES_UNDEFINED: + case FROG_COLOR_MANAGED_SURFACE_PRIMARIES_REC709: surface->colorManagement->m_imageDescription.primaries = NColorPrimaries::BT709; break; + case FROG_COLOR_MANAGED_SURFACE_PRIMARIES_REC2020: surface->colorManagement->m_imageDescription.primaries = NColorPrimaries::BT2020; break; + } + + surface->colorManagement->m_hasImageDescription = true; + }); + resource->setSetRenderIntent([this](CFrogColorManagedSurface* r, frogColorManagedSurfaceRenderIntent intent) { + LOGM(TRACE, "Set frog cm intent {}", (uint32_t)intent); + pqIntentSent = intent == FROG_COLOR_MANAGED_SURFACE_RENDER_INTENT_PERCEPTUAL; + surface->colorManagement->m_hasImageDescription = true; + }); + resource->setSetHdrMetadata([this](CFrogColorManagedSurface* r, uint32_t r_x, uint32_t r_y, uint32_t g_x, uint32_t g_y, uint32_t b_x, uint32_t b_y, uint32_t w_x, uint32_t w_y, + uint32_t max_lum, uint32_t min_lum, uint32_t cll, uint32_t fall) { + LOGM(TRACE, "Set frog primaries r:{},{} g:{},{} b:{},{} w:{},{} luminances {} - {} cll {} fall {}", r_x, r_y, g_x, g_y, b_x, b_y, w_x, w_y, min_lum, max_lum, cll, fall); + surface->colorManagement->m_imageDescription.masteringPrimaries = SImageDescription::SPCPRimaries{.red = {.x = r_x / 50000.0f, .y = r_y / 50000.0f}, + .green = {.x = g_x / 50000.0f, .y = g_y / 50000.0f}, + .blue = {.x = b_x / 50000.0f, .y = b_y / 50000.0f}, + .white = {.x = w_x / 50000.0f, .y = w_y / 50000.0f}}; + surface->colorManagement->m_imageDescription.masteringLuminances.min = min_lum / 10000.0f; + surface->colorManagement->m_imageDescription.masteringLuminances.max = max_lum; + surface->colorManagement->m_imageDescription.maxCLL = cll; + surface->colorManagement->m_imageDescription.maxFALL = fall; + + surface->colorManagement->m_hasImageDescription = true; + }); +} + +bool CFrogColorManagementSurface::good() { + return resource->resource(); +} + +wl_client* CFrogColorManagementSurface::client() { + return pClient; +} + +CFrogColorManagementProtocol::CFrogColorManagementProtocol(const wl_interface* iface, const int& ver, const std::string& name) : IWaylandProtocol(iface, ver, name) { + ; +} + +void CFrogColorManagementProtocol::bindManager(wl_client* client, void* data, uint32_t ver, uint32_t id) { + const auto RESOURCE = m_vManagers.emplace_back(makeShared(makeShared(client, ver, id))); + + if (!RESOURCE->good()) { + wl_client_post_no_memory(client); + m_vManagers.pop_back(); + return; + } + + LOGM(TRACE, "New frog_color_management at {:x}", (uintptr_t)RESOURCE.get()); +} + +void CFrogColorManagementProtocol::destroyResource(CFrogColorManager* resource) { + std::erase_if(m_vManagers, [&](const auto& other) { return other.get() == resource; }); +} + +void CFrogColorManagementProtocol::destroyResource(CFrogColorManagementSurface* resource) { + std::erase_if(m_vSurfaces, [&](const auto& other) { return other.get() == resource; }); +} diff --git a/src/protocols/FrogColorManagement.hpp b/src/protocols/FrogColorManagement.hpp new file mode 100644 index 00000000..6c00e38d --- /dev/null +++ b/src/protocols/FrogColorManagement.hpp @@ -0,0 +1,55 @@ +#pragma once + +#include +#include +#include "WaylandProtocol.hpp" +#include "protocols/core/Compositor.hpp" +#include "frog-color-management-v1.hpp" + +class CFrogColorManager { + public: + CFrogColorManager(SP resource_); + + bool good(); + + private: + SP resource; +}; + +class CFrogColorManagementSurface { + public: + CFrogColorManagementSurface(SP resource_, SP surface_); + + bool good(); + wl_client* client(); + + WP self; + WP surface; + + bool pqIntentSent = false; + + private: + SP resource; + wl_client* pClient = nullptr; +}; + +class CFrogColorManagementProtocol : public IWaylandProtocol { + public: + CFrogColorManagementProtocol(const wl_interface* iface, const int& ver, const std::string& name); + + virtual void bindManager(wl_client* client, void* data, uint32_t ver, uint32_t id); + + private: + void destroyResource(CFrogColorManager* resource); + void destroyResource(CFrogColorManagementSurface* resource); + + std::vector> m_vManagers; + std::vector> m_vSurfaces; + + friend class CFrogColorManager; + friend class CFrogColorManagementSurface; +}; + +namespace PROTO { + inline UP frogColorManagement; +}; diff --git a/src/protocols/core/Compositor.hpp b/src/protocols/core/Compositor.hpp index 2a6f96f6..b347eb64 100644 --- a/src/protocols/core/Compositor.hpp +++ b/src/protocols/core/Compositor.hpp @@ -25,6 +25,8 @@ class CWLSurfaceResource; class CWLSubsurfaceResource; class CViewportResource; class CDRMSyncobjSurfaceResource; +class CColorManagementSurface; +class CFrogColorManagementSurface; class CWLCallbackResource { public: @@ -121,6 +123,7 @@ class CWLSurfaceResource { SP role; WP viewportResource; WP syncobj; // may not be present + WP colorManagement; void breadthfirst(std::function, const Vector2D&, void*)> fn, void* data); CRegion accumulateCurrentBufferDamage(); diff --git a/src/protocols/types/ColorManagement.hpp b/src/protocols/types/ColorManagement.hpp new file mode 100644 index 00000000..e18f0b84 --- /dev/null +++ b/src/protocols/types/ColorManagement.hpp @@ -0,0 +1,47 @@ +#pragma once + +#include "xx-color-management-v4.hpp" + +struct SImageDescription { + int iccFd = -1; + uint32_t iccSize = 0; + + xxColorManagerV4TransferFunction transferFunction = XX_COLOR_MANAGER_V4_TRANSFER_FUNCTION_SRGB; + float transferFunctionPower = 1.0f; + + bool primariesNameSet = false; + xxColorManagerV4Primaries primariesNamed = XX_COLOR_MANAGER_V4_PRIMARIES_SRGB; + // primaries are stored as FP values with the same scale as standard defines (0.0 - 1.0) + // wayland protocol expects int32_t values multiplied by 10000 + // drm expects uint16_t values multiplied by 50000 + // frog protocol expects drm values + struct SPCPRimaries { + struct { + float x = 0; + float y = 0; + } red, green, blue, white; + } primaries, masteringPrimaries; + + // luminances in cd/m² + // protos and drm expect min * 10000 + struct SPCLuminances { + float min = 0.2; // 0.2 cd/m² + uint32_t max = 80; // 80 cd/m² + uint32_t reference = 80; // 80 cd/m² + } luminances; + struct SPCMasteringLuminances { + float min = 0; + uint32_t max = 0; + } masteringLuminances; + + uint32_t maxCLL = 0; + uint32_t maxFALL = 0; +}; + +namespace NColorPrimaries { + static const auto BT709 = + SImageDescription::SPCPRimaries{.red = {.x = 0.64, .y = 0.33}, .green = {.x = 0.30, .y = 0.60}, .blue = {.x = 0.15, .y = 0.06}, .white = {.x = 0.3127, .y = 0.3290}}; + + static const auto BT2020 = + SImageDescription::SPCPRimaries{.red = {.x = 0.708, .y = 0.292}, .green = {.x = 0.170, .y = 0.797}, .blue = {.x = 0.131, .y = 0.046}, .white = {.x = 0.3127, .y = 0.3290}}; +} \ No newline at end of file diff --git a/src/render/Renderer.cpp b/src/render/Renderer.cpp index 4d93d92f..978384d5 100644 --- a/src/render/Renderer.cpp +++ b/src/render/Renderer.cpp @@ -25,6 +25,7 @@ #include "pass/RendererHintsPassElement.hpp" #include "pass/SurfacePassElement.hpp" #include "debug/Log.hpp" +#include "protocols/ColorManagement.hpp" #include using namespace Hyprutils::Utils; @@ -1374,6 +1375,82 @@ void CHyprRenderer::renderMonitor(PHLMONITOR pMonitor) { } } +static const auto BT709 = Aquamarine::IOutput::SChromaticityCoords{ + .red = Aquamarine::IOutput::xy{.x = 0.64, .y = 0.33}, + .green = Aquamarine::IOutput::xy{.x = 0.30, .y = 0.60}, + .blue = Aquamarine::IOutput::xy{.x = 0.15, .y = 0.06}, + .white = Aquamarine::IOutput::xy{.x = 0.3127, .y = 0.3290}, +}; + +static hdr_output_metadata createHDRMetadata(uint8_t eotf, Aquamarine::IOutput::SParsedEDID edid) { + if (eotf == 0) + return hdr_output_metadata{.hdmi_metadata_type1 = hdr_metadata_infoframe{.eotf = 0}}; // empty metadata for SDR + + const auto toNits = [](float value) { return uint16_t(std::round(value)); }; + const auto to16Bit = [](float value) { return uint16_t(std::round(value * 50000)); }; + const auto colorimetry = edid.chromaticityCoords.value_or(BT709); + + Debug::log(TRACE, "ColorManagement primaries {},{} {},{} {},{} {},{}", colorimetry.red.x, colorimetry.red.y, colorimetry.green.x, colorimetry.green.y, colorimetry.blue.x, + colorimetry.blue.y, colorimetry.white.x, colorimetry.white.y); + Debug::log(TRACE, "ColorManagement max avg {}, min {}, max {}", edid.hdrMetadata->desiredMaxFrameAverageLuminance, edid.hdrMetadata->desiredContentMinLuminance, + edid.hdrMetadata->desiredContentMaxLuminance); + return hdr_output_metadata{ + .metadata_type = 0, + .hdmi_metadata_type1 = + hdr_metadata_infoframe{ + .eotf = eotf, + .metadata_type = 0, + .display_primaries = + { + {.x = to16Bit(colorimetry.red.x), .y = to16Bit(colorimetry.red.y)}, + {.x = to16Bit(colorimetry.green.x), .y = to16Bit(colorimetry.green.y)}, + {.x = to16Bit(colorimetry.blue.x), .y = to16Bit(colorimetry.blue.y)}, + }, + .white_point = {.x = to16Bit(colorimetry.white.x), .y = to16Bit(colorimetry.white.y)}, + .max_display_mastering_luminance = toNits(edid.hdrMetadata->desiredMaxFrameAverageLuminance), + .min_display_mastering_luminance = toNits(edid.hdrMetadata->desiredContentMinLuminance * 10000), + .max_cll = toNits(edid.hdrMetadata->desiredMaxFrameAverageLuminance), + .max_fall = toNits(edid.hdrMetadata->desiredMaxFrameAverageLuminance), + }, + }; +} + +static hdr_output_metadata createHDRMetadata(SImageDescription settings, Aquamarine::IOutput::SParsedEDID edid) { + if (settings.transferFunction != XX_COLOR_MANAGER_V4_TRANSFER_FUNCTION_ST2084_PQ) + return hdr_output_metadata{.hdmi_metadata_type1 = hdr_metadata_infoframe{.eotf = 0}}; // empty metadata for SDR + + const auto toNits = [](uint32_t value) { return uint16_t(std::round(value)); }; + const auto to16Bit = [](uint32_t value) { return uint16_t(std::round(value * 50000)); }; + + auto colorimetry = settings.primaries; + auto luminances = settings.masteringLuminances.max > 0 ? + settings.masteringLuminances : + SImageDescription::SPCMasteringLuminances{.min = edid.hdrMetadata->desiredContentMinLuminance, .max = edid.hdrMetadata->desiredContentMaxLuminance}; + + Debug::log(TRACE, "ColorManagement primaries {},{} {},{} {},{} {},{}", colorimetry.red.x, colorimetry.red.y, colorimetry.green.x, colorimetry.green.y, colorimetry.blue.x, + colorimetry.blue.y, colorimetry.white.x, colorimetry.white.y); + Debug::log(TRACE, "ColorManagement min {}, max {}, cll {}, fall {}", luminances.min, luminances.max, settings.maxCLL, settings.maxFALL); + return hdr_output_metadata{ + .metadata_type = 0, + .hdmi_metadata_type1 = + hdr_metadata_infoframe{ + .eotf = 2, + .metadata_type = 0, + .display_primaries = + { + {.x = to16Bit(colorimetry.red.x), .y = to16Bit(colorimetry.red.y)}, + {.x = to16Bit(colorimetry.green.x), .y = to16Bit(colorimetry.green.y)}, + {.x = to16Bit(colorimetry.blue.x), .y = to16Bit(colorimetry.blue.y)}, + }, + .white_point = {.x = to16Bit(colorimetry.white.x), .y = to16Bit(colorimetry.white.y)}, + .max_display_mastering_luminance = toNits(luminances.max), + .min_display_mastering_luminance = toNits(luminances.min * 10000), + .max_cll = toNits(settings.maxCLL), + .max_fall = toNits(settings.maxFALL), + }, + }; +} + bool CHyprRenderer::commitPendingAndDoExplicitSync(PHLMONITOR pMonitor) { // apply timelines for explicit sync // save inFD otherwise reset will reset it @@ -1382,6 +1459,26 @@ bool CHyprRenderer::commitPendingAndDoExplicitSync(PHLMONITOR pMonitor) { if (inFD >= 0) pMonitor->output->state->setExplicitInFence(inFD); + static auto PWIDE = CConfigValue("experimental:wide_color_gamut"); + if (pMonitor->output->state->state().wideColorGamut != *PWIDE) + Debug::log(TRACE, "Setting wide color gamut {}", *PWIDE ? "on" : "off"); + pMonitor->output->state->setWideColorGamut(*PWIDE); + + static auto PHDR = CConfigValue("experimental:hdr"); + + Debug::log(TRACE, "ColorManagement supportsBT2020 {}, supportsPQ {}", pMonitor->output->parsedEDID.supportsBT2020, pMonitor->output->parsedEDID.hdrMetadata->supportsPQ); + if (pMonitor->output->parsedEDID.supportsBT2020 && pMonitor->output->parsedEDID.hdrMetadata->supportsPQ) { + if (pMonitor->activeWorkspace && pMonitor->activeWorkspace->m_bHasFullscreenWindow && pMonitor->activeWorkspace->m_efFullscreenMode == FSMODE_FULLSCREEN) { + const auto WINDOW = pMonitor->activeWorkspace->getFullscreenWindow(); + const auto SURF = WINDOW->m_pWLSurface->resource(); + if (SURF->colorManagement.valid() && SURF->colorManagement->hasImageDescription()) + pMonitor->output->state->setHDRMetadata(createHDRMetadata(SURF->colorManagement.get()->imageDescription(), pMonitor->output->parsedEDID)); + else + pMonitor->output->state->setHDRMetadata(*PHDR ? createHDRMetadata(2, pMonitor->output->parsedEDID) : createHDRMetadata(0, pMonitor->output->parsedEDID)); + } else + pMonitor->output->state->setHDRMetadata(*PHDR ? createHDRMetadata(2, pMonitor->output->parsedEDID) : createHDRMetadata(0, pMonitor->output->parsedEDID)); + } + if (pMonitor->ctmUpdated) { pMonitor->ctmUpdated = false; pMonitor->output->state->setCTM(pMonitor->ctm); diff --git a/src/render/pass/SurfacePassElement.cpp b/src/render/pass/SurfacePassElement.cpp index f2f2627a..71aa26be 100644 --- a/src/render/pass/SurfacePassElement.cpp +++ b/src/render/pass/SurfacePassElement.cpp @@ -79,6 +79,8 @@ void CSurfacePassElement::draw(const CRegion& damage) { DELTALESSTHAN(windowBox.height, data.surface->current.bufferSize.y, 3) /* off by one-or-two */ && (!data.pWindow || (!data.pWindow->m_vRealSize->isBeingAnimated() && !INTERACTIVERESIZEINPROGRESS)) /* not window or not animated/resizing */; + if (data.surface->colorManagement.valid()) + Debug::log(TRACE, "FIXME: rendering surface with color management enabled, should apply necessary transformations"); g_pHyprRenderer->calculateUVForSurface(data.pWindow, data.surface, data.pMonitor->self.lock(), data.mainSurface, windowBox.size(), PROJSIZEUNSCALED, MISALIGNEDFSV1); // check for fractional scale surfaces misaligning the buffer size From c14390785745972903865c824fd324aa708f296a Mon Sep 17 00:00:00 2001 From: vaxerski Date: Tue, 7 Jan 2025 20:27:07 +0100 Subject: [PATCH 0825/2181] config: update animation even if disabled --- src/config/ConfigManager.cpp | 44 +++++++++++++++++------------------- 1 file changed, 21 insertions(+), 23 deletions(-) diff --git a/src/config/ConfigManager.cpp b/src/config/ConfigManager.cpp index bbb3e68f..5839204f 100644 --- a/src/config/ConfigManager.cpp +++ b/src/config/ConfigManager.cpp @@ -2053,37 +2053,35 @@ std::optional CConfigManager::handleAnimation(const std::string& co if (enabledInt != 0 && enabledInt != 1) return "invalid animation on/off state"; - if (enabledInt) { - int64_t speed = -1; + int64_t speed = -1; - // speed - if (isNumber(ARGS[2], true)) { - speed = std::stof(ARGS[2]); + // speed + if (isNumber(ARGS[2], true)) { + speed = std::stof(ARGS[2]); - if (speed <= 0) { - speed = 1.f; - return "invalid speed"; - } - } else { - speed = 10.f; + if (speed <= 0) { + speed = 1.f; return "invalid speed"; } + } else { + speed = 10.f; + return "invalid speed"; + } - std::string bezierName = ARGS[3]; - m_AnimationTree.setConfigForNode(ANIMNAME, enabledInt, speed, ARGS[3], ARGS[4]); + std::string bezierName = ARGS[3]; + m_AnimationTree.setConfigForNode(ANIMNAME, enabledInt, speed, ARGS[3], ARGS[4]); - if (!g_pAnimationManager->bezierExists(bezierName)) { - const auto PANIMNODE = m_AnimationTree.getConfig(ANIMNAME); - PANIMNODE->internalBezier = "default"; - return "no such bezier"; - } + if (!g_pAnimationManager->bezierExists(bezierName)) { + const auto PANIMNODE = m_AnimationTree.getConfig(ANIMNAME); + PANIMNODE->internalBezier = "default"; + return "no such bezier"; + } - if (ARGS[4] != "") { - auto ERR = g_pAnimationManager->styleValidInConfigVar(ANIMNAME, ARGS[4]); + if (ARGS[4] != "") { + auto ERR = g_pAnimationManager->styleValidInConfigVar(ANIMNAME, ARGS[4]); - if (ERR != "") - return ERR; - } + if (ERR != "") + return ERR; } return {}; From 308b1f3afbb150fa008e3147faeee5d3ba7e6876 Mon Sep 17 00:00:00 2001 From: vaxerski Date: Tue, 7 Jan 2025 20:30:44 +0100 Subject: [PATCH 0826/2181] core: minor fixes for animation rewrite --- src/desktop/Workspace.cpp | 2 +- src/managers/AnimationManager.cpp | 5 ++--- 2 files changed, 3 insertions(+), 4 deletions(-) diff --git a/src/desktop/Workspace.cpp b/src/desktop/Workspace.cpp index cab19254..376288ed 100644 --- a/src/desktop/Workspace.cpp +++ b/src/desktop/Workspace.cpp @@ -628,7 +628,7 @@ void CWorkspace::forceReportSizesToWindows() { if (w->m_pWorkspace != m_pSelf || !w->m_bIsMapped || w->isHidden()) continue; - g_pXWaylandManager->setWindowSize(w, w->m_vRealSize->value(), true); + g_pXWaylandManager->setWindowSize(w, w->m_vRealSize->goal(), true); } } diff --git a/src/managers/AnimationManager.cpp b/src/managers/AnimationManager.cpp index 6bfeed83..c1ea1d27 100644 --- a/src/managers/AnimationManager.cpp +++ b/src/managers/AnimationManager.cpp @@ -147,11 +147,10 @@ static void handleUpdate(CAnimatedVariable& av, bool warp) { const auto PBEZIER = g_pAnimationManager->getBezier(av.getBezierName()); const auto POINTY = PBEZIER->getYForPoint(SPENT); - if constexpr (std::same_as) { + if constexpr (std::same_as) updateColorVariable(av, POINTY, animationsDisabled); - } else { + else updateVariable(av, POINTY, animationsDisabled); - } av.onUpdate(); From 67e1e46f9b6285ea260bc88844f85dec6b7d7d02 Mon Sep 17 00:00:00 2001 From: vaxerski Date: Tue, 7 Jan 2025 20:58:49 +0100 Subject: [PATCH 0827/2181] window: fixup fade out animation on silent moves --- src/desktop/Window.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/desktop/Window.cpp b/src/desktop/Window.cpp index 8175fc57..2bd82ad3 100644 --- a/src/desktop/Window.cpp +++ b/src/desktop/Window.cpp @@ -413,10 +413,10 @@ void CWindow::moveToWorkspace(PHLWORKSPACE pWorkspace) { const auto OLDWORKSPACE = m_pWorkspace; - m_iMonitorMovedFrom = OLDWORKSPACE ? OLDWORKSPACE->monitorID() : -1; - m_fMovingToWorkspaceAlpha->setCallbackOnEnd([this](auto) { m_iMonitorMovedFrom = -1; }); m_fMovingToWorkspaceAlpha->setValueAndWarp(1.F); *m_fMovingToWorkspaceAlpha = 0.F; + m_fMovingToWorkspaceAlpha->setCallbackOnEnd([this](auto) { m_iMonitorMovedFrom = -1; }); + m_iMonitorMovedFrom = OLDWORKSPACE ? OLDWORKSPACE->monitorID() : -1; m_pWorkspace = pWorkspace; @@ -541,9 +541,9 @@ void CWindow::onMap() { m_fMovingFromWorkspaceAlpha->resetAllCallbacks(); m_fMovingFromWorkspaceAlpha->setValueAndWarp(1.F); - m_fBorderAngleAnimationProgress->setCallbackOnEnd([&](WP p) { onBorderAngleAnimEnd(p); }, false); m_fBorderAngleAnimationProgress->setValueAndWarp(0.f); + m_fBorderAngleAnimationProgress->setCallbackOnEnd([&](WP p) { onBorderAngleAnimEnd(p); }, false); *m_fBorderAngleAnimationProgress = 1.f; m_fMovingFromWorkspaceAlpha->setValueAndWarp(1.F); From 75727e7c17f31d97d518df8fdb11ec9d802ca5f3 Mon Sep 17 00:00:00 2001 From: staz Date: Wed, 8 Jan 2025 15:28:47 +0500 Subject: [PATCH 0828/2181] protocols: fix compilation error (#8988) --- src/protocols/FrogColorManagement.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/protocols/FrogColorManagement.cpp b/src/protocols/FrogColorManagement.cpp index 3ea20405..6a921981 100644 --- a/src/protocols/FrogColorManagement.cpp +++ b/src/protocols/FrogColorManagement.cpp @@ -88,7 +88,7 @@ CFrogColorManagementSurface::CFrogColorManagementSurface(SPcolorManagement->m_imageDescription.transferFunction = XX_COLOR_MANAGER_V4_TRANSFER_FUNCTION_SRGB; From 5fa2594659f9f4ad19a1afe456ee34bd1c1907b7 Mon Sep 17 00:00:00 2001 From: Maximilian Seidler <78690852+PaideiaDilemma@users.noreply.github.com> Date: Wed, 8 Jan 2025 10:28:55 +0000 Subject: [PATCH 0829/2181] renderer: don't access hdrMetadata optional if it has no value (#8987) --- src/render/Renderer.cpp | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/render/Renderer.cpp b/src/render/Renderer.cpp index 978384d5..cf25d477 100644 --- a/src/render/Renderer.cpp +++ b/src/render/Renderer.cpp @@ -1466,8 +1466,9 @@ bool CHyprRenderer::commitPendingAndDoExplicitSync(PHLMONITOR pMonitor) { static auto PHDR = CConfigValue("experimental:hdr"); - Debug::log(TRACE, "ColorManagement supportsBT2020 {}, supportsPQ {}", pMonitor->output->parsedEDID.supportsBT2020, pMonitor->output->parsedEDID.hdrMetadata->supportsPQ); - if (pMonitor->output->parsedEDID.supportsBT2020 && pMonitor->output->parsedEDID.hdrMetadata->supportsPQ) { + const bool SUPPORTSPQ = pMonitor->output->parsedEDID.hdrMetadata.has_value() ? pMonitor->output->parsedEDID.hdrMetadata->supportsPQ : false; + Debug::log(TRACE, "ColorManagement supportsBT2020 {}, supportsPQ {}", pMonitor->output->parsedEDID.supportsBT2020, SUPPORTSPQ); + if (pMonitor->output->parsedEDID.supportsBT2020 && SUPPORTSPQ) { if (pMonitor->activeWorkspace && pMonitor->activeWorkspace->m_bHasFullscreenWindow && pMonitor->activeWorkspace->m_efFullscreenMode == FSMODE_FULLSCREEN) { const auto WINDOW = pMonitor->activeWorkspace->getFullscreenWindow(); const auto SURF = WINDOW->m_pWLSurface->resource(); From ad64726f5df0fa3cabcd6af9f872d5e8e1f65dbc Mon Sep 17 00:00:00 2001 From: vaxerski Date: Wed, 8 Jan 2025 11:33:41 +0100 Subject: [PATCH 0830/2181] opengl: only allocate offMainFB on demand These are not used by hyprland, only potentially plugins. No need to keep the VRAM allocated all the time --- src/render/OpenGL.cpp | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/src/render/OpenGL.cpp b/src/render/OpenGL.cpp index 93ab5fdf..819791e8 100644 --- a/src/render/OpenGL.cpp +++ b/src/render/OpenGL.cpp @@ -843,7 +843,6 @@ void CHyprOpenGLImpl::begin(PHLMONITOR pMonitor, const CRegion& damage_, CFrameb m_RenderData.pCurrentMonData->offloadFB.alloc(pMonitor->vecPixelSize.x, pMonitor->vecPixelSize.y, pMonitor->output->state->state().drmFormat); m_RenderData.pCurrentMonData->mirrorFB.alloc(pMonitor->vecPixelSize.x, pMonitor->vecPixelSize.y, pMonitor->output->state->state().drmFormat); m_RenderData.pCurrentMonData->mirrorSwapFB.alloc(pMonitor->vecPixelSize.x, pMonitor->vecPixelSize.y, pMonitor->output->state->state().drmFormat); - m_RenderData.pCurrentMonData->offMainFB.alloc(pMonitor->vecPixelSize.x, pMonitor->vecPixelSize.y, pMonitor->output->state->state().drmFormat); m_RenderData.pCurrentMonData->offloadFB.addStencil(m_RenderData.pCurrentMonData->stencilTex); m_RenderData.pCurrentMonData->mirrorFB.addStencil(m_RenderData.pCurrentMonData->stencilTex); @@ -954,6 +953,12 @@ void CHyprOpenGLImpl::end() { m_RenderData.mainFB = nullptr; m_RenderData.outFB = nullptr; + // if we dropped to offMain, release it now. + // if there is a plugin constantly using it, this might be a bit slow, + // but I havent seen a single plugin yet use these, so it's better to drop a bit of vram. + if (m_RenderData.pCurrentMonData->offMainFB.isAllocated()) + m_RenderData.pCurrentMonData->offMainFB.release(); + // check for gl errors const GLenum ERR = glGetError(); @@ -2881,6 +2886,9 @@ void CHyprOpenGLImpl::restoreMatrix() { } void CHyprOpenGLImpl::bindOffMain() { + if (!m_RenderData.pCurrentMonData->offMainFB.isAllocated()) + m_RenderData.pCurrentMonData->offMainFB.alloc(m_RenderData.pMonitor->vecPixelSize.x, m_RenderData.pMonitor->vecPixelSize.y, + m_RenderData.pMonitor->output->state->state().drmFormat); m_RenderData.pCurrentMonData->offMainFB.bind(); clear(CHyprColor(0, 0, 0, 0)); m_RenderData.currentFB = &m_RenderData.pCurrentMonData->offMainFB; From b320bc2dc6e308360936ce4396010359b74558bf Mon Sep 17 00:00:00 2001 From: vaxerski Date: Wed, 8 Jan 2025 12:29:24 +0100 Subject: [PATCH 0831/2181] core: use cpu-buffer hw cursors on nvidia by default --- src/config/ConfigManager.cpp | 6 +++--- src/managers/PointerManager.cpp | 14 ++++++++------ 2 files changed, 11 insertions(+), 9 deletions(-) diff --git a/src/config/ConfigManager.cpp b/src/config/ConfigManager.cpp index 5839204f..def15f26 100644 --- a/src/config/ConfigManager.cpp +++ b/src/config/ConfigManager.cpp @@ -578,7 +578,7 @@ CConfigManager::CConfigManager() { m_pConfig->addConfigValue("opengl:nvidia_anti_flicker", Hyprlang::INT{1}); m_pConfig->addConfigValue("opengl:force_introspection", Hyprlang::INT{1}); // TODO: remove this. I don't think it does us any good to disable intro. - m_pConfig->addConfigValue("cursor:no_hardware_cursors", Hyprlang::INT{2}); + m_pConfig->addConfigValue("cursor:no_hardware_cursors", Hyprlang::INT{0}); m_pConfig->addConfigValue("cursor:no_break_fs_vrr", Hyprlang::INT{0}); m_pConfig->addConfigValue("cursor:min_refresh_rate", Hyprlang::INT{24}); m_pConfig->addConfigValue("cursor:hotspot_padding", Hyprlang::INT{0}); @@ -593,7 +593,7 @@ CConfigManager::CConfigManager() { m_pConfig->addConfigValue("cursor:sync_gsettings_theme", Hyprlang::INT{1}); m_pConfig->addConfigValue("cursor:hide_on_key_press", Hyprlang::INT{0}); m_pConfig->addConfigValue("cursor:hide_on_touch", Hyprlang::INT{1}); - m_pConfig->addConfigValue("cursor:use_cpu_buffer", Hyprlang::INT{0}); + m_pConfig->addConfigValue("cursor:use_cpu_buffer", Hyprlang::INT{2}); m_pConfig->addConfigValue("cursor:warp_back_after_non_mouse_input", Hyprlang::INT{0}); m_pConfig->addConfigValue("autogenerated", Hyprlang::INT{0}); @@ -2741,7 +2741,7 @@ bool CConfigManager::shouldUseSoftwareCursors() { switch (*PNOHW) { case 0: return false; case 1: return true; - default: return g_pHyprRenderer->isNvidia(); + default: break; } return true; diff --git a/src/managers/PointerManager.cpp b/src/managers/PointerManager.cpp index bc166825..85e1c601 100644 --- a/src/managers/PointerManager.cpp +++ b/src/managers/PointerManager.cpp @@ -376,7 +376,9 @@ SP CPointerManager::renderHWCursorBuffer(SPmonitor->output->cursorPlaneSize(); auto const& cursorSize = currentCursorImage.size; - static auto PDUMB = CConfigValue("cursor:use_cpu_buffer"); + static auto PCPUBUFFER = CConfigValue("cursor:use_cpu_buffer"); + + const bool shouldUseCpuBuffer = *PCPUBUFFER == 1 || (*PCPUBUFFER != 0 && g_pHyprRenderer->isNvidia()); if (maxSize == Vector2D{}) return nullptr; @@ -390,12 +392,12 @@ SP CPointerManager::renderHWCursorBuffer(SPmonitor->cursorSwapchain || maxSize != state->monitor->cursorSwapchain->currentOptions().size || - *PDUMB != (state->monitor->cursorSwapchain->getAllocator()->type() != Aquamarine::AQ_ALLOCATOR_TYPE_GBM)) { + shouldUseCpuBuffer != (state->monitor->cursorSwapchain->getAllocator()->type() != Aquamarine::AQ_ALLOCATOR_TYPE_GBM)) { - if (!state->monitor->cursorSwapchain || *PDUMB != (state->monitor->cursorSwapchain->getAllocator()->type() != Aquamarine::AQ_ALLOCATOR_TYPE_GBM)) { + if (!state->monitor->cursorSwapchain || shouldUseCpuBuffer != (state->monitor->cursorSwapchain->getAllocator()->type() != Aquamarine::AQ_ALLOCATOR_TYPE_GBM)) { auto allocator = state->monitor->output->getBackend()->preferredAllocator(); - if (*PDUMB) { + if (shouldUseCpuBuffer) { for (const auto& a : state->monitor->output->getBackend()->getAllocators()) { if (a->type() == Aquamarine::AQ_ALLOCATOR_TYPE_DRM_DUMB) { allocator = a; @@ -415,7 +417,7 @@ SP CPointerManager::renderHWCursorBuffer(SPmonitor->output->getBackend()->preferredAllocator()->drmFD() != g_pCompositor->m_iDRMFD; // We do not set the format (unless shm). If it's unset (DRM_FORMAT_INVALID) then the swapchain will pick for us, // but if it's set, we don't wanna change it. - if (*PDUMB) + if (shouldUseCpuBuffer) options.format = DRM_FORMAT_ARGB8888; if (!state->monitor->cursorSwapchain->reconfigure(options)) { @@ -438,7 +440,7 @@ SP CPointerManager::renderHWCursorBuffer(SPdataCopy(); if (texData.empty()) { From 983bc067dac2e737bc724721c79d87cd81f27501 Mon Sep 17 00:00:00 2001 From: vaxerski Date: Wed, 8 Jan 2025 12:34:43 +0100 Subject: [PATCH 0832/2181] opengl: fix crash on null fb stencil op --- src/render/OpenGL.cpp | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/src/render/OpenGL.cpp b/src/render/OpenGL.cpp index 819791e8..3a4781e7 100644 --- a/src/render/OpenGL.cpp +++ b/src/render/OpenGL.cpp @@ -847,7 +847,6 @@ void CHyprOpenGLImpl::begin(PHLMONITOR pMonitor, const CRegion& damage_, CFrameb m_RenderData.pCurrentMonData->offloadFB.addStencil(m_RenderData.pCurrentMonData->stencilTex); m_RenderData.pCurrentMonData->mirrorFB.addStencil(m_RenderData.pCurrentMonData->stencilTex); m_RenderData.pCurrentMonData->mirrorSwapFB.addStencil(m_RenderData.pCurrentMonData->stencilTex); - m_RenderData.pCurrentMonData->offMainFB.addStencil(m_RenderData.pCurrentMonData->stencilTex); } if (m_RenderData.pCurrentMonData->monitorMirrorFB.isAllocated() && m_RenderData.pMonitor->mirrors.empty()) @@ -2886,9 +2885,13 @@ void CHyprOpenGLImpl::restoreMatrix() { } void CHyprOpenGLImpl::bindOffMain() { - if (!m_RenderData.pCurrentMonData->offMainFB.isAllocated()) + if (!m_RenderData.pCurrentMonData->offMainFB.isAllocated()) { m_RenderData.pCurrentMonData->offMainFB.alloc(m_RenderData.pMonitor->vecPixelSize.x, m_RenderData.pMonitor->vecPixelSize.y, m_RenderData.pMonitor->output->state->state().drmFormat); + + m_RenderData.pCurrentMonData->offMainFB.addStencil(m_RenderData.pCurrentMonData->stencilTex); + } + m_RenderData.pCurrentMonData->offMainFB.bind(); clear(CHyprColor(0, 0, 0, 0)); m_RenderData.currentFB = &m_RenderData.pCurrentMonData->offMainFB; From c9822b08f914da2997e8ef47c8bef8016e5ff313 Mon Sep 17 00:00:00 2001 From: littleblack111 Date: Thu, 9 Jan 2025 05:16:34 +0800 Subject: [PATCH 0833/2181] keybinds: add new window destruction dispatchers (#8962) --- src/managers/KeybindManager.cpp | 84 +++++++++++++++++++++++++++++++-- src/managers/KeybindManager.hpp | 6 ++- 2 files changed, 84 insertions(+), 6 deletions(-) diff --git a/src/managers/KeybindManager.cpp b/src/managers/KeybindManager.cpp index fd4992eb..09f6f928 100644 --- a/src/managers/KeybindManager.cpp +++ b/src/managers/KeybindManager.cpp @@ -12,6 +12,7 @@ #include "eventLoop/EventLoopManager.hpp" #include "debug/Log.hpp" #include "helpers/varlist/VarList.hpp" +#include "../helpers/signal/Signal.hpp" #include #include @@ -63,8 +64,12 @@ CKeybindManager::CKeybindManager() { m_mDispatchers["exec"] = spawn; m_mDispatchers["execr"] = spawnRaw; - m_mDispatchers["killactive"] = killActive; - m_mDispatchers["closewindow"] = kill; + m_mDispatchers["killactive"] = closeActive; + m_mDispatchers["forcekillactive"] = killActive; + m_mDispatchers["closewindow"] = closeWindow; + m_mDispatchers["killwindow"] = killWindow; + m_mDispatchers["signal"] = signalActive; + m_mDispatchers["signalwindow"] = signalWindow; m_mDispatchers["togglefloating"] = toggleActiveFloating; m_mDispatchers["setfloating"] = setActiveFloating; m_mDispatchers["settiled"] = setActiveTiled; @@ -978,17 +983,23 @@ uint64_t CKeybindManager::spawnRawProc(std::string args, PHLWORKSPACE pInitialWo } SDispatchResult CKeybindManager::killActive(std::string args) { + kill(g_pCompositor->m_pLastWindow.lock()->getPID(), SIGKILL); + + return {}; +} + +SDispatchResult CKeybindManager::closeActive(std::string args) { g_pCompositor->closeWindow(g_pCompositor->m_pLastWindow.lock()); return {}; } -SDispatchResult CKeybindManager::kill(std::string args) { +SDispatchResult CKeybindManager::closeWindow(std::string args) { const auto PWINDOW = g_pCompositor->getWindowByRegex(args); if (!PWINDOW) { - Debug::log(ERR, "kill: no window found"); - return {.success = false, .error = "kill: no window found"}; + Debug::log(ERR, "closeWindow: no window found"); + return {.success = false, .error = "closeWindow: no window found"}; } g_pCompositor->closeWindow(PWINDOW); @@ -996,6 +1007,69 @@ SDispatchResult CKeybindManager::kill(std::string args) { return {}; } +SDispatchResult CKeybindManager::killWindow(std::string args) { + const auto PWINDOW = g_pCompositor->getWindowByRegex(args); + + if (!PWINDOW) { + Debug::log(ERR, "killWindow: no window found"); + return {.success = false, .error = "killWindow: no window found"}; + } + + kill(PWINDOW->getPID(), SIGKILL); + + return {}; +} + +SDispatchResult CKeybindManager::signalActive(std::string args) { + if (!std::all_of(args.begin(), args.end(), ::isdigit)) + return {.success = false, .error = "signalActive: signal has to be int"}; + + try { + const auto SIGNALNUM = std::stoi(args); + if (SIGNALNUM < 1 || SIGNALNUM > 31) { + Debug::log(ERR, "signalActive: invalid signal number {}", SIGNALNUM); + return {.success = false, .error = std::format("signalActive: invalid signal number {}", SIGNALNUM)}; + } + kill(g_pCompositor->m_pLastWindow.lock()->getPID(), SIGNALNUM); + } catch (const std::exception& e) { + Debug::log(ERR, "signalActive: invalid signal format \"{}\"", args); + return {.success = false, .error = std::format("signalActive: invalid signal format \"{}\"", args)}; + } + + kill(g_pCompositor->m_pLastWindow.lock()->getPID(), std::stoi(args)); + + return {}; +} + +SDispatchResult CKeybindManager::signalWindow(std::string args) { + const auto WINDOWREGEX = args.substr(0, args.find_first_of(',')); + const auto SIGNAL = args.substr(args.find_first_of(',') + 1); + + const auto PWINDOW = g_pCompositor->getWindowByRegex(WINDOWREGEX); + + if (!PWINDOW) { + Debug::log(ERR, "signalWindow: no window"); + return {.success = false, .error = "signalWindow: no window"}; + } + + if (!std::all_of(SIGNAL.begin(), SIGNAL.end(), ::isdigit)) + return {.success = false, .error = "signalWindow: signal has to be int"}; + + try { + const auto SIGNALNUM = std::stoi(SIGNAL); + if (SIGNALNUM < 1 || SIGNALNUM > 31) { + Debug::log(ERR, "signalWindow: invalid signal number {}", SIGNALNUM); + return {.success = false, .error = std::format("signalWindow: invalid signal number {}", SIGNALNUM)}; + } + kill(PWINDOW->getPID(), SIGNALNUM); + } catch (const std::exception& e) { + Debug::log(ERR, "signalWindow: invalid signal format \"{}\"", SIGNAL); + return {.success = false, .error = std::format("signalWindow: invalid signal format \"{}\"", SIGNAL)}; + } + + return {}; +} + void CKeybindManager::clearKeybinds() { m_vKeybinds.clear(); } diff --git a/src/managers/KeybindManager.hpp b/src/managers/KeybindManager.hpp index 02a39df9..76c72187 100644 --- a/src/managers/KeybindManager.hpp +++ b/src/managers/KeybindManager.hpp @@ -152,8 +152,12 @@ class CKeybindManager { static uint64_t spawnWithRules(std::string, PHLWORKSPACE pInitialWorkspace); // -------------- Dispatchers -------------- // + static SDispatchResult closeActive(std::string); static SDispatchResult killActive(std::string); - static SDispatchResult kill(std::string); + static SDispatchResult closeWindow(std::string); + static SDispatchResult killWindow(std::string); + static SDispatchResult signalActive(std::string); + static SDispatchResult signalWindow(std::string); static SDispatchResult spawn(std::string); static SDispatchResult spawnRaw(std::string); static SDispatchResult toggleActiveFloating(std::string); From e66eab7b6a90514251439f661454c536afa3e5c8 Mon Sep 17 00:00:00 2001 From: Maximilian Seidler <78690852+PaideiaDilemma@users.noreply.github.com> Date: Thu, 9 Jan 2025 11:13:47 +0000 Subject: [PATCH 0834/2181] animationmgr: don't warp based on POINTY value (#9000) --- src/managers/AnimationManager.cpp | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/src/managers/AnimationManager.cpp b/src/managers/AnimationManager.cpp index c1ea1d27..f0f6a980 100644 --- a/src/managers/AnimationManager.cpp +++ b/src/managers/AnimationManager.cpp @@ -40,7 +40,7 @@ CHyprAnimationManager::CHyprAnimationManager() { template void updateVariable(CAnimatedVariable& av, const float POINTY, bool warp = false) { - if (POINTY >= 1.f || warp || av.value() == av.goal()) { + if (warp || av.value() == av.goal()) { av.warp(); return; } @@ -50,7 +50,7 @@ void updateVariable(CAnimatedVariable& av, const float POINTY, bool war } void updateColorVariable(CAnimatedVariable& av, const float POINTY, bool warp) { - if (POINTY >= 1.f || warp || av.value() == av.goal()) { + if (warp || av.value() == av.goal()) { av.warp(); return; } @@ -146,11 +146,12 @@ static void handleUpdate(CAnimatedVariable& av, bool warp) { const auto SPENT = av.getPercent(); const auto PBEZIER = g_pAnimationManager->getBezier(av.getBezierName()); const auto POINTY = PBEZIER->getYForPoint(SPENT); + const bool WARP = animationsDisabled || SPENT >= 1.f; if constexpr (std::same_as) - updateColorVariable(av, POINTY, animationsDisabled); + updateColorVariable(av, POINTY, WARP); else - updateVariable(av, POINTY, animationsDisabled); + updateVariable(av, POINTY, WARP); av.onUpdate(); From 2d1ebadb9b65ef8d57f998031f022b29842b40e4 Mon Sep 17 00:00:00 2001 From: zakk4223 Date: Thu, 9 Jan 2025 14:52:26 -0600 Subject: [PATCH 0835/2181] selectors: add a tag: to for matching window tag(s) by regex (#8985) --- src/Compositor.cpp | 15 +++++++++++++++ src/managers/KeybindManager.hpp | 1 + 2 files changed, 16 insertions(+) diff --git a/src/Compositor.cpp b/src/Compositor.cpp index 3d159042..79574084 100644 --- a/src/Compositor.cpp +++ b/src/Compositor.cpp @@ -2401,6 +2401,9 @@ PHLWINDOW CCompositor::getWindowByRegex(const std::string& regexp_) { } else if (regexp.starts_with("initialtitle:")) { mode = MODE_INITIAL_TITLE_REGEX; regexCheck = regexp.substr(13); + } else if (regexp.starts_with("tag:")) { + mode = MODE_TAG_REGEX; + regexCheck = regexp.substr(4); } else if (regexp.starts_with("address:")) { mode = MODE_ADDRESS; matchCheck = regexp.substr(8); @@ -2438,6 +2441,18 @@ PHLWINDOW CCompositor::getWindowByRegex(const std::string& regexp_) { continue; break; } + case MODE_TAG_REGEX: { + bool tagMatched = false; + for (auto const& t : w->m_tags.getTags()) { + if (RE2::FullMatch(t, regexCheck)) { + tagMatched = true; + break; + } + } + if (!tagMatched) + continue; + break; + } case MODE_ADDRESS: { std::string addr = std::format("0x{:x}", (uintptr_t)w.get()); if (matchCheck != addr) diff --git a/src/managers/KeybindManager.hpp b/src/managers/KeybindManager.hpp index 76c72187..d01ec75b 100644 --- a/src/managers/KeybindManager.hpp +++ b/src/managers/KeybindManager.hpp @@ -49,6 +49,7 @@ enum eFocusWindowMode : uint8_t { MODE_INITIAL_CLASS_REGEX, MODE_TITLE_REGEX, MODE_INITIAL_TITLE_REGEX, + MODE_TAG_REGEX, MODE_ADDRESS, MODE_PID, MODE_ACTIVE_WINDOW From 85aba23cbeea2e651fa1d3f88345f9ba4d4bd4a8 Mon Sep 17 00:00:00 2001 From: littleblack111 Date: Fri, 10 Jan 2025 04:54:25 +0800 Subject: [PATCH 0836/2181] ci(clang-format): directly do the clang-format instead of error (#8955) Will suggest a clang-format fix on every MR that violates it. --- .github/workflows/ci.yaml | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) diff --git a/.github/workflows/ci.yaml b/.github/workflows/ci.yaml index 22421d18..65bfa1ca 100644 --- a/.github/workflows/ci.yaml +++ b/.github/workflows/ci.yaml @@ -126,3 +126,27 @@ jobs: - name: clang-format check run: ninja -C build clang-format-check + + - name: clang-format apply + if: ${{ failure() && github.event_name == 'pull_request' }} + run: ninja -C build clang-format + + - name: Create patch + if: ${{ failure() && github.event_name == 'pull_request' }} + run: | + echo 'Please fix the formatting issues by running [`clang-format`](https://wiki.hyprland.org/Contributing-and-Debugging/PR-Guidelines/#code-style), or directly apply this patch:' > clang-format.patch + echo '
' >> clang-format.patch + echo 'clang-format.patch' >> clang-format.patch + echo >> clang-format.patch + echo '```diff' >> clang-format.patch + git diff >> clang-format.patch + echo '```' >> clang-format.patch + echo >> clang-format.patch + echo '
' >> clang-format.patch + + - name: Comment patch + if: ${{ failure() && github.event_name == 'pull_request' }} + uses: mshick/add-pr-comment@v2 + with: + message-path: | + clang-format.patch From 9dc9366fc65ca8b4f18f6554d0b147baceda01f0 Mon Sep 17 00:00:00 2001 From: vaxerski Date: Thu, 9 Jan 2025 22:08:16 +0100 Subject: [PATCH 0837/2181] config: fix animations requiring all args fixes #9009 --- src/config/ConfigManager.cpp | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/config/ConfigManager.cpp b/src/config/ConfigManager.cpp index def15f26..b575a167 100644 --- a/src/config/ConfigManager.cpp +++ b/src/config/ConfigManager.cpp @@ -2053,6 +2053,11 @@ std::optional CConfigManager::handleAnimation(const std::string& co if (enabledInt != 0 && enabledInt != 1) return "invalid animation on/off state"; + if (!enabledInt) { + m_AnimationTree.setConfigForNode(ANIMNAME, enabledInt, 1, "default"); + return {}; + } + int64_t speed = -1; // speed From f9c37ca43b14a4564d92b5788c81bf16f7bb719c Mon Sep 17 00:00:00 2001 From: Dardo D Kleiner Date: Thu, 9 Jan 2025 17:38:38 -0500 Subject: [PATCH 0838/2181] windows: honor xdg_toplevel_set_fullscreen output hint (#8965) Co-authored-by: Dardo D Kleiner --- src/desktop/Window.cpp | 21 ++++++++++++++++----- src/desktop/Window.hpp | 4 +++- src/events/Windows.cpp | 25 +++++++++++++++++++++++++ src/protocols/XDGShell.cpp | 8 +++++++- src/protocols/XDGShell.hpp | 7 ++++--- 5 files changed, 55 insertions(+), 10 deletions(-) diff --git a/src/desktop/Window.cpp b/src/desktop/Window.cpp index 2bd82ad3..65e1eb79 100644 --- a/src/desktop/Window.cpp +++ b/src/desktop/Window.cpp @@ -1382,15 +1382,26 @@ void CWindow::activate(bool force) { } void CWindow::onUpdateState() { - std::optional requestsFS = m_pXDGSurface ? m_pXDGSurface->toplevel->state.requestsFullscreen : m_pXWaylandSurface->state.requestsFullscreen; - std::optional requestsMX = m_pXDGSurface ? m_pXDGSurface->toplevel->state.requestsMaximize : m_pXWaylandSurface->state.requestsMaximize; + std::optional requestsFS = m_pXDGSurface ? m_pXDGSurface->toplevel->state.requestsFullscreen : m_pXWaylandSurface->state.requestsFullscreen; + std::optional requestsID = m_pXDGSurface ? m_pXDGSurface->toplevel->state.requestsFullscreenMonitor : MONITOR_INVALID; + std::optional requestsMX = m_pXDGSurface ? m_pXDGSurface->toplevel->state.requestsMaximize : m_pXWaylandSurface->state.requestsMaximize; if (requestsFS.has_value() && !(m_eSuppressedEvents & SUPPRESS_FULLSCREEN)) { - bool fs = requestsFS.value(); - if (m_bIsMapped) { - g_pCompositor->changeWindowFullscreenModeClient(m_pSelf.lock(), FSMODE_FULLSCREEN, requestsFS.value()); + if (requestsID.has_value() && (requestsID.value() != MONITOR_INVALID) && !(m_eSuppressedEvents & SUPPRESS_FULLSCREEN_OUTPUT)) { + if (m_bIsMapped) { + const auto monitor = g_pCompositor->getMonitorFromID(requestsID.value()); + g_pCompositor->moveWindowToWorkspaceSafe(m_pSelf.lock(), monitor->activeWorkspace); + g_pCompositor->setActiveMonitor(monitor); + } + + if (!m_bIsMapped) + m_iWantsInitialFullscreenMonitor = requestsID.value(); } + bool fs = requestsFS.value(); + if (m_bIsMapped) + g_pCompositor->changeWindowFullscreenModeClient(m_pSelf.lock(), FSMODE_FULLSCREEN, requestsFS.value()); + if (!m_bIsMapped) m_bWantsInitialFullscreen = fs; } diff --git a/src/desktop/Window.hpp b/src/desktop/Window.hpp index 37189a00..d503ac3b 100644 --- a/src/desktop/Window.hpp +++ b/src/desktop/Window.hpp @@ -57,6 +57,7 @@ enum eSuppressEvents : uint8_t { SUPPRESS_MAXIMIZE = 1 << 1, SUPPRESS_ACTIVATE = 1 << 2, SUPPRESS_ACTIVATE_FOCUSONLY = 1 << 3, + SUPPRESS_FULLSCREEN_OUTPUT = 1 << 4, }; class IWindowTransformer; @@ -288,7 +289,8 @@ class CWindow { bool m_bNoInitialFocus = false; // Fullscreen and Maximize - bool m_bWantsInitialFullscreen = false; + bool m_bWantsInitialFullscreen = false; + MONITORID m_iWantsInitialFullscreenMonitor = MONITOR_INVALID; // bitfield eSuppressEvents uint64_t m_eSuppressedEvents = SUPPRESS_NONE; diff --git a/src/events/Windows.cpp b/src/events/Windows.cpp index 8082cdc9..ff69e83f 100644 --- a/src/events/Windows.cpp +++ b/src/events/Windows.cpp @@ -131,6 +131,7 @@ void Events::listener_mapWindow(void* owner, void* data) { std::optional requestedFSState; if (PWINDOW->m_bWantsInitialFullscreen || (PWINDOW->m_bIsX11 && PWINDOW->m_pXWaylandSurface->fullscreen)) requestedClientFSMode = FSMODE_FULLSCREEN; + MONITORID requestedFSMonitor = PWINDOW->m_iWantsInitialFullscreenMonitor; for (auto const& r : PWINDOW->m_vMatchedRules) { switch (r->ruleType) { @@ -168,6 +169,7 @@ void Events::listener_mapWindow(void* owner, void* data) { PWORKSPACE = PWINDOW->m_pWorkspace; Debug::log(LOG, "Rule monitor, applying to {:mw}", PWINDOW); + requestedFSMonitor = MONITOR_INVALID; } catch (std::exception& e) { Debug::log(ERR, "Rule monitor failed, rule: {} -> {} | err: {}", r->szRule, r->szValue, e.what()); } break; } @@ -186,6 +188,7 @@ void Events::listener_mapWindow(void* owner, void* data) { requestedWorkspace = ""; Debug::log(LOG, "Rule workspace matched by {}, {} applied.", PWINDOW, r->szValue); + requestedFSMonitor = MONITOR_INVALID; break; } case CWindowRule::RULE_FLOAT: { @@ -227,6 +230,8 @@ void Events::listener_mapWindow(void* owner, void* data) { PWINDOW->m_eSuppressedEvents |= SUPPRESS_ACTIVATE; else if (vars[i] == "activatefocus") PWINDOW->m_eSuppressedEvents |= SUPPRESS_ACTIVATE_FOCUSONLY; + else if (vars[i] == "fullscreenoutput") + PWINDOW->m_eSuppressedEvents |= SUPPRESS_FULLSCREEN_OUTPUT; else Debug::log(ERR, "Error while parsing suppressevent windowrule: unknown event type {}", vars[i]); } @@ -337,10 +342,30 @@ void Events::listener_mapWindow(void* owner, void* data) { PMONITOR = g_pCompositor->m_pLastMonitor.lock(); } + + requestedFSMonitor = MONITOR_INVALID; } else workspaceSilent = false; } + if (PWINDOW->m_eSuppressedEvents & SUPPRESS_FULLSCREEN_OUTPUT) + requestedFSMonitor = MONITOR_INVALID; + else if (requestedFSMonitor != MONITOR_INVALID) { + if (const auto PM = g_pCompositor->getMonitorFromID(requestedFSMonitor); PM) + PWINDOW->m_pMonitor = PM; + + const auto PMONITORFROMID = PWINDOW->m_pMonitor.lock(); + + if (PWINDOW->m_pMonitor != PMONITOR) { + g_pKeybindManager->m_mDispatchers["focusmonitor"](std::to_string(PWINDOW->monitorID())); + PMONITOR = PMONITORFROMID; + } + PWINDOW->m_pWorkspace = PMONITOR->activeSpecialWorkspace ? PMONITOR->activeSpecialWorkspace : PMONITOR->activeWorkspace; + PWORKSPACE = PWINDOW->m_pWorkspace; + + Debug::log(LOG, "Requested monitor, applying to {:mw}", PWINDOW); + } + if (PWORKSPACE->m_bDefaultFloating) PWINDOW->m_bIsFloating = true; diff --git a/src/protocols/XDGShell.cpp b/src/protocols/XDGShell.cpp index 282aec47..6b7cb3c1 100644 --- a/src/protocols/XDGShell.cpp +++ b/src/protocols/XDGShell.cpp @@ -5,6 +5,7 @@ #include "../managers/SeatManager.hpp" #include "core/Seat.hpp" #include "core/Compositor.hpp" +#include "protocols/core/Output.hpp" #include #include @@ -191,9 +192,14 @@ CXDGToplevelResource::CXDGToplevelResource(SP resource_, SPsetSetFullscreen([this](CXdgToplevel* r, wl_resource* output) { + if (output) + if (const auto PM = CWLOutputResource::fromResource(output)->monitor; PM) + state.requestsFullscreenMonitor = PM->ID; + state.requestsFullscreen = true; events.stateChanged.emit(); state.requestsFullscreen.reset(); + state.requestsFullscreenMonitor.reset(); }); resource->setUnsetFullscreen([this](CXdgToplevel* r) { @@ -205,7 +211,7 @@ CXDGToplevelResource::CXDGToplevelResource(SP resource_, SPsetSetMinimized([this](CXdgToplevel* r) { state.requestsMinimize = true; events.stateChanged.emit(); - state.requestsFullscreen.reset(); + state.requestsMinimize.reset(); }); resource->setSetParent([this](CXdgToplevel* r, wl_resource* parentR) { diff --git a/src/protocols/XDGShell.hpp b/src/protocols/XDGShell.hpp index ef847f3b..6eef99bb 100644 --- a/src/protocols/XDGShell.hpp +++ b/src/protocols/XDGShell.hpp @@ -123,9 +123,10 @@ class CXDGToplevelResource { std::string appid; // volatile state: is reset after the stateChanged signal fires - std::optional requestsMaximize; - std::optional requestsFullscreen; - std::optional requestsMinimize; + std::optional requestsMaximize; + std::optional requestsFullscreen; + std::optional requestsFullscreenMonitor; + std::optional requestsMinimize; } state; struct { From 8475a8ef992fd45be41b3217ac0f0dd71235f257 Mon Sep 17 00:00:00 2001 From: vaxerski Date: Fri, 10 Jan 2025 14:09:09 +0100 Subject: [PATCH 0839/2181] core: always use goal size to send to clients --- src/desktop/Window.cpp | 2 +- src/managers/KeybindManager.cpp | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/desktop/Window.cpp b/src/desktop/Window.cpp index 65e1eb79..5608daef 100644 --- a/src/desktop/Window.cpp +++ b/src/desktop/Window.cpp @@ -444,7 +444,7 @@ void CWindow::moveToWorkspace(PHLWORKSPACE pWorkspace) { } // update xwayland coords - g_pXWaylandManager->setWindowSize(m_pSelf.lock(), m_vRealSize->value()); + g_pXWaylandManager->setWindowSize(m_pSelf.lock(), m_vRealSize->goal()); if (OLDWORKSPACE && g_pCompositor->isWorkspaceSpecial(OLDWORKSPACE->m_iID) && OLDWORKSPACE->getWindows() == 0 && *PCLOSEONLASTSPECIAL) { if (const auto PMONITOR = OLDWORKSPACE->m_pMonitor.lock(); PMONITOR) diff --git a/src/managers/KeybindManager.cpp b/src/managers/KeybindManager.cpp index 09f6f928..b0bd0e9c 100644 --- a/src/managers/KeybindManager.cpp +++ b/src/managers/KeybindManager.cpp @@ -1891,8 +1891,8 @@ SDispatchResult CKeybindManager::workspaceOpt(std::string args) { continue; if (!w->m_bRequestsFloat && w->m_bIsFloating != PWORKSPACE->m_bDefaultFloating) { - const auto SAVEDPOS = w->m_vRealPosition->value(); - const auto SAVEDSIZE = w->m_vRealSize->value(); + const auto SAVEDPOS = w->m_vRealPosition->goal(); + const auto SAVEDSIZE = w->m_vRealSize->goal(); w->m_bIsFloating = PWORKSPACE->m_bDefaultFloating; g_pLayoutManager->getCurrentLayout()->changeWindowFloatingMode(w); From da9252a23e69fc4d34beca73ebcc90b03af0ed2a Mon Sep 17 00:00:00 2001 From: littleblack111 Date: Fri, 10 Jan 2025 23:16:52 +0800 Subject: [PATCH 0840/2181] keybinds: fix nullptr deref in forcekillactive (#9021) --- src/managers/KeybindManager.cpp | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/src/managers/KeybindManager.cpp b/src/managers/KeybindManager.cpp index b0bd0e9c..4cd97913 100644 --- a/src/managers/KeybindManager.cpp +++ b/src/managers/KeybindManager.cpp @@ -983,7 +983,14 @@ uint64_t CKeybindManager::spawnRawProc(std::string args, PHLWORKSPACE pInitialWo } SDispatchResult CKeybindManager::killActive(std::string args) { - kill(g_pCompositor->m_pLastWindow.lock()->getPID(), SIGKILL); + const auto PWINDOW = g_pCompositor->m_pLastWindow.lock(); + + if (!PWINDOW) { + Debug::log(ERR, "killActive: no window found"); + return {.success = false, .error = "killActive: no window found"}; + } + + kill(PWINDOW->getPID(), SIGKILL); return {}; } From b5fb6110ab1f75440b4b90d09f95d304d8c2080b Mon Sep 17 00:00:00 2001 From: Vaxry <43317083+vaxerski@users.noreply.github.com> Date: Fri, 10 Jan 2025 19:09:40 +0100 Subject: [PATCH 0841/2181] core: Add a periodic donation request (#8981) Will fire once in december and july. Disableable with `ecosystem:no_donation:nag` --- src/Compositor.cpp | 9 +- src/config/ConfigManager.cpp | 1 + src/helpers/MiscFunctions.cpp | 27 ------ src/helpers/MiscFunctions.hpp | 1 - src/helpers/fs/FsUtils.cpp | 107 ++++++++++++++++++++++++ src/helpers/fs/FsUtils.hpp | 15 ++++ src/managers/DonationNagManager.cpp | 114 ++++++++++++++++++++++++++ src/managers/DonationNagManager.hpp | 16 ++++ src/managers/VersionKeeperManager.cpp | 92 +++------------------ src/managers/VersionKeeperManager.hpp | 11 +-- 10 files changed, 278 insertions(+), 115 deletions(-) create mode 100644 src/helpers/fs/FsUtils.cpp create mode 100644 src/helpers/fs/FsUtils.hpp create mode 100644 src/managers/DonationNagManager.cpp create mode 100644 src/managers/DonationNagManager.hpp diff --git a/src/Compositor.cpp b/src/Compositor.cpp index 79574084..fcd15312 100644 --- a/src/Compositor.cpp +++ b/src/Compositor.cpp @@ -9,6 +9,7 @@ #include "managers/PointerManager.hpp" #include "managers/SeatManager.hpp" #include "managers/VersionKeeperManager.hpp" +#include "managers/DonationNagManager.hpp" #include "managers/eventLoop/EventLoopManager.hpp" #include #include @@ -25,6 +26,7 @@ #endif #include #include "helpers/varlist/VarList.hpp" +#include "helpers/fs/FsUtils.hpp" #include "protocols/FractionalScale.hpp" #include "protocols/PointerConstraints.hpp" #include "protocols/LayerShell.hpp" @@ -544,6 +546,8 @@ void CCompositor::cleanup() { g_pSeatManager.reset(); g_pHyprCtl.reset(); g_pEventLoopManager.reset(); + g_pVersionKeeperMgr.reset(); + g_pDonationNagManager.reset(); if (m_pAqBackend) m_pAqBackend.reset(); @@ -645,6 +649,9 @@ void CCompositor::initManagers(eManagersInitStage stage) { Debug::log(LOG, "Creating the VersionKeeper!"); g_pVersionKeeperMgr = std::make_unique(); + Debug::log(LOG, "Creating the DonationNag!"); + g_pDonationNagManager = std::make_unique(); + Debug::log(LOG, "Starting XWayland"); g_pXWayland = std::make_unique(g_pCompositor->m_bEnableXwayland); } break; @@ -2645,7 +2652,7 @@ void CCompositor::performUserChecks() { } if (!*PNOCHECKQTUTILS) { - if (!executableExistsInPath("hyprland-dialog")) { + if (!NFsUtils::executableExistsInPath("hyprland-dialog")) { g_pHyprNotificationOverlay->addNotification( "Your system does not have hyprland-qtutils installed. This is a runtime dependency for some dialogs. Consider installing it.", CHyprColor{}, 15000, ICON_WARNING); } diff --git a/src/config/ConfigManager.cpp b/src/config/ConfigManager.cpp index b575a167..3f8862ee 100644 --- a/src/config/ConfigManager.cpp +++ b/src/config/ConfigManager.cpp @@ -621,6 +621,7 @@ CConfigManager::CConfigManager() { m_pConfig->addConfigValue("render:ctm_animation", Hyprlang::INT{2}); m_pConfig->addConfigValue("ecosystem:no_update_news", Hyprlang::INT{0}); + m_pConfig->addConfigValue("ecosystem:no_donation_nag", Hyprlang::INT{0}); m_pConfig->addConfigValue("experimental:wide_color_gamut", Hyprlang::INT{0}); m_pConfig->addConfigValue("experimental:hdr", Hyprlang::INT{0}); diff --git a/src/helpers/MiscFunctions.cpp b/src/helpers/MiscFunctions.cpp index e970b781..08a1106a 100644 --- a/src/helpers/MiscFunctions.cpp +++ b/src/helpers/MiscFunctions.cpp @@ -911,30 +911,3 @@ float stringToPercentage(const std::string& VALUE, const float REL) { else return std::stof(VALUE); } - -bool executableExistsInPath(const std::string& exe) { - if (!getenv("PATH")) - return false; - - static CVarList paths(getenv("PATH"), 0, ':', true); - - for (auto& p : paths) { - std::string path = p + std::string{"/"} + exe; - std::error_code ec; - if (!std::filesystem::exists(path, ec) || ec) - continue; - - if (!std::filesystem::is_regular_file(path, ec) || ec) - continue; - - auto stat = std::filesystem::status(path, ec); - if (ec) - continue; - - auto perms = stat.permissions(); - - return std::filesystem::perms::none != (perms & std::filesystem::perms::others_exec); - } - - return false; -} diff --git a/src/helpers/MiscFunctions.hpp b/src/helpers/MiscFunctions.hpp index b179b3d6..64802279 100644 --- a/src/helpers/MiscFunctions.hpp +++ b/src/helpers/MiscFunctions.hpp @@ -40,7 +40,6 @@ bool envEnabled(const std::string& env); int allocateSHMFile(size_t len); bool allocateSHMFilePair(size_t size, int* rw_fd_ptr, int* ro_fd_ptr); float stringToPercentage(const std::string& VALUE, const float REL); -bool executableExistsInPath(const std::string& exe); template [[deprecated("use std::format instead")]] std::string getFormat(std::format_string fmt, Args&&... args) { diff --git a/src/helpers/fs/FsUtils.cpp b/src/helpers/fs/FsUtils.cpp new file mode 100644 index 00000000..0bc2e685 --- /dev/null +++ b/src/helpers/fs/FsUtils.cpp @@ -0,0 +1,107 @@ +#include "FsUtils.hpp" +#include "../../debug/Log.hpp" + +#include +#include + +#include +#include +using namespace Hyprutils::String; + +std::optional NFsUtils::getDataHome() { + const auto DATA_HOME = getenv("XDG_DATA_HOME"); + + std::string dataRoot; + + if (!DATA_HOME) { + const auto HOME = getenv("HOME"); + + if (!HOME) { + Debug::log(ERR, "FsUtils::getDataHome: can't get data home: no $HOME or $XDG_DATA_HOME"); + return std::nullopt; + } + + dataRoot = HOME + std::string{"/.local/share/"}; + } else + dataRoot = DATA_HOME + std::string{"/"}; + + std::error_code ec; + if (!std::filesystem::exists(dataRoot, ec) || ec) { + Debug::log(ERR, "FsUtils::getDataHome: can't get data home: inaccessible / missing"); + return std::nullopt; + } + + dataRoot += "hyprland/"; + + if (!std::filesystem::exists(dataRoot, ec) || ec) { + Debug::log(LOG, "FsUtils::getDataHome: no hyprland data home, creating."); + std::filesystem::create_directory(dataRoot, ec); + if (ec) { + Debug::log(ERR, "FsUtils::getDataHome: can't create new data home for hyprland"); + return std::nullopt; + } + std::filesystem::permissions(dataRoot, std::filesystem::perms::owner_read | std::filesystem::perms::owner_write | std::filesystem::perms::owner_exec, ec); + if (ec) + Debug::log(WARN, "FsUtils::getDataHome: couldn't set perms on hyprland data store. Proceeding anyways."); + } + + if (!std::filesystem::exists(dataRoot, ec) || ec) { + Debug::log(ERR, "FsUtils::getDataHome: no hyprland data home, failed to create."); + return std::nullopt; + } + + return dataRoot; +} + +std::optional NFsUtils::readFileAsString(const std::string& path) { + std::error_code ec; + + if (!std::filesystem::exists(path, ec) || ec) + return std::nullopt; + + std::ifstream file(path); + if (!file.good()) + return std::nullopt; + + return trim(std::string((std::istreambuf_iterator(file)), (std::istreambuf_iterator()))); +} + +bool NFsUtils::writeToFile(const std::string& path, const std::string& content) { + std::ofstream of(path, std::ios::trunc); + if (!of.good()) { + Debug::log(ERR, "CVersionKeeperManager: couldn't open an ofstream for writing the version file."); + return false; + } + + of << content; + of.close(); + + return true; +} + +bool NFsUtils::executableExistsInPath(const std::string& exe) { + if (!getenv("PATH")) + return false; + + static CVarList paths(getenv("PATH"), 0, ':', true); + + for (auto& p : paths) { + std::string path = p + std::string{"/"} + exe; + std::error_code ec; + if (!std::filesystem::exists(path, ec) || ec) + continue; + + if (!std::filesystem::is_regular_file(path, ec) || ec) + continue; + + auto stat = std::filesystem::status(path, ec); + if (ec) + continue; + + auto perms = stat.permissions(); + + return std::filesystem::perms::none != (perms & std::filesystem::perms::others_exec); + } + + return false; +} diff --git a/src/helpers/fs/FsUtils.hpp b/src/helpers/fs/FsUtils.hpp new file mode 100644 index 00000000..bc3b3bf1 --- /dev/null +++ b/src/helpers/fs/FsUtils.hpp @@ -0,0 +1,15 @@ +#pragma once +#include +#include + +namespace NFsUtils { + // Returns the path to the hyprland directory in data home. + std::optional getDataHome(); + + std::optional readFileAsString(const std::string& path); + + // overwrites the file if exists + bool writeToFile(const std::string& path, const std::string& content); + + bool executableExistsInPath(const std::string& exe); +}; diff --git a/src/managers/DonationNagManager.cpp b/src/managers/DonationNagManager.cpp new file mode 100644 index 00000000..d7eab9ae --- /dev/null +++ b/src/managers/DonationNagManager.cpp @@ -0,0 +1,114 @@ +#include "DonationNagManager.hpp" +#include "../debug/Log.hpp" +#include "VersionKeeperManager.hpp" +#include "eventLoop/EventLoopManager.hpp" +#include "../config/ConfigValue.hpp" + +#include +#include + +#include "../helpers/fs/FsUtils.hpp" + +#include +using namespace Hyprutils::OS; + +constexpr const char* LAST_NAG_FILE_NAME = "lastNag"; +constexpr uint64_t DAY_IN_SECONDS = 3600ULL * 24; +constexpr uint64_t MONTH_IN_SECONDS = DAY_IN_SECONDS * 30; + +struct SNagDatePoint { + // Counted from 1, as in Jan 1st is 1, 1 + // No month-boundaries because I am lazy + uint8_t month = 0, dayStart = 0, dayEnd = 0; +}; + +// clang-format off +const std::vector NAG_DATE_POINTS = { + SNagDatePoint { + 7, 20, 31, + }, + SNagDatePoint { + 12, 1, 28 + }, +}; +// clang-format on + +CDonationNagManager::CDonationNagManager() { + static auto PNONAG = CConfigValue("ecosystem:no_donation_nag"); + + if (g_pVersionKeeperMgr->fired() || *PNONAG) + return; + + const auto DATAROOT = NFsUtils::getDataHome(); + + if (!DATAROOT) + return; + + const auto EPOCH = std::chrono::duration_cast(std::chrono::system_clock::now().time_since_epoch()).count(); + + const auto LASTNAGSTR = NFsUtils::readFileAsString(*DATAROOT + "/" + LAST_NAG_FILE_NAME); + + if (!LASTNAGSTR) { + const auto EPOCHSTR = std::format("{}", EPOCH); + NFsUtils::writeToFile(*DATAROOT + "/" + LAST_NAG_FILE_NAME, EPOCHSTR); + return; + } + + uint64_t LAST_EPOCH = 0; + + try { + LAST_EPOCH = std::stoull(*LASTNAGSTR); + } catch (std::exception& e) { + Debug::log(ERR, "DonationNag: Last epoch invalid? Failed to parse \"{}\". Setting to today.", *LASTNAGSTR); + const auto EPOCHSTR = std::format("{}", EPOCH); + NFsUtils::writeToFile(*DATAROOT + "/" + LAST_NAG_FILE_NAME, EPOCHSTR); + return; + } + + // don't nag if the last nag was less than a month ago. This is + // mostly for first-time nags, as other nags happen in specific time frames shorter than a month + if (EPOCH - LAST_EPOCH < MONTH_IN_SECONDS) { + Debug::log(LOG, "DonationNag: last nag was {} days ago, too early for a nag.", (int)std::round((EPOCH - LAST_EPOCH) / (double)MONTH_IN_SECONDS)); + return; + } + + if (!NFsUtils::executableExistsInPath("hyprland-donate-screen")) { + Debug::log(ERR, "DonationNag: executable doesn't exist, skipping."); + return; + } + + auto tt = std::chrono::system_clock::to_time_t(std::chrono::system_clock::now()); + auto local = *localtime(&tt); + + const auto MONTH = local.tm_mon + 1; + const auto DAY = local.tm_mday; + + for (const auto& nagPoint : NAG_DATE_POINTS) { + if (MONTH != nagPoint.month) + continue; + + if (DAY < nagPoint.dayStart || DAY > nagPoint.dayEnd) + continue; + + Debug::log(LOG, "DonationNag: hit nag month {} days {}-{}, it's {} today, nagging", MONTH, nagPoint.dayStart, nagPoint.dayEnd, DAY); + + m_bFired = true; + + const auto EPOCHSTR = std::format("{}", EPOCH); + NFsUtils::writeToFile(*DATAROOT + "/" + LAST_NAG_FILE_NAME, EPOCHSTR); + + g_pEventLoopManager->doLater([] { + CProcess proc("hyprland-donate-screen", {}); + proc.runAsync(); + }); + + break; + } + + if (!m_bFired) + Debug::log(LOG, "DonationNag: didn't hit any nagging periods"); +} + +bool CDonationNagManager::fired() { + return m_bFired; +} \ No newline at end of file diff --git a/src/managers/DonationNagManager.hpp b/src/managers/DonationNagManager.hpp new file mode 100644 index 00000000..e296d815 --- /dev/null +++ b/src/managers/DonationNagManager.hpp @@ -0,0 +1,16 @@ +#pragma once + +#include + +class CDonationNagManager { + public: + CDonationNagManager(); + + // whether the donation nag was shown this boot. + bool fired(); + + private: + bool m_bFired = false; +}; + +inline std::unique_ptr g_pDonationNagManager; \ No newline at end of file diff --git a/src/managers/VersionKeeperManager.cpp b/src/managers/VersionKeeperManager.cpp index 1ef1040e..cc03a7b9 100644 --- a/src/managers/VersionKeeperManager.cpp +++ b/src/managers/VersionKeeperManager.cpp @@ -6,6 +6,7 @@ #include "../helpers/varlist/VarList.hpp" #include "eventLoop/EventLoopManager.hpp" #include "../config/ConfigValue.hpp" +#include "../helpers/fs/FsUtils.hpp" #include #include @@ -20,12 +21,12 @@ constexpr const char* VERSION_FILE_NAME = "lastVersion"; CVersionKeeperManager::CVersionKeeperManager() { static auto PNONOTIFY = CConfigValue("ecosystem:no_update_news"); - const auto DATAROOT = getDataHome(); + const auto DATAROOT = NFsUtils::getDataHome(); if (!DATAROOT) return; - const auto LASTVER = getDataLastVersion(*DATAROOT); + const auto LASTVER = NFsUtils::readFileAsString(*DATAROOT + "/" + VERSION_FILE_NAME); if (!LASTVER) return; @@ -35,101 +36,26 @@ CVersionKeeperManager::CVersionKeeperManager() { return; } - writeVersionToVersionFile(*DATAROOT); + NFsUtils::writeToFile(*DATAROOT + "/" + VERSION_FILE_NAME, HYPRLAND_VERSION); if (*PNONOTIFY) { Debug::log(LOG, "CVersionKeeperManager: updated, but update news is disabled in the config :("); return; } - if (!executableExistsInPath("hyprland-update-screen")) { + if (!NFsUtils::executableExistsInPath("hyprland-update-screen")) { Debug::log(ERR, "CVersionKeeperManager: hyprland-update-screen doesn't seem to exist, skipping notif about update..."); return; } + m_bFired = true; + g_pEventLoopManager->doLater([]() { CProcess proc("hyprland-update-screen", {"--new-version", HYPRLAND_VERSION}); proc.runAsync(); }); } -std::optional CVersionKeeperManager::getDataHome() { - const auto DATA_HOME = getenv("XDG_DATA_HOME"); - - std::string dataRoot; - - if (!DATA_HOME) { - const auto HOME = getenv("HOME"); - - if (!HOME) { - Debug::log(ERR, "CVersionKeeperManager: can't get data home: no $HOME or $XDG_DATA_HOME"); - return std::nullopt; - } - - dataRoot = HOME + std::string{"/.local/share/"}; - } else - dataRoot = DATA_HOME + std::string{"/"}; - - std::error_code ec; - if (!std::filesystem::exists(dataRoot, ec) || ec) { - Debug::log(ERR, "CVersionKeeperManager: can't get data home: inaccessible / missing"); - return std::nullopt; - } - - dataRoot += "hyprland/"; - - if (!std::filesystem::exists(dataRoot, ec) || ec) { - Debug::log(LOG, "CVersionKeeperManager: no hyprland data home, creating."); - std::filesystem::create_directory(dataRoot, ec); - if (ec) { - Debug::log(ERR, "CVersionKeeperManager: can't create new data home for hyprland"); - return std::nullopt; - } - std::filesystem::permissions(dataRoot, std::filesystem::perms::owner_read | std::filesystem::perms::owner_write | std::filesystem::perms::owner_exec, ec); - if (ec) - Debug::log(WARN, "CVersionKeeperManager: couldn't set perms on hyprland data store. Proceeding anyways."); - } - - if (!std::filesystem::exists(dataRoot, ec) || ec) { - Debug::log(ERR, "CVersionKeeperManager: no hyprland data home, failed to create."); - return std::nullopt; - } - - return dataRoot; -} - -std::optional CVersionKeeperManager::getDataLastVersion(const std::string& dataRoot) { - std::error_code ec; - std::string lastVerFile = dataRoot + "/" + VERSION_FILE_NAME; - - if (!std::filesystem::exists(lastVerFile, ec) || ec) { - Debug::log(LOG, "CVersionKeeperManager: no hyprland last version file, creating."); - writeVersionToVersionFile(dataRoot); - - return "0.0.0"; - } - - std::ifstream file(lastVerFile); - if (!file.good()) { - Debug::log(ERR, "CVersionKeeperManager: couldn't open an ifstream for reading the version file."); - return std::nullopt; - } - - return trim(std::string((std::istreambuf_iterator(file)), (std::istreambuf_iterator()))); -} - -void CVersionKeeperManager::writeVersionToVersionFile(const std::string& dataRoot) { - std::string lastVerFile = dataRoot + "/" + VERSION_FILE_NAME; - std::ofstream of(lastVerFile, std::ios::trunc); - if (!of.good()) { - Debug::log(ERR, "CVersionKeeperManager: couldn't open an ofstream for writing the version file."); - return; - } - - of << HYPRLAND_VERSION; - of.close(); -} - bool CVersionKeeperManager::isVersionOlderThanRunning(const std::string& ver) { const CVarList verStrings(ver, 0, '.', true); @@ -151,3 +77,7 @@ bool CVersionKeeperManager::isVersionOlderThanRunning(const std::string& ver) { return true; return false; } + +bool CVersionKeeperManager::fired() { + return m_bFired; +} diff --git a/src/managers/VersionKeeperManager.hpp b/src/managers/VersionKeeperManager.hpp index f0dc05ce..eb404d88 100644 --- a/src/managers/VersionKeeperManager.hpp +++ b/src/managers/VersionKeeperManager.hpp @@ -1,17 +1,18 @@ #pragma once #include -#include class CVersionKeeperManager { public: CVersionKeeperManager(); + // whether the update screen was shown this boot. + bool fired(); + private: - std::optional getDataHome(); - std::optional getDataLastVersion(const std::string& dataRoot); - void writeVersionToVersionFile(const std::string& dataRoot); - bool isVersionOlderThanRunning(const std::string& ver); + bool isVersionOlderThanRunning(const std::string& ver); + + bool m_bFired = false; }; inline std::unique_ptr g_pVersionKeeperMgr; \ No newline at end of file From a8b568c6c451cdce3c8d40ae010247be3f25728b Mon Sep 17 00:00:00 2001 From: UjinT34 <41110182+UjinT34@users.noreply.github.com> Date: Fri, 10 Jan 2025 21:42:26 +0300 Subject: [PATCH 0842/2181] core: Add render:allow_early_buffer_release to make buffer release configurable (#9019) --- src/config/ConfigDescriptions.hpp | 6 ++++++ src/config/ConfigManager.cpp | 1 + src/protocols/core/Compositor.cpp | 15 ++++++++++----- 3 files changed, 17 insertions(+), 5 deletions(-) diff --git a/src/config/ConfigDescriptions.hpp b/src/config/ConfigDescriptions.hpp index 686b996a..483f1f1f 100644 --- a/src/config/ConfigDescriptions.hpp +++ b/src/config/ConfigDescriptions.hpp @@ -1313,6 +1313,12 @@ inline static const std::vector CONFIG_OPTIONS = { .type = CONFIG_OPTION_INT, .data = SConfigOptionDescription::SRangeData{2, 0, 2}, }, + SConfigOptionDescription{ + .value = "render:allow_early_buffer_release", + .description = "Allow early buffer release event. Fixes stuttering and missing frames for some apps. May cause graphical glitches and memory leaks in others", + .type = CONFIG_OPTION_BOOL, + .data = SConfigOptionDescription::SBoolData{true}, + }, /* * cursor: diff --git a/src/config/ConfigManager.cpp b/src/config/ConfigManager.cpp index 3f8862ee..299dfbc3 100644 --- a/src/config/ConfigManager.cpp +++ b/src/config/ConfigManager.cpp @@ -619,6 +619,7 @@ CConfigManager::CConfigManager() { m_pConfig->addConfigValue("render:expand_undersized_textures", Hyprlang::INT{1}); m_pConfig->addConfigValue("render:xp_mode", Hyprlang::INT{0}); m_pConfig->addConfigValue("render:ctm_animation", Hyprlang::INT{2}); + m_pConfig->addConfigValue("render:allow_early_buffer_release", Hyprlang::INT{1}); m_pConfig->addConfigValue("ecosystem:no_update_news", Hyprlang::INT{0}); m_pConfig->addConfigValue("ecosystem:no_donation_nag", Hyprlang::INT{0}); diff --git a/src/protocols/core/Compositor.cpp b/src/protocols/core/Compositor.cpp index 6213f987..e1d6ef7d 100644 --- a/src/protocols/core/Compositor.cpp +++ b/src/protocols/core/Compositor.cpp @@ -11,6 +11,7 @@ #include "../PresentationTime.hpp" #include "../DRMSyncobj.hpp" #include "../../render/Renderer.hpp" +#include "config/ConfigValue.hpp" #include class CDefaultSurfaceRole : public ISurfaceRole { @@ -423,12 +424,14 @@ void CWLSurfaceResource::unlockPendingState() { } void CWLSurfaceResource::commitPendingState() { - auto const previousBuffer = current.buffer; - current = pending; + static auto PDROP = CConfigValue("render:allow_early_buffer_release"); + auto const previousBuffer = current.buffer; + current = pending; pending.damage.clear(); pending.bufferDamage.clear(); pending.newBuffer = false; - dropPendingBuffer(); // at this point current.buffer holds the same SP and we don't use pending anymore + if (!*PDROP) + dropPendingBuffer(); // at this point current.buffer holds the same SP and we don't use pending anymore events.roleCommit.emit(); @@ -450,8 +453,10 @@ void CWLSurfaceResource::commitPendingState() { // release the buffer if it's synchronous as update() has done everything thats needed // so we can let the app know we're done. // Some clients aren't ready to receive a release this early. Should be fine to release it on the next commitPendingState. - // if (current.buffer->buffer->isSynchronous()) - // dropCurrentBuffer(); + if (current.buffer->buffer->isSynchronous() && *PDROP) { + dropCurrentBuffer(); + dropPendingBuffer(); // at this point current.buffer holds the same SP and we don't use pending anymore + } } // TODO: we should _accumulate_ and not replace above if sync From cef09fbfe6624d2133d81be863bd48bcfc5939d3 Mon Sep 17 00:00:00 2001 From: vaxerski Date: Fri, 10 Jan 2025 21:55:19 +0100 Subject: [PATCH 0843/2181] animation: avoid crashes in ::tick() on mutations mutating the active variables is valid during a tick, we can't let it crash --- src/managers/AnimationManager.cpp | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/managers/AnimationManager.cpp b/src/managers/AnimationManager.cpp index f0f6a980..ea74ffd2 100644 --- a/src/managers/AnimationManager.cpp +++ b/src/managers/AnimationManager.cpp @@ -215,7 +215,11 @@ void CHyprAnimationManager::tick() { lastTick = std::chrono::high_resolution_clock::now(); static auto PANIMENABLED = CConfigValue("animations:enabled"); - for (auto const& pav : m_vActiveAnimatedVariables) { + + // We need to do this because it's perfectly valid to add/change a var during this (via callbacks) + // FIXME: instead of doing this, make a fn to defer adding until tick is done and not in progress anymore. + const auto PAVS = m_vActiveAnimatedVariables; + for (auto const& pav : PAVS) { const auto PAV = pav.lock(); if (!PAV) continue; From 3b85690aa6d9c14bb926692e25cc4480b85200ab Mon Sep 17 00:00:00 2001 From: littleblack111 Date: Sat, 11 Jan 2025 23:58:05 +0800 Subject: [PATCH 0844/2181] config: add exec(-onec) with rules and execr(-once) (#8953) --- src/config/ConfigManager.cpp | 51 +++++++++++++++++++++++++++++++++--- src/config/ConfigManager.hpp | 10 ++++++- 2 files changed, 56 insertions(+), 5 deletions(-) diff --git a/src/config/ConfigManager.cpp b/src/config/ConfigManager.cpp index 299dfbc3..60723220 100644 --- a/src/config/ConfigManager.cpp +++ b/src/config/ConfigManager.cpp @@ -130,6 +130,18 @@ static void configHandleGapDestroy(void** data) { delete reinterpret_cast(*data); } +static Hyprlang::CParseResult handleExec(const char* c, const char* v) { + const std::string VALUE = v; + const std::string COMMAND = c; + + const auto RESULT = g_pConfigManager->handleExec(COMMAND, VALUE); + + Hyprlang::CParseResult result; + if (RESULT.has_value()) + result.setError(RESULT.value().c_str()); + return result; +} + static Hyprlang::CParseResult handleRawExec(const char* c, const char* v) { const std::string VALUE = v; const std::string COMMAND = c; @@ -154,6 +166,18 @@ static Hyprlang::CParseResult handleExecOnce(const char* c, const char* v) { return result; } +static Hyprlang::CParseResult handleExecRawOnce(const char* c, const char* v) { + const std::string VALUE = v; + const std::string COMMAND = c; + + const auto RESULT = g_pConfigManager->handleExecRawOnce(COMMAND, VALUE); + + Hyprlang::CParseResult result; + if (RESULT.has_value()) + result.setError(RESULT.value().c_str()); + return result; +} + static Hyprlang::CParseResult handleExecShutdown(const char* c, const char* v) { const std::string VALUE = v; const std::string COMMAND = c; @@ -666,8 +690,10 @@ CConfigManager::CConfigManager() { m_pConfig->addSpecialConfigValue("device", "active_area_size", Hyprlang::VEC2{0, 0}); // only for tablets // keywords - m_pConfig->registerHandler(&::handleRawExec, "exec", {false}); + m_pConfig->registerHandler(&::handleExec, "exec", {false}); + m_pConfig->registerHandler(&::handleRawExec, "execr", {false}); m_pConfig->registerHandler(&::handleExecOnce, "exec-once", {false}); + m_pConfig->registerHandler(&::handleExecRawOnce, "execr-once", {false}); m_pConfig->registerHandler(&::handleExecShutdown, "exec-shutdown", {false}); m_pConfig->registerHandler(&::handleMonitor, "monitor", {false}); m_pConfig->registerHandler(&::handleBind, "bind", {true}); @@ -1441,7 +1467,7 @@ void CConfigManager::dispatchExecOnce() { isLaunchingExecOnce = true; for (auto const& c : firstExecRequests) { - handleRawExec("", c); + c.withRules ? handleExec("", c.exec) : handleRawExec("", c.exec); } firstExecRequests.clear(); // free some kb of memory :P @@ -1744,7 +1770,17 @@ std::string CConfigManager::getDefaultWorkspaceFor(const std::string& name) { std::optional CConfigManager::handleRawExec(const std::string& command, const std::string& args) { if (isFirstLaunch) { - firstExecRequests.push_back(args); + firstExecRequests.push_back({args, false}); + return {}; + } + + g_pKeybindManager->spawnRaw(args); + return {}; +} + +std::optional CConfigManager::handleExec(const std::string& command, const std::string& args) { + if (isFirstLaunch) { + firstExecRequests.push_back({args, true}); return {}; } @@ -1754,7 +1790,14 @@ std::optional CConfigManager::handleRawExec(const std::string& comm std::optional CConfigManager::handleExecOnce(const std::string& command, const std::string& args) { if (isFirstLaunch) - firstExecRequests.push_back(args); + firstExecRequests.push_back({args, true}); + + return {}; +} + +std::optional CConfigManager::handleExecRawOnce(const std::string& command, const std::string& args) { + if (isFirstLaunch) + firstExecRequests.push_back({args, false}); return {}; } diff --git a/src/config/ConfigManager.hpp b/src/config/ConfigManager.hpp index 53772401..a27ee7ab 100644 --- a/src/config/ConfigManager.hpp +++ b/src/config/ConfigManager.hpp @@ -132,6 +132,11 @@ struct SConfigOptionDescription { std::variant data; }; +struct SFirstExecRequest { + std::string exec = ""; + bool withRules = false; +}; + class CConfigManager { public: CConfigManager(); @@ -196,7 +201,9 @@ class CConfigManager { // keywords std::optional handleRawExec(const std::string&, const std::string&); + std::optional handleExec(const std::string&, const std::string&); std::optional handleExecOnce(const std::string&, const std::string&); + std::optional handleExecRawOnce(const std::string&, const std::string&); std::optional handleExecShutdown(const std::string&, const std::string&); std::optional handleMonitor(const std::string&, const std::string&); std::optional handleBind(const std::string&, const std::string&); @@ -280,7 +287,8 @@ class CConfigManager { bool firstExecDispatched = false; bool m_bManualCrashInitiated = false; - std::vector firstExecRequests; + + std::vector firstExecRequests; // bool is for if with rules std::vector finalExecRequests; std::vector> m_vFailedPluginConfigValues; // for plugin values of unloaded plugins From 15dc024a398d35957ccfb50ddade5f456a1646b5 Mon Sep 17 00:00:00 2001 From: Alexander <51529891+Truenya@users.noreply.github.com> Date: Sat, 11 Jan 2025 19:05:53 +0300 Subject: [PATCH 0845/2181] keybinds: fix previous_per_monitor logic (#9010) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Крылов Александр --- src/desktop/Workspace.cpp | 10 ++-------- src/desktop/Workspace.hpp | 22 +++++++++++----------- src/helpers/MiscFunctions.cpp | 2 +- src/helpers/Monitor.cpp | 24 ++++++++++++++++++++++++ src/helpers/Monitor.hpp | 15 +++++++++++---- src/managers/KeybindManager.cpp | 33 ++++++++++++++------------------- 6 files changed, 63 insertions(+), 43 deletions(-) diff --git a/src/desktop/Workspace.cpp b/src/desktop/Workspace.cpp index 376288ed..07c1a435 100644 --- a/src/desktop/Workspace.cpp +++ b/src/desktop/Workspace.cpp @@ -52,10 +52,7 @@ void CWorkspace::init(PHLWORKSPACE self) { EMIT_HOOK_EVENT("createWorkspace", this); } -SWorkspaceIDName CWorkspace::getPrevWorkspaceIDName(bool perMonitor) const { - if (perMonitor) - return m_sPrevWorkspacePerMonitor; - +SWorkspaceIDName CWorkspace::getPrevWorkspaceIDName() const { return m_sPrevWorkspace; } @@ -216,10 +213,7 @@ void CWorkspace::rememberPrevWorkspace(const PHLWORKSPACE& prev) { m_sPrevWorkspace.id = prev->m_iID; m_sPrevWorkspace.name = prev->m_szName; - if (prev->m_pMonitor == m_pMonitor) { - m_sPrevWorkspacePerMonitor.id = prev->m_iID; - m_sPrevWorkspacePerMonitor.name = prev->m_szName; - } + prev->m_pMonitor->addPrevWorkspaceID(prev->m_iID); } std::string CWorkspace::getConfigName() { diff --git a/src/desktop/Workspace.hpp b/src/desktop/Workspace.hpp index f86dd656..e9859d4f 100644 --- a/src/desktop/Workspace.hpp +++ b/src/desktop/Workspace.hpp @@ -24,17 +24,14 @@ class CWorkspace { // Workspaces ID-based have IDs > 0 // and workspaces name-based have IDs starting with -1337 - WORKSPACEID m_iID = WORKSPACE_INVALID; - std::string m_szName = ""; - PHLMONITORREF m_pMonitor; - // Previous workspace ID and name is stored during a workspace change, allowing travel - // to the previous workspace. - SWorkspaceIDName m_sPrevWorkspace, m_sPrevWorkspacePerMonitor; + WORKSPACEID m_iID = WORKSPACE_INVALID; + std::string m_szName = ""; + PHLMONITORREF m_pMonitor; - bool m_bHasFullscreenWindow = false; - eFullscreenMode m_efFullscreenMode = FSMODE_NONE; + bool m_bHasFullscreenWindow = false; + eFullscreenMode m_efFullscreenMode = FSMODE_NONE; - wl_array m_wlrCoordinateArr; + wl_array m_wlrCoordinateArr; // for animations PHLANIMVAR m_vRenderOffset; @@ -72,7 +69,7 @@ class CWorkspace { std::string getConfigName(); bool matchesStaticSelector(const std::string& selector); void markInert(); - SWorkspaceIDName getPrevWorkspaceIDName(bool perMonitor) const; + SWorkspaceIDName getPrevWorkspaceIDName() const; void updateWindowDecos(); void updateWindowData(); int getWindows(std::optional onlyTiled = {}, std::optional onlyVisible = {}); @@ -88,7 +85,10 @@ class CWorkspace { void updateWindows(); private: - void init(PHLWORKSPACE self); + void init(PHLWORKSPACE self); + // Previous workspace ID and name is stored during a workspace change, allowing travel + // to the previous workspace. + SWorkspaceIDName m_sPrevWorkspace; SP m_pFocusedWindowHook; bool m_bInert = true; diff --git a/src/helpers/MiscFunctions.cpp b/src/helpers/MiscFunctions.cpp index 08a1106a..0fa73e45 100644 --- a/src/helpers/MiscFunctions.cpp +++ b/src/helpers/MiscFunctions.cpp @@ -258,7 +258,7 @@ SWorkspaceIDName getWorkspaceIDNameFromString(const std::string& in) { if (!valid(PWORKSPACE)) return {WORKSPACE_INVALID}; - const auto PLASTWORKSPACE = g_pCompositor->getWorkspaceByID(PWORKSPACE->m_sPrevWorkspace.id); + const auto PLASTWORKSPACE = g_pCompositor->getWorkspaceByID(PWORKSPACE->getPrevWorkspaceIDName().id); if (!PLASTWORKSPACE) return {WORKSPACE_INVALID}; diff --git a/src/helpers/Monitor.cpp b/src/helpers/Monitor.cpp index e833e661..cf62bc54 100644 --- a/src/helpers/Monitor.cpp +++ b/src/helpers/Monitor.cpp @@ -1,5 +1,6 @@ #include "Monitor.hpp" #include "MiscFunctions.hpp" +#include "macros.hpp" #include "math/Math.hpp" #include "sync/SyncReleaser.hpp" #include "../Compositor.hpp" @@ -1169,6 +1170,29 @@ void CMonitor::moveTo(const Vector2D& pos) { vecPosition = pos; } +SWorkspaceIDName CMonitor::getPrevWorkspaceIDName(const WORKSPACEID id) { + while (!prevWorkSpaces.empty()) { + const int PREVID = prevWorkSpaces.top(); + prevWorkSpaces.pop(); + if (PREVID == id) // skip same workspace + continue; + + // recheck if previous workspace's was moved to another monitor + const auto ws = g_pCompositor->getWorkspaceByID(PREVID); + if (ws && ws->monitorID() == ID) + return {.id = PREVID, .name = ws->m_szName}; + } + + return {.id = WORKSPACE_INVALID}; +} + +void CMonitor::addPrevWorkspaceID(const WORKSPACEID id) { + if (!prevWorkSpaces.empty() && prevWorkSpaces.top() == id) + return; + + prevWorkSpaces.emplace(id); +} + Vector2D CMonitor::middle() { return vecPosition + vecSize / 2.f; } diff --git a/src/helpers/Monitor.hpp b/src/helpers/Monitor.hpp index b075df81..8085c460 100644 --- a/src/helpers/Monitor.hpp +++ b/src/helpers/Monitor.hpp @@ -1,7 +1,9 @@ #pragma once #include "../defines.hpp" +#include #include +#include "SharedDefs.hpp" #include "WLClasses.hpp" #include #include @@ -196,11 +198,16 @@ class CMonitor { return vecPosition == rhs.vecPosition && vecSize == rhs.vecSize && szName == rhs.szName; } - private: - void setupDefaultWS(const SMonitorRule&); - WORKSPACEID findAvailableDefaultWS(); + // workspace previous per monitor functionality + SWorkspaceIDName getPrevWorkspaceIDName(const WORKSPACEID id); + void addPrevWorkspaceID(const WORKSPACEID id); - bool doneScheduled = false; + private: + void setupDefaultWS(const SMonitorRule&); + WORKSPACEID findAvailableDefaultWS(); + + bool doneScheduled = false; + std::stack prevWorkSpaces; struct { CHyprSignalListener frame; diff --git a/src/managers/KeybindManager.cpp b/src/managers/KeybindManager.cpp index 4cd97913..720d27f6 100644 --- a/src/managers/KeybindManager.cpp +++ b/src/managers/KeybindManager.cpp @@ -1176,27 +1176,24 @@ SDispatchResult CKeybindManager::toggleActivePseudo(std::string args) { return {}; } -static SWorkspaceIDName getWorkspaceToChangeFromArgs(std::string args, PHLWORKSPACE PCURRENTWORKSPACE) { +static SWorkspaceIDName getWorkspaceToChangeFromArgs(std::string args, PHLWORKSPACE PCURRENTWORKSPACE, PHLMONITORREF PMONITOR) { if (!args.starts_with("previous")) { return getWorkspaceIDNameFromString(args); } const bool PER_MON = args.contains("_per_monitor"); - const SWorkspaceIDName PPREVWS = PCURRENTWORKSPACE->getPrevWorkspaceIDName(PER_MON); + const SWorkspaceIDName PPREVWS = PER_MON ? PMONITOR->getPrevWorkspaceIDName(PCURRENTWORKSPACE->m_iID) : PCURRENTWORKSPACE->getPrevWorkspaceIDName(); // Do nothing if there's no previous workspace, otherwise switch to it. - if (PPREVWS.id == -1) { + if (PPREVWS.id == -1 || PPREVWS.id == PCURRENTWORKSPACE->m_iID) { Debug::log(LOG, "No previous workspace to change to"); - return {WORKSPACE_NOT_CHANGED, ""}; + return {.id = WORKSPACE_NOT_CHANGED}; } - const auto ID = PCURRENTWORKSPACE->m_iID; if (const auto PWORKSPACETOCHANGETO = g_pCompositor->getWorkspaceByID(PPREVWS.id); PWORKSPACETOCHANGETO) { - if (PER_MON && PCURRENTWORKSPACE->m_pMonitor != PWORKSPACETOCHANGETO->m_pMonitor) - return {WORKSPACE_NOT_CHANGED, ""}; - return {ID, PWORKSPACETOCHANGETO->m_szName}; + return {.id = PWORKSPACETOCHANGETO->m_iID, .name = PWORKSPACETOCHANGETO->m_szName}; } - return {ID, PPREVWS.name.empty() ? std::to_string(PPREVWS.id) : PPREVWS.name}; + return {.id = PPREVWS.id, .name = PPREVWS.name.empty() ? std::to_string(PPREVWS.id) : PPREVWS.name}; } SDispatchResult CKeybindManager::changeworkspace(std::string args) { @@ -1214,7 +1211,7 @@ SDispatchResult CKeybindManager::changeworkspace(std::string args) { const auto PCURRENTWORKSPACE = PMONITOR->activeWorkspace; const bool EXPLICITPREVIOUS = args.contains("previous"); - const auto& [workspaceToChangeTo, workspaceName] = getWorkspaceToChangeFromArgs(args, PCURRENTWORKSPACE); + const auto& [workspaceToChangeTo, workspaceName] = getWorkspaceToChangeFromArgs(args, PCURRENTWORKSPACE, PMONITOR); if (workspaceToChangeTo == WORKSPACE_INVALID) { Debug::log(ERR, "Error in changeworkspace, invalid value"); return {.success = false, .error = "Error in changeworkspace, invalid value"}; @@ -1223,19 +1220,19 @@ SDispatchResult CKeybindManager::changeworkspace(std::string args) { if (workspaceToChangeTo == WORKSPACE_NOT_CHANGED) return {}; - const auto PREVWS = PCURRENTWORKSPACE->getPrevWorkspaceIDName(args.contains("_per_monitor")); + const SWorkspaceIDName PPREVWS = args.contains("_per_monitor") ? PMONITOR->getPrevWorkspaceIDName(PCURRENTWORKSPACE->m_iID) : PCURRENTWORKSPACE->getPrevWorkspaceIDName(); - const bool BISWORKSPACECURRENT = workspaceToChangeTo == PCURRENTWORKSPACE->m_iID; - if (BISWORKSPACECURRENT && (!(*PBACKANDFORTH || EXPLICITPREVIOUS) || PREVWS.id == -1)) + const bool BISWORKSPACECURRENT = workspaceToChangeTo == PCURRENTWORKSPACE->m_iID; + if (BISWORKSPACECURRENT && (!(*PBACKANDFORTH || EXPLICITPREVIOUS) || PPREVWS.id == -1)) return {.success = false, .error = "Previous workspace doesn't exist"}; g_pInputManager->unconstrainMouse(); g_pInputManager->m_bEmptyFocusCursorSet = false; - auto pWorkspaceToChangeTo = g_pCompositor->getWorkspaceByID(BISWORKSPACECURRENT ? PREVWS.id : workspaceToChangeTo); + auto pWorkspaceToChangeTo = g_pCompositor->getWorkspaceByID(BISWORKSPACECURRENT ? PPREVWS.id : workspaceToChangeTo); if (!pWorkspaceToChangeTo) pWorkspaceToChangeTo = - g_pCompositor->createNewWorkspace(BISWORKSPACECURRENT ? PREVWS.id : workspaceToChangeTo, PMONITOR->ID, BISWORKSPACECURRENT ? PREVWS.name : workspaceName); + g_pCompositor->createNewWorkspace(BISWORKSPACECURRENT ? PPREVWS.id : workspaceToChangeTo, PMONITOR->ID, BISWORKSPACECURRENT ? PPREVWS.name : workspaceName); if (!BISWORKSPACECURRENT && pWorkspaceToChangeTo->m_bIsSpecialWorkspace) { PMONITOR->setSpecialWorkspace(pWorkspaceToChangeTo); @@ -1407,9 +1404,7 @@ SDispatchResult CKeybindManager::moveActiveToWorkspace(std::string args) { } SDispatchResult CKeybindManager::moveActiveToWorkspaceSilent(std::string args) { - PHLWINDOW PWINDOW = nullptr; - - const auto ORIGINALARGS = args; + PHLWINDOW PWINDOW = nullptr; if (args.contains(',')) { PWINDOW = g_pCompositor->getWindowByRegex(args.substr(args.find_last_of(',') + 1)); @@ -2033,7 +2028,7 @@ SDispatchResult CKeybindManager::focusWorkspaceOnCurrentMonitor(std::string args } static auto PBACKANDFORTH = CConfigValue("binds:workspace_back_and_forth"); - const auto PREVWS = pWorkspace->getPrevWorkspaceIDName(false); + const auto PREVWS = pWorkspace->getPrevWorkspaceIDName(); if (*PBACKANDFORTH && PCURRMONITOR->activeWorkspaceID() == workspaceID && PREVWS.id != -1) { // Workspace to focus is previous workspace From 9e4f90aedf2f51d3e7f3dbe5391cb193aa0bddf5 Mon Sep 17 00:00:00 2001 From: Maximilian Seidler <78690852+PaideiaDilemma@users.noreply.github.com> Date: Sat, 11 Jan 2025 16:35:57 +0000 Subject: [PATCH 0846/2181] animation: fixup adding animvars during ::tick (#9030) --- src/managers/AnimationManager.cpp | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/src/managers/AnimationManager.cpp b/src/managers/AnimationManager.cpp index ea74ffd2..28adc330 100644 --- a/src/managers/AnimationManager.cpp +++ b/src/managers/AnimationManager.cpp @@ -216,11 +216,8 @@ void CHyprAnimationManager::tick() { static auto PANIMENABLED = CConfigValue("animations:enabled"); - // We need to do this because it's perfectly valid to add/change a var during this (via callbacks) - // FIXME: instead of doing this, make a fn to defer adding until tick is done and not in progress anymore. - const auto PAVS = m_vActiveAnimatedVariables; - for (auto const& pav : PAVS) { - const auto PAV = pav.lock(); + for (size_t i = 0; i < m_vActiveAnimatedVariables.size(); i++) { + const auto PAV = m_vActiveAnimatedVariables[i].lock(); if (!PAV) continue; From 2778aff08fba59a34b404751039d7acb6bfb3bdf Mon Sep 17 00:00:00 2001 From: Maximilian Seidler <78690852+PaideiaDilemma@users.noreply.github.com> Date: Sat, 11 Jan 2025 16:38:04 +0000 Subject: [PATCH 0847/2181] animations: fix XWayland cursor glitch and refactor skill issues (#9033) --- src/events/Windows.cpp | 2 +- src/managers/XWaylandManager.cpp | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/events/Windows.cpp b/src/events/Windows.cpp index ff69e83f..14e89b4b 100644 --- a/src/events/Windows.cpp +++ b/src/events/Windows.cpp @@ -38,7 +38,7 @@ static void setVector2DAnimToMove(WP pav) { animvar->setConfig(g_pConfigManager->getAnimationPropertyConfig("windowsMove")); const auto PHLWINDOW = animvar->m_Context.pWindow.lock(); - if (PHLWINDOW && PHLWINDOW->m_vRealPosition->isBeingAnimated() && PHLWINDOW->m_vRealSize->isBeingAnimated()) + if (PHLWINDOW && !PHLWINDOW->m_vRealPosition->isBeingAnimated() && !PHLWINDOW->m_vRealSize->isBeingAnimated()) PHLWINDOW->m_bAnimatingIn = false; } diff --git a/src/managers/XWaylandManager.cpp b/src/managers/XWaylandManager.cpp index bc988f39..ab0bfb88 100644 --- a/src/managers/XWaylandManager.cpp +++ b/src/managers/XWaylandManager.cpp @@ -123,7 +123,7 @@ void CHyprXWaylandManager::setWindowSize(PHLWINDOW pWindow, Vector2D size, bool // calculate pos // TODO: this should be decoupled from setWindowSize IMO - Vector2D windowPos = pWindow->m_vRealPosition->value(); + Vector2D windowPos = pWindow->m_vRealPosition->goal(); if (pWindow->m_bIsX11 && PMONITOR) { windowPos -= PMONITOR->vecPosition; // normalize to monitor From 2671656a75708452e9408a111e69e4436b6ad301 Mon Sep 17 00:00:00 2001 From: Toria Date: Sun, 12 Jan 2025 16:35:10 +0000 Subject: [PATCH 0848/2181] helpers/Monitor.cpp: fix include path (#9039) --- src/helpers/Monitor.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/helpers/Monitor.hpp b/src/helpers/Monitor.hpp index 8085c460..8c7566e2 100644 --- a/src/helpers/Monitor.hpp +++ b/src/helpers/Monitor.hpp @@ -3,7 +3,7 @@ #include "../defines.hpp" #include #include -#include "SharedDefs.hpp" +#include "../SharedDefs.hpp" #include "WLClasses.hpp" #include #include From b117fae3b493b9d5ac7ada3140cac555c3979dfd Mon Sep 17 00:00:00 2001 From: staz Date: Sun, 12 Jan 2025 22:00:56 +0500 Subject: [PATCH 0849/2181] keybinds: fix movefocus fallback for special workspaces (#9040) --- src/managers/KeybindManager.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/managers/KeybindManager.cpp b/src/managers/KeybindManager.cpp index 720d27f6..9a719130 100644 --- a/src/managers/KeybindManager.cpp +++ b/src/managers/KeybindManager.cpp @@ -1534,7 +1534,8 @@ SDispatchResult CKeybindManager::moveFocusTo(std::string args) { break; } - const auto PWINDOWCANDIDATE = g_pCompositor->getWindowInDirection(box, PMONITOR->activeWorkspace, arg, PLASTWINDOW, PLASTWINDOW->m_bIsFloating); + const auto PWINDOWCANDIDATE = g_pCompositor->getWindowInDirection(box, PMONITOR->activeSpecialWorkspace ? PMONITOR->activeSpecialWorkspace : PMONITOR->activeWorkspace, arg, + PLASTWINDOW, PLASTWINDOW->m_bIsFloating); if (PWINDOWCANDIDATE) switchToWindow(PWINDOWCANDIDATE); From a3a74993173662c06025ca633faa68b5590e2c5b Mon Sep 17 00:00:00 2001 From: UjinT34 <41110182+UjinT34@users.noreply.github.com> Date: Sun, 12 Jan 2025 20:02:41 +0300 Subject: [PATCH 0850/2181] renderer: Do not set hdr metadata unless needed (#9014) --- src/protocols/ColorManagement.cpp | 26 ++++++++++++++++++++++---- src/protocols/ColorManagement.hpp | 7 +++++++ src/protocols/FrogColorManagement.cpp | 10 +++++----- src/render/Renderer.cpp | 23 ++++++++++++++++------- src/render/Renderer.hpp | 1 + 5 files changed, 51 insertions(+), 16 deletions(-) diff --git a/src/protocols/ColorManagement.cpp b/src/protocols/ColorManagement.cpp index 7ff4db4f..a76e13c0 100644 --- a/src/protocols/ColorManagement.cpp +++ b/src/protocols/ColorManagement.cpp @@ -194,13 +194,13 @@ CColorManagementSurface::CColorManagementSurface(SP return; } - m_hasImageDescription = true; - m_imageDescription = imageDescription->get()->settings; + setHasImageDescription(true); + m_imageDescription = imageDescription->get()->settings; }); resource->setUnsetImageDescription([this](CXxColorManagementSurfaceV4* r) { LOGM(TRACE, "Unset image description for surface={}", (uintptr_t)r); - m_imageDescription = SImageDescription{}; - m_hasImageDescription = false; + m_imageDescription = SImageDescription{}; + setHasImageDescription(false); }); } @@ -222,6 +222,24 @@ bool CColorManagementSurface::hasImageDescription() { return m_hasImageDescription; } +void CColorManagementSurface::setHasImageDescription(bool has) { + m_hasImageDescription = has; + m_needsNewMetadata = true; +} + +const hdr_output_metadata& CColorManagementSurface::hdrMetadata() { + return m_hdrMetadata; +} + +void CColorManagementSurface::setHDRMetadata(const hdr_output_metadata& metadata) { + m_hdrMetadata = metadata; + m_needsNewMetadata = false; +} + +bool CColorManagementSurface::needsHdrMetadataUpdate() { + return m_needsNewMetadata; +} + CColorManagementFeedbackSurface::CColorManagementFeedbackSurface(SP resource_, SP surface_) : surface(surface_), resource(resource_) { if (!good()) diff --git a/src/protocols/ColorManagement.hpp b/src/protocols/ColorManagement.hpp index 573abf69..e387b3b7 100644 --- a/src/protocols/ColorManagement.hpp +++ b/src/protocols/ColorManagement.hpp @@ -1,5 +1,6 @@ #pragma once +#include #include #include #include @@ -54,12 +55,18 @@ class CColorManagementSurface { const SImageDescription& imageDescription(); bool hasImageDescription(); + void setHasImageDescription(bool has); + const hdr_output_metadata& hdrMetadata(); + void setHDRMetadata(const hdr_output_metadata& metadata); + bool needsHdrMetadataUpdate(); private: SP resource; wl_client* pClient = nullptr; SImageDescription m_imageDescription; bool m_hasImageDescription = false; + bool m_needsNewMetadata = false; + hdr_output_metadata m_hdrMetadata; friend class CFrogColorManagementSurface; }; diff --git a/src/protocols/FrogColorManagement.cpp b/src/protocols/FrogColorManagement.cpp index 6a921981..f27af5c8 100644 --- a/src/protocols/FrogColorManagement.cpp +++ b/src/protocols/FrogColorManagement.cpp @@ -92,7 +92,7 @@ CFrogColorManagementSurface::CFrogColorManagementSurface(SPcolorManagement->m_imageDescription.transferFunction = XX_COLOR_MANAGER_V4_TRANSFER_FUNCTION_SRGB; - surface->colorManagement->m_hasImageDescription = true; + surface->colorManagement->setHasImageDescription(true); } }); resource->setSetKnownContainerColorVolume([this](CFrogColorManagedSurface* r, frogColorManagedSurfacePrimaries primariesName) { @@ -103,12 +103,12 @@ CFrogColorManagementSurface::CFrogColorManagementSurface(SPcolorManagement->m_imageDescription.primaries = NColorPrimaries::BT2020; break; } - surface->colorManagement->m_hasImageDescription = true; + surface->colorManagement->setHasImageDescription(true); }); resource->setSetRenderIntent([this](CFrogColorManagedSurface* r, frogColorManagedSurfaceRenderIntent intent) { LOGM(TRACE, "Set frog cm intent {}", (uint32_t)intent); - pqIntentSent = intent == FROG_COLOR_MANAGED_SURFACE_RENDER_INTENT_PERCEPTUAL; - surface->colorManagement->m_hasImageDescription = true; + pqIntentSent = intent == FROG_COLOR_MANAGED_SURFACE_RENDER_INTENT_PERCEPTUAL; + surface->colorManagement->setHasImageDescription(true); }); resource->setSetHdrMetadata([this](CFrogColorManagedSurface* r, uint32_t r_x, uint32_t r_y, uint32_t g_x, uint32_t g_y, uint32_t b_x, uint32_t b_y, uint32_t w_x, uint32_t w_y, uint32_t max_lum, uint32_t min_lum, uint32_t cll, uint32_t fall) { @@ -122,7 +122,7 @@ CFrogColorManagementSurface::CFrogColorManagementSurface(SPcolorManagement->m_imageDescription.maxCLL = cll; surface->colorManagement->m_imageDescription.maxFALL = fall; - surface->colorManagement->m_hasImageDescription = true; + surface->colorManagement->setHasImageDescription(true); }); } diff --git a/src/render/Renderer.cpp b/src/render/Renderer.cpp index cf25d477..b9c8dd98 100644 --- a/src/render/Renderer.cpp +++ b/src/render/Renderer.cpp @@ -1460,9 +1460,10 @@ bool CHyprRenderer::commitPendingAndDoExplicitSync(PHLMONITOR pMonitor) { pMonitor->output->state->setExplicitInFence(inFD); static auto PWIDE = CConfigValue("experimental:wide_color_gamut"); - if (pMonitor->output->state->state().wideColorGamut != *PWIDE) + if (pMonitor->output->state->state().wideColorGamut != *PWIDE) { Debug::log(TRACE, "Setting wide color gamut {}", *PWIDE ? "on" : "off"); - pMonitor->output->state->setWideColorGamut(*PWIDE); + pMonitor->output->state->setWideColorGamut(*PWIDE); + } static auto PHDR = CConfigValue("experimental:hdr"); @@ -1472,12 +1473,20 @@ bool CHyprRenderer::commitPendingAndDoExplicitSync(PHLMONITOR pMonitor) { if (pMonitor->activeWorkspace && pMonitor->activeWorkspace->m_bHasFullscreenWindow && pMonitor->activeWorkspace->m_efFullscreenMode == FSMODE_FULLSCREEN) { const auto WINDOW = pMonitor->activeWorkspace->getFullscreenWindow(); const auto SURF = WINDOW->m_pWLSurface->resource(); - if (SURF->colorManagement.valid() && SURF->colorManagement->hasImageDescription()) - pMonitor->output->state->setHDRMetadata(createHDRMetadata(SURF->colorManagement.get()->imageDescription(), pMonitor->output->parsedEDID)); - else + if (SURF->colorManagement.valid() && SURF->colorManagement->hasImageDescription()) { + bool needsHdrMetadataUpdate = SURF->colorManagement->needsHdrMetadataUpdate() || m_previousFSWindow != WINDOW; + if (SURF->colorManagement->needsHdrMetadataUpdate()) + SURF->colorManagement->setHDRMetadata(createHDRMetadata(SURF->colorManagement.get()->imageDescription(), pMonitor->output->parsedEDID)); + if (needsHdrMetadataUpdate) + pMonitor->output->state->setHDRMetadata(SURF->colorManagement->hdrMetadata()); + } else pMonitor->output->state->setHDRMetadata(*PHDR ? createHDRMetadata(2, pMonitor->output->parsedEDID) : createHDRMetadata(0, pMonitor->output->parsedEDID)); - } else - pMonitor->output->state->setHDRMetadata(*PHDR ? createHDRMetadata(2, pMonitor->output->parsedEDID) : createHDRMetadata(0, pMonitor->output->parsedEDID)); + m_previousFSWindow = WINDOW; + } else { + if ((pMonitor->output->state->state().hdrMetadata.hdmi_metadata_type1.eotf == 2) != *PHDR) + pMonitor->output->state->setHDRMetadata(*PHDR ? createHDRMetadata(2, pMonitor->output->parsedEDID) : createHDRMetadata(0, pMonitor->output->parsedEDID)); + m_previousFSWindow.reset(); + } } if (pMonitor->ctmUpdated) { diff --git a/src/render/Renderer.hpp b/src/render/Renderer.hpp index 6900c775..f3e0c5a2 100644 --- a/src/render/Renderer.hpp +++ b/src/render/Renderer.hpp @@ -129,6 +129,7 @@ class CHyprRenderer { bool commitPendingAndDoExplicitSync(PHLMONITOR pMonitor); + WP m_previousFSWindow; bool m_bCursorHidden = false; bool m_bCursorHasSurface = false; SP m_pCurrentRenderbuffer = nullptr; From 4f0f512cab5a8052c80b365449b69b953a97e169 Mon Sep 17 00:00:00 2001 From: outfoxxed Date: Sun, 12 Jan 2025 09:09:02 -0800 Subject: [PATCH 0851/2181] protocols: do not capture cursor in toplevel without pointer focus (#9042) --- src/protocols/ToplevelExport.cpp | 21 ++++++++++++++++++++- src/protocols/ToplevelExport.hpp | 7 ++++--- 2 files changed, 24 insertions(+), 4 deletions(-) diff --git a/src/protocols/ToplevelExport.cpp b/src/protocols/ToplevelExport.cpp index 2c934b40..68561533 100644 --- a/src/protocols/ToplevelExport.cpp +++ b/src/protocols/ToplevelExport.cpp @@ -2,6 +2,7 @@ #include "../Compositor.hpp" #include "ForeignToplevelWlr.hpp" #include "../managers/PointerManager.hpp" +#include "../managers/SeatManager.hpp" #include "types/WLBuffer.hpp" #include "types/Buffer.hpp" #include "../helpers/Format.hpp" @@ -77,7 +78,7 @@ CToplevelExportFrame::CToplevelExportFrame(SP re if (!good()) return; - overlayCursor = !!overlayCursor_; + cursorOverlayRequested = !!overlayCursor_; if (!pWindow) { LOGM(ERR, "Client requested sharing of window handle {:x} which does not exist!", pWindow); @@ -247,6 +248,8 @@ bool CToplevelExportFrame::copyShm(timespec* now) { CFramebuffer outFB; outFB.alloc(PMONITOR->vecPixelSize.x, PMONITOR->vecPixelSize.y, PMONITOR->output->state->state().drmFormat); + auto overlayCursor = shouldOverlayCursor(); + if (overlayCursor) { g_pPointerManager->lockSoftwareForMonitor(PMONITOR->self.lock()); g_pPointerManager->damageCursor(PMONITOR->self.lock()); @@ -300,6 +303,8 @@ bool CToplevelExportFrame::copyDmabuf(timespec* now) { CRegion fakeDamage{0, 0, INT16_MAX, INT16_MAX}; + auto overlayCursor = shouldOverlayCursor(); + if (overlayCursor) { g_pPointerManager->lockSoftwareForMonitor(PMONITOR->self.lock()); g_pPointerManager->damageCursor(PMONITOR->self.lock()); @@ -328,6 +333,20 @@ bool CToplevelExportFrame::copyDmabuf(timespec* now) { return true; } +bool CToplevelExportFrame::shouldOverlayCursor() const { + if (!cursorOverlayRequested) + return false; + + auto pointerSurfaceResource = g_pSeatManager->state.pointerFocus.lock(); + + if (!pointerSurfaceResource) + return false; + + auto pointerSurface = CWLSurface::fromResource(pointerSurfaceResource); + + return pointerSurface && pointerSurface->getWindow() == pWindow; +} + bool CToplevelExportFrame::good() { return resource->resource(); } diff --git a/src/protocols/ToplevelExport.hpp b/src/protocols/ToplevelExport.hpp index 1ca3e5aa..956a085b 100644 --- a/src/protocols/ToplevelExport.hpp +++ b/src/protocols/ToplevelExport.hpp @@ -51,9 +51,9 @@ class CToplevelExportFrame { SP resource; PHLWINDOW pWindow; - bool overlayCursor = false; - bool ignoreDamage = false; - bool lockedSWCursors = false; + bool cursorOverlayRequested = false; + bool ignoreDamage = false; + bool lockedSWCursors = false; WP buffer; bool bufferDMA = false; @@ -66,6 +66,7 @@ class CToplevelExportFrame { bool copyDmabuf(timespec* now); bool copyShm(timespec* now); void share(); + bool shouldOverlayCursor() const; friend class CToplevelExportProtocol; }; From a6b263713a2b862ed41362082e2147e081934077 Mon Sep 17 00:00:00 2001 From: outfoxxed Date: Sun, 12 Jan 2025 09:10:36 -0800 Subject: [PATCH 0852/2181] protocols: allow hyprland-toplevel-export to capture hidden windows (#9041) --- src/protocols/ToplevelExport.cpp | 4 ++-- src/render/Renderer.cpp | 14 +++++++------- src/render/Renderer.hpp | 2 +- 3 files changed, 10 insertions(+), 10 deletions(-) diff --git a/src/protocols/ToplevelExport.cpp b/src/protocols/ToplevelExport.cpp index 68561533..0ddd84c8 100644 --- a/src/protocols/ToplevelExport.cpp +++ b/src/protocols/ToplevelExport.cpp @@ -87,7 +87,7 @@ CToplevelExportFrame::CToplevelExportFrame(SP re return; } - if (!pWindow->m_bIsMapped || pWindow->isHidden()) { + if (!pWindow->m_bIsMapped) { LOGM(ERR, "Client requested sharing of window handle {:x} which is not shareable!", pWindow); resource->sendFailed(); PROTO::toplevelExport->destroyResource(this); @@ -148,7 +148,7 @@ void CToplevelExportFrame::copy(CHyprlandToplevelExportFrameV1* pFrame, wl_resou return; } - if (!pWindow->m_bIsMapped || pWindow->isHidden()) { + if (!pWindow->m_bIsMapped) { LOGM(ERR, "Client requested sharing of window handle {:x} which is not shareable (2)!", pWindow); resource->sendFailed(); PROTO::toplevelExport->destroyResource(this); diff --git a/src/render/Renderer.cpp b/src/render/Renderer.cpp index b9c8dd98..d4523a31 100644 --- a/src/render/Renderer.cpp +++ b/src/render/Renderer.cpp @@ -417,8 +417,8 @@ void CHyprRenderer::renderWorkspaceWindows(PHLMONITOR pMonitor, PHLWORKSPACE pWo } } -void CHyprRenderer::renderWindow(PHLWINDOW pWindow, PHLMONITOR pMonitor, timespec* time, bool decorate, eRenderPassMode mode, bool ignorePosition, bool ignoreAllGeometry) { - if (pWindow->isHidden()) +void CHyprRenderer::renderWindow(PHLWINDOW pWindow, PHLMONITOR pMonitor, timespec* time, bool decorate, eRenderPassMode mode, bool ignorePosition, bool standalone) { + if (pWindow->isHidden() && !standalone) return; if (pWindow->m_bFadingOut) { @@ -450,7 +450,7 @@ void CHyprRenderer::renderWindow(PHLWINDOW pWindow, PHLMONITOR pMonitor, timespe renderdata.pos.y = pMonitor->vecPosition.y; } - if (ignoreAllGeometry) + if (standalone) decorate = false; // whether to use m_fMovingToWorkspaceAlpha, only if fading out into an invisible ws @@ -463,12 +463,12 @@ void CHyprRenderer::renderWindow(PHLWINDOW pWindow, PHLMONITOR pMonitor, timespe (USE_WORKSPACE_FADE_ALPHA ? pWindow->m_fMovingToWorkspaceAlpha->value() : 1.F) * pWindow->m_fMovingFromWorkspaceAlpha->value(); renderdata.alpha = pWindow->m_fActiveInactiveAlpha->value(); renderdata.decorate = decorate && !pWindow->m_bX11DoesntWantBorders && !pWindow->isEffectiveInternalFSMode(FSMODE_FULLSCREEN); - renderdata.rounding = ignoreAllGeometry || renderdata.dontRound ? 0 : pWindow->rounding() * pMonitor->scale; - renderdata.roundingPower = ignoreAllGeometry || renderdata.dontRound ? 2.0f : pWindow->roundingPower(); - renderdata.blur = !ignoreAllGeometry && *PBLUR && !DONT_BLUR; + renderdata.rounding = standalone || renderdata.dontRound ? 0 : pWindow->rounding() * pMonitor->scale; + renderdata.roundingPower = standalone || renderdata.dontRound ? 2.0f : pWindow->roundingPower(); + renderdata.blur = !standalone && *PBLUR && !DONT_BLUR; renderdata.pWindow = pWindow; - if (ignoreAllGeometry) { + if (standalone) { renderdata.alpha = 1.f; renderdata.fadeAlpha = 1.f; } diff --git a/src/render/Renderer.hpp b/src/render/Renderer.hpp index f3e0c5a2..8b4988c3 100644 --- a/src/render/Renderer.hpp +++ b/src/render/Renderer.hpp @@ -117,7 +117,7 @@ class CHyprRenderer { void arrangeLayerArray(PHLMONITOR, const std::vector&, bool, CBox*); void renderWorkspaceWindowsFullscreen(PHLMONITOR, PHLWORKSPACE, timespec*); // renders workspace windows (fullscreen) (tiled, floating, pinned, but no special) void renderWorkspaceWindows(PHLMONITOR, PHLWORKSPACE, timespec*); // renders workspace windows (no fullscreen) (tiled, floating, pinned, but no special) - void renderWindow(PHLWINDOW, PHLMONITOR, timespec*, bool, eRenderPassMode, bool ignorePosition = false, bool ignoreAllGeometry = false); + void renderWindow(PHLWINDOW, PHLMONITOR, timespec*, bool, eRenderPassMode, bool ignorePosition = false, bool standalone = false); void renderLayer(PHLLS, PHLMONITOR, timespec*, bool popups = false); void renderSessionLockSurface(SSessionLockSurface*, PHLMONITOR, timespec*); void renderDragIcon(PHLMONITOR, timespec*); From f16f170433540d85cf672217bca2d64c6db9eb01 Mon Sep 17 00:00:00 2001 From: outfoxxed Date: Tue, 14 Jan 2025 08:44:09 -0800 Subject: [PATCH 0853/2181] protocols: immediately copy toplevel content when ignoreDamage set (#9049) Also sets m_ignoreDamage, as it wasn't set before. --- src/protocols/ToplevelExport.cpp | 9 +++++++-- src/protocols/ToplevelExport.hpp | 2 +- 2 files changed, 8 insertions(+), 3 deletions(-) diff --git a/src/protocols/ToplevelExport.cpp b/src/protocols/ToplevelExport.cpp index 0ddd84c8..73e5cad9 100644 --- a/src/protocols/ToplevelExport.cpp +++ b/src/protocols/ToplevelExport.cpp @@ -202,7 +202,12 @@ void CToplevelExportFrame::copy(CHyprlandToplevelExportFrameV1* pFrame, wl_resou buffer = PBUFFER->buffer; - PROTO::toplevelExport->m_vFramesAwaitingWrite.emplace_back(self); + m_ignoreDamage = ignoreDamage; + + if (ignoreDamage && validMapped(pWindow)) + share(); + else + PROTO::toplevelExport->m_vFramesAwaitingWrite.emplace_back(self); } void CToplevelExportFrame::share() { @@ -226,7 +231,7 @@ void CToplevelExportFrame::share() { resource->sendFlags((hyprlandToplevelExportFrameV1Flags)0); - if (!ignoreDamage) { + if (!m_ignoreDamage) { resource->sendDamage(0, 0, box.width, box.height); } diff --git a/src/protocols/ToplevelExport.hpp b/src/protocols/ToplevelExport.hpp index 956a085b..8d734dbd 100644 --- a/src/protocols/ToplevelExport.hpp +++ b/src/protocols/ToplevelExport.hpp @@ -52,7 +52,7 @@ class CToplevelExportFrame { PHLWINDOW pWindow; bool cursorOverlayRequested = false; - bool ignoreDamage = false; + bool m_ignoreDamage = false; bool lockedSWCursors = false; WP buffer; From 25add26881d7b98d2b80eb7a95d3aee0449b72b9 Mon Sep 17 00:00:00 2001 From: vaxerski Date: Tue, 14 Jan 2025 17:52:19 +0100 Subject: [PATCH 0854/2181] renderer: unload background texture if it's disabled ref #9031 --- src/config/ConfigManager.cpp | 5 +++-- src/render/OpenGL.cpp | 21 ++++++++++++++------- src/render/OpenGL.hpp | 4 +++- 3 files changed, 20 insertions(+), 10 deletions(-) diff --git a/src/config/ConfigManager.cpp b/src/config/ConfigManager.cpp index 60723220..17957899 100644 --- a/src/config/ConfigManager.cpp +++ b/src/config/ConfigManager.cpp @@ -899,11 +899,12 @@ void CConfigManager::postConfigReload(const Hyprlang::CParseResult& result) { g_pInputManager->setPointerConfigs(); g_pInputManager->setTouchDeviceConfigs(); g_pInputManager->setTabletConfigs(); - } - if (!isFirstLaunch) g_pHyprOpenGL->m_bReloadScreenShader = true; + g_pHyprOpenGL->ensureBackgroundTexturePresence(); + } + // parseError will be displayed next frame if (result.error) diff --git a/src/render/OpenGL.cpp b/src/render/OpenGL.cpp index 3a4781e7..b68448ae 100644 --- a/src/render/OpenGL.cpp +++ b/src/render/OpenGL.cpp @@ -2699,10 +2699,6 @@ void CHyprOpenGLImpl::initMissingAssetTexture() { void CHyprOpenGLImpl::initAssets() { initMissingAssetTexture(); - static auto PFORCEWALLPAPER = CConfigValue("misc:force_default_wallpaper"); - - const auto FORCEWALLPAPER = std::clamp(*PFORCEWALLPAPER, static_cast(-1L), static_cast(2L)); - m_pLockDeadTexture = loadAsset("lockdead.png"); m_pLockDead2Texture = loadAsset("lockdead2.png"); @@ -2712,9 +2708,20 @@ void CHyprOpenGLImpl::initAssets() { "unknown"), CHyprColor{0.9F, 0.9F, 0.9F, 0.7F}, 20, true); - // create the default background texture - { - std::string texPath = std::format("{}", "wall"); + ensureBackgroundTexturePresence(); +} + +void CHyprOpenGLImpl::ensureBackgroundTexturePresence() { + static auto PNOWALLPAPER = CConfigValue("misc:disable_hyprland_logo"); + static auto PFORCEWALLPAPER = CConfigValue("misc:force_default_wallpaper"); + + const auto FORCEWALLPAPER = std::clamp(*PFORCEWALLPAPER, static_cast(-1L), static_cast(2L)); + + if (*PNOWALLPAPER) + m_pBackgroundTexture.reset(); + else if (!m_pBackgroundTexture) { + // create the default background texture + std::string texPath = "wall"; // get the adequate tex if (FORCEWALLPAPER == -1) { diff --git a/src/render/OpenGL.hpp b/src/render/OpenGL.hpp index 3f117a5a..2b600a03 100644 --- a/src/render/OpenGL.hpp +++ b/src/render/OpenGL.hpp @@ -223,6 +223,8 @@ class CHyprOpenGLImpl { void setDamage(const CRegion& damage, std::optional finalDamage = {}); + void ensureBackgroundTexturePresence(); + uint32_t getPreferredReadFormat(PHLMONITOR pMonitor); std::vector getDRMFormats(); EGLImageKHR createEGLImage(const Aquamarine::SDMABUFAttrs& attrs); @@ -293,7 +295,7 @@ class CHyprOpenGLImpl { CShader m_sFinalScreenShader; CTimer m_tGlobalTimer; - SP m_pMissingAssetTexture, m_pBackgroundTexture, m_pLockDeadTexture, m_pLockDead2Texture, m_pLockTtyTextTexture; + SP m_pMissingAssetTexture, m_pBackgroundTexture, m_pLockDeadTexture, m_pLockDead2Texture, m_pLockTtyTextTexture; // TODO: don't always load lock void logShaderError(const GLuint&, bool program = false); GLuint createProgram(const std::string&, const std::string&, bool dynamic = false); From 52b9ae592b90cc9f857743ae7f59e787cc58fc8a Mon Sep 17 00:00:00 2001 From: UjinT34 <41110182+UjinT34@users.noreply.github.com> Date: Thu, 16 Jan 2025 15:13:47 +0300 Subject: [PATCH 0855/2181] renderer: fix fullscreen hdr check (#9076) --- src/render/Renderer.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/render/Renderer.cpp b/src/render/Renderer.cpp index d4523a31..6c77b27a 100644 --- a/src/render/Renderer.cpp +++ b/src/render/Renderer.cpp @@ -1479,7 +1479,7 @@ bool CHyprRenderer::commitPendingAndDoExplicitSync(PHLMONITOR pMonitor) { SURF->colorManagement->setHDRMetadata(createHDRMetadata(SURF->colorManagement.get()->imageDescription(), pMonitor->output->parsedEDID)); if (needsHdrMetadataUpdate) pMonitor->output->state->setHDRMetadata(SURF->colorManagement->hdrMetadata()); - } else + } else if ((pMonitor->output->state->state().hdrMetadata.hdmi_metadata_type1.eotf == 2) != *PHDR) pMonitor->output->state->setHDRMetadata(*PHDR ? createHDRMetadata(2, pMonitor->output->parsedEDID) : createHDRMetadata(0, pMonitor->output->parsedEDID)); m_previousFSWindow = WINDOW; } else { From 0dc7367a7006cc3cc877d52bf34c4998144bff84 Mon Sep 17 00:00:00 2001 From: Vaxry <43317083+vaxerski@users.noreply.github.com> Date: Thu, 16 Jan 2025 15:42:39 +0100 Subject: [PATCH 0856/2181] renderer: use cairo for cpu buffer rendering (#9071) Instead of a wonky memcpy which doesn't work when anything non-standard is used (size, pos, transform), just use cairo --- src/managers/PointerManager.cpp | 58 +++++++++++++++++++++++++++++---- 1 file changed, 51 insertions(+), 7 deletions(-) diff --git a/src/managers/PointerManager.cpp b/src/managers/PointerManager.cpp index 85e1c601..522187b4 100644 --- a/src/managers/PointerManager.cpp +++ b/src/managers/PointerManager.cpp @@ -12,6 +12,7 @@ #include "SeatManager.hpp" #include #include +#include CPointerManager::CPointerManager() { hooks.monitorAdded = g_pHookSystem->hookDynamic("monitorAdded", [this](void* self, SCallbackInfo& info, std::any data) { @@ -481,15 +482,58 @@ SP CPointerManager::renderHWCursorBuffer(SPdmabuf(); auto [data, fmt, size] = buf->beginDataPtr(0); - memset(data, 0, size); - if (buf->dmabuf().size.x > texture->m_vSize.x) { - size_t STRIDE = 4 * texture->m_vSize.x; - for (int i = 0; i < texture->m_vSize.y; i++) - memcpy(data + i * buf->dmabuf().strides[0], texData.data() + i * STRIDE, STRIDE); - } else - memcpy(data, texData.data(), std::min(size, texData.size())); + auto CAIROSURFACE = cairo_image_surface_create(CAIRO_FORMAT_ARGB32, DMABUF.size.x, DMABUF.size.y); + auto CAIRODATASURFACE = + cairo_image_surface_create_for_data((unsigned char*)texData.data(), CAIRO_FORMAT_ARGB32, texture->m_vSize.x, texture->m_vSize.y, texture->m_vSize.x * 4); + + auto CAIRO = cairo_create(CAIROSURFACE); + + cairo_set_operator(CAIRO, CAIRO_OPERATOR_SOURCE); + cairo_set_source_rgba(CAIRO, 0, 0, 0, 0); + cairo_rectangle(CAIRO, 0, 0, texture->m_vSize.x, texture->m_vSize.y); + cairo_fill(CAIRO); + + const auto PATTERNPRE = cairo_pattern_create_for_surface(CAIRODATASURFACE); + cairo_pattern_set_filter(PATTERNPRE, CAIRO_FILTER_BILINEAR); + cairo_matrix_t matrixPre; + cairo_matrix_init_identity(&matrixPre); + + const auto TR = state->monitor->transform; + + if (TR) { + cairo_matrix_rotate(&matrixPre, M_PI_2 * (double)TR); + + // FIXME: this is wrong, and doesnt work for 5, 6 and 7. (flipped + rot) + // cba to do it rn, does anyone fucking use that?? + if (TR >= WL_OUTPUT_TRANSFORM_FLIPPED) { + cairo_matrix_scale(&matrixPre, -1, 1); + cairo_matrix_translate(&matrixPre, -DMABUF.size.x, 0); + } + + if (TR == 3 || TR == 7) + cairo_matrix_translate(&matrixPre, -DMABUF.size.x, 0); + else if (TR == 2 || TR == 6) + cairo_matrix_translate(&matrixPre, -DMABUF.size.x, -DMABUF.size.y); + else if (TR == 1 || TR == 5) + cairo_matrix_translate(&matrixPre, 0, -DMABUF.size.y); + } + + cairo_pattern_set_matrix(PATTERNPRE, &matrixPre); + cairo_set_source(CAIRO, PATTERNPRE); + cairo_paint(CAIRO); + + cairo_surface_flush(CAIROSURFACE); + + cairo_pattern_destroy(PATTERNPRE); + + memcpy(data, cairo_image_surface_get_data(CAIROSURFACE), (size_t)cairo_image_surface_get_height(CAIROSURFACE) * cairo_image_surface_get_stride(CAIROSURFACE)); + + cairo_destroy(CAIRO); + cairo_surface_destroy(CAIROSURFACE); + cairo_surface_destroy(CAIRODATASURFACE); buf->endDataPtr(); From 2bad73354a5dbb9be8ba9a39b6238017a216a25b Mon Sep 17 00:00:00 2001 From: user111111111111111111111111111111111 <192911676+user111111111111111111111111111111111@users.noreply.github.com> Date: Fri, 17 Jan 2025 15:21:35 +0000 Subject: [PATCH 0857/2181] core: cleanup header includes (#9088) Cleanup some unneeded includes to speed up compilation --- src/Compositor.cpp | 19 +++++++++++++++++++ src/Compositor.hpp | 18 ------------------ src/SharedDefs.hpp | 1 + src/config/ConfigManager.cpp | 13 ++++++++++++- src/config/ConfigManager.hpp | 13 +++++++------ src/config/ConfigValue.hpp | 3 +-- src/debug/CrashReporter.cpp | 1 + src/debug/HyprCtl.cpp | 10 ++++++++++ src/debug/HyprCtl.hpp | 2 +- src/debug/HyprDebugOverlay.cpp | 1 + src/debug/HyprDebugOverlay.hpp | 3 +-- src/debug/HyprNotificationOverlay.cpp | 4 ++++ src/debug/HyprNotificationOverlay.hpp | 1 - src/debug/Log.cpp | 1 - src/debug/Log.hpp | 2 -- src/defines.hpp | 2 ++ src/desktop/DesktopTypes.hpp | 2 +- src/desktop/LayerSurface.cpp | 6 ++++++ src/desktop/LayerSurface.hpp | 1 - src/desktop/Popup.cpp | 4 ++++ src/desktop/Subsurface.cpp | 2 ++ src/desktop/WLSurface.cpp | 4 +++- src/desktop/Window.cpp | 7 +++++++ src/desktop/Window.hpp | 2 +- src/desktop/Workspace.cpp | 2 ++ src/devices/Keyboard.cpp | 1 - src/events/Windows.cpp | 5 +++++ src/helpers/Color.hpp | 1 - src/helpers/MiscFunctions.cpp | 2 ++ src/helpers/MiscFunctions.hpp | 2 -- src/helpers/Monitor.cpp | 6 ++++++ src/helpers/Monitor.hpp | 1 + src/helpers/WLClasses.hpp | 6 +++--- src/hyprerror/HyprError.cpp | 2 ++ src/layout/DwindleLayout.cpp | 4 ++++ src/layout/IHyprLayout.cpp | 5 +++++ src/layout/MasterLayout.cpp | 4 ++++ src/layout/MasterLayout.hpp | 2 +- src/macros.hpp | 1 + src/managers/AnimationManager.cpp | 1 + src/managers/CursorManager.cpp | 1 + src/managers/HookSystemManager.hpp | 2 +- src/managers/KeybindManager.cpp | 6 ++++++ src/managers/PointerManager.cpp | 4 ++++ src/managers/ProtocolManager.hpp | 1 - src/managers/SeatManager.cpp | 3 +++ src/managers/SeatManager.hpp | 1 - src/managers/SessionLockManager.cpp | 4 +++- src/managers/input/InputManager.cpp | 5 +++++ src/managers/input/InputMethodPopup.cpp | 2 ++ src/managers/input/InputMethodRelay.cpp | 1 + src/managers/input/Swipe.cpp | 3 +++ src/managers/input/Tablets.cpp | 2 +- src/managers/input/TextInput.hpp | 2 +- src/managers/input/Touch.cpp | 2 ++ src/plugins/HookSystem.cpp | 4 ++-- src/plugins/PluginAPI.cpp | 5 +++++ src/plugins/PluginSystem.cpp | 4 +++- src/protocols/CTMControl.cpp | 1 + src/protocols/DRMLease.cpp | 1 + src/protocols/ForeignToplevel.cpp | 1 + src/protocols/ForeignToplevelWlr.cpp | 1 + src/protocols/GammaControl.cpp | 2 +- src/protocols/GlobalShortcuts.cpp | 1 - src/protocols/LayerShell.cpp | 2 ++ src/protocols/MesaDRM.cpp | 1 + src/protocols/OutputManagement.cpp | 3 +++ src/protocols/OutputPower.cpp | 2 +- src/protocols/PointerConstraints.cpp | 3 +++ src/protocols/PointerGestures.cpp | 1 - src/protocols/RelativePointer.cpp | 3 +-- src/protocols/Screencopy.cpp | 4 ++++ src/protocols/SessionLock.cpp | 3 ++- src/protocols/SinglePixel.cpp | 1 + src/protocols/Tablet.cpp | 1 + src/protocols/TearingControl.cpp | 1 + src/protocols/TextInputV1.cpp | 1 - src/protocols/ToplevelExport.cpp | 3 +++ src/protocols/XDGOutput.cpp | 4 ++-- src/protocols/XDGShell.cpp | 1 + src/protocols/core/DataDevice.cpp | 4 ++++ src/protocols/core/Shm.cpp | 2 +- src/protocols/types/DMABuffer.cpp | 1 + src/protocols/types/WLBuffer.cpp | 1 - src/render/OpenGL.cpp | 3 +++ src/render/OpenGL.hpp | 1 - src/render/Renderbuffer.cpp | 3 ++- src/render/Renderer.cpp | 7 +++++++ src/render/Renderer.hpp | 1 + .../decorations/CHyprBorderDecoration.cpp | 2 ++ .../decorations/CHyprDropShadowDecoration.cpp | 1 + .../decorations/CHyprGroupBarDecoration.cpp | 2 ++ .../decorations/DecorationPositioner.cpp | 4 +++- src/render/pass/Pass.cpp | 1 + src/render/pass/SurfacePassElement.cpp | 1 + src/xwayland/XSurface.cpp | 1 - src/xwayland/XWM.hpp | 1 - 97 files changed, 224 insertions(+), 72 deletions(-) diff --git a/src/Compositor.cpp b/src/Compositor.cpp index fcd15312..496ca4fe 100644 --- a/src/Compositor.cpp +++ b/src/Compositor.cpp @@ -42,6 +42,25 @@ #include "helpers/ByteOperations.hpp" #include "render/decorations/CHyprGroupBarDecoration.hpp" +#include "managers/KeybindManager.hpp" +#include "managers/SessionLockManager.hpp" +#include "managers/ThreadManager.hpp" +#include "managers/XWaylandManager.hpp" + +#include "config/ConfigManager.hpp" +#include "render/OpenGL.hpp" +#include "managers/input/InputManager.hpp" +#include "managers/AnimationManager.hpp" +#include "managers/EventManager.hpp" +#include "managers/HookSystemManager.hpp" +#include "managers/ProtocolManager.hpp" +#include "managers/LayoutManager.hpp" +#include "plugins/PluginSystem.hpp" +#include "helpers/Watchdog.hpp" +#include "hyprerror/HyprError.hpp" +#include "debug/HyprNotificationOverlay.hpp" +#include "debug/HyprDebugOverlay.hpp" + #include #include diff --git a/src/Compositor.hpp b/src/Compositor.hpp index 629b71bc..0a701a59 100644 --- a/src/Compositor.hpp +++ b/src/Compositor.hpp @@ -5,30 +5,12 @@ #include #include "defines.hpp" -#include "debug/Log.hpp" -#include "events/Events.hpp" -#include "config/ConfigManager.hpp" #include "managers/ThreadManager.hpp" #include "managers/XWaylandManager.hpp" -#include "managers/input/InputManager.hpp" -#include "managers/LayoutManager.hpp" #include "managers/KeybindManager.hpp" -#include "managers/AnimationManager.hpp" -#include "managers/EventManager.hpp" -#include "managers/ProtocolManager.hpp" #include "managers/SessionLockManager.hpp" -#include "managers/HookSystemManager.hpp" -#include "debug/HyprDebugOverlay.hpp" -#include "debug/HyprNotificationOverlay.hpp" -#include "helpers/Monitor.hpp" -#include "desktop/Workspace.hpp" #include "desktop/Window.hpp" #include "protocols/types/ColorManagement.hpp" -#include "render/Renderer.hpp" -#include "render/OpenGL.hpp" -#include "hyprerror/HyprError.hpp" -#include "plugins/PluginSystem.hpp" -#include "helpers/Watchdog.hpp" #include #include diff --git a/src/SharedDefs.hpp b/src/SharedDefs.hpp index a6271556..a46a2429 100644 --- a/src/SharedDefs.hpp +++ b/src/SharedDefs.hpp @@ -4,6 +4,7 @@ #include #include #include +#include #include enum eIcons : uint8_t { diff --git a/src/config/ConfigManager.cpp b/src/config/ConfigManager.cpp index 17957899..52f2e316 100644 --- a/src/config/ConfigManager.cpp +++ b/src/config/ConfigManager.cpp @@ -11,8 +11,19 @@ #include "../protocols/LayerShell.hpp" #include "../xwayland/XWayland.hpp" #include "../protocols/OutputManagement.hpp" -#include "managers/AnimationManager.hpp" +#include "../managers/AnimationManager.hpp" +#include "../desktop/LayerSurface.hpp" +#include "defaultConfig.hpp" +#include "../render/Renderer.hpp" +#include "../hyprerror/HyprError.hpp" +#include "../managers/input/InputManager.hpp" +#include "../managers/LayoutManager.hpp" +#include "../managers/EventManager.hpp" +#include "../debug/HyprNotificationOverlay.hpp" +#include "../plugins/PluginSystem.hpp" + +#include "managers/HookSystemManager.hpp" #include #include #include diff --git a/src/config/ConfigManager.hpp b/src/config/ConfigManager.hpp index a27ee7ab..1ba1df62 100644 --- a/src/config/ConfigManager.hpp +++ b/src/config/ConfigManager.hpp @@ -4,23 +4,24 @@ #define CONFIG_MANAGER_H #include -#include "../debug/Log.hpp" #include #include "../defines.hpp" #include #include -#include #include #include #include -#include "../helpers/WLClasses.hpp" #include "../helpers/Monitor.hpp" -#include "../helpers/varlist/VarList.hpp" #include "../desktop/Window.hpp" -#include "../desktop/LayerSurface.hpp" +#include "../desktop/LayerRule.hpp" -#include "defaultConfig.hpp" #include "ConfigDataValues.hpp" +#include "SharedDefs.hpp" +#include "helpers/Color.hpp" +#include "desktop/DesktopTypes.hpp" +#include "helpers/memory/Memory.hpp" +#include "desktop/WindowRule.hpp" +#include "managers/XWaylandManager.hpp" #include diff --git a/src/config/ConfigValue.hpp b/src/config/ConfigValue.hpp index 181fdd0f..089ae8bf 100644 --- a/src/config/ConfigValue.hpp +++ b/src/config/ConfigValue.hpp @@ -3,7 +3,6 @@ #include #include #include -#include "../debug/Log.hpp" #include "../macros.hpp" #include "ConfigManager.hpp" @@ -71,4 +70,4 @@ template <> inline Hyprlang::CUSTOMTYPE CConfigValue::operator*() const { RASSERT(false, "Impossible to implement operator* of CConfigValue, use ptr()"); return *ptr(); -} \ No newline at end of file +} diff --git a/src/debug/CrashReporter.cpp b/src/debug/CrashReporter.cpp index 7bff7295..f6e0b55f 100644 --- a/src/debug/CrashReporter.cpp +++ b/src/debug/CrashReporter.cpp @@ -6,6 +6,7 @@ #include #include #include +#include "../helpers/MiscFunctions.hpp" #include "../plugins/PluginSystem.hpp" #include "../signal-safe.hpp" diff --git a/src/debug/HyprCtl.cpp b/src/debug/HyprCtl.cpp index 7edace21..41b0abe1 100644 --- a/src/debug/HyprCtl.cpp +++ b/src/debug/HyprCtl.cpp @@ -39,8 +39,18 @@ using namespace Hyprutils::String; #include "debug/RollingLogFollow.hpp" #include "config/ConfigManager.hpp" #include "helpers/MiscFunctions.hpp" +#include "../desktop/LayerSurface.hpp" #include "../version.h" +#include "../Compositor.hpp" +#include "../managers/input/InputManager.hpp" +#include "../managers/XWaylandManager.hpp" +#include "../managers/LayoutManager.hpp" +#include "../plugins/PluginSystem.hpp" +#include "../managers/AnimationManager.hpp" +#include "../debug/HyprNotificationOverlay.hpp" +#include "../render/Renderer.hpp" + static void trimTrailingComma(std::string& str) { if (!str.empty() && str.back() == ',') str.pop_back(); diff --git a/src/debug/HyprCtl.hpp b/src/debug/HyprCtl.hpp index c1bf51ca..2603612c 100644 --- a/src/debug/HyprCtl.hpp +++ b/src/debug/HyprCtl.hpp @@ -1,8 +1,8 @@ #pragma once -#include "../Compositor.hpp" #include #include "../helpers/MiscFunctions.hpp" +#include "../desktop/Window.hpp" #include // exposed for main.cpp diff --git a/src/debug/HyprDebugOverlay.cpp b/src/debug/HyprDebugOverlay.cpp index d72e2144..6e7a0407 100644 --- a/src/debug/HyprDebugOverlay.cpp +++ b/src/debug/HyprDebugOverlay.cpp @@ -4,6 +4,7 @@ #include "../Compositor.hpp" #include "../render/pass/TexPassElement.hpp" #include "../render/Renderer.hpp" +#include "../managers/AnimationManager.hpp" CHyprDebugOverlay::CHyprDebugOverlay() { m_pTexture = makeShared(); diff --git a/src/debug/HyprDebugOverlay.hpp b/src/debug/HyprDebugOverlay.hpp index 42cdac55..a58ecffc 100644 --- a/src/debug/HyprDebugOverlay.hpp +++ b/src/debug/HyprDebugOverlay.hpp @@ -1,7 +1,6 @@ #pragma once #include "../defines.hpp" -#include "../helpers/Monitor.hpp" #include "../render/Texture.hpp" #include #include @@ -49,4 +48,4 @@ class CHyprDebugOverlay { friend class CHyprRenderer; }; -inline std::unique_ptr g_pDebugOverlay; \ No newline at end of file +inline std::unique_ptr g_pDebugOverlay; diff --git a/src/debug/HyprNotificationOverlay.cpp b/src/debug/HyprNotificationOverlay.cpp index 504ad6c9..09125243 100644 --- a/src/debug/HyprNotificationOverlay.cpp +++ b/src/debug/HyprNotificationOverlay.cpp @@ -5,6 +5,10 @@ #include "../config/ConfigValue.hpp" #include "../render/pass/TexPassElement.hpp" +#include "../managers/AnimationManager.hpp" +#include "../managers/HookSystemManager.hpp" +#include "../render/Renderer.hpp" + static inline auto iconBackendFromLayout(PangoLayout* layout) { // preference: Nerd > FontAwesome > text auto eIconBackendChecks = std::array{ICONS_BACKEND_NF, ICONS_BACKEND_FA}; diff --git a/src/debug/HyprNotificationOverlay.hpp b/src/debug/HyprNotificationOverlay.hpp index 3ff0b35c..2546d04f 100644 --- a/src/debug/HyprNotificationOverlay.hpp +++ b/src/debug/HyprNotificationOverlay.hpp @@ -2,7 +2,6 @@ #include "../defines.hpp" #include "../helpers/Timer.hpp" -#include "../helpers/Monitor.hpp" #include "../render/Texture.hpp" #include "../SharedDefs.hpp" diff --git a/src/debug/Log.cpp b/src/debug/Log.cpp index 1563628c..9cf86345 100644 --- a/src/debug/Log.cpp +++ b/src/debug/Log.cpp @@ -1,6 +1,5 @@ #include "Log.hpp" #include "../defines.hpp" -#include "../Compositor.hpp" #include "RollingLogFollow.hpp" #include diff --git a/src/debug/Log.hpp b/src/debug/Log.hpp index 9696aa90..3791aeac 100644 --- a/src/debug/Log.hpp +++ b/src/debug/Log.hpp @@ -5,8 +5,6 @@ #include #include #include -#include "../includes.hpp" -#include "../helpers/MiscFunctions.hpp" #define LOGMESSAGESIZE 1024 #define ROLLING_LOG_SIZE 4096 diff --git a/src/defines.hpp b/src/defines.hpp index 41ee4502..5c70f21a 100644 --- a/src/defines.hpp +++ b/src/defines.hpp @@ -1,3 +1,5 @@ +#pragma once + #include "includes.hpp" #include "debug/Log.hpp" #include "helpers/Color.hpp" diff --git a/src/desktop/DesktopTypes.hpp b/src/desktop/DesktopTypes.hpp index 7f812cc1..ae2ac366 100644 --- a/src/desktop/DesktopTypes.hpp +++ b/src/desktop/DesktopTypes.hpp @@ -1,5 +1,5 @@ #pragma once -#include "../macros.hpp" +#include "helpers/memory/Memory.hpp" class CWorkspace; class CWindow; class CLayerSurface; diff --git a/src/desktop/LayerSurface.cpp b/src/desktop/LayerSurface.cpp index fe11f3f3..c572f6b2 100644 --- a/src/desktop/LayerSurface.cpp +++ b/src/desktop/LayerSurface.cpp @@ -5,6 +5,12 @@ #include "../protocols/core/Compositor.hpp" #include "../managers/SeatManager.hpp" #include "../managers/AnimationManager.hpp" +#include "../render/Renderer.hpp" +#include "../config/ConfigManager.hpp" +#include "../helpers/Monitor.hpp" +#include "../managers/input/InputManager.hpp" +#include "../managers/HookSystemManager.hpp" +#include "../managers/EventManager.hpp" PHLLS CLayerSurface::create(SP resource) { PHLLS pLS = SP(new CLayerSurface(resource)); diff --git a/src/desktop/LayerSurface.hpp b/src/desktop/LayerSurface.hpp index 3a03e57e..591dfd99 100644 --- a/src/desktop/LayerSurface.hpp +++ b/src/desktop/LayerSurface.hpp @@ -4,7 +4,6 @@ #include "../defines.hpp" #include "WLSurface.hpp" #include "../helpers/AnimatedVariable.hpp" -#include "LayerRule.hpp" class CLayerShellResource; diff --git a/src/desktop/Popup.cpp b/src/desktop/Popup.cpp index ce286b28..ce6ab9a0 100644 --- a/src/desktop/Popup.cpp +++ b/src/desktop/Popup.cpp @@ -6,6 +6,10 @@ #include "../protocols/core/Compositor.hpp" #include "../managers/SeatManager.hpp" #include "../managers/eventLoop/EventLoopManager.hpp" +#include "../desktop/LayerSurface.hpp" +#include "../managers/input/InputManager.hpp" +#include "../render/Renderer.hpp" +#include "../render/OpenGL.hpp" #include CPopup::CPopup(PHLWINDOW pOwner) : m_pWindowOwner(pOwner) { diff --git a/src/desktop/Subsurface.cpp b/src/desktop/Subsurface.cpp index 62854f80..26638f7a 100644 --- a/src/desktop/Subsurface.cpp +++ b/src/desktop/Subsurface.cpp @@ -4,6 +4,8 @@ #include "../config/ConfigValue.hpp" #include "../protocols/core/Compositor.hpp" #include "../protocols/core/Subcompositor.hpp" +#include "../render/Renderer.hpp" +#include "../managers/input/InputManager.hpp" CSubsurface::CSubsurface(PHLWINDOW pOwner) : m_pWindowParent(pOwner) { initSignals(); diff --git a/src/desktop/WLSurface.cpp b/src/desktop/WLSurface.cpp index 9ed8ec49..e86ac036 100644 --- a/src/desktop/WLSurface.cpp +++ b/src/desktop/WLSurface.cpp @@ -1,7 +1,9 @@ #include "WLSurface.hpp" -#include "../Compositor.hpp" +#include "LayerSurface.hpp" +#include "../desktop/Window.hpp" #include "../protocols/core/Compositor.hpp" #include "../protocols/LayerShell.hpp" +#include "../render/Renderer.hpp" void CWLSurface::assign(SP pSurface) { m_pResource = pSurface; diff --git a/src/desktop/Window.cpp b/src/desktop/Window.cpp index 5608daef..241a17d7 100644 --- a/src/desktop/Window.cpp +++ b/src/desktop/Window.cpp @@ -17,6 +17,13 @@ #include "../protocols/core/Compositor.hpp" #include "../xwayland/XWayland.hpp" #include "../helpers/Color.hpp" +#include "../events/Events.hpp" +#include "../managers/XWaylandManager.hpp" +#include "../render/Renderer.hpp" +#include "../managers/LayoutManager.hpp" +#include "../managers/HookSystemManager.hpp" +#include "../managers/EventManager.hpp" +#include "../managers/input/InputManager.hpp" #include diff --git a/src/desktop/Window.hpp b/src/desktop/Window.hpp index d503ac3b..ebda235c 100644 --- a/src/desktop/Window.hpp +++ b/src/desktop/Window.hpp @@ -4,7 +4,6 @@ #include #include "../config/ConfigDataValues.hpp" -#include "../defines.hpp" #include "../helpers/AnimatedVariable.hpp" #include "../helpers/math/Math.hpp" #include "../helpers/signal/Signal.hpp" @@ -12,6 +11,7 @@ #include "../macros.hpp" #include "../managers/XWaylandManager.hpp" #include "../render/decorations/IHyprWindowDecoration.hpp" +#include "../render/Transformer.hpp" #include "DesktopTypes.hpp" #include "Popup.hpp" #include "Subsurface.hpp" diff --git a/src/desktop/Workspace.cpp b/src/desktop/Workspace.cpp index 07c1a435..99ba441d 100644 --- a/src/desktop/Workspace.cpp +++ b/src/desktop/Workspace.cpp @@ -3,6 +3,8 @@ #include "../config/ConfigValue.hpp" #include "config/ConfigManager.hpp" #include "managers/AnimationManager.hpp" +#include "../managers/EventManager.hpp" +#include "../managers/HookSystemManager.hpp" #include #include diff --git a/src/devices/Keyboard.cpp b/src/devices/Keyboard.cpp index 0a8f6b57..191cc6b2 100644 --- a/src/devices/Keyboard.cpp +++ b/src/devices/Keyboard.cpp @@ -1,6 +1,5 @@ #include "Keyboard.hpp" #include "../defines.hpp" -#include "../Compositor.hpp" #include diff --git a/src/events/Windows.cpp b/src/events/Windows.cpp index 14e89b4b..cadd4cbc 100644 --- a/src/events/Windows.cpp +++ b/src/events/Windows.cpp @@ -14,6 +14,11 @@ #include "../xwayland/XSurface.hpp" #include "managers/AnimationManager.hpp" #include "managers/PointerManager.hpp" +#include "../desktop/LayerSurface.hpp" +#include "../managers/input/InputManager.hpp" +#include "../managers/LayoutManager.hpp" +#include "../managers/EventManager.hpp" +#include "../managers/AnimationManager.hpp" #include using namespace Hyprutils::String; diff --git a/src/helpers/Color.hpp b/src/helpers/Color.hpp index 0ea816f3..8050bebd 100644 --- a/src/helpers/Color.hpp +++ b/src/helpers/Color.hpp @@ -2,7 +2,6 @@ #include #include -#include "../debug/Log.hpp" #include "../macros.hpp" class CHyprColor { diff --git a/src/helpers/MiscFunctions.cpp b/src/helpers/MiscFunctions.cpp index 0fa73e45..fafe1811 100644 --- a/src/helpers/MiscFunctions.cpp +++ b/src/helpers/MiscFunctions.cpp @@ -3,6 +3,8 @@ #include #include "../Compositor.hpp" #include "../managers/TokenManager.hpp" +#include "Monitor.hpp" +#include "../config/ConfigManager.hpp" #include #include #include diff --git a/src/helpers/MiscFunctions.hpp b/src/helpers/MiscFunctions.hpp index 64802279..d0824284 100644 --- a/src/helpers/MiscFunctions.hpp +++ b/src/helpers/MiscFunctions.hpp @@ -1,9 +1,7 @@ #pragma once #include -#include #include -#include "math/Math.hpp" #include #include #include diff --git a/src/helpers/Monitor.cpp b/src/helpers/Monitor.cpp index cf62bc54..718baf23 100644 --- a/src/helpers/Monitor.cpp +++ b/src/helpers/Monitor.cpp @@ -17,9 +17,15 @@ #include "../managers/PointerManager.hpp" #include "../managers/eventLoop/EventLoopManager.hpp" #include "../protocols/core/Compositor.hpp" +#include "../render/Renderer.hpp" +#include "../managers/EventManager.hpp" +#include "../managers/LayoutManager.hpp" +#include "../managers/input/InputManager.hpp" #include "sync/SyncTimeline.hpp" +#include "../desktop/LayerSurface.hpp" #include #include "debug/Log.hpp" +#include "debug/HyprNotificationOverlay.hpp" #include #include #include diff --git a/src/helpers/Monitor.hpp b/src/helpers/Monitor.hpp index 8c7566e2..3335a896 100644 --- a/src/helpers/Monitor.hpp +++ b/src/helpers/Monitor.hpp @@ -4,6 +4,7 @@ #include #include #include "../SharedDefs.hpp" +#include "MiscFunctions.hpp" #include "WLClasses.hpp" #include #include diff --git a/src/helpers/WLClasses.hpp b/src/helpers/WLClasses.hpp index b6e3ac12..c2e828e7 100644 --- a/src/helpers/WLClasses.hpp +++ b/src/helpers/WLClasses.hpp @@ -1,13 +1,13 @@ #pragma once -#include "../events/Events.hpp" #include "../defines.hpp" -#include "../desktop/Window.hpp" #include "../desktop/Subsurface.hpp" #include "../desktop/Popup.hpp" #include "../desktop/WLSurface.hpp" +#include "macros.hpp" +#include "desktop/DesktopTypes.hpp" +#include "helpers/memory/Memory.hpp" #include "signal/Signal.hpp" -#include "math/Math.hpp" class CMonitor; class IPointer; diff --git a/src/hyprerror/HyprError.cpp b/src/hyprerror/HyprError.cpp index 5e0dcf5e..d14173bf 100644 --- a/src/hyprerror/HyprError.cpp +++ b/src/hyprerror/HyprError.cpp @@ -4,6 +4,8 @@ #include "../config/ConfigValue.hpp" #include "../render/pass/TexPassElement.hpp" #include "../managers/AnimationManager.hpp" +#include "../render/Renderer.hpp" +#include "../managers/HookSystemManager.hpp" #include using namespace Hyprutils::Animation; diff --git a/src/layout/DwindleLayout.cpp b/src/layout/DwindleLayout.cpp index 2ee41eba..c6cf2b4c 100644 --- a/src/layout/DwindleLayout.cpp +++ b/src/layout/DwindleLayout.cpp @@ -2,6 +2,10 @@ #include "../Compositor.hpp" #include "../config/ConfigValue.hpp" #include "../render/decorations/CHyprGroupBarDecoration.hpp" +#include "../render/Renderer.hpp" +#include "../managers/input/InputManager.hpp" +#include "../managers/LayoutManager.hpp" +#include "../managers/EventManager.hpp" void SDwindleNodeData::recalcSizePosRecursive(bool force, bool horizontalOverride, bool verticalOverride) { if (children[0]) { diff --git a/src/layout/IHyprLayout.cpp b/src/layout/IHyprLayout.cpp index eeebd815..156141f6 100644 --- a/src/layout/IHyprLayout.cpp +++ b/src/layout/IHyprLayout.cpp @@ -7,6 +7,11 @@ #include "../protocols/XDGShell.hpp" #include "../protocols/core/Compositor.hpp" #include "../xwayland/XSurface.hpp" +#include "../render/Renderer.hpp" +#include "../managers/input/InputManager.hpp" +#include "../managers/LayoutManager.hpp" +#include "../managers/EventManager.hpp" +#include "../managers/HookSystemManager.hpp" void IHyprLayout::onWindowCreated(PHLWINDOW pWindow, eDirection direction) { CBox desiredGeometry = {}; diff --git a/src/layout/MasterLayout.cpp b/src/layout/MasterLayout.cpp index e6e22326..3b8ff734 100644 --- a/src/layout/MasterLayout.cpp +++ b/src/layout/MasterLayout.cpp @@ -4,6 +4,10 @@ #include "config/ConfigDataValues.hpp" #include #include "../config/ConfigValue.hpp" +#include "../render/Renderer.hpp" +#include "../managers/input/InputManager.hpp" +#include "../managers/LayoutManager.hpp" +#include "../managers/EventManager.hpp" SMasterNodeData* CHyprMasterLayout::getNodeFromWindow(PHLWINDOW pWindow) { for (auto& nd : m_lMasterNodesData) { diff --git a/src/layout/MasterLayout.hpp b/src/layout/MasterLayout.hpp index 03ca3c3b..381ccc9d 100644 --- a/src/layout/MasterLayout.hpp +++ b/src/layout/MasterLayout.hpp @@ -2,7 +2,7 @@ #include "IHyprLayout.hpp" #include "../desktop/DesktopTypes.hpp" -#include "../config/ConfigManager.hpp" +#include "../helpers/varlist/VarList.hpp" #include #include #include diff --git a/src/macros.hpp b/src/macros.hpp index de2fd009..08c17952 100644 --- a/src/macros.hpp +++ b/src/macros.hpp @@ -6,6 +6,7 @@ #include #include "helpers/memory/Memory.hpp" +#include "debug/Log.hpp" #ifndef NDEBUG #ifdef HYPRLAND_DEBUG diff --git a/src/managers/AnimationManager.cpp b/src/managers/AnimationManager.cpp index 28adc330..9cf35116 100644 --- a/src/managers/AnimationManager.cpp +++ b/src/managers/AnimationManager.cpp @@ -10,6 +10,7 @@ #include "../desktop/LayerSurface.hpp" #include "eventLoop/EventLoopManager.hpp" #include "../helpers/varlist/VarList.hpp" +#include "../render/Renderer.hpp" #include #include diff --git a/src/managers/CursorManager.cpp b/src/managers/CursorManager.cpp index 2dd97feb..d6584f35 100644 --- a/src/managers/CursorManager.cpp +++ b/src/managers/CursorManager.cpp @@ -3,6 +3,7 @@ #include "../config/ConfigValue.hpp" #include "PointerManager.hpp" #include "../xwayland/XWayland.hpp" +#include "../managers/HookSystemManager.hpp" static int cursorAnimTimer(SP self, void* data) { const auto cursorMgr = reinterpret_cast(data); diff --git a/src/managers/HookSystemManager.hpp b/src/managers/HookSystemManager.hpp index 75377aaa..5a9d0c00 100644 --- a/src/managers/HookSystemManager.hpp +++ b/src/managers/HookSystemManager.hpp @@ -57,4 +57,4 @@ class CHookSystemManager { std::unordered_map> m_mRegisteredHooks; }; -inline std::unique_ptr g_pHookSystem; \ No newline at end of file +inline std::unique_ptr g_pHookSystem; diff --git a/src/managers/KeybindManager.cpp b/src/managers/KeybindManager.cpp index 9a719130..a1979206 100644 --- a/src/managers/KeybindManager.cpp +++ b/src/managers/KeybindManager.cpp @@ -13,6 +13,12 @@ #include "debug/Log.hpp" #include "helpers/varlist/VarList.hpp" #include "../helpers/signal/Signal.hpp" +#include "../managers/HookSystemManager.hpp" +#include "../managers/input/InputManager.hpp" +#include "../managers/LayoutManager.hpp" +#include "../managers/EventManager.hpp" +#include "../render/Renderer.hpp" +#include "../hyprerror/HyprError.hpp" #include #include diff --git a/src/managers/PointerManager.cpp b/src/managers/PointerManager.cpp index 522187b4..df145f6d 100644 --- a/src/managers/PointerManager.cpp +++ b/src/managers/PointerManager.cpp @@ -9,6 +9,10 @@ #include "../protocols/core/Seat.hpp" #include "eventLoop/EventLoopManager.hpp" #include "../render/pass/TexPassElement.hpp" +#include "../managers/input/InputManager.hpp" +#include "../managers/HookSystemManager.hpp" +#include "../render/Renderer.hpp" +#include "../render/OpenGL.hpp" #include "SeatManager.hpp" #include #include diff --git a/src/managers/ProtocolManager.hpp b/src/managers/ProtocolManager.hpp index 69dadd0f..6ceff9ad 100644 --- a/src/managers/ProtocolManager.hpp +++ b/src/managers/ProtocolManager.hpp @@ -1,7 +1,6 @@ #pragma once #include "../defines.hpp" -#include "../helpers/Monitor.hpp" #include "../helpers/memory/Memory.hpp" #include "../helpers/signal/Signal.hpp" #include diff --git a/src/managers/SeatManager.cpp b/src/managers/SeatManager.cpp index 3b9a4925..8fee6b16 100644 --- a/src/managers/SeatManager.cpp +++ b/src/managers/SeatManager.cpp @@ -6,6 +6,9 @@ #include "../protocols/core/Compositor.hpp" #include "../Compositor.hpp" #include "../devices/IKeyboard.hpp" +#include "../desktop/LayerSurface.hpp" +#include "../managers/input/InputManager.hpp" +#include "../managers/HookSystemManager.hpp" #include "wlr-layer-shell-unstable-v1.hpp" #include #include diff --git a/src/managers/SeatManager.hpp b/src/managers/SeatManager.hpp index ccfe5e76..32472aa3 100644 --- a/src/managers/SeatManager.hpp +++ b/src/managers/SeatManager.hpp @@ -2,7 +2,6 @@ #include #include -#include "../macros.hpp" #include "../helpers/signal/Signal.hpp" #include "../helpers/math/Math.hpp" #include "../protocols/types/DataDevice.hpp" diff --git a/src/managers/SessionLockManager.cpp b/src/managers/SessionLockManager.cpp index b7110990..3d77f05a 100644 --- a/src/managers/SessionLockManager.cpp +++ b/src/managers/SessionLockManager.cpp @@ -4,6 +4,8 @@ #include "../protocols/FractionalScale.hpp" #include "../protocols/SessionLock.hpp" #include "../managers/SeatManager.hpp" +#include "../render/Renderer.hpp" +#include "../managers/input/InputManager.hpp" #include #include @@ -185,4 +187,4 @@ bool CSessionLockManager::shallConsiderLockMissing() { static auto LOCKDEAD_SCREEN_DELAY = CConfigValue("misc:lockdead_screen_delay"); return m_pSessionLock->mLockTimer.getMillis() > *LOCKDEAD_SCREEN_DELAY; -} \ No newline at end of file +} diff --git a/src/managers/input/InputManager.cpp b/src/managers/input/InputManager.cpp index 8a50a7bf..3d8c6de8 100644 --- a/src/managers/input/InputManager.cpp +++ b/src/managers/input/InputManager.cpp @@ -5,6 +5,7 @@ #include #include "../../config/ConfigValue.hpp" #include "../../desktop/Window.hpp" +#include "../../desktop/LayerSurface.hpp" #include "../../protocols/CursorShape.hpp" #include "../../protocols/IdleInhibit.hpp" #include "../../protocols/RelativePointer.hpp" @@ -29,6 +30,10 @@ #include "../../managers/PointerManager.hpp" #include "../../managers/SeatManager.hpp" #include "../../managers/KeybindManager.hpp" +#include "../../render/Renderer.hpp" +#include "../../managers/HookSystemManager.hpp" +#include "../../managers/EventManager.hpp" +#include "../../managers/LayoutManager.hpp" #include diff --git a/src/managers/input/InputMethodPopup.cpp b/src/managers/input/InputMethodPopup.cpp index ffb4edcc..8c55416b 100644 --- a/src/managers/input/InputMethodPopup.cpp +++ b/src/managers/input/InputMethodPopup.cpp @@ -4,6 +4,8 @@ #include "../../protocols/FractionalScale.hpp" #include "../../protocols/InputMethodV2.hpp" #include "../../protocols/core/Compositor.hpp" +#include "../../helpers/Monitor.hpp" +#include "../../render/Renderer.hpp" CInputPopup::CInputPopup(SP popup_) : popup(popup_) { listeners.commit = popup_->events.commit.registerListener([this](std::any d) { onCommit(); }); diff --git a/src/managers/input/InputMethodRelay.cpp b/src/managers/input/InputMethodRelay.cpp index 88439924..58cff043 100644 --- a/src/managers/input/InputMethodRelay.cpp +++ b/src/managers/input/InputMethodRelay.cpp @@ -5,6 +5,7 @@ #include "../../protocols/TextInputV1.hpp" #include "../../protocols/InputMethodV2.hpp" #include "../../protocols/core/Compositor.hpp" +#include "../../managers/HookSystemManager.hpp" CInputMethodRelay::CInputMethodRelay() { static auto P = diff --git a/src/managers/input/Swipe.cpp b/src/managers/input/Swipe.cpp index 3e03c4c7..b5282e3c 100644 --- a/src/managers/input/Swipe.cpp +++ b/src/managers/input/Swipe.cpp @@ -1,6 +1,9 @@ #include "InputManager.hpp" #include "../../Compositor.hpp" +#include "../../desktop/LayerSurface.hpp" #include "../../config/ConfigValue.hpp" +#include "../../managers/HookSystemManager.hpp" +#include "../../render/Renderer.hpp" void CInputManager::onSwipeBegin(IPointer::SSwipeBeginEvent e) { static auto PSWIPE = CConfigValue("gestures:workspace_swipe"); diff --git a/src/managers/input/Tablets.cpp b/src/managers/input/Tablets.cpp index d7ebfe87..f61d8184 100644 --- a/src/managers/input/Tablets.cpp +++ b/src/managers/input/Tablets.cpp @@ -1,5 +1,5 @@ #include "InputManager.hpp" -#include "../../Compositor.hpp" +#include "../../desktop/Window.hpp" #include "../../protocols/Tablet.hpp" #include "../../devices/Tablet.hpp" #include "../../managers/PointerManager.hpp" diff --git a/src/managers/input/TextInput.hpp b/src/managers/input/TextInput.hpp index 3cf07006..c0b590ac 100644 --- a/src/managers/input/TextInput.hpp +++ b/src/managers/input/TextInput.hpp @@ -1,8 +1,8 @@ #pragma once -#include "../../macros.hpp" #include "../../helpers/math/Math.hpp" #include "../../helpers/signal/Signal.hpp" +#include "../../helpers/memory/Memory.hpp" #include struct wl_client; diff --git a/src/managers/input/Touch.cpp b/src/managers/input/Touch.cpp index 7212ba61..990fbc41 100644 --- a/src/managers/input/Touch.cpp +++ b/src/managers/input/Touch.cpp @@ -1,9 +1,11 @@ #include "InputManager.hpp" #include "../../Compositor.hpp" +#include "../../desktop/LayerSurface.hpp" #include "../../config/ConfigValue.hpp" #include "../../devices/ITouch.hpp" #include "../SeatManager.hpp" #include "managers/AnimationManager.hpp" +#include "../HookSystemManager.hpp" void CInputManager::onTouchDown(ITouch::SDownEvent e) { m_bLastInputTouch = true; diff --git a/src/plugins/HookSystem.cpp b/src/plugins/HookSystem.cpp index 3baca5b1..c19f6f46 100644 --- a/src/plugins/HookSystem.cpp +++ b/src/plugins/HookSystem.cpp @@ -2,7 +2,7 @@ #include "../debug/Log.hpp" #include "../helpers/varlist/VarList.hpp" #include "../managers/TokenManager.hpp" -#include "../Compositor.hpp" +#include "../helpers/MiscFunctions.hpp" #define register #include @@ -383,4 +383,4 @@ uint64_t CHookSystem::getAddressForTrampo() { Debug::log(LOG, "getAddressForTrampo: Returning addr 0x{:x} for page at 0x{:x}", ADDRFORCONSUMER, page->addr); return ADDRFORCONSUMER; -} \ No newline at end of file +} diff --git a/src/plugins/PluginAPI.cpp b/src/plugins/PluginAPI.cpp index 5e1d9e58..b6bbc460 100644 --- a/src/plugins/PluginAPI.cpp +++ b/src/plugins/PluginAPI.cpp @@ -1,6 +1,11 @@ #include "PluginAPI.hpp" #include "../Compositor.hpp" #include "../debug/HyprCtl.hpp" +#include "../plugins/PluginSystem.hpp" +#include "../managers/HookSystemManager.hpp" +#include "../managers/LayoutManager.hpp" +#include "../config/ConfigManager.hpp" +#include "../debug/HyprNotificationOverlay.hpp" #include #include diff --git a/src/plugins/PluginSystem.cpp b/src/plugins/PluginSystem.cpp index 52a3bace..ce7dd7c7 100644 --- a/src/plugins/PluginSystem.cpp +++ b/src/plugins/PluginSystem.cpp @@ -2,7 +2,9 @@ #include #include -#include "../Compositor.hpp" +#include "../config/ConfigManager.hpp" +#include "../managers/LayoutManager.hpp" +#include "../managers/HookSystemManager.hpp" CPluginSystem::CPluginSystem() { g_pFunctionHookSystem = std::make_unique(); diff --git a/src/protocols/CTMControl.cpp b/src/protocols/CTMControl.cpp index fd7cdcd6..91e05ac4 100644 --- a/src/protocols/CTMControl.cpp +++ b/src/protocols/CTMControl.cpp @@ -4,6 +4,7 @@ #include "core/Output.hpp" #include "../config/ConfigValue.hpp" #include "managers/AnimationManager.hpp" +#include "../helpers/Monitor.hpp" CHyprlandCTMControlResource::CHyprlandCTMControlResource(SP resource_) : resource(resource_) { if (!good()) diff --git a/src/protocols/DRMLease.cpp b/src/protocols/DRMLease.cpp index be5a6985..4ab46a46 100644 --- a/src/protocols/DRMLease.cpp +++ b/src/protocols/DRMLease.cpp @@ -1,5 +1,6 @@ #include "DRMLease.hpp" #include "../Compositor.hpp" +#include "../helpers/Monitor.hpp" #include "managers/eventLoop/EventLoopManager.hpp" #include #include diff --git a/src/protocols/ForeignToplevel.cpp b/src/protocols/ForeignToplevel.cpp index 38bb5e69..f6513a1d 100644 --- a/src/protocols/ForeignToplevel.cpp +++ b/src/protocols/ForeignToplevel.cpp @@ -1,5 +1,6 @@ #include "ForeignToplevel.hpp" #include "../Compositor.hpp" +#include "../managers/HookSystemManager.hpp" CForeignToplevelHandle::CForeignToplevelHandle(SP resource_, PHLWINDOW pWindow_) : resource(resource_), pWindow(pWindow_) { if (!resource_->resource()) diff --git a/src/protocols/ForeignToplevelWlr.cpp b/src/protocols/ForeignToplevelWlr.cpp index 6bbd377c..45ef3f93 100644 --- a/src/protocols/ForeignToplevelWlr.cpp +++ b/src/protocols/ForeignToplevelWlr.cpp @@ -3,6 +3,7 @@ #include "../Compositor.hpp" #include "protocols/core/Output.hpp" #include "render/Renderer.hpp" +#include "../managers/HookSystemManager.hpp" CForeignToplevelHandleWlr::CForeignToplevelHandleWlr(SP resource_, PHLWINDOW pWindow_) : resource(resource_), pWindow(pWindow_) { if (!resource_->resource()) diff --git a/src/protocols/GammaControl.cpp b/src/protocols/GammaControl.cpp index 14c6596f..b0da29a2 100644 --- a/src/protocols/GammaControl.cpp +++ b/src/protocols/GammaControl.cpp @@ -2,8 +2,8 @@ #include #include #include "../helpers/Monitor.hpp" -#include "../Compositor.hpp" #include "../protocols/core/Output.hpp" +#include "../render/Renderer.hpp" CGammaControl::CGammaControl(SP resource_, wl_resource* output) : resource(resource_) { if (!resource_->resource()) diff --git a/src/protocols/GlobalShortcuts.cpp b/src/protocols/GlobalShortcuts.cpp index b02126ef..ca67f063 100644 --- a/src/protocols/GlobalShortcuts.cpp +++ b/src/protocols/GlobalShortcuts.cpp @@ -1,5 +1,4 @@ #include "GlobalShortcuts.hpp" -#include "../Compositor.hpp" CShortcutClient::CShortcutClient(SP resource_) : resource(resource_) { if (!good()) diff --git a/src/protocols/LayerShell.cpp b/src/protocols/LayerShell.cpp index 5ceae5f2..0777149f 100644 --- a/src/protocols/LayerShell.cpp +++ b/src/protocols/LayerShell.cpp @@ -1,8 +1,10 @@ #include "LayerShell.hpp" #include "../Compositor.hpp" +#include "../desktop/LayerSurface.hpp" #include "XDGShell.hpp" #include "core/Compositor.hpp" #include "core/Output.hpp" +#include "../helpers/Monitor.hpp" void CLayerShellResource::SState::reset() { anchor = 0; diff --git a/src/protocols/MesaDRM.cpp b/src/protocols/MesaDRM.cpp index b4efd2c8..41536988 100644 --- a/src/protocols/MesaDRM.cpp +++ b/src/protocols/MesaDRM.cpp @@ -3,6 +3,7 @@ #include #include "../Compositor.hpp" #include "types/WLBuffer.hpp" +#include "../render/OpenGL.hpp" CMesaDRMBufferResource::CMesaDRMBufferResource(uint32_t id, wl_client* client, Aquamarine::SDMABUFAttrs attrs_) { LOGM(LOG, "Creating a Mesa dmabuf, with id {}: size {}, fmt {}, planes {}", id, attrs_.size, attrs_.format, attrs_.planes); diff --git a/src/protocols/OutputManagement.cpp b/src/protocols/OutputManagement.cpp index 4f7d48c4..4a976021 100644 --- a/src/protocols/OutputManagement.cpp +++ b/src/protocols/OutputManagement.cpp @@ -1,6 +1,9 @@ #include "OutputManagement.hpp" #include #include "../Compositor.hpp" +#include "../managers/input/InputManager.hpp" +#include "../managers/HookSystemManager.hpp" +#include "../config/ConfigManager.hpp" using namespace Aquamarine; diff --git a/src/protocols/OutputPower.cpp b/src/protocols/OutputPower.cpp index 257155e4..dd3e8e1a 100644 --- a/src/protocols/OutputPower.cpp +++ b/src/protocols/OutputPower.cpp @@ -1,6 +1,6 @@ #include "OutputPower.hpp" -#include "../Compositor.hpp" #include "core/Output.hpp" +#include "../helpers/Monitor.hpp" COutputPower::COutputPower(SP resource_, PHLMONITOR pMonitor_) : resource(resource_), pMonitor(pMonitor_) { if (!resource->resource()) diff --git a/src/protocols/PointerConstraints.cpp b/src/protocols/PointerConstraints.cpp index 0a787414..e12fa75f 100644 --- a/src/protocols/PointerConstraints.cpp +++ b/src/protocols/PointerConstraints.cpp @@ -4,6 +4,9 @@ #include "../config/ConfigValue.hpp" #include "../managers/SeatManager.hpp" #include "core/Compositor.hpp" +#include "../managers/input/InputManager.hpp" +#include "../render/Renderer.hpp" +#include "../helpers/Monitor.hpp" CPointerConstraint::CPointerConstraint(SP resource_, SP surf, wl_resource* region_, zwpPointerConstraintsV1Lifetime lifetime_) : resourceL(resource_), locked(true), lifetime(lifetime_) { diff --git a/src/protocols/PointerGestures.cpp b/src/protocols/PointerGestures.cpp index 4eb74102..5dfb9d51 100644 --- a/src/protocols/PointerGestures.cpp +++ b/src/protocols/PointerGestures.cpp @@ -1,5 +1,4 @@ #include "PointerGestures.hpp" -#include "../Compositor.hpp" #include "../managers/SeatManager.hpp" #include "core/Seat.hpp" #include "core/Compositor.hpp" diff --git a/src/protocols/RelativePointer.cpp b/src/protocols/RelativePointer.cpp index 16248c02..b7cf75c6 100644 --- a/src/protocols/RelativePointer.cpp +++ b/src/protocols/RelativePointer.cpp @@ -1,5 +1,4 @@ #include "RelativePointer.hpp" -#include "../Compositor.hpp" #include "../managers/SeatManager.hpp" #include "core/Seat.hpp" #include @@ -71,4 +70,4 @@ void CRelativePointerProtocol::sendRelativeMotion(uint64_t time, const Vector2D& rp->sendRelativeMotion(time, delta, deltaUnaccel); } -} \ No newline at end of file +} diff --git a/src/protocols/Screencopy.cpp b/src/protocols/Screencopy.cpp index 898a1d6b..da0a9412 100644 --- a/src/protocols/Screencopy.cpp +++ b/src/protocols/Screencopy.cpp @@ -2,6 +2,10 @@ #include "../Compositor.hpp" #include "../managers/eventLoop/EventLoopManager.hpp" #include "../managers/PointerManager.hpp" +#include "../managers/EventManager.hpp" +#include "../render/Renderer.hpp" +#include "../render/OpenGL.hpp" +#include "../helpers/Monitor.hpp" #include "core/Output.hpp" #include "types/WLBuffer.hpp" #include "types/Buffer.hpp" diff --git a/src/protocols/SessionLock.cpp b/src/protocols/SessionLock.cpp index 642a5b89..c3f19e53 100644 --- a/src/protocols/SessionLock.cpp +++ b/src/protocols/SessionLock.cpp @@ -4,6 +4,7 @@ #include "FractionalScale.hpp" #include "core/Compositor.hpp" #include "core/Output.hpp" +#include "../helpers/Monitor.hpp" CSessionLockSurface::CSessionLockSurface(SP resource_, SP surface_, PHLMONITOR pMonitor_, WP owner_) : resource(resource_), sessionLock(owner_), pSurface(surface_), pMonitor(pMonitor_) { @@ -208,4 +209,4 @@ void CSessionLockProtocol::onGetLockSurface(CExtSessionLockV1* lock, uint32_t id bool CSessionLockProtocol::isLocked() { return locked; -} \ No newline at end of file +} diff --git a/src/protocols/SinglePixel.cpp b/src/protocols/SinglePixel.cpp index 41771ce2..91154671 100644 --- a/src/protocols/SinglePixel.cpp +++ b/src/protocols/SinglePixel.cpp @@ -1,4 +1,5 @@ #include "SinglePixel.hpp" +#include "../desktop/LayerSurface.hpp" #include #include "render/Renderer.hpp" diff --git a/src/protocols/Tablet.cpp b/src/protocols/Tablet.cpp index b4ab6ea0..2fdd8731 100644 --- a/src/protocols/Tablet.cpp +++ b/src/protocols/Tablet.cpp @@ -2,6 +2,7 @@ #include "../devices/Tablet.hpp" #include "../Compositor.hpp" #include "../managers/SeatManager.hpp" +#include "../managers/input/InputManager.hpp" #include "core/Seat.hpp" #include "core/Compositor.hpp" #include diff --git a/src/protocols/TearingControl.cpp b/src/protocols/TearingControl.cpp index 66a4efd2..eb1a53cb 100644 --- a/src/protocols/TearingControl.cpp +++ b/src/protocols/TearingControl.cpp @@ -3,6 +3,7 @@ #include "../desktop/Window.hpp" #include "../Compositor.hpp" #include "core/Compositor.hpp" +#include "../managers/HookSystemManager.hpp" CTearingControlProtocol::CTearingControlProtocol(const wl_interface* iface, const int& ver, const std::string& name) : IWaylandProtocol(iface, ver, name) { static auto P = diff --git a/src/protocols/TextInputV1.cpp b/src/protocols/TextInputV1.cpp index 6395e158..b8eb5835 100644 --- a/src/protocols/TextInputV1.cpp +++ b/src/protocols/TextInputV1.cpp @@ -1,6 +1,5 @@ #include "TextInputV1.hpp" -#include "../Compositor.hpp" #include "core/Compositor.hpp" CTextInputV1::~CTextInputV1() { diff --git a/src/protocols/ToplevelExport.cpp b/src/protocols/ToplevelExport.cpp index 73e5cad9..8e34cf4b 100644 --- a/src/protocols/ToplevelExport.cpp +++ b/src/protocols/ToplevelExport.cpp @@ -6,6 +6,9 @@ #include "types/WLBuffer.hpp" #include "types/Buffer.hpp" #include "../helpers/Format.hpp" +#include "../managers/EventManager.hpp" +#include "../managers/input/InputManager.hpp" +#include "../render/Renderer.hpp" #include diff --git a/src/protocols/XDGOutput.cpp b/src/protocols/XDGOutput.cpp index deb87829..fadc48a1 100644 --- a/src/protocols/XDGOutput.cpp +++ b/src/protocols/XDGOutput.cpp @@ -1,7 +1,7 @@ #include "XDGOutput.hpp" -#include "../Compositor.hpp" #include "../config/ConfigValue.hpp" #include "../xwayland/XWayland.hpp" +#include "../managers/HookSystemManager.hpp" #include "core/Output.hpp" #define OUTPUT_MANAGER_VERSION 3 @@ -119,4 +119,4 @@ void CXDGOutput::sendDetails() { if (resource->version() < OUTPUT_DONE_DEPRECATED_SINCE_VERSION) resource->sendDone(); -} \ No newline at end of file +} diff --git a/src/protocols/XDGShell.cpp b/src/protocols/XDGShell.cpp index 6b7cb3c1..aabb225a 100644 --- a/src/protocols/XDGShell.cpp +++ b/src/protocols/XDGShell.cpp @@ -3,6 +3,7 @@ #include #include "../Compositor.hpp" #include "../managers/SeatManager.hpp" +#include "../helpers/Monitor.hpp" #include "core/Seat.hpp" #include "core/Compositor.hpp" #include "protocols/core/Output.hpp" diff --git a/src/protocols/core/DataDevice.cpp b/src/protocols/core/DataDevice.cpp index 722eb9fd..fd3cd1fa 100644 --- a/src/protocols/core/DataDevice.cpp +++ b/src/protocols/core/DataDevice.cpp @@ -9,6 +9,10 @@ #include "Compositor.hpp" #include "../../xwayland/XWayland.hpp" #include "../../xwayland/Server.hpp" +#include "../../managers/input/InputManager.hpp" +#include "../../managers/HookSystemManager.hpp" +#include "../../helpers/Monitor.hpp" +#include "../../render/Renderer.hpp" CWLDataOfferResource::CWLDataOfferResource(SP resource_, SP source_) : source(source_), resource(resource_) { if (!good()) diff --git a/src/protocols/core/Shm.cpp b/src/protocols/core/Shm.cpp index fddd4e9a..6365c5d6 100644 --- a/src/protocols/core/Shm.cpp +++ b/src/protocols/core/Shm.cpp @@ -5,8 +5,8 @@ #include #include "../../render/Texture.hpp" #include "../types/WLBuffer.hpp" -#include "../../Compositor.hpp" #include "../../helpers/Format.hpp" +#include "../../render/Renderer.hpp" CWLSHMBuffer::CWLSHMBuffer(SP pool_, uint32_t id, int32_t offset_, const Vector2D& size_, int32_t stride_, uint32_t fmt_) { if (!pool_->pool->data) diff --git a/src/protocols/types/DMABuffer.cpp b/src/protocols/types/DMABuffer.cpp index ae684424..9f31f6a2 100644 --- a/src/protocols/types/DMABuffer.cpp +++ b/src/protocols/types/DMABuffer.cpp @@ -1,5 +1,6 @@ #include "DMABuffer.hpp" #include "WLBuffer.hpp" +#include "../../desktop/LayerSurface.hpp" #include "../../render/Renderer.hpp" #include "../../helpers/Format.hpp" diff --git a/src/protocols/types/WLBuffer.cpp b/src/protocols/types/WLBuffer.cpp index eb7d1fde..a9e6400a 100644 --- a/src/protocols/types/WLBuffer.cpp +++ b/src/protocols/types/WLBuffer.cpp @@ -3,7 +3,6 @@ #include "../core/Compositor.hpp" #include "../DRMSyncobj.hpp" #include "../../helpers/sync/SyncTimeline.hpp" -#include "../../Compositor.hpp" #include CWLBufferResource::CWLBufferResource(SP resource_) : resource(resource_) { diff --git a/src/render/OpenGL.cpp b/src/render/OpenGL.cpp index b68448ae..c5bb3620 100644 --- a/src/render/OpenGL.cpp +++ b/src/render/OpenGL.cpp @@ -2,12 +2,15 @@ #include #include "Shaders.hpp" #include "OpenGL.hpp" +#include "Renderer.hpp" #include "../Compositor.hpp" #include "../helpers/MiscFunctions.hpp" #include "../config/ConfigValue.hpp" #include "../desktop/LayerSurface.hpp" #include "../protocols/LayerShell.hpp" #include "../protocols/core/Compositor.hpp" +#include "../managers/HookSystemManager.hpp" +#include "../managers/input/InputManager.hpp" #include "pass/TexPassElement.hpp" #include "pass/RectPassElement.hpp" #include "pass/PreBlurElement.hpp" diff --git a/src/render/OpenGL.hpp b/src/render/OpenGL.hpp index 2b600a03..8098485e 100644 --- a/src/render/OpenGL.hpp +++ b/src/render/OpenGL.hpp @@ -17,7 +17,6 @@ #include "Shader.hpp" #include "Texture.hpp" #include "Framebuffer.hpp" -#include "Transformer.hpp" #include "Renderbuffer.hpp" #include "pass/Pass.hpp" diff --git a/src/render/Renderbuffer.cpp b/src/render/Renderbuffer.cpp index c4425ce9..887f31a9 100644 --- a/src/render/Renderbuffer.cpp +++ b/src/render/Renderbuffer.cpp @@ -1,4 +1,5 @@ #include "Renderbuffer.hpp" +#include "Renderer.hpp" #include "OpenGL.hpp" #include "../Compositor.hpp" #include "../protocols/types/Buffer.hpp" @@ -76,4 +77,4 @@ void CRenderbuffer::unbind() { CFramebuffer* CRenderbuffer::getFB() { return &m_sFramebuffer; -} \ No newline at end of file +} diff --git a/src/render/Renderer.cpp b/src/render/Renderer.cpp index 6c77b27a..fddb9a9a 100644 --- a/src/render/Renderer.cpp +++ b/src/render/Renderer.cpp @@ -8,6 +8,10 @@ #include "../config/ConfigValue.hpp" #include "../managers/CursorManager.hpp" #include "../managers/PointerManager.hpp" +#include "../managers/input/InputManager.hpp" +#include "../managers/HookSystemManager.hpp" +#include "../managers/AnimationManager.hpp" +#include "../managers/LayoutManager.hpp" #include "../desktop/Window.hpp" #include "../desktop/LayerSurface.hpp" #include "../protocols/SessionLock.hpp" @@ -19,6 +23,9 @@ #include "../protocols/DRMSyncobj.hpp" #include "../protocols/LinuxDMABUF.hpp" #include "../helpers/sync/SyncTimeline.hpp" +#include "../hyprerror/HyprError.hpp" +#include "../debug/HyprDebugOverlay.hpp" +#include "../debug/HyprNotificationOverlay.hpp" #include "pass/TexPassElement.hpp" #include "pass/ClearPassElement.hpp" #include "pass/RectPassElement.hpp" diff --git a/src/render/Renderer.hpp b/src/render/Renderer.hpp index 8b4988c3..6ba7a654 100644 --- a/src/render/Renderer.hpp +++ b/src/render/Renderer.hpp @@ -3,6 +3,7 @@ #include "../defines.hpp" #include #include "../helpers/Monitor.hpp" +#include "../desktop/LayerSurface.hpp" #include "OpenGL.hpp" #include "Renderbuffer.hpp" #include "../helpers/Timer.hpp" diff --git a/src/render/decorations/CHyprBorderDecoration.cpp b/src/render/decorations/CHyprBorderDecoration.cpp index 7261431f..6fb0ff88 100644 --- a/src/render/decorations/CHyprBorderDecoration.cpp +++ b/src/render/decorations/CHyprBorderDecoration.cpp @@ -3,6 +3,8 @@ #include "../../config/ConfigValue.hpp" #include "../../managers/eventLoop/EventLoopManager.hpp" #include "../pass/BorderPassElement.hpp" +#include "../Renderer.hpp" +#include "../../managers/HookSystemManager.hpp" CHyprBorderDecoration::CHyprBorderDecoration(PHLWINDOW pWindow) : IHyprWindowDecoration(pWindow), m_pWindow(pWindow) { ; diff --git a/src/render/decorations/CHyprDropShadowDecoration.cpp b/src/render/decorations/CHyprDropShadowDecoration.cpp index ddd5198d..022e123e 100644 --- a/src/render/decorations/CHyprDropShadowDecoration.cpp +++ b/src/render/decorations/CHyprDropShadowDecoration.cpp @@ -3,6 +3,7 @@ #include "../../Compositor.hpp" #include "../../config/ConfigValue.hpp" #include "../pass/ShadowPassElement.hpp" +#include "../Renderer.hpp" CHyprDropShadowDecoration::CHyprDropShadowDecoration(PHLWINDOW pWindow) : IHyprWindowDecoration(pWindow), m_pWindow(pWindow) { ; diff --git a/src/render/decorations/CHyprGroupBarDecoration.cpp b/src/render/decorations/CHyprGroupBarDecoration.cpp index 970273d7..4a411b6c 100644 --- a/src/render/decorations/CHyprGroupBarDecoration.cpp +++ b/src/render/decorations/CHyprGroupBarDecoration.cpp @@ -6,6 +6,8 @@ #include #include "../pass/TexPassElement.hpp" #include "../pass/RectPassElement.hpp" +#include "../Renderer.hpp" +#include "../../managers/input/InputManager.hpp" // shared things to conserve VRAM static SP m_tGradientActive = makeShared(); diff --git a/src/render/decorations/DecorationPositioner.cpp b/src/render/decorations/DecorationPositioner.cpp index abfa19ec..c2d34fb6 100644 --- a/src/render/decorations/DecorationPositioner.cpp +++ b/src/render/decorations/DecorationPositioner.cpp @@ -1,5 +1,7 @@ #include "DecorationPositioner.hpp" -#include "../../Compositor.hpp" +#include "../../desktop/Window.hpp" +#include "../../managers/HookSystemManager.hpp" +#include "../../managers/LayoutManager.hpp" CDecorationPositioner::CDecorationPositioner() { static auto P = g_pHookSystem->hookDynamic("closeWindow", [this](void* call, SCallbackInfo& info, std::any data) { diff --git a/src/render/pass/Pass.cpp b/src/render/pass/Pass.cpp index b72248c2..5b133b7d 100644 --- a/src/render/pass/Pass.cpp +++ b/src/render/pass/Pass.cpp @@ -6,6 +6,7 @@ #include "../../desktop/WLSurface.hpp" #include "../../managers/SeatManager.hpp" #include "../../managers/eventLoop/EventLoopManager.hpp" +#include "../../render/Renderer.hpp" #include "../../Compositor.hpp" bool CRenderPass::empty() const { diff --git a/src/render/pass/SurfacePassElement.cpp b/src/render/pass/SurfacePassElement.cpp index 71aa26be..d720081f 100644 --- a/src/render/pass/SurfacePassElement.cpp +++ b/src/render/pass/SurfacePassElement.cpp @@ -1,6 +1,7 @@ #include "SurfacePassElement.hpp" #include "../OpenGL.hpp" #include "../../desktop/WLSurface.hpp" +#include "../../desktop/Window.hpp" #include "../../protocols/core/Compositor.hpp" #include "../../protocols/DRMSyncobj.hpp" #include "../../managers/input/InputManager.hpp" diff --git a/src/xwayland/XSurface.cpp b/src/xwayland/XSurface.cpp index 6048269a..b5ee75f6 100644 --- a/src/xwayland/XSurface.cpp +++ b/src/xwayland/XSurface.cpp @@ -6,7 +6,6 @@ #ifndef NO_XWAYLAND #include -#include "../Compositor.hpp" CXWaylandSurface::CXWaylandSurface(uint32_t xID_, CBox geometry_, bool OR) : xID(xID_), geometry(geometry_), overrideRedirect(OR) { xcb_res_query_client_ids_cookie_t client_id_cookie = {0}; diff --git a/src/xwayland/XWM.hpp b/src/xwayland/XWM.hpp index 38fdab94..bc5aa47b 100644 --- a/src/xwayland/XWM.hpp +++ b/src/xwayland/XWM.hpp @@ -1,6 +1,5 @@ #pragma once -#include "../macros.hpp" #include "XDataSource.hpp" #include "Dnd.hpp" #include "../helpers/memory/Memory.hpp" From b7a3c4526990d6601ff2cac748ff860cda6bc16d Mon Sep 17 00:00:00 2001 From: vaxerski Date: Fri, 17 Jan 2025 18:21:34 +0100 Subject: [PATCH 0858/2181] core: add LIKELY and UNLIKELY macros helps the compiler optimize --- src/devices/VirtualPointer.cpp | 2 +- src/macros.hpp | 3 ++ src/protocols/AlphaModifier.cpp | 4 +- src/protocols/CTMControl.cpp | 8 +-- src/protocols/ColorManagement.cpp | 32 ++++++------ src/protocols/CursorShape.cpp | 2 +- src/protocols/DRMLease.cpp | 16 +++--- src/protocols/DRMSyncobj.cpp | 18 +++---- src/protocols/DataDeviceWlr.cpp | 16 +++--- src/protocols/FocusGrab.cpp | 14 +++--- src/protocols/ForeignToplevel.cpp | 20 ++++---- src/protocols/ForeignToplevelWlr.cpp | 70 +++++++++++++-------------- src/protocols/FractionalScale.cpp | 2 +- src/protocols/FrogColorManagement.cpp | 10 ++-- src/protocols/GammaControl.cpp | 20 ++++---- src/protocols/GlobalShortcuts.cpp | 8 +-- src/protocols/HyprlandSurface.cpp | 8 +-- src/protocols/IdleNotify.cpp | 4 +- src/protocols/InputMethodV2.cpp | 16 +++--- src/protocols/LayerShell.cpp | 8 +-- src/protocols/LinuxDMABUF.cpp | 26 +++++----- src/protocols/MesaDRM.cpp | 6 +-- src/protocols/OutputManagement.cpp | 22 ++++----- src/protocols/OutputPower.cpp | 6 +-- src/protocols/PointerConstraints.cpp | 12 ++--- src/protocols/PointerGestures.cpp | 12 ++--- src/protocols/PresentationTime.cpp | 8 +-- src/protocols/PrimarySelection.cpp | 16 +++--- src/protocols/RelativePointer.cpp | 4 +- src/protocols/Screencopy.cpp | 17 +++---- src/protocols/SecurityContext.cpp | 26 +++++----- src/protocols/ServerDecorationKDE.cpp | 4 +- src/protocols/SessionLock.cpp | 8 +-- src/protocols/ShortcutsInhibit.cpp | 6 +-- src/protocols/SinglePixel.cpp | 8 +-- src/protocols/Tablet.cpp | 28 +++++------ src/protocols/TearingControl.cpp | 4 +- src/protocols/TextInputV1.cpp | 6 +-- src/protocols/TextInputV3.cpp | 4 +- src/protocols/ToplevelExport.cpp | 29 ++++++----- src/protocols/Viewporter.cpp | 16 +++--- src/protocols/VirtualKeyboard.cpp | 14 +++--- src/protocols/VirtualPointer.cpp | 10 ++-- src/protocols/WaylandProtocol.cpp | 2 +- src/protocols/XDGActivation.cpp | 12 ++--- src/protocols/XDGDecoration.cpp | 6 +-- src/protocols/XDGDialog.cpp | 14 +++--- src/protocols/XDGOutput.cpp | 10 ++-- src/protocols/XDGShell.cpp | 34 ++++++------- src/protocols/XWaylandShell.cpp | 8 +-- src/protocols/core/Compositor.cpp | 34 ++++++------- src/protocols/core/DataDevice.cpp | 18 +++---- src/protocols/core/Output.cpp | 10 ++-- src/protocols/core/Seat.cpp | 16 +++--- src/protocols/core/Shm.cpp | 32 ++++++------ src/protocols/core/Subcompositor.cpp | 14 +++--- src/protocols/types/DMABuffer.cpp | 6 +-- src/protocols/types/WLBuffer.cpp | 2 +- 58 files changed, 395 insertions(+), 396 deletions(-) diff --git a/src/devices/VirtualPointer.cpp b/src/devices/VirtualPointer.cpp index 514c8c32..7cfb0631 100644 --- a/src/devices/VirtualPointer.cpp +++ b/src/devices/VirtualPointer.cpp @@ -11,7 +11,7 @@ SP CVirtualPointer::create(SP resour } CVirtualPointer::CVirtualPointer(SP resource) : pointer(resource) { - if (!resource->good()) + if UNLIKELY (!resource->good()) return; listeners.destroy = pointer->events.destroy.registerListener([this](std::any d) { diff --git a/src/macros.hpp b/src/macros.hpp index 08c17952..0a3be8bc 100644 --- a/src/macros.hpp +++ b/src/macros.hpp @@ -114,3 +114,6 @@ namespace Aquamarine { \ class name; \ } + +#define UNLIKELY(expr) (expr) [[unlikely]] +#define LIKELY(expr) (expr) [[likely]] diff --git a/src/protocols/AlphaModifier.cpp b/src/protocols/AlphaModifier.cpp index d695b58f..dc32bb8c 100644 --- a/src/protocols/AlphaModifier.cpp +++ b/src/protocols/AlphaModifier.cpp @@ -15,7 +15,7 @@ bool CAlphaModifier::good() { void CAlphaModifier::setResource(SP resource) { m_pResource = std::move(resource); - if (!m_pResource->resource()) + if UNLIKELY (!m_pResource->resource()) return; m_pResource->setDestroy([this](CWpAlphaModifierSurfaceV1* resource) { destroy(); }); @@ -98,7 +98,7 @@ void CAlphaModifierProtocol::getSurface(CWpAlphaModifierV1* manager, uint32_t id .first->second.get(); } - if (!alphaModifier->good()) { + if UNLIKELY (!alphaModifier->good()) { manager->noMemory(); m_mAlphaModifiers.erase(surface); } diff --git a/src/protocols/CTMControl.cpp b/src/protocols/CTMControl.cpp index 91e05ac4..91f4501f 100644 --- a/src/protocols/CTMControl.cpp +++ b/src/protocols/CTMControl.cpp @@ -7,7 +7,7 @@ #include "../helpers/Monitor.hpp" CHyprlandCTMControlResource::CHyprlandCTMControlResource(SP resource_) : resource(resource_) { - if (!good()) + if UNLIKELY (!good()) return; resource->setDestroy([this](CHyprlandCtmControlManagerV1* pMgr) { PROTO::ctm->destroyResource(this); }); @@ -17,12 +17,12 @@ CHyprlandCTMControlResource::CHyprlandCTMControlResource(SPmonitor.lock(); - if (!PMONITOR) + if UNLIKELY (!PMONITOR) return; // ?!?! const std::array MAT = {wl_fixed_to_double(mat0), wl_fixed_to_double(mat1), wl_fixed_to_double(mat2), wl_fixed_to_double(mat3), wl_fixed_to_double(mat4), @@ -72,7 +72,7 @@ void CHyprlandCTMControlProtocol::bindManager(wl_client* client, void* data, uin const auto RESOURCE = m_vManagers.emplace_back(makeShared(makeShared(client, ver, id))); - if (!RESOURCE->good()) { + if UNLIKELY (!RESOURCE->good()) { wl_client_post_no_memory(client); m_vManagers.pop_back(); return; diff --git a/src/protocols/ColorManagement.cpp b/src/protocols/ColorManagement.cpp index a76e13c0..c2814361 100644 --- a/src/protocols/ColorManagement.cpp +++ b/src/protocols/ColorManagement.cpp @@ -2,7 +2,7 @@ #include "Compositor.hpp" CColorManager::CColorManager(SP resource_) : resource(resource_) { - if (!good()) + if UNLIKELY (!good()) return; resource->sendSupportedFeature(XX_COLOR_MANAGER_V4_FEATURE_PARAMETRIC); @@ -38,7 +38,7 @@ CColorManager::CColorManager(SP resource_) : resource(resourc const auto RESOURCE = PROTO::colorManagement->m_vOutputs.emplace_back(makeShared(makeShared(r->client(), r->version(), id))); - if (!RESOURCE->good()) { + if UNLIKELY (!RESOURCE->good()) { r->noMemory(); PROTO::colorManagement->m_vOutputs.pop_back(); return; @@ -63,7 +63,7 @@ CColorManager::CColorManager(SP resource_) : resource(resourc const auto RESOURCE = PROTO::colorManagement->m_vSurfaces.emplace_back(makeShared(makeShared(r->client(), r->version(), id), SURF)); - if (!RESOURCE->good()) { + if UNLIKELY (!RESOURCE->good()) { r->noMemory(); PROTO::colorManagement->m_vSurfaces.pop_back(); return; @@ -86,7 +86,7 @@ CColorManager::CColorManager(SP resource_) : resource(resourc const auto RESOURCE = PROTO::colorManagement->m_vFeedbackSurfaces.emplace_back( makeShared(makeShared(r->client(), r->version(), id), SURF)); - if (!RESOURCE->good()) { + if UNLIKELY (!RESOURCE->good()) { r->noMemory(); PROTO::colorManagement->m_vFeedbackSurfaces.pop_back(); return; @@ -104,7 +104,7 @@ CColorManager::CColorManager(SP resource_) : resource(resourc const auto RESOURCE = PROTO::colorManagement->m_vParametricCreators.emplace_back( makeShared(makeShared(r->client(), r->version(), id))); - if (!RESOURCE->good()) { + if UNLIKELY (!RESOURCE->good()) { r->noMemory(); PROTO::colorManagement->m_vParametricCreators.pop_back(); return; @@ -121,7 +121,7 @@ bool CColorManager::good() { } CColorManagementOutput::CColorManagementOutput(SP resource_) : resource(resource_) { - if (!good()) + if UNLIKELY (!good()) return; pClient = resource->client(); @@ -137,7 +137,7 @@ CColorManagementOutput::CColorManagementOutput(SP re const auto RESOURCE = PROTO::colorManagement->m_vImageDescriptions.emplace_back( makeShared(makeShared(r->client(), r->version(), id))); - if (!RESOURCE->good()) { + if UNLIKELY (!RESOURCE->good()) { r->noMemory(); PROTO::colorManagement->m_vImageDescriptions.pop_back(); return; @@ -160,7 +160,7 @@ CColorManagementSurface::CColorManagementSurface(SP surface_ } CColorManagementSurface::CColorManagementSurface(SP resource_, SP surface_) : surface(surface_), resource(resource_) { - if (!good()) + if UNLIKELY (!good()) return; pClient = resource->client(); @@ -242,7 +242,7 @@ bool CColorManagementSurface::needsHdrMetadataUpdate() { CColorManagementFeedbackSurface::CColorManagementFeedbackSurface(SP resource_, SP surface_) : surface(surface_), resource(resource_) { - if (!good()) + if UNLIKELY (!good()) return; pClient = resource->client(); @@ -269,7 +269,7 @@ CColorManagementFeedbackSurface::CColorManagementFeedbackSurface(SPm_vImageDescriptions.emplace_back( makeShared(makeShared(r->client(), r->version(), id), true)); - if (!RESOURCE->good()) { + if UNLIKELY (!RESOURCE->good()) { r->noMemory(); PROTO::colorManagement->m_vImageDescriptions.pop_back(); return; @@ -293,7 +293,7 @@ wl_client* CColorManagementFeedbackSurface::client() { } CColorManagementParametricCreator::CColorManagementParametricCreator(SP resource_) : resource(resource_) { - if (!good()) + if UNLIKELY (!good()) return; // pClient = resource->client(); @@ -318,7 +318,7 @@ CColorManagementParametricCreator::CColorManagementParametricCreator(SPm_vImageDescriptions.emplace_back( makeShared(makeShared(r->client(), r->version(), id))); - if (!RESOURCE->good()) { + if UNLIKELY (!RESOURCE->good()) { r->noMemory(); PROTO::colorManagement->m_vImageDescriptions.pop_back(); return; @@ -465,7 +465,7 @@ wl_client* CColorManagementParametricCreator::client() { CColorManagementImageDescription::CColorManagementImageDescription(SP resource_, bool allowGetInformation) : m_resource(resource_), m_allowGetInformation(allowGetInformation) { - if (!good()) + if UNLIKELY (!good()) return; pClient = m_resource->client(); @@ -482,7 +482,7 @@ CColorManagementImageDescription::CColorManagementImageDescription(SP(makeShared(r->client(), r->version(), id), settings); - if (!RESOURCE->good()) + if UNLIKELY (!RESOURCE->good()) r->noMemory(); // CColorManagementImageDescriptionInfo should send everything in the constructor and be ready for destroying at this point @@ -504,7 +504,7 @@ SP CColorManagementImageDescription::resource() { CColorManagementImageDescriptionInfo::CColorManagementImageDescriptionInfo(SP resource_, const SImageDescription& settings_) : m_resource(resource_), settings(settings_) { - if (!good()) + if UNLIKELY (!good()) return; pClient = m_resource->client(); @@ -549,7 +549,7 @@ CColorManagementProtocol::CColorManagementProtocol(const wl_interface* iface, co void CColorManagementProtocol::bindManager(wl_client* client, void* data, uint32_t ver, uint32_t id) { const auto RESOURCE = m_vManagers.emplace_back(makeShared(makeShared(client, ver, id))); - if (!RESOURCE->good()) { + if UNLIKELY (!RESOURCE->good()) { wl_client_post_no_memory(client); m_vManagers.pop_back(); return; diff --git a/src/protocols/CursorShape.cpp b/src/protocols/CursorShape.cpp index 233a5df9..429d604f 100644 --- a/src/protocols/CursorShape.cpp +++ b/src/protocols/CursorShape.cpp @@ -41,7 +41,7 @@ void CCursorShapeProtocol::createCursorShapeDevice(CWpCursorShapeManagerV1* pMgr } void CCursorShapeProtocol::onSetShape(CWpCursorShapeDeviceV1* pMgr, uint32_t serial, wpCursorShapeDeviceV1Shape shape) { - if ((uint32_t)shape == 0 || (uint32_t)shape > CURSOR_SHAPE_NAMES.size()) { + if UNLIKELY ((uint32_t)shape == 0 || (uint32_t)shape > CURSOR_SHAPE_NAMES.size()) { pMgr->error(WP_CURSOR_SHAPE_DEVICE_V1_ERROR_INVALID_SHAPE, "The shape is invalid"); return; } diff --git a/src/protocols/DRMLease.cpp b/src/protocols/DRMLease.cpp index 4ab46a46..fce1e345 100644 --- a/src/protocols/DRMLease.cpp +++ b/src/protocols/DRMLease.cpp @@ -6,7 +6,7 @@ #include CDRMLeaseResource::CDRMLeaseResource(SP resource_, SP request) : resource(resource_) { - if (!good()) + if UNLIKELY (!good()) return; resource->setOnDestroy([this](CWpDrmLeaseV1* r) { PROTO::lease->destroyResource(this); }); @@ -79,7 +79,7 @@ CDRMLeaseResource::~CDRMLeaseResource() { } CDRMLeaseRequestResource::CDRMLeaseRequestResource(SP resource_) : resource(resource_) { - if (!good()) + if UNLIKELY (!good()) return; resource->setOnDestroy([this](CWpDrmLeaseRequestV1* r) { PROTO::lease->destroyResource(this); }); @@ -109,7 +109,7 @@ CDRMLeaseRequestResource::CDRMLeaseRequestResource(SP reso } auto RESOURCE = makeShared(makeShared(resource->client(), resource->version(), id), self.lock()); - if (!RESOURCE) { + if UNLIKELY (!RESOURCE) { resource->noMemory(); return; } @@ -131,7 +131,7 @@ SP CDRMLeaseConnectorResource::fromResource(wl_resou } CDRMLeaseConnectorResource::CDRMLeaseConnectorResource(SP resource_, PHLMONITOR monitor_) : monitor(monitor_), resource(resource_) { - if (!good()) + if UNLIKELY (!good()) return; resource->setOnDestroy([this](CWpDrmLeaseConnectorV1* r) { PROTO::lease->destroyResource(this); }); @@ -160,7 +160,7 @@ void CDRMLeaseConnectorResource::sendData() { } CDRMLeaseDeviceResource::CDRMLeaseDeviceResource(SP resource_) : resource(resource_) { - if (!good()) + if UNLIKELY (!good()) return; resource->setOnDestroy([this](CWpDrmLeaseDeviceV1* r) { PROTO::lease->destroyResource(this); }); @@ -168,7 +168,7 @@ CDRMLeaseDeviceResource::CDRMLeaseDeviceResource(SP resourc resource->setCreateLeaseRequest([this](CWpDrmLeaseDeviceV1* r, uint32_t id) { auto RESOURCE = makeShared(makeShared(resource->client(), resource->version(), id)); - if (!RESOURCE) { + if UNLIKELY (!RESOURCE) { resource->noMemory(); return; } @@ -209,7 +209,7 @@ void CDRMLeaseDeviceResource::sendConnector(PHLMONITOR monitor) { return; auto RESOURCE = makeShared(makeShared(resource->client(), resource->version(), 0), monitor); - if (!RESOURCE) { + if UNLIKELY (!RESOURCE) { resource->noMemory(); return; } @@ -262,7 +262,7 @@ CDRMLeaseProtocol::CDRMLeaseProtocol(const wl_interface* iface, const int& ver, void CDRMLeaseProtocol::bindManager(wl_client* client, void* data, uint32_t ver, uint32_t id) { const auto RESOURCE = m_vManagers.emplace_back(makeShared(makeShared(client, ver, id))); - if (!RESOURCE->good()) { + if UNLIKELY (!RESOURCE->good()) { wl_client_post_no_memory(client); m_vManagers.pop_back(); return; diff --git a/src/protocols/DRMSyncobj.cpp b/src/protocols/DRMSyncobj.cpp index 1da4baaf..ce598385 100644 --- a/src/protocols/DRMSyncobj.cpp +++ b/src/protocols/DRMSyncobj.cpp @@ -8,7 +8,7 @@ #include CDRMSyncobjSurfaceResource::CDRMSyncobjSurfaceResource(SP resource_, SP surface_) : surface(surface_), resource(resource_) { - if (!good()) + if UNLIKELY (!good()) return; resource->setData(this); @@ -104,7 +104,7 @@ bool CDRMSyncobjSurfaceResource::good() { } CDRMSyncobjTimelineResource::CDRMSyncobjTimelineResource(SP resource_, int fd_) : fd(fd_), resource(resource_) { - if (!good()) + if UNLIKELY (!good()) return; resource->setData(this); @@ -135,31 +135,31 @@ bool CDRMSyncobjTimelineResource::good() { } CDRMSyncobjManagerResource::CDRMSyncobjManagerResource(SP resource_) : resource(resource_) { - if (!good()) + if UNLIKELY (!good()) return; resource->setOnDestroy([this](CWpLinuxDrmSyncobjManagerV1* r) { PROTO::sync->destroyResource(this); }); resource->setDestroy([this](CWpLinuxDrmSyncobjManagerV1* r) { PROTO::sync->destroyResource(this); }); resource->setGetSurface([this](CWpLinuxDrmSyncobjManagerV1* r, uint32_t id, wl_resource* surf) { - if (!surf) { + if UNLIKELY (!surf) { resource->error(-1, "Invalid surface"); return; } auto SURF = CWLSurfaceResource::fromResource(surf); - if (!SURF) { + if UNLIKELY (!SURF) { resource->error(-1, "Invalid surface (2)"); return; } - if (SURF->syncobj) { + if UNLIKELY (SURF->syncobj) { resource->error(WP_LINUX_DRM_SYNCOBJ_MANAGER_V1_ERROR_SURFACE_EXISTS, "Surface already has a syncobj attached"); return; } auto RESOURCE = makeShared(makeShared(resource->client(), resource->version(), id), SURF); - if (!RESOURCE->good()) { + if UNLIKELY (!RESOURCE->good()) { resource->noMemory(); return; } @@ -172,7 +172,7 @@ CDRMSyncobjManagerResource::CDRMSyncobjManagerResource(SPsetImportTimeline([this](CWpLinuxDrmSyncobjManagerV1* r, uint32_t id, int32_t fd) { auto RESOURCE = makeShared(makeShared(resource->client(), resource->version(), id), fd); - if (!RESOURCE->good()) { + if UNLIKELY (!RESOURCE->good()) { resource->noMemory(); return; } @@ -195,7 +195,7 @@ CDRMSyncobjProtocol::CDRMSyncobjProtocol(const wl_interface* iface, const int& v void CDRMSyncobjProtocol::bindManager(wl_client* client, void* data, uint32_t ver, uint32_t id) { const auto RESOURCE = m_vManagers.emplace_back(makeShared(makeShared(client, ver, id))); - if (!RESOURCE->good()) { + if UNLIKELY (!RESOURCE->good()) { wl_client_post_no_memory(client); m_vManagers.pop_back(); return; diff --git a/src/protocols/DataDeviceWlr.cpp b/src/protocols/DataDeviceWlr.cpp index d8103d11..71ee1c4a 100644 --- a/src/protocols/DataDeviceWlr.cpp +++ b/src/protocols/DataDeviceWlr.cpp @@ -4,7 +4,7 @@ #include "core/Seat.hpp" CWLRDataOffer::CWLRDataOffer(SP resource_, SP source_) : source(source_), resource(resource_) { - if (!good()) + if UNLIKELY (!good()) return; resource->setDestroy([this](CZwlrDataControlOfferV1* r) { PROTO::dataWlr->destroyResource(this); }); @@ -34,7 +34,7 @@ bool CWLRDataOffer::good() { } void CWLRDataOffer::sendData() { - if (!source) + if UNLIKELY (!source) return; for (auto const& m : source->mimes()) { @@ -43,7 +43,7 @@ void CWLRDataOffer::sendData() { } CWLRDataSource::CWLRDataSource(SP resource_, SP device_) : device(device_), resource(resource_) { - if (!good()) + if UNLIKELY (!good()) return; resource->setData(this); @@ -104,7 +104,7 @@ void CWLRDataSource::error(uint32_t code, const std::string& msg) { } CWLRDataDevice::CWLRDataDevice(SP resource_) : resource(resource_) { - if (!good()) + if UNLIKELY (!good()) return; pClient = resource->client(); @@ -173,7 +173,7 @@ void CWLRDataDevice::sendPrimarySelection(SP selection) { } CWLRDataControlManagerResource::CWLRDataControlManagerResource(SP resource_) : resource(resource_) { - if (!good()) + if UNLIKELY (!good()) return; resource->setDestroy([this](CZwlrDataControlManagerV1* r) { PROTO::dataWlr->destroyResource(this); }); @@ -182,7 +182,7 @@ CWLRDataControlManagerResource::CWLRDataControlManagerResource(SPsetGetDataDevice([this](CZwlrDataControlManagerV1* r, uint32_t id, wl_resource* seat) { const auto RESOURCE = PROTO::dataWlr->m_vDevices.emplace_back(makeShared(makeShared(r->client(), r->version(), id))); - if (!RESOURCE->good()) { + if UNLIKELY (!RESOURCE->good()) { r->noMemory(); PROTO::dataWlr->m_vDevices.pop_back(); return; @@ -208,7 +208,7 @@ CWLRDataControlManagerResource::CWLRDataControlManagerResource(SPm_vSources.emplace_back(makeShared(makeShared(r->client(), r->version(), id), device.lock())); - if (!RESOURCE->good()) { + if UNLIKELY (!RESOURCE->good()) { r->noMemory(); PROTO::dataWlr->m_vSources.pop_back(); return; @@ -236,7 +236,7 @@ CDataDeviceWLRProtocol::CDataDeviceWLRProtocol(const wl_interface* iface, const void CDataDeviceWLRProtocol::bindManager(wl_client* client, void* data, uint32_t ver, uint32_t id) { const auto RESOURCE = m_vManagers.emplace_back(makeShared(makeShared(client, ver, id))); - if (!RESOURCE->good()) { + if UNLIKELY (!RESOURCE->good()) { wl_client_post_no_memory(client); m_vManagers.pop_back(); return; diff --git a/src/protocols/FocusGrab.cpp b/src/protocols/FocusGrab.cpp index aff232e4..ee30343f 100644 --- a/src/protocols/FocusGrab.cpp +++ b/src/protocols/FocusGrab.cpp @@ -17,7 +17,7 @@ CFocusGrabSurfaceState::~CFocusGrabSurfaceState() { } CFocusGrab::CFocusGrab(SP resource_) : resource(resource_) { - if (!resource->resource()) + if UNLIKELY (!resource->resource()) return; grab = makeShared(); @@ -63,9 +63,8 @@ void CFocusGrab::finish(bool sendCleared) { if (m_bGrabActive) { m_bGrabActive = false; - if (g_pSeatManager->seatGrab == grab) { + if (g_pSeatManager->seatGrab == grab) g_pSeatManager->setGrab(nullptr); - } grab->clear(); m_mSurfaces.clear(); @@ -77,17 +76,16 @@ void CFocusGrab::finish(bool sendCleared) { void CFocusGrab::addSurface(SP surface) { auto iter = std::find_if(m_mSurfaces.begin(), m_mSurfaces.end(), [surface](const auto& e) { return e.first == surface; }); - if (iter == m_mSurfaces.end()) { + if (iter == m_mSurfaces.end()) m_mSurfaces.emplace(surface, std::make_unique(this, surface)); - } } void CFocusGrab::removeSurface(SP surface) { auto iter = m_mSurfaces.find(surface); if (iter != m_mSurfaces.end()) { - if (iter->second->state == CFocusGrabSurfaceState::PendingAddition) { + if (iter->second->state == CFocusGrabSurfaceState::PendingAddition) m_mSurfaces.erase(iter); - } else + else iter->second->state = CFocusGrabSurfaceState::PendingRemoval; } } @@ -172,7 +170,7 @@ void CFocusGrabProtocol::onCreateGrab(CHyprlandFocusGrabManagerV1* pMgr, uint32_ m_vGrabs.push_back(std::make_unique(makeShared(pMgr->client(), pMgr->version(), id))); const auto RESOURCE = m_vGrabs.back().get(); - if (!RESOURCE->good()) { + if UNLIKELY (!RESOURCE->good()) { pMgr->noMemory(); m_vGrabs.pop_back(); } diff --git a/src/protocols/ForeignToplevel.cpp b/src/protocols/ForeignToplevel.cpp index f6513a1d..6880164f 100644 --- a/src/protocols/ForeignToplevel.cpp +++ b/src/protocols/ForeignToplevel.cpp @@ -3,7 +3,7 @@ #include "../managers/HookSystemManager.hpp" CForeignToplevelHandle::CForeignToplevelHandle(SP resource_, PHLWINDOW pWindow_) : resource(resource_), pWindow(pWindow_) { - if (!resource_->resource()) + if UNLIKELY (!resource_->resource()) return; resource->setOnDestroy([this](CExtForeignToplevelHandleV1* h) { PROTO::foreignToplevel->destroyHandle(this); }); @@ -19,7 +19,7 @@ PHLWINDOW CForeignToplevelHandle::window() { } CForeignToplevelList::CForeignToplevelList(SP resource_) : resource(resource_) { - if (!resource_->resource()) + if UNLIKELY (!resource_->resource()) return; resource->setOnDestroy([this](CExtForeignToplevelListV1* h) { PROTO::foreignToplevel->onManagerResourceDestroy(this); }); @@ -40,7 +40,7 @@ CForeignToplevelList::CForeignToplevelList(SP resourc } void CForeignToplevelList::onMap(PHLWINDOW pWindow) { - if (finished) + if UNLIKELY (finished) return; const auto NEWHANDLE = PROTO::foreignToplevel->m_vHandles.emplace_back( @@ -72,11 +72,11 @@ SP CForeignToplevelList::handleForWindow(PHLWINDOW pWind } void CForeignToplevelList::onTitle(PHLWINDOW pWindow) { - if (finished) + if UNLIKELY (finished) return; const auto H = handleForWindow(pWindow); - if (!H || H->closed) + if UNLIKELY (!H || H->closed) return; H->resource->sendTitle(pWindow->m_szTitle.c_str()); @@ -84,11 +84,11 @@ void CForeignToplevelList::onTitle(PHLWINDOW pWindow) { } void CForeignToplevelList::onClass(PHLWINDOW pWindow) { - if (finished) + if UNLIKELY (finished) return; const auto H = handleForWindow(pWindow); - if (!H || H->closed) + if UNLIKELY (!H || H->closed) return; H->resource->sendAppId(pWindow->m_szClass.c_str()); @@ -96,11 +96,11 @@ void CForeignToplevelList::onClass(PHLWINDOW pWindow) { } void CForeignToplevelList::onUnmap(PHLWINDOW pWindow) { - if (finished) + if UNLIKELY (finished) return; const auto H = handleForWindow(pWindow); - if (!H) + if UNLIKELY (!H) return; H->resource->sendClosed(); @@ -149,7 +149,7 @@ CForeignToplevelProtocol::CForeignToplevelProtocol(const wl_interface* iface, co void CForeignToplevelProtocol::bindManager(wl_client* client, void* data, uint32_t ver, uint32_t id) { const auto RESOURCE = m_vManagers.emplace_back(std::make_unique(makeShared(client, ver, id))).get(); - if (!RESOURCE->good()) { + if UNLIKELY (!RESOURCE->good()) { LOGM(ERR, "Couldn't create a foreign list"); wl_client_post_no_memory(client); m_vManagers.pop_back(); diff --git a/src/protocols/ForeignToplevelWlr.cpp b/src/protocols/ForeignToplevelWlr.cpp index 45ef3f93..e18f6e23 100644 --- a/src/protocols/ForeignToplevelWlr.cpp +++ b/src/protocols/ForeignToplevelWlr.cpp @@ -6,7 +6,7 @@ #include "../managers/HookSystemManager.hpp" CForeignToplevelHandleWlr::CForeignToplevelHandleWlr(SP resource_, PHLWINDOW pWindow_) : resource(resource_), pWindow(pWindow_) { - if (!resource_->resource()) + if UNLIKELY (!resource_->resource()) return; resource->setOnDestroy([this](CZwlrForeignToplevelHandleV1* h) { PROTO::foreignToplevelWlr->destroyHandle(this); }); @@ -15,7 +15,7 @@ CForeignToplevelHandleWlr::CForeignToplevelHandleWlr(SPsetActivate([this](CZwlrForeignToplevelHandleV1* p, wl_resource* seat) { const auto PWINDOW = pWindow.lock(); - if (!PWINDOW) + if UNLIKELY (!PWINDOW) return; // these requests bypass the config'd stuff cuz it's usually like @@ -26,13 +26,13 @@ CForeignToplevelHandleWlr::CForeignToplevelHandleWlr(SPsetSetFullscreen([this](CZwlrForeignToplevelHandleV1* p, wl_resource* output) { const auto PWINDOW = pWindow.lock(); - if (!PWINDOW) + if UNLIKELY (!PWINDOW) return; - if (PWINDOW->m_eSuppressedEvents & SUPPRESS_FULLSCREEN) + if UNLIKELY (PWINDOW->m_eSuppressedEvents & SUPPRESS_FULLSCREEN) return; - if (!PWINDOW->m_bIsMapped) { + if UNLIKELY (!PWINDOW->m_bIsMapped) { PWINDOW->m_bWantsInitialFullscreen = true; return; } @@ -57,10 +57,10 @@ CForeignToplevelHandleWlr::CForeignToplevelHandleWlr(SPsetUnsetFullscreen([this](CZwlrForeignToplevelHandleV1* p) { const auto PWINDOW = pWindow.lock(); - if (!PWINDOW) + if UNLIKELY (!PWINDOW) return; - if (PWINDOW->m_eSuppressedEvents & SUPPRESS_FULLSCREEN) + if UNLIKELY (PWINDOW->m_eSuppressedEvents & SUPPRESS_FULLSCREEN) return; g_pCompositor->changeWindowFullscreenModeClient(PWINDOW, FSMODE_FULLSCREEN, false); @@ -69,13 +69,13 @@ CForeignToplevelHandleWlr::CForeignToplevelHandleWlr(SPsetSetMaximized([this](CZwlrForeignToplevelHandleV1* p) { const auto PWINDOW = pWindow.lock(); - if (!PWINDOW) + if UNLIKELY (!PWINDOW) return; - if (PWINDOW->m_eSuppressedEvents & SUPPRESS_MAXIMIZE) + if UNLIKELY (PWINDOW->m_eSuppressedEvents & SUPPRESS_MAXIMIZE) return; - if (!PWINDOW->m_bIsMapped) { + if UNLIKELY (!PWINDOW->m_bIsMapped) { PWINDOW->m_bWantsInitialFullscreen = true; return; } @@ -86,10 +86,10 @@ CForeignToplevelHandleWlr::CForeignToplevelHandleWlr(SPsetUnsetMaximized([this](CZwlrForeignToplevelHandleV1* p) { const auto PWINDOW = pWindow.lock(); - if (!PWINDOW) + if UNLIKELY (!PWINDOW) return; - if (PWINDOW->m_eSuppressedEvents & SUPPRESS_MAXIMIZE) + if UNLIKELY (PWINDOW->m_eSuppressedEvents & SUPPRESS_MAXIMIZE) return; g_pCompositor->changeWindowFullscreenModeClient(PWINDOW, FSMODE_MAXIMIZED, false); @@ -98,7 +98,7 @@ CForeignToplevelHandleWlr::CForeignToplevelHandleWlr(SPsetClose([this](CZwlrForeignToplevelHandleV1* p) { const auto PWINDOW = pWindow.lock(); - if (!PWINDOW) + if UNLIKELY (!PWINDOW) return; g_pCompositor->closeWindow(PWINDOW); @@ -126,14 +126,14 @@ void CForeignToplevelHandleWlr::sendMonitor(PHLMONITOR pMonitor) { if (const auto PLASTMONITOR = g_pCompositor->getMonitorFromID(lastMonitorID); PLASTMONITOR && PROTO::outputs.contains(PLASTMONITOR->szName)) { const auto OLDRESOURCE = PROTO::outputs.at(PLASTMONITOR->szName)->outputResourceFrom(CLIENT); - if (OLDRESOURCE) + if LIKELY (OLDRESOURCE) resource->sendOutputLeave(OLDRESOURCE->getResource()->resource()); } if (PROTO::outputs.contains(pMonitor->szName)) { const auto NEWRESOURCE = PROTO::outputs.at(pMonitor->szName)->outputResourceFrom(CLIENT); - if (NEWRESOURCE) + if LIKELY (NEWRESOURCE) resource->sendOutputEnter(NEWRESOURCE->getResource()->resource()); } @@ -143,7 +143,7 @@ void CForeignToplevelHandleWlr::sendMonitor(PHLMONITOR pMonitor) { void CForeignToplevelHandleWlr::sendState() { const auto PWINDOW = pWindow.lock(); - if (!PWINDOW || !PWINDOW->m_pWorkspace || !PWINDOW->m_bIsMapped) + if UNLIKELY (!PWINDOW || !PWINDOW->m_pWorkspace || !PWINDOW->m_bIsMapped) return; wl_array state; @@ -168,7 +168,7 @@ void CForeignToplevelHandleWlr::sendState() { } CForeignToplevelWlrManager::CForeignToplevelWlrManager(SP resource_) : resource(resource_) { - if (!resource_->resource()) + if UNLIKELY (!resource_->resource()) return; resource->setOnDestroy([this](CZwlrForeignToplevelManagerV1* h) { PROTO::foreignToplevelWlr->onManagerResourceDestroy(this); }); @@ -191,13 +191,13 @@ CForeignToplevelWlrManager::CForeignToplevelWlrManager(SPm_vHandles.emplace_back( makeShared(makeShared(resource->client(), resource->version(), 0), pWindow)); - if (!NEWHANDLE->good()) { + if UNLIKELY (!NEWHANDLE->good()) { LOGM(ERR, "Couldn't create a foreign handle"); resource->noMemory(); PROTO::foreignToplevelWlr->m_vHandles.pop_back(); @@ -208,7 +208,7 @@ void CForeignToplevelWlrManager::onMap(PHLWINDOW pWindow) { resource->sendToplevel(NEWHANDLE->resource.get()); NEWHANDLE->resource->sendAppId(pWindow->m_szClass.c_str()); NEWHANDLE->resource->sendTitle(pWindow->m_szTitle.c_str()); - if (const auto PMONITOR = pWindow->m_pMonitor.lock(); PMONITOR) + if LIKELY (const auto PMONITOR = pWindow->m_pMonitor.lock(); PMONITOR) NEWHANDLE->sendMonitor(PMONITOR); NEWHANDLE->sendState(); NEWHANDLE->resource->sendDone(); @@ -223,11 +223,11 @@ SP CForeignToplevelWlrManager::handleForWindow(PHLWIN } void CForeignToplevelWlrManager::onTitle(PHLWINDOW pWindow) { - if (finished) + if UNLIKELY (finished) return; const auto H = handleForWindow(pWindow); - if (!H || H->closed) + if UNLIKELY (!H || H->closed) return; H->resource->sendTitle(pWindow->m_szTitle.c_str()); @@ -235,11 +235,11 @@ void CForeignToplevelWlrManager::onTitle(PHLWINDOW pWindow) { } void CForeignToplevelWlrManager::onClass(PHLWINDOW pWindow) { - if (finished) + if UNLIKELY (finished) return; const auto H = handleForWindow(pWindow); - if (!H || H->closed) + if UNLIKELY (!H || H->closed) return; H->resource->sendAppId(pWindow->m_szClass.c_str()); @@ -247,11 +247,11 @@ void CForeignToplevelWlrManager::onClass(PHLWINDOW pWindow) { } void CForeignToplevelWlrManager::onUnmap(PHLWINDOW pWindow) { - if (finished) + if UNLIKELY (finished) return; const auto H = handleForWindow(pWindow); - if (!H) + if UNLIKELY (!H) return; H->resource->sendClosed(); @@ -260,16 +260,16 @@ void CForeignToplevelWlrManager::onUnmap(PHLWINDOW pWindow) { } void CForeignToplevelWlrManager::onMoveMonitor(PHLWINDOW pWindow) { - if (finished) + if UNLIKELY (finished) return; const auto H = handleForWindow(pWindow); - if (!H || H->closed) + if UNLIKELY (!H || H->closed) return; const auto PMONITOR = pWindow->m_pMonitor.lock(); - if (!PMONITOR) + if UNLIKELY (!PMONITOR) return; H->sendMonitor(PMONITOR); @@ -277,11 +277,11 @@ void CForeignToplevelWlrManager::onMoveMonitor(PHLWINDOW pWindow) { } void CForeignToplevelWlrManager::onFullscreen(PHLWINDOW pWindow) { - if (finished) + if UNLIKELY (finished) return; const auto H = handleForWindow(pWindow); - if (!H || H->closed) + if UNLIKELY (!H || H->closed) return; H->sendState(); @@ -289,10 +289,10 @@ void CForeignToplevelWlrManager::onFullscreen(PHLWINDOW pWindow) { } void CForeignToplevelWlrManager::onNewFocus(PHLWINDOW pWindow) { - if (finished) + if UNLIKELY (finished) return; - if (const auto HOLD = handleForWindow(lastFocus.lock()); HOLD) { + if LIKELY (const auto HOLD = handleForWindow(lastFocus.lock()); HOLD) { HOLD->sendState(); HOLD->resource->sendDone(); } @@ -300,7 +300,7 @@ void CForeignToplevelWlrManager::onNewFocus(PHLWINDOW pWindow) { lastFocus = pWindow; const auto H = handleForWindow(pWindow); - if (!H || H->closed) + if UNLIKELY (!H || H->closed) return; H->sendState(); @@ -378,7 +378,7 @@ CForeignToplevelWlrProtocol::CForeignToplevelWlrProtocol(const wl_interface* ifa void CForeignToplevelWlrProtocol::bindManager(wl_client* client, void* data, uint32_t ver, uint32_t id) { const auto RESOURCE = m_vManagers.emplace_back(std::make_unique(makeShared(client, ver, id))).get(); - if (!RESOURCE->good()) { + if UNLIKELY (!RESOURCE->good()) { LOGM(ERR, "Couldn't create a foreign list"); wl_client_post_no_memory(client); m_vManagers.pop_back(); diff --git a/src/protocols/FractionalScale.cpp b/src/protocols/FractionalScale.cpp index d8010eac..d1e0a604 100644 --- a/src/protocols/FractionalScale.cpp +++ b/src/protocols/FractionalScale.cpp @@ -35,7 +35,7 @@ void CFractionalScaleProtocol::onGetFractionalScale(CWpFractionalScaleManagerV1* const auto PADDON = m_mAddons.emplace(surface, std::make_unique(makeShared(pMgr->client(), pMgr->version(), id), surface)).first->second.get(); - if (!PADDON->good()) { + if UNLIKELY (!PADDON->good()) { m_mAddons.erase(surface); pMgr->noMemory(); return; diff --git a/src/protocols/FrogColorManagement.cpp b/src/protocols/FrogColorManagement.cpp index f27af5c8..cb2eed12 100644 --- a/src/protocols/FrogColorManagement.cpp +++ b/src/protocols/FrogColorManagement.cpp @@ -3,7 +3,7 @@ #include "protocols/core/Subcompositor.hpp" CFrogColorManager::CFrogColorManager(SP resource_) : resource(resource_) { - if (!good()) + if UNLIKELY (!good()) return; resource->setDestroy([](CFrogColorManagementFactoryV1* r) { LOGM(TRACE, "Destroy frog_color_management at {:x} (generated default)", (uintptr_t)r); }); @@ -24,7 +24,7 @@ CFrogColorManager::CFrogColorManager(SP resource_ const auto RESOURCE = PROTO::frogColorManagement->m_vSurfaces.emplace_back( makeShared(makeShared(r->client(), r->version(), id), SURF)); - if (!RESOURCE->good()) { + if UNLIKELY (!RESOURCE->good()) { r->noMemory(); PROTO::frogColorManagement->m_vSurfaces.pop_back(); return; @@ -39,14 +39,14 @@ bool CFrogColorManager::good() { } CFrogColorManagementSurface::CFrogColorManagementSurface(SP resource_, SP surface_) : surface(surface_), resource(resource_) { - if (!good()) + if UNLIKELY (!good()) return; pClient = resource->client(); if (!surface->colorManagement.valid()) { const auto RESOURCE = PROTO::colorManagement->m_vSurfaces.emplace_back(makeShared(surface_)); - if (!RESOURCE) { + if UNLIKELY (!RESOURCE) { resource->noMemory(); PROTO::colorManagement->m_vSurfaces.pop_back(); return; @@ -141,7 +141,7 @@ CFrogColorManagementProtocol::CFrogColorManagementProtocol(const wl_interface* i void CFrogColorManagementProtocol::bindManager(wl_client* client, void* data, uint32_t ver, uint32_t id) { const auto RESOURCE = m_vManagers.emplace_back(makeShared(makeShared(client, ver, id))); - if (!RESOURCE->good()) { + if UNLIKELY (!RESOURCE->good()) { wl_client_post_no_memory(client); m_vManagers.pop_back(); return; diff --git a/src/protocols/GammaControl.cpp b/src/protocols/GammaControl.cpp index b0da29a2..299d7717 100644 --- a/src/protocols/GammaControl.cpp +++ b/src/protocols/GammaControl.cpp @@ -6,12 +6,12 @@ #include "../render/Renderer.hpp" CGammaControl::CGammaControl(SP resource_, wl_resource* output) : resource(resource_) { - if (!resource_->resource()) + if UNLIKELY (!resource_->resource()) return; auto OUTPUTRES = CWLOutputResource::fromResource(output); - if (!OUTPUTRES) { + if UNLIKELY (!OUTPUTRES) { LOGM(ERR, "No output in CGammaControl"); resource->sendFailed(); return; @@ -19,14 +19,14 @@ CGammaControl::CGammaControl(SP resource_, wl_resource* out pMonitor = OUTPUTRES->monitor; - if (!pMonitor || !pMonitor->output) { + if UNLIKELY (!pMonitor || !pMonitor->output) { LOGM(ERR, "No CMonitor"); resource->sendFailed(); return; } for (auto const& g : PROTO::gamma->m_vGammaControllers) { - if (g->pMonitor == pMonitor) { + if UNLIKELY (g->pMonitor == pMonitor) { resource->sendFailed(); return; } @@ -34,7 +34,7 @@ CGammaControl::CGammaControl(SP resource_, wl_resource* out gammaSize = pMonitor->output->getGammaSize(); - if (gammaSize <= 0) { + if UNLIKELY (gammaSize <= 0) { LOGM(ERR, "Output {} doesn't support gamma", pMonitor->szName); resource->sendFailed(); return; @@ -46,7 +46,7 @@ CGammaControl::CGammaControl(SP resource_, wl_resource* out resource->setOnDestroy([this](CZwlrGammaControlV1* gamma) { PROTO::gamma->destroyGammaControl(this); }); resource->setSetGamma([this](CZwlrGammaControlV1* gamma, int32_t fd) { - if (!pMonitor) { + if UNLIKELY (!pMonitor) { LOGM(ERR, "setGamma for a dead monitor"); resource->sendFailed(); close(fd); @@ -56,14 +56,14 @@ CGammaControl::CGammaControl(SP resource_, wl_resource* out LOGM(LOG, "setGamma for {}", pMonitor->szName); int fdFlags = fcntl(fd, F_GETFL, 0); - if (fdFlags < 0) { + if UNLIKELY (fdFlags < 0) { LOGM(ERR, "Failed to get fd flags"); resource->sendFailed(); close(fd); return; } - if (fcntl(fd, F_SETFL, fdFlags | O_NONBLOCK) < 0) { + if UNLIKELY (fcntl(fd, F_SETFL, fdFlags | O_NONBLOCK) < 0) { LOGM(ERR, "Failed to set fd flags"); resource->sendFailed(); close(fd); @@ -126,7 +126,7 @@ bool CGammaControl::good() { } void CGammaControl::applyToMonitor() { - if (!pMonitor || !pMonitor->output) + if UNLIKELY (!pMonitor || !pMonitor->output) return; // ?? LOGM(LOG, "setting to monitor {}", pMonitor->szName); @@ -179,7 +179,7 @@ void CGammaControlProtocol::onGetGammaControl(CZwlrGammaControlManagerV1* pMgr, const auto CLIENT = pMgr->client(); const auto RESOURCE = m_vGammaControllers.emplace_back(std::make_unique(makeShared(CLIENT, pMgr->version(), id), output)).get(); - if (!RESOURCE->good()) { + if UNLIKELY (!RESOURCE->good()) { pMgr->noMemory(); m_vGammaControllers.pop_back(); return; diff --git a/src/protocols/GlobalShortcuts.cpp b/src/protocols/GlobalShortcuts.cpp index ca67f063..6fac2d7f 100644 --- a/src/protocols/GlobalShortcuts.cpp +++ b/src/protocols/GlobalShortcuts.cpp @@ -1,7 +1,7 @@ #include "GlobalShortcuts.hpp" CShortcutClient::CShortcutClient(SP resource_) : resource(resource_) { - if (!good()) + if UNLIKELY (!good()) return; resource->setOnDestroy([this](CHyprlandGlobalShortcutsManagerV1* pMgr) { PROTO::globalShortcuts->destroyResource(this); }); @@ -9,7 +9,7 @@ CShortcutClient::CShortcutClient(SP resource_ resource->setRegisterShortcut([this](CHyprlandGlobalShortcutsManagerV1* pMgr, uint32_t shortcut, const char* id, const char* app_id, const char* description, const char* trigger_description) { - if (PROTO::globalShortcuts->isTaken(id, app_id)) { + if UNLIKELY (PROTO::globalShortcuts->isTaken(id, app_id)) { resource->error(HYPRLAND_GLOBAL_SHORTCUTS_MANAGER_V1_ERROR_ALREADY_TAKEN, "Combination is taken"); return; } @@ -20,7 +20,7 @@ CShortcutClient::CShortcutClient(SP resource_ PSHORTCUT->appid = app_id; PSHORTCUT->shortcut = shortcut; - if (!PSHORTCUT->resource->resource()) { + if UNLIKELY (!PSHORTCUT->resource->resource()) { PSHORTCUT->resource->noMemory(); shortcuts.pop_back(); return; @@ -41,7 +41,7 @@ CGlobalShortcutsProtocol::CGlobalShortcutsProtocol(const wl_interface* iface, co void CGlobalShortcutsProtocol::bindManager(wl_client* client, void* data, uint32_t ver, uint32_t id) { const auto RESROUCE = m_vClients.emplace_back(makeShared(makeShared(client, ver, id))); - if (!RESROUCE->good()) { + if UNLIKELY (!RESROUCE->good()) { wl_client_post_no_memory(client); m_vClients.pop_back(); return; diff --git a/src/protocols/HyprlandSurface.cpp b/src/protocols/HyprlandSurface.cpp index ce6fc77a..bcf4905c 100644 --- a/src/protocols/HyprlandSurface.cpp +++ b/src/protocols/HyprlandSurface.cpp @@ -15,20 +15,20 @@ bool CHyprlandSurface::good() const { void CHyprlandSurface::setResource(SP resource) { m_pResource = std::move(resource); - if (!m_pResource->resource()) + if UNLIKELY (!m_pResource->resource()) return; m_pResource->setDestroy([this](CHyprlandSurfaceV1* resource) { destroy(); }); m_pResource->setOnDestroy([this](CHyprlandSurfaceV1* resource) { destroy(); }); m_pResource->setSetOpacity([this](CHyprlandSurfaceV1* resource, uint32_t opacity) { - if (!m_pSurface) { + if UNLIKELY (!m_pSurface) { m_pResource->error(HYPRLAND_SURFACE_V1_ERROR_NO_SURFACE, "set_opacity called for destroyed wl_surface"); return; } auto fOpacity = wl_fixed_to_double(opacity); - if (fOpacity < 0.0 || fOpacity > 1.0) { + if UNLIKELY (fOpacity < 0.0 || fOpacity > 1.0) { m_pResource->error(HYPRLAND_SURFACE_V1_ERROR_OUT_OF_RANGE, "set_opacity called with an opacity value larger than 1.0 or smaller than 0.0."); return; } @@ -104,7 +104,7 @@ void CHyprlandSurfaceProtocol::getSurface(CHyprlandSurfaceManagerV1* manager, ui .first->second.get(); } - if (!hyprlandSurface->good()) { + if UNLIKELY (!hyprlandSurface->good()) { manager->noMemory(); m_mSurfaces.erase(surface); } diff --git a/src/protocols/IdleNotify.cpp b/src/protocols/IdleNotify.cpp index 3517a62d..85a9f8e2 100644 --- a/src/protocols/IdleNotify.cpp +++ b/src/protocols/IdleNotify.cpp @@ -11,7 +11,7 @@ static int onTimer(SP self, void* data) { } CExtIdleNotification::CExtIdleNotification(SP resource_, uint32_t timeoutMs_) : resource(resource_), timeoutMs(timeoutMs_) { - if (!resource_->resource()) + if UNLIKELY (!resource_->resource()) return; resource->setDestroy([this](CExtIdleNotificationV1* r) { PROTO::idle->destroyNotification(this); }); @@ -78,7 +78,7 @@ void CIdleNotifyProtocol::onGetNotification(CExtIdleNotifierV1* pMgr, uint32_t i const auto CLIENT = pMgr->client(); const auto RESOURCE = m_vNotifications.emplace_back(makeShared(makeShared(CLIENT, pMgr->version(), id), timeout)).get(); - if (!RESOURCE->good()) { + if UNLIKELY (!RESOURCE->good()) { pMgr->noMemory(); m_vNotifications.pop_back(); return; diff --git a/src/protocols/InputMethodV2.cpp b/src/protocols/InputMethodV2.cpp index 5fd1e893..cf777f45 100644 --- a/src/protocols/InputMethodV2.cpp +++ b/src/protocols/InputMethodV2.cpp @@ -7,7 +7,7 @@ #include CInputMethodKeyboardGrabV2::CInputMethodKeyboardGrabV2(SP resource_, SP owner_) : resource(resource_), owner(owner_) { - if (!resource->resource()) + if UNLIKELY (!resource->resource()) return; resource->setRelease([this](CZwpInputMethodKeyboardGrabV2* r) { PROTO::ime->destroyResource(this); }); @@ -34,13 +34,13 @@ void CInputMethodKeyboardGrabV2::sendKeyboardData(SP keyboard) { pLastKeyboard = keyboard; int keymapFD = allocateSHMFile(keyboard->xkbKeymapString.length() + 1); - if (keymapFD < 0) { + if UNLIKELY (keymapFD < 0) { LOGM(ERR, "Failed to create a keymap file for keyboard grab"); return; } void* data = mmap(nullptr, keyboard->xkbKeymapString.length() + 1, PROT_READ | PROT_WRITE, MAP_SHARED, keymapFD, 0); - if (data == MAP_FAILED) { + if UNLIKELY (data == MAP_FAILED) { LOGM(ERR, "Failed to mmap a keymap file for keyboard grab"); close(keymapFD); return; @@ -83,7 +83,7 @@ wl_client* CInputMethodKeyboardGrabV2::client() { } CInputMethodPopupV2::CInputMethodPopupV2(SP resource_, SP owner_, SP surface) : resource(resource_), owner(owner_) { - if (!resource->resource()) + if UNLIKELY (!resource->resource()) return; resource->setDestroy([this](CZwpInputPopupSurfaceV2* r) { PROTO::ime->destroyResource(this); }); @@ -149,7 +149,7 @@ void CInputMethodV2::SState::reset() { } CInputMethodV2::CInputMethodV2(SP resource_) : resource(resource_) { - if (!resource->resource()) + if UNLIKELY (!resource->resource()) return; resource->setDestroy([this](CZwpInputMethodV2* r) { @@ -189,7 +189,7 @@ CInputMethodV2::CInputMethodV2(SP resource_) : resource(resou const auto RESOURCE = PROTO::ime->m_vPopups.emplace_back( makeShared(makeShared(r->client(), r->version(), id), self.lock(), CWLSurfaceResource::fromResource(surface))); - if (!RESOURCE->good()) { + if UNLIKELY (!RESOURCE->good()) { r->noMemory(); PROTO::ime->m_vPopups.pop_back(); return; @@ -206,7 +206,7 @@ CInputMethodV2::CInputMethodV2(SP resource_) : resource(resou const auto RESOURCE = PROTO::ime->m_vGrabs.emplace_back(makeShared(makeShared(r->client(), r->version(), id), self.lock())); - if (!RESOURCE->good()) { + if UNLIKELY (!RESOURCE->good()) { r->noMemory(); PROTO::ime->m_vGrabs.pop_back(); return; @@ -360,7 +360,7 @@ void CInputMethodV2Protocol::destroyResource(CInputMethodV2* ime) { void CInputMethodV2Protocol::onGetIME(CZwpInputMethodManagerV2* mgr, wl_resource* seat, uint32_t id) { const auto RESOURCE = m_vIMEs.emplace_back(makeShared(makeShared(mgr->client(), mgr->version(), id))); - if (!RESOURCE->good()) { + if UNLIKELY (!RESOURCE->good()) { mgr->noMemory(); m_vIMEs.pop_back(); return; diff --git a/src/protocols/LayerShell.cpp b/src/protocols/LayerShell.cpp index 0777149f..82d00a30 100644 --- a/src/protocols/LayerShell.cpp +++ b/src/protocols/LayerShell.cpp @@ -18,7 +18,7 @@ void CLayerShellResource::SState::reset() { CLayerShellResource::CLayerShellResource(SP resource_, SP surf_, std::string namespace_, PHLMONITOR pMonitor, zwlrLayerShellV1Layer layer) : layerNamespace(namespace_), surface(surf_), resource(resource_) { - if (!good()) + if UNLIKELY (!good()) return; current.layer = layer; @@ -223,19 +223,19 @@ void CLayerShellProtocol::onGetLayerSurface(CZwlrLayerShellV1* pMgr, uint32_t id const auto PMONITOR = output ? CWLOutputResource::fromResource(output)->monitor.lock() : nullptr; auto SURF = CWLSurfaceResource::fromResource(surface); - if (!SURF) { + if UNLIKELY (!SURF) { pMgr->error(-1, "Invalid surface"); return; } - if (SURF->role->role() != SURFACE_ROLE_UNASSIGNED) { + if UNLIKELY (SURF->role->role() != SURFACE_ROLE_UNASSIGNED) { pMgr->error(-1, "Surface already has a different role"); return; } const auto RESOURCE = m_vLayers.emplace_back(makeShared(makeShared(CLIENT, pMgr->version(), id), SURF, namespace_, PMONITOR, layer)); - if (!RESOURCE->good()) { + if UNLIKELY (!RESOURCE->good()) { pMgr->noMemory(); m_vLayers.pop_back(); return; diff --git a/src/protocols/LinuxDMABUF.cpp b/src/protocols/LinuxDMABUF.cpp index 24b8f62c..85f7b1c6 100644 --- a/src/protocols/LinuxDMABUF.cpp +++ b/src/protocols/LinuxDMABUF.cpp @@ -126,7 +126,7 @@ bool CLinuxDMABuffer::good() { } CLinuxDMABBUFParamsResource::CLinuxDMABBUFParamsResource(SP resource_) : resource(resource_) { - if (!good()) + if UNLIKELY (!good()) return; resource->setOnDestroy([this](CZwpLinuxBufferParamsV1* r) { PROTO::linuxDma->destroyResource(this); }); @@ -208,12 +208,12 @@ bool CLinuxDMABBUFParamsResource::good() { void CLinuxDMABBUFParamsResource::create(uint32_t id) { used = true; - if (!verify()) { + if UNLIKELY (!verify()) { LOGM(ERR, "Failed creating a dmabuf: verify() said no"); return; // if verify failed, we errored the resource. } - if (!commence()) { + if UNLIKELY (!commence()) { LOGM(ERR, "Failed creating a dmabuf: commence() said no"); resource->sendFailed(); return; @@ -226,7 +226,7 @@ void CLinuxDMABBUFParamsResource::create(uint32_t id) { auto buf = PROTO::linuxDma->m_vBuffers.emplace_back(makeShared(id, resource->client(), *attrs)); - if (!buf->good() || !buf->buffer->success) { + if UNLIKELY (!buf->good() || !buf->buffer->success) { resource->sendFailed(); return; } @@ -259,12 +259,12 @@ bool CLinuxDMABBUFParamsResource::commence() { } bool CLinuxDMABBUFParamsResource::verify() { - if (attrs->planes <= 0) { + if UNLIKELY (attrs->planes <= 0) { resource->error(ZWP_LINUX_BUFFER_PARAMS_V1_ERROR_INCOMPLETE, "No planes added"); return false; } - if (attrs->fds.at(0) < 0) { + if UNLIKELY (attrs->fds.at(0) < 0) { resource->error(ZWP_LINUX_BUFFER_PARAMS_V1_ERROR_INCOMPLETE, "No plane 0"); return false; } @@ -282,7 +282,7 @@ bool CLinuxDMABBUFParamsResource::verify() { } } - if (attrs->size.x < 1 || attrs->size.y < 1) { + if UNLIKELY (attrs->size.x < 1 || attrs->size.y < 1) { resource->error(ZWP_LINUX_BUFFER_PARAMS_V1_ERROR_INVALID_DIMENSIONS, "x/y < 1"); return false; } @@ -300,7 +300,7 @@ bool CLinuxDMABBUFParamsResource::verify() { } CLinuxDMABUFFeedbackResource::CLinuxDMABUFFeedbackResource(SP resource_, SP surface_) : surface(surface_), resource(resource_) { - if (!good()) + if UNLIKELY (!good()) return; resource->setOnDestroy([this](CZwpLinuxDmabufFeedbackV1* r) { PROTO::linuxDma->destroyResource(this); }); @@ -355,7 +355,7 @@ void CLinuxDMABUFFeedbackResource::sendDefaultFeedback() { } CLinuxDMABUFResource::CLinuxDMABUFResource(SP resource_) : resource(resource_) { - if (!good()) + if UNLIKELY (!good()) return; resource->setOnDestroy([this](CZwpLinuxDmabufV1* r) { PROTO::linuxDma->destroyResource(this); }); @@ -365,7 +365,7 @@ CLinuxDMABUFResource::CLinuxDMABUFResource(SP resource_) : re const auto RESOURCE = PROTO::linuxDma->m_vFeedbacks.emplace_back(makeShared(makeShared(r->client(), r->version(), id), nullptr)); - if (!RESOURCE->good()) { + if UNLIKELY (!RESOURCE->good()) { r->noMemory(); PROTO::linuxDma->m_vFeedbacks.pop_back(); return; @@ -376,7 +376,7 @@ CLinuxDMABUFResource::CLinuxDMABUFResource(SP resource_) : re const auto RESOURCE = PROTO::linuxDma->m_vFeedbacks.emplace_back( makeShared(makeShared(r->client(), r->version(), id), CWLSurfaceResource::fromResource(surf))); - if (!RESOURCE->good()) { + if UNLIKELY (!RESOURCE->good()) { r->noMemory(); PROTO::linuxDma->m_vFeedbacks.pop_back(); return; @@ -386,7 +386,7 @@ CLinuxDMABUFResource::CLinuxDMABUFResource(SP resource_) : re resource->setCreateParams([](CZwpLinuxDmabufV1* r, uint32_t id) { const auto RESOURCE = PROTO::linuxDma->m_vParams.emplace_back(makeShared(makeShared(r->client(), r->version(), id))); - if (!RESOURCE->good()) { + if UNLIKELY (!RESOURCE->good()) { r->noMemory(); PROTO::linuxDma->m_vParams.pop_back(); return; @@ -535,7 +535,7 @@ CLinuxDMABufV1Protocol::~CLinuxDMABufV1Protocol() { void CLinuxDMABufV1Protocol::bindManager(wl_client* client, void* data, uint32_t ver, uint32_t id) { const auto RESOURCE = m_vManagers.emplace_back(makeShared(makeShared(client, ver, id))); - if (!RESOURCE->good()) { + if UNLIKELY (!RESOURCE->good()) { wl_client_post_no_memory(client); m_vManagers.pop_back(); return; diff --git a/src/protocols/MesaDRM.cpp b/src/protocols/MesaDRM.cpp index 41536988..caa539a2 100644 --- a/src/protocols/MesaDRM.cpp +++ b/src/protocols/MesaDRM.cpp @@ -35,7 +35,7 @@ bool CMesaDRMBufferResource::good() { } CMesaDRMResource::CMesaDRMResource(SP resource_) : resource(resource_) { - if (!good()) + if UNLIKELY (!good()) return; resource->setOnDestroy([this](CWlDrm* r) { PROTO::mesaDRM->destroyResource(this); }); @@ -87,7 +87,7 @@ CMesaDRMResource::CMesaDRMResource(SP resource_) : resource(resource_) { const auto RESOURCE = PROTO::mesaDRM->m_vBuffers.emplace_back(makeShared(id, resource->client(), attrs)); - if (!RESOURCE->good()) { + if UNLIKELY (!RESOURCE->good()) { r->noMemory(); PROTO::mesaDRM->m_vBuffers.pop_back(); return; @@ -140,7 +140,7 @@ CMesaDRMProtocol::CMesaDRMProtocol(const wl_interface* iface, const int& ver, co void CMesaDRMProtocol::bindManager(wl_client* client, void* data, uint32_t ver, uint32_t id) { const auto RESOURCE = m_vManagers.emplace_back(makeShared(makeShared(client, ver, id))); - if (!RESOURCE->good()) { + if UNLIKELY (!RESOURCE->good()) { wl_client_post_no_memory(client); m_vManagers.pop_back(); return; diff --git a/src/protocols/OutputManagement.cpp b/src/protocols/OutputManagement.cpp index 4a976021..ecca0c48 100644 --- a/src/protocols/OutputManagement.cpp +++ b/src/protocols/OutputManagement.cpp @@ -8,7 +8,7 @@ using namespace Aquamarine; COutputManager::COutputManager(SP resource_) : resource(resource_) { - if (!good()) + if UNLIKELY (!good()) return; LOGM(LOG, "New OutputManager registered"); @@ -23,7 +23,7 @@ COutputManager::COutputManager(SP resource_) : resource(re const auto RESOURCE = PROTO::outputManagement->m_vConfigurations.emplace_back( makeShared(makeShared(resource->client(), resource->version(), id), self.lock())); - if (!RESOURCE->good()) { + if UNLIKELY (!RESOURCE->good()) { resource->noMemory(); PROTO::outputManagement->m_vConfigurations.pop_back(); return; @@ -48,13 +48,13 @@ bool COutputManager::good() { } void COutputManager::makeAndSendNewHead(PHLMONITOR pMonitor) { - if (stopped) + if UNLIKELY (stopped) return; const auto RESOURCE = PROTO::outputManagement->m_vHeads.emplace_back(makeShared(makeShared(resource->client(), resource->version(), 0), pMonitor)); - if (!RESOURCE->good()) { + if UNLIKELY (!RESOURCE->good()) { resource->noMemory(); PROTO::outputManagement->m_vHeads.pop_back(); return; @@ -90,7 +90,7 @@ void COutputManager::sendDone() { } COutputHead::COutputHead(SP resource_, PHLMONITOR pMonitor_) : resource(resource_), pMonitor(pMonitor_) { - if (!good()) + if UNLIKELY (!good()) return; resource->setRelease([this](CZwlrOutputHeadV1* r) { PROTO::outputManagement->destroyResource(this); }); @@ -213,7 +213,7 @@ void COutputHead::updateMode() { void COutputHead::makeAndSendNewMode(SP mode) { const auto RESOURCE = PROTO::outputManagement->m_vModes.emplace_back(makeShared(makeShared(resource->client(), resource->version(), 0), mode)); - if (!RESOURCE->good()) { + if UNLIKELY (!RESOURCE->good()) { resource->noMemory(); PROTO::outputManagement->m_vModes.pop_back(); return; @@ -229,7 +229,7 @@ PHLMONITOR COutputHead::monitor() { } COutputMode::COutputMode(SP resource_, SP mode_) : resource(resource_), mode(mode_) { - if (!good()) + if UNLIKELY (!good()) return; resource->setRelease([this](CZwlrOutputModeV1* r) { PROTO::outputManagement->destroyResource(this); }); @@ -258,7 +258,7 @@ SP COutputMode::getMode() { } COutputConfiguration::COutputConfiguration(SP resource_, SP owner_) : resource(resource_), owner(owner_) { - if (!good()) + if UNLIKELY (!good()) return; resource->setDestroy([this](CZwlrOutputConfigurationV1* r) { PROTO::outputManagement->destroyResource(this); }); @@ -282,7 +282,7 @@ COutputConfiguration::COutputConfiguration(SP resour const auto RESOURCE = PROTO::outputManagement->m_vConfigurationHeads.emplace_back( makeShared(makeShared(resource->client(), resource->version(), id), PMONITOR)); - if (!RESOURCE->good()) { + if UNLIKELY (!RESOURCE->good()) { resource->noMemory(); PROTO::outputManagement->m_vConfigurationHeads.pop_back(); return; @@ -428,7 +428,7 @@ bool COutputConfiguration::applyTestConfiguration(bool test) { } COutputConfigurationHead::COutputConfigurationHead(SP resource_, PHLMONITOR pMonitor_) : resource(resource_), pMonitor(pMonitor_) { - if (!good()) + if UNLIKELY (!good()) return; resource->setOnDestroy([this](CZwlrOutputConfigurationHeadV1* r) { PROTO::outputManagement->destroyResource(this); }); @@ -581,7 +581,7 @@ COutputManagementProtocol::COutputManagementProtocol(const wl_interface* iface, void COutputManagementProtocol::bindManager(wl_client* client, void* data, uint32_t ver, uint32_t id) { const auto RESOURCE = m_vManagers.emplace_back(makeShared(makeShared(client, ver, id))); - if (!RESOURCE->good()) { + if UNLIKELY (!RESOURCE->good()) { wl_client_post_no_memory(client); m_vManagers.pop_back(); return; diff --git a/src/protocols/OutputPower.cpp b/src/protocols/OutputPower.cpp index dd3e8e1a..f97babc2 100644 --- a/src/protocols/OutputPower.cpp +++ b/src/protocols/OutputPower.cpp @@ -3,7 +3,7 @@ #include "../helpers/Monitor.hpp" COutputPower::COutputPower(SP resource_, PHLMONITOR pMonitor_) : resource(resource_), pMonitor(pMonitor_) { - if (!resource->resource()) + if UNLIKELY (!resource->resource()) return; resource->setDestroy([this](CZwlrOutputPowerV1* r) { PROTO::outputPower->destroyOutputPower(this); }); @@ -62,7 +62,7 @@ void COutputPowerProtocol::onGetOutputPower(CZwlrOutputPowerManagerV1* pMgr, uin const auto OUTPUT = CWLOutputResource::fromResource(output); - if (!OUTPUT) { + if UNLIKELY (!OUTPUT) { pMgr->error(0, "Invalid output resource"); return; } @@ -70,7 +70,7 @@ void COutputPowerProtocol::onGetOutputPower(CZwlrOutputPowerManagerV1* pMgr, uin const auto CLIENT = pMgr->client(); const auto RESOURCE = m_vOutputPowers.emplace_back(std::make_unique(makeShared(CLIENT, pMgr->version(), id), OUTPUT->monitor.lock())).get(); - if (!RESOURCE->good()) { + if UNLIKELY (!RESOURCE->good()) { pMgr->noMemory(); m_vOutputPowers.pop_back(); return; diff --git a/src/protocols/PointerConstraints.cpp b/src/protocols/PointerConstraints.cpp index e12fa75f..c0531799 100644 --- a/src/protocols/PointerConstraints.cpp +++ b/src/protocols/PointerConstraints.cpp @@ -10,7 +10,7 @@ CPointerConstraint::CPointerConstraint(SP resource_, SP surf, wl_resource* region_, zwpPointerConstraintsV1Lifetime lifetime_) : resourceL(resource_), locked(true), lifetime(lifetime_) { - if (!resource_->resource()) + if UNLIKELY (!resource_->resource()) return; resource_->setOnDestroy([this](CZwpLockedPointerV1* p) { PROTO::constraints->destroyPointerConstraint(this); }); @@ -49,7 +49,7 @@ CPointerConstraint::CPointerConstraint(SP resource_, SP resource_, SP surf, wl_resource* region_, zwpPointerConstraintsV1Lifetime lifetime_) : resourceC(resource_), lifetime(lifetime_) { - if (!resource_->resource()) + if UNLIKELY (!resource_->resource()) return; resource_->setOnDestroy([this](CZwpConfinedPointerV1* p) { PROTO::constraints->destroyPointerConstraint(this); }); @@ -185,7 +185,7 @@ bool CPointerConstraint::isLocked() { } Vector2D CPointerConstraint::logicPositionHint() { - if (!pHLSurface) + if UNLIKELY (!pHLSurface) return {}; const auto SURFBOX = pHLSurface->getSurfaceBoxGlobal(); @@ -218,14 +218,14 @@ void CPointerConstraintsProtocol::destroyPointerConstraint(CPointerConstraint* h } void CPointerConstraintsProtocol::onNewConstraint(SP constraint, CZwpPointerConstraintsV1* pMgr) { - if (!constraint->good()) { + if UNLIKELY (!constraint->good()) { LOGM(ERR, "Couldn't create constraint??"); pMgr->noMemory(); m_vConstraints.pop_back(); return; } - if (!constraint->owner()) { + if UNLIKELY (!constraint->owner()) { LOGM(ERR, "New constraint has no CWLSurface owner??"); return; } @@ -234,7 +234,7 @@ void CPointerConstraintsProtocol::onNewConstraint(SP constra const auto DUPES = std::count_if(m_vConstraints.begin(), m_vConstraints.end(), [OWNER](const auto& c) { return c->owner() == OWNER; }); - if (DUPES > 1) { + if UNLIKELY (DUPES > 1) { LOGM(ERR, "Constraint for surface duped"); pMgr->error(ZWP_POINTER_CONSTRAINTS_V1_ERROR_ALREADY_CONSTRAINED, "Surface already confined"); m_vConstraints.pop_back(); diff --git a/src/protocols/PointerGestures.cpp b/src/protocols/PointerGestures.cpp index 5dfb9d51..4df51b47 100644 --- a/src/protocols/PointerGestures.cpp +++ b/src/protocols/PointerGestures.cpp @@ -4,7 +4,7 @@ #include "core/Compositor.hpp" CPointerGestureSwipe::CPointerGestureSwipe(SP resource_) : resource(resource_) { - if (!resource->resource()) + if UNLIKELY (!resource->resource()) return; resource->setOnDestroy([this](CZwpPointerGestureSwipeV1* p) { PROTO::pointerGestures->onGestureDestroy(this); }); @@ -16,7 +16,7 @@ bool CPointerGestureSwipe::good() { } CPointerGestureHold::CPointerGestureHold(SP resource_) : resource(resource_) { - if (!resource->resource()) + if UNLIKELY (!resource->resource()) return; resource->setOnDestroy([this](CZwpPointerGestureHoldV1* p) { PROTO::pointerGestures->onGestureDestroy(this); }); @@ -28,7 +28,7 @@ bool CPointerGestureHold::good() { } CPointerGesturePinch::CPointerGesturePinch(SP resource_) : resource(resource_) { - if (!resource->resource()) + if UNLIKELY (!resource->resource()) return; resource->setOnDestroy([this](CZwpPointerGesturePinchV1* p) { PROTO::pointerGestures->onGestureDestroy(this); }); @@ -73,7 +73,7 @@ void CPointerGesturesProtocol::onGetPinchGesture(CZwpPointerGesturesV1* pMgr, ui const auto CLIENT = pMgr->client(); const auto RESOURCE = m_vPinches.emplace_back(std::make_unique(makeShared(CLIENT, pMgr->version(), id))).get(); - if (!RESOURCE->good()) { + if UNLIKELY (!RESOURCE->good()) { pMgr->noMemory(); LOGM(ERR, "Couldn't create gesture"); return; @@ -84,7 +84,7 @@ void CPointerGesturesProtocol::onGetSwipeGesture(CZwpPointerGesturesV1* pMgr, ui const auto CLIENT = pMgr->client(); const auto RESOURCE = m_vSwipes.emplace_back(std::make_unique(makeShared(CLIENT, pMgr->version(), id))).get(); - if (!RESOURCE->good()) { + if UNLIKELY (!RESOURCE->good()) { pMgr->noMemory(); LOGM(ERR, "Couldn't create gesture"); return; @@ -95,7 +95,7 @@ void CPointerGesturesProtocol::onGetHoldGesture(CZwpPointerGesturesV1* pMgr, uin const auto CLIENT = pMgr->client(); const auto RESOURCE = m_vHolds.emplace_back(std::make_unique(makeShared(CLIENT, pMgr->version(), id))).get(); - if (!RESOURCE->good()) { + if UNLIKELY (!RESOURCE->good()) { pMgr->noMemory(); LOGM(ERR, "Couldn't create gesture"); return; diff --git a/src/protocols/PresentationTime.cpp b/src/protocols/PresentationTime.cpp index 411036c3..1654041c 100644 --- a/src/protocols/PresentationTime.cpp +++ b/src/protocols/PresentationTime.cpp @@ -27,7 +27,7 @@ void CQueuedPresentationData::discarded() { } CPresentationFeedback::CPresentationFeedback(SP resource_, SP surf) : resource(resource_), surface(surf) { - if (!good()) + if UNLIKELY (!good()) return; resource->setOnDestroy([this](CWpPresentationFeedback* pMgr) { @@ -43,8 +43,8 @@ bool CPresentationFeedback::good() { void CPresentationFeedback::sendQueued(SP data, timespec* when, uint32_t untilRefreshNs, uint64_t seq, uint32_t reportedFlags) { auto client = resource->client(); - if (PROTO::outputs.contains(data->pMonitor->szName)) { - if (auto outputResource = PROTO::outputs.at(data->pMonitor->szName)->outputResourceFrom(client); outputResource) + if LIKELY (PROTO::outputs.contains(data->pMonitor->szName)) { + if LIKELY (auto outputResource = PROTO::outputs.at(data->pMonitor->szName)->outputResourceFrom(client); outputResource) resource->sendSyncOutput(outputResource->getResource()->resource()); } @@ -100,7 +100,7 @@ void CPresentationProtocol::onGetFeedback(CWpPresentation* pMgr, wl_resource* su m_vFeedbacks.emplace_back(makeShared(makeShared(CLIENT, pMgr->version(), id), CWLSurfaceResource::fromResource(surf))) .get(); - if (!RESOURCE->good()) { + if UNLIKELY (!RESOURCE->good()) { pMgr->noMemory(); m_vFeedbacks.pop_back(); return; diff --git a/src/protocols/PrimarySelection.cpp b/src/protocols/PrimarySelection.cpp index ecc4ee71..567bfdd2 100644 --- a/src/protocols/PrimarySelection.cpp +++ b/src/protocols/PrimarySelection.cpp @@ -5,7 +5,7 @@ #include "../config/ConfigValue.hpp" CPrimarySelectionOffer::CPrimarySelectionOffer(SP resource_, SP source_) : source(source_), resource(resource_) { - if (!good()) + if UNLIKELY (!good()) return; resource->setDestroy([this](CZwpPrimarySelectionOfferV1* r) { PROTO::primarySelection->destroyResource(this); }); @@ -35,7 +35,7 @@ bool CPrimarySelectionOffer::good() { } void CPrimarySelectionOffer::sendData() { - if (!source) + if UNLIKELY (!source) return; for (auto const& m : source->mimes()) { @@ -44,7 +44,7 @@ void CPrimarySelectionOffer::sendData() { } CPrimarySelectionSource::CPrimarySelectionSource(SP resource_, SP device_) : device(device_), resource(resource_) { - if (!good()) + if UNLIKELY (!good()) return; resource->setData(this); @@ -105,7 +105,7 @@ void CPrimarySelectionSource::error(uint32_t code, const std::string& msg) { } CPrimarySelectionDevice::CPrimarySelectionDevice(SP resource_) : resource(resource_) { - if (!good()) + if UNLIKELY (!good()) return; pClient = resource->client(); @@ -159,7 +159,7 @@ void CPrimarySelectionDevice::sendSelection(SP selection } CPrimarySelectionManager::CPrimarySelectionManager(SP resource_) : resource(resource_) { - if (!good()) + if UNLIKELY (!good()) return; resource->setOnDestroy([this](CZwpPrimarySelectionDeviceManagerV1* r) { PROTO::primarySelection->destroyResource(this); }); @@ -168,7 +168,7 @@ CPrimarySelectionManager::CPrimarySelectionManager(SPm_vDevices.emplace_back(makeShared(makeShared(r->client(), r->version(), id))); - if (!RESOURCE->good()) { + if UNLIKELY (!RESOURCE->good()) { r->noMemory(); PROTO::primarySelection->m_vDevices.pop_back(); return; @@ -192,7 +192,7 @@ CPrimarySelectionManager::CPrimarySelectionManager(SPm_vSources.emplace_back( makeShared(makeShared(r->client(), r->version(), id), device.lock())); - if (!RESOURCE->good()) { + if UNLIKELY (!RESOURCE->good()) { r->noMemory(); PROTO::primarySelection->m_vSources.pop_back(); return; @@ -220,7 +220,7 @@ CPrimarySelectionProtocol::CPrimarySelectionProtocol(const wl_interface* iface, void CPrimarySelectionProtocol::bindManager(wl_client* client, void* data, uint32_t ver, uint32_t id) { const auto RESOURCE = m_vManagers.emplace_back(makeShared(makeShared(client, ver, id))); - if (!RESOURCE->good()) { + if UNLIKELY (!RESOURCE->good()) { wl_client_post_no_memory(client); m_vManagers.pop_back(); return; diff --git a/src/protocols/RelativePointer.cpp b/src/protocols/RelativePointer.cpp index b7cf75c6..842af894 100644 --- a/src/protocols/RelativePointer.cpp +++ b/src/protocols/RelativePointer.cpp @@ -4,7 +4,7 @@ #include CRelativePointer::CRelativePointer(SP resource_) : resource(resource_) { - if (!resource_->resource()) + if UNLIKELY (!resource_->resource()) return; pClient = resource->client(); @@ -50,7 +50,7 @@ void CRelativePointerProtocol::onGetRelativePointer(CZwpRelativePointerManagerV1 const auto CLIENT = pMgr->client(); const auto RESOURCE = m_vRelativePointers.emplace_back(std::make_unique(makeShared(CLIENT, pMgr->version(), id))).get(); - if (!RESOURCE->good()) { + if UNLIKELY (!RESOURCE->good()) { pMgr->noMemory(); m_vRelativePointers.pop_back(); return; diff --git a/src/protocols/Screencopy.cpp b/src/protocols/Screencopy.cpp index da0a9412..8bdaf8f9 100644 --- a/src/protocols/Screencopy.cpp +++ b/src/protocols/Screencopy.cpp @@ -19,7 +19,7 @@ CScreencopyFrame::~CScreencopyFrame() { } CScreencopyFrame::CScreencopyFrame(SP resource_, int32_t overlay_cursor, wl_resource* output, CBox box_) : resource(resource_) { - if (!good()) + if UNLIKELY (!good()) return; overlayCursor = !!overlay_cursor; @@ -77,21 +77,20 @@ CScreencopyFrame::CScreencopyFrame(SP resource_, int32_t resource->sendBuffer(NFormatUtils::drmToShm(shmFormat), box.width, box.height, shmStride); if (resource->version() >= 3) { - if (dmabufFormat != DRM_FORMAT_INVALID) { + if LIKELY (dmabufFormat != DRM_FORMAT_INVALID) resource->sendLinuxDmabuf(dmabufFormat, box.width, box.height); - } resource->sendBufferDone(); } } void CScreencopyFrame::copy(CZwlrScreencopyFrameV1* pFrame, wl_resource* buffer_) { - if (!good()) { + if UNLIKELY (!good()) { LOGM(ERR, "No frame in copyFrame??"); return; } - if (!g_pCompositor->monitorExists(pMonitor.lock())) { + if UNLIKELY (!g_pCompositor->monitorExists(pMonitor.lock())) { LOGM(ERR, "Client requested sharing of a monitor that is gone"); resource->sendFailed(); PROTO::screencopy->destroyResource(this); @@ -99,7 +98,7 @@ void CScreencopyFrame::copy(CZwlrScreencopyFrameV1* pFrame, wl_resource* buffer_ } const auto PBUFFER = CWLBufferResource::fromResource(buffer_); - if (!PBUFFER) { + if UNLIKELY (!PBUFFER) { LOGM(ERR, "Invalid buffer in {:x}", (uintptr_t)this); resource->error(ZWLR_SCREENCOPY_FRAME_V1_ERROR_INVALID_BUFFER, "invalid buffer"); PROTO::screencopy->destroyResource(this); @@ -108,14 +107,14 @@ void CScreencopyFrame::copy(CZwlrScreencopyFrameV1* pFrame, wl_resource* buffer_ PBUFFER->buffer->lock(); - if (PBUFFER->buffer->size != box.size()) { + if UNLIKELY (PBUFFER->buffer->size != box.size()) { LOGM(ERR, "Invalid dimensions in {:x}", (uintptr_t)this); resource->error(ZWLR_SCREENCOPY_FRAME_V1_ERROR_INVALID_BUFFER, "invalid buffer dimensions"); PROTO::screencopy->destroyResource(this); return; } - if (buffer) { + if UNLIKELY (buffer) { LOGM(ERR, "Buffer used in {:x}", (uintptr_t)this); resource->error(ZWLR_SCREENCOPY_FRAME_V1_ERROR_ALREADY_USED, "frame already used"); PROTO::screencopy->destroyResource(this); @@ -308,7 +307,7 @@ CScreencopyClient::~CScreencopyClient() { } CScreencopyClient::CScreencopyClient(SP resource_) : resource(resource_) { - if (!good()) + if UNLIKELY (!good()) return; resource->setDestroy([this](CZwlrScreencopyManagerV1* pMgr) { PROTO::screencopy->destroyResource(this); }); diff --git a/src/protocols/SecurityContext.cpp b/src/protocols/SecurityContext.cpp index 0818907f..e5b3cf2a 100644 --- a/src/protocols/SecurityContext.cpp +++ b/src/protocols/SecurityContext.cpp @@ -49,7 +49,7 @@ void CSecurityContextSandboxedClient::onDestroy() { } CSecurityContext::CSecurityContext(SP resource_, int listenFD_, int closeFD_) : listenFD(listenFD_), closeFD(closeFD_), resource(resource_) { - if (!good()) + if UNLIKELY (!good()) return; resource->setDestroy([this](CWpSecurityContextV1* r) { @@ -64,12 +64,12 @@ CSecurityContext::CSecurityContext(SP resource_, int liste LOGM(LOG, "New security_context at 0x{:x}", (uintptr_t)this); resource->setSetSandboxEngine([this](CWpSecurityContextV1* r, const char* engine) { - if (!sandboxEngine.empty()) { + if UNLIKELY (!sandboxEngine.empty()) { r->error(WP_SECURITY_CONTEXT_V1_ERROR_ALREADY_SET, "Sandbox engine already set"); return; } - if (committed) { + if UNLIKELY (committed) { r->error(WP_SECURITY_CONTEXT_V1_ERROR_ALREADY_USED, "Context already committed"); return; } @@ -79,12 +79,12 @@ CSecurityContext::CSecurityContext(SP resource_, int liste }); resource->setSetAppId([this](CWpSecurityContextV1* r, const char* appid) { - if (!appID.empty()) { + if UNLIKELY (!appID.empty()) { r->error(WP_SECURITY_CONTEXT_V1_ERROR_ALREADY_SET, "Sandbox appid already set"); return; } - if (committed) { + if UNLIKELY (committed) { r->error(WP_SECURITY_CONTEXT_V1_ERROR_ALREADY_USED, "Context already committed"); return; } @@ -94,12 +94,12 @@ CSecurityContext::CSecurityContext(SP resource_, int liste }); resource->setSetInstanceId([this](CWpSecurityContextV1* r, const char* instance) { - if (!instanceID.empty()) { + if UNLIKELY (!instanceID.empty()) { r->error(WP_SECURITY_CONTEXT_V1_ERROR_ALREADY_SET, "Sandbox instance already set"); return; } - if (committed) { + if UNLIKELY (committed) { r->error(WP_SECURITY_CONTEXT_V1_ERROR_ALREADY_USED, "Context already committed"); return; } @@ -135,7 +135,7 @@ bool CSecurityContext::good() { } void CSecurityContext::onListen(uint32_t mask) { - if (mask & (WL_EVENT_HANGUP | WL_EVENT_ERROR)) { + if UNLIKELY (mask & (WL_EVENT_HANGUP | WL_EVENT_ERROR)) { LOGM(ERR, "security_context at 0x{:x} got an error in listen", (uintptr_t)this); PROTO::securityContext->destroyContext(this); return; @@ -145,13 +145,13 @@ void CSecurityContext::onListen(uint32_t mask) { return; int clientFD = accept(listenFD, nullptr, nullptr); - if (clientFD < 0) { + if UNLIKELY (clientFD < 0) { LOGM(ERR, "security_context at 0x{:x} couldn't accept", (uintptr_t)this); return; } auto newClient = CSecurityContextSandboxedClient::create(clientFD); - if (!newClient) { + if UNLIKELY (!newClient) { LOGM(ERR, "security_context at 0x{:x} couldn't create a client", (uintptr_t)this); close(clientFD); return; @@ -170,7 +170,7 @@ void CSecurityContext::onClose(uint32_t mask) { } CSecurityContextManagerResource::CSecurityContextManagerResource(SP resource_) : resource(resource_) { - if (!good()) + if UNLIKELY (!good()) return; resource->setDestroy([this](CWpSecurityContextManagerV1* r) { PROTO::securityContext->destroyResource(this); }); @@ -180,7 +180,7 @@ CSecurityContextManagerResource::CSecurityContextManagerResource(SPm_vContexts.emplace_back(makeShared(makeShared(r->client(), r->version(), id), lfd, cfd)); - if (!RESOURCE->good()) { + if UNLIKELY (!RESOURCE->good()) { r->noMemory(); PROTO::securityContext->m_vContexts.pop_back(); return; @@ -199,7 +199,7 @@ CSecurityContextProtocol::CSecurityContextProtocol(const wl_interface* iface, co void CSecurityContextProtocol::bindManager(wl_client* client, void* data, uint32_t ver, uint32_t id) { const auto RESOURCE = m_vManagers.emplace_back(makeShared(makeShared(client, ver, id))); - if (!RESOURCE->good()) { + if UNLIKELY (!RESOURCE->good()) { wl_client_post_no_memory(client); m_vManagers.pop_back(); return; diff --git a/src/protocols/ServerDecorationKDE.cpp b/src/protocols/ServerDecorationKDE.cpp index c7b98a9c..3e33db52 100644 --- a/src/protocols/ServerDecorationKDE.cpp +++ b/src/protocols/ServerDecorationKDE.cpp @@ -2,7 +2,7 @@ #include "core/Compositor.hpp" CServerDecorationKDE::CServerDecorationKDE(SP resource_, SP surf) : resource(resource_) { - if (!good()) + if UNLIKELY (!good()) return; resource->setRelease([this](COrgKdeKwinServerDecoration* pMgr) { PROTO::serverDecorationKDE->destroyResource(this); }); @@ -44,7 +44,7 @@ void CServerDecorationKDEProtocol::createDecoration(COrgKdeKwinServerDecorationM m_vDecos.emplace_back(std::make_unique(makeShared(CLIENT, pMgr->version(), id), CWLSurfaceResource::fromResource(surf))) .get(); - if (!RESOURCE->good()) { + if UNLIKELY (!RESOURCE->good()) { pMgr->noMemory(); m_vDecos.pop_back(); return; diff --git a/src/protocols/SessionLock.cpp b/src/protocols/SessionLock.cpp index c3f19e53..db65ee5f 100644 --- a/src/protocols/SessionLock.cpp +++ b/src/protocols/SessionLock.cpp @@ -8,7 +8,7 @@ CSessionLockSurface::CSessionLockSurface(SP resource_, SP surface_, PHLMONITOR pMonitor_, WP owner_) : resource(resource_), sessionLock(owner_), pSurface(surface_), pMonitor(pMonitor_) { - if (!resource->resource()) + if UNLIKELY (!resource->resource()) return; resource->setDestroy([this](CExtSessionLockSurfaceV1* r) { @@ -92,7 +92,7 @@ SP CSessionLockSurface::surface() { } CSessionLock::CSessionLock(SP resource_) : resource(resource_) { - if (!resource->resource()) + if UNLIKELY (!resource->resource()) return; resource->setDestroy([this](CExtSessionLockV1* r) { PROTO::sessionLock->destroyResource(this); }); @@ -170,7 +170,7 @@ void CSessionLockProtocol::onLock(CExtSessionLockManagerV1* pMgr, uint32_t id) { const auto CLIENT = pMgr->client(); const auto RESOURCE = m_vLocks.emplace_back(makeShared(makeShared(CLIENT, pMgr->version(), id))); - if (!RESOURCE->good()) { + if UNLIKELY (!RESOURCE->good()) { pMgr->noMemory(); m_vLocks.pop_back(); return; @@ -198,7 +198,7 @@ void CSessionLockProtocol::onGetLockSurface(CExtSessionLockV1* lock, uint32_t id const auto RESOURCE = m_vLockSurfaces.emplace_back(makeShared(makeShared(lock->client(), lock->version(), id), PSURFACE, PMONITOR, sessionLock)); - if (!RESOURCE->good()) { + if UNLIKELY (!RESOURCE->good()) { lock->noMemory(); m_vLockSurfaces.pop_back(); return; diff --git a/src/protocols/ShortcutsInhibit.cpp b/src/protocols/ShortcutsInhibit.cpp index 308b385d..a0d29f92 100644 --- a/src/protocols/ShortcutsInhibit.cpp +++ b/src/protocols/ShortcutsInhibit.cpp @@ -4,7 +4,7 @@ #include "core/Compositor.hpp" CKeyboardShortcutsInhibitor::CKeyboardShortcutsInhibitor(SP resource_, SP surf) : resource(resource_), pSurface(surf) { - if (!resource->resource()) + if UNLIKELY (!resource->resource()) return; resource->setDestroy([this](CZwpKeyboardShortcutsInhibitorV1* pMgr) { PROTO::shortcutsInhibit->destroyInhibitor(this); }); @@ -49,7 +49,7 @@ void CKeyboardShortcutsInhibitProtocol::onInhibit(CZwpKeyboardShortcutsInhibitMa const auto CLIENT = pMgr->client(); for (auto const& in : m_vInhibitors) { - if (in->surface() != surf) + if LIKELY (in->surface() != surf) continue; pMgr->error(ZWP_KEYBOARD_SHORTCUTS_INHIBIT_MANAGER_V1_ERROR_ALREADY_INHIBITED, "Already inhibited for surface resource"); @@ -59,7 +59,7 @@ void CKeyboardShortcutsInhibitProtocol::onInhibit(CZwpKeyboardShortcutsInhibitMa const auto RESOURCE = m_vInhibitors.emplace_back(std::make_unique(makeShared(CLIENT, pMgr->version(), id), surf)).get(); - if (!RESOURCE->good()) { + if UNLIKELY (!RESOURCE->good()) { pMgr->noMemory(); m_vInhibitors.pop_back(); LOGM(ERR, "Failed to create an inhibitor resource"); diff --git a/src/protocols/SinglePixel.cpp b/src/protocols/SinglePixel.cpp index 91154671..2fbfc93d 100644 --- a/src/protocols/SinglePixel.cpp +++ b/src/protocols/SinglePixel.cpp @@ -63,7 +63,7 @@ bool CSinglePixelBuffer::good() { CSinglePixelBufferResource::CSinglePixelBufferResource(uint32_t id, wl_client* client, CHyprColor color) { buffer = makeShared(id, client, color); - if (!buffer->good()) + if UNLIKELY (!buffer->good()) return; buffer->resource->buffer = buffer; @@ -83,7 +83,7 @@ bool CSinglePixelBufferResource::good() { } CSinglePixelBufferManagerResource::CSinglePixelBufferManagerResource(SP resource_) : resource(resource_) { - if (!good()) + if UNLIKELY (!good()) return; resource->setDestroy([this](CWpSinglePixelBufferManagerV1* r) { PROTO::singlePixel->destroyResource(this); }); @@ -94,7 +94,7 @@ CSinglePixelBufferManagerResource::CSinglePixelBufferManagerResource(SP::max()}; const auto RESOURCE = PROTO::singlePixel->m_vBuffers.emplace_back(makeShared(id, resource->client(), color)); - if (!RESOURCE->good()) { + if UNLIKELY (!RESOURCE->good()) { res->noMemory(); PROTO::singlePixel->m_vBuffers.pop_back(); return; @@ -113,7 +113,7 @@ CSinglePixelProtocol::CSinglePixelProtocol(const wl_interface* iface, const int& void CSinglePixelProtocol::bindManager(wl_client* client, void* data, uint32_t ver, uint32_t id) { const auto RESOURCE = m_vManagers.emplace_back(makeShared(makeShared(client, ver, id))); - if (!RESOURCE->good()) { + if UNLIKELY (!RESOURCE->good()) { wl_client_post_no_memory(client); m_vManagers.pop_back(); return; diff --git a/src/protocols/Tablet.cpp b/src/protocols/Tablet.cpp index 2fdd8731..62e8b2d2 100644 --- a/src/protocols/Tablet.cpp +++ b/src/protocols/Tablet.cpp @@ -9,7 +9,7 @@ #include CTabletPadStripV2Resource::CTabletPadStripV2Resource(SP resource_, uint32_t id_) : id(id_), resource(resource_) { - if (!good()) + if UNLIKELY (!good()) return; resource->setDestroy([this](CZwpTabletPadStripV2* r) { PROTO::tablet->destroyResource(this); }); @@ -21,7 +21,7 @@ bool CTabletPadStripV2Resource::good() { } CTabletPadRingV2Resource::CTabletPadRingV2Resource(SP resource_, uint32_t id_) : id(id_), resource(resource_) { - if (!good()) + if UNLIKELY (!good()) return; resource->setDestroy([this](CZwpTabletPadRingV2* r) { PROTO::tablet->destroyResource(this); }); @@ -33,7 +33,7 @@ bool CTabletPadRingV2Resource::good() { } CTabletPadGroupV2Resource::CTabletPadGroupV2Resource(SP resource_, size_t idx_) : idx(idx_), resource(resource_) { - if (!good()) + if UNLIKELY (!good()) return; resource->setDestroy([this](CZwpTabletPadGroupV2* r) { PROTO::tablet->destroyResource(this); }); @@ -58,7 +58,7 @@ void CTabletPadGroupV2Resource::sendData(SP pad, SPm_vStrips.emplace_back(makeShared(makeShared(resource->client(), resource->version(), 0), i)); - if (!RESOURCE->good()) { + if UNLIKELY (!RESOURCE->good()) { resource->noMemory(); PROTO::tablet->m_vStrips.pop_back(); return; @@ -71,7 +71,7 @@ void CTabletPadGroupV2Resource::sendData(SP pad, SPm_vRings.emplace_back(makeShared(makeShared(resource->client(), resource->version(), 0), i)); - if (!RESOURCE->good()) { + if UNLIKELY (!RESOURCE->good()) { resource->noMemory(); PROTO::tablet->m_vRings.pop_back(); return; @@ -84,7 +84,7 @@ void CTabletPadGroupV2Resource::sendData(SP pad, SP resource_, SP pad_, SP seat_) : pad(pad_), seat(seat_), resource(resource_) { - if (!good()) + if UNLIKELY (!good()) return; resource->setDestroy([this](CZwpTabletPadV2* r) { PROTO::tablet->destroyResource(this); }); @@ -114,7 +114,7 @@ void CTabletPadV2Resource::createGroup(SPm_vGroups.emplace_back(makeShared(makeShared(resource->client(), resource->version(), 0), idx)); - if (!RESOURCE->good()) { + if UNLIKELY (!RESOURCE->good()) { resource->noMemory(); PROTO::tablet->m_vGroups.pop_back(); return; @@ -126,7 +126,7 @@ void CTabletPadV2Resource::createGroup(SP resource_, SP tablet_, SP seat_) : tablet(tablet_), seat(seat_), resource(resource_) { - if (!good()) + if UNLIKELY (!good()) return; resource->setDestroy([this](CZwpTabletV2* r) { PROTO::tablet->destroyResource(this); }); @@ -149,7 +149,7 @@ void CTabletV2Resource::sendData() { } CTabletToolV2Resource::CTabletToolV2Resource(SP resource_, SP tool_, SP seat_) : tool(tool_), seat(seat_), resource(resource_) { - if (!good()) + if UNLIKELY (!good()) return; resource->setDestroy([this](CZwpTabletToolV2* r) { PROTO::tablet->destroyResource(this); }); @@ -228,7 +228,7 @@ void CTabletToolV2Resource::sendFrame(bool removeSource) { } CTabletSeat::CTabletSeat(SP resource_) : resource(resource_) { - if (!good()) + if UNLIKELY (!good()) return; resource->setDestroy([this](CZwpTabletSeatV2* r) { PROTO::tablet->destroyResource(this); }); @@ -243,7 +243,7 @@ void CTabletSeat::sendTool(SP tool) { const auto RESOURCE = PROTO::tablet->m_vTools.emplace_back(makeShared(makeShared(resource->client(), resource->version(), 0), tool, self.lock())); - if (!RESOURCE->good()) { + if UNLIKELY (!RESOURCE->good()) { resource->noMemory(); PROTO::tablet->m_vTools.pop_back(); return; @@ -259,7 +259,7 @@ void CTabletSeat::sendPad(SP pad) { const auto RESOURCE = PROTO::tablet->m_vPads.emplace_back(makeShared(makeShared(resource->client(), resource->version(), 0), pad, self.lock())); - if (!RESOURCE->good()) { + if UNLIKELY (!RESOURCE->good()) { resource->noMemory(); PROTO::tablet->m_vPads.pop_back(); return; @@ -275,7 +275,7 @@ void CTabletSeat::sendTablet(SP tablet) { const auto RESOURCE = PROTO::tablet->m_vTablets.emplace_back(makeShared(makeShared(resource->client(), resource->version(), 0), tablet, self.lock())); - if (!RESOURCE->good()) { + if UNLIKELY (!RESOURCE->good()) { resource->noMemory(); PROTO::tablet->m_vTablets.pop_back(); return; @@ -357,7 +357,7 @@ void CTabletV2Protocol::destroyResource(CTabletPadStripV2Resource* resource) { void CTabletV2Protocol::onGetSeat(CZwpTabletManagerV2* pMgr, uint32_t id, wl_resource* seat) { const auto RESOURCE = m_vSeats.emplace_back(makeShared(makeShared(pMgr->client(), pMgr->version(), id))); - if (!RESOURCE->good()) { + if UNLIKELY (!RESOURCE->good()) { pMgr->noMemory(); m_vSeats.pop_back(); return; diff --git a/src/protocols/TearingControl.cpp b/src/protocols/TearingControl.cpp index eb1a53cb..14c80052 100644 --- a/src/protocols/TearingControl.cpp +++ b/src/protocols/TearingControl.cpp @@ -27,7 +27,7 @@ void CTearingControlProtocol::onManagerResourceDestroy(wl_resource* res) { void CTearingControlProtocol::onGetController(wl_client* client, CWpTearingControlManagerV1* pMgr, uint32_t id, SP surf) { const auto CONTROLLER = m_vTearingControllers.emplace_back(std::make_unique(makeShared(client, pMgr->version(), id), surf)).get(); - if (!CONTROLLER->good()) { + if UNLIKELY (!CONTROLLER->good()) { pMgr->noMemory(); m_vTearingControllers.pop_back(); return; @@ -67,7 +67,7 @@ void CTearingControl::onHint(wpTearingControlV1PresentationHint hint_) { } void CTearingControl::updateWindow() { - if (pWindow.expired()) + if UNLIKELY (pWindow.expired()) return; pWindow->m_bTearingHint = hint == WP_TEARING_CONTROL_V1_PRESENTATION_HINT_ASYNC; diff --git a/src/protocols/TextInputV1.cpp b/src/protocols/TextInputV1.cpp index b8eb5835..4bf5e9e1 100644 --- a/src/protocols/TextInputV1.cpp +++ b/src/protocols/TextInputV1.cpp @@ -7,13 +7,13 @@ CTextInputV1::~CTextInputV1() { } CTextInputV1::CTextInputV1(SP resource_) : resource(resource_) { - if (!good()) + if UNLIKELY (!good()) return; resource->setOnDestroy([this](CZwpTextInputV1* pMgr) { PROTO::textInputV1->destroyResource(this); }); resource->setActivate([this](CZwpTextInputV1* pMgr, wl_resource* seat, wl_resource* surface) { - if (!surface) { + if UNLIKELY (!surface) { LOGM(WARN, "Text-input-v1 PTI{:x}: No surface to activate text input on!", (uintptr_t)this); return; } @@ -105,7 +105,7 @@ void CTextInputV1Protocol::bindManager(wl_client* client, void* data, uint32_t v const auto PTI = m_vClients.emplace_back(makeShared(makeShared(pMgr->client(), pMgr->version(), id))); LOGM(LOG, "New TI V1 at {:x}", (uintptr_t)PTI.get()); - if (!PTI->good()) { + if UNLIKELY (!PTI->good()) { LOGM(ERR, "Could not alloc wl_resource for TIV1"); pMgr->noMemory(); PROTO::textInputV1->destroyResource(PTI.get()); diff --git a/src/protocols/TextInputV3.cpp b/src/protocols/TextInputV3.cpp index 30374104..71ef6dac 100644 --- a/src/protocols/TextInputV3.cpp +++ b/src/protocols/TextInputV3.cpp @@ -10,7 +10,7 @@ void CTextInputV3::SState::reset() { } CTextInputV3::CTextInputV3(SP resource_) : resource(resource_) { - if (!resource->resource()) + if UNLIKELY (!resource->resource()) return; LOGM(LOG, "New tiv3 at {:016x}", (uintptr_t)this); @@ -129,7 +129,7 @@ void CTextInputV3Protocol::onGetTextInput(CZwpTextInputManagerV3* pMgr, uint32_t const auto CLIENT = pMgr->client(); const auto RESOURCE = m_vTextInputs.emplace_back(makeShared(makeShared(CLIENT, pMgr->version(), id))); - if (!RESOURCE->good()) { + if UNLIKELY (!RESOURCE->good()) { pMgr->noMemory(); m_vTextInputs.pop_back(); LOGM(ERR, "Failed to create a tiv3 resource"); diff --git a/src/protocols/ToplevelExport.cpp b/src/protocols/ToplevelExport.cpp index 8e34cf4b..2d40cb78 100644 --- a/src/protocols/ToplevelExport.cpp +++ b/src/protocols/ToplevelExport.cpp @@ -13,7 +13,7 @@ #include CToplevelExportClient::CToplevelExportClient(SP resource_) : resource(resource_) { - if (!good()) + if UNLIKELY (!good()) return; resource->setOnDestroy([this](CHyprlandToplevelExportManagerV1* pMgr) { PROTO::toplevelExport->destroyResource(this); }); @@ -35,7 +35,7 @@ void CToplevelExportClient::captureToplevel(CHyprlandToplevelExportManagerV1* pM const auto FRAME = PROTO::toplevelExport->m_vFrames.emplace_back( makeShared(makeShared(resource->client(), resource->version(), frame), overlayCursor_, handle)); - if (!FRAME->good()) { + if UNLIKELY (!FRAME->good()) { LOGM(ERR, "Couldn't alloc frame for sharing! (no memory)"); resource->noMemory(); PROTO::toplevelExport->destroyResource(FRAME.get()); @@ -78,19 +78,19 @@ CToplevelExportFrame::~CToplevelExportFrame() { } CToplevelExportFrame::CToplevelExportFrame(SP resource_, int32_t overlayCursor_, PHLWINDOW pWindow_) : resource(resource_), pWindow(pWindow_) { - if (!good()) + if UNLIKELY (!good()) return; cursorOverlayRequested = !!overlayCursor_; - if (!pWindow) { + if UNLIKELY (!pWindow) { LOGM(ERR, "Client requested sharing of window handle {:x} which does not exist!", pWindow); resource->sendFailed(); PROTO::toplevelExport->destroyResource(this); return; } - if (!pWindow->m_bIsMapped) { + if UNLIKELY (!pWindow->m_bIsMapped) { LOGM(ERR, "Client requested sharing of window handle {:x} which is not shareable!", pWindow); resource->sendFailed(); PROTO::toplevelExport->destroyResource(this); @@ -106,7 +106,7 @@ CToplevelExportFrame::CToplevelExportFrame(SP re g_pHyprRenderer->makeEGLCurrent(); shmFormat = g_pHyprOpenGL->getPreferredReadFormat(PMONITOR); - if (shmFormat == DRM_FORMAT_INVALID) { + if UNLIKELY (shmFormat == DRM_FORMAT_INVALID) { LOGM(ERR, "No format supported by renderer in capture toplevel"); resource->sendFailed(); PROTO::toplevelExport->destroyResource(this); @@ -114,7 +114,7 @@ CToplevelExportFrame::CToplevelExportFrame(SP re } const auto PSHMINFO = NFormatUtils::getPixelFormatFromDRM(shmFormat); - if (!PSHMINFO) { + if UNLIKELY (!PSHMINFO) { LOGM(ERR, "No pixel format supported by renderer in capture toplevel"); resource->sendFailed(); PROTO::toplevelExport->destroyResource(this); @@ -131,27 +131,26 @@ CToplevelExportFrame::CToplevelExportFrame(SP re resource->sendBuffer(NFormatUtils::drmToShm(shmFormat), box.width, box.height, shmStride); - if (dmabufFormat != DRM_FORMAT_INVALID) { + if LIKELY (dmabufFormat != DRM_FORMAT_INVALID) resource->sendLinuxDmabuf(dmabufFormat, box.width, box.height); - } resource->sendBufferDone(); } void CToplevelExportFrame::copy(CHyprlandToplevelExportFrameV1* pFrame, wl_resource* buffer_, int32_t ignoreDamage) { - if (!good()) { + if UNLIKELY (!good()) { LOGM(ERR, "No frame in copyFrame??"); return; } - if (!validMapped(pWindow)) { + if UNLIKELY (!validMapped(pWindow)) { LOGM(ERR, "Client requested sharing of window handle {:x} which is gone!", pWindow); resource->sendFailed(); PROTO::toplevelExport->destroyResource(this); return; } - if (!pWindow->m_bIsMapped) { + if UNLIKELY (!pWindow->m_bIsMapped) { LOGM(ERR, "Client requested sharing of window handle {:x} which is not shareable (2)!", pWindow); resource->sendFailed(); PROTO::toplevelExport->destroyResource(this); @@ -159,7 +158,7 @@ void CToplevelExportFrame::copy(CHyprlandToplevelExportFrameV1* pFrame, wl_resou } const auto PBUFFER = CWLBufferResource::fromResource(buffer_); - if (!PBUFFER) { + if UNLIKELY (!PBUFFER) { resource->error(HYPRLAND_TOPLEVEL_EXPORT_FRAME_V1_ERROR_INVALID_BUFFER, "invalid buffer"); PROTO::toplevelExport->destroyResource(this); return; @@ -167,13 +166,13 @@ void CToplevelExportFrame::copy(CHyprlandToplevelExportFrameV1* pFrame, wl_resou PBUFFER->buffer->lock(); - if (PBUFFER->buffer->size != box.size()) { + if UNLIKELY (PBUFFER->buffer->size != box.size()) { resource->error(HYPRLAND_TOPLEVEL_EXPORT_FRAME_V1_ERROR_INVALID_BUFFER, "invalid buffer dimensions"); PROTO::toplevelExport->destroyResource(this); return; } - if (buffer) { + if UNLIKELY (buffer) { resource->error(HYPRLAND_TOPLEVEL_EXPORT_FRAME_V1_ERROR_ALREADY_USED, "frame already used"); PROTO::toplevelExport->destroyResource(this); return; diff --git a/src/protocols/Viewporter.cpp b/src/protocols/Viewporter.cpp index 58cb851d..4964bead 100644 --- a/src/protocols/Viewporter.cpp +++ b/src/protocols/Viewporter.cpp @@ -3,14 +3,14 @@ #include CViewportResource::CViewportResource(SP resource_, SP surface_) : surface(surface_), resource(resource_) { - if (!good()) + if UNLIKELY (!good()) return; resource->setDestroy([this](CWpViewport* r) { PROTO::viewport->destroyResource(this); }); resource->setOnDestroy([this](CWpViewport* r) { PROTO::viewport->destroyResource(this); }); resource->setSetDestination([this](CWpViewport* r, int32_t x, int32_t y) { - if (!surface) { + if UNLIKELY (!surface) { r->error(WP_VIEWPORT_ERROR_NO_SURFACE, "Surface is gone"); return; } @@ -20,7 +20,7 @@ CViewportResource::CViewportResource(SP resource_, SPerror(WP_VIEWPORT_ERROR_BAD_SIZE, "Size was <= 0"); return; } @@ -30,7 +30,7 @@ CViewportResource::CViewportResource(SP resource_, SPsetSetSource([this](CWpViewport* r, wl_fixed_t fx, wl_fixed_t fy, wl_fixed_t fw, wl_fixed_t fh) { - if (!surface) { + if UNLIKELY (!surface) { r->error(WP_VIEWPORT_ERROR_NO_SURFACE, "Surface is gone"); return; } @@ -42,7 +42,7 @@ CViewportResource::CViewportResource(SP resource_, SPerror(WP_VIEWPORT_ERROR_BAD_SIZE, "Pos was < 0"); return; } @@ -80,7 +80,7 @@ bool CViewportResource::good() { } CViewporterResource::CViewporterResource(SP resource_) : resource(resource_) { - if (!good()) + if UNLIKELY (!good()) return; resource->setDestroy([this](CWpViewporter* r) { PROTO::viewport->destroyResource(this); }); @@ -90,7 +90,7 @@ CViewporterResource::CViewporterResource(SP resource_) : resource const auto RESOURCE = PROTO::viewport->m_vViewports.emplace_back( makeShared(makeShared(r->client(), r->version(), id), CWLSurfaceResource::fromResource(surf))); - if (!RESOURCE->good()) { + if UNLIKELY (!RESOURCE->good()) { r->noMemory(); PROTO::viewport->m_vViewports.pop_back(); return; @@ -109,7 +109,7 @@ CViewporterProtocol::CViewporterProtocol(const wl_interface* iface, const int& v void CViewporterProtocol::bindManager(wl_client* client, void* data, uint32_t ver, uint32_t id) { const auto RESOURCE = m_vManagers.emplace_back(makeShared(makeShared(client, ver, id))); - if (!RESOURCE->good()) { + if UNLIKELY (!RESOURCE->good()) { wl_client_post_no_memory(client); m_vManagers.pop_back(); return; diff --git a/src/protocols/VirtualKeyboard.cpp b/src/protocols/VirtualKeyboard.cpp index bb51315d..7da1fe01 100644 --- a/src/protocols/VirtualKeyboard.cpp +++ b/src/protocols/VirtualKeyboard.cpp @@ -3,7 +3,7 @@ #include "../devices/IKeyboard.hpp" CVirtualKeyboardV1Resource::CVirtualKeyboardV1Resource(SP resource_) : resource(resource_) { - if (!good()) + if UNLIKELY (!good()) return; resource->setDestroy([this](CZwpVirtualKeyboardV1* r) { @@ -18,7 +18,7 @@ CVirtualKeyboardV1Resource::CVirtualKeyboardV1Resource(SP }); resource->setKey([this](CZwpVirtualKeyboardV1* r, uint32_t timeMs, uint32_t key, uint32_t state) { - if (!hasKeymap) { + if UNLIKELY (!hasKeymap) { r->error(ZWP_VIRTUAL_KEYBOARD_V1_ERROR_NO_KEYMAP, "Key event received before a keymap was set"); return; } @@ -37,7 +37,7 @@ CVirtualKeyboardV1Resource::CVirtualKeyboardV1Resource(SP }); resource->setModifiers([this](CZwpVirtualKeyboardV1* r, uint32_t depressed, uint32_t latched, uint32_t locked, uint32_t group) { - if (!hasKeymap) { + if UNLIKELY (!hasKeymap) { r->error(ZWP_VIRTUAL_KEYBOARD_V1_ERROR_NO_KEYMAP, "Mods event received before a keymap was set"); return; } @@ -52,7 +52,7 @@ CVirtualKeyboardV1Resource::CVirtualKeyboardV1Resource(SP resource->setKeymap([this](CZwpVirtualKeyboardV1* r, uint32_t fmt, int32_t fd, uint32_t len) { auto xkbContext = xkb_context_new(XKB_CONTEXT_NO_FLAGS); - if (!xkbContext) { + if UNLIKELY (!xkbContext) { LOGM(ERR, "xkbContext creation failed"); r->noMemory(); close(fd); @@ -60,7 +60,7 @@ CVirtualKeyboardV1Resource::CVirtualKeyboardV1Resource(SP } auto keymapData = mmap(nullptr, len, PROT_READ, MAP_PRIVATE, fd, 0); - if (keymapData == MAP_FAILED) { + if UNLIKELY (keymapData == MAP_FAILED) { LOGM(ERR, "keymapData alloc failed"); xkb_context_unref(xkbContext); r->noMemory(); @@ -71,7 +71,7 @@ CVirtualKeyboardV1Resource::CVirtualKeyboardV1Resource(SP auto xkbKeymap = xkb_keymap_new_from_string(xkbContext, (const char*)keymapData, XKB_KEYMAP_FORMAT_TEXT_V1, XKB_KEYMAP_COMPILE_NO_FLAGS); munmap(keymapData, len); - if (!xkbKeymap) { + if UNLIKELY (!xkbKeymap) { LOGM(ERR, "xkbKeymap creation failed"); xkb_context_unref(xkbContext); r->noMemory(); @@ -142,7 +142,7 @@ void CVirtualKeyboardProtocol::onCreateKeeb(CZwpVirtualKeyboardManagerV1* pMgr, const auto RESOURCE = m_vKeyboards.emplace_back(makeShared(makeShared(pMgr->client(), pMgr->version(), id))); - if (!RESOURCE->good()) { + if UNLIKELY (!RESOURCE->good()) { pMgr->noMemory(); m_vKeyboards.pop_back(); return; diff --git a/src/protocols/VirtualPointer.cpp b/src/protocols/VirtualPointer.cpp index 4c5aa13a..3e0b00eb 100644 --- a/src/protocols/VirtualPointer.cpp +++ b/src/protocols/VirtualPointer.cpp @@ -2,7 +2,7 @@ #include "core/Output.hpp" CVirtualPointerV1Resource::CVirtualPointerV1Resource(SP resource_, PHLMONITORREF boundOutput_) : boundOutput(boundOutput_), resource(resource_) { - if (!good()) + if UNLIKELY (!good()) return; resource->setDestroy([this](CZwlrVirtualPointerV1* r) { @@ -41,7 +41,7 @@ CVirtualPointerV1Resource::CVirtualPointerV1Resource(SP r }); resource->setAxis([this](CZwlrVirtualPointerV1* r, uint32_t timeMs, uint32_t axis_, wl_fixed_t value) { - if (axis > WL_POINTER_AXIS_HORIZONTAL_SCROLL) { + if UNLIKELY (axis > WL_POINTER_AXIS_HORIZONTAL_SCROLL) { r->error(ZWLR_VIRTUAL_POINTER_V1_ERROR_INVALID_AXIS, "Invalid axis"); return; } @@ -64,7 +64,7 @@ CVirtualPointerV1Resource::CVirtualPointerV1Resource(SP r resource->setAxisSource([this](CZwlrVirtualPointerV1* r, uint32_t source) { axisEvents[axis].source = (wl_pointer_axis_source)source; }); resource->setAxisStop([this](CZwlrVirtualPointerV1* r, uint32_t timeMs, uint32_t axis_) { - if (axis > WL_POINTER_AXIS_HORIZONTAL_SCROLL) { + if UNLIKELY (axis > WL_POINTER_AXIS_HORIZONTAL_SCROLL) { r->error(ZWLR_VIRTUAL_POINTER_V1_ERROR_INVALID_AXIS, "Invalid axis"); return; } @@ -77,7 +77,7 @@ CVirtualPointerV1Resource::CVirtualPointerV1Resource(SP r }); resource->setAxisDiscrete([this](CZwlrVirtualPointerV1* r, uint32_t timeMs, uint32_t axis_, wl_fixed_t value, int32_t discrete) { - if (axis > WL_POINTER_AXIS_HORIZONTAL_SCROLL) { + if UNLIKELY (axis > WL_POINTER_AXIS_HORIZONTAL_SCROLL) { r->error(ZWLR_VIRTUAL_POINTER_V1_ERROR_INVALID_AXIS, "Invalid axis"); return; } @@ -138,7 +138,7 @@ void CVirtualPointerProtocol::onCreatePointer(CZwlrVirtualPointerManagerV1* pMgr const auto RESOURCE = m_vPointers.emplace_back(makeShared(makeShared(pMgr->client(), pMgr->version(), id), output)); - if (!RESOURCE->good()) { + if UNLIKELY (!RESOURCE->good()) { pMgr->noMemory(); m_vPointers.pop_back(); return; diff --git a/src/protocols/WaylandProtocol.cpp b/src/protocols/WaylandProtocol.cpp index 5c6a4a56..7fef5179 100644 --- a/src/protocols/WaylandProtocol.cpp +++ b/src/protocols/WaylandProtocol.cpp @@ -20,7 +20,7 @@ void IWaylandProtocol::onDisplayDestroy() { IWaylandProtocol::IWaylandProtocol(const wl_interface* iface, const int& ver, const std::string& name) : m_szName(name), m_pGlobal(wl_global_create(g_pCompositor->m_sWLDisplay, iface, ver, this, &bindManagerInternal)) { - if (!m_pGlobal) { + if UNLIKELY (!m_pGlobal) { LOGM(ERR, "could not create a global [{}]", m_szName); return; } diff --git a/src/protocols/XDGActivation.cpp b/src/protocols/XDGActivation.cpp index 4a6c7bfe..c49dc3dc 100644 --- a/src/protocols/XDGActivation.cpp +++ b/src/protocols/XDGActivation.cpp @@ -5,7 +5,7 @@ #include CXDGActivationToken::CXDGActivationToken(SP resource_) : resource(resource_) { - if (!resource_->resource()) + if UNLIKELY (!resource_->resource()) return; resource->setDestroy([this](CXdgActivationTokenV1* r) { PROTO::activation->destroyToken(this); }); @@ -18,7 +18,7 @@ CXDGActivationToken::CXDGActivationToken(SP resource_) : resource->setCommit([this](CXdgActivationTokenV1* r) { // TODO: should we send a protocol error of already_used here // if it was used? the protocol spec doesn't say _when_ it should be sent... - if (committed) { + if UNLIKELY (committed) { LOGM(WARN, "possible protocol error, two commits from one token. Ignoring."); return; } @@ -36,7 +36,7 @@ CXDGActivationToken::CXDGActivationToken(SP resource_) : auto count = std::count_if(PROTO::activation->m_vSentTokens.begin(), PROTO::activation->m_vSentTokens.end(), [this](const auto& other) { return other.client == resource->client(); }); - if (count > 10) { + if UNLIKELY (count > 10) { // remove first token. Too many, dear app. for (auto i = PROTO::activation->m_vSentTokens.begin(); i != PROTO::activation->m_vSentTokens.end(); ++i) { if (i->client == resource->client()) { @@ -70,7 +70,7 @@ void CXDGActivationProtocol::bindManager(wl_client* client, void* data, uint32_t RESOURCE->setActivate([this](CXdgActivationV1* pMgr, const char* token, wl_resource* surface) { auto TOKEN = std::find_if(m_vSentTokens.begin(), m_vSentTokens.end(), [token](const auto& t) { return t.token == token; }); - if (TOKEN == m_vSentTokens.end()) { + if UNLIKELY (TOKEN == m_vSentTokens.end()) { LOGM(WARN, "activate event for non-existent token {}??", token); return; } @@ -81,7 +81,7 @@ void CXDGActivationProtocol::bindManager(wl_client* client, void* data, uint32_t SP surf = CWLSurfaceResource::fromResource(surface); const auto PWINDOW = g_pCompositor->getWindowFromSurface(surf); - if (!PWINDOW) { + if UNLIKELY (!PWINDOW) { LOGM(WARN, "activate event for non-window or gone surface with token {}, ignoring", token); return; } @@ -102,7 +102,7 @@ void CXDGActivationProtocol::onGetToken(CXdgActivationV1* pMgr, uint32_t id) { const auto CLIENT = pMgr->client(); const auto RESOURCE = m_vTokens.emplace_back(std::make_unique(makeShared(CLIENT, pMgr->version(), id))).get(); - if (!RESOURCE->good()) { + if UNLIKELY (!RESOURCE->good()) { pMgr->noMemory(); m_vTokens.pop_back(); return; diff --git a/src/protocols/XDGDecoration.cpp b/src/protocols/XDGDecoration.cpp index 07b1694c..8ec0d5b0 100644 --- a/src/protocols/XDGDecoration.cpp +++ b/src/protocols/XDGDecoration.cpp @@ -2,7 +2,7 @@ #include CXDGDecoration::CXDGDecoration(SP resource_, wl_resource* toplevel) : resource(resource_), pToplevelResource(toplevel) { - if (!resource->resource()) + if UNLIKELY (!resource->resource()) return; resource->setDestroy([this](CZxdgToplevelDecorationV1* pMgr) { PROTO::xdgDecoration->destroyDecoration(this); }); @@ -57,7 +57,7 @@ void CXDGDecorationProtocol::destroyDecoration(CXDGDecoration* decoration) { } void CXDGDecorationProtocol::onGetDecoration(CZxdgDecorationManagerV1* pMgr, uint32_t id, wl_resource* xdgToplevel) { - if (m_mDecorations.contains(xdgToplevel)) { + if UNLIKELY (m_mDecorations.contains(xdgToplevel)) { pMgr->error(ZXDG_TOPLEVEL_DECORATION_V1_ERROR_ALREADY_CONSTRUCTED, "Decoration object already exists"); return; } @@ -66,7 +66,7 @@ void CXDGDecorationProtocol::onGetDecoration(CZxdgDecorationManagerV1* pMgr, uin const auto RESOURCE = m_mDecorations.emplace(xdgToplevel, std::make_unique(makeShared(CLIENT, pMgr->version(), id), xdgToplevel)).first->second.get(); - if (!RESOURCE->good()) { + if UNLIKELY (!RESOURCE->good()) { pMgr->noMemory(); m_mDecorations.erase(xdgToplevel); return; diff --git a/src/protocols/XDGDialog.cpp b/src/protocols/XDGDialog.cpp index 3f58f326..675d4e78 100644 --- a/src/protocols/XDGDialog.cpp +++ b/src/protocols/XDGDialog.cpp @@ -5,7 +5,7 @@ #include CXDGDialogV1Resource::CXDGDialogV1Resource(SP resource_, SP toplevel_) : resource(resource_), toplevel(toplevel_) { - if (!good()) + if UNLIKELY (!good()) return; resource->setDestroy([this](CXdgDialogV1* r) { PROTO::xdgDialog->destroyResource(this); }); @@ -23,11 +23,11 @@ CXDGDialogV1Resource::CXDGDialogV1Resource(SP resource_, SPparent || !toplevel->parent->owner) + if UNLIKELY (!toplevel || !toplevel->parent || !toplevel->parent->owner) return; auto HLSurface = CWLSurface::fromResource(toplevel->parent->owner->surface.lock()); - if (!HLSurface || !HLSurface->getWindow()) + if UNLIKELY (!HLSurface || !HLSurface->getWindow()) return; g_pCompositor->updateWindowAnimatedDecorationValues(HLSurface->getWindow()); @@ -38,7 +38,7 @@ bool CXDGDialogV1Resource::good() { } CXDGWmDialogManagerResource::CXDGWmDialogManagerResource(SP resource_) : resource(resource_) { - if (!good()) + if UNLIKELY (!good()) return; resource->setDestroy([this](CXdgWmDialogV1* r) { PROTO::xdgDialog->destroyResource(this); }); @@ -46,14 +46,14 @@ CXDGWmDialogManagerResource::CXDGWmDialogManagerResource(SP reso resource->setGetXdgDialog([](CXdgWmDialogV1* r, uint32_t id, wl_resource* toplevel) { auto tl = CXDGToplevelResource::fromResource(toplevel); - if (!tl) { + if UNLIKELY (!tl) { r->error(-1, "Toplevel inert"); return; } const auto RESOURCE = PROTO::xdgDialog->m_vDialogs.emplace_back(makeShared(makeShared(r->client(), r->version(), id), tl)); - if (!RESOURCE->good()) { + if UNLIKELY (!RESOURCE->good()) { r->noMemory(); return; } @@ -73,7 +73,7 @@ CXDGDialogProtocol::CXDGDialogProtocol(const wl_interface* iface, const int& ver void CXDGDialogProtocol::bindManager(wl_client* client, void* data, uint32_t ver, uint32_t id) { const auto RESOURCE = m_vManagers.emplace_back(makeShared(makeShared(client, ver, id))); - if (!RESOURCE->good()) { + if UNLIKELY (!RESOURCE->good()) { wl_client_post_no_memory(client); return; } diff --git a/src/protocols/XDGOutput.cpp b/src/protocols/XDGOutput.cpp index fadc48a1..5be16d07 100644 --- a/src/protocols/XDGOutput.cpp +++ b/src/protocols/XDGOutput.cpp @@ -23,7 +23,7 @@ void CXDGOutputProtocol::onOutputResourceDestroy(wl_resource* res) { void CXDGOutputProtocol::bindManager(wl_client* client, void* data, uint32_t ver, uint32_t id) { const auto RESOURCE = m_vManagerResources.emplace_back(std::make_unique(client, ver, id)).get(); - if (!RESOURCE->resource()) { + if UNLIKELY (!RESOURCE->resource()) { LOGM(LOG, "Couldn't bind XDGOutputMgr"); wl_client_post_no_memory(client); return; @@ -53,13 +53,13 @@ void CXDGOutputProtocol::onManagerGetXDGOutput(CZxdgOutputManagerV1* mgr, uint32 pXDGOutput->outputProto = OUTPUT->owner; - if (!pXDGOutput->resource->resource()) { + if UNLIKELY (!pXDGOutput->resource->resource()) { m_vXDGOutputs.pop_back(); mgr->noMemory(); return; } - if (!PMONITOR) { + if UNLIKELY (!PMONITOR) { LOGM(ERR, "New xdg_output from client {:x} ({}) has no CMonitor?!", (uintptr_t)CLIENT, pXDGOutput->isXWayland ? "xwayland" : "not xwayland"); return; } @@ -96,7 +96,7 @@ void CXDGOutputProtocol::updateAllOutputs() { // CXDGOutput::CXDGOutput(SP resource_, PHLMONITOR monitor_) : monitor(monitor_), resource(resource_) { - if (!resource->resource()) + if UNLIKELY (!resource->resource()) return; resource->setDestroy([](CZxdgOutputV1* pMgr) { PROTO::xdgOutput->onOutputResourceDestroy(pMgr->resource()); }); @@ -106,7 +106,7 @@ CXDGOutput::CXDGOutput(SP resource_, PHLMONITOR monitor_) : monit void CXDGOutput::sendDetails() { static auto PXWLFORCESCALEZERO = CConfigValue("xwayland:force_zero_scaling"); - if (!monitor || !outputProto || outputProto->isDefunct()) + if UNLIKELY (!monitor || !outputProto || outputProto->isDefunct()) return; const auto POS = isXWayland ? monitor->vecXWaylandPosition : monitor->vecPosition; diff --git a/src/protocols/XDGShell.cpp b/src/protocols/XDGShell.cpp index aabb225a..f5d1a8fa 100644 --- a/src/protocols/XDGShell.cpp +++ b/src/protocols/XDGShell.cpp @@ -26,7 +26,7 @@ void SXDGPositionerState::setGravity(xdgPositionerGravity edges) { CXDGPopupResource::CXDGPopupResource(SP resource_, SP owner_, SP surface_, SP positioner) : surface(surface_), parent(owner_), resource(resource_), positionerRules(positioner) { - if (!good()) + if UNLIKELY (!good()) return; resource->setData(this); @@ -79,7 +79,7 @@ void CXDGPopupResource::applyPositioning(const CBox& box, const Vector2D& t1coor configure(geometry); - if (lastRepositionToken) + if UNLIKELY (lastRepositionToken) repositioned(); } @@ -118,7 +118,7 @@ void CXDGPopupResource::done() { } void CXDGPopupResource::repositioned() { - if (!lastRepositionToken) + if LIKELY (!lastRepositionToken) return; LOGM(LOG, "repositioned: sending reposition token {}", lastRepositionToken); @@ -128,7 +128,7 @@ void CXDGPopupResource::repositioned() { } CXDGToplevelResource::CXDGToplevelResource(SP resource_, SP owner_) : owner(owner_), resource(resource_) { - if (!good()) + if UNLIKELY (!good()) return; resource->setData(this); @@ -350,7 +350,7 @@ Vector2D CXDGToplevelResource::layoutMaxSize() { CXDGSurfaceResource::CXDGSurfaceResource(SP resource_, SP owner_, SP surface_) : owner(owner_), surface(surface_), resource(resource_) { - if (!good()) + if UNLIKELY (!good()) return; resource->setData(this); @@ -386,7 +386,7 @@ CXDGSurfaceResource::CXDGSurfaceResource(SP resource_, SPcurrent = toplevel->pending; - if (initialCommit && surface->pending.texture) { + if UNLIKELY (initialCommit && surface->pending.texture) { resource->error(-1, "Buffer attached before initial commit"); return; } @@ -416,7 +416,7 @@ CXDGSurfaceResource::CXDGSurfaceResource(SP resource_, SPsetGetToplevel([this](CXdgSurface* r, uint32_t id) { const auto RESOURCE = PROTO::xdgShell->m_vToplevels.emplace_back(makeShared(makeShared(r->client(), r->version(), id), self.lock())); - if (!RESOURCE->good()) { + if UNLIKELY (!RESOURCE->good()) { r->noMemory(); PROTO::xdgShell->m_vToplevels.pop_back(); return; @@ -442,7 +442,7 @@ CXDGSurfaceResource::CXDGSurfaceResource(SP resource_, SPm_vPopups.emplace_back(makeShared(makeShared(r->client(), r->version(), id), parent, self.lock(), positioner)); - if (!RESOURCE->good()) { + if UNLIKELY (!RESOURCE->good()) { r->noMemory(); PROTO::xdgShell->m_vPopups.pop_back(); return; @@ -511,7 +511,7 @@ void CXDGSurfaceResource::configure() { } CXDGPositionerResource::CXDGPositionerResource(SP resource_, SP owner_) : owner(owner_), resource(resource_) { - if (!good()) + if UNLIKELY (!good()) return; resource->setData(this); @@ -520,7 +520,7 @@ CXDGPositionerResource::CXDGPositionerResource(SP resource_, SP< resource->setOnDestroy([this](CXdgPositioner* r) { PROTO::xdgShell->destroyResource(this); }); resource->setSetSize([this](CXdgPositioner* r, int32_t x, int32_t y) { - if (x <= 0 || y <= 0) { + if UNLIKELY (x <= 0 || y <= 0) { r->error(XDG_POSITIONER_ERROR_INVALID_INPUT, "Invalid size"); return; } @@ -529,7 +529,7 @@ CXDGPositionerResource::CXDGPositionerResource(SP resource_, SP< }); resource->setSetAnchorRect([this](CXdgPositioner* r, int32_t x, int32_t y, int32_t w, int32_t h) { - if (w <= 0 || h <= 0) { + if UNLIKELY (w <= 0 || h <= 0) { r->error(XDG_POSITIONER_ERROR_INVALID_INPUT, "Invalid box"); return; } @@ -686,7 +686,7 @@ CBox CXDGPositionerRules::getPosition(CBox constraint, const Vector2D& parentCoo } CXDGWMBase::CXDGWMBase(SP resource_) : resource(resource_) { - if (!good()) + if UNLIKELY (!good()) return; resource->setDestroy([this](CXdgWmBase* r) { PROTO::xdgShell->destroyResource(this); }); @@ -698,7 +698,7 @@ CXDGWMBase::CXDGWMBase(SP resource_) : resource(resource_) { const auto RESOURCE = PROTO::xdgShell->m_vPositioners.emplace_back(makeShared(makeShared(r->client(), r->version(), id), self.lock())); - if (!RESOURCE->good()) { + if UNLIKELY (!RESOURCE->good()) { r->noMemory(); PROTO::xdgShell->m_vPositioners.pop_back(); return; @@ -714,19 +714,19 @@ CXDGWMBase::CXDGWMBase(SP resource_) : resource(resource_) { resource->setGetXdgSurface([this](CXdgWmBase* r, uint32_t id, wl_resource* surf) { auto SURF = CWLSurfaceResource::fromResource(surf); - if (!SURF) { + if UNLIKELY (!SURF) { r->error(-1, "Invalid surface passed"); return; } - if (SURF->role->role() != SURFACE_ROLE_UNASSIGNED) { + if UNLIKELY (SURF->role->role() != SURFACE_ROLE_UNASSIGNED) { r->error(-1, "Surface already has a different role"); return; } const auto RESOURCE = PROTO::xdgShell->m_vSurfaces.emplace_back(makeShared(makeShared(r->client(), r->version(), id), self.lock(), SURF)); - if (!RESOURCE->good()) { + if UNLIKELY (!RESOURCE->good()) { r->noMemory(); PROTO::xdgShell->m_vSurfaces.pop_back(); return; @@ -765,7 +765,7 @@ CXDGShellProtocol::CXDGShellProtocol(const wl_interface* iface, const int& ver, void CXDGShellProtocol::bindManager(wl_client* client, void* data, uint32_t ver, uint32_t id) { const auto RESOURCE = m_vWMBases.emplace_back(makeShared(makeShared(client, ver, id))); - if (!RESOURCE->good()) { + if UNLIKELY (!RESOURCE->good()) { wl_client_post_no_memory(client); m_vWMBases.pop_back(); return; diff --git a/src/protocols/XWaylandShell.cpp b/src/protocols/XWaylandShell.cpp index 81194163..b4615e19 100644 --- a/src/protocols/XWaylandShell.cpp +++ b/src/protocols/XWaylandShell.cpp @@ -3,7 +3,7 @@ #include CXWaylandSurfaceResource::CXWaylandSurfaceResource(SP resource_, SP surface_) : surface(surface_), resource(resource_) { - if (!good()) + if UNLIKELY (!good()) return; resource->setDestroy([this](CXwaylandSurfaceV1* r) { @@ -36,7 +36,7 @@ wl_client* CXWaylandSurfaceResource::client() { } CXWaylandShellResource::CXWaylandShellResource(SP resource_) : resource(resource_) { - if (!good()) + if UNLIKELY (!good()) return; resource->setDestroy([this](CXwaylandShellV1* r) { PROTO::xwaylandShell->destroyResource(this); }); @@ -46,7 +46,7 @@ CXWaylandShellResource::CXWaylandShellResource(SP resource_) : const auto RESOURCE = PROTO::xwaylandShell->m_vSurfaces.emplace_back( makeShared(makeShared(r->client(), r->version(), id), CWLSurfaceResource::fromResource(surface))); - if (!RESOURCE->good()) { + if UNLIKELY (!RESOURCE->good()) { r->noMemory(); PROTO::xwaylandShell->m_vSurfaces.pop_back(); return; @@ -67,7 +67,7 @@ CXWaylandShellProtocol::CXWaylandShellProtocol(const wl_interface* iface, const void CXWaylandShellProtocol::bindManager(wl_client* client, void* data, uint32_t ver, uint32_t id) { const auto RESOURCE = m_vManagers.emplace_back(makeShared(makeShared(client, ver, id))); - if (!RESOURCE->good()) { + if UNLIKELY (!RESOURCE->good()) { wl_client_post_no_memory(client); m_vManagers.pop_back(); return; diff --git a/src/protocols/core/Compositor.cpp b/src/protocols/core/Compositor.cpp index e1d6ef7d..93683993 100644 --- a/src/protocols/core/Compositor.cpp +++ b/src/protocols/core/Compositor.cpp @@ -34,7 +34,7 @@ void CWLCallbackResource::send(timespec* now) { } CWLRegionResource::CWLRegionResource(SP resource_) : resource(resource_) { - if (!good()) + if UNLIKELY (!good()) return; resource->setData(this); @@ -56,7 +56,7 @@ SP CWLRegionResource::fromResource(wl_resource* res) { } CWLSurfaceResource::CWLSurfaceResource(SP resource_) : resource(resource_) { - if (!good()) + if UNLIKELY (!good()) return; pClient = resource->client(); @@ -187,20 +187,20 @@ void CWLSurfaceResource::enter(PHLMONITOR monitor) { if (std::find(enteredOutputs.begin(), enteredOutputs.end(), monitor) != enteredOutputs.end()) return; - if (!PROTO::outputs.contains(monitor->szName)) { + if UNLIKELY (!PROTO::outputs.contains(monitor->szName)) { // can happen on unplug/replug LOGM(ERR, "enter() called on a non-existent output global"); return; } - if (PROTO::outputs.at(monitor->szName)->isDefunct()) { + if UNLIKELY (PROTO::outputs.at(monitor->szName)->isDefunct()) { LOGM(ERR, "enter() called on a defunct output global"); return; } auto output = PROTO::outputs.at(monitor->szName)->outputResourceFrom(pClient); - if (!output || !output->getResource() || !output->getResource()->resource()) { + if UNLIKELY (!output || !output->getResource() || !output->getResource()->resource()) { LOGM(ERR, "Cannot enter surface {:x} to {}, client hasn't bound the output", (uintptr_t)this, monitor->szName); return; } @@ -211,12 +211,12 @@ void CWLSurfaceResource::enter(PHLMONITOR monitor) { } void CWLSurfaceResource::leave(PHLMONITOR monitor) { - if (std::find(enteredOutputs.begin(), enteredOutputs.end(), monitor) == enteredOutputs.end()) + if UNLIKELY (std::find(enteredOutputs.begin(), enteredOutputs.end(), monitor) == enteredOutputs.end()) return; auto output = PROTO::outputs.at(monitor->szName)->outputResourceFrom(pClient); - if (!output) { + if UNLIKELY (!output) { LOGM(ERR, "Cannot leave surface {:x} from {}, client hasn't bound the output", (uintptr_t)this, monitor->szName); return; } @@ -332,7 +332,7 @@ uint32_t CWLSurfaceResource::id() { } void CWLSurfaceResource::map() { - if (mapped) + if UNLIKELY (mapped) return; mapped = true; @@ -346,7 +346,7 @@ void CWLSurfaceResource::map() { } void CWLSurfaceResource::unmap() { - if (!mapped) + if UNLIKELY (!mapped) return; mapped = false; @@ -385,10 +385,10 @@ CBox CWLSurfaceResource::extends() { } Vector2D CWLSurfaceResource::sourceSize() { - if (!current.texture) + if UNLIKELY (!current.texture) return {}; - if (current.viewport.hasSource) + if UNLIKELY (current.viewport.hasSource) return current.viewport.source.size(); Vector2D trc = current.transform % 2 == 1 ? Vector2D{current.bufferSize.y, current.bufferSize.x} : current.bufferSize; @@ -396,7 +396,7 @@ Vector2D CWLSurfaceResource::sourceSize() { } CRegion CWLSurfaceResource::accumulateCurrentBufferDamage() { - if (!current.texture) + if UNLIKELY (!current.texture) return {}; CRegion surfaceDamage = current.damage; @@ -495,7 +495,7 @@ void CWLSurfaceResource::commitPendingState() { void CWLSurfaceResource::updateCursorShm(CRegion damage) { auto buf = current.buffer ? current.buffer->buffer : lastBuffer; - if (!buf) + if UNLIKELY (!buf) return; auto& shmData = CCursorSurfaceRole::cursorPixelData(self.lock()); @@ -545,7 +545,7 @@ void CWLSurfaceResource::presentFeedback(timespec* when, PHLMONITOR pMonitor, bo } CWLCompositorResource::CWLCompositorResource(SP resource_) : resource(resource_) { - if (!good()) + if UNLIKELY (!good()) return; resource->setOnDestroy([this](CWlCompositor* r) { PROTO::compositor->destroyResource(this); }); @@ -553,7 +553,7 @@ CWLCompositorResource::CWLCompositorResource(SP resource_) : reso resource->setCreateSurface([](CWlCompositor* r, uint32_t id) { const auto RESOURCE = PROTO::compositor->m_vSurfaces.emplace_back(makeShared(makeShared(r->client(), r->version(), id))); - if (!RESOURCE->good()) { + if UNLIKELY (!RESOURCE->good()) { r->noMemory(); PROTO::compositor->m_vSurfaces.pop_back(); return; @@ -569,7 +569,7 @@ CWLCompositorResource::CWLCompositorResource(SP resource_) : reso resource->setCreateRegion([](CWlCompositor* r, uint32_t id) { const auto RESOURCE = PROTO::compositor->m_vRegions.emplace_back(makeShared(makeShared(r->client(), r->version(), id))); - if (!RESOURCE->good()) { + if UNLIKELY (!RESOURCE->good()) { r->noMemory(); PROTO::compositor->m_vRegions.pop_back(); return; @@ -592,7 +592,7 @@ CWLCompositorProtocol::CWLCompositorProtocol(const wl_interface* iface, const in void CWLCompositorProtocol::bindManager(wl_client* client, void* data, uint32_t ver, uint32_t id) { const auto RESOURCE = m_vManagers.emplace_back(makeShared(makeShared(client, ver, id))); - if (!RESOURCE->good()) { + if UNLIKELY (!RESOURCE->good()) { wl_client_post_no_memory(client); m_vManagers.pop_back(); return; diff --git a/src/protocols/core/DataDevice.cpp b/src/protocols/core/DataDevice.cpp index fd3cd1fa..ade16498 100644 --- a/src/protocols/core/DataDevice.cpp +++ b/src/protocols/core/DataDevice.cpp @@ -15,7 +15,7 @@ #include "../../render/Renderer.hpp" CWLDataOfferResource::CWLDataOfferResource(SP resource_, SP source_) : source(source_), resource(resource_) { - if (!good()) + if UNLIKELY (!good()) return; resource->setDestroy([this](CWlDataOffer* r) { PROTO::data->destroyResource(this); }); @@ -127,7 +127,7 @@ SP CWLDataOfferResource::getSource() { } CWLDataSourceResource::CWLDataSourceResource(SP resource_, SP device_) : device(device_), resource(resource_) { - if (!good()) + if UNLIKELY (!good()) return; resource->setData(this); @@ -237,7 +237,7 @@ eDataSourceType CWLDataSourceResource::type() { } CWLDataDeviceResource::CWLDataDeviceResource(SP resource_) : resource(resource_) { - if (!good()) + if UNLIKELY (!good()) return; resource->setRelease([this](CWlDataDevice* r) { PROTO::data->destroyResource(this); }); @@ -333,7 +333,7 @@ SP CWLDataDeviceResource::getX11() { } CWLDataDeviceManagerResource::CWLDataDeviceManagerResource(SP resource_) : resource(resource_) { - if (!good()) + if UNLIKELY (!good()) return; resource->setOnDestroy([this](CWlDataDeviceManager* r) { PROTO::data->destroyResource(this); }); @@ -343,7 +343,7 @@ CWLDataDeviceManagerResource::CWLDataDeviceManagerResource(SPm_vSources.emplace_back(makeShared(makeShared(r->client(), r->version(), id), device.lock())); - if (!RESOURCE->good()) { + if UNLIKELY (!RESOURCE->good()) { r->noMemory(); PROTO::data->m_vSources.pop_back(); return; @@ -362,7 +362,7 @@ CWLDataDeviceManagerResource::CWLDataDeviceManagerResource(SPsetGetDataDevice([this](CWlDataDeviceManager* r, uint32_t id, wl_resource* seat) { const auto RESOURCE = PROTO::data->m_vDevices.emplace_back(makeShared(makeShared(r->client(), r->version(), id))); - if (!RESOURCE->good()) { + if UNLIKELY (!RESOURCE->good()) { r->noMemory(); PROTO::data->m_vDevices.pop_back(); return; @@ -394,7 +394,7 @@ CWLDataDeviceProtocol::CWLDataDeviceProtocol(const wl_interface* iface, const in void CWLDataDeviceProtocol::bindManager(wl_client* client, void* data, uint32_t ver, uint32_t id) { const auto RESOURCE = m_vManagers.emplace_back(makeShared(makeShared(client, ver, id))); - if (!RESOURCE->good()) { + if UNLIKELY (!RESOURCE->good()) { wl_client_post_no_memory(client); m_vManagers.pop_back(); return; @@ -441,7 +441,7 @@ void CWLDataDeviceProtocol::sendSelectionToDevice(SP dev, SPgetWayland(); WL) { const auto OFFER = m_vOffers.emplace_back(makeShared(makeShared(WL->resource->client(), WL->resource->version(), 0), sel)); - if (!OFFER->good()) { + if UNLIKELY (!OFFER->good()) { WL->resource->noMemory(); m_vOffers.pop_back(); return; @@ -455,7 +455,7 @@ void CWLDataDeviceProtocol::sendSelectionToDevice(SP dev, SPpWM->createX11DataOffer(g_pSeatManager->state.keyboardFocus.lock(), sel); #endif - if (!offer) { + if UNLIKELY (!offer) { LOGM(ERR, "No offer could be created in sendSelectionToDevice"); return; } diff --git a/src/protocols/core/Output.cpp b/src/protocols/core/Output.cpp index db580457..77f0661e 100644 --- a/src/protocols/core/Output.cpp +++ b/src/protocols/core/Output.cpp @@ -4,7 +4,7 @@ #include "../../helpers/Monitor.hpp" CWLOutputResource::CWLOutputResource(SP resource_, PHLMONITOR pMonitor) : monitor(pMonitor), resource(resource_) { - if (!good()) + if UNLIKELY (!good()) return; resource->setData(this); @@ -94,12 +94,12 @@ CWLOutputProtocol::CWLOutputProtocol(const wl_interface* iface, const int& ver, } void CWLOutputProtocol::bindManager(wl_client* client, void* data, uint32_t ver, uint32_t id) { - if (defunct) + if UNLIKELY (defunct) Debug::log(WARN, "[wl_output] Binding a wl_output that's inert?? Possible client bug."); const auto RESOURCE = m_vOutputs.emplace_back(makeShared(makeShared(client, ver, id), monitor.lock())); - if (!RESOURCE->good()) { + if UNLIKELY (!RESOURCE->good()) { wl_client_post_no_memory(client); m_vOutputs.pop_back(); return; @@ -128,7 +128,7 @@ SP CWLOutputProtocol::outputResourceFrom(wl_client* client) { } void CWLOutputProtocol::remove() { - if (defunct) + if UNLIKELY (defunct) return; defunct = true; @@ -140,7 +140,7 @@ bool CWLOutputProtocol::isDefunct() { } void CWLOutputProtocol::sendDone() { - if (defunct) + if UNLIKELY (defunct) return; for (auto const& r : m_vOutputs) { diff --git a/src/protocols/core/Seat.cpp b/src/protocols/core/Seat.cpp index f7969a4d..c6b2de05 100644 --- a/src/protocols/core/Seat.cpp +++ b/src/protocols/core/Seat.cpp @@ -10,7 +10,7 @@ #include CWLTouchResource::CWLTouchResource(SP resource_, SP owner_) : owner(owner_), resource(resource_) { - if (!good()) + if UNLIKELY (!good()) return; resource->setRelease([this](CWlTouch* r) { PROTO::seat->destroyResource(this); }); @@ -105,7 +105,7 @@ void CWLTouchResource::sendOrientation(int32_t id, double angle) { } CWLPointerResource::CWLPointerResource(SP resource_, SP owner_) : owner(owner_), resource(resource_) { - if (!good()) + if UNLIKELY (!good()) return; resource->setRelease([this](CWlPointer* r) { PROTO::seat->destroyResource(this); }); @@ -292,7 +292,7 @@ void CWLPointerResource::sendAxisRelativeDirection(wl_pointer_axis axis, wl_poin } CWLKeyboardResource::CWLKeyboardResource(SP resource_, SP owner_) : owner(owner_), resource(resource_) { - if (!good()) + if UNLIKELY (!good()) return; resource->setRelease([this](CWlKeyboard* r) { PROTO::seat->destroyResource(this); }); @@ -419,7 +419,7 @@ void CWLKeyboardResource::repeatInfo(uint32_t rate, uint32_t delayMs) { } CWLSeatResource::CWLSeatResource(SP resource_) : resource(resource_) { - if (!good()) + if UNLIKELY (!good()) return; resource->setOnDestroy([this](CWlSeat* r) { @@ -436,7 +436,7 @@ CWLSeatResource::CWLSeatResource(SP resource_) : resource(resource_) { resource->setGetKeyboard([this](CWlSeat* r, uint32_t id) { const auto RESOURCE = PROTO::seat->m_vKeyboards.emplace_back(makeShared(makeShared(r->client(), r->version(), id), self.lock())); - if (!RESOURCE->good()) { + if UNLIKELY (!RESOURCE->good()) { r->noMemory(); PROTO::seat->m_vKeyboards.pop_back(); return; @@ -448,7 +448,7 @@ CWLSeatResource::CWLSeatResource(SP resource_) : resource(resource_) { resource->setGetPointer([this](CWlSeat* r, uint32_t id) { const auto RESOURCE = PROTO::seat->m_vPointers.emplace_back(makeShared(makeShared(r->client(), r->version(), id), self.lock())); - if (!RESOURCE->good()) { + if UNLIKELY (!RESOURCE->good()) { r->noMemory(); PROTO::seat->m_vPointers.pop_back(); return; @@ -460,7 +460,7 @@ CWLSeatResource::CWLSeatResource(SP resource_) : resource(resource_) { resource->setGetTouch([this](CWlSeat* r, uint32_t id) { const auto RESOURCE = PROTO::seat->m_vTouches.emplace_back(makeShared(makeShared(r->client(), r->version(), id), self.lock())); - if (!RESOURCE->good()) { + if UNLIKELY (!RESOURCE->good()) { r->noMemory(); PROTO::seat->m_vTouches.pop_back(); return; @@ -506,7 +506,7 @@ CWLSeatProtocol::CWLSeatProtocol(const wl_interface* iface, const int& ver, cons void CWLSeatProtocol::bindManager(wl_client* client, void* data, uint32_t ver, uint32_t id) { const auto RESOURCE = m_vSeatResources.emplace_back(makeShared(makeShared(client, ver, id))); - if (!RESOURCE->good()) { + if UNLIKELY (!RESOURCE->good()) { wl_client_post_no_memory(client); m_vSeatResources.pop_back(); return; diff --git a/src/protocols/core/Shm.cpp b/src/protocols/core/Shm.cpp index 6365c5d6..28585aeb 100644 --- a/src/protocols/core/Shm.cpp +++ b/src/protocols/core/Shm.cpp @@ -9,7 +9,7 @@ #include "../../render/Renderer.hpp" CWLSHMBuffer::CWLSHMBuffer(SP pool_, uint32_t id, int32_t offset_, const Vector2D& size_, int32_t stride_, uint32_t fmt_) { - if (!pool_->pool->data) + if UNLIKELY (!pool_->pool->data) return; g_pHyprRenderer->makeEGLCurrent(); @@ -32,7 +32,7 @@ CWLSHMBuffer::CWLSHMBuffer(SP pool_, uint32_t id, int32_t of success = texture->m_iTexID; - if (!success) + if UNLIKELY (!success) Debug::log(ERR, "Failed creating a shm texture: null texture id"); } @@ -96,13 +96,13 @@ void CSHMPool::resize(size_t size_) { size = size_; data = mmap(nullptr, size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0); - if (data == MAP_FAILED) + if UNLIKELY (data == MAP_FAILED) LOGM(ERR, "Couldn't mmap {} bytes from fd {} of shm client", size, fd); } static int shmIsSizeValid(int fd, size_t size) { struct stat st; - if (fstat(fd, &st) == -1) { + if UNLIKELY (fstat(fd, &st) == -1) { LOGM(ERR, "Couldn't get stat for fd {} of shm client", fd); return 0; } @@ -111,10 +111,10 @@ static int shmIsSizeValid(int fd, size_t size) { } CWLSHMPoolResource::CWLSHMPoolResource(SP resource_, int fd_, size_t size_) : resource(resource_) { - if (!good()) + if UNLIKELY (!good()) return; - if (!shmIsSizeValid(fd_, size_)) { + if UNLIKELY (!shmIsSizeValid(fd_, size_)) { resource_->error(-1, "The size of the file is not big enough for the shm pool"); return; } @@ -125,11 +125,11 @@ CWLSHMPoolResource::CWLSHMPoolResource(SP resource_, int fd_, size_t resource->setOnDestroy([this](CWlShmPool* r) { PROTO::shm->destroyResource(this); }); resource->setResize([this](CWlShmPool* r, int32_t size_) { - if (size_ < (int32_t)pool->size) { + if UNLIKELY (size_ < (int32_t)pool->size) { r->error(-1, "Shrinking a shm pool is illegal"); return; } - if (!shmIsSizeValid(pool->fd, size_)) { + if UNLIKELY (!shmIsSizeValid(pool->fd, size_)) { r->error(-1, "The size of the file is not big enough for the shm pool"); return; } @@ -138,24 +138,24 @@ CWLSHMPoolResource::CWLSHMPoolResource(SP resource_, int fd_, size_t }); resource->setCreateBuffer([this](CWlShmPool* r, uint32_t id, int32_t offset, int32_t w, int32_t h, int32_t stride, uint32_t fmt) { - if (!pool || !pool->data) { + if UNLIKELY (!pool || !pool->data) { r->error(-1, "The provided shm pool failed to allocate properly"); return; } - if (std::find(PROTO::shm->shmFormats.begin(), PROTO::shm->shmFormats.end(), fmt) == PROTO::shm->shmFormats.end()) { + if UNLIKELY (std::find(PROTO::shm->shmFormats.begin(), PROTO::shm->shmFormats.end(), fmt) == PROTO::shm->shmFormats.end()) { r->error(WL_SHM_ERROR_INVALID_FORMAT, "Format invalid"); return; } - if (offset < 0 || w <= 0 || h <= 0 || stride <= 0) { + if UNLIKELY (offset < 0 || w <= 0 || h <= 0 || stride <= 0) { r->error(WL_SHM_ERROR_INVALID_STRIDE, "Invalid stride, w, h, or offset"); return; } const auto RESOURCE = PROTO::shm->m_vBuffers.emplace_back(makeShared(self.lock(), id, offset, Vector2D{w, h}, stride, fmt)); - if (!RESOURCE->good()) { + if UNLIKELY (!RESOURCE->good()) { r->noMemory(); PROTO::shm->m_vBuffers.pop_back(); return; @@ -165,7 +165,7 @@ CWLSHMPoolResource::CWLSHMPoolResource(SP resource_, int fd_, size_t RESOURCE->resource->buffer = RESOURCE; }); - if (pool->data == MAP_FAILED) + if UNLIKELY (pool->data == MAP_FAILED) resource->error(WL_SHM_ERROR_INVALID_FD, "Couldn't mmap from fd"); } @@ -174,7 +174,7 @@ bool CWLSHMPoolResource::good() { } CWLSHMResource::CWLSHMResource(SP resource_) : resource(resource_) { - if (!good()) + if UNLIKELY (!good()) return; resource->setOnDestroy([this](CWlShm* r) { PROTO::shm->destroyResource(this); }); @@ -182,7 +182,7 @@ CWLSHMResource::CWLSHMResource(SP resource_) : resource(resource_) { resource->setCreatePool([](CWlShm* r, uint32_t id, int32_t fd, int32_t size) { const auto RESOURCE = PROTO::shm->m_vPools.emplace_back(makeShared(makeShared(r->client(), r->version(), id), fd, size)); - if (!RESOURCE->good()) { + if UNLIKELY (!RESOURCE->good()) { r->noMemory(); PROTO::shm->m_vPools.pop_back(); return; @@ -221,7 +221,7 @@ void CWLSHMProtocol::bindManager(wl_client* client, void* data, uint32_t ver, ui const auto RESOURCE = m_vManagers.emplace_back(makeShared(makeShared(client, ver, id))); - if (!RESOURCE->good()) { + if UNLIKELY (!RESOURCE->good()) { wl_client_post_no_memory(client); m_vManagers.pop_back(); return; diff --git a/src/protocols/core/Subcompositor.cpp b/src/protocols/core/Subcompositor.cpp index 46e20305..4edb07ff 100644 --- a/src/protocols/core/Subcompositor.cpp +++ b/src/protocols/core/Subcompositor.cpp @@ -4,7 +4,7 @@ CWLSubsurfaceResource::CWLSubsurfaceResource(SP resource_, SP surface_, SP parent_) : surface(surface_), parent(parent_), resource(resource_) { - if (!good()) + if UNLIKELY (!good()) return; resource->setOnDestroy([this](CWlSubsurface* r) { destroy(); }); @@ -142,7 +142,7 @@ SP CWLSubsurfaceResource::t1Parent() { } CWLSubcompositorResource::CWLSubcompositorResource(SP resource_) : resource(resource_) { - if (!good()) + if UNLIKELY (!good()) return; resource->setOnDestroy([this](CWlSubcompositor* r) { PROTO::subcompositor->destroyResource(this); }); @@ -152,12 +152,12 @@ CWLSubcompositorResource::CWLSubcompositorResource(SP resource auto SURF = CWLSurfaceResource::fromResource(surface); auto PARENT = CWLSurfaceResource::fromResource(parent); - if (!SURF || !PARENT || SURF == PARENT) { + if UNLIKELY (!SURF || !PARENT || SURF == PARENT) { r->error(WL_SUBCOMPOSITOR_ERROR_BAD_SURFACE, "Invalid surface/parent"); return; } - if (SURF->role->role() != SURFACE_ROLE_UNASSIGNED) { + if UNLIKELY (SURF->role->role() != SURFACE_ROLE_UNASSIGNED) { r->error(-1, "Surface already has a different role"); return; } @@ -170,7 +170,7 @@ CWLSubcompositorResource::CWLSubcompositorResource(SP resource } else t1Parent = PARENT; - if (t1Parent == SURF) { + if UNLIKELY (t1Parent == SURF) { r->error(WL_SUBCOMPOSITOR_ERROR_BAD_PARENT, "Bad parent, t1 parent == surf"); return; } @@ -178,7 +178,7 @@ CWLSubcompositorResource::CWLSubcompositorResource(SP resource const auto RESOURCE = PROTO::subcompositor->m_vSurfaces.emplace_back(makeShared(makeShared(r->client(), r->version(), id), SURF, PARENT)); - if (!RESOURCE->good()) { + if UNLIKELY (!RESOURCE->good()) { r->noMemory(); PROTO::subcompositor->m_vSurfaces.pop_back(); return; @@ -205,7 +205,7 @@ CWLSubcompositorProtocol::CWLSubcompositorProtocol(const wl_interface* iface, co void CWLSubcompositorProtocol::bindManager(wl_client* client, void* data, uint32_t ver, uint32_t id) { const auto RESOURCE = m_vManagers.emplace_back(makeShared(makeShared(client, ver, id))); - if (!RESOURCE->good()) { + if UNLIKELY (!RESOURCE->good()) { wl_client_post_no_memory(client); m_vManagers.pop_back(); return; diff --git a/src/protocols/types/DMABuffer.cpp b/src/protocols/types/DMABuffer.cpp index 9f31f6a2..3f53225c 100644 --- a/src/protocols/types/DMABuffer.cpp +++ b/src/protocols/types/DMABuffer.cpp @@ -17,11 +17,11 @@ CDMABuffer::CDMABuffer(uint32_t id, wl_client* client, Aquamarine::SDMABUFAttrs auto eglImage = g_pHyprOpenGL->createEGLImage(attrs); - if (!eglImage) { + if UNLIKELY (!eglImage) { Debug::log(ERR, "CDMABuffer: failed to import EGLImage, retrying as implicit"); attrs.modifier = DRM_FORMAT_MOD_INVALID; eglImage = g_pHyprOpenGL->createEGLImage(attrs); - if (!eglImage) { + if UNLIKELY (!eglImage) { Debug::log(ERR, "CDMABuffer: failed to import EGLImage"); return; } @@ -31,7 +31,7 @@ CDMABuffer::CDMABuffer(uint32_t id, wl_client* client, Aquamarine::SDMABUFAttrs opaque = NFormatUtils::isFormatOpaque(attrs.format); success = texture->m_iTexID; - if (!success) + if UNLIKELY (!success) Debug::log(ERR, "Failed to create a dmabuf: texture is null"); } diff --git a/src/protocols/types/WLBuffer.cpp b/src/protocols/types/WLBuffer.cpp index a9e6400a..4bd115a2 100644 --- a/src/protocols/types/WLBuffer.cpp +++ b/src/protocols/types/WLBuffer.cpp @@ -6,7 +6,7 @@ #include CWLBufferResource::CWLBufferResource(SP resource_) : resource(resource_) { - if (!good()) + if UNLIKELY (!good()) return; resource->setOnDestroy([this](CWlBuffer* r) { From 76a899627ecff1f4fa3644ee06d8e1d279634850 Mon Sep 17 00:00:00 2001 From: vaxerski Date: Fri, 17 Jan 2025 18:24:10 +0100 Subject: [PATCH 0859/2181] regex: log an error if regex parsing fails --- src/desktop/Rule.cpp | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/desktop/Rule.cpp b/src/desktop/Rule.cpp index dd1848d4..ae280642 100644 --- a/src/desktop/Rule.cpp +++ b/src/desktop/Rule.cpp @@ -1,11 +1,16 @@ #include "Rule.hpp" #include +#include "../debug/Log.hpp" CRuleRegexContainer::CRuleRegexContainer(const std::string& regex_) { const bool NEGATIVE = regex_.starts_with("negative:"); negative = NEGATIVE; regex = std::make_unique(NEGATIVE ? regex_.substr(9) : regex_); + + // TODO: maybe pop an error? + if (!regex->ok()) + Debug::log(ERR, "RuleRegexContainer: regex {} failed to parse!", regex_); } bool CRuleRegexContainer::passes(const std::string& str) const { From 401a3bae614ae4863da3e5cd5bf4d9997a893045 Mon Sep 17 00:00:00 2001 From: vaxerski Date: Fri, 17 Jan 2025 18:28:53 +0100 Subject: [PATCH 0860/2181] core: fix warning in shadow --- src/render/decorations/CHyprDropShadowDecoration.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/src/render/decorations/CHyprDropShadowDecoration.cpp b/src/render/decorations/CHyprDropShadowDecoration.cpp index 022e123e..c576b966 100644 --- a/src/render/decorations/CHyprDropShadowDecoration.cpp +++ b/src/render/decorations/CHyprDropShadowDecoration.cpp @@ -56,7 +56,6 @@ void CHyprDropShadowDecoration::damageEntire() { static auto PSHADOWIGNOREWINDOW = CConfigValue("decoration:shadow:ignore_window"); const auto ROUNDING = PWINDOW->rounding(); - const auto ROUNDINGPOWER = PWINDOW->roundingPower(); const auto ROUNDINGSIZE = ROUNDING - M_SQRT1_2 * ROUNDING + 1; CRegion shadowRegion(shadowBox); From b65f8a87232c13697f0469fb7dfa31ff4f14af22 Mon Sep 17 00:00:00 2001 From: Beau Date: Fri, 17 Jan 2025 18:35:39 +0100 Subject: [PATCH 0861/2181] desktop/DesktopTypes.hpp: fix include (#9104) --- src/desktop/DesktopTypes.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/desktop/DesktopTypes.hpp b/src/desktop/DesktopTypes.hpp index ae2ac366..080f13d3 100644 --- a/src/desktop/DesktopTypes.hpp +++ b/src/desktop/DesktopTypes.hpp @@ -1,5 +1,5 @@ #pragma once -#include "helpers/memory/Memory.hpp" +#include "../helpers/memory/Memory.hpp" class CWorkspace; class CWindow; class CLayerSurface; From 47d645d84a7a290dc974cad552ee4912ca606069 Mon Sep 17 00:00:00 2001 From: vaxerski Date: Fri, 17 Jan 2025 19:14:55 +0100 Subject: [PATCH 0862/2181] core: fixup includes --- src/config/ConfigManager.hpp | 12 ++++++------ src/helpers/Monitor.cpp | 2 +- src/helpers/WLClasses.hpp | 6 +++--- src/managers/AnimationManager.cpp | 8 ++++---- src/protocols/FocusGrab.hpp | 2 +- 5 files changed, 15 insertions(+), 15 deletions(-) diff --git a/src/config/ConfigManager.hpp b/src/config/ConfigManager.hpp index 1ba1df62..bef52584 100644 --- a/src/config/ConfigManager.hpp +++ b/src/config/ConfigManager.hpp @@ -16,12 +16,12 @@ #include "../desktop/LayerRule.hpp" #include "ConfigDataValues.hpp" -#include "SharedDefs.hpp" -#include "helpers/Color.hpp" -#include "desktop/DesktopTypes.hpp" -#include "helpers/memory/Memory.hpp" -#include "desktop/WindowRule.hpp" -#include "managers/XWaylandManager.hpp" +#include "../SharedDefs.hpp" +#include "../helpers/Color.hpp" +#include "../desktop/DesktopTypes.hpp" +#include "../helpers/memory/Memory.hpp" +#include "../desktop/WindowRule.hpp" +#include "../managers/XWaylandManager.hpp" #include diff --git a/src/helpers/Monitor.cpp b/src/helpers/Monitor.cpp index 718baf23..1f00e4ad 100644 --- a/src/helpers/Monitor.cpp +++ b/src/helpers/Monitor.cpp @@ -1,6 +1,6 @@ #include "Monitor.hpp" #include "MiscFunctions.hpp" -#include "macros.hpp" +#include "../macros.hpp" #include "math/Math.hpp" #include "sync/SyncReleaser.hpp" #include "../Compositor.hpp" diff --git a/src/helpers/WLClasses.hpp b/src/helpers/WLClasses.hpp index c2e828e7..bedea065 100644 --- a/src/helpers/WLClasses.hpp +++ b/src/helpers/WLClasses.hpp @@ -4,9 +4,9 @@ #include "../desktop/Subsurface.hpp" #include "../desktop/Popup.hpp" #include "../desktop/WLSurface.hpp" -#include "macros.hpp" -#include "desktop/DesktopTypes.hpp" -#include "helpers/memory/Memory.hpp" +#include "../macros.hpp" +#include "../desktop/DesktopTypes.hpp" +#include "memory/Memory.hpp" #include "signal/Signal.hpp" class CMonitor; diff --git a/src/managers/AnimationManager.cpp b/src/managers/AnimationManager.cpp index 9cf35116..f884acdd 100644 --- a/src/managers/AnimationManager.cpp +++ b/src/managers/AnimationManager.cpp @@ -1,10 +1,10 @@ #include "AnimationManager.hpp" #include "../Compositor.hpp" #include "HookSystemManager.hpp" -#include "config/ConfigManager.hpp" -#include "desktop/DesktopTypes.hpp" -#include "helpers/AnimatedVariable.hpp" -#include "macros.hpp" +#include "../config/ConfigManager.hpp" +#include "../desktop/DesktopTypes.hpp" +#include "../helpers/AnimatedVariable.hpp" +#include "../macros.hpp" #include "../config/ConfigValue.hpp" #include "../desktop/Window.hpp" #include "../desktop/LayerSurface.hpp" diff --git a/src/protocols/FocusGrab.hpp b/src/protocols/FocusGrab.hpp index 6fe8780f..3c907ed0 100644 --- a/src/protocols/FocusGrab.hpp +++ b/src/protocols/FocusGrab.hpp @@ -2,7 +2,7 @@ #include "WaylandProtocol.hpp" #include "hyprland-focus-grab-v1.hpp" -#include "macros.hpp" +#include "../macros.hpp" #include #include #include From 078e13f463d56a4e773aa104bca5567b9e9c8658 Mon Sep 17 00:00:00 2001 From: UjinT34 <41110182+UjinT34@users.noreply.github.com> Date: Fri, 17 Jan 2025 23:23:57 +0300 Subject: [PATCH 0863/2181] renderer: Auto enable wide color gamut in HDR mode (#9090) --- src/helpers/Monitor.hpp | 1 + src/render/Renderer.cpp | 29 ++++++++++++++++++++--------- src/render/Renderer.hpp | 1 - 3 files changed, 21 insertions(+), 10 deletions(-) diff --git a/src/helpers/Monitor.hpp b/src/helpers/Monitor.hpp index 3335a896..b33725d5 100644 --- a/src/helpers/Monitor.hpp +++ b/src/helpers/Monitor.hpp @@ -192,6 +192,7 @@ class CMonitor { bool m_bEnabled = false; bool m_bRenderingInitPassed = false; + WP m_previousFSWindow; // For the list lookup diff --git a/src/render/Renderer.cpp b/src/render/Renderer.cpp index fddb9a9a..384db1e6 100644 --- a/src/render/Renderer.cpp +++ b/src/render/Renderer.cpp @@ -1466,12 +1466,6 @@ bool CHyprRenderer::commitPendingAndDoExplicitSync(PHLMONITOR pMonitor) { if (inFD >= 0) pMonitor->output->state->setExplicitInFence(inFD); - static auto PWIDE = CConfigValue("experimental:wide_color_gamut"); - if (pMonitor->output->state->state().wideColorGamut != *PWIDE) { - Debug::log(TRACE, "Setting wide color gamut {}", *PWIDE ? "on" : "off"); - pMonitor->output->state->setWideColorGamut(*PWIDE); - } - static auto PHDR = CConfigValue("experimental:hdr"); const bool SUPPORTSPQ = pMonitor->output->parsedEDID.hdrMetadata.has_value() ? pMonitor->output->parsedEDID.hdrMetadata->supportsPQ : false; @@ -1481,18 +1475,35 @@ bool CHyprRenderer::commitPendingAndDoExplicitSync(PHLMONITOR pMonitor) { const auto WINDOW = pMonitor->activeWorkspace->getFullscreenWindow(); const auto SURF = WINDOW->m_pWLSurface->resource(); if (SURF->colorManagement.valid() && SURF->colorManagement->hasImageDescription()) { - bool needsHdrMetadataUpdate = SURF->colorManagement->needsHdrMetadataUpdate() || m_previousFSWindow != WINDOW; + bool needsHdrMetadataUpdate = SURF->colorManagement->needsHdrMetadataUpdate() || pMonitor->m_previousFSWindow != WINDOW; if (SURF->colorManagement->needsHdrMetadataUpdate()) SURF->colorManagement->setHDRMetadata(createHDRMetadata(SURF->colorManagement.get()->imageDescription(), pMonitor->output->parsedEDID)); if (needsHdrMetadataUpdate) pMonitor->output->state->setHDRMetadata(SURF->colorManagement->hdrMetadata()); } else if ((pMonitor->output->state->state().hdrMetadata.hdmi_metadata_type1.eotf == 2) != *PHDR) pMonitor->output->state->setHDRMetadata(*PHDR ? createHDRMetadata(2, pMonitor->output->parsedEDID) : createHDRMetadata(0, pMonitor->output->parsedEDID)); - m_previousFSWindow = WINDOW; + pMonitor->m_previousFSWindow = WINDOW; } else { if ((pMonitor->output->state->state().hdrMetadata.hdmi_metadata_type1.eotf == 2) != *PHDR) pMonitor->output->state->setHDRMetadata(*PHDR ? createHDRMetadata(2, pMonitor->output->parsedEDID) : createHDRMetadata(0, pMonitor->output->parsedEDID)); - m_previousFSWindow.reset(); + pMonitor->m_previousFSWindow.reset(); + } + } + + static auto PWIDE = CConfigValue("experimental:wide_color_gamut"); + const bool needsWCG = *PWIDE || pMonitor->output->state->state().hdrMetadata.hdmi_metadata_type1.eotf == 2; + if (pMonitor->output->state->state().wideColorGamut != needsWCG) { + Debug::log(TRACE, "Setting wide color gamut {}", needsWCG ? "on" : "off"); + pMonitor->output->state->setWideColorGamut(needsWCG); + + // FIXME do not trust enabled10bit, auto switch to 10bit and back if needed + if (needsWCG && !pMonitor->enabled10bit) { + Debug::log(WARN, "Wide color gamut is enabled but the display is not in 10bit mode"); + static bool shown = false; + if (!shown) { + g_pHyprNotificationOverlay->addNotification("Wide color gamut is enabled but the display is not in 10bit mode", CHyprColor{}, 15000, ICON_WARNING); + shown = true; + } } } diff --git a/src/render/Renderer.hpp b/src/render/Renderer.hpp index 6ba7a654..7aef96e6 100644 --- a/src/render/Renderer.hpp +++ b/src/render/Renderer.hpp @@ -130,7 +130,6 @@ class CHyprRenderer { bool commitPendingAndDoExplicitSync(PHLMONITOR pMonitor); - WP m_previousFSWindow; bool m_bCursorHidden = false; bool m_bCursorHasSurface = false; SP m_pCurrentRenderbuffer = nullptr; From d01756c1f41977e852eba1cbf45c0149ae0f08e8 Mon Sep 17 00:00:00 2001 From: Mihai Fufezan Date: Sat, 18 Jan 2025 10:59:25 +0200 Subject: [PATCH 0864/2181] Meson: properly install 'hyprland' symlink (#9091) --- CMakeLists.txt | 11 +++++++++-- src/meson.build | 6 ++++++ 2 files changed, 15 insertions(+), 2 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index c1ecb14c..532f1d95 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -248,7 +248,15 @@ target_precompile_headers(Hyprland PRIVATE message(STATUS "Setting link libraries") -target_link_libraries(Hyprland rt PkgConfig::aquamarine_dep PkgConfig::hyprlang_dep PkgConfig::hyprutils_dep PkgConfig::hyprcursor_dep PkgConfig::hyprgraphics_dep PkgConfig::deps) +target_link_libraries( + Hyprland + rt + PkgConfig::aquamarine_dep + PkgConfig::hyprlang_dep + PkgConfig::hyprutils_dep + PkgConfig::hyprcursor_dep + PkgConfig::hyprgraphics_dep + PkgConfig::deps) if(udis_dep_FOUND) target_link_libraries(Hyprland PkgConfig::udis_dep) else() @@ -369,7 +377,6 @@ install( ${CMAKE_INSTALL_FULL_BINDIR}/Hyprland \ \"\$ENV{DESTDIR}${CMAKE_INSTALL_FULL_BINDIR}/hyprland\" \ )") - # session file install(FILES ${CMAKE_SOURCE_DIR}/example/hyprland.desktop DESTINATION ${CMAKE_INSTALL_DATAROOTDIR}/wayland-sessions) diff --git a/src/meson.build b/src/meson.build index 2efc2213..7054d8e4 100644 --- a/src/meson.build +++ b/src/meson.build @@ -49,3 +49,9 @@ executable( ], install: true, ) + +install_symlink( + 'hyprland', + install_dir: get_option('bindir'), + pointing_to: 'Hyprland', +) From fdfcfc824e715d372b5cc6791d5e1b7c2bc4769b Mon Sep 17 00:00:00 2001 From: Mihai Fufezan Date: Sat, 18 Jan 2025 11:04:40 +0200 Subject: [PATCH 0865/2181] CMake, Meson: add option controlling hyprpm building --- CMakeLists.txt | 8 +++++++- meson.build | 5 ++++- meson_options.txt | 1 + 3 files changed, 12 insertions(+), 2 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 532f1d95..a36d70fe 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -366,7 +366,13 @@ protocolwayland() # tools add_subdirectory(hyprctl) -add_subdirectory(hyprpm) + +if(NO_HYPRPM) + message(STATUS "hyprpm is disabled") +else() + add_subdirectory(hyprpm) + message(STATUS "hyprpm is enabled (NO_HYPRPM not defined)") +endif() # binary and symlink install(TARGETS Hyprland) diff --git a/meson.build b/meson.build index d79a2845..6b50ff2d 100644 --- a/meson.build +++ b/meson.build @@ -101,11 +101,14 @@ endif subdir('protocols') subdir('src') subdir('hyprctl') -subdir('hyprpm/src') subdir('assets') subdir('example') subdir('docs') +if get_option('hyprpm').enabled() + subdir('hyprpm/src') +endif + # Generate hyprland.pc pkg_install_dir = join_paths(get_option('datadir'), 'pkgconfig') diff --git a/meson_options.txt b/meson_options.txt index 9b64fb32..3eb01696 100644 --- a/meson_options.txt +++ b/meson_options.txt @@ -2,4 +2,5 @@ option('xwayland', type: 'feature', value: 'auto', description: 'Enable support option('systemd', type: 'feature', value: 'auto', description: 'Enable systemd integration') option('uwsm', type: 'feature', value: 'enabled', description: 'Enable uwsm integration (only if systemd is enabled)') option('legacy_renderer', type: 'feature', value: 'disabled', description: 'Enable legacy renderer') +option('hyprpm', type: 'feature', value: 'enabled', description: 'Enable hyprpm') option('tracy_enable', type: 'boolean', value: false , description: 'Enable profiling') From a36fa5c229c175f47602f1b92d97e6a4dd3417a8 Mon Sep 17 00:00:00 2001 From: Mihai Fufezan Date: Sat, 18 Jan 2025 11:05:05 +0200 Subject: [PATCH 0866/2181] Nix: disable hyprpm MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit It does not work properly on Nix anyway. If you were using hyprpm in some way before, please switch to using the `plugins` option in the HM module (and the upcoming option in the NixOS module, soon™). --- nix/default.nix | 1 + 1 file changed, 1 insertion(+) diff --git a/nix/default.nix b/nix/default.nix index 8e3af31d..a4ddc63b 100644 --- a/nix/default.nix +++ b/nix/default.nix @@ -163,6 +163,7 @@ in "xwayland" = enableXWayland; "legacy_renderer" = legacyRenderer; "uwsm" = false; + "hyprpm" = false; }) (mapAttrsToList mesonBool { "b_pch" = false; From f56153a9c1b0a00fac0932a95e0cfa5a4f6c681f Mon Sep 17 00:00:00 2001 From: Charlie Root Date: Sat, 18 Jan 2025 10:48:38 +0000 Subject: [PATCH 0867/2181] nix/module.nix: expand nixos module for configuring hyprland Expand the nixos module to be able to configure hyprland, just like the current home-manager module does. --- nix/module.nix | 205 +++++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 198 insertions(+), 7 deletions(-) diff --git a/nix/module.nix b/nix/module.nix index 6f553893..46191dfa 100644 --- a/nix/module.nix +++ b/nix/module.nix @@ -7,15 +7,206 @@ inputs: { inherit (pkgs.stdenv.hostPlatform) system; cfg = config.programs.hyprland; - package = inputs.self.packages.${system}.hyprland; - portalPackage = inputs.self.packages.${system}.xdg-desktop-portal-hyprland.override { - hyprland = cfg.finalPackage; - }; + # basically 1:1 taken from https://github.com/nix-community/home-manager/blob/master/modules/services/window-managers/hyprland.nix + toHyprconf = { + attrs, + indentLevel ? 0, + importantPrefixes ? ["$"], + }: let + inherit + (lib) + all + concatMapStringsSep + concatStrings + concatStringsSep + filterAttrs + foldl + generators + hasPrefix + isAttrs + isList + mapAttrsToList + replicate + ; + + initialIndent = concatStrings (replicate indentLevel " "); + + toHyprconf' = indent: attrs: let + sections = + filterAttrs (n: v: isAttrs v || (isList v && all isAttrs v)) attrs; + + mkSection = n: attrs: + if lib.isList attrs + then (concatMapStringsSep "\n" (a: mkSection n a) attrs) + else '' + ${indent}${n} { + ${toHyprconf' " ${indent}" attrs}${indent}} + ''; + + mkFields = generators.toKeyValue { + listsAsDuplicateKeys = true; + inherit indent; + }; + + allFields = + filterAttrs (n: v: !(isAttrs v || (isList v && all isAttrs v))) + attrs; + + isImportantField = n: _: + foldl (acc: prev: + if hasPrefix prev n + then true + else acc) + false + importantPrefixes; + + importantFields = filterAttrs isImportantField allFields; + + fields = + builtins.removeAttrs allFields + (mapAttrsToList (n: _: n) importantFields); + in + mkFields importantFields + + concatStringsSep "\n" (mapAttrsToList mkSection sections) + + mkFields fields; + in + toHyprconf' initialIndent attrs; in { - config = { + options = { programs.hyprland = { - package = lib.mkDefault package; - portalPackage = lib.mkDefault portalPackage; + plugins = lib.mkOption { + type = with lib.types; listOf (either package path); + default = []; + description = '' + List of Hyprland plugins to use. Can either be packages or + absolute plugin paths. + ''; + }; + + settings = lib.mkOption { + type = with lib.types; let + valueType = + nullOr (oneOf [ + bool + int + float + str + path + (attrsOf valueType) + (listOf valueType) + ]) + // { + description = "Hyprland configuration value"; + }; + in + valueType; + default = {}; + description = '' + Hyprland configuration written in Nix. Entries with the same key + should be written as lists. Variables' and colors' names should be + quoted. See for more examples. + + ::: {.note} + Use the [](#programs.hyprland.plugins) option to + declare plugins. + ::: + + ''; + example = lib.literalExpression '' + { + decoration = { + shadow_offset = "0 5"; + "col.shadow" = "rgba(00000099)"; + }; + + "$mod" = "SUPER"; + + bindm = [ + # mouse movements + "$mod, mouse:272, movewindow" + "$mod, mouse:273, resizewindow" + "$mod ALT, mouse:272, resizewindow" + ]; + } + ''; + }; + + extraConfig = lib.mkOption { + type = lib.types.lines; + default = ""; + example = '' + # window resize + bind = $mod, S, submap, resize + + submap = resize + binde = , right, resizeactive, 10 0 + binde = , left, resizeactive, -10 0 + binde = , up, resizeactive, 0 -10 + binde = , down, resizeactive, 0 10 + bind = , escape, submap, reset + submap = reset + ''; + description = '' + Extra configuration lines to add to `/etc/xdg/hypr/hyprland.conf`. + ''; + }; + + sourceFirst = + lib.mkEnableOption '' + putting source entries at the top of the configuration + '' + // { + default = true; + }; + + importantPrefixes = lib.mkOption { + type = with lib.types; listOf str; + default = ["$" "bezier" "name"] ++ lib.optionals cfg.sourceFirst ["source"]; + example = ["$" "bezier"]; + description = '' + List of prefix of attributes to source at the top of the config. + ''; + }; }; }; + config = lib.mkMerge [ + { + programs.hyprland = { + package = lib.mkDefault inputs.self.packages.${system}.hyprland; + portalPackage = lib.mkDefault (inputs.self.packages.${system}.xdg-desktop-portal-hyprland.override { + hyprland = cfg.finalPackage; + }); + }; + } + (lib.mkIf cfg.enable { + environment.etc."xdg/hypr/hyprland.conf" = let + shouldGenerate = cfg.extraConfig != "" || cfg.settings != {} || cfg.plugins != []; + + pluginsToHyprconf = plugins: + toHyprconf { + attrs = { + plugin = let + mkEntry = entry: + if lib.types.package.check entry + then "${entry}/lib/lib${entry.pname}.so" + else entry; + in + map mkEntry cfg.plugins; + }; + inherit (cfg) importantPrefixes; + }; + in + lib.mkIf shouldGenerate { + text = + lib.optionalString (cfg.plugins != []) + (pluginsToHyprconf cfg.plugins) + + lib.optionalString (cfg.settings != {}) + (toHyprconf { + attrs = cfg.settings; + inherit (cfg) importantPrefixes; + }) + + lib.optionalString (cfg.extraConfig != "") cfg.extraConfig; + }; + }) + ]; } From 4da9b7cc5b50c346309378fbb5ae8aa07746fd33 Mon Sep 17 00:00:00 2001 From: Tom Englund Date: Sun, 19 Jan 2025 10:38:42 +0000 Subject: [PATCH 0868/2181] core: reserve vector sizes as much as we can (#9118) avoid reallocations as much as possible with a few edge cases where the reservation overshoots a tiny bit. but a few bytes of memory short term is better used then the overhead of potential reallocation. --- src/Compositor.cpp | 6 ++---- src/desktop/Window.cpp | 2 ++ src/managers/KeybindManager.cpp | 4 +--- src/protocols/DRMLease.cpp | 3 +++ src/protocols/GlobalShortcuts.cpp | 15 +++++++++++++-- src/protocols/Screencopy.cpp | 2 ++ src/protocols/ToplevelExport.cpp | 2 ++ src/render/OpenGL.cpp | 14 +++++++++++--- src/render/decorations/DecorationPositioner.cpp | 3 +++ src/xwayland/Dnd.cpp | 2 ++ src/xwayland/XWM.cpp | 4 ++++ 11 files changed, 45 insertions(+), 12 deletions(-) diff --git a/src/Compositor.cpp b/src/Compositor.cpp index 496ca4fe..889ae181 100644 --- a/src/Compositor.cpp +++ b/src/Compositor.cpp @@ -2785,11 +2785,9 @@ PHLWINDOW CCompositor::getForceFocus() { void CCompositor::arrangeMonitors() { static auto* const PXWLFORCESCALEZERO = (Hyprlang::INT* const*)g_pConfigManager->getConfigValuePtr("xwayland:force_zero_scaling"); - std::vector toArrange; + std::vector toArrange(m_vMonitors.begin(), m_vMonitors.end()); std::vector arranged; - - for (auto const& m : m_vMonitors) - toArrange.push_back(m); + arranged.reserve(toArrange.size()); Debug::log(LOG, "arrangeMonitors: {} to arrange", toArrange.size()); diff --git a/src/desktop/Window.cpp b/src/desktop/Window.cpp index 241a17d7..829f4e2e 100644 --- a/src/desktop/Window.cpp +++ b/src/desktop/Window.cpp @@ -282,6 +282,8 @@ void CWindow::updateWindowDecos() { // make a copy because updateWindow can remove decos. std::vector decos; + // reserve to avoid reallocations + decos.reserve(m_dWindowDecorations.size()); for (auto const& wd : m_dWindowDecorations) { decos.push_back(wd.get()); diff --git a/src/managers/KeybindManager.cpp b/src/managers/KeybindManager.cpp index a1979206..65891840 100644 --- a/src/managers/KeybindManager.cpp +++ b/src/managers/KeybindManager.cpp @@ -1891,9 +1891,7 @@ SDispatchResult CKeybindManager::workspaceOpt(std::string args) { // apply // we make a copy because changeWindowFloatingMode might invalidate the iterator - std::vector ptrs; - for (auto const& w : g_pCompositor->m_vWindows) - ptrs.push_back(w); + std::vector ptrs(g_pCompositor->m_vWindows.begin(), g_pCompositor->m_vWindows.end()); for (auto const& w : ptrs) { if (!w->m_bIsMapped || w->m_pWorkspace != PWORKSPACE || w->isHidden()) diff --git a/src/protocols/DRMLease.cpp b/src/protocols/DRMLease.cpp index fce1e345..6fdbaf4b 100644 --- a/src/protocols/DRMLease.cpp +++ b/src/protocols/DRMLease.cpp @@ -34,6 +34,9 @@ CDRMLeaseResource::CDRMLeaseResource(SP resource_, SP> outputs; + // reserve to avoid reallocations + outputs.reserve(requested.size()); + for (auto const& m : requested) { outputs.emplace_back(m->monitor->output); } diff --git a/src/protocols/GlobalShortcuts.cpp b/src/protocols/GlobalShortcuts.cpp index 6fac2d7f..9f8f422c 100644 --- a/src/protocols/GlobalShortcuts.cpp +++ b/src/protocols/GlobalShortcuts.cpp @@ -83,8 +83,19 @@ void CGlobalShortcutsProtocol::sendGlobalShortcutEvent(std::string appid, std::s std::vector CGlobalShortcutsProtocol::getAllShortcuts() { std::vector copy; - for (auto const& c : m_vClients) { - for (auto const& sh : c->shortcuts) { + // calculate the total number of shortcuts, precomputing size is linear + // and potential reallocation is more costly then the added precompute overhead of looping + // and finding the total size. + size_t totalShortcuts = 0; + for (const auto& c : m_vClients) { + totalShortcuts += c->shortcuts.size(); + } + + // reserve number of elements to avoid reallocations + copy.reserve(totalShortcuts); + + for (const auto& c : m_vClients) { + for (const auto& sh : c->shortcuts) { copy.push_back(*sh); } } diff --git a/src/protocols/Screencopy.cpp b/src/protocols/Screencopy.cpp index 8bdaf8f9..5cf54eb4 100644 --- a/src/protocols/Screencopy.cpp +++ b/src/protocols/Screencopy.cpp @@ -412,6 +412,8 @@ void CScreencopyProtocol::onOutputCommit(PHLMONITOR pMonitor) { } std::vector> framesToRemove; + // reserve number of elements to avoid reallocations + framesToRemove.reserve(m_vFramesAwaitingWrite.size()); // share frame if correct output for (auto const& f : m_vFramesAwaitingWrite) { diff --git a/src/protocols/ToplevelExport.cpp b/src/protocols/ToplevelExport.cpp index 2d40cb78..fb49f722 100644 --- a/src/protocols/ToplevelExport.cpp +++ b/src/protocols/ToplevelExport.cpp @@ -393,6 +393,8 @@ void CToplevelExportProtocol::onOutputCommit(PHLMONITOR pMonitor) { return; // nothing to share std::vector> framesToRemove; + // reserve number of elements to avoid reallocations + framesToRemove.reserve(m_vFramesAwaitingWrite.size()); // share frame if correct output for (auto const& f : m_vFramesAwaitingWrite) { diff --git a/src/render/OpenGL.cpp b/src/render/OpenGL.cpp index c5bb3620..ceb94c81 100644 --- a/src/render/OpenGL.cpp +++ b/src/render/OpenGL.cpp @@ -400,7 +400,10 @@ std::optional> CHyprOpenGLImpl::getModsForFormat(EGLint fo m_sProc.eglQueryDmaBufModifiersEXT(m_pEglDisplay, format, len, mods.data(), external.data(), &len); std::vector result; - bool linearIsExternal = false; + // reserve number of elements to avoid reallocations + result.reserve(mods.size()); + + bool linearIsExternal = false; for (size_t i = 0; i < mods.size(); ++i) { if (external.at(i)) { if (mods.at(i) == DRM_FORMAT_MOD_LINEAR) @@ -449,6 +452,8 @@ void CHyprOpenGLImpl::initDRMFormats() { Debug::log(LOG, "Supported DMA-BUF formats:"); std::vector dmaFormats; + // reserve number of elements to avoid reallocations + dmaFormats.reserve(formats.size()); for (auto const& fmt : formats) { std::vector mods; @@ -472,8 +477,10 @@ void CHyprOpenGLImpl::initDRMFormats() { }); std::vector> modifierData; + // reserve number of elements to avoid reallocations + modifierData.reserve(mods.size()); - auto fmtName = drmGetFormatName(fmt); + auto fmtName = drmGetFormatName(fmt); Debug::log(LOG, "EGL: GPU Supports Format {} (0x{:x})", fmtName ? fmtName : "?unknown?", fmt); for (auto const& mod : mods) { auto modName = drmGetFormatModifierName(mod); @@ -2942,7 +2949,8 @@ SP CHyprOpenGLImpl::createEGLSync(int fenceFD) { Debug::log(ERR, "createEGLSync: dup failed"); return nullptr; } - + // reserve number of elements to avoid reallocations + attribs.reserve(3); attribs.push_back(EGL_SYNC_NATIVE_FENCE_FD_ANDROID); attribs.push_back(dupFd); attribs.push_back(EGL_NONE); diff --git a/src/render/decorations/DecorationPositioner.cpp b/src/render/decorations/DecorationPositioner.cpp index c2d34fb6..2ba3c4a7 100644 --- a/src/render/decorations/DecorationPositioner.cpp +++ b/src/render/decorations/DecorationPositioner.cpp @@ -122,6 +122,9 @@ void CDecorationPositioner::onWindowUpdate(PHLWINDOW pWindow) { // std::vector datas; + // reserve to avoid reallocations + datas.reserve(pWindow->m_dWindowDecorations.size()); + for (auto const& wd : pWindow->m_dWindowDecorations) { datas.push_back(getDataFor(wd.get(), pWindow)); } diff --git a/src/xwayland/Dnd.cpp b/src/xwayland/Dnd.cpp index 58fc6db3..d4ae3780 100644 --- a/src/xwayland/Dnd.cpp +++ b/src/xwayland/Dnd.cpp @@ -75,6 +75,8 @@ void CX11DataDevice::sendEnter(uint32_t serial, SP surf, con data.data32[1] |= 1; std::vector targets; + // reserve to avoid reallocations + targets.reserve(SOURCE->mimes().size()); for (auto& mime : SOURCE->mimes()) { targets.emplace_back(g_pXWayland->pWM->mimeToAtom(mime)); diff --git a/src/xwayland/XWM.cpp b/src/xwayland/XWM.cpp index 44485381..ae8e0ccc 100644 --- a/src/xwayland/XWM.cpp +++ b/src/xwayland/XWM.cpp @@ -643,6 +643,8 @@ void CXWM::handleSelectionRequest(xcb_selection_request_event_t* e) { Debug::log(WARN, "[xwm] WARNING: No mimes in TARGETS?"); std::vector atoms; + // reserve to avoid reallocations + atoms.reserve(mimes.size() + 2); atoms.push_back(HYPRATOMS["TIMESTAMP"]); atoms.push_back(HYPRATOMS["TARGETS"]); @@ -989,6 +991,8 @@ void CXWM::sendState(SP surf) { } std::vector props; + // reserve to avoid reallocations + props.reserve(6); // props below if (surf->modal) props.push_back(HYPRATOMS["_NET_WM_STATE_MODAL"]); if (surf->fullscreen) From 086fd7ece8cc8904909f5a597ab69fe73ecac34c Mon Sep 17 00:00:00 2001 From: outfoxxed Date: Sun, 19 Jan 2025 04:51:42 -0800 Subject: [PATCH 0869/2181] protocols: do not destroy screencopy resources before client request (#9048) --- src/protocols/Screencopy.cpp | 4 ---- src/protocols/ToplevelExport.cpp | 6 ------ 2 files changed, 10 deletions(-) diff --git a/src/protocols/Screencopy.cpp b/src/protocols/Screencopy.cpp index 5cf54eb4..e0e3a559 100644 --- a/src/protocols/Screencopy.cpp +++ b/src/protocols/Screencopy.cpp @@ -28,7 +28,6 @@ CScreencopyFrame::CScreencopyFrame(SP resource_, int32_t if (!pMonitor) { LOGM(ERR, "Client requested sharing of a monitor that doesnt exist"); resource->sendFailed(); - PROTO::screencopy->destroyResource(this); return; } @@ -46,7 +45,6 @@ CScreencopyFrame::CScreencopyFrame(SP resource_, int32_t if (shmFormat == DRM_FORMAT_INVALID) { LOGM(ERR, "No format supported by renderer in capture output"); resource->sendFailed(); - PROTO::screencopy->destroyResource(this); return; } @@ -58,7 +56,6 @@ CScreencopyFrame::CScreencopyFrame(SP resource_, int32_t if (!PSHMINFO) { LOGM(ERR, "No pixel format supported by renderer in capture output"); resource->sendFailed(); - PROTO::screencopy->destroyResource(this); return; } @@ -93,7 +90,6 @@ void CScreencopyFrame::copy(CZwlrScreencopyFrameV1* pFrame, wl_resource* buffer_ if UNLIKELY (!g_pCompositor->monitorExists(pMonitor.lock())) { LOGM(ERR, "Client requested sharing of a monitor that is gone"); resource->sendFailed(); - PROTO::screencopy->destroyResource(this); return; } diff --git a/src/protocols/ToplevelExport.cpp b/src/protocols/ToplevelExport.cpp index fb49f722..8b835b50 100644 --- a/src/protocols/ToplevelExport.cpp +++ b/src/protocols/ToplevelExport.cpp @@ -86,14 +86,12 @@ CToplevelExportFrame::CToplevelExportFrame(SP re if UNLIKELY (!pWindow) { LOGM(ERR, "Client requested sharing of window handle {:x} which does not exist!", pWindow); resource->sendFailed(); - PROTO::toplevelExport->destroyResource(this); return; } if UNLIKELY (!pWindow->m_bIsMapped) { LOGM(ERR, "Client requested sharing of window handle {:x} which is not shareable!", pWindow); resource->sendFailed(); - PROTO::toplevelExport->destroyResource(this); return; } @@ -109,7 +107,6 @@ CToplevelExportFrame::CToplevelExportFrame(SP re if UNLIKELY (shmFormat == DRM_FORMAT_INVALID) { LOGM(ERR, "No format supported by renderer in capture toplevel"); resource->sendFailed(); - PROTO::toplevelExport->destroyResource(this); return; } @@ -117,7 +114,6 @@ CToplevelExportFrame::CToplevelExportFrame(SP re if UNLIKELY (!PSHMINFO) { LOGM(ERR, "No pixel format supported by renderer in capture toplevel"); resource->sendFailed(); - PROTO::toplevelExport->destroyResource(this); return; } @@ -146,14 +142,12 @@ void CToplevelExportFrame::copy(CHyprlandToplevelExportFrameV1* pFrame, wl_resou if UNLIKELY (!validMapped(pWindow)) { LOGM(ERR, "Client requested sharing of window handle {:x} which is gone!", pWindow); resource->sendFailed(); - PROTO::toplevelExport->destroyResource(this); return; } if UNLIKELY (!pWindow->m_bIsMapped) { LOGM(ERR, "Client requested sharing of window handle {:x} which is not shareable (2)!", pWindow); resource->sendFailed(); - PROTO::toplevelExport->destroyResource(this); return; } From 0a0e56d99c3b5f900ec561b3fe9a3c8a64fe1217 Mon Sep 17 00:00:00 2001 From: vaxerski Date: Sun, 19 Jan 2025 14:02:47 +0100 Subject: [PATCH 0870/2181] core: use readFileAsString instead of cat for os-release --- src/helpers/MiscFunctions.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/helpers/MiscFunctions.cpp b/src/helpers/MiscFunctions.cpp index fafe1811..5ebb0842 100644 --- a/src/helpers/MiscFunctions.cpp +++ b/src/helpers/MiscFunctions.cpp @@ -5,6 +5,7 @@ #include "../managers/TokenManager.hpp" #include "Monitor.hpp" #include "../config/ConfigManager.hpp" +#include "fs/FsUtils.hpp" #include #include #include @@ -621,7 +622,7 @@ void logSystemInfo() { // log etc Debug::log(LOG, "os-release:"); - Debug::log(NONE, "{}", execAndGet("cat /etc/os-release")); + Debug::log(NONE, "{}", NFsUtils::readFileAsString("/etc/os-release").value_or("error")); } int64_t getPPIDof(int64_t pid) { From 8dd2cd41fb4c5a5eb6886cc190419b36084cabfa Mon Sep 17 00:00:00 2001 From: vaxerski Date: Sun, 19 Jan 2025 15:39:19 +0100 Subject: [PATCH 0871/2181] core: move to inotify for monitoring the config files instead of manually polling every second which is not efficient, use inotify. an added bonus is that inotify is much much faster --- src/Compositor.cpp | 7 +- src/Compositor.hpp | 1 - src/config/ConfigManager.cpp | 70 +++++--------------- src/config/ConfigManager.hpp | 7 +- src/config/ConfigWatcher.cpp | 72 +++++++++++++++++++++ src/config/ConfigWatcher.hpp | 32 +++++++++ src/debug/HyprCtl.cpp | 7 +- src/managers/ThreadManager.cpp | 26 -------- src/managers/ThreadManager.hpp | 16 ----- src/managers/eventLoop/EventLoopManager.cpp | 11 ++++ src/managers/eventLoop/EventLoopManager.hpp | 2 + src/plugins/PluginAPI.cpp | 3 +- src/plugins/PluginSystem.cpp | 5 +- 13 files changed, 143 insertions(+), 116 deletions(-) create mode 100644 src/config/ConfigWatcher.cpp create mode 100644 src/config/ConfigWatcher.hpp delete mode 100644 src/managers/ThreadManager.cpp delete mode 100644 src/managers/ThreadManager.hpp diff --git a/src/Compositor.cpp b/src/Compositor.cpp index 889ae181..325bd882 100644 --- a/src/Compositor.cpp +++ b/src/Compositor.cpp @@ -4,6 +4,7 @@ #include "debug/Log.hpp" #include "helpers/Splashes.hpp" #include "config/ConfigValue.hpp" +#include "config/ConfigWatcher.hpp" #include "managers/CursorManager.hpp" #include "managers/TokenManager.hpp" #include "managers/PointerManager.hpp" @@ -44,7 +45,6 @@ #include "managers/KeybindManager.hpp" #include "managers/SessionLockManager.hpp" -#include "managers/ThreadManager.hpp" #include "managers/XWaylandManager.hpp" #include "config/ConfigManager.hpp" @@ -551,7 +551,6 @@ void CCompositor::cleanup() { g_pProtocolManager.reset(); g_pHyprRenderer.reset(); g_pHyprOpenGL.reset(); - g_pThreadManager.reset(); g_pConfigManager.reset(); g_pLayoutManager.reset(); g_pHyprError.reset(); @@ -567,6 +566,7 @@ void CCompositor::cleanup() { g_pEventLoopManager.reset(); g_pVersionKeeperMgr.reset(); g_pDonationNagManager.reset(); + g_pConfigWatcher.reset(); if (m_pAqBackend) m_pAqBackend.reset(); @@ -631,9 +631,6 @@ void CCompositor::initManagers(eManagersInitStage stage) { g_pSeatManager = std::make_unique(); } break; case STAGE_LATE: { - Debug::log(LOG, "Creating the ThreadManager!"); - g_pThreadManager = std::make_unique(); - Debug::log(LOG, "Creating CHyprCtl"); g_pHyprCtl = std::make_unique(); diff --git a/src/Compositor.hpp b/src/Compositor.hpp index 0a701a59..430e583c 100644 --- a/src/Compositor.hpp +++ b/src/Compositor.hpp @@ -5,7 +5,6 @@ #include #include "defines.hpp" -#include "managers/ThreadManager.hpp" #include "managers/XWaylandManager.hpp" #include "managers/KeybindManager.hpp" #include "managers/SessionLockManager.hpp" diff --git a/src/config/ConfigManager.cpp b/src/config/ConfigManager.cpp index 52f2e316..ebeb2397 100644 --- a/src/config/ConfigManager.cpp +++ b/src/config/ConfigManager.cpp @@ -1,6 +1,7 @@ #include #include "ConfigManager.hpp" +#include "ConfigWatcher.hpp" #include "../managers/KeybindManager.hpp" #include "../Compositor.hpp" @@ -372,8 +373,8 @@ static Hyprlang::CParseResult handlePlugin(const char* c, const char* v) { CConfigManager::CConfigManager() { const auto ERR = verifyConfigExists(); - configPaths.emplace_back(getMainConfigPath()); - m_pConfig = std::make_unique(configPaths.begin()->c_str(), Hyprlang::SConfigOptions{.throwAllErrors = true, .allowMissingConfig = true}); + m_configPaths.emplace_back(getMainConfigPath()); + m_pConfig = std::make_unique(m_configPaths.begin()->c_str(), Hyprlang::SConfigOptions{.throwAllErrors = true, .allowMissingConfig = true}); m_pConfig->addConfigValue("general:border_size", Hyprlang::INT{1}); m_pConfig->addConfigValue("general:no_border_on_floating", Hyprlang::INT{0}); @@ -795,7 +796,7 @@ std::string CConfigManager::getConfigString() { std::string configString; std::string currFileContent; - for (const auto& path : configPaths) { + for (const auto& path : m_configPaths) { std::ifstream configFile(path); configString += ("\n\nConfig File: " + path + ": "); if (!configFile.is_open()) { @@ -883,10 +884,10 @@ std::optional CConfigManager::resetHLConfig() { finalExecRequests.clear(); // paths - configPaths.clear(); + m_configPaths.clear(); std::string mainConfigPath = getMainConfigPath(); Debug::log(LOG, "Using config: {}", mainConfigPath); - configPaths.push_back(mainConfigPath); + m_configPaths.emplace_back(mainConfigPath); const auto RET = verifyConfigExists(); @@ -897,6 +898,8 @@ void CConfigManager::postConfigReload(const Hyprlang::CParseResult& result) { static const auto PENABLEEXPLICIT = CConfigValue("render:explicit_sync"); static int prevEnabledExplicit = *PENABLEEXPLICIT; + g_pConfigWatcher->setWatchList(m_configPaths); + for (auto const& w : g_pCompositor->m_vWindows) { w->uncacheWindowDecos(); } @@ -1029,17 +1032,14 @@ void CConfigManager::postConfigReload(const Hyprlang::CParseResult& result) { void CConfigManager::init() { + g_pConfigWatcher->setOnChange([this](const CConfigWatcher::SConfigWatchEvent& e) { + Debug::log(LOG, "CConfigManager: file {} modified, reloading", e.file); + reload(); + }); + const std::string CONFIGPATH = getMainConfigPath(); reload(); - struct stat fileStat; - int err = stat(CONFIGPATH.c_str(), &fileStat); - if (err != 0) { - Debug::log(WARN, "Error at statting config, error {}", errno); - } - - configModifyTimes[CONFIGPATH] = fileStat.st_mtime; - isFirstLaunch = false; } @@ -1080,37 +1080,6 @@ std::string CConfigManager::parseKeyword(const std::string& COMMAND, const std:: return RET.error ? RET.getError() : ""; } -void CConfigManager::tick() { - std::string CONFIGPATH = getMainConfigPath(); - if (!std::filesystem::exists(CONFIGPATH)) { - Debug::log(ERR, "Config doesn't exist??"); - return; - } - - bool parse = false; - - for (auto const& cf : configPaths) { - struct stat fileStat; - int err = stat(cf.c_str(), &fileStat); - if (err != 0) { - Debug::log(WARN, "Error at ticking config at {}, error {}: {}", cf, err, strerror(err)); - continue; - } - - // check if we need to reload cfg - if (fileStat.st_mtime != configModifyTimes[cf] || m_bForceReload) { - parse = true; - configModifyTimes[cf] = fileStat.st_mtime; - } - } - - if (parse) { - m_bForceReload = false; - - reload(); - } -} - Hyprlang::CConfigValue* CConfigManager::getConfigValueSafeDevice(const std::string& dev, const std::string& val, const std::string& fallback) { const auto VAL = m_pConfig->getSpecialConfigValuePtr("device", val.c_str(), dev.c_str()); @@ -1719,8 +1688,7 @@ void CConfigManager::handlePluginLoads() { if (pluginsChanged) { g_pHyprError->destroy(); - m_bForceReload = true; - tick(); + reload(); } } @@ -2732,16 +2700,8 @@ std::optional CConfigManager::handleSource(const std::string& comma Debug::log(ERR, "source= file doesn't exist: {}", value); return "source= file " + value + " doesn't exist!"; } - configPaths.push_back(value); + m_configPaths.emplace_back(value); - struct stat fileStat; - int err = stat(value.c_str(), &fileStat); - if (err != 0) { - Debug::log(WARN, "Error at ticking config at {}, error {}: {}", value, err, strerror(err)); - return {}; - } - - configModifyTimes[value] = fileStat.st_mtime; auto configCurrentPathBackup = configCurrentPath; configCurrentPath = value; diff --git a/src/config/ConfigManager.hpp b/src/config/ConfigManager.hpp index bef52584..1962e4d2 100644 --- a/src/config/ConfigManager.hpp +++ b/src/config/ConfigManager.hpp @@ -142,8 +142,8 @@ class CConfigManager { public: CConfigManager(); - void tick(); void init(); + void reload(); int getDeviceInt(const std::string&, const std::string&, const std::string& fallback = ""); float getDeviceFloat(const std::string&, const std::string&, const std::string& fallback = ""); @@ -258,15 +258,13 @@ class CConfigManager { {"scrolltouchpad", [](const PHLWINDOW& pWindow) { return &pWindow->m_sWindowData.scrollTouchpad; }}}; bool m_bWantsMonitorReload = false; - bool m_bForceReload = false; bool m_bNoMonitorReload = false; bool isLaunchingExecOnce = false; // For exec-once to skip initial ws tracking private: std::unique_ptr m_pConfig; - std::vector configPaths; // stores all the config paths - std::unordered_map configModifyTimes; // stores modify times + std::vector m_configPaths; Hyprutils::Animation::CAnimationConfigTree m_AnimationTree; @@ -302,7 +300,6 @@ class CConfigManager { std::optional generateConfig(std::string configPath); std::optional verifyConfigExists(); void postConfigReload(const Hyprlang::CParseResult& result); - void reload(); SWorkspaceRule mergeWorkspaceRules(const SWorkspaceRule&, const SWorkspaceRule&); }; diff --git a/src/config/ConfigWatcher.cpp b/src/config/ConfigWatcher.cpp new file mode 100644 index 00000000..38191e9e --- /dev/null +++ b/src/config/ConfigWatcher.cpp @@ -0,0 +1,72 @@ +#include "ConfigWatcher.hpp" +#include +#include "../debug/Log.hpp" +#include +#include + +CConfigWatcher::CConfigWatcher() : m_inotifyFd(inotify_init()) { + if (m_inotifyFd < 0) { + Debug::log(ERR, "CConfigWatcher couldn't open an inotify node. Config will not be automatically reloaded"); + return; + } + + const int FLAGS = fcntl(m_inotifyFd, F_GETFL, 0); + if (fcntl(m_inotifyFd, F_SETFL, FLAGS | O_NONBLOCK) < 0) { + Debug::log(ERR, "CConfigWatcher couldn't non-block inotify node. Config will not be automatically reloaded"); + close(m_inotifyFd); + m_inotifyFd = -1; + return; + } +} + +CConfigWatcher::~CConfigWatcher() { + if (m_inotifyFd >= 0) + close(m_inotifyFd); +} + +int CConfigWatcher::getInotifyFD() { + return m_inotifyFd; +} + +void CConfigWatcher::setWatchList(const std::vector& paths) { + + // we clear all watches first, because whichever fired is now invalid + // or that is at least what it seems to be. + // since we don't know which fired, + // plus it doesn't matter that much, these ops are done rarely and fast anyways. + + // cleanup old paths + for (auto& watch : m_watches) { + inotify_rm_watch(m_inotifyFd, watch.wd); + } + + m_watches.clear(); + + // add new paths + for (const auto& path : paths) { + m_watches.emplace_back(SInotifyWatch{ + .wd = inotify_add_watch(m_inotifyFd, path.c_str(), IN_MODIFY), + .file = path, + }); + } +} + +void CConfigWatcher::setOnChange(const std::function& fn) { + m_watchCallback = fn; +} + +void CConfigWatcher::onInotifyEvent() { + inotify_event ev; + while (read(m_inotifyFd, &ev, sizeof(ev)) > 0) { + const auto WD = std::ranges::find_if(m_watches.begin(), m_watches.end(), [wd = ev.wd](const auto& e) { return e.wd == wd; }); + + if (WD == m_watches.end()) { + Debug::log(ERR, "CConfigWatcher: got an event for wd {} which we don't have?!", ev.wd); + return; + } + + m_watchCallback(SConfigWatchEvent{ + .file = WD->file, + }); + } +} diff --git a/src/config/ConfigWatcher.hpp b/src/config/ConfigWatcher.hpp new file mode 100644 index 00000000..0a698fc8 --- /dev/null +++ b/src/config/ConfigWatcher.hpp @@ -0,0 +1,32 @@ +#pragma once +#include +#include +#include +#include + +class CConfigWatcher { + public: + CConfigWatcher(); + ~CConfigWatcher(); + + struct SConfigWatchEvent { + std::string file; + }; + + int getInotifyFD(); + void setWatchList(const std::vector& paths); + void setOnChange(const std::function& fn); + void onInotifyEvent(); + + private: + struct SInotifyWatch { + int wd = -1; + std::string file; + }; + + std::function m_watchCallback; + std::vector m_watches; + int m_inotifyFd = -1; +}; + +inline std::unique_ptr g_pConfigWatcher = std::make_unique(); \ No newline at end of file diff --git a/src/debug/HyprCtl.cpp b/src/debug/HyprCtl.cpp index 41b0abe1..cfdba100 100644 --- a/src/debug/HyprCtl.cpp +++ b/src/debug/HyprCtl.cpp @@ -1121,13 +1121,10 @@ static std::string reloadRequest(eHyprCtlOutputFormat format, std::string reques const auto REQMODE = request.substr(request.find_last_of(' ') + 1); - g_pConfigManager->m_bForceReload = true; - - if (REQMODE == "config-only") { + if (REQMODE == "config-only") g_pConfigManager->m_bNoMonitorReload = true; - } - g_pConfigManager->tick(); + g_pConfigManager->reload(); return "ok"; } diff --git a/src/managers/ThreadManager.cpp b/src/managers/ThreadManager.cpp deleted file mode 100644 index bd124c99..00000000 --- a/src/managers/ThreadManager.cpp +++ /dev/null @@ -1,26 +0,0 @@ -#include "ThreadManager.hpp" -#include "../debug/HyprCtl.hpp" -#include "../Compositor.hpp" -#include "../config/ConfigValue.hpp" - -static int handleTimer(void* data) { - const auto PTM = (CThreadManager*)data; - - static auto PDISABLECFGRELOAD = CConfigValue("misc:disable_autoreload"); - - if (*PDISABLECFGRELOAD != 1) - g_pConfigManager->tick(); - - wl_event_source_timer_update(PTM->m_esConfigTimer, 1000); - - return 0; -} - -CThreadManager::CThreadManager() : m_esConfigTimer(wl_event_loop_add_timer(g_pCompositor->m_sWLEventLoop, handleTimer, this)) { - wl_event_source_timer_update(m_esConfigTimer, 1000); -} - -CThreadManager::~CThreadManager() { - if (m_esConfigTimer) - wl_event_source_remove(m_esConfigTimer); -} diff --git a/src/managers/ThreadManager.hpp b/src/managers/ThreadManager.hpp deleted file mode 100644 index 13e2fcd8..00000000 --- a/src/managers/ThreadManager.hpp +++ /dev/null @@ -1,16 +0,0 @@ -#pragma once - -#include "../defines.hpp" -struct wl_event_source; - -class CThreadManager { - public: - CThreadManager(); - ~CThreadManager(); - - wl_event_source* m_esConfigTimer = nullptr; - - private: -}; - -inline std::unique_ptr g_pThreadManager; \ No newline at end of file diff --git a/src/managers/eventLoop/EventLoopManager.cpp b/src/managers/eventLoop/EventLoopManager.cpp index db8b49b6..f98efc92 100644 --- a/src/managers/eventLoop/EventLoopManager.cpp +++ b/src/managers/eventLoop/EventLoopManager.cpp @@ -1,6 +1,7 @@ #include "EventLoopManager.hpp" #include "../../debug/Log.hpp" #include "../../Compositor.hpp" +#include "../../config/ConfigWatcher.hpp" #include #include @@ -27,6 +28,8 @@ CEventLoopManager::~CEventLoopManager() { wl_event_source_remove(m_sWayland.eventSource); if (m_sIdle.eventSource) wl_event_source_remove(m_sIdle.eventSource); + if (m_configWatcherInotifySource) + wl_event_source_remove(m_configWatcherInotifySource); if (m_sTimers.timerfd >= 0) close(m_sTimers.timerfd); } @@ -42,9 +45,17 @@ static int aquamarineFDWrite(int fd, uint32_t mask, void* data) { return 1; } +static int configWatcherWrite(int fd, uint32_t mask, void* data) { + g_pConfigWatcher->onInotifyEvent(); + return 0; +} + void CEventLoopManager::enterLoop() { m_sWayland.eventSource = wl_event_loop_add_fd(m_sWayland.loop, m_sTimers.timerfd, WL_EVENT_READABLE, timerWrite, nullptr); + if (const auto FD = g_pConfigWatcher->getInotifyFD(); FD >= 0) + m_configWatcherInotifySource = wl_event_loop_add_fd(m_sWayland.loop, FD, WL_EVENT_READABLE, configWatcherWrite, nullptr); + aqPollFDs = g_pCompositor->m_pAqBackend->getPollFDs(); for (auto const& fd : aqPollFDs) { m_sWayland.aqEventSources.emplace_back(wl_event_loop_add_fd(m_sWayland.loop, fd->fd, WL_EVENT_READABLE, aquamarineFDWrite, fd.get())); diff --git a/src/managers/eventLoop/EventLoopManager.hpp b/src/managers/eventLoop/EventLoopManager.hpp index 39d8bbeb..90402de2 100644 --- a/src/managers/eventLoop/EventLoopManager.hpp +++ b/src/managers/eventLoop/EventLoopManager.hpp @@ -51,6 +51,8 @@ class CEventLoopManager { SIdleData m_sIdle; std::vector> aqPollFDs; + wl_event_source* m_configWatcherInotifySource = nullptr; + friend class CSyncTimeline; }; diff --git a/src/plugins/PluginAPI.cpp b/src/plugins/PluginAPI.cpp index b6bbc460..fbb1ec1b 100644 --- a/src/plugins/PluginAPI.cpp +++ b/src/plugins/PluginAPI.cpp @@ -4,6 +4,7 @@ #include "../plugins/PluginSystem.hpp" #include "../managers/HookSystemManager.hpp" #include "../managers/LayoutManager.hpp" +#include "../managers/eventLoop/EventLoopManager.hpp" #include "../config/ConfigManager.hpp" #include "../debug/HyprNotificationOverlay.hpp" #include @@ -72,7 +73,7 @@ APICALL bool HyprlandAPI::removeLayout(HANDLE handle, IHyprLayout* layout) { } APICALL bool HyprlandAPI::reloadConfig() { - g_pConfigManager->m_bForceReload = true; + g_pEventLoopManager->doLater([] { g_pConfigManager->reload(); }); return true; } diff --git a/src/plugins/PluginSystem.cpp b/src/plugins/PluginSystem.cpp index ce7dd7c7..e849bf11 100644 --- a/src/plugins/PluginSystem.cpp +++ b/src/plugins/PluginSystem.cpp @@ -5,6 +5,7 @@ #include "../config/ConfigManager.hpp" #include "../managers/LayoutManager.hpp" #include "../managers/HookSystemManager.hpp" +#include "../managers/eventLoop/EventLoopManager.hpp" CPluginSystem::CPluginSystem() { g_pFunctionHookSystem = std::make_unique(); @@ -82,7 +83,7 @@ CPlugin* CPluginSystem::loadPlugin(const std::string& path) { PLUGIN->version = PLUGINDATA.version; PLUGIN->name = PLUGINDATA.name; - g_pConfigManager->m_bForceReload = true; + g_pEventLoopManager->doLater([] { g_pConfigManager->reload(); }); Debug::log(LOG, R"( [PluginSystem] Plugin {} loaded. Handle: {:x}, path: "{}", author: "{}", description: "{}", version: "{}")", PLUGINDATA.name, (uintptr_t)MODULE, path, PLUGINDATA.author, PLUGINDATA.description, PLUGINDATA.version); @@ -137,7 +138,7 @@ void CPluginSystem::unloadPlugin(const CPlugin* plugin, bool eject) { Debug::log(LOG, " [PluginSystem] Plugin {} unloaded.", PLNAME); // reload config to fix some stuf like e.g. unloadedPluginVars - g_pConfigManager->m_bForceReload = true; + g_pEventLoopManager->doLater([] { g_pConfigManager->reload(); }); } void CPluginSystem::unloadAllPlugins() { From 407453166ce2a52433c7b0b4ee92a41e47ef8f6d Mon Sep 17 00:00:00 2001 From: Maximilian Seidler <78690852+PaideiaDilemma@users.noreply.github.com> Date: Sun, 19 Jan 2025 18:21:36 +0000 Subject: [PATCH 0872/2181] protocols: add hyprland_lock_notify_v1 implementation (#9092) --- CMakeLists.txt | 3 +- flake.lock | 6 +-- protocols/meson.build | 3 +- src/managers/ProtocolManager.cpp | 5 +- src/protocols/LockNotify.cpp | 88 ++++++++++++++++++++++++++++++++ src/protocols/LockNotify.hpp | 50 ++++++++++++++++++ src/protocols/SessionLock.cpp | 4 ++ subprojects/hyprland-protocols | 2 +- 8 files changed, 154 insertions(+), 7 deletions(-) create mode 100644 src/protocols/LockNotify.cpp create mode 100644 src/protocols/LockNotify.hpp diff --git a/CMakeLists.txt b/CMakeLists.txt index a36d70fe..c022f3ba 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -298,7 +298,7 @@ endfunction() target_link_libraries(Hyprland OpenGL::EGL OpenGL::GL Threads::Threads) -pkg_check_modules(hyprland_protocols_dep hyprland-protocols>=0.4.0) +pkg_check_modules(hyprland_protocols_dep hyprland-protocols>=0.6.0) if(hyprland_protocols_dep_FOUND) pkg_get_variable(HYPRLAND_PROTOCOLS hyprland-protocols pkgdatadir) message(STATUS "hyprland-protocols dependency set to ${HYPRLAND_PROTOCOLS}") @@ -329,6 +329,7 @@ protocolnew("protocols" "frog-color-management-v1" true) protocolnew("protocols" "wayland-drm" true) protocolnew("${HYPRLAND_PROTOCOLS}/protocols" "hyprland-ctm-control-v1" true) protocolnew("${HYPRLAND_PROTOCOLS}/protocols" "hyprland-surface-v1" true) +protocolnew("${HYPRLAND_PROTOCOLS}/protocols" "hyprland-lock-notify-v1" true) protocolnew("staging/tearing-control" "tearing-control-v1" false) protocolnew("staging/fractional-scale" "fractional-scale-v1" false) diff --git a/flake.lock b/flake.lock index f16ecaa7..7b85bd17 100644 --- a/flake.lock +++ b/flake.lock @@ -128,11 +128,11 @@ ] }, "locked": { - "lastModified": 1735774328, - "narHash": "sha256-vIRwLS9w+N99EU1aJ+XNOU6mJTxrUBa31i1r82l0V7s=", + "lastModified": 1737127640, + "narHash": "sha256-mIQ3/axCZ4g8ySwWRbW4fJcyC9v55uAii3cqlJRtW8g=", "owner": "hyprwm", "repo": "hyprland-protocols", - "rev": "e3b6af97ddcfaafbda8e2828c719a5af84f662cb", + "rev": "455c055883d9639d4fcbfcedb4c6d12ce313791e", "type": "github" }, "original": { diff --git a/protocols/meson.build b/protocols/meson.build index fdbbf181..aa20940d 100644 --- a/protocols/meson.build +++ b/protocols/meson.build @@ -7,7 +7,7 @@ wayland_protos = dependency( hyprland_protos = dependency( 'hyprland-protocols', - version: '>=0.4', + version: '>=0.6', fallback: 'hyprland-protocols', ) @@ -40,6 +40,7 @@ protocols = [ hyprland_protocol_dir / 'protocols/hyprland-focus-grab-v1.xml', hyprland_protocol_dir / 'protocols/hyprland-ctm-control-v1.xml', hyprland_protocol_dir / 'protocols/hyprland-surface-v1.xml', + hyprland_protocol_dir / 'protocols/hyprland-lock-notify-v1.xml', wayland_protocol_dir / 'staging/tearing-control/tearing-control-v1.xml', wayland_protocol_dir / 'staging/fractional-scale/fractional-scale-v1.xml', wayland_protocol_dir / 'unstable/xdg-output/xdg-output-unstable-v1.xml', diff --git a/src/managers/ProtocolManager.cpp b/src/managers/ProtocolManager.cpp index b7d61f67..8e32bdec 100644 --- a/src/managers/ProtocolManager.cpp +++ b/src/managers/ProtocolManager.cpp @@ -20,6 +20,7 @@ #include "../protocols/OutputPower.hpp" #include "../protocols/XDGActivation.hpp" #include "../protocols/IdleNotify.hpp" +#include "../protocols/LockNotify.hpp" #include "../protocols/SessionLock.hpp" #include "../protocols/InputMethodV2.hpp" #include "../protocols/VirtualKeyboard.hpp" @@ -145,6 +146,7 @@ CProtocolManager::CProtocolManager() { PROTO::outputPower = std::make_unique(&zwlr_output_power_manager_v1_interface, 1, "OutputPower"); PROTO::activation = std::make_unique(&xdg_activation_v1_interface, 1, "XDGActivation"); PROTO::idle = std::make_unique(&ext_idle_notifier_v1_interface, 1, "IdleNotify"); + PROTO::lockNotify = std::make_unique(&hyprland_lock_notifier_v1_interface, 1, "IdleNotify"); PROTO::sessionLock = std::make_unique(&ext_session_lock_manager_v1_interface, 1, "SessionLock"); PROTO::ime = std::make_unique(&zwp_input_method_manager_v2_interface, 1, "IMEv2"); PROTO::virtualKeyboard = std::make_unique(&zwp_virtual_keyboard_manager_v1_interface, 1, "VirtualKeyboard"); @@ -224,6 +226,7 @@ CProtocolManager::~CProtocolManager() { PROTO::outputPower.reset(); PROTO::activation.reset(); PROTO::idle.reset(); + PROTO::lockNotify.reset(); PROTO::sessionLock.reset(); PROTO::ime.reset(); PROTO::virtualKeyboard.reset(); @@ -296,7 +299,7 @@ bool CProtocolManager::isGlobalPrivileged(const wl_global* global) { PROTO::xdgDialog->getGlobal(), PROTO::singlePixel->getGlobal(), PROTO::primarySelection->getGlobal(), - PROTO::hyprlandSurface->getGlobal(), + PROTO::hyprlandSurface->getGlobal(), PROTO::sync ? PROTO::sync->getGlobal() : nullptr, PROTO::mesaDRM ? PROTO::mesaDRM->getGlobal() : nullptr, PROTO::linuxDma ? PROTO::linuxDma->getGlobal() : nullptr, diff --git a/src/protocols/LockNotify.cpp b/src/protocols/LockNotify.cpp new file mode 100644 index 00000000..adcd0b2d --- /dev/null +++ b/src/protocols/LockNotify.cpp @@ -0,0 +1,88 @@ +#include "LockNotify.hpp" + +CHyprlandLockNotification::CHyprlandLockNotification(SP resource_) : m_resource(resource_) { + if UNLIKELY (!m_resource->resource()) + return; + + m_resource->setDestroy([this](CHyprlandLockNotificationV1* r) { PROTO::lockNotify->destroyNotification(this); }); + m_resource->setOnDestroy([this](CHyprlandLockNotificationV1* r) { PROTO::lockNotify->destroyNotification(this); }); +} + +bool CHyprlandLockNotification::good() { + return m_resource->resource(); +} + +void CHyprlandLockNotification::onLocked() { + if LIKELY (!m_locked) + m_resource->sendLocked(); + + m_locked = true; +} + +void CHyprlandLockNotification::onUnlocked() { + if LIKELY (m_locked) + m_resource->sendUnlocked(); + + m_locked = false; +} + +CLockNotifyProtocol::CLockNotifyProtocol(const wl_interface* iface, const int& ver, const std::string& name) : IWaylandProtocol(iface, ver, name) { + ; +} + +void CLockNotifyProtocol::bindManager(wl_client* client, void* data, uint32_t ver, uint32_t id) { + const auto RESOURCE = m_managers.emplace_back(std::make_unique(client, ver, id)).get(); + RESOURCE->setOnDestroy([this](CHyprlandLockNotifierV1* p) { this->onManagerResourceDestroy(p->resource()); }); + + RESOURCE->setDestroy([this](CHyprlandLockNotifierV1* pMgr) { this->onManagerResourceDestroy(pMgr->resource()); }); + RESOURCE->setGetLockNotification([this](CHyprlandLockNotifierV1* pMgr, uint32_t id) { this->onGetNotification(pMgr, id); }); +} + +void CLockNotifyProtocol::onManagerResourceDestroy(wl_resource* res) { + std::erase_if(m_managers, [&](const auto& other) { return other->resource() == res; }); +} + +void CLockNotifyProtocol::destroyNotification(CHyprlandLockNotification* notif) { + std::erase_if(m_notifications, [&](const auto& other) { return other.get() == notif; }); +} + +void CLockNotifyProtocol::onGetNotification(CHyprlandLockNotifierV1* pMgr, uint32_t id) { + const auto CLIENT = pMgr->client(); + const auto RESOURCE = m_notifications.emplace_back(makeShared(makeShared(CLIENT, pMgr->version(), id))).get(); + + if UNLIKELY (!RESOURCE->good()) { + pMgr->noMemory(); + m_notifications.pop_back(); + return; + } + + // Already locked?? Send locked right away + if UNLIKELY (m_isLocked) + m_notifications.back()->onLocked(); +} + +void CLockNotifyProtocol::onLocked() { + if UNLIKELY (m_isLocked) { + LOGM(ERR, "Not sending lock notification. Already locked!"); + return; + } + + for (auto const& n : m_notifications) { + n->onLocked(); + } + + m_isLocked = true; +} + +void CLockNotifyProtocol::onUnlocked() { + if UNLIKELY (!m_isLocked) { + LOGM(ERR, "Not sending unlock notification. Not locked!"); + return; + } + + for (auto const& n : m_notifications) { + n->onUnlocked(); + } + + m_isLocked = false; +} diff --git a/src/protocols/LockNotify.hpp b/src/protocols/LockNotify.hpp new file mode 100644 index 00000000..ec71034b --- /dev/null +++ b/src/protocols/LockNotify.hpp @@ -0,0 +1,50 @@ +#pragma once + +#include +#include +#include +#include "WaylandProtocol.hpp" +#include "hyprland-lock-notify-v1.hpp" + +class CEventLoopTimer; + +class CHyprlandLockNotification { + public: + CHyprlandLockNotification(SP resource_); + ~CHyprlandLockNotification() = default; + + bool good(); + void onLocked(); + void onUnlocked(); + + private: + SP m_resource; + bool m_locked = false; +}; + +class CLockNotifyProtocol : public IWaylandProtocol { + public: + CLockNotifyProtocol(const wl_interface* iface, const int& ver, const std::string& name); + + virtual void bindManager(wl_client* client, void* data, uint32_t ver, uint32_t id); + + void onLocked(); + void onUnlocked(); + + private: + void onManagerResourceDestroy(wl_resource* res); + void destroyNotification(CHyprlandLockNotification* notif); + void onGetNotification(CHyprlandLockNotifierV1* pMgr, uint32_t id); + + bool m_isLocked = false; + + // + std::vector> m_managers; + std::vector> m_notifications; + + friend class CHyprlandLockNotification; +}; + +namespace PROTO { + inline UP lockNotify; +}; diff --git a/src/protocols/SessionLock.cpp b/src/protocols/SessionLock.cpp index db65ee5f..8e215ffa 100644 --- a/src/protocols/SessionLock.cpp +++ b/src/protocols/SessionLock.cpp @@ -2,6 +2,7 @@ #include "../Compositor.hpp" #include "../managers/SeatManager.hpp" #include "FractionalScale.hpp" +#include "LockNotify.hpp" #include "core/Compositor.hpp" #include "core/Output.hpp" #include "../helpers/Monitor.hpp" @@ -115,6 +116,8 @@ CSessionLock::CSessionLock(SP resource_) : resource(resource_ PROTO::sessionLock->locked = false; + PROTO::lockNotify->onUnlocked(); + events.unlockAndDestroy.emit(); inert = true; @@ -128,6 +131,7 @@ CSessionLock::~CSessionLock() { void CSessionLock::sendLocked() { resource->sendLocked(); + PROTO::lockNotify->onLocked(); } bool CSessionLock::good() { diff --git a/subprojects/hyprland-protocols b/subprojects/hyprland-protocols index 271df559..455c0558 160000 --- a/subprojects/hyprland-protocols +++ b/subprojects/hyprland-protocols @@ -1 +1 @@ -Subproject commit 271df559dd30e4bc5ec6af02d017ac0aaabd63a7 +Subproject commit 455c055883d9639d4fcbfcedb4c6d12ce313791e From 2d82a923241c0d7cb6209ee035bbac581d4dc555 Mon Sep 17 00:00:00 2001 From: Maximilian Seidler <78690852+PaideiaDilemma@users.noreply.github.com> Date: Mon, 20 Jan 2025 16:48:04 +0000 Subject: [PATCH 0873/2181] config: fix float animation speeds < 0 (#9123) --- src/config/ConfigManager.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/config/ConfigManager.cpp b/src/config/ConfigManager.cpp index ebeb2397..0347ced4 100644 --- a/src/config/ConfigManager.cpp +++ b/src/config/ConfigManager.cpp @@ -2083,7 +2083,7 @@ std::optional CConfigManager::handleAnimation(const std::string& co return {}; } - int64_t speed = -1; + float speed = -1; // speed if (isNumber(ARGS[2], true)) { From 9e8d9791c7f9b7d1183110da370772a8b2c1b6f4 Mon Sep 17 00:00:00 2001 From: DDoSolitary Date: Tue, 21 Jan 2025 01:53:29 +0800 Subject: [PATCH 0874/2181] xwayland: support sending clipboard change notification on focus (#9111) --- src/xwayland/XWM.cpp | 13 ++++++++++++- src/xwayland/XWM.hpp | 3 +++ 2 files changed, 15 insertions(+), 1 deletion(-) diff --git a/src/xwayland/XWM.cpp b/src/xwayland/XWM.cpp index ae8e0ccc..3486b286 100644 --- a/src/xwayland/XWM.cpp +++ b/src/xwayland/XWM.cpp @@ -1144,7 +1144,8 @@ void CXWM::initSelection() { XCB_XFIXES_SELECTION_EVENT_MASK_SET_SELECTION_OWNER | XCB_XFIXES_SELECTION_EVENT_MASK_SELECTION_WINDOW_DESTROY | XCB_XFIXES_SELECTION_EVENT_MASK_SELECTION_CLIENT_CLOSE; xcb_xfixes_select_selection_input(connection, clipboard.window, HYPRATOMS["CLIPBOARD"], mask2); - clipboard.listeners.setSelection = g_pSeatManager->events.setSelection.registerListener([this](std::any d) { clipboard.onSelection(); }); + clipboard.listeners.setSelection = g_pSeatManager->events.setSelection.registerListener([this](std::any d) { clipboard.onSelection(); }); + clipboard.listeners.keyboardFocusChange = g_pSeatManager->events.keyboardFocusChange.registerListener([this](std::any d) { clipboard.onKeyboardFocus(); }); dndSelection.window = xcb_generate_id(connection); xcb_create_window(connection, XCB_COPY_FROM_PARENT, dndSelection.window, screen->root, 0, 0, 8192, 8192, 0, XCB_WINDOW_CLASS_INPUT_ONLY, screen->root_visual, XCB_CW_EVENT_MASK, @@ -1287,6 +1288,16 @@ void SXSelection::onSelection() { if (g_pSeatManager->selection.currentSelection) { xcb_set_selection_owner(g_pXWayland->pWM->connection, g_pXWayland->pWM->clipboard.window, HYPRATOMS["CLIPBOARD"], XCB_TIME_CURRENT_TIME); xcb_flush(g_pXWayland->pWM->connection); + g_pXWayland->pWM->clipboard.notifyOnFocus = true; + } +} + +void SXSelection::onKeyboardFocus() { + if (!g_pSeatManager->state.keyboardFocusResource || g_pSeatManager->state.keyboardFocusResource->client() != g_pXWayland->pServer->xwaylandClient) + return; + if (g_pXWayland->pWM->clipboard.notifyOnFocus) { + onSelection(); + g_pXWayland->pWM->clipboard.notifyOnFocus = false; } } diff --git a/src/xwayland/XWM.hpp b/src/xwayland/XWM.hpp index bc5aa47b..0455c761 100644 --- a/src/xwayland/XWM.hpp +++ b/src/xwayland/XWM.hpp @@ -44,13 +44,16 @@ struct SXSelection { xcb_window_t owner = 0; xcb_timestamp_t timestamp = 0; SP dataSource; + bool notifyOnFocus = false; void onSelection(); + void onKeyboardFocus(); bool sendData(xcb_selection_request_event_t* e, std::string mime); int onRead(int fd, uint32_t mask); struct { CHyprSignalListener setSelection; + CHyprSignalListener keyboardFocusChange; } listeners; std::unique_ptr transfer; From a661203bb6d4714b211572759e2f74b1da194972 Mon Sep 17 00:00:00 2001 From: Zach DeCook Date: Mon, 20 Jan 2025 13:40:51 -0500 Subject: [PATCH 0875/2181] xwayland: fix crash when trying to initialize without Xwayland installed (#9077) --- src/Compositor.cpp | 2 +- src/Compositor.hpp | 2 +- src/config/ConfigManager.cpp | 22 ++++++---------------- src/xwayland/XWayland.cpp | 34 ++++++++++++++++++++++++++++------ src/xwayland/XWayland.hpp | 6 +++++- 5 files changed, 41 insertions(+), 25 deletions(-) diff --git a/src/Compositor.cpp b/src/Compositor.cpp index 325bd882..cd0c7c61 100644 --- a/src/Compositor.cpp +++ b/src/Compositor.cpp @@ -669,7 +669,7 @@ void CCompositor::initManagers(eManagersInitStage stage) { g_pDonationNagManager = std::make_unique(); Debug::log(LOG, "Starting XWayland"); - g_pXWayland = std::make_unique(g_pCompositor->m_bEnableXwayland); + g_pXWayland = std::make_unique(g_pCompositor->m_bWantsXwayland); } break; default: UNREACHABLE(); } diff --git a/src/Compositor.hpp b/src/Compositor.hpp index 430e583c..ebcca5d0 100644 --- a/src/Compositor.hpp +++ b/src/Compositor.hpp @@ -74,7 +74,7 @@ class CCompositor { bool m_bIsShuttingDown = false; bool m_bFinalRequests = false; bool m_bDesktopEnvSet = false; - bool m_bEnableXwayland = true; + bool m_bWantsXwayland = true; // ------------------------------------------------- // diff --git a/src/config/ConfigManager.cpp b/src/config/ConfigManager.cpp index 0347ced4..40f8d9ef 100644 --- a/src/config/ConfigManager.cpp +++ b/src/config/ConfigManager.cpp @@ -950,26 +950,16 @@ void CConfigManager::postConfigReload(const Hyprlang::CParseResult& result) { } #ifndef NO_XWAYLAND - const auto PENABLEXWAYLAND = std::any_cast(m_pConfig->getConfigValue("xwayland:enabled")); + const auto PENABLEXWAYLAND = std::any_cast(m_pConfig->getConfigValue("xwayland:enabled")); + g_pCompositor->m_bWantsXwayland = PENABLEXWAYLAND; // enable/disable xwayland usage if (!isFirstLaunch) { - bool prevEnabledXwayland = g_pCompositor->m_bEnableXwayland; - if (PENABLEXWAYLAND != prevEnabledXwayland) { - g_pCompositor->m_bEnableXwayland = PENABLEXWAYLAND; - if (PENABLEXWAYLAND) { - Debug::log(LOG, "xwayland has been enabled"); - } else { - Debug::log(LOG, "xwayland has been disabled, cleaning up..."); - for (auto& w : g_pCompositor->m_vWindows) { - if (w->m_pXDGSurface || !w->m_bIsX11) - continue; - g_pCompositor->closeWindow(w); - } - } - g_pXWayland = std::make_unique(g_pCompositor->m_bEnableXwayland); + bool prevEnabledXwayland = g_pXWayland->enabled(); + if (g_pCompositor->m_bWantsXwayland != prevEnabledXwayland) { + g_pXWayland = std::make_unique(g_pCompositor->m_bWantsXwayland); } } else - g_pCompositor->m_bEnableXwayland = PENABLEXWAYLAND; + g_pCompositor->m_bWantsXwayland = PENABLEXWAYLAND; #endif if (!isFirstLaunch && !g_pCompositor->m_bUnsafeState) diff --git a/src/xwayland/XWayland.cpp b/src/xwayland/XWayland.cpp index 8cdb1fca..6b8a630b 100644 --- a/src/xwayland/XWayland.cpp +++ b/src/xwayland/XWayland.cpp @@ -1,21 +1,39 @@ #include "XWayland.hpp" +#include "../Compositor.hpp" #include "../debug/Log.hpp" +#include "../helpers/fs/FsUtils.hpp" -CXWayland::CXWayland(const bool enabled) { +CXWayland::CXWayland(const bool wantsEnabled) { #ifndef NO_XWAYLAND + // Disable Xwayland and clean up if the user disabled it. + if (!wantsEnabled) { + Debug::log(LOG, "XWayland has been disabled, cleaning up..."); + for (auto& w : g_pCompositor->m_vWindows) { + if (!w->m_bIsX11) + continue; + g_pCompositor->closeWindow(w); + } + unsetenv("DISPLAY"); + m_enabled = false; + return; + } + + if (!NFsUtils::executableExistsInPath("Xwayland")) { + // If Xwayland doesn't exist, don't try to start it. + Debug::log(LOG, "Unable to find XWayland; not starting it."); + return; + } + Debug::log(LOG, "Starting up the XWayland server"); pServer = std::make_unique(); - if (!enabled) { - unsetenv("DISPLAY"); - return; - } - if (!pServer->create()) { Debug::log(ERR, "XWayland failed to start: it will not work."); return; } + + m_enabled = true; #else Debug::log(LOG, "Not starting XWayland: disabled at compile time"); #endif @@ -31,3 +49,7 @@ void CXWayland::setCursor(unsigned char* pixData, uint32_t stride, const Vector2 pWM->setCursor(pixData, stride, size, hotspot); #endif } + +bool CXWayland::enabled() { + return m_enabled; +} diff --git a/src/xwayland/XWayland.hpp b/src/xwayland/XWayland.hpp index 113ca4d4..8347a6a7 100644 --- a/src/xwayland/XWayland.hpp +++ b/src/xwayland/XWayland.hpp @@ -17,18 +17,22 @@ class CXWM; class CXWayland { public: - CXWayland(const bool enabled); + CXWayland(const bool wantsEnabled); #ifndef NO_XWAYLAND std::unique_ptr pServer; std::unique_ptr pWM; #endif + bool enabled(); void setCursor(unsigned char* pixData, uint32_t stride, const Vector2D& size, const Vector2D& hotspot); struct { CSignal newSurface; } events; + + private: + bool m_enabled = false; }; inline std::unique_ptr g_pXWayland; From da6e9663135aa492252fe8684747ff734730a323 Mon Sep 17 00:00:00 2001 From: Alexander <51529891+Truenya@users.noreply.github.com> Date: Tue, 21 Jan 2025 17:17:07 +0300 Subject: [PATCH 0876/2181] keybinds: add visible arg for cyclenext (#9045) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Крылов Александр --- src/Compositor.cpp | 89 ++++++++++++--------------------- src/Compositor.hpp | 5 +- src/managers/KeybindManager.cpp | 13 ++--- 3 files changed, 41 insertions(+), 66 deletions(-) diff --git a/src/Compositor.cpp b/src/Compositor.cpp index cd0c7c61..f5f1d1f9 100644 --- a/src/Compositor.cpp +++ b/src/Compositor.cpp @@ -2,6 +2,7 @@ #include "Compositor.hpp" #include "debug/Log.hpp" +#include "desktop/DesktopTypes.hpp" #include "helpers/Splashes.hpp" #include "config/ConfigValue.hpp" #include "config/ConfigWatcher.hpp" @@ -12,6 +13,7 @@ #include "managers/VersionKeeperManager.hpp" #include "managers/DonationNagManager.hpp" #include "managers/eventLoop/EventLoopManager.hpp" +#include #include #include #include @@ -19,13 +21,13 @@ #include #include #include +#include #include #include "debug/HyprCtl.hpp" #include "debug/CrashReporter.hpp" #ifdef USES_SYSTEMD #include // for SdNotify #endif -#include #include "helpers/varlist/VarList.hpp" #include "helpers/fs/FsUtils.hpp" #include "protocols/FractionalScale.hpp" @@ -1638,62 +1640,37 @@ PHLWINDOW CCompositor::getWindowInDirection(const CBox& box, PHLWORKSPACE pWorks return nullptr; } -PHLWINDOW CCompositor::getNextWindowOnWorkspace(PHLWINDOW pWindow, bool focusableOnly, std::optional floating) { - bool gotToWindow = false; - for (auto const& w : m_vWindows) { - if (w != pWindow && !gotToWindow) - continue; - - if (w == pWindow) { - gotToWindow = true; - continue; - } - - if (floating.has_value() && w->m_bIsFloating != floating.value()) - continue; - - if (w->m_pWorkspace == pWindow->m_pWorkspace && w->m_bIsMapped && !w->isHidden() && (!focusableOnly || !w->m_sWindowData.noFocus.valueOrDefault())) - return w; - } - - for (auto const& w : m_vWindows) { - if (floating.has_value() && w->m_bIsFloating != floating.value()) - continue; - - if (w != pWindow && w->m_pWorkspace == pWindow->m_pWorkspace && w->m_bIsMapped && !w->isHidden() && (!focusableOnly || !w->m_sWindowData.noFocus.valueOrDefault())) - return w; - } - - return nullptr; +PHLWINDOW CCompositor::getNextWindowOnWorkspace(PHLWINDOW pWindow, bool focusableOnly, std::optional floating, bool visible) { + auto it = std::ranges::find(m_vWindows, pWindow); + const auto FINDER = [&](const PHLWINDOW& w) { return isWindowAvailableForCycle(pWindow, w, focusableOnly, floating, visible); }; + const auto IN_RIGHT = std::find_if(it, m_vWindows.end(), FINDER); + if (IN_RIGHT != m_vWindows.end()) + return *IN_RIGHT; + const auto IN_LEFT = std::find_if(m_vWindows.begin(), it, FINDER); + return *IN_LEFT; } -PHLWINDOW CCompositor::getPrevWindowOnWorkspace(PHLWINDOW pWindow, bool focusableOnly, std::optional floating) { - bool gotToWindow = false; - for (auto const& w : m_vWindows | std::views::reverse) { - if (w != pWindow && !gotToWindow) - continue; +PHLWINDOW CCompositor::getPrevWindowOnWorkspace(PHLWINDOW pWindow, bool focusableOnly, std::optional floating, bool visible) { + auto it = std::ranges::find(std::ranges::reverse_view(m_vWindows), pWindow); + const auto FINDER = [&](const PHLWINDOW& w) { return isWindowAvailableForCycle(pWindow, w, focusableOnly, floating, visible); }; + const auto IN_LEFT = std::find_if(it, m_vWindows.rend(), FINDER); + if (IN_LEFT != m_vWindows.rend()) + return *IN_LEFT; + const auto IN_RIGHT = std::find_if(m_vWindows.rbegin(), it, FINDER); + return *IN_RIGHT; +} - if (w == pWindow) { - gotToWindow = true; - continue; - } +inline static bool isWorkspaceMatches(PHLWINDOW pWindow, const PHLWINDOW w, bool anyWorkspace) { + return anyWorkspace ? w->m_pWorkspace && w->m_pWorkspace->isVisible() : w->m_pWorkspace == pWindow->m_pWorkspace; +} - if (floating.has_value() && w->m_bIsFloating != floating.value()) - continue; +inline static bool isFloatingMatches(PHLWINDOW w, std::optional floating) { + return !floating.has_value() || w->m_bIsFloating == floating.value(); +}; - if (w->m_pWorkspace == pWindow->m_pWorkspace && w->m_bIsMapped && !w->isHidden() && (!focusableOnly || !w->m_sWindowData.noFocus.valueOrDefault())) - return w; - } - - for (auto const& w : m_vWindows | std::views::reverse) { - if (floating.has_value() && w->m_bIsFloating != floating.value()) - continue; - - if (w != pWindow && w->m_pWorkspace == pWindow->m_pWorkspace && w->m_bIsMapped && !w->isHidden() && (!focusableOnly || !w->m_sWindowData.noFocus.valueOrDefault())) - return w; - } - - return nullptr; +bool CCompositor::isWindowAvailableForCycle(PHLWINDOW pWindow, const PHLWINDOW w, bool focusableOnly, std::optional floating, bool anyWorkspace) { + return isFloatingMatches(w, floating) && w != pWindow && isWorkspaceMatches(pWindow, w, anyWorkspace) && w->m_bIsMapped && !w->isHidden() && + (!focusableOnly || !w->m_sWindowData.noFocus.valueOrDefault()); } WORKSPACEID CCompositor::getNextAvailableNamedWorkspace() { @@ -1728,12 +1705,8 @@ PHLWORKSPACE CCompositor::getWorkspaceByString(const std::string& str) { } bool CCompositor::isPointOnAnyMonitor(const Vector2D& point) { - for (auto const& m : m_vMonitors) { - if (VECINRECT(point, m->vecPosition.x, m->vecPosition.y, m->vecSize.x + m->vecPosition.x, m->vecSize.y + m->vecPosition.y)) - return true; - } - - return false; + return std::ranges::any_of( + m_vMonitors, [&](const PHLMONITOR& m) { return VECINRECT(point, m->vecPosition.x, m->vecPosition.y, m->vecSize.x + m->vecPosition.x, m->vecSize.y + m->vecPosition.y); }); } bool CCompositor::isPointOnReservedArea(const Vector2D& point, const PHLMONITOR pMonitor) { diff --git a/src/Compositor.hpp b/src/Compositor.hpp index ebcca5d0..0a87ec33 100644 --- a/src/Compositor.hpp +++ b/src/Compositor.hpp @@ -106,8 +106,8 @@ class CCompositor { void cleanupFadingOut(const MONITORID& monid); PHLWINDOW getWindowInDirection(PHLWINDOW, char); PHLWINDOW getWindowInDirection(const CBox& box, PHLWORKSPACE pWorkspace, char dir, PHLWINDOW ignoreWindow = nullptr, bool useVectorAngles = false); - PHLWINDOW getNextWindowOnWorkspace(PHLWINDOW, bool focusableOnly = false, std::optional floating = {}); - PHLWINDOW getPrevWindowOnWorkspace(PHLWINDOW, bool focusableOnly = false, std::optional floating = {}); + PHLWINDOW getNextWindowOnWorkspace(PHLWINDOW, bool focusableOnly = false, std::optional floating = {}, bool visible = false); + PHLWINDOW getPrevWindowOnWorkspace(PHLWINDOW, bool focusableOnly = false, std::optional floating = {}, bool visible = false); WORKSPACEID getNextAvailableNamedWorkspace(); bool isPointOnAnyMonitor(const Vector2D&); bool isPointOnReservedArea(const Vector2D& point, const PHLMONITOR monitor = nullptr); @@ -163,6 +163,7 @@ class CCompositor { void setRandomSplash(); void initManagers(eManagersInitStage stage); void prepareFallbackOutput(); + bool isWindowAvailableForCycle(PHLWINDOW pWindow, PHLWINDOW w, bool focusableOnly, std::optional floating, bool anyWorkspace = false); uint64_t m_iHyprlandPID = 0; wl_event_source* m_critSigSource = nullptr; diff --git a/src/managers/KeybindManager.cpp b/src/managers/KeybindManager.cpp index 65891840..0816de2a 100644 --- a/src/managers/KeybindManager.cpp +++ b/src/managers/KeybindManager.cpp @@ -750,7 +750,7 @@ SDispatchResult CKeybindManager::handleKeybinds(const uint32_t modmask, const SP Debug::log(ERR, "Invalid handler in a keybind! (handler {} does not exist)", k->handler); } else { // call the dispatcher - Debug::log(LOG, "Keybind triggered, calling dispatcher ({}, {}, {})", modmask, key.keyName, key.keysym); + Debug::log(LOG, "Keybind triggered, calling dispatcher ({}, {}, {}, {})", modmask, key.keyName, key.keysym, DISPATCHER->first); m_iPassPressed = (int)pressed; @@ -2201,7 +2201,6 @@ SDispatchResult CKeybindManager::resizeWindow(std::string args) { } SDispatchResult CKeybindManager::circleNext(std::string arg) { - if (g_pCompositor->m_pLastWindow.expired()) { // if we have a clear focus, find the first window and get the next focusable. const auto PWS = g_pCompositor->m_pLastMonitor->activeWorkspace; @@ -2221,10 +2220,12 @@ SDispatchResult CKeybindManager::circleNext(std::string arg) { else if (args.contains("float") || args.contains("floating")) floatStatus = true; - if (args.contains("prev") || args.contains("p") || args.contains("last") || args.contains("l")) - switchToWindow(g_pCompositor->getPrevWindowOnWorkspace(g_pCompositor->m_pLastWindow.lock(), true, floatStatus)); - else - switchToWindow(g_pCompositor->getNextWindowOnWorkspace(g_pCompositor->m_pLastWindow.lock(), true, floatStatus)); + const auto VISIBLE = args.contains("visible") || args.contains("v"); + const auto& w = (args.contains("prev") || args.contains("p") || args.contains("last") || args.contains("l")) ? + g_pCompositor->getPrevWindowOnWorkspace(g_pCompositor->m_pLastWindow.lock(), true, floatStatus, VISIBLE) : + g_pCompositor->getNextWindowOnWorkspace(g_pCompositor->m_pLastWindow.lock(), true, floatStatus, VISIBLE); + + switchToWindow(w); return {}; } From ce48bc540824fcaefd777959703df9908e258d0a Mon Sep 17 00:00:00 2001 From: Christoph Hrdinka Date: Tue, 21 Jan 2025 20:21:00 +0100 Subject: [PATCH 0877/2181] flake.lock: update (#9128) --- flake.lock | 68 +++++++++++++++++++++++++++++++++++++----------------- 1 file changed, 47 insertions(+), 21 deletions(-) diff --git a/flake.lock b/flake.lock index 7b85bd17..31dc720b 100644 --- a/flake.lock +++ b/flake.lock @@ -16,11 +16,11 @@ ] }, "locked": { - "lastModified": 1736102453, - "narHash": "sha256-5qb4kb7Xbt8jJFL/oDqOor9Z2+E+A+ql3PiyDvsfWZ0=", + "lastModified": 1736702516, + "narHash": "sha256-NbJiiPFnmciji3JHpqF/L0SdMQXKXn+q3Q/D8RjF/ak=", "owner": "hyprwm", "repo": "aquamarine", - "rev": "4846091641f3be0ad7542086d52769bb7932bde6", + "rev": "e7719f9b9f5321c7100733773ad9f38cb6db6b6f", "type": "github" }, "original": { @@ -79,11 +79,11 @@ ] }, "locked": { - "lastModified": 1734906540, - "narHash": "sha256-vQ/L9hZFezC0LquLo4TWXkyniWtYBlFHAKIsDc7PYJE=", + "lastModified": 1737391116, + "narHash": "sha256-wOlplOftCnD2J1VwkRiAzASiXi80LypWqhVJcBYuLG8=", "owner": "hyprwm", "repo": "hyprcursor", - "rev": "69270ba8f057d55b0e6c2dca0e165d652856e613", + "rev": "3219b311283803d4dbdacb3c5cc10cf9e9b7c2b5", "type": "github" }, "original": { @@ -141,8 +141,34 @@ "type": "github" } }, + "hyprland-qt-support": { + "inputs": { + "nixpkgs": [ + "hyprland-qtutils", + "nixpkgs" + ], + "systems": [ + "hyprland-qtutils", + "systems" + ] + }, + "locked": { + "lastModified": 1736376766, + "narHash": "sha256-tZG+mkJJzqoi/gH8nN6P/yY1/PEYtom9+2WdYKKv5YM=", + "owner": "hyprwm", + "repo": "hyprland-qt-support", + "rev": "0ecf224f213497c45b12c4dc7bdc2c2edd0e3084", + "type": "github" + }, + "original": { + "owner": "hyprwm", + "repo": "hyprland-qt-support", + "type": "github" + } + }, "hyprland-qtutils": { "inputs": { + "hyprland-qt-support": "hyprland-qt-support", "hyprutils": [ "hyprutils" ], @@ -154,11 +180,11 @@ ] }, "locked": { - "lastModified": 1736114838, - "narHash": "sha256-FxbuGQExtN37ToWYnGmO6weOYN6WPHN/RAqbr7gNPek=", + "lastModified": 1736774415, + "narHash": "sha256-pb8v7axHdVKFGhQHEAxIuZP/9REsmlyuDW5eLGIplLc=", "owner": "hyprwm", "repo": "hyprland-qtutils", - "rev": "6997fe382dcf396704227d2b98ffdd5066da6959", + "rev": "534cd1badc46ec9bdd986ab41ad2408bf845961e", "type": "github" }, "original": { @@ -203,11 +229,11 @@ ] }, "locked": { - "lastModified": 1736164519, - "narHash": "sha256-1LimBKvDpBbeX+qW7T240WEyw+DBVpDotZB4JYm8Aps=", + "lastModified": 1736613432, + "narHash": "sha256-x7nMS1dFtlzgG13QoguKMZ6SKwSIQw82OANA5ZKF0d0=", "owner": "hyprwm", "repo": "hyprutils", - "rev": "3c895da64b0eb19870142196fa48c07090b441c4", + "rev": "72dfbf52967e4040693164319a027d8ac6315887", "type": "github" }, "original": { @@ -241,11 +267,11 @@ }, "nixpkgs": { "locked": { - "lastModified": 1736012469, - "narHash": "sha256-/qlNWm/IEVVH7GfgAIyP6EsVZI6zjAx1cV5zNyrs+rI=", + "lastModified": 1737062831, + "narHash": "sha256-Tbk1MZbtV2s5aG+iM99U8FqwxU/YNArMcWAv6clcsBc=", "owner": "NixOS", "repo": "nixpkgs", - "rev": "8f3e1f807051e32d8c95cd12b9b421623850a34d", + "rev": "5df43628fdf08d642be8ba5b3625a6c70731c19c", "type": "github" }, "original": { @@ -264,11 +290,11 @@ ] }, "locked": { - "lastModified": 1735882644, - "narHash": "sha256-3FZAG+pGt3OElQjesCAWeMkQ7C/nB1oTHLRQ8ceP110=", + "lastModified": 1737465171, + "narHash": "sha256-R10v2hoJRLq8jcL4syVFag7nIGE7m13qO48wRIukWNg=", "owner": "cachix", "repo": "git-hooks.nix", - "rev": "a5a961387e75ae44cc20f0a57ae463da5e959656", + "rev": "9364dc02281ce2d37a1f55b6e51f7c0f65a75f17", "type": "github" }, "original": { @@ -330,11 +356,11 @@ ] }, "locked": { - "lastModified": 1734907020, - "narHash": "sha256-p6HxwpRKVl1KIiY5xrJdjcEeK3pbmc///UOyV6QER+w=", + "lastModified": 1736421203, + "narHash": "sha256-BNe2xnHsSsTZiHp8OWl9UUf697w0gVtzh67AYe+pP+g=", "owner": "hyprwm", "repo": "xdg-desktop-portal-hyprland", - "rev": "d7f18dda5e511749fa1511185db3536208fb1a63", + "rev": "7613351375de66ca0d56689e333d460e2db05454", "type": "github" }, "original": { From c8a0443adc2711744e080c28e763443b1eef115e Mon Sep 17 00:00:00 2001 From: amnesiacsardine <56002958+amnesiacsardine@users.noreply.github.com> Date: Wed, 22 Jan 2025 11:16:46 +0100 Subject: [PATCH 0878/2181] config/ConfigManager.cpp: add instruction to edit config (#9130) --- src/config/ConfigManager.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/config/ConfigManager.cpp b/src/config/ConfigManager.cpp index 40f8d9ef..60b818f0 100644 --- a/src/config/ConfigManager.cpp +++ b/src/config/ConfigManager.cpp @@ -930,7 +930,7 @@ void CConfigManager::postConfigReload(const Hyprlang::CParseResult& result) { g_pHyprError->queueCreate(result.getError(), CHyprColor(1.0, 50.0 / 255.0, 50.0 / 255.0, 1.0)); else if (std::any_cast(m_pConfig->getConfigValue("autogenerated")) == 1) g_pHyprError->queueCreate( - "Warning: You're using an autogenerated config! (config file: " + getMainConfigPath() + + "Warning: You're using an autogenerated config! Edit the config file to get rid of this message. (config file: " + getMainConfigPath() + " )\nSUPER+Q -> kitty (if it doesn't launch, make sure it's installed or choose a different terminal in the config)\nSUPER+M -> exit Hyprland", CHyprColor(1.0, 1.0, 70.0 / 255.0, 1.0)); else if (*PENABLEEXPLICIT != prevEnabledExplicit) From d335c8f10135e165a1085fd14134c659e4caf05a Mon Sep 17 00:00:00 2001 From: Vaxry Date: Wed, 22 Jan 2025 10:41:04 +0000 Subject: [PATCH 0879/2181] fractional-scale: avoid redundant and duplicate scale events fixes #9126 --- example/launch.json | 1 + src/protocols/FractionalScale.cpp | 29 +++++++++++++++-------------- src/protocols/FractionalScale.hpp | 12 +++++------- 3 files changed, 21 insertions(+), 21 deletions(-) diff --git a/example/launch.json b/example/launch.json index c47bdb72..e60cc900 100644 --- a/example/launch.json +++ b/example/launch.json @@ -22,5 +22,6 @@ } ] }, + ] } \ No newline at end of file diff --git a/src/protocols/FractionalScale.cpp b/src/protocols/FractionalScale.cpp index d1e0a604..3b24becd 100644 --- a/src/protocols/FractionalScale.cpp +++ b/src/protocols/FractionalScale.cpp @@ -41,13 +41,14 @@ void CFractionalScaleProtocol::onGetFractionalScale(CWpFractionalScaleManagerV1* return; } - PADDON->resource->setOnDestroy([this, PADDON](CWpFractionalScaleV1* self) { this->removeAddon(PADDON); }); - PADDON->resource->setDestroy([this, PADDON](CWpFractionalScaleV1* self) { this->removeAddon(PADDON); }); + PADDON->m_resource->setOnDestroy([this, PADDON](CWpFractionalScaleV1* self) { this->removeAddon(PADDON); }); + PADDON->m_resource->setDestroy([this, PADDON](CWpFractionalScaleV1* self) { this->removeAddon(PADDON); }); - if (std::find_if(m_mSurfaceScales.begin(), m_mSurfaceScales.end(), [surface](const auto& e) { return e.first == surface; }) == m_mSurfaceScales.end()) + if (std::ranges::find_if(m_mSurfaceScales, [surface](const auto& e) { return e.first == surface; }) == m_mSurfaceScales.end()) m_mSurfaceScales.emplace(surface, 1.F); - PADDON->setScale(m_mSurfaceScales.at(surface)); + if (surface->mapped) + PADDON->setScale(m_mSurfaceScales.at(surface)); // clean old std::erase_if(m_mSurfaceScales, [](const auto& e) { return e.first.expired(); }); @@ -59,23 +60,23 @@ void CFractionalScaleProtocol::sendScale(SP surf, const floa m_mAddons[surf]->setScale(scale); } -CFractionalScaleAddon::CFractionalScaleAddon(SP resource_, SP surf_) : resource(resource_), surface(surf_) { - resource->setDestroy([this](CWpFractionalScaleV1* self) { PROTO::fractional->removeAddon(this); }); - resource->setOnDestroy([this](CWpFractionalScaleV1* self) { PROTO::fractional->removeAddon(this); }); -} - -void CFractionalScaleAddon::onSurfaceDestroy() { - surfaceGone = true; +CFractionalScaleAddon::CFractionalScaleAddon(SP resource_, SP surf_) : m_resource(resource_), m_surface(surf_) { + m_resource->setDestroy([this](CWpFractionalScaleV1* self) { PROTO::fractional->removeAddon(this); }); + m_resource->setOnDestroy([this](CWpFractionalScaleV1* self) { PROTO::fractional->removeAddon(this); }); } void CFractionalScaleAddon::setScale(const float& scale) { - resource->sendPreferredScale(std::round(scale * 120.0)); + if (m_scale == scale) + return; + + m_scale = scale; + m_resource->sendPreferredScale(std::round(scale * 120.0)); } bool CFractionalScaleAddon::good() { - return resource->resource(); + return m_resource->resource(); } SP CFractionalScaleAddon::surf() { - return surface.lock(); + return m_surface.lock(); } diff --git a/src/protocols/FractionalScale.hpp b/src/protocols/FractionalScale.hpp index f6d1f96f..98cd7eaa 100644 --- a/src/protocols/FractionalScale.hpp +++ b/src/protocols/FractionalScale.hpp @@ -13,25 +13,23 @@ class CFractionalScaleAddon { CFractionalScaleAddon(SP resource_, SP surf_); void setScale(const float& scale); - void onSurfaceDestroy(); bool good(); SP surf(); bool operator==(const wl_resource* other) const { - return other == resource->resource(); + return other == m_resource->resource(); } bool operator==(const CFractionalScaleAddon* other) const { - return other->resource == resource; + return other->m_resource == m_resource; } private: - SP resource; - float scale = 1.F; - WP surface; - bool surfaceGone = false; + SP m_resource; + float m_scale = -1.F; // unset + WP m_surface; friend class CFractionalScaleProtocol; }; From c90dbfab6f0f7f295b8b4b211223ea6e82a1021d Mon Sep 17 00:00:00 2001 From: DDoSolitary Date: Wed, 22 Jan 2025 22:26:53 +0800 Subject: [PATCH 0880/2181] xwayland: fix clipboard mime name and atom mismatch (#9137) --- src/xwayland/XDataSource.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/xwayland/XDataSource.cpp b/src/xwayland/XDataSource.cpp index 54b23937..181955a8 100644 --- a/src/xwayland/XDataSource.cpp +++ b/src/xwayland/XDataSource.cpp @@ -34,7 +34,8 @@ CXDataSource::CXDataSource(SXSelection& sel_) : selection(sel_) { continue; mimeTypes.push_back(type); - } + } else + continue; mimeAtoms.push_back(value[i]); } From fda5626594c3f31bbab08e877a797a623c98c450 Mon Sep 17 00:00:00 2001 From: DDoSolitary Date: Wed, 22 Jan 2025 22:27:46 +0800 Subject: [PATCH 0881/2181] xwayland: fix sending large clipboard data (#9134) --- src/xwayland/XWM.cpp | 55 +++++++++++++++++++++++++++----------------- src/xwayland/XWM.hpp | 1 + 2 files changed, 35 insertions(+), 21 deletions(-) diff --git a/src/xwayland/XWM.cpp b/src/xwayland/XWM.cpp index 3486b286..71a7c44c 100644 --- a/src/xwayland/XWM.cpp +++ b/src/xwayland/XWM.cpp @@ -1168,6 +1168,11 @@ void CXWM::setClipboardToWayland(SXSelection& sel) { g_pSeatManager->setCurrentSelection(sel.dataSource); } +static int writeDataSource(int fd, uint32_t mask, void* data) { + auto selection = (SXSelection*)data; + return selection->onWrite(); +} + void CXWM::getTransferData(SXSelection& sel) { Debug::log(LOG, "[xwm] getTransferData"); @@ -1179,26 +1184,9 @@ void CXWM::getTransferData(SXSelection& sel) { sel.transfer.reset(); return; } else { - char* property = (char*)xcb_get_property_value(sel.transfer->propertyReply); - int remainder = xcb_get_property_value_length(sel.transfer->propertyReply) - sel.transfer->propertyStart; - - ssize_t len = write(sel.transfer->wlFD, property + sel.transfer->propertyStart, remainder); - if (len == -1) { - Debug::log(ERR, "[xwm] write died in transfer get"); - close(sel.transfer->wlFD); - sel.transfer.reset(); - return; - } - - if (len < remainder) { - sel.transfer->propertyStart += len; - Debug::log(ERR, "[xwm] wl client read partially: len {}", len); - return; - } else { - Debug::log(LOG, "[xwm] cb transfer to wl client complete, read {} bytes", len); - close(sel.transfer->wlFD); - sel.transfer.reset(); - } + sel.onWrite(); + if (sel.transfer) + sel.transfer->eventSource = wl_event_loop_add_fd(g_pCompositor->m_sWLEventLoop, sel.transfer->wlFD, WL_EVENT_WRITABLE, ::writeDataSource, &sel); } } @@ -1370,7 +1358,8 @@ bool SXSelection::sendData(xcb_selection_request_event_t* e, std::string mime) { fcntl(p[0], F_SETFD, FD_CLOEXEC); fcntl(p[0], F_SETFL, O_NONBLOCK); fcntl(p[1], F_SETFD, FD_CLOEXEC); - fcntl(p[1], F_SETFL, O_NONBLOCK); + // the wayland client might not expect a non-blocking fd + // fcntl(p[1], F_SETFL, O_NONBLOCK); transfer->wlFD = p[0]; @@ -1383,6 +1372,30 @@ bool SXSelection::sendData(xcb_selection_request_event_t* e, std::string mime) { return true; } +int SXSelection::onWrite() { + char* property = (char*)xcb_get_property_value(transfer->propertyReply); + int remainder = xcb_get_property_value_length(transfer->propertyReply) - transfer->propertyStart; + + ssize_t len = write(transfer->wlFD, property + transfer->propertyStart, remainder); + if (len == -1) { + Debug::log(ERR, "[xwm] write died in transfer get"); + close(transfer->wlFD); + transfer.reset(); + return 0; + } + + if (len < remainder) { + transfer->propertyStart += len; + Debug::log(LOG, "[xwm] wl client read partially: len {}", len); + } else { + Debug::log(LOG, "[xwm] cb transfer to wl client complete, read {} bytes", len); + close(transfer->wlFD); + transfer.reset(); + } + + return 1; +} + SXTransfer::~SXTransfer() { if (wlFD) close(wlFD); diff --git a/src/xwayland/XWM.hpp b/src/xwayland/XWM.hpp index 0455c761..02ade80d 100644 --- a/src/xwayland/XWM.hpp +++ b/src/xwayland/XWM.hpp @@ -50,6 +50,7 @@ struct SXSelection { void onKeyboardFocus(); bool sendData(xcb_selection_request_event_t* e, std::string mime); int onRead(int fd, uint32_t mask); + int onWrite(); struct { CHyprSignalListener setSelection; From f1bd62806e538fa2bfa7899c2b2ad02d6a5ca2db Mon Sep 17 00:00:00 2001 From: maround95 <39220886+maround95@users.noreply.github.com> Date: Thu, 23 Jan 2025 13:08:19 +0200 Subject: [PATCH 0882/2181] core/renderer: Add GPU hotplug support (#8980) --- src/managers/eventLoop/EventLoopManager.cpp | 32 +++++++++++++++++---- src/managers/eventLoop/EventLoopManager.hpp | 29 +++++++++++++------ 2 files changed, 47 insertions(+), 14 deletions(-) diff --git a/src/managers/eventLoop/EventLoopManager.cpp b/src/managers/eventLoop/EventLoopManager.cpp index f98efc92..4021c171 100644 --- a/src/managers/eventLoop/EventLoopManager.cpp +++ b/src/managers/eventLoop/EventLoopManager.cpp @@ -5,6 +5,7 @@ #include #include +#include #include #include @@ -20,8 +21,8 @@ CEventLoopManager::CEventLoopManager(wl_display* display, wl_event_loop* wlEvent } CEventLoopManager::~CEventLoopManager() { - for (auto const& eventSource : m_sWayland.aqEventSources) { - wl_event_source_remove(eventSource); + for (auto const& [_, eventSourceData] : aqEventSources) { + wl_event_source_remove(eventSourceData.eventSource); } if (m_sWayland.eventSource) @@ -56,10 +57,8 @@ void CEventLoopManager::enterLoop() { if (const auto FD = g_pConfigWatcher->getInotifyFD(); FD >= 0) m_configWatcherInotifySource = wl_event_loop_add_fd(m_sWayland.loop, FD, WL_EVENT_READABLE, configWatcherWrite, nullptr); - aqPollFDs = g_pCompositor->m_pAqBackend->getPollFDs(); - for (auto const& fd : aqPollFDs) { - m_sWayland.aqEventSources.emplace_back(wl_event_loop_add_fd(m_sWayland.loop, fd->fd, WL_EVENT_READABLE, aquamarineFDWrite, fd.get())); - } + syncPollFDs(); + m_sListeners.pollFDsChanged = g_pCompositor->m_pAqBackend->events.pollFDsChanged.registerListener([this](std::any d) { syncPollFDs(); }); // if we have a session, dispatch it to get the pending input devices if (g_pCompositor->m_pAqBackend->hasSession()) @@ -144,3 +143,24 @@ void CEventLoopManager::doLater(const std::function& fn) { }, &m_sIdle); } + +void CEventLoopManager::syncPollFDs() { + auto aqPollFDs = g_pCompositor->m_pAqBackend->getPollFDs(); + + std::erase_if(aqEventSources, [&](const auto& item) { + auto const& [fd, eventSourceData] = item; + + // If no pollFD has the same fd, remove this event source + const bool shouldRemove = std::ranges::none_of(aqPollFDs, [&](const auto& pollFD) { return pollFD->fd == fd; }); + + if (shouldRemove) + wl_event_source_remove(eventSourceData.eventSource); + + return shouldRemove; + }); + + for (auto& fd : aqPollFDs | std::views::filter([&](SP fd) { return !aqEventSources.contains(fd->fd); })) { + auto eventSource = wl_event_loop_add_fd(m_sWayland.loop, fd->fd, WL_EVENT_READABLE, aquamarineFDWrite, fd.get()); + aqEventSources[fd->fd] = {.pollFD = fd, .eventSource = eventSource}; + } +} diff --git a/src/managers/eventLoop/EventLoopManager.hpp b/src/managers/eventLoop/EventLoopManager.hpp index 90402de2..e1c243d3 100644 --- a/src/managers/eventLoop/EventLoopManager.hpp +++ b/src/managers/eventLoop/EventLoopManager.hpp @@ -1,9 +1,11 @@ #pragma once #include +#include #include #include #include +#include "helpers/signal/Signal.hpp" #include "EventLoopTimer.hpp" @@ -36,11 +38,18 @@ class CEventLoopManager { }; private: + // Manages the event sources after AQ pollFDs change. + void syncPollFDs(); + + struct SEventSourceData { + SP pollFD; + wl_event_source* eventSource = nullptr; + }; + struct { - wl_event_loop* loop = nullptr; - wl_display* display = nullptr; - wl_event_source* eventSource = nullptr; - std::vector aqEventSources; + wl_event_loop* loop = nullptr; + wl_display* display = nullptr; + wl_event_source* eventSource = nullptr; } m_sWayland; struct { @@ -48,12 +57,16 @@ class CEventLoopManager { int timerfd = -1; } m_sTimers; - SIdleData m_sIdle; - std::vector> aqPollFDs; + SIdleData m_sIdle; + std::map aqEventSources; - wl_event_source* m_configWatcherInotifySource = nullptr; + struct { + CHyprSignalListener pollFDsChanged; + } m_sListeners; + + wl_event_source* m_configWatcherInotifySource = nullptr; friend class CSyncTimeline; }; -inline std::unique_ptr g_pEventLoopManager; \ No newline at end of file +inline std::unique_ptr g_pEventLoopManager; From ecae3c5e4be11531c2296a22f177e9e7dedb441d Mon Sep 17 00:00:00 2001 From: littleblack111 Date: Thu, 23 Jan 2025 20:32:44 +0800 Subject: [PATCH 0883/2181] ci: fix "Resource not accessible by integration" for cf workflow (#9144) --- .github/workflows/ci.yaml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/ci.yaml b/.github/workflows/ci.yaml index 65bfa1ca..34c45d6b 100644 --- a/.github/workflows/ci.yaml +++ b/.github/workflows/ci.yaml @@ -107,6 +107,7 @@ jobs: run: make release clang-format: + permissions: read-all if: github.event_name != 'pull_request' || github.event.pull_request.head.repo.fork name: "Code Style (Arch)" runs-on: ubuntu-latest From ae4e38d9d5faddd6e1dbc1750f589ef33d5ac16c Mon Sep 17 00:00:00 2001 From: Junxuan Liao <70618504+MikeWalrus@users.noreply.github.com> Date: Thu, 23 Jan 2025 06:35:13 -0600 Subject: [PATCH 0884/2181] tablet: send `motion`s on tip events (#9132) Typically, the position of the tool tip also changes on tool tip events, so we should forward this update to the clients. --- src/managers/input/Tablets.cpp | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/src/managers/input/Tablets.cpp b/src/managers/input/Tablets.cpp index f61d8184..0952a7d4 100644 --- a/src/managers/input/Tablets.cpp +++ b/src/managers/input/Tablets.cpp @@ -159,12 +159,13 @@ void CInputManager::onTabletAxis(CTablet::SAxisEvent e) { void CInputManager::onTabletTip(CTablet::STipEvent e) { const auto PTAB = e.tablet; const auto PTOOL = ensureTabletToolPresent(e.tool); + const auto POS = e.tip; + g_pPointerManager->warpAbsolute(POS, PTAB); + refocusTablet(PTAB, PTOOL, true); - if (e.in) { - simulateMouseMovement(); - refocusTablet(PTAB, PTOOL); + if (e.in) PROTO::tablet->down(PTOOL); - } else + else PROTO::tablet->up(PTOOL); PTOOL->isDown = e.in; From ae403e6a05452336abd97e61be2706f6a930d827 Mon Sep 17 00:00:00 2001 From: Mihai Fufezan Date: Thu, 23 Jan 2025 14:48:37 +0200 Subject: [PATCH 0885/2181] flake.lock: update --- flake.lock | 121 ++++++++++++++++++++++++++++++++++++++--------------- 1 file changed, 88 insertions(+), 33 deletions(-) diff --git a/flake.lock b/flake.lock index 31dc720b..ed1702d1 100644 --- a/flake.lock +++ b/flake.lock @@ -16,11 +16,11 @@ ] }, "locked": { - "lastModified": 1736702516, - "narHash": "sha256-NbJiiPFnmciji3JHpqF/L0SdMQXKXn+q3Q/D8RjF/ak=", + "lastModified": 1737636397, + "narHash": "sha256-F5MbBj3QVorycVSFE9qjuOTLtIQBqt2VWbXa0uwzm98=", "owner": "hyprwm", "repo": "aquamarine", - "rev": "e7719f9b9f5321c7100733773ad9f38cb6db6b6f", + "rev": "7fe006981fae53e931f513026fc754e322f13145", "type": "github" }, "original": { @@ -79,11 +79,11 @@ ] }, "locked": { - "lastModified": 1737391116, - "narHash": "sha256-wOlplOftCnD2J1VwkRiAzASiXi80LypWqhVJcBYuLG8=", + "lastModified": 1737634937, + "narHash": "sha256-Ffw4ujFpi++6pPHe+gCBOfDgAoNlzVPZN6MReC1beu8=", "owner": "hyprwm", "repo": "hyprcursor", - "rev": "3219b311283803d4dbdacb3c5cc10cf9e9b7c2b5", + "rev": "9c5dd1f7c825ee47f72727ad0a4e16ca46a2688e", "type": "github" }, "original": { @@ -105,11 +105,11 @@ ] }, "locked": { - "lastModified": 1736115290, - "narHash": "sha256-Jcn6yAzfUMcxy3tN/iZRbi/QgrYm7XLyVRl9g/nbUl4=", + "lastModified": 1737634889, + "narHash": "sha256-9JZE3KxcXOqZH9zs3UeadngDiK/yIACTiAR8HSA/TNI=", "owner": "hyprwm", "repo": "hyprgraphics", - "rev": "52202272d89da32a9f866c0d10305a5e3d954c50", + "rev": "0d77b4895ad5f1bb3b0ee43103a5246c58b65591", "type": "github" }, "original": { @@ -128,11 +128,11 @@ ] }, "locked": { - "lastModified": 1737127640, - "narHash": "sha256-mIQ3/axCZ4g8ySwWRbW4fJcyC9v55uAii3cqlJRtW8g=", + "lastModified": 1737556638, + "narHash": "sha256-laKgI3mr2qz6tas/q3tuGPxMdsGhBi/w+HO+hO2f1AY=", "owner": "hyprwm", "repo": "hyprland-protocols", - "rev": "455c055883d9639d4fcbfcedb4c6d12ce313791e", + "rev": "4c75dd5c015c8a0e5a34c6d02a018a650f57feb5", "type": "github" }, "original": { @@ -143,6 +143,7 @@ }, "hyprland-qt-support": { "inputs": { + "hyprlang": "hyprlang", "nixpkgs": [ "hyprland-qtutils", "nixpkgs" @@ -153,11 +154,11 @@ ] }, "locked": { - "lastModified": 1736376766, - "narHash": "sha256-tZG+mkJJzqoi/gH8nN6P/yY1/PEYtom9+2WdYKKv5YM=", + "lastModified": 1737634706, + "narHash": "sha256-nGCibkfsXz7ARx5R+SnisRtMq21IQIhazp6viBU8I/A=", "owner": "hyprwm", "repo": "hyprland-qt-support", - "rev": "0ecf224f213497c45b12c4dc7bdc2c2edd0e3084", + "rev": "8810df502cdee755993cb803eba7b23f189db795", "type": "github" }, "original": { @@ -180,11 +181,11 @@ ] }, "locked": { - "lastModified": 1736774415, - "narHash": "sha256-pb8v7axHdVKFGhQHEAxIuZP/9REsmlyuDW5eLGIplLc=", + "lastModified": 1737634810, + "narHash": "sha256-ZIJ03DeisbQuDaADSgmbgyocjecaozK4yGTa0/9bOr0=", "owner": "hyprwm", "repo": "hyprland-qtutils", - "rev": "534cd1badc46ec9bdd986ab41ad2408bf845961e", + "rev": "a9852dbf5a1ec77cf617543728144c1362709e46", "type": "github" }, "original": { @@ -194,6 +195,29 @@ } }, "hyprlang": { + "inputs": { + "hyprutils": [ + "hyprland-qtutils", + "hyprutils" + ], + "nixpkgs": "nixpkgs", + "systems": "systems" + }, + "locked": { + "lastModified": 1737634606, + "narHash": "sha256-W7W87Cv6wqZ9PHegI6rH1+ve3zJPiyevMFf0/HwdbCQ=", + "owner": "hyprwm", + "repo": "hyprlang", + "rev": "f41271d35cc0f370d300413d756c2677f386af9d", + "type": "github" + }, + "original": { + "owner": "hyprwm", + "repo": "hyprlang", + "type": "github" + } + }, + "hyprlang_2": { "inputs": { "hyprutils": [ "hyprutils" @@ -206,11 +230,11 @@ ] }, "locked": { - "lastModified": 1735393019, - "narHash": "sha256-NPpqA8rtmDLsEmZOmz+qR67zsB6Y503Jnv+nSFLKJZ8=", + "lastModified": 1737634606, + "narHash": "sha256-W7W87Cv6wqZ9PHegI6rH1+ve3zJPiyevMFf0/HwdbCQ=", "owner": "hyprwm", "repo": "hyprlang", - "rev": "55608efdaa387af7bfdc0eddb404c409958efa43", + "rev": "f41271d35cc0f370d300413d756c2677f386af9d", "type": "github" }, "original": { @@ -229,11 +253,11 @@ ] }, "locked": { - "lastModified": 1736613432, - "narHash": "sha256-x7nMS1dFtlzgG13QoguKMZ6SKwSIQw82OANA5ZKF0d0=", + "lastModified": 1737632363, + "narHash": "sha256-X9I8POSlHxBVjD0fiX1O2j7U9Zi1+4rIkrsyHP0uHXY=", "owner": "hyprwm", "repo": "hyprutils", - "rev": "72dfbf52967e4040693164319a027d8ac6315887", + "rev": "006620eb29d54ea9086538891404c78563d1bae1", "type": "github" }, "original": { @@ -267,11 +291,27 @@ }, "nixpkgs": { "locked": { - "lastModified": 1737062831, - "narHash": "sha256-Tbk1MZbtV2s5aG+iM99U8FqwxU/YNArMcWAv6clcsBc=", + "lastModified": 1737469691, + "narHash": "sha256-nmKOgAU48S41dTPIXAq0AHZSehWUn6ZPrUKijHAMmIk=", "owner": "NixOS", "repo": "nixpkgs", - "rev": "5df43628fdf08d642be8ba5b3625a6c70731c19c", + "rev": "9e4d5190a9482a1fb9d18adf0bdb83c6e506eaab", + "type": "github" + }, + "original": { + "owner": "NixOS", + "ref": "nixos-unstable", + "repo": "nixpkgs", + "type": "github" + } + }, + "nixpkgs_2": { + "locked": { + "lastModified": 1737469691, + "narHash": "sha256-nmKOgAU48S41dTPIXAq0AHZSehWUn6ZPrUKijHAMmIk=", + "owner": "NixOS", + "repo": "nixpkgs", + "rev": "9e4d5190a9482a1fb9d18adf0bdb83c6e506eaab", "type": "github" }, "original": { @@ -310,12 +350,12 @@ "hyprgraphics": "hyprgraphics", "hyprland-protocols": "hyprland-protocols", "hyprland-qtutils": "hyprland-qtutils", - "hyprlang": "hyprlang", + "hyprlang": "hyprlang_2", "hyprutils": "hyprutils", "hyprwayland-scanner": "hyprwayland-scanner", - "nixpkgs": "nixpkgs", + "nixpkgs": "nixpkgs_2", "pre-commit-hooks": "pre-commit-hooks", - "systems": "systems", + "systems": "systems_2", "xdph": "xdph" } }, @@ -334,6 +374,21 @@ "type": "github" } }, + "systems_2": { + "locked": { + "lastModified": 1689347949, + "narHash": "sha256-12tWmuL2zgBgZkdoB6qXZsgJEH9LR3oUgpaQq2RbI80=", + "owner": "nix-systems", + "repo": "default-linux", + "rev": "31732fcf5e8fea42e59c2488ad31a0e651500f68", + "type": "github" + }, + "original": { + "owner": "nix-systems", + "repo": "default-linux", + "type": "github" + } + }, "xdph": { "inputs": { "hyprland-protocols": [ @@ -356,11 +411,11 @@ ] }, "locked": { - "lastModified": 1736421203, - "narHash": "sha256-BNe2xnHsSsTZiHp8OWl9UUf697w0gVtzh67AYe+pP+g=", + "lastModified": 1737634991, + "narHash": "sha256-dBAnb7Kbnier30cA7AgxVSxxARmxKZ1vHZT33THSIr8=", "owner": "hyprwm", "repo": "xdg-desktop-portal-hyprland", - "rev": "7613351375de66ca0d56689e333d460e2db05454", + "rev": "e09dfe2726c8008f983e45a0aa1a3b7416aaeb8a", "type": "github" }, "original": { From 0a1ae48a9fd6eb76baad27de98c00f653a55e4ac Mon Sep 17 00:00:00 2001 From: Vaxry <43317083+vaxerski@users.noreply.github.com> Date: Thu, 23 Jan 2025 21:55:41 +0100 Subject: [PATCH 0886/2181] core: move all shared_ptrs from the STL to hyprutils (#9143) --- CMakeLists.txt | 2 +- src/Compositor.cpp | 56 ++++----- src/Compositor.hpp | 4 +- src/config/ConfigManager.cpp | 10 +- src/config/ConfigManager.hpp | 4 +- src/config/ConfigWatcher.hpp | 4 +- src/debug/HyprCtl.hpp | 2 +- src/debug/HyprDebugOverlay.hpp | 2 +- src/debug/HyprNotificationOverlay.cpp | 2 +- src/debug/HyprNotificationOverlay.hpp | 18 +-- src/desktop/LayerRule.cpp | 2 +- src/desktop/LayerSurface.cpp | 2 +- src/desktop/LayerSurface.hpp | 2 +- src/desktop/Popup.cpp | 2 +- src/desktop/Popup.hpp | 6 +- src/desktop/Rule.cpp | 5 +- src/desktop/Rule.hpp | 6 +- src/desktop/Subsurface.cpp | 4 +- src/desktop/Subsurface.hpp | 16 +-- src/desktop/Window.cpp | 18 +-- src/desktop/Window.hpp | 12 +- src/helpers/Monitor.hpp | 2 +- src/helpers/SdDaemon.cpp | 2 +- src/helpers/Watchdog.cpp | 2 +- src/helpers/Watchdog.hpp | 6 +- src/helpers/memory/Memory.hpp | 2 +- src/hyprerror/HyprError.hpp | 2 +- src/layout/IHyprLayout.cpp | 4 +- src/main.cpp | 2 +- src/managers/AnimationManager.hpp | 2 +- src/managers/CursorManager.cpp | 6 +- src/managers/CursorManager.hpp | 27 +++-- src/managers/DonationNagManager.hpp | 4 +- src/managers/EventManager.hpp | 2 +- src/managers/HookSystemManager.hpp | 2 +- src/managers/KeybindManager.cpp | 2 +- src/managers/KeybindManager.hpp | 2 +- src/managers/LayoutManager.hpp | 2 +- src/managers/ProtocolManager.cpp | 108 +++++++++--------- src/managers/ProtocolManager.hpp | 2 +- src/managers/SessionLockManager.cpp | 4 +- src/managers/SessionLockManager.hpp | 10 +- src/managers/TokenManager.hpp | 2 +- src/managers/VersionKeeperManager.hpp | 4 +- src/managers/XCursorManager.cpp | 1 + src/managers/XWaylandManager.hpp | 2 +- src/managers/eventLoop/EventLoopManager.hpp | 2 +- src/managers/input/IdleInhibitor.cpp | 2 +- src/managers/input/InputManager.hpp | 4 +- src/managers/input/InputMethodRelay.cpp | 6 +- src/managers/input/InputMethodRelay.hpp | 6 +- src/managers/input/TextInput.hpp | 1 - src/pch/pch.hpp | 2 +- src/plugins/HookSystem.cpp | 2 +- src/plugins/HookSystem.hpp | 8 +- src/plugins/PluginAPI.cpp | 2 +- src/plugins/PluginAPI.hpp | 2 +- src/plugins/PluginSystem.cpp | 4 +- src/plugins/PluginSystem.hpp | 6 +- src/protocols/AlphaModifier.cpp | 7 +- src/protocols/AlphaModifier.hpp | 1 - src/protocols/CTMControl.cpp | 2 +- src/protocols/CTMControl.hpp | 3 +- src/protocols/ColorManagement.hpp | 1 - src/protocols/CursorShape.cpp | 2 +- src/protocols/CursorShape.hpp | 1 - src/protocols/DRMLease.hpp | 1 - src/protocols/DRMSyncobj.hpp | 1 - src/protocols/DataDeviceWlr.hpp | 1 - src/protocols/FocusGrab.cpp | 7 +- src/protocols/ForeignToplevel.cpp | 2 +- src/protocols/ForeignToplevel.hpp | 1 - src/protocols/ForeignToplevelWlr.cpp | 2 +- src/protocols/ForeignToplevelWlr.hpp | 1 - src/protocols/FractionalScale.cpp | 4 +- src/protocols/FractionalScale.hpp | 1 - src/protocols/FrogColorManagement.hpp | 1 - src/protocols/GammaControl.cpp | 4 +- src/protocols/GammaControl.hpp | 1 - src/protocols/HyprlandSurface.cpp | 6 +- src/protocols/HyprlandSurface.hpp | 1 - src/protocols/IdleInhibit.cpp | 2 +- src/protocols/IdleInhibit.hpp | 1 - src/protocols/IdleNotify.cpp | 2 +- src/protocols/IdleNotify.hpp | 1 - src/protocols/InputMethodV2.cpp | 2 +- src/protocols/InputMethodV2.hpp | 1 - src/protocols/LayerShell.cpp | 2 +- src/protocols/LayerShell.hpp | 1 - src/protocols/LinuxDMABUF.cpp | 4 +- src/protocols/LinuxDMABUF.hpp | 1 - src/protocols/LockNotify.cpp | 2 +- src/protocols/MesaDRM.hpp | 1 - src/protocols/OutputManagement.hpp | 1 - src/protocols/OutputPower.cpp | 4 +- src/protocols/OutputPower.hpp | 1 - src/protocols/PointerConstraints.cpp | 2 +- src/protocols/PointerConstraints.hpp | 1 - src/protocols/PointerGestures.cpp | 8 +- src/protocols/PointerGestures.hpp | 1 - src/protocols/PresentationTime.cpp | 2 +- src/protocols/PresentationTime.hpp | 1 - src/protocols/PrimarySelection.hpp | 1 - src/protocols/RelativePointer.cpp | 4 +- src/protocols/RelativePointer.hpp | 1 - src/protocols/SecurityContext.hpp | 1 - src/protocols/ServerDecorationKDE.cpp | 5 +- src/protocols/ServerDecorationKDE.hpp | 1 - src/protocols/SessionLock.cpp | 2 +- src/protocols/SessionLock.hpp | 1 - src/protocols/ShortcutsInhibit.cpp | 4 +- src/protocols/ShortcutsInhibit.hpp | 1 - src/protocols/SinglePixel.hpp | 1 - src/protocols/Tablet.cpp | 2 +- src/protocols/Tablet.hpp | 1 - src/protocols/TearingControl.cpp | 4 +- src/protocols/TearingControl.hpp | 1 - src/protocols/TextInputV3.cpp | 2 +- src/protocols/TextInputV3.hpp | 1 - src/protocols/Viewporter.hpp | 1 - src/protocols/VirtualKeyboard.cpp | 2 +- src/protocols/VirtualKeyboard.hpp | 1 - src/protocols/VirtualPointer.cpp | 2 +- src/protocols/VirtualPointer.hpp | 1 - src/protocols/WaylandProtocol.hpp | 1 + src/protocols/XDGActivation.cpp | 4 +- src/protocols/XDGActivation.hpp | 1 - src/protocols/XDGDecoration.cpp | 4 +- src/protocols/XDGDecoration.hpp | 1 - src/protocols/XDGDialog.hpp | 1 - src/protocols/XDGOutput.cpp | 4 +- src/protocols/XDGShell.hpp | 1 - src/protocols/XWaylandShell.hpp | 1 - src/protocols/core/Compositor.hpp | 1 - src/protocols/core/DataDevice.hpp | 1 - src/protocols/core/Output.hpp | 1 - src/protocols/core/Seat.hpp | 1 - src/protocols/core/Shm.hpp | 1 - src/protocols/core/Subcompositor.hpp | 1 - src/protocols/types/WLBuffer.hpp | 1 - src/render/OpenGL.hpp | 2 +- src/render/Renderer.hpp | 2 +- .../decorations/CHyprGroupBarDecoration.cpp | 12 +- .../decorations/CHyprGroupBarDecoration.hpp | 4 +- .../decorations/DecorationPositioner.cpp | 2 +- .../decorations/DecorationPositioner.hpp | 14 +-- src/xwayland/Server.cpp | 2 +- src/xwayland/XDataSource.cpp | 2 +- src/xwayland/XWM.cpp | 8 +- src/xwayland/XWM.hpp | 2 +- src/xwayland/XWayland.cpp | 2 +- src/xwayland/XWayland.hpp | 7 +- 152 files changed, 297 insertions(+), 349 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index c022f3ba..3cfb8688 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -104,7 +104,7 @@ find_package(OpenGL REQUIRED COMPONENTS ${GLES_VERSION}) pkg_check_modules(aquamarine_dep REQUIRED IMPORTED_TARGET aquamarine>=0.4.5) pkg_check_modules(hyprlang_dep REQUIRED IMPORTED_TARGET hyprlang>=0.3.2) pkg_check_modules(hyprcursor_dep REQUIRED IMPORTED_TARGET hyprcursor>=0.1.7) -pkg_check_modules(hyprutils_dep REQUIRED IMPORTED_TARGET hyprutils>=0.3.3) +pkg_check_modules(hyprutils_dep REQUIRED IMPORTED_TARGET hyprutils>=0.4.0) pkg_check_modules(hyprgraphics_dep REQUIRED IMPORTED_TARGET hyprgraphics>=0.1.1) add_compile_definitions(AQUAMARINE_VERSION="${aquamarine_dep_VERSION}") diff --git a/src/Compositor.cpp b/src/Compositor.cpp index f5f1d1f9..aeec2830 100644 --- a/src/Compositor.cpp +++ b/src/Compositor.cpp @@ -586,92 +586,92 @@ void CCompositor::initManagers(eManagersInitStage stage) { switch (stage) { case STAGE_PRIORITY: { Debug::log(LOG, "Creating the EventLoopManager!"); - g_pEventLoopManager = std::make_unique(m_sWLDisplay, m_sWLEventLoop); + g_pEventLoopManager = makeUnique(m_sWLDisplay, m_sWLEventLoop); Debug::log(LOG, "Creating the HookSystem!"); - g_pHookSystem = std::make_unique(); + g_pHookSystem = makeUnique(); Debug::log(LOG, "Creating the KeybindManager!"); - g_pKeybindManager = std::make_unique(); + g_pKeybindManager = makeUnique(); Debug::log(LOG, "Creating the AnimationManager!"); - g_pAnimationManager = std::make_unique(); + g_pAnimationManager = makeUnique(); Debug::log(LOG, "Creating the ConfigManager!"); - g_pConfigManager = std::make_unique(); + g_pConfigManager = makeUnique(); Debug::log(LOG, "Creating the CHyprError!"); - g_pHyprError = std::make_unique(); + g_pHyprError = makeUnique(); Debug::log(LOG, "Creating the LayoutManager!"); - g_pLayoutManager = std::make_unique(); + g_pLayoutManager = makeUnique(); Debug::log(LOG, "Creating the TokenManager!"); - g_pTokenManager = std::make_unique(); + g_pTokenManager = makeUnique(); g_pConfigManager->init(); - g_pWatchdog = std::make_unique(); // requires config + g_pWatchdog = makeUnique(); // requires config // wait for watchdog to initialize to not hit data races in reading config values. while (!g_pWatchdog->m_bWatchdogInitialized) { std::this_thread::yield(); } Debug::log(LOG, "Creating the PointerManager!"); - g_pPointerManager = std::make_unique(); + g_pPointerManager = makeUnique(); Debug::log(LOG, "Creating the EventManager!"); - g_pEventManager = std::make_unique(); + g_pEventManager = makeUnique(); } break; case STAGE_BASICINIT: { Debug::log(LOG, "Creating the CHyprOpenGLImpl!"); - g_pHyprOpenGL = std::make_unique(); + g_pHyprOpenGL = makeUnique(); Debug::log(LOG, "Creating the ProtocolManager!"); - g_pProtocolManager = std::make_unique(); + g_pProtocolManager = makeUnique(); Debug::log(LOG, "Creating the SeatManager!"); - g_pSeatManager = std::make_unique(); + g_pSeatManager = makeUnique(); } break; case STAGE_LATE: { Debug::log(LOG, "Creating CHyprCtl"); - g_pHyprCtl = std::make_unique(); + g_pHyprCtl = makeUnique(); Debug::log(LOG, "Creating the InputManager!"); - g_pInputManager = std::make_unique(); + g_pInputManager = makeUnique(); Debug::log(LOG, "Creating the HyprRenderer!"); - g_pHyprRenderer = std::make_unique(); + g_pHyprRenderer = makeUnique(); Debug::log(LOG, "Creating the XWaylandManager!"); - g_pXWaylandManager = std::make_unique(); + g_pXWaylandManager = makeUnique(); Debug::log(LOG, "Creating the SessionLockManager!"); - g_pSessionLockManager = std::make_unique(); + g_pSessionLockManager = makeUnique(); Debug::log(LOG, "Creating the HyprDebugOverlay!"); - g_pDebugOverlay = std::make_unique(); + g_pDebugOverlay = makeUnique(); Debug::log(LOG, "Creating the HyprNotificationOverlay!"); - g_pHyprNotificationOverlay = std::make_unique(); + g_pHyprNotificationOverlay = makeUnique(); Debug::log(LOG, "Creating the PluginSystem!"); - g_pPluginSystem = std::make_unique(); + g_pPluginSystem = makeUnique(); g_pConfigManager->handlePluginLoads(); Debug::log(LOG, "Creating the DecorationPositioner!"); - g_pDecorationPositioner = std::make_unique(); + g_pDecorationPositioner = makeUnique(); Debug::log(LOG, "Creating the CursorManager!"); - g_pCursorManager = std::make_unique(); + g_pCursorManager = makeUnique(); Debug::log(LOG, "Creating the VersionKeeper!"); - g_pVersionKeeperMgr = std::make_unique(); + g_pVersionKeeperMgr = makeUnique(); Debug::log(LOG, "Creating the DonationNag!"); - g_pDonationNagManager = std::make_unique(); + g_pDonationNagManager = makeUnique(); Debug::log(LOG, "Starting XWayland"); - g_pXWayland = std::make_unique(g_pCompositor->m_bWantsXwayland); + g_pXWayland = makeUnique(g_pCompositor->m_bWantsXwayland); } break; default: UNREACHABLE(); } @@ -2701,7 +2701,7 @@ void CCompositor::moveWindowToWorkspaceSafe(PHLWINDOW pWindow, PHLWORKSPACE pWor g_pLayoutManager->getCurrentLayout()->recalculateWindow(pWindow); if (!pWindow->getDecorationByType(DECORATION_GROUPBAR)) - pWindow->addWindowDeco(std::make_unique(pWindow)); + pWindow->addWindowDeco(makeUnique(pWindow)); } else { if (!pWindow->m_bIsFloating) diff --git a/src/Compositor.hpp b/src/Compositor.hpp index 0a87ec33..f2e2ca14 100644 --- a/src/Compositor.hpp +++ b/src/Compositor.hpp @@ -1,6 +1,5 @@ #pragma once -#include #include #include @@ -10,6 +9,7 @@ #include "managers/SessionLockManager.hpp" #include "desktop/Window.hpp" #include "protocols/types/ColorManagement.hpp" +#include "helpers/memory/Memory.hpp" #include #include @@ -170,4 +170,4 @@ class CCompositor { rlimit m_sOriginalNofile = {0}; }; -inline std::unique_ptr g_pCompositor; +inline UP g_pCompositor; diff --git a/src/config/ConfigManager.cpp b/src/config/ConfigManager.cpp index 60b818f0..08f0f33f 100644 --- a/src/config/ConfigManager.cpp +++ b/src/config/ConfigManager.cpp @@ -44,6 +44,7 @@ #include #include #include +#include using namespace Hyprutils::String; using namespace Hyprutils::Animation; @@ -374,7 +375,7 @@ CConfigManager::CConfigManager() { const auto ERR = verifyConfigExists(); m_configPaths.emplace_back(getMainConfigPath()); - m_pConfig = std::make_unique(m_configPaths.begin()->c_str(), Hyprlang::SConfigOptions{.throwAllErrors = true, .allowMissingConfig = true}); + m_pConfig = makeUnique(m_configPaths.begin()->c_str(), Hyprlang::SConfigOptions{.throwAllErrors = true, .allowMissingConfig = true}); m_pConfig->addConfigValue("general:border_size", Hyprlang::INT{1}); m_pConfig->addConfigValue("general:no_border_on_floating", Hyprlang::INT{0}); @@ -955,9 +956,8 @@ void CConfigManager::postConfigReload(const Hyprlang::CParseResult& result) { // enable/disable xwayland usage if (!isFirstLaunch) { bool prevEnabledXwayland = g_pXWayland->enabled(); - if (g_pCompositor->m_bWantsXwayland != prevEnabledXwayland) { - g_pXWayland = std::make_unique(g_pCompositor->m_bWantsXwayland); - } + if (g_pCompositor->m_bWantsXwayland != prevEnabledXwayland) + g_pXWayland = makeUnique(g_pCompositor->m_bWantsXwayland); } else g_pCompositor->m_bWantsXwayland = PENABLEXWAYLAND; #endif @@ -1659,7 +1659,7 @@ void CConfigManager::addExecRule(const SExecRequestedRule& rule) { } void CConfigManager::handlePluginLoads() { - if (g_pPluginSystem == nullptr) + if (!g_pPluginSystem) return; bool pluginsChanged = false; diff --git a/src/config/ConfigManager.hpp b/src/config/ConfigManager.hpp index 1962e4d2..31ad81cd 100644 --- a/src/config/ConfigManager.hpp +++ b/src/config/ConfigManager.hpp @@ -262,7 +262,7 @@ class CConfigManager { bool isLaunchingExecOnce = false; // For exec-once to skip initial ws tracking private: - std::unique_ptr m_pConfig; + UP m_pConfig; std::vector m_configPaths; @@ -303,4 +303,4 @@ class CConfigManager { SWorkspaceRule mergeWorkspaceRules(const SWorkspaceRule&, const SWorkspaceRule&); }; -inline std::unique_ptr g_pConfigManager; +inline UP g_pConfigManager; diff --git a/src/config/ConfigWatcher.hpp b/src/config/ConfigWatcher.hpp index 0a698fc8..c36ecd17 100644 --- a/src/config/ConfigWatcher.hpp +++ b/src/config/ConfigWatcher.hpp @@ -1,5 +1,5 @@ #pragma once -#include +#include "../helpers/memory/Memory.hpp" #include #include #include @@ -29,4 +29,4 @@ class CConfigWatcher { int m_inotifyFd = -1; }; -inline std::unique_ptr g_pConfigWatcher = std::make_unique(); \ No newline at end of file +inline UP g_pConfigWatcher = makeUnique(); \ No newline at end of file diff --git a/src/debug/HyprCtl.hpp b/src/debug/HyprCtl.hpp index 2603612c..eed8265c 100644 --- a/src/debug/HyprCtl.hpp +++ b/src/debug/HyprCtl.hpp @@ -38,4 +38,4 @@ class CHyprCtl { std::string m_socketPath; }; -inline std::unique_ptr g_pHyprCtl; +inline UP g_pHyprCtl; diff --git a/src/debug/HyprDebugOverlay.hpp b/src/debug/HyprDebugOverlay.hpp index a58ecffc..f4ef122f 100644 --- a/src/debug/HyprDebugOverlay.hpp +++ b/src/debug/HyprDebugOverlay.hpp @@ -48,4 +48,4 @@ class CHyprDebugOverlay { friend class CHyprRenderer; }; -inline std::unique_ptr g_pDebugOverlay; +inline UP g_pDebugOverlay; diff --git a/src/debug/HyprNotificationOverlay.cpp b/src/debug/HyprNotificationOverlay.cpp index 09125243..66c68d08 100644 --- a/src/debug/HyprNotificationOverlay.cpp +++ b/src/debug/HyprNotificationOverlay.cpp @@ -40,7 +40,7 @@ CHyprNotificationOverlay::~CHyprNotificationOverlay() { } void CHyprNotificationOverlay::addNotification(const std::string& text, const CHyprColor& color, const float timeMs, const eIcons icon, const float fontSize) { - const auto PNOTIF = m_vNotifications.emplace_back(std::make_unique()).get(); + const auto PNOTIF = m_vNotifications.emplace_back(makeUnique()).get(); PNOTIF->text = icon != eIcons::ICON_NONE ? " " + text /* tiny bit of padding otherwise icon touches text */ : text; PNOTIF->color = color == CHyprColor(0) ? ICONS_COLORS[icon] : color; diff --git a/src/debug/HyprNotificationOverlay.hpp b/src/debug/HyprNotificationOverlay.hpp index 2546d04f..b04cb73b 100644 --- a/src/debug/HyprNotificationOverlay.hpp +++ b/src/debug/HyprNotificationOverlay.hpp @@ -46,18 +46,18 @@ class CHyprNotificationOverlay { bool hasAny(); private: - CBox drawNotifications(PHLMONITOR pMonitor); - CBox m_bLastDamage; + CBox drawNotifications(PHLMONITOR pMonitor); + CBox m_bLastDamage; - std::vector> m_vNotifications; + std::vector> m_vNotifications; - cairo_surface_t* m_pCairoSurface = nullptr; - cairo_t* m_pCairo = nullptr; + cairo_surface_t* m_pCairoSurface = nullptr; + cairo_t* m_pCairo = nullptr; - PHLMONITORREF m_pLastMonitor; - Vector2D m_vecLastSize = Vector2D(-1, -1); + PHLMONITORREF m_pLastMonitor; + Vector2D m_vecLastSize = Vector2D(-1, -1); - SP m_pTexture; + SP m_pTexture; }; -inline std::unique_ptr g_pHyprNotificationOverlay; +inline UP g_pHyprNotificationOverlay; diff --git a/src/desktop/LayerRule.cpp b/src/desktop/LayerRule.cpp index 23371947..791a557e 100644 --- a/src/desktop/LayerRule.cpp +++ b/src/desktop/LayerRule.cpp @@ -1,7 +1,7 @@ +#include #include "LayerRule.hpp" #include #include -#include #include "../debug/Log.hpp" static const auto RULES = std::unordered_set{"noanim", "blur", "blurpopups", "dimaround"}; diff --git a/src/desktop/LayerSurface.cpp b/src/desktop/LayerSurface.cpp index c572f6b2..dd30aa7c 100644 --- a/src/desktop/LayerSurface.cpp +++ b/src/desktop/LayerSurface.cpp @@ -32,7 +32,7 @@ PHLLS CLayerSurface::create(SP resource) { pLS->szNamespace = resource->layerNamespace; pLS->layer = resource->current.layer; - pLS->popupHead = std::make_unique(pLS); + pLS->popupHead = makeUnique(pLS); pLS->monitor = pMonitor; pMonitor->m_aLayerSurfaceLayers[resource->current.layer].emplace_back(pLS); diff --git a/src/desktop/LayerSurface.hpp b/src/desktop/LayerSurface.hpp index 591dfd99..ab259733 100644 --- a/src/desktop/LayerSurface.hpp +++ b/src/desktop/LayerSurface.hpp @@ -59,7 +59,7 @@ class CLayerSurface { CBox geometry = {0, 0, 0, 0}; Vector2D position; std::string szNamespace = ""; - std::unique_ptr popupHead; + UP popupHead; void onDestroy(); void onMap(); diff --git a/src/desktop/Popup.cpp b/src/desktop/Popup.cpp index ce6ab9a0..831619a5 100644 --- a/src/desktop/Popup.cpp +++ b/src/desktop/Popup.cpp @@ -89,7 +89,7 @@ void CPopup::onMap() { g_pInputManager->simulateMouseMovement(); - m_pSubsurfaceHead = std::make_unique(this); + m_pSubsurfaceHead = makeUnique(this); //unconstrain(); sendScale(); diff --git a/src/desktop/Popup.hpp b/src/desktop/Popup.hpp index e9b3e0f0..2b7b4e82 100644 --- a/src/desktop/Popup.hpp +++ b/src/desktop/Popup.hpp @@ -1,9 +1,9 @@ #pragma once #include -#include #include "Subsurface.hpp" #include "../helpers/signal/Signal.hpp" +#include "../helpers/memory/Memory.hpp" class CXDGPopupResource; @@ -61,8 +61,8 @@ class CPopup { bool m_bInert = false; // - std::vector> m_vChildren; - std::unique_ptr m_pSubsurfaceHead; + std::vector> m_vChildren; + UP m_pSubsurfaceHead; struct { CHyprSignalListener newPopup; diff --git a/src/desktop/Rule.cpp b/src/desktop/Rule.cpp index ae280642..aa87a483 100644 --- a/src/desktop/Rule.cpp +++ b/src/desktop/Rule.cpp @@ -1,12 +1,13 @@ -#include "Rule.hpp" #include +#include "../helpers/memory/Memory.hpp" +#include "Rule.hpp" #include "../debug/Log.hpp" CRuleRegexContainer::CRuleRegexContainer(const std::string& regex_) { const bool NEGATIVE = regex_.starts_with("negative:"); negative = NEGATIVE; - regex = std::make_unique(NEGATIVE ? regex_.substr(9) : regex_); + regex = makeUnique(NEGATIVE ? regex_.substr(9) : regex_); // TODO: maybe pop an error? if (!regex->ok()) diff --git a/src/desktop/Rule.hpp b/src/desktop/Rule.hpp index 4b178ee8..858b4ded 100644 --- a/src/desktop/Rule.hpp +++ b/src/desktop/Rule.hpp @@ -1,6 +1,6 @@ #pragma once -#include +#include //NOLINTNEXTLINE namespace re2 { @@ -16,6 +16,6 @@ class CRuleRegexContainer { bool passes(const std::string& str) const; private: - std::unique_ptr regex; - bool negative = false; + Hyprutils::Memory::CUniquePointer regex; + bool negative = false; }; \ No newline at end of file diff --git a/src/desktop/Subsurface.cpp b/src/desktop/Subsurface.cpp index 26638f7a..9cdf3685 100644 --- a/src/desktop/Subsurface.cpp +++ b/src/desktop/Subsurface.cpp @@ -126,9 +126,9 @@ void CSubsurface::onNewSubsurface(SP pSubsurface) { CSubsurface* PSUBSURFACE = nullptr; if (!m_pWindowParent.expired()) - PSUBSURFACE = m_vChildren.emplace_back(std::make_unique(pSubsurface, m_pWindowParent.lock())).get(); + PSUBSURFACE = m_vChildren.emplace_back(makeUnique(pSubsurface, m_pWindowParent.lock())).get(); else if (m_pPopupParent) - PSUBSURFACE = m_vChildren.emplace_back(std::make_unique(pSubsurface, m_pPopupParent)).get(); + PSUBSURFACE = m_vChildren.emplace_back(makeUnique(pSubsurface, m_pPopupParent)).get(); ASSERT(PSUBSURFACE); diff --git a/src/desktop/Subsurface.hpp b/src/desktop/Subsurface.hpp index 7829c489..aacbad91 100644 --- a/src/desktop/Subsurface.hpp +++ b/src/desktop/Subsurface.hpp @@ -48,16 +48,16 @@ class CSubsurface { Vector2D m_vLastSize = {}; // if nullptr, means it's a dummy node - CSubsurface* m_pParent = nullptr; + CSubsurface* m_pParent = nullptr; - PHLWINDOWREF m_pWindowParent; - CPopup* m_pPopupParent = nullptr; + PHLWINDOWREF m_pWindowParent; + CPopup* m_pPopupParent = nullptr; - std::vector> m_vChildren; + std::vector> m_vChildren; - bool m_bInert = false; + bool m_bInert = false; - void initSignals(); - void initExistingSubsurfaces(SP pSurface); - void checkSiblingDamage(); + void initSignals(); + void initExistingSubsurfaces(SP pSurface); + void checkSiblingDamage(); }; \ No newline at end of file diff --git a/src/desktop/Window.cpp b/src/desktop/Window.cpp index 829f4e2e..fb5904be 100644 --- a/src/desktop/Window.cpp +++ b/src/desktop/Window.cpp @@ -47,8 +47,8 @@ PHLWINDOW CWindow::create(SP surface) { g_pAnimationManager->createAnimation(0.f, pWindow->m_fMovingToWorkspaceAlpha, g_pConfigManager->getAnimationPropertyConfig("fadeOut"), pWindow, AVARDAMAGE_ENTIRE); g_pAnimationManager->createAnimation(0.f, pWindow->m_fMovingFromWorkspaceAlpha, g_pConfigManager->getAnimationPropertyConfig("fadeIn"), pWindow, AVARDAMAGE_ENTIRE); - pWindow->addWindowDeco(std::make_unique(pWindow)); - pWindow->addWindowDeco(std::make_unique(pWindow)); + pWindow->addWindowDeco(makeUnique(pWindow)); + pWindow->addWindowDeco(makeUnique(pWindow)); return pWindow; } @@ -70,8 +70,8 @@ PHLWINDOW CWindow::create(SP resource) { g_pAnimationManager->createAnimation(0.f, pWindow->m_fMovingToWorkspaceAlpha, g_pConfigManager->getAnimationPropertyConfig("fadeOut"), pWindow, AVARDAMAGE_ENTIRE); g_pAnimationManager->createAnimation(0.f, pWindow->m_fMovingFromWorkspaceAlpha, g_pConfigManager->getAnimationPropertyConfig("fadeIn"), pWindow, AVARDAMAGE_ENTIRE); - pWindow->addWindowDeco(std::make_unique(pWindow)); - pWindow->addWindowDeco(std::make_unique(pWindow)); + pWindow->addWindowDeco(makeUnique(pWindow)); + pWindow->addWindowDeco(makeUnique(pWindow)); pWindow->m_pWLSurface->assign(pWindow->m_pXDGSurface->surface.lock(), pWindow); @@ -296,7 +296,7 @@ void CWindow::updateWindowDecos() { } } -void CWindow::addWindowDeco(std::unique_ptr deco) { +void CWindow::addWindowDeco(UP deco) { m_dWindowDecorations.emplace_back(std::move(deco)); g_pDecorationPositioner->forceRecalcFor(m_pSelf.lock()); updateWindowDecos(); @@ -567,8 +567,8 @@ void CWindow::onMap() { if (m_bIsX11) return; - m_pSubsurfaceHead = std::make_unique(m_pSelf.lock()); - m_pPopupHead = std::make_unique(m_pSelf.lock()); + m_pSubsurfaceHead = makeUnique(m_pSelf.lock()); + m_pPopupHead = makeUnique(m_pSelf.lock()); } void CWindow::onBorderAngleAnimEnd(WP pav) { @@ -870,7 +870,7 @@ void CWindow::createGroup() { m_sGroupData.locked = false; m_sGroupData.deny = false; - addWindowDeco(std::make_unique(m_pSelf.lock())); + addWindowDeco(makeUnique(m_pSelf.lock())); if (m_pWorkspace) { m_pWorkspace->updateWindows(); @@ -1052,7 +1052,7 @@ void CWindow::insertWindowToGroup(PHLWINDOW pWindow) { const auto ENDAT = m_sGroupData.pNextWindow.lock(); if (!pWindow->getDecorationByType(DECORATION_GROUPBAR)) - pWindow->addWindowDeco(std::make_unique(pWindow)); + pWindow->addWindowDeco(makeUnique(pWindow)); if (!pWindow->m_sGroupData.pNextWindow.lock()) { BEGINAT->m_sGroupData.pNextWindow = pWindow; diff --git a/src/desktop/Window.hpp b/src/desktop/Window.hpp index ebda235c..5b4ad654 100644 --- a/src/desktop/Window.hpp +++ b/src/desktop/Window.hpp @@ -296,8 +296,8 @@ class CWindow { uint64_t m_eSuppressedEvents = SUPPRESS_NONE; // desktop components - std::unique_ptr m_pSubsurfaceHead; - std::unique_ptr m_pPopupHead; + UP m_pSubsurfaceHead; + UP m_pPopupHead; // Animated border CGradientValueData m_cRealBorderColor = {0}; @@ -328,14 +328,14 @@ class CWindow { // Window decorations // TODO: make this a SP. - std::vector> m_dWindowDecorations; - std::vector m_vDecosToRemove; + std::vector> m_dWindowDecorations; + std::vector m_vDecosToRemove; // Special render data, rules, etc SWindowData m_sWindowData; // Transformers - std::vector> m_vTransformers; + std::vector> m_vTransformers; // for alpha PHLANIMVAR m_fActiveInactiveAlpha; @@ -396,7 +396,7 @@ class CWindow { SBoxExtents getFullWindowExtents(); CBox getWindowBoxUnified(uint64_t props); CBox getWindowIdealBoundingBoxIgnoreReserved(); - void addWindowDeco(std::unique_ptr deco); + void addWindowDeco(UP deco); void updateWindowDecos(); void removeWindowDeco(IHyprWindowDecoration* deco); void uncacheWindowDecos(); diff --git a/src/helpers/Monitor.hpp b/src/helpers/Monitor.hpp index b33725d5..e07d62c6 100644 --- a/src/helpers/Monitor.hpp +++ b/src/helpers/Monitor.hpp @@ -8,7 +8,7 @@ #include "WLClasses.hpp" #include #include -#include + #include #include "Timer.hpp" #include "math/Math.hpp" diff --git a/src/helpers/SdDaemon.cpp b/src/helpers/SdDaemon.cpp index 018165c0..1cf15741 100644 --- a/src/helpers/SdDaemon.cpp +++ b/src/helpers/SdDaemon.cpp @@ -1,7 +1,7 @@ #include "SdDaemon.hpp" +#include "memory/Memory.hpp" #include - #include #include #include diff --git a/src/helpers/Watchdog.cpp b/src/helpers/Watchdog.cpp index b919bbc7..0956eed5 100644 --- a/src/helpers/Watchdog.cpp +++ b/src/helpers/Watchdog.cpp @@ -14,7 +14,7 @@ CWatchdog::~CWatchdog() { CWatchdog::CWatchdog() : m_iMainThreadPID(pthread_self()) { - m_pWatchdog = std::make_unique([this] { + m_pWatchdog = makeUnique([this] { static auto PTIMEOUT = CConfigValue("debug:watchdog_timeout"); m_bWatchdogInitialized = true; diff --git a/src/helpers/Watchdog.hpp b/src/helpers/Watchdog.hpp index b16cb518..51b71d13 100644 --- a/src/helpers/Watchdog.hpp +++ b/src/helpers/Watchdog.hpp @@ -1,6 +1,6 @@ #pragma once -#include +#include "memory/Memory.hpp" #include #include #include @@ -24,11 +24,11 @@ class CWatchdog { std::atomic m_bWatching = false; std::atomic m_bWillWatch = false; - std::unique_ptr m_pWatchdog; + UP m_pWatchdog; std::mutex m_mWatchdogMutex; std::atomic m_bNotified = false; std::atomic m_bExitThread = false; std::condition_variable m_cvWatchdogCondition; }; -inline std::unique_ptr g_pWatchdog; \ No newline at end of file +inline UP g_pWatchdog; \ No newline at end of file diff --git a/src/helpers/memory/Memory.hpp b/src/helpers/memory/Memory.hpp index 07f41154..e67c2c81 100644 --- a/src/helpers/memory/Memory.hpp +++ b/src/helpers/memory/Memory.hpp @@ -7,4 +7,4 @@ using namespace Hyprutils::Memory; #define SP Hyprutils::Memory::CSharedPointer #define WP Hyprutils::Memory::CWeakPointer -#define UP std::unique_ptr +#define UP Hyprutils::Memory::CUniquePointer diff --git a/src/hyprerror/HyprError.hpp b/src/hyprerror/HyprError.hpp index 9a662423..771e50f0 100644 --- a/src/hyprerror/HyprError.hpp +++ b/src/hyprerror/HyprError.hpp @@ -32,4 +32,4 @@ class CHyprError { bool m_bMonitorChanged = false; }; -inline std::unique_ptr g_pHyprError; // This is a full-screen error. Treat it with respect, and there can only be one at a time. +inline UP g_pHyprError; // This is a full-screen error. Treat it with respect, and there can only be one at a time. diff --git a/src/layout/IHyprLayout.cpp b/src/layout/IHyprLayout.cpp index 156141f6..576d80eb 100644 --- a/src/layout/IHyprLayout.cpp +++ b/src/layout/IHyprLayout.cpp @@ -215,7 +215,7 @@ bool IHyprLayout::onWindowCreatedAutoGroup(PHLWINDOW pWindow) { recalculateWindow(pWindow); if (!pWindow->getDecorationByType(DECORATION_GROUPBAR)) - pWindow->addWindowDeco(std::make_unique(pWindow)); + pWindow->addWindowDeco(makeUnique(pWindow)); return true; } @@ -374,7 +374,7 @@ void IHyprLayout::onEndDragWindow() { DRAGGINGWINDOW->updateWindowDecos(); if (!DRAGGINGWINDOW->getDecorationByType(DECORATION_GROUPBAR)) - DRAGGINGWINDOW->addWindowDeco(std::make_unique(DRAGGINGWINDOW)); + DRAGGINGWINDOW->addWindowDeco(makeUnique(DRAGGINGWINDOW)); } } } diff --git a/src/main.cpp b/src/main.cpp index ebae055b..bb5e5622 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -155,7 +155,7 @@ int main(int argc, char** argv) { // let's init the compositor. // it initializes basic Wayland stuff in the constructor. try { - g_pCompositor = std::make_unique(); + g_pCompositor = makeUnique(); g_pCompositor->explicitConfigPath = configPath; } catch (const std::exception& e) { std::println(stderr, "Hyprland threw in ctor: {}\nCannot continue.", e.what()); diff --git a/src/managers/AnimationManager.hpp b/src/managers/AnimationManager.hpp index 10eeef05..067fa676 100644 --- a/src/managers/AnimationManager.hpp +++ b/src/managers/AnimationManager.hpp @@ -61,4 +61,4 @@ class CHyprAnimationManager : public Hyprutils::Animation::CAnimationManager { void animationSlide(PHLWINDOW, std::string force = "", bool close = false); }; -inline std::unique_ptr g_pAnimationManager; +inline UP g_pAnimationManager; diff --git a/src/managers/CursorManager.cpp b/src/managers/CursorManager.cpp index d6584f35..160ef2eb 100644 --- a/src/managers/CursorManager.cpp +++ b/src/managers/CursorManager.cpp @@ -64,8 +64,8 @@ void CCursorBuffer::endDataPtr() { } CCursorManager::CCursorManager() { - m_pHyprcursor = std::make_unique(m_szTheme.empty() ? nullptr : m_szTheme.c_str(), hcLogger); - m_pXcursor = std::make_unique(); + m_pHyprcursor = makeUnique(m_szTheme.empty() ? nullptr : m_szTheme.c_str(), hcLogger); + m_pXcursor = makeUnique(); static auto PUSEHYPRCURSOR = CConfigValue("cursor:enable_hyprcursor"); if (m_pHyprcursor->valid() && *PUSEHYPRCURSOR) { @@ -323,7 +323,7 @@ bool CCursorManager::changeTheme(const std::string& name, const int size) { m_szTheme = name.empty() ? "" : name; m_iSize = size; - m_pHyprcursor = std::make_unique(m_szTheme.empty() ? nullptr : m_szTheme.c_str(), options); + m_pHyprcursor = makeUnique(m_szTheme.empty() ? nullptr : m_szTheme.c_str(), options); if (!m_pHyprcursor->valid()) { Debug::log(ERR, "Hyprcursor failed loading theme \"{}\", falling back to XCursor.", m_szTheme); m_pXcursor->loadTheme(m_szTheme.empty() ? xcursor_theme : m_szTheme, m_iSize, m_fCursorScale); diff --git a/src/managers/CursorManager.hpp b/src/managers/CursorManager.hpp index 796ab10e..c5ded5da 100644 --- a/src/managers/CursorManager.hpp +++ b/src/managers/CursorManager.hpp @@ -2,7 +2,6 @@ #include #include -#include #include "../includes.hpp" #include "../helpers/math/Math.hpp" #include "../helpers/memory/Memory.hpp" @@ -58,22 +57,22 @@ class CCursorManager { void tickAnimatedCursor(); private: - bool m_bOurBufferConnected = false; - std::vector> m_vCursorBuffers; + bool m_bOurBufferConnected = false; + std::vector> m_vCursorBuffers; - std::unique_ptr m_pHyprcursor; - std::unique_ptr m_pXcursor; - SP m_currentXcursor; + UP m_pHyprcursor; + UP m_pXcursor; + SP m_currentXcursor; - std::string m_szTheme = ""; - int m_iSize = 0; - float m_fCursorScale = 1.0; + std::string m_szTheme = ""; + int m_iSize = 0; + float m_fCursorScale = 1.0; - Hyprcursor::SCursorStyleInfo m_sCurrentStyleInfo; + Hyprcursor::SCursorStyleInfo m_sCurrentStyleInfo; - SP m_pAnimationTimer; - int m_iCurrentAnimationFrame = 0; - Hyprcursor::SCursorShapeData m_sCurrentCursorShapeData; + SP m_pAnimationTimer; + int m_iCurrentAnimationFrame = 0; + Hyprcursor::SCursorShapeData m_sCurrentCursorShapeData; }; -inline std::unique_ptr g_pCursorManager; +inline UP g_pCursorManager; diff --git a/src/managers/DonationNagManager.hpp b/src/managers/DonationNagManager.hpp index e296d815..357f979f 100644 --- a/src/managers/DonationNagManager.hpp +++ b/src/managers/DonationNagManager.hpp @@ -1,6 +1,6 @@ #pragma once -#include +#include "../helpers/memory/Memory.hpp" class CDonationNagManager { public: @@ -13,4 +13,4 @@ class CDonationNagManager { bool m_bFired = false; }; -inline std::unique_ptr g_pDonationNagManager; \ No newline at end of file +inline UP g_pDonationNagManager; \ No newline at end of file diff --git a/src/managers/EventManager.hpp b/src/managers/EventManager.hpp index 37716e63..5a88963e 100644 --- a/src/managers/EventManager.hpp +++ b/src/managers/EventManager.hpp @@ -42,4 +42,4 @@ class CEventManager { std::vector m_vClients; }; -inline std::unique_ptr g_pEventManager; +inline UP g_pEventManager; diff --git a/src/managers/HookSystemManager.hpp b/src/managers/HookSystemManager.hpp index 5a9d0c00..6d72a02d 100644 --- a/src/managers/HookSystemManager.hpp +++ b/src/managers/HookSystemManager.hpp @@ -57,4 +57,4 @@ class CHookSystemManager { std::unordered_map> m_mRegisteredHooks; }; -inline std::unique_ptr g_pHookSystem; +inline UP g_pHookSystem; diff --git a/src/managers/KeybindManager.cpp b/src/managers/KeybindManager.cpp index 0816de2a..f4a55a73 100644 --- a/src/managers/KeybindManager.cpp +++ b/src/managers/KeybindManager.cpp @@ -2840,7 +2840,7 @@ void CKeybindManager::moveWindowIntoGroup(PHLWINDOW pWindow, PHLWINDOW pWindowIn pWindow->warpCursor(); if (!pWindow->getDecorationByType(DECORATION_GROUPBAR)) - pWindow->addWindowDeco(std::make_unique(pWindow)); + pWindow->addWindowDeco(makeUnique(pWindow)); g_pEventManager->postEvent(SHyprIPCEvent{"moveintogroup", std::format("{:x}", (uintptr_t)pWindow.get())}); } diff --git a/src/managers/KeybindManager.hpp b/src/managers/KeybindManager.hpp index d01ec75b..1848ca78 100644 --- a/src/managers/KeybindManager.hpp +++ b/src/managers/KeybindManager.hpp @@ -229,4 +229,4 @@ class CKeybindManager { friend class CPointerManager; }; -inline std::unique_ptr g_pKeybindManager; +inline UP g_pKeybindManager; diff --git a/src/managers/LayoutManager.hpp b/src/managers/LayoutManager.hpp index 6042b3b2..63e54baa 100644 --- a/src/managers/LayoutManager.hpp +++ b/src/managers/LayoutManager.hpp @@ -28,4 +28,4 @@ class CLayoutManager { std::vector> m_vLayouts; }; -inline std::unique_ptr g_pLayoutManager; +inline UP g_pLayoutManager; diff --git a/src/managers/ProtocolManager.cpp b/src/managers/ProtocolManager.cpp index 8e32bdec..f73a6d3c 100644 --- a/src/managers/ProtocolManager.cpp +++ b/src/managers/ProtocolManager.cpp @@ -119,75 +119,75 @@ CProtocolManager::CProtocolManager() { }); // Core - PROTO::seat = std::make_unique(&wl_seat_interface, 9, "WLSeat"); - PROTO::data = std::make_unique(&wl_data_device_manager_interface, 3, "WLDataDevice"); - PROTO::compositor = std::make_unique(&wl_compositor_interface, 6, "WLCompositor"); - PROTO::subcompositor = std::make_unique(&wl_subcompositor_interface, 1, "WLSubcompositor"); - PROTO::shm = std::make_unique(&wl_shm_interface, 1, "WLSHM"); + PROTO::seat = makeUnique(&wl_seat_interface, 9, "WLSeat"); + PROTO::data = makeUnique(&wl_data_device_manager_interface, 3, "WLDataDevice"); + PROTO::compositor = makeUnique(&wl_compositor_interface, 6, "WLCompositor"); + PROTO::subcompositor = makeUnique(&wl_subcompositor_interface, 1, "WLSubcompositor"); + PROTO::shm = makeUnique(&wl_shm_interface, 1, "WLSHM"); // Extensions - PROTO::viewport = std::make_unique(&wp_viewporter_interface, 1, "Viewporter"); - PROTO::tearing = std::make_unique(&wp_tearing_control_manager_v1_interface, 1, "TearingControl"); - PROTO::fractional = std::make_unique(&wp_fractional_scale_manager_v1_interface, 1, "FractionalScale"); - PROTO::xdgOutput = std::make_unique(&zxdg_output_manager_v1_interface, 3, "XDGOutput"); - PROTO::cursorShape = std::make_unique(&wp_cursor_shape_manager_v1_interface, 1, "CursorShape"); - PROTO::idleInhibit = std::make_unique(&zwp_idle_inhibit_manager_v1_interface, 1, "IdleInhibit"); - PROTO::relativePointer = std::make_unique(&zwp_relative_pointer_manager_v1_interface, 1, "RelativePointer"); - PROTO::xdgDecoration = std::make_unique(&zxdg_decoration_manager_v1_interface, 1, "XDGDecoration"); - PROTO::alphaModifier = std::make_unique(&wp_alpha_modifier_v1_interface, 1, "AlphaModifier"); - PROTO::gamma = std::make_unique(&zwlr_gamma_control_manager_v1_interface, 1, "GammaControl"); - PROTO::foreignToplevel = std::make_unique(&ext_foreign_toplevel_list_v1_interface, 1, "ForeignToplevel"); - PROTO::pointerGestures = std::make_unique(&zwp_pointer_gestures_v1_interface, 3, "PointerGestures"); - PROTO::foreignToplevelWlr = std::make_unique(&zwlr_foreign_toplevel_manager_v1_interface, 3, "ForeignToplevelWlr"); - PROTO::shortcutsInhibit = std::make_unique(&zwp_keyboard_shortcuts_inhibit_manager_v1_interface, 1, "ShortcutsInhibit"); - PROTO::textInputV1 = std::make_unique(&zwp_text_input_manager_v1_interface, 1, "TextInputV1"); - PROTO::textInputV3 = std::make_unique(&zwp_text_input_manager_v3_interface, 1, "TextInputV3"); - PROTO::constraints = std::make_unique(&zwp_pointer_constraints_v1_interface, 1, "PointerConstraints"); - PROTO::outputPower = std::make_unique(&zwlr_output_power_manager_v1_interface, 1, "OutputPower"); - PROTO::activation = std::make_unique(&xdg_activation_v1_interface, 1, "XDGActivation"); - PROTO::idle = std::make_unique(&ext_idle_notifier_v1_interface, 1, "IdleNotify"); - PROTO::lockNotify = std::make_unique(&hyprland_lock_notifier_v1_interface, 1, "IdleNotify"); - PROTO::sessionLock = std::make_unique(&ext_session_lock_manager_v1_interface, 1, "SessionLock"); - PROTO::ime = std::make_unique(&zwp_input_method_manager_v2_interface, 1, "IMEv2"); - PROTO::virtualKeyboard = std::make_unique(&zwp_virtual_keyboard_manager_v1_interface, 1, "VirtualKeyboard"); - PROTO::virtualPointer = std::make_unique(&zwlr_virtual_pointer_manager_v1_interface, 2, "VirtualPointer"); - PROTO::outputManagement = std::make_unique(&zwlr_output_manager_v1_interface, 4, "OutputManagement"); - PROTO::serverDecorationKDE = std::make_unique(&org_kde_kwin_server_decoration_manager_interface, 1, "ServerDecorationKDE"); - PROTO::focusGrab = std::make_unique(&hyprland_focus_grab_manager_v1_interface, 1, "FocusGrab"); - PROTO::tablet = std::make_unique(&zwp_tablet_manager_v2_interface, 1, "TabletV2"); - PROTO::layerShell = std::make_unique(&zwlr_layer_shell_v1_interface, 5, "LayerShell"); - PROTO::presentation = std::make_unique(&wp_presentation_interface, 1, "Presentation"); - PROTO::xdgShell = std::make_unique(&xdg_wm_base_interface, 6, "XDGShell"); - PROTO::dataWlr = std::make_unique(&zwlr_data_control_manager_v1_interface, 2, "DataDeviceWlr"); - PROTO::primarySelection = std::make_unique(&zwp_primary_selection_device_manager_v1_interface, 1, "PrimarySelection"); - PROTO::xwaylandShell = std::make_unique(&xwayland_shell_v1_interface, 1, "XWaylandShell"); - PROTO::screencopy = std::make_unique(&zwlr_screencopy_manager_v1_interface, 3, "Screencopy"); - PROTO::toplevelExport = std::make_unique(&hyprland_toplevel_export_manager_v1_interface, 2, "ToplevelExport"); - PROTO::globalShortcuts = std::make_unique(&hyprland_global_shortcuts_manager_v1_interface, 1, "GlobalShortcuts"); - PROTO::xdgDialog = std::make_unique(&xdg_dialog_v1_interface, 1, "XDGDialog"); - PROTO::singlePixel = std::make_unique(&wp_single_pixel_buffer_manager_v1_interface, 1, "SinglePixel"); - PROTO::securityContext = std::make_unique(&wp_security_context_manager_v1_interface, 1, "SecurityContext"); - PROTO::ctm = std::make_unique(&hyprland_ctm_control_manager_v1_interface, 1, "CTMControl"); - PROTO::hyprlandSurface = std::make_unique(&hyprland_surface_manager_v1_interface, 1, "HyprlandSurface"); + PROTO::viewport = makeUnique(&wp_viewporter_interface, 1, "Viewporter"); + PROTO::tearing = makeUnique(&wp_tearing_control_manager_v1_interface, 1, "TearingControl"); + PROTO::fractional = makeUnique(&wp_fractional_scale_manager_v1_interface, 1, "FractionalScale"); + PROTO::xdgOutput = makeUnique(&zxdg_output_manager_v1_interface, 3, "XDGOutput"); + PROTO::cursorShape = makeUnique(&wp_cursor_shape_manager_v1_interface, 1, "CursorShape"); + PROTO::idleInhibit = makeUnique(&zwp_idle_inhibit_manager_v1_interface, 1, "IdleInhibit"); + PROTO::relativePointer = makeUnique(&zwp_relative_pointer_manager_v1_interface, 1, "RelativePointer"); + PROTO::xdgDecoration = makeUnique(&zxdg_decoration_manager_v1_interface, 1, "XDGDecoration"); + PROTO::alphaModifier = makeUnique(&wp_alpha_modifier_v1_interface, 1, "AlphaModifier"); + PROTO::gamma = makeUnique(&zwlr_gamma_control_manager_v1_interface, 1, "GammaControl"); + PROTO::foreignToplevel = makeUnique(&ext_foreign_toplevel_list_v1_interface, 1, "ForeignToplevel"); + PROTO::pointerGestures = makeUnique(&zwp_pointer_gestures_v1_interface, 3, "PointerGestures"); + PROTO::foreignToplevelWlr = makeUnique(&zwlr_foreign_toplevel_manager_v1_interface, 3, "ForeignToplevelWlr"); + PROTO::shortcutsInhibit = makeUnique(&zwp_keyboard_shortcuts_inhibit_manager_v1_interface, 1, "ShortcutsInhibit"); + PROTO::textInputV1 = makeUnique(&zwp_text_input_manager_v1_interface, 1, "TextInputV1"); + PROTO::textInputV3 = makeUnique(&zwp_text_input_manager_v3_interface, 1, "TextInputV3"); + PROTO::constraints = makeUnique(&zwp_pointer_constraints_v1_interface, 1, "PointerConstraints"); + PROTO::outputPower = makeUnique(&zwlr_output_power_manager_v1_interface, 1, "OutputPower"); + PROTO::activation = makeUnique(&xdg_activation_v1_interface, 1, "XDGActivation"); + PROTO::idle = makeUnique(&ext_idle_notifier_v1_interface, 1, "IdleNotify"); + PROTO::lockNotify = makeUnique(&hyprland_lock_notifier_v1_interface, 1, "IdleNotify"); + PROTO::sessionLock = makeUnique(&ext_session_lock_manager_v1_interface, 1, "SessionLock"); + PROTO::ime = makeUnique(&zwp_input_method_manager_v2_interface, 1, "IMEv2"); + PROTO::virtualKeyboard = makeUnique(&zwp_virtual_keyboard_manager_v1_interface, 1, "VirtualKeyboard"); + PROTO::virtualPointer = makeUnique(&zwlr_virtual_pointer_manager_v1_interface, 2, "VirtualPointer"); + PROTO::outputManagement = makeUnique(&zwlr_output_manager_v1_interface, 4, "OutputManagement"); + PROTO::serverDecorationKDE = makeUnique(&org_kde_kwin_server_decoration_manager_interface, 1, "ServerDecorationKDE"); + PROTO::focusGrab = makeUnique(&hyprland_focus_grab_manager_v1_interface, 1, "FocusGrab"); + PROTO::tablet = makeUnique(&zwp_tablet_manager_v2_interface, 1, "TabletV2"); + PROTO::layerShell = makeUnique(&zwlr_layer_shell_v1_interface, 5, "LayerShell"); + PROTO::presentation = makeUnique(&wp_presentation_interface, 1, "Presentation"); + PROTO::xdgShell = makeUnique(&xdg_wm_base_interface, 6, "XDGShell"); + PROTO::dataWlr = makeUnique(&zwlr_data_control_manager_v1_interface, 2, "DataDeviceWlr"); + PROTO::primarySelection = makeUnique(&zwp_primary_selection_device_manager_v1_interface, 1, "PrimarySelection"); + PROTO::xwaylandShell = makeUnique(&xwayland_shell_v1_interface, 1, "XWaylandShell"); + PROTO::screencopy = makeUnique(&zwlr_screencopy_manager_v1_interface, 3, "Screencopy"); + PROTO::toplevelExport = makeUnique(&hyprland_toplevel_export_manager_v1_interface, 2, "ToplevelExport"); + PROTO::globalShortcuts = makeUnique(&hyprland_global_shortcuts_manager_v1_interface, 1, "GlobalShortcuts"); + PROTO::xdgDialog = makeUnique(&xdg_dialog_v1_interface, 1, "XDGDialog"); + PROTO::singlePixel = makeUnique(&wp_single_pixel_buffer_manager_v1_interface, 1, "SinglePixel"); + PROTO::securityContext = makeUnique(&wp_security_context_manager_v1_interface, 1, "SecurityContext"); + PROTO::ctm = makeUnique(&hyprland_ctm_control_manager_v1_interface, 1, "CTMControl"); + PROTO::hyprlandSurface = makeUnique(&hyprland_surface_manager_v1_interface, 1, "HyprlandSurface"); if (*PENABLEXXCM) { - PROTO::colorManagement = std::make_unique(&xx_color_manager_v4_interface, 1, "ColorManagement"); - PROTO::frogColorManagement = std::make_unique(&frog_color_management_factory_v1_interface, 1, "FrogColorManagement"); + PROTO::colorManagement = makeUnique(&xx_color_manager_v4_interface, 1, "ColorManagement"); + PROTO::frogColorManagement = makeUnique(&frog_color_management_factory_v1_interface, 1, "FrogColorManagement"); } for (auto const& b : g_pCompositor->m_pAqBackend->getImplementations()) { if (b->type() != Aquamarine::AQ_BACKEND_DRM) continue; - PROTO::lease = std::make_unique(&wp_drm_lease_device_v1_interface, 1, "DRMLease"); + PROTO::lease = makeUnique(&wp_drm_lease_device_v1_interface, 1, "DRMLease"); if (*PENABLEEXPLICIT) - PROTO::sync = std::make_unique(&wp_linux_drm_syncobj_manager_v1_interface, 1, "DRMSyncobj"); + PROTO::sync = makeUnique(&wp_linux_drm_syncobj_manager_v1_interface, 1, "DRMSyncobj"); break; } if (g_pHyprOpenGL->getDRMFormats().size() > 0) { - PROTO::mesaDRM = std::make_unique(&wl_drm_interface, 2, "MesaDRM"); - PROTO::linuxDma = std::make_unique(&zwp_linux_dmabuf_v1_interface, 5, "LinuxDMABUF"); + PROTO::mesaDRM = makeUnique(&wl_drm_interface, 2, "MesaDRM"); + PROTO::linuxDma = makeUnique(&zwp_linux_dmabuf_v1_interface, 5, "LinuxDMABUF"); } else Debug::log(WARN, "ProtocolManager: Not binding linux-dmabuf and MesaDRM: DMABUF not available"); } diff --git a/src/managers/ProtocolManager.hpp b/src/managers/ProtocolManager.hpp index 6ceff9ad..1ec8db4a 100644 --- a/src/managers/ProtocolManager.hpp +++ b/src/managers/ProtocolManager.hpp @@ -18,4 +18,4 @@ class CProtocolManager { void onMonitorModeChange(PHLMONITOR pMonitor); }; -inline std::unique_ptr g_pProtocolManager; +inline UP g_pProtocolManager; diff --git a/src/managers/SessionLockManager.cpp b/src/managers/SessionLockManager.cpp index 3d77f05a..ea0d8dfc 100644 --- a/src/managers/SessionLockManager.cpp +++ b/src/managers/SessionLockManager.cpp @@ -57,7 +57,7 @@ void CSessionLockManager::onNewSessionLock(SP pLock) { Debug::log(LOG, "Session got locked by {:x}", (uintptr_t)pLock.get()); - m_pSessionLock = std::make_unique(); + m_pSessionLock = makeUnique(); m_pSessionLock->lock = pLock; m_pSessionLock->mLockTimer.reset(); @@ -66,7 +66,7 @@ void CSessionLockManager::onNewSessionLock(SP pLock) { const auto PMONITOR = SURFACE->monitor(); - const auto NEWSURFACE = m_pSessionLock->vSessionLockSurfaces.emplace_back(std::make_unique(SURFACE)).get(); + const auto NEWSURFACE = m_pSessionLock->vSessionLockSurfaces.emplace_back(makeUnique(SURFACE)).get(); NEWSURFACE->iMonitorID = PMONITOR->ID; PROTO::fractional->sendScale(SURFACE->surface(), PMONITOR->scale); }); diff --git a/src/managers/SessionLockManager.hpp b/src/managers/SessionLockManager.hpp index 59090605..aaf78819 100644 --- a/src/managers/SessionLockManager.hpp +++ b/src/managers/SessionLockManager.hpp @@ -28,11 +28,11 @@ struct SSessionLockSurface { }; struct SSessionLock { - WP lock; - CTimer mLockTimer; + WP lock; + CTimer mLockTimer; - std::vector> vSessionLockSurfaces; - std::unordered_map mMonitorsWithoutMappedSurfaceTimers; + std::vector> vSessionLockSurfaces; + std::unordered_map mMonitorsWithoutMappedSurfaceTimers; struct { CHyprSignalListener newSurface; @@ -74,4 +74,4 @@ class CSessionLockManager { void onNewSessionLock(SP pWlrLock); }; -inline std::unique_ptr g_pSessionLockManager; +inline UP g_pSessionLockManager; diff --git a/src/managers/TokenManager.hpp b/src/managers/TokenManager.hpp index 92638e9b..aaf068bc 100644 --- a/src/managers/TokenManager.hpp +++ b/src/managers/TokenManager.hpp @@ -35,4 +35,4 @@ class CTokenManager { std::unordered_map> m_mTokens; }; -inline std::unique_ptr g_pTokenManager; \ No newline at end of file +inline UP g_pTokenManager; \ No newline at end of file diff --git a/src/managers/VersionKeeperManager.hpp b/src/managers/VersionKeeperManager.hpp index eb404d88..250a36b8 100644 --- a/src/managers/VersionKeeperManager.hpp +++ b/src/managers/VersionKeeperManager.hpp @@ -1,6 +1,6 @@ #pragma once -#include +#include "../helpers/memory/Memory.hpp" class CVersionKeeperManager { public: @@ -15,4 +15,4 @@ class CVersionKeeperManager { bool m_bFired = false; }; -inline std::unique_ptr g_pVersionKeeperMgr; \ No newline at end of file +inline UP g_pVersionKeeperMgr; \ No newline at end of file diff --git a/src/managers/XCursorManager.cpp b/src/managers/XCursorManager.cpp index 42c5e427..3473df44 100644 --- a/src/managers/XCursorManager.cpp +++ b/src/managers/XCursorManager.cpp @@ -9,6 +9,7 @@ #include "../managers/CursorManager.hpp" #include "debug/Log.hpp" #include "XCursorManager.hpp" +#include // clang-format off static std::vector HYPR_XCURSOR_PIXELS = { diff --git a/src/managers/XWaylandManager.hpp b/src/managers/XWaylandManager.hpp index 18627a78..8ce239f6 100644 --- a/src/managers/XWaylandManager.hpp +++ b/src/managers/XWaylandManager.hpp @@ -25,4 +25,4 @@ class CHyprXWaylandManager { Vector2D waylandToXWaylandCoords(const Vector2D&); }; -inline std::unique_ptr g_pXWaylandManager; \ No newline at end of file +inline UP g_pXWaylandManager; \ No newline at end of file diff --git a/src/managers/eventLoop/EventLoopManager.hpp b/src/managers/eventLoop/EventLoopManager.hpp index e1c243d3..95cc6109 100644 --- a/src/managers/eventLoop/EventLoopManager.hpp +++ b/src/managers/eventLoop/EventLoopManager.hpp @@ -69,4 +69,4 @@ class CEventLoopManager { friend class CSyncTimeline; }; -inline std::unique_ptr g_pEventLoopManager; +inline UP g_pEventLoopManager; diff --git a/src/managers/input/IdleInhibitor.cpp b/src/managers/input/IdleInhibitor.cpp index 74760c0a..67837c17 100644 --- a/src/managers/input/IdleInhibitor.cpp +++ b/src/managers/input/IdleInhibitor.cpp @@ -5,7 +5,7 @@ #include "../../protocols/core/Compositor.hpp" void CInputManager::newIdleInhibitor(std::any inhibitor) { - const auto PINHIBIT = m_vIdleInhibitors.emplace_back(std::make_unique()).get(); + const auto PINHIBIT = m_vIdleInhibitors.emplace_back(makeUnique()).get(); PINHIBIT->inhibitor = std::any_cast>(inhibitor); Debug::log(LOG, "New idle inhibitor registered for surface {:x}", (uintptr_t)PINHIBIT->inhibitor->surface.get()); diff --git a/src/managers/input/InputManager.hpp b/src/managers/input/InputManager.hpp index 36c8144d..c0f1939e 100644 --- a/src/managers/input/InputManager.hpp +++ b/src/managers/input/InputManager.hpp @@ -268,7 +268,7 @@ class CInputManager { bool nonDesktop = false; CHyprSignalListener surfaceDestroyListener; }; - std::vector> m_vIdleInhibitors; + std::vector> m_vIdleInhibitors; // swipe void beginWorkspaceSwipe(); @@ -304,4 +304,4 @@ class CInputManager { friend class CWLSurface; }; -inline std::unique_ptr g_pInputManager; +inline UP g_pInputManager; diff --git a/src/managers/input/InputMethodRelay.cpp b/src/managers/input/InputMethodRelay.cpp index 58cff043..5f6c4354 100644 --- a/src/managers/input/InputMethodRelay.cpp +++ b/src/managers/input/InputMethodRelay.cpp @@ -50,7 +50,7 @@ void CInputMethodRelay::onNewIME(SP pIME) { }); listeners.newPopup = pIME->events.newPopup.registerListener([this](std::any d) { - m_vIMEPopups.emplace_back(std::make_unique(std::any_cast>(d))); + m_vIMEPopups.emplace_back(makeUnique(std::any_cast>(d))); Debug::log(LOG, "New input popup"); }); @@ -86,11 +86,11 @@ CTextInput* CInputMethodRelay::getFocusedTextInput() { } void CInputMethodRelay::onNewTextInput(WP tiv3) { - m_vTextInputs.emplace_back(std::make_unique(tiv3)); + m_vTextInputs.emplace_back(makeUnique(tiv3)); } void CInputMethodRelay::onNewTextInput(WP pTIV1) { - m_vTextInputs.emplace_back(std::make_unique(pTIV1)); + m_vTextInputs.emplace_back(makeUnique(pTIV1)); } void CInputMethodRelay::removeTextInput(CTextInput* pInput) { diff --git a/src/managers/input/InputMethodRelay.hpp b/src/managers/input/InputMethodRelay.hpp index 998e1fc6..602a939a 100644 --- a/src/managers/input/InputMethodRelay.hpp +++ b/src/managers/input/InputMethodRelay.hpp @@ -40,10 +40,10 @@ class CInputMethodRelay { WP m_pIME; private: - std::vector> m_vTextInputs; - std::vector> m_vIMEPopups; + std::vector> m_vTextInputs; + std::vector> m_vIMEPopups; - WP m_pLastKbFocus; + WP m_pLastKbFocus; struct { CHyprSignalListener newTIV3; diff --git a/src/managers/input/TextInput.hpp b/src/managers/input/TextInput.hpp index c0b590ac..37b471af 100644 --- a/src/managers/input/TextInput.hpp +++ b/src/managers/input/TextInput.hpp @@ -3,7 +3,6 @@ #include "../../helpers/math/Math.hpp" #include "../../helpers/signal/Signal.hpp" #include "../../helpers/memory/Memory.hpp" -#include struct wl_client; diff --git a/src/pch/pch.hpp b/src/pch/pch.hpp index 8dc98fac..f9d5b130 100644 --- a/src/pch/pch.hpp +++ b/src/pch/pch.hpp @@ -11,7 +11,7 @@ #include #include #include -#include + #include #include #include diff --git a/src/plugins/HookSystem.cpp b/src/plugins/HookSystem.cpp index c19f6f46..9fa61561 100644 --- a/src/plugins/HookSystem.cpp +++ b/src/plugins/HookSystem.cpp @@ -253,7 +253,7 @@ bool CFunctionHook::unhook() { } CFunctionHook* CHookSystem::initHook(HANDLE owner, void* source, void* destination) { - return m_vHooks.emplace_back(std::make_unique(owner, source, destination)).get(); + return m_vHooks.emplace_back(makeUnique(owner, source, destination)).get(); } bool CHookSystem::removeHook(CFunctionHook* hook) { diff --git a/src/plugins/HookSystem.hpp b/src/plugins/HookSystem.hpp index f0a5a11d..93ca4ff5 100644 --- a/src/plugins/HookSystem.hpp +++ b/src/plugins/HookSystem.hpp @@ -2,7 +2,7 @@ #include #include -#include +#include "../helpers/memory/Memory.hpp" #define HANDLE void* #define HOOK_TRAMPOLINE_MAX_SIZE 64 @@ -60,9 +60,9 @@ class CHookSystem { void removeAllHooksFrom(HANDLE handle); private: - std::vector> m_vHooks; + std::vector> m_vHooks; - uint64_t getAddressForTrampo(); + uint64_t getAddressForTrampo(); struct SAllocatedPage { uint64_t addr = 0; @@ -75,4 +75,4 @@ class CHookSystem { friend class CFunctionHook; }; -inline std::unique_ptr g_pFunctionHookSystem; \ No newline at end of file +inline UP g_pFunctionHookSystem; \ No newline at end of file diff --git a/src/plugins/PluginAPI.cpp b/src/plugins/PluginAPI.cpp index fbb1ec1b..92f043fd 100644 --- a/src/plugins/PluginAPI.cpp +++ b/src/plugins/PluginAPI.cpp @@ -106,7 +106,7 @@ APICALL bool HyprlandAPI::removeFunctionHook(HANDLE handle, CFunctionHook* hook) return g_pFunctionHookSystem->removeHook(hook); } -APICALL bool HyprlandAPI::addWindowDecoration(HANDLE handle, PHLWINDOW pWindow, std::unique_ptr pDecoration) { +APICALL bool HyprlandAPI::addWindowDecoration(HANDLE handle, PHLWINDOW pWindow, UP pDecoration) { auto* const PLUGIN = g_pPluginSystem->getPluginByHandle(handle); if (!PLUGIN) diff --git a/src/plugins/PluginAPI.hpp b/src/plugins/PluginAPI.hpp index 96c32bf1..c8c9e563 100644 --- a/src/plugins/PluginAPI.hpp +++ b/src/plugins/PluginAPI.hpp @@ -223,7 +223,7 @@ namespace HyprlandAPI { returns: true on success. False otherwise. */ - APICALL bool addWindowDecoration(HANDLE handle, PHLWINDOW pWindow, std::unique_ptr pDecoration); + APICALL bool addWindowDecoration(HANDLE handle, PHLWINDOW pWindow, UP pDecoration); /* Removes a window decoration diff --git a/src/plugins/PluginSystem.cpp b/src/plugins/PluginSystem.cpp index e849bf11..87b9e8ef 100644 --- a/src/plugins/PluginSystem.cpp +++ b/src/plugins/PluginSystem.cpp @@ -8,7 +8,7 @@ #include "../managers/eventLoop/EventLoopManager.hpp" CPluginSystem::CPluginSystem() { - g_pFunctionHookSystem = std::make_unique(); + g_pFunctionHookSystem = makeUnique(); } CPlugin* CPluginSystem::loadPlugin(const std::string& path) { @@ -21,7 +21,7 @@ CPlugin* CPluginSystem::loadPlugin(const std::string& path) { return nullptr; } - auto* const PLUGIN = m_vLoadedPlugins.emplace_back(std::make_unique()).get(); + auto* const PLUGIN = m_vLoadedPlugins.emplace_back(makeUnique()).get(); PLUGIN->path = path; diff --git a/src/plugins/PluginSystem.hpp b/src/plugins/PluginSystem.hpp index 336c484d..95841bef 100644 --- a/src/plugins/PluginSystem.hpp +++ b/src/plugins/PluginSystem.hpp @@ -44,9 +44,9 @@ class CPluginSystem { std::string m_szLastError = ""; private: - std::vector> m_vLoadedPlugins; + std::vector> m_vLoadedPlugins; - jmp_buf m_jbPluginFaultJumpBuf; + jmp_buf m_jbPluginFaultJumpBuf; }; -inline std::unique_ptr g_pPluginSystem; +inline UP g_pPluginSystem; diff --git a/src/protocols/AlphaModifier.cpp b/src/protocols/AlphaModifier.cpp index dc32bb8c..e8766405 100644 --- a/src/protocols/AlphaModifier.cpp +++ b/src/protocols/AlphaModifier.cpp @@ -64,7 +64,7 @@ CAlphaModifierProtocol::CAlphaModifierProtocol(const wl_interface* iface, const } void CAlphaModifierProtocol::bindManager(wl_client* client, void* data, uint32_t ver, uint32_t id) { - const auto RESOURCE = m_vManagers.emplace_back(std::make_unique(client, ver, id)).get(); + const auto RESOURCE = m_vManagers.emplace_back(makeUnique(client, ver, id)).get(); RESOURCE->setOnDestroy([this](CWpAlphaModifierV1* manager) { destroyManager(manager); }); RESOURCE->setDestroy([this](CWpAlphaModifierV1* manager) { destroyManager(manager); }); @@ -93,9 +93,8 @@ void CAlphaModifierProtocol::getSurface(CWpAlphaModifierV1* manager, uint32_t id alphaModifier = iter->second.get(); } } else { - alphaModifier = - m_mAlphaModifiers.emplace(surface, std::make_unique(makeShared(manager->client(), manager->version(), id), surface)) - .first->second.get(); + alphaModifier = m_mAlphaModifiers.emplace(surface, makeUnique(makeShared(manager->client(), manager->version(), id), surface)) + .first->second.get(); } if UNLIKELY (!alphaModifier->good()) { diff --git a/src/protocols/AlphaModifier.hpp b/src/protocols/AlphaModifier.hpp index 43f78bef..9a7873ae 100644 --- a/src/protocols/AlphaModifier.hpp +++ b/src/protocols/AlphaModifier.hpp @@ -1,6 +1,5 @@ #pragma once -#include #include #include #include "WaylandProtocol.hpp" diff --git a/src/protocols/CTMControl.cpp b/src/protocols/CTMControl.cpp index 91f4501f..5560271f 100644 --- a/src/protocols/CTMControl.cpp +++ b/src/protocols/CTMControl.cpp @@ -106,7 +106,7 @@ void CHyprlandCTMControlProtocol::setCTM(PHLMONITOR monitor, const Mat3x3& ctm) std::erase_if(m_mCTMDatas, [](const auto& el) { return !el.first; }); if (!m_mCTMDatas.contains(monitor)) - m_mCTMDatas[monitor] = std::make_unique(); + m_mCTMDatas[monitor] = makeUnique(); auto& data = m_mCTMDatas.at(monitor); diff --git a/src/protocols/CTMControl.hpp b/src/protocols/CTMControl.hpp index 2639d176..2c168acd 100644 --- a/src/protocols/CTMControl.hpp +++ b/src/protocols/CTMControl.hpp @@ -1,6 +1,5 @@ #pragma once -#include #include #include #include "WaylandProtocol.hpp" @@ -45,7 +44,7 @@ class CHyprlandCTMControlProtocol : public IWaylandProtocol { Mat3x3 ctmFrom = Mat3x3::identity(), ctmTo = Mat3x3::identity(); PHLANIMVAR progress; }; - std::map> m_mCTMDatas; + std::map> m_mCTMDatas; friend class CHyprlandCTMControlResource; }; diff --git a/src/protocols/ColorManagement.hpp b/src/protocols/ColorManagement.hpp index e387b3b7..39e3f486 100644 --- a/src/protocols/ColorManagement.hpp +++ b/src/protocols/ColorManagement.hpp @@ -1,7 +1,6 @@ #pragma once #include -#include #include #include #include "WaylandProtocol.hpp" diff --git a/src/protocols/CursorShape.cpp b/src/protocols/CursorShape.cpp index 429d604f..e7eb6159 100644 --- a/src/protocols/CursorShape.cpp +++ b/src/protocols/CursorShape.cpp @@ -15,7 +15,7 @@ void CCursorShapeProtocol::onDeviceResourceDestroy(wl_resource* res) { } void CCursorShapeProtocol::bindManager(wl_client* client, void* data, uint32_t ver, uint32_t id) { - const auto RESOURCE = m_vManagers.emplace_back(std::make_unique(client, ver, id)).get(); + const auto RESOURCE = m_vManagers.emplace_back(makeUnique(client, ver, id)).get(); RESOURCE->setOnDestroy([this](CWpCursorShapeManagerV1* p) { this->onManagerResourceDestroy(p->resource()); }); RESOURCE->setDestroy([this](CWpCursorShapeManagerV1* pMgr) { this->onManagerResourceDestroy(pMgr->resource()); }); diff --git a/src/protocols/CursorShape.hpp b/src/protocols/CursorShape.hpp index 9fcca28d..37b7e6c8 100644 --- a/src/protocols/CursorShape.hpp +++ b/src/protocols/CursorShape.hpp @@ -1,6 +1,5 @@ #pragma once -#include #include #include "WaylandProtocol.hpp" #include "../helpers/signal/Signal.hpp" diff --git a/src/protocols/DRMLease.hpp b/src/protocols/DRMLease.hpp index 37de40e3..ec1e73f2 100644 --- a/src/protocols/DRMLease.hpp +++ b/src/protocols/DRMLease.hpp @@ -1,6 +1,5 @@ #pragma once -#include #include #include #include "WaylandProtocol.hpp" diff --git a/src/protocols/DRMSyncobj.hpp b/src/protocols/DRMSyncobj.hpp index bc89a3d3..42ecdb3e 100644 --- a/src/protocols/DRMSyncobj.hpp +++ b/src/protocols/DRMSyncobj.hpp @@ -1,6 +1,5 @@ #pragma once -#include #include #include "WaylandProtocol.hpp" #include "linux-drm-syncobj-v1.hpp" diff --git a/src/protocols/DataDeviceWlr.hpp b/src/protocols/DataDeviceWlr.hpp index 193e918c..5eef163c 100644 --- a/src/protocols/DataDeviceWlr.hpp +++ b/src/protocols/DataDeviceWlr.hpp @@ -1,6 +1,5 @@ #pragma once -#include #include #include #include "WaylandProtocol.hpp" diff --git a/src/protocols/FocusGrab.cpp b/src/protocols/FocusGrab.cpp index ee30343f..ab9d22ef 100644 --- a/src/protocols/FocusGrab.cpp +++ b/src/protocols/FocusGrab.cpp @@ -5,7 +5,6 @@ #include "../managers/SeatManager.hpp" #include "core/Compositor.hpp" #include -#include #include CFocusGrabSurfaceState::CFocusGrabSurfaceState(CFocusGrab* grab, SP surface) { @@ -77,7 +76,7 @@ void CFocusGrab::finish(bool sendCleared) { void CFocusGrab::addSurface(SP surface) { auto iter = std::find_if(m_mSurfaces.begin(), m_mSurfaces.end(), [surface](const auto& e) { return e.first == surface; }); if (iter == m_mSurfaces.end()) - m_mSurfaces.emplace(surface, std::make_unique(this, surface)); + m_mSurfaces.emplace(surface, makeUnique(this, surface)); } void CFocusGrab::removeSurface(SP surface) { @@ -151,7 +150,7 @@ CFocusGrabProtocol::CFocusGrabProtocol(const wl_interface* iface, const int& ver } void CFocusGrabProtocol::bindManager(wl_client* client, void* data, uint32_t ver, uint32_t id) { - const auto RESOURCE = m_vManagers.emplace_back(std::make_unique(client, ver, id)).get(); + const auto RESOURCE = m_vManagers.emplace_back(makeUnique(client, ver, id)).get(); RESOURCE->setOnDestroy([this](CHyprlandFocusGrabManagerV1* p) { onManagerResourceDestroy(p->resource()); }); RESOURCE->setDestroy([this](CHyprlandFocusGrabManagerV1* p) { onManagerResourceDestroy(p->resource()); }); @@ -167,7 +166,7 @@ void CFocusGrabProtocol::destroyGrab(CFocusGrab* grab) { } void CFocusGrabProtocol::onCreateGrab(CHyprlandFocusGrabManagerV1* pMgr, uint32_t id) { - m_vGrabs.push_back(std::make_unique(makeShared(pMgr->client(), pMgr->version(), id))); + m_vGrabs.push_back(makeUnique(makeShared(pMgr->client(), pMgr->version(), id))); const auto RESOURCE = m_vGrabs.back().get(); if UNLIKELY (!RESOURCE->good()) { diff --git a/src/protocols/ForeignToplevel.cpp b/src/protocols/ForeignToplevel.cpp index 6880164f..4e5fda48 100644 --- a/src/protocols/ForeignToplevel.cpp +++ b/src/protocols/ForeignToplevel.cpp @@ -147,7 +147,7 @@ CForeignToplevelProtocol::CForeignToplevelProtocol(const wl_interface* iface, co } void CForeignToplevelProtocol::bindManager(wl_client* client, void* data, uint32_t ver, uint32_t id) { - const auto RESOURCE = m_vManagers.emplace_back(std::make_unique(makeShared(client, ver, id))).get(); + const auto RESOURCE = m_vManagers.emplace_back(makeUnique(makeShared(client, ver, id))).get(); if UNLIKELY (!RESOURCE->good()) { LOGM(ERR, "Couldn't create a foreign list"); diff --git a/src/protocols/ForeignToplevel.hpp b/src/protocols/ForeignToplevel.hpp index 076bfd7c..712b32e0 100644 --- a/src/protocols/ForeignToplevel.hpp +++ b/src/protocols/ForeignToplevel.hpp @@ -1,6 +1,5 @@ #pragma once -#include #include #include #include "WaylandProtocol.hpp" diff --git a/src/protocols/ForeignToplevelWlr.cpp b/src/protocols/ForeignToplevelWlr.cpp index e18f6e23..e50c85d9 100644 --- a/src/protocols/ForeignToplevelWlr.cpp +++ b/src/protocols/ForeignToplevelWlr.cpp @@ -376,7 +376,7 @@ CForeignToplevelWlrProtocol::CForeignToplevelWlrProtocol(const wl_interface* ifa } void CForeignToplevelWlrProtocol::bindManager(wl_client* client, void* data, uint32_t ver, uint32_t id) { - const auto RESOURCE = m_vManagers.emplace_back(std::make_unique(makeShared(client, ver, id))).get(); + const auto RESOURCE = m_vManagers.emplace_back(makeUnique(makeShared(client, ver, id))).get(); if UNLIKELY (!RESOURCE->good()) { LOGM(ERR, "Couldn't create a foreign list"); diff --git a/src/protocols/ForeignToplevelWlr.hpp b/src/protocols/ForeignToplevelWlr.hpp index 880b7a14..d0479d98 100644 --- a/src/protocols/ForeignToplevelWlr.hpp +++ b/src/protocols/ForeignToplevelWlr.hpp @@ -1,6 +1,5 @@ #pragma once -#include #include #include "WaylandProtocol.hpp" #include "wlr-foreign-toplevel-management-unstable-v1.hpp" diff --git a/src/protocols/FractionalScale.cpp b/src/protocols/FractionalScale.cpp index 3b24becd..494de9c5 100644 --- a/src/protocols/FractionalScale.cpp +++ b/src/protocols/FractionalScale.cpp @@ -7,7 +7,7 @@ CFractionalScaleProtocol::CFractionalScaleProtocol(const wl_interface* iface, co } void CFractionalScaleProtocol::bindManager(wl_client* client, void* data, uint32_t ver, uint32_t id) { - const auto RESOURCE = m_vManagers.emplace_back(std::make_unique(client, ver, id)).get(); + const auto RESOURCE = m_vManagers.emplace_back(makeUnique(client, ver, id)).get(); RESOURCE->setOnDestroy([this](CWpFractionalScaleManagerV1* p) { this->onManagerResourceDestroy(p->resource()); }); RESOURCE->setDestroy([this](CWpFractionalScaleManagerV1* pMgr) { this->onManagerResourceDestroy(pMgr->resource()); }); @@ -33,7 +33,7 @@ void CFractionalScaleProtocol::onGetFractionalScale(CWpFractionalScaleManagerV1* } const auto PADDON = - m_mAddons.emplace(surface, std::make_unique(makeShared(pMgr->client(), pMgr->version(), id), surface)).first->second.get(); + m_mAddons.emplace(surface, makeUnique(makeShared(pMgr->client(), pMgr->version(), id), surface)).first->second.get(); if UNLIKELY (!PADDON->good()) { m_mAddons.erase(surface); diff --git a/src/protocols/FractionalScale.hpp b/src/protocols/FractionalScale.hpp index 98cd7eaa..ba896c01 100644 --- a/src/protocols/FractionalScale.hpp +++ b/src/protocols/FractionalScale.hpp @@ -1,6 +1,5 @@ #pragma once -#include #include #include "WaylandProtocol.hpp" #include "fractional-scale-v1.hpp" diff --git a/src/protocols/FrogColorManagement.hpp b/src/protocols/FrogColorManagement.hpp index 6c00e38d..db467b1d 100644 --- a/src/protocols/FrogColorManagement.hpp +++ b/src/protocols/FrogColorManagement.hpp @@ -1,6 +1,5 @@ #pragma once -#include #include #include "WaylandProtocol.hpp" #include "protocols/core/Compositor.hpp" diff --git a/src/protocols/GammaControl.cpp b/src/protocols/GammaControl.cpp index 299d7717..43ba9d41 100644 --- a/src/protocols/GammaControl.cpp +++ b/src/protocols/GammaControl.cpp @@ -160,7 +160,7 @@ CGammaControlProtocol::CGammaControlProtocol(const wl_interface* iface, const in } void CGammaControlProtocol::bindManager(wl_client* client, void* data, uint32_t ver, uint32_t id) { - const auto RESOURCE = m_vManagers.emplace_back(std::make_unique(client, ver, id)).get(); + const auto RESOURCE = m_vManagers.emplace_back(makeUnique(client, ver, id)).get(); RESOURCE->setOnDestroy([this](CZwlrGammaControlManagerV1* p) { this->onManagerResourceDestroy(p->resource()); }); RESOURCE->setDestroy([this](CZwlrGammaControlManagerV1* pMgr) { this->onManagerResourceDestroy(pMgr->resource()); }); @@ -177,7 +177,7 @@ void CGammaControlProtocol::destroyGammaControl(CGammaControl* gamma) { void CGammaControlProtocol::onGetGammaControl(CZwlrGammaControlManagerV1* pMgr, uint32_t id, wl_resource* output) { const auto CLIENT = pMgr->client(); - const auto RESOURCE = m_vGammaControllers.emplace_back(std::make_unique(makeShared(CLIENT, pMgr->version(), id), output)).get(); + const auto RESOURCE = m_vGammaControllers.emplace_back(makeUnique(makeShared(CLIENT, pMgr->version(), id), output)).get(); if UNLIKELY (!RESOURCE->good()) { pMgr->noMemory(); diff --git a/src/protocols/GammaControl.hpp b/src/protocols/GammaControl.hpp index 5cfcd60a..9e21ef08 100644 --- a/src/protocols/GammaControl.hpp +++ b/src/protocols/GammaControl.hpp @@ -1,6 +1,5 @@ #pragma once -#include #include #include #include "WaylandProtocol.hpp" diff --git a/src/protocols/HyprlandSurface.cpp b/src/protocols/HyprlandSurface.cpp index bcf4905c..ca133b78 100644 --- a/src/protocols/HyprlandSurface.cpp +++ b/src/protocols/HyprlandSurface.cpp @@ -70,7 +70,7 @@ CHyprlandSurfaceProtocol::CHyprlandSurfaceProtocol(const wl_interface* iface, co } void CHyprlandSurfaceProtocol::bindManager(wl_client* client, void* data, uint32_t ver, uint32_t id) { - auto manager = m_vManagers.emplace_back(std::make_unique(client, ver, id)).get(); + auto manager = m_vManagers.emplace_back(makeUnique(client, ver, id)).get(); manager->setOnDestroy([this](CHyprlandSurfaceManagerV1* manager) { destroyManager(manager); }); manager->setDestroy([this](CHyprlandSurfaceManagerV1* manager) { destroyManager(manager); }); @@ -100,8 +100,8 @@ void CHyprlandSurfaceProtocol::getSurface(CHyprlandSurfaceManagerV1* manager, ui hyprlandSurface = iter->second.get(); } } else { - hyprlandSurface = m_mSurfaces.emplace(surface, std::make_unique(makeShared(manager->client(), manager->version(), id), surface)) - .first->second.get(); + hyprlandSurface = + m_mSurfaces.emplace(surface, makeUnique(makeShared(manager->client(), manager->version(), id), surface)).first->second.get(); } if UNLIKELY (!hyprlandSurface->good()) { diff --git a/src/protocols/HyprlandSurface.hpp b/src/protocols/HyprlandSurface.hpp index f67de115..a5812b89 100644 --- a/src/protocols/HyprlandSurface.hpp +++ b/src/protocols/HyprlandSurface.hpp @@ -1,6 +1,5 @@ #pragma once -#include #include #include #include "WaylandProtocol.hpp" diff --git a/src/protocols/IdleInhibit.cpp b/src/protocols/IdleInhibit.cpp index 89eb3108..a015cdd0 100644 --- a/src/protocols/IdleInhibit.cpp +++ b/src/protocols/IdleInhibit.cpp @@ -31,7 +31,7 @@ void CIdleInhibitProtocol::onManagerResourceDestroy(wl_resource* res) { } void CIdleInhibitProtocol::bindManager(wl_client* client, void* data, uint32_t ver, uint32_t id) { - const auto RESOURCE = m_vManagers.emplace_back(std::make_unique(client, ver, id)).get(); + const auto RESOURCE = m_vManagers.emplace_back(makeUnique(client, ver, id)).get(); RESOURCE->setOnDestroy([this](CZwpIdleInhibitManagerV1* p) { this->onManagerResourceDestroy(p->resource()); }); RESOURCE->setDestroy([this](CZwpIdleInhibitManagerV1* pMgr) { this->onManagerResourceDestroy(pMgr->resource()); }); diff --git a/src/protocols/IdleInhibit.hpp b/src/protocols/IdleInhibit.hpp index 3cbfd78d..2e024a7a 100644 --- a/src/protocols/IdleInhibit.hpp +++ b/src/protocols/IdleInhibit.hpp @@ -1,6 +1,5 @@ #pragma once -#include #include #include "WaylandProtocol.hpp" #include "idle-inhibit-unstable-v1.hpp" diff --git a/src/protocols/IdleNotify.cpp b/src/protocols/IdleNotify.cpp index 85a9f8e2..bc5aabb1 100644 --- a/src/protocols/IdleNotify.cpp +++ b/src/protocols/IdleNotify.cpp @@ -59,7 +59,7 @@ CIdleNotifyProtocol::CIdleNotifyProtocol(const wl_interface* iface, const int& v } void CIdleNotifyProtocol::bindManager(wl_client* client, void* data, uint32_t ver, uint32_t id) { - const auto RESOURCE = m_vManagers.emplace_back(std::make_unique(client, ver, id)).get(); + const auto RESOURCE = m_vManagers.emplace_back(makeUnique(client, ver, id)).get(); RESOURCE->setOnDestroy([this](CExtIdleNotifierV1* p) { this->onManagerResourceDestroy(p->resource()); }); RESOURCE->setDestroy([this](CExtIdleNotifierV1* pMgr) { this->onManagerResourceDestroy(pMgr->resource()); }); diff --git a/src/protocols/IdleNotify.hpp b/src/protocols/IdleNotify.hpp index d0b40775..e3dcdc98 100644 --- a/src/protocols/IdleNotify.hpp +++ b/src/protocols/IdleNotify.hpp @@ -1,6 +1,5 @@ #pragma once -#include #include #include #include "WaylandProtocol.hpp" diff --git a/src/protocols/InputMethodV2.cpp b/src/protocols/InputMethodV2.cpp index cf777f45..796cec06 100644 --- a/src/protocols/InputMethodV2.cpp +++ b/src/protocols/InputMethodV2.cpp @@ -334,7 +334,7 @@ CInputMethodV2Protocol::CInputMethodV2Protocol(const wl_interface* iface, const } void CInputMethodV2Protocol::bindManager(wl_client* client, void* data, uint32_t ver, uint32_t id) { - const auto RESOURCE = m_vManagers.emplace_back(std::make_unique(client, ver, id)).get(); + const auto RESOURCE = m_vManagers.emplace_back(makeUnique(client, ver, id)).get(); RESOURCE->setOnDestroy([this](CZwpInputMethodManagerV2* p) { this->onManagerResourceDestroy(p->resource()); }); RESOURCE->setDestroy([this](CZwpInputMethodManagerV2* pMgr) { this->onManagerResourceDestroy(pMgr->resource()); }); diff --git a/src/protocols/InputMethodV2.hpp b/src/protocols/InputMethodV2.hpp index 0b2c7a49..0c249c6c 100644 --- a/src/protocols/InputMethodV2.hpp +++ b/src/protocols/InputMethodV2.hpp @@ -1,6 +1,5 @@ #pragma once -#include #include #include #include "WaylandProtocol.hpp" diff --git a/src/protocols/LayerShell.cpp b/src/protocols/LayerShell.cpp index 82d00a30..1533a7c0 100644 --- a/src/protocols/LayerShell.cpp +++ b/src/protocols/LayerShell.cpp @@ -201,7 +201,7 @@ CLayerShellProtocol::CLayerShellProtocol(const wl_interface* iface, const int& v } void CLayerShellProtocol::bindManager(wl_client* client, void* data, uint32_t ver, uint32_t id) { - const auto RESOURCE = m_vManagers.emplace_back(std::make_unique(client, ver, id)).get(); + const auto RESOURCE = m_vManagers.emplace_back(makeUnique(client, ver, id)).get(); RESOURCE->setOnDestroy([this](CZwlrLayerShellV1* p) { this->onManagerResourceDestroy(p->resource()); }); RESOURCE->setDestroy([this](CZwlrLayerShellV1* pMgr) { this->onManagerResourceDestroy(pMgr->resource()); }); diff --git a/src/protocols/LayerShell.hpp b/src/protocols/LayerShell.hpp index 5e74c91b..b634c63c 100644 --- a/src/protocols/LayerShell.hpp +++ b/src/protocols/LayerShell.hpp @@ -1,6 +1,5 @@ #pragma once -#include #include #include #include diff --git a/src/protocols/LinuxDMABUF.cpp b/src/protocols/LinuxDMABUF.cpp index 85f7b1c6..82d31c84 100644 --- a/src/protocols/LinuxDMABUF.cpp +++ b/src/protocols/LinuxDMABUF.cpp @@ -469,7 +469,7 @@ CLinuxDMABufV1Protocol::CLinuxDMABufV1Protocol(const wl_interface* iface, const }); } - formatTable = std::make_unique(eglTranche, tches); + formatTable = makeUnique(eglTranche, tches); drmDevice* device = nullptr; if (drmGetDeviceFromDevId(mainDevice, 0, &device) != 0) { @@ -501,7 +501,7 @@ void CLinuxDMABufV1Protocol::resetFormatTable() { LOGM(LOG, "Resetting format table"); // this might be a big copy - auto newFormatTable = std::make_unique(formatTable->rendererTranche, formatTable->monitorTranches); + auto newFormatTable = makeUnique(formatTable->rendererTranche, formatTable->monitorTranches); for (auto const& feedback : m_vFeedbacks) { feedback->resource->sendFormatTable(newFormatTable->tableFD, newFormatTable->tableSize); diff --git a/src/protocols/LinuxDMABUF.hpp b/src/protocols/LinuxDMABUF.hpp index e4941a6d..8c574dbc 100644 --- a/src/protocols/LinuxDMABUF.hpp +++ b/src/protocols/LinuxDMABUF.hpp @@ -1,6 +1,5 @@ #pragma once -#include #include #include #include "WaylandProtocol.hpp" diff --git a/src/protocols/LockNotify.cpp b/src/protocols/LockNotify.cpp index adcd0b2d..1855f891 100644 --- a/src/protocols/LockNotify.cpp +++ b/src/protocols/LockNotify.cpp @@ -31,7 +31,7 @@ CLockNotifyProtocol::CLockNotifyProtocol(const wl_interface* iface, const int& v } void CLockNotifyProtocol::bindManager(wl_client* client, void* data, uint32_t ver, uint32_t id) { - const auto RESOURCE = m_managers.emplace_back(std::make_unique(client, ver, id)).get(); + const auto RESOURCE = m_managers.emplace_back(makeUnique(client, ver, id)).get(); RESOURCE->setOnDestroy([this](CHyprlandLockNotifierV1* p) { this->onManagerResourceDestroy(p->resource()); }); RESOURCE->setDestroy([this](CHyprlandLockNotifierV1* pMgr) { this->onManagerResourceDestroy(pMgr->resource()); }); diff --git a/src/protocols/MesaDRM.hpp b/src/protocols/MesaDRM.hpp index 46811d68..bfa604cf 100644 --- a/src/protocols/MesaDRM.hpp +++ b/src/protocols/MesaDRM.hpp @@ -1,6 +1,5 @@ #pragma once -#include #include #include #include "WaylandProtocol.hpp" diff --git a/src/protocols/OutputManagement.hpp b/src/protocols/OutputManagement.hpp index b9e7ce98..1594df5d 100644 --- a/src/protocols/OutputManagement.hpp +++ b/src/protocols/OutputManagement.hpp @@ -1,6 +1,5 @@ #pragma once -#include #include #include #include diff --git a/src/protocols/OutputPower.cpp b/src/protocols/OutputPower.cpp index f97babc2..24106817 100644 --- a/src/protocols/OutputPower.cpp +++ b/src/protocols/OutputPower.cpp @@ -43,7 +43,7 @@ COutputPowerProtocol::COutputPowerProtocol(const wl_interface* iface, const int& } void COutputPowerProtocol::bindManager(wl_client* client, void* data, uint32_t ver, uint32_t id) { - const auto RESOURCE = m_vManagers.emplace_back(std::make_unique(client, ver, id)).get(); + const auto RESOURCE = m_vManagers.emplace_back(makeUnique(client, ver, id)).get(); RESOURCE->setOnDestroy([this](CZwlrOutputPowerManagerV1* p) { this->onManagerResourceDestroy(p->resource()); }); RESOURCE->setDestroy([this](CZwlrOutputPowerManagerV1* pMgr) { this->onManagerResourceDestroy(pMgr->resource()); }); @@ -68,7 +68,7 @@ void COutputPowerProtocol::onGetOutputPower(CZwlrOutputPowerManagerV1* pMgr, uin } const auto CLIENT = pMgr->client(); - const auto RESOURCE = m_vOutputPowers.emplace_back(std::make_unique(makeShared(CLIENT, pMgr->version(), id), OUTPUT->monitor.lock())).get(); + const auto RESOURCE = m_vOutputPowers.emplace_back(makeUnique(makeShared(CLIENT, pMgr->version(), id), OUTPUT->monitor.lock())).get(); if UNLIKELY (!RESOURCE->good()) { pMgr->noMemory(); diff --git a/src/protocols/OutputPower.hpp b/src/protocols/OutputPower.hpp index 91f2c5f3..c61eaa3d 100644 --- a/src/protocols/OutputPower.hpp +++ b/src/protocols/OutputPower.hpp @@ -1,6 +1,5 @@ #pragma once -#include #include #include #include "WaylandProtocol.hpp" diff --git a/src/protocols/PointerConstraints.cpp b/src/protocols/PointerConstraints.cpp index c0531799..30ab0a55 100644 --- a/src/protocols/PointerConstraints.cpp +++ b/src/protocols/PointerConstraints.cpp @@ -199,7 +199,7 @@ CPointerConstraintsProtocol::CPointerConstraintsProtocol(const wl_interface* ifa } void CPointerConstraintsProtocol::bindManager(wl_client* client, void* data, uint32_t ver, uint32_t id) { - const auto RESOURCE = m_vManagers.emplace_back(std::make_unique(client, ver, id)).get(); + const auto RESOURCE = m_vManagers.emplace_back(makeUnique(client, ver, id)).get(); RESOURCE->setOnDestroy([this](CZwpPointerConstraintsV1* p) { this->onManagerResourceDestroy(p->resource()); }); RESOURCE->setDestroy([this](CZwpPointerConstraintsV1* pMgr) { this->onManagerResourceDestroy(pMgr->resource()); }); diff --git a/src/protocols/PointerConstraints.hpp b/src/protocols/PointerConstraints.hpp index 964bf672..1cd2fca9 100644 --- a/src/protocols/PointerConstraints.hpp +++ b/src/protocols/PointerConstraints.hpp @@ -2,7 +2,6 @@ #pragma once -#include #include #include #include "WaylandProtocol.hpp" diff --git a/src/protocols/PointerGestures.cpp b/src/protocols/PointerGestures.cpp index 4df51b47..8de73ffa 100644 --- a/src/protocols/PointerGestures.cpp +++ b/src/protocols/PointerGestures.cpp @@ -44,7 +44,7 @@ CPointerGesturesProtocol::CPointerGesturesProtocol(const wl_interface* iface, co } void CPointerGesturesProtocol::bindManager(wl_client* client, void* data, uint32_t ver, uint32_t id) { - const auto RESOURCE = m_vManagers.emplace_back(std::make_unique(client, ver, id)).get(); + const auto RESOURCE = m_vManagers.emplace_back(makeUnique(client, ver, id)).get(); RESOURCE->setOnDestroy([this](CZwpPointerGesturesV1* p) { this->onManagerResourceDestroy(p->resource()); }); RESOURCE->setRelease([this](CZwpPointerGesturesV1* pMgr) { this->onManagerResourceDestroy(pMgr->resource()); }); @@ -71,7 +71,7 @@ void CPointerGesturesProtocol::onGestureDestroy(CPointerGestureHold* gesture) { void CPointerGesturesProtocol::onGetPinchGesture(CZwpPointerGesturesV1* pMgr, uint32_t id, wl_resource* pointer) { const auto CLIENT = pMgr->client(); - const auto RESOURCE = m_vPinches.emplace_back(std::make_unique(makeShared(CLIENT, pMgr->version(), id))).get(); + const auto RESOURCE = m_vPinches.emplace_back(makeUnique(makeShared(CLIENT, pMgr->version(), id))).get(); if UNLIKELY (!RESOURCE->good()) { pMgr->noMemory(); @@ -82,7 +82,7 @@ void CPointerGesturesProtocol::onGetPinchGesture(CZwpPointerGesturesV1* pMgr, ui void CPointerGesturesProtocol::onGetSwipeGesture(CZwpPointerGesturesV1* pMgr, uint32_t id, wl_resource* pointer) { const auto CLIENT = pMgr->client(); - const auto RESOURCE = m_vSwipes.emplace_back(std::make_unique(makeShared(CLIENT, pMgr->version(), id))).get(); + const auto RESOURCE = m_vSwipes.emplace_back(makeUnique(makeShared(CLIENT, pMgr->version(), id))).get(); if UNLIKELY (!RESOURCE->good()) { pMgr->noMemory(); @@ -93,7 +93,7 @@ void CPointerGesturesProtocol::onGetSwipeGesture(CZwpPointerGesturesV1* pMgr, ui void CPointerGesturesProtocol::onGetHoldGesture(CZwpPointerGesturesV1* pMgr, uint32_t id, wl_resource* pointer) { const auto CLIENT = pMgr->client(); - const auto RESOURCE = m_vHolds.emplace_back(std::make_unique(makeShared(CLIENT, pMgr->version(), id))).get(); + const auto RESOURCE = m_vHolds.emplace_back(makeUnique(makeShared(CLIENT, pMgr->version(), id))).get(); if UNLIKELY (!RESOURCE->good()) { pMgr->noMemory(); diff --git a/src/protocols/PointerGestures.hpp b/src/protocols/PointerGestures.hpp index f907a49f..5211ecf3 100644 --- a/src/protocols/PointerGestures.hpp +++ b/src/protocols/PointerGestures.hpp @@ -1,6 +1,5 @@ #pragma once -#include #include #include "WaylandProtocol.hpp" #include "pointer-gestures-unstable-v1.hpp" diff --git a/src/protocols/PresentationTime.cpp b/src/protocols/PresentationTime.cpp index 1654041c..a9139ac0 100644 --- a/src/protocols/PresentationTime.cpp +++ b/src/protocols/PresentationTime.cpp @@ -79,7 +79,7 @@ CPresentationProtocol::CPresentationProtocol(const wl_interface* iface, const in } void CPresentationProtocol::bindManager(wl_client* client, void* data, uint32_t ver, uint32_t id) { - const auto RESOURCE = m_vManagers.emplace_back(std::make_unique(client, ver, id)).get(); + const auto RESOURCE = m_vManagers.emplace_back(makeUnique(client, ver, id)).get(); RESOURCE->setOnDestroy([this](CWpPresentation* p) { this->onManagerResourceDestroy(p->resource()); }); RESOURCE->setDestroy([this](CWpPresentation* pMgr) { this->onManagerResourceDestroy(pMgr->resource()); }); diff --git a/src/protocols/PresentationTime.hpp b/src/protocols/PresentationTime.hpp index d9b45448..03b59b89 100644 --- a/src/protocols/PresentationTime.hpp +++ b/src/protocols/PresentationTime.hpp @@ -1,6 +1,5 @@ #pragma once -#include #include #include #include "WaylandProtocol.hpp" diff --git a/src/protocols/PrimarySelection.hpp b/src/protocols/PrimarySelection.hpp index c33a00e8..aeebe03c 100644 --- a/src/protocols/PrimarySelection.hpp +++ b/src/protocols/PrimarySelection.hpp @@ -1,6 +1,5 @@ #pragma once -#include #include #include #include "WaylandProtocol.hpp" diff --git a/src/protocols/RelativePointer.cpp b/src/protocols/RelativePointer.cpp index 842af894..f002fac1 100644 --- a/src/protocols/RelativePointer.cpp +++ b/src/protocols/RelativePointer.cpp @@ -31,7 +31,7 @@ CRelativePointerProtocol::CRelativePointerProtocol(const wl_interface* iface, co } void CRelativePointerProtocol::bindManager(wl_client* client, void* data, uint32_t ver, uint32_t id) { - const auto RESOURCE = m_vManagers.emplace_back(std::make_unique(client, ver, id)).get(); + const auto RESOURCE = m_vManagers.emplace_back(makeUnique(client, ver, id)).get(); RESOURCE->setOnDestroy([this](CZwpRelativePointerManagerV1* p) { this->onManagerResourceDestroy(p->resource()); }); RESOURCE->setDestroy([this](CZwpRelativePointerManagerV1* pMgr) { this->onManagerResourceDestroy(pMgr->resource()); }); @@ -48,7 +48,7 @@ void CRelativePointerProtocol::destroyRelativePointer(CRelativePointer* pointer) void CRelativePointerProtocol::onGetRelativePointer(CZwpRelativePointerManagerV1* pMgr, uint32_t id, wl_resource* pointer) { const auto CLIENT = pMgr->client(); - const auto RESOURCE = m_vRelativePointers.emplace_back(std::make_unique(makeShared(CLIENT, pMgr->version(), id))).get(); + const auto RESOURCE = m_vRelativePointers.emplace_back(makeUnique(makeShared(CLIENT, pMgr->version(), id))).get(); if UNLIKELY (!RESOURCE->good()) { pMgr->noMemory(); diff --git a/src/protocols/RelativePointer.hpp b/src/protocols/RelativePointer.hpp index 453ce157..ce060ed3 100644 --- a/src/protocols/RelativePointer.hpp +++ b/src/protocols/RelativePointer.hpp @@ -1,6 +1,5 @@ #pragma once -#include #include #include #include "WaylandProtocol.hpp" diff --git a/src/protocols/SecurityContext.hpp b/src/protocols/SecurityContext.hpp index d675d660..2bec08d4 100644 --- a/src/protocols/SecurityContext.hpp +++ b/src/protocols/SecurityContext.hpp @@ -1,6 +1,5 @@ #pragma once -#include #include #include #include "WaylandProtocol.hpp" diff --git a/src/protocols/ServerDecorationKDE.cpp b/src/protocols/ServerDecorationKDE.cpp index 3e33db52..0726c8a5 100644 --- a/src/protocols/ServerDecorationKDE.cpp +++ b/src/protocols/ServerDecorationKDE.cpp @@ -21,7 +21,7 @@ CServerDecorationKDEProtocol::CServerDecorationKDEProtocol(const wl_interface* i } void CServerDecorationKDEProtocol::bindManager(wl_client* client, void* data, uint32_t ver, uint32_t id) { - const auto RESOURCE = m_vManagers.emplace_back(std::make_unique(client, ver, id)).get(); + const auto RESOURCE = m_vManagers.emplace_back(makeUnique(client, ver, id)).get(); RESOURCE->setOnDestroy([this](COrgKdeKwinServerDecorationManager* p) { this->onManagerResourceDestroy(p->resource()); }); RESOURCE->setCreate([this](COrgKdeKwinServerDecorationManager* pMgr, uint32_t id, wl_resource* pointer) { this->createDecoration(pMgr, id, pointer); }); @@ -41,8 +41,7 @@ void CServerDecorationKDEProtocol::destroyResource(CServerDecorationKDE* hayperl void CServerDecorationKDEProtocol::createDecoration(COrgKdeKwinServerDecorationManager* pMgr, uint32_t id, wl_resource* surf) { const auto CLIENT = pMgr->client(); const auto RESOURCE = - m_vDecos.emplace_back(std::make_unique(makeShared(CLIENT, pMgr->version(), id), CWLSurfaceResource::fromResource(surf))) - .get(); + m_vDecos.emplace_back(makeUnique(makeShared(CLIENT, pMgr->version(), id), CWLSurfaceResource::fromResource(surf))).get(); if UNLIKELY (!RESOURCE->good()) { pMgr->noMemory(); diff --git a/src/protocols/ServerDecorationKDE.hpp b/src/protocols/ServerDecorationKDE.hpp index ab082b17..0d0fa898 100644 --- a/src/protocols/ServerDecorationKDE.hpp +++ b/src/protocols/ServerDecorationKDE.hpp @@ -1,6 +1,5 @@ #pragma once -#include #include #include #include "WaylandProtocol.hpp" diff --git a/src/protocols/SessionLock.cpp b/src/protocols/SessionLock.cpp index 8e215ffa..d87775e9 100644 --- a/src/protocols/SessionLock.cpp +++ b/src/protocols/SessionLock.cpp @@ -148,7 +148,7 @@ CSessionLockProtocol::CSessionLockProtocol(const wl_interface* iface, const int& } void CSessionLockProtocol::bindManager(wl_client* client, void* data, uint32_t ver, uint32_t id) { - const auto RESOURCE = m_vManagers.emplace_back(std::make_unique(client, ver, id)).get(); + const auto RESOURCE = m_vManagers.emplace_back(makeUnique(client, ver, id)).get(); RESOURCE->setOnDestroy([this](CExtSessionLockManagerV1* p) { this->onManagerResourceDestroy(p->resource()); }); RESOURCE->setDestroy([this](CExtSessionLockManagerV1* pMgr) { this->onManagerResourceDestroy(pMgr->resource()); }); diff --git a/src/protocols/SessionLock.hpp b/src/protocols/SessionLock.hpp index a1df6fcf..670e5e1d 100644 --- a/src/protocols/SessionLock.hpp +++ b/src/protocols/SessionLock.hpp @@ -1,6 +1,5 @@ #pragma once -#include #include #include #include "WaylandProtocol.hpp" diff --git a/src/protocols/ShortcutsInhibit.cpp b/src/protocols/ShortcutsInhibit.cpp index a0d29f92..5786de26 100644 --- a/src/protocols/ShortcutsInhibit.cpp +++ b/src/protocols/ShortcutsInhibit.cpp @@ -28,7 +28,7 @@ CKeyboardShortcutsInhibitProtocol::CKeyboardShortcutsInhibitProtocol(const wl_in } void CKeyboardShortcutsInhibitProtocol::bindManager(wl_client* client, void* data, uint32_t ver, uint32_t id) { - const auto RESOURCE = m_vManagers.emplace_back(std::make_unique(client, ver, id)).get(); + const auto RESOURCE = m_vManagers.emplace_back(makeUnique(client, ver, id)).get(); RESOURCE->setOnDestroy([this](CZwpKeyboardShortcutsInhibitManagerV1* p) { this->onManagerResourceDestroy(p->resource()); }); RESOURCE->setDestroy([this](CZwpKeyboardShortcutsInhibitManagerV1* pMgr) { this->onManagerResourceDestroy(pMgr->resource()); }); @@ -57,7 +57,7 @@ void CKeyboardShortcutsInhibitProtocol::onInhibit(CZwpKeyboardShortcutsInhibitMa } const auto RESOURCE = - m_vInhibitors.emplace_back(std::make_unique(makeShared(CLIENT, pMgr->version(), id), surf)).get(); + m_vInhibitors.emplace_back(makeUnique(makeShared(CLIENT, pMgr->version(), id), surf)).get(); if UNLIKELY (!RESOURCE->good()) { pMgr->noMemory(); diff --git a/src/protocols/ShortcutsInhibit.hpp b/src/protocols/ShortcutsInhibit.hpp index ba1c134c..c093ac6e 100644 --- a/src/protocols/ShortcutsInhibit.hpp +++ b/src/protocols/ShortcutsInhibit.hpp @@ -1,6 +1,5 @@ #pragma once -#include #include #include #include "WaylandProtocol.hpp" diff --git a/src/protocols/SinglePixel.hpp b/src/protocols/SinglePixel.hpp index b20f582a..2a86d050 100644 --- a/src/protocols/SinglePixel.hpp +++ b/src/protocols/SinglePixel.hpp @@ -1,6 +1,5 @@ #pragma once -#include #include #include #include "WaylandProtocol.hpp" diff --git a/src/protocols/Tablet.cpp b/src/protocols/Tablet.cpp index 62e8b2d2..de2ed71b 100644 --- a/src/protocols/Tablet.cpp +++ b/src/protocols/Tablet.cpp @@ -315,7 +315,7 @@ CTabletV2Protocol::CTabletV2Protocol(const wl_interface* iface, const int& ver, } void CTabletV2Protocol::bindManager(wl_client* client, void* data, uint32_t ver, uint32_t id) { - const auto RESOURCE = m_vManagers.emplace_back(std::make_unique(client, ver, id)).get(); + const auto RESOURCE = m_vManagers.emplace_back(makeUnique(client, ver, id)).get(); RESOURCE->setOnDestroy([this](CZwpTabletManagerV2* p) { this->onManagerResourceDestroy(p->resource()); }); RESOURCE->setDestroy([this](CZwpTabletManagerV2* pMgr) { this->onManagerResourceDestroy(pMgr->resource()); }); diff --git a/src/protocols/Tablet.hpp b/src/protocols/Tablet.hpp index 1ebcb1e5..264c7633 100644 --- a/src/protocols/Tablet.hpp +++ b/src/protocols/Tablet.hpp @@ -1,6 +1,5 @@ #pragma once -#include #include #include #include "WaylandProtocol.hpp" diff --git a/src/protocols/TearingControl.cpp b/src/protocols/TearingControl.cpp index 14c80052..16e85352 100644 --- a/src/protocols/TearingControl.cpp +++ b/src/protocols/TearingControl.cpp @@ -11,7 +11,7 @@ CTearingControlProtocol::CTearingControlProtocol(const wl_interface* iface, cons } void CTearingControlProtocol::bindManager(wl_client* client, void* data, uint32_t ver, uint32_t id) { - const auto RESOURCE = m_vManagers.emplace_back(std::make_unique(client, ver, id)).get(); + const auto RESOURCE = m_vManagers.emplace_back(makeUnique(client, ver, id)).get(); RESOURCE->setOnDestroy([this](CWpTearingControlManagerV1* p) { this->onManagerResourceDestroy(p->resource()); }); RESOURCE->setDestroy([this](CWpTearingControlManagerV1* pMgr) { this->onManagerResourceDestroy(pMgr->resource()); }); @@ -25,7 +25,7 @@ void CTearingControlProtocol::onManagerResourceDestroy(wl_resource* res) { } void CTearingControlProtocol::onGetController(wl_client* client, CWpTearingControlManagerV1* pMgr, uint32_t id, SP surf) { - const auto CONTROLLER = m_vTearingControllers.emplace_back(std::make_unique(makeShared(client, pMgr->version(), id), surf)).get(); + const auto CONTROLLER = m_vTearingControllers.emplace_back(makeUnique(makeShared(client, pMgr->version(), id), surf)).get(); if UNLIKELY (!CONTROLLER->good()) { pMgr->noMemory(); diff --git a/src/protocols/TearingControl.hpp b/src/protocols/TearingControl.hpp index d81a27cd..7763214e 100644 --- a/src/protocols/TearingControl.hpp +++ b/src/protocols/TearingControl.hpp @@ -1,6 +1,5 @@ #pragma once -#include #include "WaylandProtocol.hpp" #include "tearing-control-v1.hpp" diff --git a/src/protocols/TextInputV3.cpp b/src/protocols/TextInputV3.cpp index 71ef6dac..06aea5ae 100644 --- a/src/protocols/TextInputV3.cpp +++ b/src/protocols/TextInputV3.cpp @@ -110,7 +110,7 @@ CTextInputV3Protocol::CTextInputV3Protocol(const wl_interface* iface, const int& } void CTextInputV3Protocol::bindManager(wl_client* client, void* data, uint32_t ver, uint32_t id) { - const auto RESOURCE = m_vManagers.emplace_back(std::make_unique(client, ver, id)).get(); + const auto RESOURCE = m_vManagers.emplace_back(makeUnique(client, ver, id)).get(); RESOURCE->setOnDestroy([this](CZwpTextInputManagerV3* p) { this->onManagerResourceDestroy(p->resource()); }); RESOURCE->setDestroy([this](CZwpTextInputManagerV3* pMgr) { this->onManagerResourceDestroy(pMgr->resource()); }); diff --git a/src/protocols/TextInputV3.hpp b/src/protocols/TextInputV3.hpp index ba8b75e6..6cece521 100644 --- a/src/protocols/TextInputV3.hpp +++ b/src/protocols/TextInputV3.hpp @@ -1,6 +1,5 @@ #pragma once -#include #include #include #include diff --git a/src/protocols/Viewporter.hpp b/src/protocols/Viewporter.hpp index 3c2a4eef..6824f2ae 100644 --- a/src/protocols/Viewporter.hpp +++ b/src/protocols/Viewporter.hpp @@ -1,6 +1,5 @@ #pragma once -#include #include #include #include "WaylandProtocol.hpp" diff --git a/src/protocols/VirtualKeyboard.cpp b/src/protocols/VirtualKeyboard.cpp index 7da1fe01..4fec57c0 100644 --- a/src/protocols/VirtualKeyboard.cpp +++ b/src/protocols/VirtualKeyboard.cpp @@ -124,7 +124,7 @@ CVirtualKeyboardProtocol::CVirtualKeyboardProtocol(const wl_interface* iface, co } void CVirtualKeyboardProtocol::bindManager(wl_client* client, void* data, uint32_t ver, uint32_t id) { - const auto RESOURCE = m_vManagers.emplace_back(std::make_unique(client, ver, id)).get(); + const auto RESOURCE = m_vManagers.emplace_back(makeUnique(client, ver, id)).get(); RESOURCE->setOnDestroy([this](CZwpVirtualKeyboardManagerV1* p) { this->onManagerResourceDestroy(p->resource()); }); RESOURCE->setCreateVirtualKeyboard([this](CZwpVirtualKeyboardManagerV1* pMgr, wl_resource* seat, uint32_t id) { this->onCreateKeeb(pMgr, seat, id); }); diff --git a/src/protocols/VirtualKeyboard.hpp b/src/protocols/VirtualKeyboard.hpp index 93b63bb5..8157b276 100644 --- a/src/protocols/VirtualKeyboard.hpp +++ b/src/protocols/VirtualKeyboard.hpp @@ -1,6 +1,5 @@ #pragma once -#include #include #include #include "WaylandProtocol.hpp" diff --git a/src/protocols/VirtualPointer.cpp b/src/protocols/VirtualPointer.cpp index 3e0b00eb..33641a7b 100644 --- a/src/protocols/VirtualPointer.cpp +++ b/src/protocols/VirtualPointer.cpp @@ -107,7 +107,7 @@ CVirtualPointerProtocol::CVirtualPointerProtocol(const wl_interface* iface, cons } void CVirtualPointerProtocol::bindManager(wl_client* client, void* data, uint32_t ver, uint32_t id) { - const auto RESOURCE = m_vManagers.emplace_back(std::make_unique(client, ver, id)).get(); + const auto RESOURCE = m_vManagers.emplace_back(makeUnique(client, ver, id)).get(); RESOURCE->setOnDestroy([this](CZwlrVirtualPointerManagerV1* p) { this->onManagerResourceDestroy(p->resource()); }); RESOURCE->setDestroy([this](CZwlrVirtualPointerManagerV1* p) { this->onManagerResourceDestroy(p->resource()); }); diff --git a/src/protocols/VirtualPointer.hpp b/src/protocols/VirtualPointer.hpp index 68fe124e..ac8bcae2 100644 --- a/src/protocols/VirtualPointer.hpp +++ b/src/protocols/VirtualPointer.hpp @@ -1,6 +1,5 @@ #pragma once -#include #include #include #include diff --git a/src/protocols/WaylandProtocol.hpp b/src/protocols/WaylandProtocol.hpp index e3507708..918ac70f 100644 --- a/src/protocols/WaylandProtocol.hpp +++ b/src/protocols/WaylandProtocol.hpp @@ -1,6 +1,7 @@ #pragma once #include "../defines.hpp" +#include "../helpers/memory/Memory.hpp" #include diff --git a/src/protocols/XDGActivation.cpp b/src/protocols/XDGActivation.cpp index c49dc3dc..4062847b 100644 --- a/src/protocols/XDGActivation.cpp +++ b/src/protocols/XDGActivation.cpp @@ -62,7 +62,7 @@ CXDGActivationProtocol::CXDGActivationProtocol(const wl_interface* iface, const } void CXDGActivationProtocol::bindManager(wl_client* client, void* data, uint32_t ver, uint32_t id) { - const auto RESOURCE = m_vManagers.emplace_back(std::make_unique(client, ver, id)).get(); + const auto RESOURCE = m_vManagers.emplace_back(makeUnique(client, ver, id)).get(); RESOURCE->setOnDestroy([this](CXdgActivationV1* p) { this->onManagerResourceDestroy(p->resource()); }); RESOURCE->setDestroy([this](CXdgActivationV1* pMgr) { this->onManagerResourceDestroy(pMgr->resource()); }); @@ -100,7 +100,7 @@ void CXDGActivationProtocol::destroyToken(CXDGActivationToken* token) { void CXDGActivationProtocol::onGetToken(CXdgActivationV1* pMgr, uint32_t id) { const auto CLIENT = pMgr->client(); - const auto RESOURCE = m_vTokens.emplace_back(std::make_unique(makeShared(CLIENT, pMgr->version(), id))).get(); + const auto RESOURCE = m_vTokens.emplace_back(makeUnique(makeShared(CLIENT, pMgr->version(), id))).get(); if UNLIKELY (!RESOURCE->good()) { pMgr->noMemory(); diff --git a/src/protocols/XDGActivation.hpp b/src/protocols/XDGActivation.hpp index 80af988d..1db16b3c 100644 --- a/src/protocols/XDGActivation.hpp +++ b/src/protocols/XDGActivation.hpp @@ -1,6 +1,5 @@ #pragma once -#include #include #include #include "WaylandProtocol.hpp" diff --git a/src/protocols/XDGDecoration.cpp b/src/protocols/XDGDecoration.cpp index 8ec0d5b0..f9dbf411 100644 --- a/src/protocols/XDGDecoration.cpp +++ b/src/protocols/XDGDecoration.cpp @@ -41,7 +41,7 @@ CXDGDecorationProtocol::CXDGDecorationProtocol(const wl_interface* iface, const } void CXDGDecorationProtocol::bindManager(wl_client* client, void* data, uint32_t ver, uint32_t id) { - const auto RESOURCE = m_vManagers.emplace_back(std::make_unique(client, ver, id)).get(); + const auto RESOURCE = m_vManagers.emplace_back(makeUnique(client, ver, id)).get(); RESOURCE->setOnDestroy([this](CZxdgDecorationManagerV1* p) { this->onManagerResourceDestroy(p->resource()); }); RESOURCE->setDestroy([this](CZxdgDecorationManagerV1* pMgr) { this->onManagerResourceDestroy(pMgr->resource()); }); @@ -64,7 +64,7 @@ void CXDGDecorationProtocol::onGetDecoration(CZxdgDecorationManagerV1* pMgr, uin const auto CLIENT = pMgr->client(); const auto RESOURCE = - m_mDecorations.emplace(xdgToplevel, std::make_unique(makeShared(CLIENT, pMgr->version(), id), xdgToplevel)).first->second.get(); + m_mDecorations.emplace(xdgToplevel, makeUnique(makeShared(CLIENT, pMgr->version(), id), xdgToplevel)).first->second.get(); if UNLIKELY (!RESOURCE->good()) { pMgr->noMemory(); diff --git a/src/protocols/XDGDecoration.hpp b/src/protocols/XDGDecoration.hpp index cbd74be4..33a9b663 100644 --- a/src/protocols/XDGDecoration.hpp +++ b/src/protocols/XDGDecoration.hpp @@ -1,6 +1,5 @@ #pragma once -#include #include #include #include "WaylandProtocol.hpp" diff --git a/src/protocols/XDGDialog.hpp b/src/protocols/XDGDialog.hpp index a635bfac..1b29e692 100644 --- a/src/protocols/XDGDialog.hpp +++ b/src/protocols/XDGDialog.hpp @@ -1,6 +1,5 @@ #pragma once -#include #include #include #include "WaylandProtocol.hpp" diff --git a/src/protocols/XDGOutput.cpp b/src/protocols/XDGOutput.cpp index 5be16d07..544deed0 100644 --- a/src/protocols/XDGOutput.cpp +++ b/src/protocols/XDGOutput.cpp @@ -21,7 +21,7 @@ void CXDGOutputProtocol::onOutputResourceDestroy(wl_resource* res) { } void CXDGOutputProtocol::bindManager(wl_client* client, void* data, uint32_t ver, uint32_t id) { - const auto RESOURCE = m_vManagerResources.emplace_back(std::make_unique(client, ver, id)).get(); + const auto RESOURCE = m_vManagerResources.emplace_back(makeUnique(client, ver, id)).get(); if UNLIKELY (!RESOURCE->resource()) { LOGM(LOG, "Couldn't bind XDGOutputMgr"); @@ -44,7 +44,7 @@ void CXDGOutputProtocol::onManagerGetXDGOutput(CZxdgOutputManagerV1* mgr, uint32 const auto PMONITOR = OUTPUT->monitor.lock(); const auto CLIENT = mgr->client(); - CXDGOutput* pXDGOutput = m_vXDGOutputs.emplace_back(std::make_unique(makeShared(CLIENT, mgr->version(), id), PMONITOR)).get(); + CXDGOutput* pXDGOutput = m_vXDGOutputs.emplace_back(makeUnique(makeShared(CLIENT, mgr->version(), id), PMONITOR)).get(); #ifndef NO_XWAYLAND if (g_pXWayland && g_pXWayland->pServer && g_pXWayland->pServer->xwaylandClient == CLIENT) pXDGOutput->isXWayland = true; diff --git a/src/protocols/XDGShell.hpp b/src/protocols/XDGShell.hpp index 6eef99bb..4c2b8100 100644 --- a/src/protocols/XDGShell.hpp +++ b/src/protocols/XDGShell.hpp @@ -1,6 +1,5 @@ #pragma once -#include #include #include #include diff --git a/src/protocols/XWaylandShell.hpp b/src/protocols/XWaylandShell.hpp index c8c0c04a..f6f91c49 100644 --- a/src/protocols/XWaylandShell.hpp +++ b/src/protocols/XWaylandShell.hpp @@ -1,6 +1,5 @@ #pragma once -#include #include #include #include "WaylandProtocol.hpp" diff --git a/src/protocols/core/Compositor.hpp b/src/protocols/core/Compositor.hpp index b347eb64..20614813 100644 --- a/src/protocols/core/Compositor.hpp +++ b/src/protocols/core/Compositor.hpp @@ -8,7 +8,6 @@ - wl_callback */ -#include #include #include #include "../WaylandProtocol.hpp" diff --git a/src/protocols/core/DataDevice.hpp b/src/protocols/core/DataDevice.hpp index ae22e474..5101862e 100644 --- a/src/protocols/core/DataDevice.hpp +++ b/src/protocols/core/DataDevice.hpp @@ -8,7 +8,6 @@ - wl_data_device_manager */ -#include #include #include #include "../WaylandProtocol.hpp" diff --git a/src/protocols/core/Output.hpp b/src/protocols/core/Output.hpp index a4c81d72..8ade5178 100644 --- a/src/protocols/core/Output.hpp +++ b/src/protocols/core/Output.hpp @@ -1,6 +1,5 @@ #pragma once -#include #include #include #include "../WaylandProtocol.hpp" diff --git a/src/protocols/core/Seat.hpp b/src/protocols/core/Seat.hpp index b5670237..a4889379 100644 --- a/src/protocols/core/Seat.hpp +++ b/src/protocols/core/Seat.hpp @@ -8,7 +8,6 @@ - wl_touch */ -#include #include #include #include "../WaylandProtocol.hpp" diff --git a/src/protocols/core/Shm.hpp b/src/protocols/core/Shm.hpp index 9f4e18f9..23a465fb 100644 --- a/src/protocols/core/Shm.hpp +++ b/src/protocols/core/Shm.hpp @@ -7,7 +7,6 @@ - wl_buffer with shm */ -#include #include #include #include "../WaylandProtocol.hpp" diff --git a/src/protocols/core/Subcompositor.hpp b/src/protocols/core/Subcompositor.hpp index 2e6b10bb..dc713044 100644 --- a/src/protocols/core/Subcompositor.hpp +++ b/src/protocols/core/Subcompositor.hpp @@ -7,7 +7,6 @@ - wl_subcompositor */ -#include #include #include #include "../WaylandProtocol.hpp" diff --git a/src/protocols/types/WLBuffer.hpp b/src/protocols/types/WLBuffer.hpp index 787abe1f..3894affc 100644 --- a/src/protocols/types/WLBuffer.hpp +++ b/src/protocols/types/WLBuffer.hpp @@ -1,6 +1,5 @@ #pragma once -#include #include #include #include "../WaylandProtocol.hpp" diff --git a/src/render/OpenGL.hpp b/src/render/OpenGL.hpp index 8098485e..3dc3b43a 100644 --- a/src/render/OpenGL.hpp +++ b/src/render/OpenGL.hpp @@ -328,4 +328,4 @@ class CHyprOpenGLImpl { friend class CSurfacePassElement; }; -inline std::unique_ptr g_pHyprOpenGL; +inline UP g_pHyprOpenGL; diff --git a/src/render/Renderer.hpp b/src/render/Renderer.hpp index 7aef96e6..1ef1eecc 100644 --- a/src/render/Renderer.hpp +++ b/src/render/Renderer.hpp @@ -155,4 +155,4 @@ class CHyprRenderer { friend class CMonitor; }; -inline std::unique_ptr g_pHyprRenderer; +inline UP g_pHyprRenderer; diff --git a/src/render/decorations/CHyprGroupBarDecoration.cpp b/src/render/decorations/CHyprGroupBarDecoration.cpp index 4a411b6c..36846fd4 100644 --- a/src/render/decorations/CHyprGroupBarDecoration.cpp +++ b/src/render/decorations/CHyprGroupBarDecoration.cpp @@ -176,11 +176,11 @@ void CHyprGroupBarDecoration::draw(PHLMONITOR pMonitor, float const& a) { CTitleTex* pTitleTex = textureFromTitle(m_dwGroupMembers[WINDOWINDEX]->m_szTitle); if (!pTitleTex) - pTitleTex = m_sTitleTexs.titleTexs - .emplace_back(std::make_unique(m_dwGroupMembers[WINDOWINDEX].lock(), - Vector2D{m_fBarWidth * pMonitor->scale, (*PTITLEFONTSIZE + 2L * BAR_TEXT_PAD) * pMonitor->scale}, - pMonitor->scale)) - .get(); + pTitleTex = + m_sTitleTexs.titleTexs + .emplace_back(makeUnique(m_dwGroupMembers[WINDOWINDEX].lock(), + Vector2D{m_fBarWidth * pMonitor->scale, (*PTITLEFONTSIZE + 2L * BAR_TEXT_PAD) * pMonitor->scale}, pMonitor->scale)) + .get(); rect.y += std::ceil((rect.height - pTitleTex->texSize.y) / 2.0); rect.height = pTitleTex->texSize.y; rect.width = pTitleTex->texSize.x; @@ -421,7 +421,7 @@ bool CHyprGroupBarDecoration::onEndWindowDragOnDeco(const Vector2D& pos, PHLWIND g_pLayoutManager->getCurrentLayout()->recalculateWindow(pDraggedWindow); if (!pDraggedWindow->getDecorationByType(DECORATION_GROUPBAR)) - pDraggedWindow->addWindowDeco(std::make_unique(pDraggedWindow)); + pDraggedWindow->addWindowDeco(makeUnique(pDraggedWindow)); return true; } diff --git a/src/render/decorations/CHyprGroupBarDecoration.hpp b/src/render/decorations/CHyprGroupBarDecoration.hpp index 653cd11c..7277955d 100644 --- a/src/render/decorations/CHyprGroupBarDecoration.hpp +++ b/src/render/decorations/CHyprGroupBarDecoration.hpp @@ -5,7 +5,7 @@ #include #include "../Texture.hpp" #include -#include +#include "../../helpers/memory/Memory.hpp" class CTitleTex { public: @@ -70,6 +70,6 @@ class CHyprGroupBarDecoration : public IHyprWindowDecoration { struct STitleTexs { // STitleTexs* overriden = nullptr; // TODO: make shit shared in-group to decrease VRAM usage. - std::vector> titleTexs; + std::vector> titleTexs; } m_sTitleTexs; }; diff --git a/src/render/decorations/DecorationPositioner.cpp b/src/render/decorations/DecorationPositioner.cpp index 2ba3c4a7..9dbb12a6 100644 --- a/src/render/decorations/DecorationPositioner.cpp +++ b/src/render/decorations/DecorationPositioner.cpp @@ -79,7 +79,7 @@ CDecorationPositioner::SWindowPositioningData* CDecorationPositioner::getDataFor if (it != m_vWindowPositioningDatas.end()) return it->get(); - const auto DATA = m_vWindowPositioningDatas.emplace_back(std::make_unique(pWindow, pDecoration)).get(); + const auto DATA = m_vWindowPositioningDatas.emplace_back(makeUnique(pWindow, pDecoration)).get(); DATA->positioningInfo = pDecoration->getPositioningInfo(); diff --git a/src/render/decorations/DecorationPositioner.hpp b/src/render/decorations/DecorationPositioner.hpp index c2d69881..787c6d1f 100644 --- a/src/render/decorations/DecorationPositioner.hpp +++ b/src/render/decorations/DecorationPositioner.hpp @@ -87,13 +87,13 @@ class CDecorationPositioner { bool needsRecalc = false; }; - std::map m_mWindowDatas; - std::vector> m_vWindowPositioningDatas; + std::map m_mWindowDatas; + std::vector> m_vWindowPositioningDatas; - SWindowPositioningData* getDataFor(IHyprWindowDecoration* pDecoration, PHLWINDOW pWindow); - void onWindowUnmap(PHLWINDOW pWindow); - void onWindowMap(PHLWINDOW pWindow); - void sanitizeDatas(); + SWindowPositioningData* getDataFor(IHyprWindowDecoration* pDecoration, PHLWINDOW pWindow); + void onWindowUnmap(PHLWINDOW pWindow); + void onWindowMap(PHLWINDOW pWindow); + void sanitizeDatas(); }; -inline std::unique_ptr g_pDecorationPositioner; \ No newline at end of file +inline UP g_pDecorationPositioner; \ No newline at end of file diff --git a/src/xwayland/Server.cpp b/src/xwayland/Server.cpp index c67d5830..d5dce333 100644 --- a/src/xwayland/Server.cpp +++ b/src/xwayland/Server.cpp @@ -442,7 +442,7 @@ int CXWaylandServer::ready(int fd, uint32_t mask) { // start the wm if (!g_pXWayland->pWM) - g_pXWayland->pWM = std::make_unique(); + g_pXWayland->pWM = makeUnique(); g_pCursorManager->setXWaylandCursor(); diff --git a/src/xwayland/XDataSource.cpp b/src/xwayland/XDataSource.cpp index 181955a8..4b0c5a29 100644 --- a/src/xwayland/XDataSource.cpp +++ b/src/xwayland/XDataSource.cpp @@ -71,7 +71,7 @@ void CXDataSource::send(const std::string& mime, uint32_t fd) { Debug::log(LOG, "[XDataSource] send with mime {} to fd {}", mime, fd); - selection.transfer = std::make_unique(selection); + selection.transfer = makeUnique(selection); selection.transfer->incomingWindow = xcb_generate_id(g_pXWayland->pWM->connection); const uint32_t MASK = XCB_EVENT_MASK_SUBSTRUCTURE_NOTIFY | XCB_EVENT_MASK_PROPERTY_CHANGE; xcb_create_window(g_pXWayland->pWM->connection, XCB_COPY_FROM_PARENT, selection.transfer->incomingWindow, g_pXWayland->pWM->screen->root, 0, 0, 10, 10, 0, diff --git a/src/xwayland/XWM.cpp b/src/xwayland/XWM.cpp index 71a7c44c..ef139b38 100644 --- a/src/xwayland/XWM.cpp +++ b/src/xwayland/XWM.cpp @@ -225,7 +225,7 @@ void CXWM::readProp(SP XSURF, uint32_t atom, xcb_get_property_ } } else if (atom == HYPRATOMS["WM_HINTS"]) { if (reply->value_len != 0) { - XSURF->hints = std::make_unique(); + XSURF->hints = makeUnique(); xcb_icccm_get_wm_hints_from_reply(XSURF->hints.get(), reply); if (!(XSURF->hints->flags & XCB_ICCCM_WM_HINT_INPUT)) @@ -254,7 +254,7 @@ void CXWM::readProp(SP XSURF, uint32_t atom, xcb_get_property_ } } else if (atom == HYPRATOMS["WM_NORMAL_HINTS"]) { if (reply->type == HYPRATOMS["WM_SIZE_HINTS"] && reply->value_len > 0) { - XSURF->sizeHints = std::make_unique(); + XSURF->sizeHints = makeUnique(); std::memset(XSURF->sizeHints.get(), 0, sizeof(xcb_size_hints_t)); xcb_icccm_get_wm_size_hints_from_reply(XSURF->sizeHints.get(), reply); @@ -735,7 +735,7 @@ int CXWM::onEvent(int fd, uint32_t mask) { g_pXWayland->pWM.reset(); g_pXWayland->pServer.reset(); // Attempt to create fresh instance - g_pEventLoopManager->doLater([]() { g_pXWayland = std::make_unique(true); }); + g_pEventLoopManager->doLater([]() { g_pXWayland = makeUnique(true); }); return 0; } @@ -1346,7 +1346,7 @@ bool SXSelection::sendData(xcb_selection_request_event_t* e, std::string mime) { mime = *MIMES.begin(); } - transfer = std::make_unique(*this); + transfer = makeUnique(*this); transfer->request = *e; int p[2]; diff --git a/src/xwayland/XWM.hpp b/src/xwayland/XWM.hpp index 02ade80d..dfaf33b9 100644 --- a/src/xwayland/XWM.hpp +++ b/src/xwayland/XWM.hpp @@ -57,7 +57,7 @@ struct SXSelection { CHyprSignalListener keyboardFocusChange; } listeners; - std::unique_ptr transfer; + UP transfer; }; class CXCBConnection { diff --git a/src/xwayland/XWayland.cpp b/src/xwayland/XWayland.cpp index 6b8a630b..9d2a0ea4 100644 --- a/src/xwayland/XWayland.cpp +++ b/src/xwayland/XWayland.cpp @@ -26,7 +26,7 @@ CXWayland::CXWayland(const bool wantsEnabled) { Debug::log(LOG, "Starting up the XWayland server"); - pServer = std::make_unique(); + pServer = makeUnique(); if (!pServer->create()) { Debug::log(ERR, "XWayland failed to start: it will not work."); diff --git a/src/xwayland/XWayland.hpp b/src/xwayland/XWayland.hpp index 8347a6a7..af8d957c 100644 --- a/src/xwayland/XWayland.hpp +++ b/src/xwayland/XWayland.hpp @@ -1,6 +1,5 @@ #pragma once -#include #include "../helpers/signal/Signal.hpp" #include "../helpers/memory/Memory.hpp" #include "../macros.hpp" @@ -20,8 +19,8 @@ class CXWayland { CXWayland(const bool wantsEnabled); #ifndef NO_XWAYLAND - std::unique_ptr pServer; - std::unique_ptr pWM; + UP pServer; + UP pWM; #endif bool enabled(); @@ -35,7 +34,7 @@ class CXWayland { bool m_enabled = false; }; -inline std::unique_ptr g_pXWayland; +inline UP g_pXWayland; inline std::unordered_map HYPRATOMS = { #ifndef NO_XWAYLAND From 1a0a22ad038bbd51c4e1514868d6dcd505af0242 Mon Sep 17 00:00:00 2001 From: Vaxry Date: Thu, 23 Jan 2025 21:27:11 +0000 Subject: [PATCH 0887/2181] configmgr: fix crash on very early plugin loads --- src/config/ConfigManager.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/config/ConfigManager.cpp b/src/config/ConfigManager.cpp index 08f0f33f..b0665db9 100644 --- a/src/config/ConfigManager.cpp +++ b/src/config/ConfigManager.cpp @@ -954,7 +954,8 @@ void CConfigManager::postConfigReload(const Hyprlang::CParseResult& result) { const auto PENABLEXWAYLAND = std::any_cast(m_pConfig->getConfigValue("xwayland:enabled")); g_pCompositor->m_bWantsXwayland = PENABLEXWAYLAND; // enable/disable xwayland usage - if (!isFirstLaunch) { + if (!isFirstLaunch && + g_pXWayland /* XWayland has to be initialized by CCompositor::initManagers for this to make sense, and it doesn't have to be (e.g. very early plugin load) */) { bool prevEnabledXwayland = g_pXWayland->enabled(); if (g_pCompositor->m_bWantsXwayland != prevEnabledXwayland) g_pXWayland = makeUnique(g_pCompositor->m_bWantsXwayland); From 465cf66df14c28427ba30580253be6e3908bd28c Mon Sep 17 00:00:00 2001 From: outfoxxed Date: Thu, 23 Jan 2025 13:57:33 -0800 Subject: [PATCH 0888/2181] protocols: add hyprland_surface_v1.set_visible_region implementation (#9120) --- src/desktop/WLSurface.hpp | 3 +- src/managers/ProtocolManager.cpp | 2 +- src/protocols/HyprlandSurface.cpp | 23 +++++++++++- src/protocols/HyprlandSurface.hpp | 5 ++- src/render/OpenGL.cpp | 17 +++++++-- src/render/OpenGL.hpp | 1 + src/render/pass/SurfacePassElement.cpp | 50 ++++++++++++++++++++++++++ src/render/pass/SurfacePassElement.hpp | 1 + subprojects/hyprland-protocols | 2 +- 9 files changed, 96 insertions(+), 8 deletions(-) diff --git a/src/desktop/WLSurface.hpp b/src/desktop/WLSurface.hpp index 057a6f90..5f8da715 100644 --- a/src/desktop/WLSurface.hpp +++ b/src/desktop/WLSurface.hpp @@ -87,7 +87,8 @@ class CWLSurface { float m_fAlphaModifier = 1.F; // used by the hyprland-surface protocol - float m_fOverallOpacity = 1.F; + float m_fOverallOpacity = 1.F; + CRegion m_visibleRegion; struct { CSignal destroy; diff --git a/src/managers/ProtocolManager.cpp b/src/managers/ProtocolManager.cpp index f73a6d3c..d3270fe2 100644 --- a/src/managers/ProtocolManager.cpp +++ b/src/managers/ProtocolManager.cpp @@ -168,7 +168,7 @@ CProtocolManager::CProtocolManager() { PROTO::singlePixel = makeUnique(&wp_single_pixel_buffer_manager_v1_interface, 1, "SinglePixel"); PROTO::securityContext = makeUnique(&wp_security_context_manager_v1_interface, 1, "SecurityContext"); PROTO::ctm = makeUnique(&hyprland_ctm_control_manager_v1_interface, 1, "CTMControl"); - PROTO::hyprlandSurface = makeUnique(&hyprland_surface_manager_v1_interface, 1, "HyprlandSurface"); + PROTO::hyprlandSurface = makeUnique(&hyprland_surface_manager_v1_interface, 2, "HyprlandSurface"); if (*PENABLEXXCM) { PROTO::colorManagement = makeUnique(&xx_color_manager_v4_interface, 1, "ColorManagement"); diff --git a/src/protocols/HyprlandSurface.cpp b/src/protocols/HyprlandSurface.cpp index ca133b78..e3716f10 100644 --- a/src/protocols/HyprlandSurface.cpp +++ b/src/protocols/HyprlandSurface.cpp @@ -3,6 +3,8 @@ #include "../render/Renderer.hpp" #include "core/Compositor.hpp" #include "hyprland-surface-v1.hpp" +#include +#include CHyprlandSurface::CHyprlandSurface(SP resource, SP surface) : m_pSurface(surface) { setResource(std::move(resource)); @@ -36,11 +38,25 @@ void CHyprlandSurface::setResource(SP resource) { m_fOpacity = fOpacity; }); + m_pResource->setSetVisibleRegion([this](CHyprlandSurfaceV1* resource, wl_resource* region) { + if (!region) { + if (!m_visibleRegion.empty()) + m_bVisibleRegionChanged = true; + + m_visibleRegion.clear(); + return; + } + + m_bVisibleRegionChanged = true; + m_visibleRegion = CWLRegionResource::fromResource(region)->region; + }); + listeners.surfaceCommitted = m_pSurface->events.commit.registerListener([this](std::any data) { auto surface = CWLSurface::fromResource(m_pSurface.lock()); - if (surface && surface->m_fOverallOpacity != m_fOpacity) { + if (surface && (surface->m_fOverallOpacity != m_fOpacity || m_bVisibleRegionChanged)) { surface->m_fOverallOpacity = m_fOpacity; + surface->m_visibleRegion = m_visibleRegion; auto box = surface->getSurfaceBoxGlobal(); if (box.has_value()) @@ -61,6 +77,11 @@ void CHyprlandSurface::destroy() { m_pResource.reset(); m_fOpacity = 1.F; + if (!m_visibleRegion.empty()) + m_bVisibleRegionChanged = true; + + m_visibleRegion.clear(); + if (!m_pSurface) PROTO::hyprlandSurface->destroySurface(this); } diff --git a/src/protocols/HyprlandSurface.hpp b/src/protocols/HyprlandSurface.hpp index a5812b89..5c1181c4 100644 --- a/src/protocols/HyprlandSurface.hpp +++ b/src/protocols/HyprlandSurface.hpp @@ -1,5 +1,6 @@ #pragma once +#include #include #include #include "WaylandProtocol.hpp" @@ -19,7 +20,9 @@ class CHyprlandSurface { private: SP m_pResource; WP m_pSurface; - float m_fOpacity = 1.0; + float m_fOpacity = 1.0; + bool m_bVisibleRegionChanged = false; + CRegion m_visibleRegion; void destroy(); diff --git a/src/render/OpenGL.cpp b/src/render/OpenGL.cpp index ceb94c81..8ae667d2 100644 --- a/src/render/OpenGL.cpp +++ b/src/render/OpenGL.cpp @@ -1556,9 +1556,15 @@ void CHyprOpenGLImpl::renderTextureInternalWithDamage(SP tex, CBox* pB glEnableVertexAttribArray(shader->posAttrib); glEnableVertexAttribArray(shader->texAttrib); - if (m_RenderData.clipBox.width != 0 && m_RenderData.clipBox.height != 0) { - CRegion damageClip{m_RenderData.clipBox.x, m_RenderData.clipBox.y, m_RenderData.clipBox.width, m_RenderData.clipBox.height}; - damageClip.intersect(damage); + if (!m_RenderData.clipBox.empty() || !m_RenderData.clipRegion.empty()) { + CRegion damageClip = m_RenderData.clipBox; + + if (!m_RenderData.clipRegion.empty()) { + if (m_RenderData.clipBox.empty()) + damageClip = m_RenderData.clipRegion; + else + damageClip.intersect(m_RenderData.clipRegion); + } if (!damageClip.empty()) { for (auto const& RECT : damageClip.getRects()) { @@ -2079,6 +2085,11 @@ void CHyprOpenGLImpl::renderTextureWithBlur(SP tex, CBox* pBox, float CRegion texDamage{m_RenderData.damage}; texDamage.intersect(pBox->x, pBox->y, pBox->width, pBox->height); + // While renderTextureInternalWithDamage will clip the blur as well, + // clipping texDamage here allows blur generation to be optimized. + if (!m_RenderData.clipRegion.empty()) + texDamage.intersect(m_RenderData.clipRegion); + if (texDamage.empty()) return; diff --git a/src/render/OpenGL.hpp b/src/render/OpenGL.hpp index 3dc3b43a..fd84d478 100644 --- a/src/render/OpenGL.hpp +++ b/src/render/OpenGL.hpp @@ -133,6 +133,7 @@ struct SCurrentRenderData { Vector2D primarySurfaceUVBottomRight = Vector2D(-1, -1); CBox clipBox = {}; // scaled coordinates + CRegion clipRegion; uint32_t discardMode = DISCARD_OPAQUE; float discardOpacity = 0.f; diff --git a/src/render/pass/SurfacePassElement.cpp b/src/render/pass/SurfacePassElement.cpp index d720081f..b79407c8 100644 --- a/src/render/pass/SurfacePassElement.cpp +++ b/src/render/pass/SurfacePassElement.cpp @@ -7,6 +7,8 @@ #include "../../managers/input/InputManager.hpp" #include "../Renderer.hpp" +#include +#include #include using namespace Hyprutils::Utils; @@ -28,6 +30,7 @@ void CSurfacePassElement::draw(const CRegion& damage) { g_pHyprOpenGL->m_RenderData.primarySurfaceUVBottomRight = Vector2D(-1, -1); g_pHyprOpenGL->m_RenderData.useNearestNeighbor = false; g_pHyprOpenGL->m_RenderData.clipBox = {}; + g_pHyprOpenGL->m_RenderData.clipRegion = {}; g_pHyprOpenGL->m_RenderData.discardMode = 0; g_pHyprOpenGL->m_RenderData.discardOpacity = 0; g_pHyprOpenGL->m_RenderData.useNearestNeighbor = false; @@ -84,6 +87,11 @@ void CSurfacePassElement::draw(const CRegion& damage) { Debug::log(TRACE, "FIXME: rendering surface with color management enabled, should apply necessary transformations"); g_pHyprRenderer->calculateUVForSurface(data.pWindow, data.surface, data.pMonitor->self.lock(), data.mainSurface, windowBox.size(), PROJSIZEUNSCALED, MISALIGNEDFSV1); + auto cancelRender = false; + g_pHyprOpenGL->m_RenderData.clipRegion = visibleRegion(cancelRender); + if (cancelRender) + return; + // check for fractional scale surfaces misaligning the buffer size // in those cases it's better to just force nearest neighbor // as long as the window is not animated. During those it'd look weird. @@ -229,6 +237,48 @@ CRegion CSurfacePassElement::opaqueRegion() { return data.texture && data.texture->m_bOpaque ? boundingBox()->expand(-data.rounding) : CRegion{}; } +CRegion CSurfacePassElement::visibleRegion(bool& cancel) { + auto PSURFACE = CWLSurface::fromResource(data.surface); + if (!PSURFACE) + return {}; + + const auto& bufferSize = data.surface->current.bufferSize; + + auto visibleRegion = PSURFACE->m_visibleRegion.copy(); + if (visibleRegion.empty()) + return {}; + + visibleRegion.intersect(CBox(Vector2D(), bufferSize)); + + if (visibleRegion.empty()) { + cancel = true; + return visibleRegion; + } + + // deal with any rounding errors that might come from scaling + visibleRegion.expand(1); + + auto uvTL = g_pHyprOpenGL->m_RenderData.primarySurfaceUVTopLeft; + auto uvBR = g_pHyprOpenGL->m_RenderData.primarySurfaceUVBottomRight; + + if (uvTL == Vector2D(-1, -1)) + uvTL = Vector2D(0, 0); + + if (uvBR == Vector2D(-1, -1)) + uvBR = Vector2D(1, 1); + + visibleRegion.translate(-uvTL * bufferSize); + + auto texBox = getTexBox(); + texBox.scale(data.pMonitor->scale); + texBox.round(); + + visibleRegion.scale((Vector2D(1, 1) / (uvBR - uvTL)) * (texBox.size() / bufferSize)); + visibleRegion.translate((data.pos + data.localPos) * data.pMonitor->scale - data.pMonitor->vecPosition); + + return visibleRegion; +} + void CSurfacePassElement::discard() { if (!g_pHyprRenderer->m_bBlockSurfaceFeedback) { Debug::log(TRACE, "discard for invisible surface"); diff --git a/src/render/pass/SurfacePassElement.hpp b/src/render/pass/SurfacePassElement.hpp index 12387367..1b6ddb0b 100644 --- a/src/render/pass/SurfacePassElement.hpp +++ b/src/render/pass/SurfacePassElement.hpp @@ -57,6 +57,7 @@ class CSurfacePassElement : public IPassElement { virtual std::optional boundingBox(); virtual CRegion opaqueRegion(); virtual void discard(); + CRegion visibleRegion(bool& cancel); virtual const char* passName() { return "CSurfacePassElement"; diff --git a/subprojects/hyprland-protocols b/subprojects/hyprland-protocols index 455c0558..4c75dd5c 160000 --- a/subprojects/hyprland-protocols +++ b/subprojects/hyprland-protocols @@ -1 +1 @@ -Subproject commit 455c055883d9639d4fcbfcedb4c6d12ce313791e +Subproject commit 4c75dd5c015c8a0e5a34c6d02a018a650f57feb5 From a8c2d5a616b2ac9c0cf66a0bc999ae57338b60d9 Mon Sep 17 00:00:00 2001 From: Vaxry Date: Thu, 23 Jan 2025 22:15:09 +0000 Subject: [PATCH 0889/2181] layout: damage window properly on float mode changes fixes #8849 --- src/layout/IHyprLayout.cpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/layout/IHyprLayout.cpp b/src/layout/IHyprLayout.cpp index 576d80eb..9fc84b22 100644 --- a/src/layout/IHyprLayout.cpp +++ b/src/layout/IHyprLayout.cpp @@ -717,6 +717,8 @@ void IHyprLayout::changeWindowFloatingMode(PHLWINDOW pWindow) { pWindow->m_bPinned = false; + g_pHyprRenderer->damageWindow(pWindow); + const auto TILED = isWindowTiled(pWindow); // event @@ -788,6 +790,8 @@ void IHyprLayout::changeWindowFloatingMode(PHLWINDOW pWindow) { g_pCompositor->updateWindowAnimatedDecorationValues(pWindow); pWindow->updateToplevel(); + + g_pHyprRenderer->damageWindow(pWindow); } void IHyprLayout::moveActiveWindow(const Vector2D& delta, PHLWINDOW pWindow) { From dadb2e0949e61d43ace69c5ae65358c6c38e32b4 Mon Sep 17 00:00:00 2001 From: Vaxry Date: Thu, 23 Jan 2025 22:41:46 +0000 Subject: [PATCH 0890/2181] opengl: use uv to avoid rendering the entire blurbox additionally can use smoothing for rounding fixes #9086 --- src/render/OpenGL.cpp | 17 +++++++++++++---- 1 file changed, 13 insertions(+), 4 deletions(-) diff --git a/src/render/OpenGL.cpp b/src/render/OpenGL.cpp index 8ae667d2..0fe9565f 100644 --- a/src/render/OpenGL.cpp +++ b/src/render/OpenGL.cpp @@ -1547,11 +1547,10 @@ void CHyprOpenGLImpl::renderTextureInternalWithDamage(SP tex, CBox* pB glVertexAttribPointer(shader->posAttrib, 2, GL_FLOAT, GL_FALSE, 0, fullVerts); - if (allowCustomUV && m_RenderData.primarySurfaceUVTopLeft != Vector2D(-1, -1)) { + if (allowCustomUV && m_RenderData.primarySurfaceUVTopLeft != Vector2D(-1, -1)) glVertexAttribPointer(shader->texAttrib, 2, GL_FLOAT, GL_FALSE, 0, verts); - } else { + else glVertexAttribPointer(shader->texAttrib, 2, GL_FLOAT, GL_FALSE, 0, fullVerts); - } glEnableVertexAttribArray(shader->posAttrib); glEnableVertexAttribArray(shader->texAttrib); @@ -2156,15 +2155,25 @@ void CHyprOpenGLImpl::renderTextureWithBlur(SP tex, CBox* pBox, float // stencil done. Render everything. CBox MONITORBOX = {0, 0, m_RenderData.pMonitor->vecTransformedSize.x, m_RenderData.pMonitor->vecTransformedSize.y}; // render our great blurred FB + // calculate the uv for it + const auto LASTTL = m_RenderData.primarySurfaceUVTopLeft; + const auto LASTBR = m_RenderData.primarySurfaceUVBottomRight; + + m_RenderData.primarySurfaceUVTopLeft = pBox->pos() / MONITORBOX.size(); + m_RenderData.primarySurfaceUVBottomRight = (pBox->pos() + pBox->size()) / MONITORBOX.size(); + static auto PBLURIGNOREOPACITY = CConfigValue("decoration:blur:ignore_opacity"); setMonitorTransformEnabled(true); if (!USENEWOPTIMIZE) setRenderModifEnabled(false); - renderTextureInternalWithDamage(POUTFB->getTexture(), &MONITORBOX, (*PBLURIGNOREOPACITY ? blurA : a * blurA) * overallA, texDamage, 0, 2.0f, false, false, false); + renderTextureInternalWithDamage(POUTFB->getTexture(), pBox, (*PBLURIGNOREOPACITY ? blurA : a * blurA) * overallA, texDamage, round, roundingPower, false, false, true); if (!USENEWOPTIMIZE) setRenderModifEnabled(true); setMonitorTransformEnabled(false); + m_RenderData.primarySurfaceUVTopLeft = LASTTL; + m_RenderData.primarySurfaceUVBottomRight = LASTBR; + // render the window, but clear stencil glClearStencil(0); glClear(GL_STENCIL_BUFFER_BIT); From bb099e5733ae92c1b563efdb32d3d56a1540ab4a Mon Sep 17 00:00:00 2001 From: Vaxry Date: Thu, 23 Jan 2025 22:57:14 +0000 Subject: [PATCH 0891/2181] pass/rect: fix box shrinking with bb fixes #9084 --- src/render/pass/RectPassElement.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/render/pass/RectPassElement.cpp b/src/render/pass/RectPassElement.cpp index a57c959e..fe2f1f78 100644 --- a/src/render/pass/RectPassElement.cpp +++ b/src/render/pass/RectPassElement.cpp @@ -24,7 +24,7 @@ bool CRectPassElement::needsPrecomputeBlur() { } std::optional CRectPassElement::boundingBox() { - return data.box.expand(-data.round); + return data.box.copy().expand(-data.round); } CRegion CRectPassElement::opaqueRegion() { From d075d1cab9e8836be4544229486fec004236f3fa Mon Sep 17 00:00:00 2001 From: Vaxry Date: Thu, 23 Jan 2025 22:59:06 +0000 Subject: [PATCH 0892/2181] pass/rect: fix bounding box --- src/render/pass/RectPassElement.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/render/pass/RectPassElement.cpp b/src/render/pass/RectPassElement.cpp index fe2f1f78..55471e78 100644 --- a/src/render/pass/RectPassElement.cpp +++ b/src/render/pass/RectPassElement.cpp @@ -24,9 +24,9 @@ bool CRectPassElement::needsPrecomputeBlur() { } std::optional CRectPassElement::boundingBox() { - return data.box.copy().expand(-data.round); + return data.box; } CRegion CRectPassElement::opaqueRegion() { - return data.color.a >= 1.F ? *boundingBox() : CRegion{}; + return data.color.a >= 1.F ? boundingBox()->expand(-data.round) : CRegion{}; } From 5d8261aee243fd1bd53f9e0eb27f1a460eac83d6 Mon Sep 17 00:00:00 2001 From: Vaxry Date: Fri, 24 Jan 2025 00:25:14 +0000 Subject: [PATCH 0893/2181] xwayland: avoid sending value of real size to xwayland --- src/managers/XWaylandManager.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/managers/XWaylandManager.cpp b/src/managers/XWaylandManager.cpp index ab0bfb88..5a933236 100644 --- a/src/managers/XWaylandManager.cpp +++ b/src/managers/XWaylandManager.cpp @@ -55,7 +55,7 @@ void CHyprXWaylandManager::activateWindow(PHLWINDOW pWindow, bool activate) { if (pWindow->m_bIsX11) { if (activate) { - setWindowSize(pWindow, pWindow->m_vRealSize->value()); // update xwayland output pos + setWindowSize(pWindow, pWindow->m_vRealSize->goal()); // update xwayland output pos pWindow->m_pXWaylandSurface->setMinimized(false); if (!pWindow->isX11OverrideRedirect()) From 4a1b960cbedb3e2893eeadecdf2b4a7314634306 Mon Sep 17 00:00:00 2001 From: Vaxry Date: Fri, 24 Jan 2025 00:49:47 +0000 Subject: [PATCH 0894/2181] layout: set window size after toggling floating --- src/layout/IHyprLayout.cpp | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/layout/IHyprLayout.cpp b/src/layout/IHyprLayout.cpp index 9fc84b22..49633d94 100644 --- a/src/layout/IHyprLayout.cpp +++ b/src/layout/IHyprLayout.cpp @@ -788,9 +788,8 @@ void IHyprLayout::changeWindowFloatingMode(PHLWINDOW pWindow) { } g_pCompositor->updateWindowAnimatedDecorationValues(pWindow); - pWindow->updateToplevel(); - + g_pXWaylandManager->setWindowSize(pWindow, pWindow->m_vRealSize->goal()); g_pHyprRenderer->damageWindow(pWindow); } From 944e36ea2e71db20cf3f8b2e5cbf978a5bf5268b Mon Sep 17 00:00:00 2001 From: Vaxry Date: Fri, 24 Jan 2025 13:23:23 +0000 Subject: [PATCH 0895/2181] config: fix misc:disable_autoreload fixes #9139 --- src/config/ConfigManager.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/config/ConfigManager.cpp b/src/config/ConfigManager.cpp index b0665db9..f5c9b3ee 100644 --- a/src/config/ConfigManager.cpp +++ b/src/config/ConfigManager.cpp @@ -897,9 +897,10 @@ std::optional CConfigManager::resetHLConfig() { void CConfigManager::postConfigReload(const Hyprlang::CParseResult& result) { static const auto PENABLEEXPLICIT = CConfigValue("render:explicit_sync"); + static const auto PDISABLEAUTORELOAD = CConfigValue("misc:disable_autoreload"); static int prevEnabledExplicit = *PENABLEEXPLICIT; - g_pConfigWatcher->setWatchList(m_configPaths); + g_pConfigWatcher->setWatchList(*PDISABLEAUTORELOAD ? std::vector{} : m_configPaths); for (auto const& w : g_pCompositor->m_vWindows) { w->uncacheWindowDecos(); From 57a39984dddd00fd1aca436e149b7566e5e48d95 Mon Sep 17 00:00:00 2001 From: Vaxry Date: Fri, 24 Jan 2025 13:37:23 +0000 Subject: [PATCH 0896/2181] input: abord dnd op on escape pressed ref #9154 --- src/managers/KeybindManager.cpp | 4 ++++ src/protocols/core/DataDevice.cpp | 6 ++++++ src/protocols/core/DataDevice.hpp | 3 +++ 3 files changed, 13 insertions(+) diff --git a/src/managers/KeybindManager.cpp b/src/managers/KeybindManager.cpp index f4a55a73..4706c1e1 100644 --- a/src/managers/KeybindManager.cpp +++ b/src/managers/KeybindManager.cpp @@ -4,6 +4,7 @@ #include "../protocols/LayerShell.hpp" #include "../protocols/ShortcutsInhibit.hpp" #include "../protocols/GlobalShortcuts.hpp" +#include "../protocols/core/DataDevice.hpp" #include "../render/decorations/CHyprGroupBarDecoration.hpp" #include "KeybindManager.hpp" #include "PointerManager.hpp" @@ -432,6 +433,9 @@ bool CKeybindManager::onKeyEvent(std::any event, SP pKeyboard) { const xkb_keysym_t keysym = xkb_state_key_get_one_sym(pKeyboard->resolveBindsBySym ? pKeyboard->xkbSymState : m_pXKBTranslationState, KEYCODE); const xkb_keysym_t internalKeysym = xkb_state_key_get_one_sym(pKeyboard->xkbState, KEYCODE); + if (keysym == XKB_KEY_Escape || internalKeysym == XKB_KEY_Escape) + PROTO::data->abortDndIfPresent(); + // handleInternalKeybinds returns true when the key should be suppressed, // while this function returns true when the key event should be sent if (handleInternalKeybinds(internalKeysym)) diff --git a/src/protocols/core/DataDevice.cpp b/src/protocols/core/DataDevice.cpp index ade16498..36437dd4 100644 --- a/src/protocols/core/DataDevice.cpp +++ b/src/protocols/core/DataDevice.cpp @@ -814,3 +814,9 @@ void CWLDataDeviceProtocol::renderDND(PHLMONITOR pMonitor, timespec* when) { bool CWLDataDeviceProtocol::dndActive() { return dnd.currentSource; } + +void CWLDataDeviceProtocol::abortDndIfPresent() { + if (!dndActive()) + return; + abortDrag(); +} diff --git a/src/protocols/core/DataDevice.hpp b/src/protocols/core/DataDevice.hpp index 5101862e..d8bc2b9c 100644 --- a/src/protocols/core/DataDevice.hpp +++ b/src/protocols/core/DataDevice.hpp @@ -144,6 +144,9 @@ class CWLDataDeviceProtocol : public IWaylandProtocol { // TODO: move handling to seatmgr bool dndActive(); + // called on an escape key pressed, for moments where it gets stuck + void abortDndIfPresent(); + private: void destroyResource(CWLDataDeviceManagerResource* resource); void destroyResource(CWLDataDeviceResource* resource); From 0e5d03a5574efb78f06f2723b345bac867d98696 Mon Sep 17 00:00:00 2001 From: Maximilian Seidler <78690852+PaideiaDilemma@users.noreply.github.com> Date: Fri, 24 Jan 2025 15:50:15 +0000 Subject: [PATCH 0897/2181] datadevice: do the unfocus surface stuff before dndActive is true (#9157) --- src/managers/SeatManager.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/managers/SeatManager.cpp b/src/managers/SeatManager.cpp index 8fee6b16..6d2b906f 100644 --- a/src/managers/SeatManager.cpp +++ b/src/managers/SeatManager.cpp @@ -194,7 +194,7 @@ void CSeatManager::setPointerFocus(SP surf, const Vector2D& if (state.pointerFocus == surf) return; - if (PROTO::data->dndActive()) { + if (PROTO::data->dndActive() && surf) { if (state.dndPointerFocus == surf) return; Debug::log(LOG, "[seatmgr] Refusing pointer focus during an active dnd, but setting dndPointerFocus"); From 9b3f71390c3db14fd2fa2ff14d533eee34538c55 Mon Sep 17 00:00:00 2001 From: heather7283 <142042427+heather7283@users.noreply.github.com> Date: Fri, 24 Jan 2025 19:51:31 +0400 Subject: [PATCH 0898/2181] layershell: check if layer is valid (#9156) fixes compositor crash when client tried to create a layer surface with invalid layer argument --- src/protocols/LayerShell.cpp | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/protocols/LayerShell.cpp b/src/protocols/LayerShell.cpp index 1533a7c0..c88dc925 100644 --- a/src/protocols/LayerShell.cpp +++ b/src/protocols/LayerShell.cpp @@ -233,6 +233,11 @@ void CLayerShellProtocol::onGetLayerSurface(CZwlrLayerShellV1* pMgr, uint32_t id return; } + if UNLIKELY (layer > ZWLR_LAYER_SHELL_V1_LAYER_OVERLAY) { + pMgr->error(ZWLR_LAYER_SHELL_V1_ERROR_INVALID_LAYER, "Invalid layer"); + return; + } + const auto RESOURCE = m_vLayers.emplace_back(makeShared(makeShared(CLIENT, pMgr->version(), id), SURF, namespace_, PMONITOR, layer)); if UNLIKELY (!RESOURCE->good()) { From fda9790cde5eb2bd15c19a1e67211eabbebf9024 Mon Sep 17 00:00:00 2001 From: Vaxry Date: Fri, 24 Jan 2025 17:51:11 +0000 Subject: [PATCH 0899/2181] layout: force full damage on toggling floating mode fixes #8849 --- src/layout/IHyprLayout.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/layout/IHyprLayout.cpp b/src/layout/IHyprLayout.cpp index 49633d94..ffc08e46 100644 --- a/src/layout/IHyprLayout.cpp +++ b/src/layout/IHyprLayout.cpp @@ -717,7 +717,7 @@ void IHyprLayout::changeWindowFloatingMode(PHLWINDOW pWindow) { pWindow->m_bPinned = false; - g_pHyprRenderer->damageWindow(pWindow); + g_pHyprRenderer->damageWindow(pWindow, true); const auto TILED = isWindowTiled(pWindow); From 80b2fd135b45f2c2e41ceb312314908f6a3e7b30 Mon Sep 17 00:00:00 2001 From: Maximilian Seidler <78690852+PaideiaDilemma@users.noreply.github.com> Date: Fri, 24 Jan 2025 18:22:05 +0000 Subject: [PATCH 0900/2181] animations: fix borderangle once (#9149) --- src/Compositor.cpp | 5 +---- src/desktop/Window.cpp | 8 ++++++++ src/desktop/Window.hpp | 1 + 3 files changed, 10 insertions(+), 4 deletions(-) diff --git a/src/Compositor.cpp b/src/Compositor.cpp index aeec2830..cb0665e5 100644 --- a/src/Compositor.cpp +++ b/src/Compositor.cpp @@ -1155,6 +1155,7 @@ void CCompositor::focusWindow(PHLWINDOW pWindow, SP pSurface g_pXWaylandManager->activateWindow(pWindow, true); // sets the m_pLastWindow pWindow->updateDynamicRules(); + pWindow->onFocusAnimUpdate(); updateWindowAnimatedDecorationValues(pWindow); @@ -1851,10 +1852,6 @@ void CCompositor::updateWindowAnimatedDecorationValues(PHLWINDOW pWindow) { } } - // tick angle if it's not running (aka dead) - if (!pWindow->m_fBorderAngleAnimationProgress->isBeingAnimated()) - pWindow->m_fBorderAngleAnimationProgress->setValueAndWarp(0.f); - // opacity const auto PWORKSPACE = pWindow->m_pWorkspace; if (pWindow->isEffectiveInternalFSMode(FSMODE_FULLSCREEN)) { diff --git a/src/desktop/Window.cpp b/src/desktop/Window.cpp index fb5904be..5306bbb4 100644 --- a/src/desktop/Window.cpp +++ b/src/desktop/Window.cpp @@ -1274,6 +1274,14 @@ void CWindow::onWorkspaceAnimUpdate() { m_vFloatingOffset = offset; } +void CWindow::onFocusAnimUpdate() { + // borderangle once + if (m_fBorderAngleAnimationProgress->enabled() && !m_fBorderAngleAnimationProgress->isBeingAnimated()) { + m_fBorderAngleAnimationProgress->setValueAndWarp(0.f); + *m_fBorderAngleAnimationProgress = 1.f; + } +} + int CWindow::popupsCount() { if (m_bIsX11) return 0; diff --git a/src/desktop/Window.hpp b/src/desktop/Window.hpp index 5b4ad654..cff13b03 100644 --- a/src/desktop/Window.hpp +++ b/src/desktop/Window.hpp @@ -454,6 +454,7 @@ class CWindow { void switchWithWindowInGroup(PHLWINDOW pWindow); void setAnimationsToMove(); void onWorkspaceAnimUpdate(); + void onFocusAnimUpdate(); void onUpdateState(); void onUpdateMeta(); void onX11Configure(CBox box); From d8f79d7678f428738f3173020109bd7b7fbd0840 Mon Sep 17 00:00:00 2001 From: Vaxry Date: Fri, 24 Jan 2025 20:30:12 +0000 Subject: [PATCH 0901/2181] core: add --verify-config to verify the config with Hyprland fixes #9135 --- src/Compositor.cpp | 18 ++++++++++++++++-- src/Compositor.hpp | 11 ++++++----- src/config/ConfigManager.cpp | 30 +++++++++++++++++++++++------- src/config/ConfigManager.hpp | 8 +++++--- src/main.cpp | 17 ++++++++++++----- src/managers/AnimationManager.cpp | 3 ++- src/managers/KeybindManager.cpp | 7 +++++-- 7 files changed, 69 insertions(+), 25 deletions(-) diff --git a/src/Compositor.cpp b/src/Compositor.cpp index cb0665e5..ab9c16f7 100644 --- a/src/Compositor.cpp +++ b/src/Compositor.cpp @@ -22,6 +22,7 @@ #include #include #include +#include #include #include "debug/HyprCtl.hpp" #include "debug/CrashReporter.hpp" @@ -162,7 +163,10 @@ void CCompositor::restoreNofile() { Debug::log(ERR, "Failed restoring NOFILE limits"); } -CCompositor::CCompositor() : m_iHyprlandPID(getpid()) { +CCompositor::CCompositor(bool onlyConfig) : m_bOnlyConfigVerification(onlyConfig), m_iHyprlandPID(getpid()) { + if (onlyConfig) + return; + m_szHyprTempDataRoot = std::string{getenv("XDG_RUNTIME_DIR")} + "/hypr"; if (m_szHyprTempDataRoot.starts_with("/hypr")) { @@ -226,7 +230,7 @@ CCompositor::CCompositor() : m_iHyprlandPID(getpid()) { } CCompositor::~CCompositor() { - if (!m_bIsShuttingDown) + if (!m_bIsShuttingDown && !m_bOnlyConfigVerification) cleanup(); } @@ -262,6 +266,16 @@ static bool filterGlobals(const wl_client* client, const wl_global* global, void // void CCompositor::initServer(std::string socketName, int socketFd) { + if (m_bOnlyConfigVerification) { + g_pHookSystem = makeUnique(); + g_pKeybindManager = makeUnique(); + g_pAnimationManager = makeUnique(); + g_pConfigManager = makeUnique(); + + std::println("\n\n======== Config parsing result:\n\n{}", g_pConfigManager->verify()); + return; + } + m_sWLDisplay = wl_display_create(); wl_display_set_global_filter(m_sWLDisplay, ::filterGlobals, nullptr); diff --git a/src/Compositor.hpp b/src/Compositor.hpp index f2e2ca14..295878df 100644 --- a/src/Compositor.hpp +++ b/src/Compositor.hpp @@ -24,7 +24,7 @@ enum eManagersInitStage : uint8_t { class CCompositor { public: - CCompositor(); + CCompositor(bool onlyConfig = false); ~CCompositor(); wl_display* m_sWLDisplay; @@ -71,10 +71,11 @@ class CCompositor { bool m_bUnsafeState = false; // unsafe state is when there is no monitors. bool m_bNextIsUnsafe = false; PHLMONITORREF m_pUnsafeOutput; // fallback output for the unsafe state - bool m_bIsShuttingDown = false; - bool m_bFinalRequests = false; - bool m_bDesktopEnvSet = false; - bool m_bWantsXwayland = true; + bool m_bIsShuttingDown = false; + bool m_bFinalRequests = false; + bool m_bDesktopEnvSet = false; + bool m_bWantsXwayland = true; + bool m_bOnlyConfigVerification = false; // ------------------------------------------------- // diff --git a/src/config/ConfigManager.cpp b/src/config/ConfigManager.cpp index f5c9b3ee..c5d70329 100644 --- a/src/config/ConfigManager.cpp +++ b/src/config/ConfigManager.cpp @@ -19,6 +19,7 @@ #include "../render/Renderer.hpp" #include "../hyprerror/HyprError.hpp" #include "../managers/input/InputManager.hpp" +#include "../managers/eventLoop/EventLoopManager.hpp" #include "../managers/LayoutManager.hpp" #include "../managers/EventManager.hpp" #include "../debug/HyprNotificationOverlay.hpp" @@ -730,15 +731,18 @@ CConfigManager::CConfigManager() { resetHLConfig(); - Debug::log(INFO, - "!!!!HEY YOU, YES YOU!!!!: further logs to stdout / logfile are disabled by default. BEFORE SENDING THIS LOG, ENABLE THEM. Use debug:disable_logs = false to do so: " - "https://wiki.hyprland.org/Configuring/Variables/#debug"); + if (!g_pCompositor->m_bOnlyConfigVerification) { + Debug::log( + INFO, + "!!!!HEY YOU, YES YOU!!!!: further logs to stdout / logfile are disabled by default. BEFORE SENDING THIS LOG, ENABLE THEM. Use debug:disable_logs = false to do so: " + "https://wiki.hyprland.org/Configuring/Variables/#debug"); + } Debug::disableLogs = reinterpret_cast(m_pConfig->getConfigValuePtr("debug:disable_logs")->getDataStaticPtr()); Debug::disableTime = reinterpret_cast(m_pConfig->getConfigValuePtr("debug:disable_time")->getDataStaticPtr()); - if (ERR.has_value()) - g_pHyprError->queueCreate(ERR.value(), CHyprColor{1.0, 0.1, 0.1, 1.0}); + if (g_pEventLoopManager && ERR.has_value()) + g_pEventLoopManager->doLater([ERR] { g_pHyprError->queueCreate(ERR.value(), CHyprColor{1.0, 0.1, 0.1, 1.0}); }); } std::optional CConfigManager::generateConfig(std::string configPath) { @@ -820,11 +824,23 @@ void CConfigManager::reload() { EMIT_HOOK_EVENT("preConfigReload", nullptr); setDefaultAnimationVars(); resetHLConfig(); - configCurrentPath = getMainConfigPath(); - const auto ERR = m_pConfig->parse(); + configCurrentPath = getMainConfigPath(); + const auto ERR = m_pConfig->parse(); + m_bLastConfigVerificationWasSuccessful = !ERR.error; postConfigReload(ERR); } +std::string CConfigManager::verify() { + setDefaultAnimationVars(); + resetHLConfig(); + configCurrentPath = getMainConfigPath(); + const auto ERR = m_pConfig->parse(); + m_bLastConfigVerificationWasSuccessful = !ERR.error; + if (ERR.error) + return ERR.getError(); + return "config ok"; +} + void CConfigManager::setDefaultAnimationVars() { m_AnimationTree.createNode("__internal_fadeCTM"); m_AnimationTree.createNode("global"); diff --git a/src/config/ConfigManager.hpp b/src/config/ConfigManager.hpp index 31ad81cd..564c1ebf 100644 --- a/src/config/ConfigManager.hpp +++ b/src/config/ConfigManager.hpp @@ -144,6 +144,7 @@ class CConfigManager { void init(); void reload(); + std::string verify(); int getDeviceInt(const std::string&, const std::string&, const std::string& fallback = ""); float getDeviceFloat(const std::string&, const std::string&, const std::string& fallback = ""); @@ -257,9 +258,10 @@ class CConfigManager { {"scrollmouse", [](const PHLWINDOW& pWindow) { return &pWindow->m_sWindowData.scrollMouse; }}, {"scrolltouchpad", [](const PHLWINDOW& pWindow) { return &pWindow->m_sWindowData.scrollTouchpad; }}}; - bool m_bWantsMonitorReload = false; - bool m_bNoMonitorReload = false; - bool isLaunchingExecOnce = false; // For exec-once to skip initial ws tracking + bool m_bWantsMonitorReload = false; + bool m_bNoMonitorReload = false; + bool isLaunchingExecOnce = false; // For exec-once to skip initial ws tracking + bool m_bLastConfigVerificationWasSuccessful = true; private: UP m_pConfig; diff --git a/src/main.cpp b/src/main.cpp index bb5e5622..d244f10f 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -27,6 +27,7 @@ static void help() { --wayland-fd FD - Sets the Wayland socket fd (for Wayland socket handover) --systeminfo - Prints system infos --i-am-really-stupid - Omits root user privileges check (why would you do that?) + --verify-config - Do not run Hyprland, only print if the config has any errors --version -v - Print this binary's version)"); } @@ -49,7 +50,7 @@ int main(int argc, char** argv) { std::string configPath; std::string socketName; int socketFd = -1; - bool ignoreSudo = false; + bool ignoreSudo = false, verifyConfig = false; std::vector args{argv + 1, argv + argc}; @@ -124,6 +125,9 @@ int main(int argc, char** argv) { } else if (*it == "--systeminfo") { std::println("{}", systemInfoRequest(eHyprCtlOutputFormat::FORMAT_NORMAL, "")); return 0; + } else if (*it == "--verify-config") { + verifyConfig = true; + continue; } else { std::println(stderr, "[ ERROR ] Unknown option '{}' !", *it); help(); @@ -138,9 +142,8 @@ int main(int argc, char** argv) { " Hint: Use the --i-am-really-stupid flag to omit that check."); return 1; - } else if (ignoreSudo && NInit::isSudo()) { + } else if (ignoreSudo && NInit::isSudo()) std::println("Superuser privileges check is omitted. I hope you know what you're doing."); - } if (socketName.empty() ^ (socketFd == -1)) { std::println(stderr, @@ -150,12 +153,13 @@ int main(int argc, char** argv) { return 1; } - std::println("Welcome to Hyprland!"); + if (!verifyConfig) + std::println("Welcome to Hyprland!"); // let's init the compositor. // it initializes basic Wayland stuff in the constructor. try { - g_pCompositor = makeUnique(); + g_pCompositor = makeUnique(verifyConfig); g_pCompositor->explicitConfigPath = configPath; } catch (const std::exception& e) { std::println(stderr, "Hyprland threw in ctor: {}\nCannot continue.", e.what()); @@ -164,6 +168,9 @@ int main(int argc, char** argv) { g_pCompositor->initServer(socketName, socketFd); + if (verifyConfig) + return !g_pConfigManager->m_bLastConfigVerificationWasSuccessful; + if (!envEnabled("HYPRLAND_NO_RT")) NInit::gainRealTime(); diff --git a/src/managers/AnimationManager.cpp b/src/managers/AnimationManager.cpp index f884acdd..964f7cfa 100644 --- a/src/managers/AnimationManager.cpp +++ b/src/managers/AnimationManager.cpp @@ -34,7 +34,8 @@ static int wlTick(SP self, void* data) { CHyprAnimationManager::CHyprAnimationManager() { m_pAnimationTimer = SP(new CEventLoopTimer(std::chrono::microseconds(500), wlTick, nullptr)); - g_pEventLoopManager->addTimer(m_pAnimationTimer); + if (g_pEventLoopManager) // null in --verify-config mode + g_pEventLoopManager->addTimer(m_pAnimationTimer); addBezierWithName("linear", Vector2D(0.0, 0.0), Vector2D(1.0, 1.0)); } diff --git a/src/managers/KeybindManager.cpp b/src/managers/KeybindManager.cpp index 4706c1e1..e2191bc6 100644 --- a/src/managers/KeybindManager.cpp +++ b/src/managers/KeybindManager.cpp @@ -172,8 +172,11 @@ CKeybindManager::CKeybindManager() { }, nullptr); - g_pEventLoopManager->addTimer(m_pLongPressTimer); - g_pEventLoopManager->addTimer(m_pRepeatKeyTimer); + // null in --verify-config mode + if (g_pEventLoopManager) { + g_pEventLoopManager->addTimer(m_pLongPressTimer); + g_pEventLoopManager->addTimer(m_pRepeatKeyTimer); + } static auto P = g_pHookSystem->hookDynamic("configReloaded", [this](void* hk, SCallbackInfo& info, std::any param) { // clear cuz realloc'd From 1815f9a2e5e12cafa670e0f4f7eb10dc9436868c Mon Sep 17 00:00:00 2001 From: heather7283 <142042427+heather7283@users.noreply.github.com> Date: Sat, 25 Jan 2025 03:26:46 +0400 Subject: [PATCH 0902/2181] compositor: fix incorrect cast, use lambda capture instead (#9161) --- src/Compositor.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/Compositor.cpp b/src/Compositor.cpp index ab9c16f7..fa73be66 100644 --- a/src/Compositor.cpp +++ b/src/Compositor.cpp @@ -2519,13 +2519,13 @@ PHLLS CCompositor::getLayerSurfaceFromSurface(SP pSurface) { continue; ls->layerSurface->surface->breadthfirst( - [](SP surf, const Vector2D& offset, void* data) { - if (surf == ((std::pair, bool>*)data)->first) { - *(bool*)data = true; + [&result](SP surf, const Vector2D& offset, void* data) { + if (surf == result.first) { + result.second = true; return; } }, - &result); + nullptr); if (result.second) return ls; From 089fdd1ea0d991da5b068db51531f54c90a2df25 Mon Sep 17 00:00:00 2001 From: Maximilian Seidler <78690852+PaideiaDilemma@users.noreply.github.com> Date: Fri, 24 Jan 2025 23:27:24 +0000 Subject: [PATCH 0903/2181] window: only set m_iMonitorMovedFrom, when moving to a different monitor (#9160) --- src/Compositor.cpp | 1 - src/desktop/Window.cpp | 5 +++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/Compositor.cpp b/src/Compositor.cpp index fa73be66..e1ded6b6 100644 --- a/src/Compositor.cpp +++ b/src/Compositor.cpp @@ -1867,7 +1867,6 @@ void CCompositor::updateWindowAnimatedDecorationValues(PHLWINDOW pWindow) { } // opacity - const auto PWORKSPACE = pWindow->m_pWorkspace; if (pWindow->isEffectiveInternalFSMode(FSMODE_FULLSCREEN)) { *pWindow->m_fActiveInactiveAlpha = pWindow->m_sWindowData.alphaFullscreen.valueOrDefault().applyAlpha(*PFULLSCREENALPHA); } else { diff --git a/src/desktop/Window.cpp b/src/desktop/Window.cpp index 5306bbb4..4be8fac5 100644 --- a/src/desktop/Window.cpp +++ b/src/desktop/Window.cpp @@ -420,12 +420,13 @@ void CWindow::moveToWorkspace(PHLWORKSPACE pWorkspace) { static auto PCLOSEONLASTSPECIAL = CConfigValue("misc:close_special_on_empty"); - const auto OLDWORKSPACE = m_pWorkspace; + const auto OLDWORKSPACE = m_pWorkspace; + const bool TOANOTHERMONITOR = OLDWORKSPACE && OLDWORKSPACE->monitorID() != pWorkspace->monitorID(); m_fMovingToWorkspaceAlpha->setValueAndWarp(1.F); *m_fMovingToWorkspaceAlpha = 0.F; m_fMovingToWorkspaceAlpha->setCallbackOnEnd([this](auto) { m_iMonitorMovedFrom = -1; }); - m_iMonitorMovedFrom = OLDWORKSPACE ? OLDWORKSPACE->monitorID() : -1; + m_iMonitorMovedFrom = TOANOTHERMONITOR ? OLDWORKSPACE->monitorID() : -1; m_pWorkspace = pWorkspace; From 354d4594de6a14e89ab337681dac2d898bc18cbf Mon Sep 17 00:00:00 2001 From: Vaxry Date: Sat, 25 Jan 2025 02:35:41 +0000 Subject: [PATCH 0904/2181] xwayland: various window handling fixes I hate this fucking garbage --- src/desktop/Window.cpp | 8 ++++---- src/events/Windows.cpp | 5 ++++- src/managers/XWaylandManager.cpp | 6 ++++-- 3 files changed, 12 insertions(+), 7 deletions(-) diff --git a/src/desktop/Window.cpp b/src/desktop/Window.cpp index 4be8fac5..97d7ecc0 100644 --- a/src/desktop/Window.cpp +++ b/src/desktop/Window.cpp @@ -1556,10 +1556,10 @@ void CWindow::onX11Configure(CBox box) { } } - m_vPosition = m_vRealPosition->value(); - m_vSize = m_vRealSize->value(); + m_vPosition = m_vRealPosition->goal(); + m_vSize = m_vRealSize->goal(); - m_pXWaylandSurface->configure(box); + g_pXWaylandManager->setWindowSize(m_pSelf.lock(), box.size(), true); m_vPendingReportedSize = box.size(); m_vReportedSize = box.size(); @@ -1569,7 +1569,7 @@ void CWindow::onX11Configure(CBox box) { if (!m_pWorkspace || !m_pWorkspace->isVisible()) return; // further things are only for visible windows - m_pWorkspace = g_pCompositor->getMonitorFromVector(m_vRealPosition->value() + m_vRealSize->value() / 2.f)->activeWorkspace; + m_pWorkspace = g_pCompositor->getMonitorFromVector(m_vRealPosition->goal() + m_vRealSize->goal() / 2.f)->activeWorkspace; g_pCompositor->changeWindowZOrder(m_pSelf.lock(), true); diff --git a/src/events/Windows.cpp b/src/events/Windows.cpp index cadd4cbc..525adc02 100644 --- a/src/events/Windows.cpp +++ b/src/events/Windows.cpp @@ -43,7 +43,7 @@ static void setVector2DAnimToMove(WP pav) { animvar->setConfig(g_pConfigManager->getAnimationPropertyConfig("windowsMove")); const auto PHLWINDOW = animvar->m_Context.pWindow.lock(); - if (PHLWINDOW && !PHLWINDOW->m_vRealPosition->isBeingAnimated() && !PHLWINDOW->m_vRealSize->isBeingAnimated()) + if (PHLWINDOW) PHLWINDOW->m_bAnimatingIn = false; } @@ -680,6 +680,9 @@ void Events::listener_mapWindow(void* owner, void* data) { if (PMONITOR && PWINDOW->isX11OverrideRedirect()) PWINDOW->m_fX11SurfaceScaledBy = PMONITOR->scale; + + if (!PWINDOW->isX11OverrideRedirect() && PWINDOW->m_bIsX11 && PWINDOW->m_bIsFloating) + g_pXWaylandManager->setWindowSize(PWINDOW, PWINDOW->m_vRealSize->goal(), true); } void Events::listener_unmapWindow(void* owner, void* data) { diff --git a/src/managers/XWaylandManager.cpp b/src/managers/XWaylandManager.cpp index 5a933236..8956cf3a 100644 --- a/src/managers/XWaylandManager.cpp +++ b/src/managers/XWaylandManager.cpp @@ -55,7 +55,7 @@ void CHyprXWaylandManager::activateWindow(PHLWINDOW pWindow, bool activate) { if (pWindow->m_bIsX11) { if (activate) { - setWindowSize(pWindow, pWindow->m_vRealSize->goal()); // update xwayland output pos + setWindowSize(pWindow, pWindow->m_vRealSize->value(), true); // update xwayland output pos pWindow->m_pXWaylandSurface->setMinimized(false); if (!pWindow->isX11OverrideRedirect()) @@ -162,7 +162,9 @@ bool CHyprXWaylandManager::shouldBeFloated(PHLWINDOW pWindow, bool pending) { if (a == HYPRATOMS["_NET_WM_WINDOW_TYPE_DROPDOWN_MENU"] || a == HYPRATOMS["_NET_WM_WINDOW_TYPE_MENU"]) pWindow->m_bX11ShouldntFocus = true; - pWindow->m_bNoInitialFocus = true; + if (a != HYPRATOMS["_NET_WM_WINDOW_TYPE_DIALOG"]) + pWindow->m_bNoInitialFocus = true; + return true; } From 065e89648b27017871c38831cf34def94feb72d6 Mon Sep 17 00:00:00 2001 From: Mihai Fufezan Date: Sat, 25 Jan 2025 15:33:27 +0200 Subject: [PATCH 0905/2181] flake.lock: update --- flake.lock | 91 ++++++++++++++++++++++++++++-------------------------- 1 file changed, 47 insertions(+), 44 deletions(-) diff --git a/flake.lock b/flake.lock index ed1702d1..34249b0a 100644 --- a/flake.lock +++ b/flake.lock @@ -181,11 +181,11 @@ ] }, "locked": { - "lastModified": 1737634810, - "narHash": "sha256-ZIJ03DeisbQuDaADSgmbgyocjecaozK4yGTa0/9bOr0=", + "lastModified": 1737811848, + "narHash": "sha256-WZ7LeiKHk5Y94MU5gHIWn0r8asWxYOvie4LqfCjVIZU=", "owner": "hyprwm", "repo": "hyprland-qtutils", - "rev": "a9852dbf5a1ec77cf617543728144c1362709e46", + "rev": "9c0831ff98856c0f312fcb8b57553fbe3dd34d5b", "type": "github" }, "original": { @@ -196,12 +196,17 @@ }, "hyprlang": { "inputs": { - "hyprutils": [ + "hyprutils": "hyprutils", + "nixpkgs": [ "hyprland-qtutils", - "hyprutils" + "hyprland-qt-support", + "nixpkgs" ], - "nixpkgs": "nixpkgs", - "systems": "systems" + "systems": [ + "hyprland-qtutils", + "hyprland-qt-support", + "systems" + ] }, "locked": { "lastModified": 1737634606, @@ -246,9 +251,15 @@ "hyprutils": { "inputs": { "nixpkgs": [ + "hyprland-qtutils", + "hyprland-qt-support", + "hyprlang", "nixpkgs" ], "systems": [ + "hyprland-qtutils", + "hyprland-qt-support", + "hyprlang", "systems" ] }, @@ -266,6 +277,29 @@ "type": "github" } }, + "hyprutils_2": { + "inputs": { + "nixpkgs": [ + "nixpkgs" + ], + "systems": [ + "systems" + ] + }, + "locked": { + "lastModified": 1737725508, + "narHash": "sha256-jGmcPc6y/prg/4A8KGYqJ27nSPaProCMiFadaxNAKvA=", + "owner": "hyprwm", + "repo": "hyprutils", + "rev": "fb0c2d1de3d1ef7396d19c18ac09e12bd956929e", + "type": "github" + }, + "original": { + "owner": "hyprwm", + "repo": "hyprutils", + "type": "github" + } + }, "hyprwayland-scanner": { "inputs": { "nixpkgs": [ @@ -291,27 +325,11 @@ }, "nixpkgs": { "locked": { - "lastModified": 1737469691, - "narHash": "sha256-nmKOgAU48S41dTPIXAq0AHZSehWUn6ZPrUKijHAMmIk=", + "lastModified": 1737632463, + "narHash": "sha256-38J9QfeGSej341ouwzqf77WIHAScihAKCt8PQJ+NH28=", "owner": "NixOS", "repo": "nixpkgs", - "rev": "9e4d5190a9482a1fb9d18adf0bdb83c6e506eaab", - "type": "github" - }, - "original": { - "owner": "NixOS", - "ref": "nixos-unstable", - "repo": "nixpkgs", - "type": "github" - } - }, - "nixpkgs_2": { - "locked": { - "lastModified": 1737469691, - "narHash": "sha256-nmKOgAU48S41dTPIXAq0AHZSehWUn6ZPrUKijHAMmIk=", - "owner": "NixOS", - "repo": "nixpkgs", - "rev": "9e4d5190a9482a1fb9d18adf0bdb83c6e506eaab", + "rev": "0aa475546ed21629c4f5bbf90e38c846a99ec9e9", "type": "github" }, "original": { @@ -351,11 +369,11 @@ "hyprland-protocols": "hyprland-protocols", "hyprland-qtutils": "hyprland-qtutils", "hyprlang": "hyprlang_2", - "hyprutils": "hyprutils", + "hyprutils": "hyprutils_2", "hyprwayland-scanner": "hyprwayland-scanner", - "nixpkgs": "nixpkgs_2", + "nixpkgs": "nixpkgs", "pre-commit-hooks": "pre-commit-hooks", - "systems": "systems_2", + "systems": "systems", "xdph": "xdph" } }, @@ -374,21 +392,6 @@ "type": "github" } }, - "systems_2": { - "locked": { - "lastModified": 1689347949, - "narHash": "sha256-12tWmuL2zgBgZkdoB6qXZsgJEH9LR3oUgpaQq2RbI80=", - "owner": "nix-systems", - "repo": "default-linux", - "rev": "31732fcf5e8fea42e59c2488ad31a0e651500f68", - "type": "github" - }, - "original": { - "owner": "nix-systems", - "repo": "default-linux", - "type": "github" - } - }, "xdph": { "inputs": { "hyprland-protocols": [ From 107723bdf448223385034a4ea724328de7ba50cc Mon Sep 17 00:00:00 2001 From: Maximilian Seidler <78690852+PaideiaDilemma@users.noreply.github.com> Date: Sat, 25 Jan 2025 18:23:36 +0000 Subject: [PATCH 0906/2181] config: disable borderangle by default (#9165) --- src/config/ConfigManager.cpp | 1 + src/desktop/Window.cpp | 8 +++++--- 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/src/config/ConfigManager.cpp b/src/config/ConfigManager.cpp index c5d70329..fd4783da 100644 --- a/src/config/ConfigManager.cpp +++ b/src/config/ConfigManager.cpp @@ -882,6 +882,7 @@ void CConfigManager::setDefaultAnimationVars() { // init the root nodes m_AnimationTree.setConfigForNode("global", 1, 8.f, "", "default"); m_AnimationTree.setConfigForNode("__internal_fadeCTM", 1, 5.f, "", "linear"); + m_AnimationTree.setConfigForNode("borderangle", 0, 0.f, "", "default"); } std::optional CConfigManager::resetHLConfig() { diff --git a/src/desktop/Window.cpp b/src/desktop/Window.cpp index 97d7ecc0..962386c8 100644 --- a/src/desktop/Window.cpp +++ b/src/desktop/Window.cpp @@ -552,9 +552,11 @@ void CWindow::onMap() { m_fMovingFromWorkspaceAlpha->setValueAndWarp(1.F); - m_fBorderAngleAnimationProgress->setValueAndWarp(0.f); - m_fBorderAngleAnimationProgress->setCallbackOnEnd([&](WP p) { onBorderAngleAnimEnd(p); }, false); - *m_fBorderAngleAnimationProgress = 1.f; + if (m_fBorderAngleAnimationProgress->enabled()) { + m_fBorderAngleAnimationProgress->setValueAndWarp(0.f); + m_fBorderAngleAnimationProgress->setCallbackOnEnd([&](WP p) { onBorderAngleAnimEnd(p); }, false); + *m_fBorderAngleAnimationProgress = 1.f; + } m_fMovingFromWorkspaceAlpha->setValueAndWarp(1.F); From f3fc8d599a7812a25f2d53957c0692d339359b43 Mon Sep 17 00:00:00 2001 From: heather7283 <142042427+heather7283@users.noreply.github.com> Date: Sat, 25 Jan 2025 22:23:53 +0400 Subject: [PATCH 0907/2181] config/ConfigWatcher.cpp: add missing include needed for clang (#9166) --- src/config/ConfigWatcher.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/src/config/ConfigWatcher.cpp b/src/config/ConfigWatcher.cpp index 38191e9e..c0a9c591 100644 --- a/src/config/ConfigWatcher.cpp +++ b/src/config/ConfigWatcher.cpp @@ -3,6 +3,7 @@ #include "../debug/Log.hpp" #include #include +#include CConfigWatcher::CConfigWatcher() : m_inotifyFd(inotify_init()) { if (m_inotifyFd < 0) { From bce58d9d6554f1b69ecf38e19f0921230e37ab6d Mon Sep 17 00:00:00 2001 From: Vaxry Date: Sat, 25 Jan 2025 18:34:10 +0000 Subject: [PATCH 0908/2181] dwindle: fix possible crash on null ws --- src/layout/DwindleLayout.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/layout/DwindleLayout.cpp b/src/layout/DwindleLayout.cpp index c6cf2b4c..6d06a3a1 100644 --- a/src/layout/DwindleLayout.cpp +++ b/src/layout/DwindleLayout.cpp @@ -105,8 +105,8 @@ void CHyprDwindleLayout::applyNodeDataToWindow(SDwindleNodeData* pNode, bool for break; } } - } else - PMONITOR = g_pCompositor->getWorkspaceByID(pNode->workspaceID)->m_pMonitor.lock(); + } else if (const auto WS = g_pCompositor->getWorkspaceByID(pNode->workspaceID); WS) + PMONITOR = WS->m_pMonitor.lock(); if (!PMONITOR) { Debug::log(ERR, "Orphaned Node {}!!", pNode); From 9199a9746d7a9355fd349909cb0f773b513ae912 Mon Sep 17 00:00:00 2001 From: Junxuan Liao <70618504+MikeWalrus@users.noreply.github.com> Date: Sat, 25 Jan 2025 12:44:13 -0600 Subject: [PATCH 0909/2181] input: pass touch events to lock screens (#9129) * refactor: use weak pointers for session lock surfaces * input: pass touch events to lock screens --- src/managers/SessionLockManager.cpp | 10 +++++----- src/managers/SessionLockManager.hpp | 18 ++++++++--------- src/managers/input/InputManager.hpp | 10 ++++++---- src/managers/input/Touch.cpp | 30 ++++++++++++++++++++++++----- src/render/Renderer.cpp | 2 +- src/render/Renderer.hpp | 2 +- 6 files changed, 47 insertions(+), 25 deletions(-) diff --git a/src/managers/SessionLockManager.cpp b/src/managers/SessionLockManager.cpp index ea0d8dfc..996860a1 100644 --- a/src/managers/SessionLockManager.cpp +++ b/src/managers/SessionLockManager.cpp @@ -95,20 +95,20 @@ bool CSessionLockManager::isSessionLocked() { return PROTO::sessionLock->isLocked(); } -SSessionLockSurface* CSessionLockManager::getSessionLockSurfaceForMonitor(uint64_t id) { +WP CSessionLockManager::getSessionLockSurfaceForMonitor(uint64_t id) { if (!m_pSessionLock) - return nullptr; + return {}; for (auto const& sls : m_pSessionLock->vSessionLockSurfaces) { if (sls->iMonitorID == id) { if (sls->mapped) - return sls.get(); + return sls; else - return nullptr; + return {}; } } - return nullptr; + return {}; } // We don't want the red screen to flash. diff --git a/src/managers/SessionLockManager.hpp b/src/managers/SessionLockManager.hpp index aaf78819..51d4cefb 100644 --- a/src/managers/SessionLockManager.hpp +++ b/src/managers/SessionLockManager.hpp @@ -49,20 +49,20 @@ class CSessionLockManager { CSessionLockManager(); ~CSessionLockManager() = default; - SSessionLockSurface* getSessionLockSurfaceForMonitor(uint64_t); + WP getSessionLockSurfaceForMonitor(uint64_t); - float getRedScreenAlphaForMonitor(uint64_t); + float getRedScreenAlphaForMonitor(uint64_t); - bool isSessionLocked(); - bool isSessionLockPresent(); - bool isSurfaceSessionLock(SP); - bool anySessionLockSurfacesPresent(); + bool isSessionLocked(); + bool isSessionLockPresent(); + bool isSurfaceSessionLock(SP); + bool anySessionLockSurfacesPresent(); - void removeSessionLockSurface(SSessionLockSurface*); + void removeSessionLockSurface(SSessionLockSurface*); - void onLockscreenRenderedOnMonitor(uint64_t id); + void onLockscreenRenderedOnMonitor(uint64_t id); - bool shallConsiderLockMissing(); + bool shallConsiderLockMissing(); private: UP m_pSessionLock; diff --git a/src/managers/input/InputManager.hpp b/src/managers/input/InputManager.hpp index c0f1939e..3afb1b88 100644 --- a/src/managers/input/InputManager.hpp +++ b/src/managers/input/InputManager.hpp @@ -10,6 +10,7 @@ #include "../../devices/IPointer.hpp" #include "../../devices/ITouch.hpp" #include "../../devices/Tablet.hpp" +#include "../SessionLockManager.hpp" class CPointerConstraint; class CWindow; @@ -52,10 +53,11 @@ enum eBorderIconDirection : uint8_t { }; struct STouchData { - PHLWINDOWREF touchFocusWindow; - PHLLSREF touchFocusLS; - WP touchFocusSurface; - Vector2D touchSurfaceOrigin; + WP touchFocusLockSurface; + PHLWINDOWREF touchFocusWindow; + PHLLSREF touchFocusLS; + WP touchFocusSurface; + Vector2D touchSurfaceOrigin; }; // The third row is always 0 0 1 and is not expected by `libinput_device_config_calibration_set_matrix` diff --git a/src/managers/input/Touch.cpp b/src/managers/input/Touch.cpp index 990fbc41..3d35764e 100644 --- a/src/managers/input/Touch.cpp +++ b/src/managers/input/Touch.cpp @@ -1,4 +1,6 @@ #include "InputManager.hpp" +#include "../SessionLockManager.hpp" +#include "../../protocols/SessionLock.hpp" #include "../../Compositor.hpp" #include "../../desktop/LayerSurface.hpp" #include "../../config/ConfigValue.hpp" @@ -6,6 +8,7 @@ #include "../SeatManager.hpp" #include "managers/AnimationManager.hpp" #include "../HookSystemManager.hpp" +#include "debug/Log.hpp" void CInputManager::onTouchDown(ITouch::SDownEvent e) { m_bLastInputTouch = true; @@ -57,13 +60,25 @@ void CInputManager::onTouchDown(ITouch::SDownEvent e) { } } - m_sTouchData.touchFocusWindow = m_pFoundWindowToFocus; - m_sTouchData.touchFocusSurface = m_pFoundSurfaceToFocus; - m_sTouchData.touchFocusLS = m_pFoundLSToFocus; + if (g_pSessionLockManager->isSessionLocked()) { + m_sTouchData.touchFocusLockSurface = g_pSessionLockManager->getSessionLockSurfaceForMonitor(PMONITOR->ID); + if (!m_sTouchData.touchFocusLockSurface) + Debug::log(WARN, "The session is locked but can't find a lock surface"); + else + m_sTouchData.touchFocusSurface = m_sTouchData.touchFocusLockSurface->surface->surface(); + } else { + m_sTouchData.touchFocusLockSurface.reset(); + m_sTouchData.touchFocusWindow = m_pFoundWindowToFocus; + m_sTouchData.touchFocusSurface = m_pFoundSurfaceToFocus; + m_sTouchData.touchFocusLS = m_pFoundLSToFocus; + } Vector2D local; - if (!m_sTouchData.touchFocusWindow.expired()) { + if (m_sTouchData.touchFocusLockSurface) { + local = g_pInputManager->getMouseCoordsInternal() - PMONITOR->vecPosition; + m_sTouchData.touchSurfaceOrigin = g_pInputManager->getMouseCoordsInternal() - local; + } else if (!m_sTouchData.touchFocusWindow.expired()) { if (m_sTouchData.touchFocusWindow->m_bIsX11) { local = (g_pInputManager->getMouseCoordsInternal() - m_sTouchData.touchFocusWindow->m_vRealPosition->goal()) * m_sTouchData.touchFocusWindow->m_fX11SurfaceScaledBy; m_sTouchData.touchSurfaceOrigin = m_sTouchData.touchFocusWindow->m_vRealPosition->goal(); @@ -126,7 +141,12 @@ void CInputManager::onTouchMove(ITouch::SMotionEvent e) { updateWorkspaceSwipe(SWIPEDISTANCE * (1 - (VERTANIMS ? e.pos.y : e.pos.x))); return; } - if (validMapped(m_sTouchData.touchFocusWindow)) { + if (m_sTouchData.touchFocusLockSurface) { + const auto PMONITOR = g_pCompositor->getMonitorFromID(m_sTouchData.touchFocusLockSurface->iMonitorID); + g_pCompositor->warpCursorTo({PMONITOR->vecPosition.x + e.pos.x * PMONITOR->vecSize.x, PMONITOR->vecPosition.y + e.pos.y * PMONITOR->vecSize.y}, true); + auto local = g_pInputManager->getMouseCoordsInternal() - PMONITOR->vecPosition; + g_pSeatManager->sendTouchMotion(e.timeMs, e.touchID, local); + } else if (validMapped(m_sTouchData.touchFocusWindow)) { const auto PMONITOR = m_sTouchData.touchFocusWindow->m_pMonitor.lock(); g_pCompositor->warpCursorTo({PMONITOR->vecPosition.x + e.pos.x * PMONITOR->vecSize.x, PMONITOR->vecPosition.y + e.pos.y * PMONITOR->vecSize.y}, true); diff --git a/src/render/Renderer.cpp b/src/render/Renderer.cpp index 384db1e6..d82d79d1 100644 --- a/src/render/Renderer.cpp +++ b/src/render/Renderer.cpp @@ -768,7 +768,7 @@ void CHyprRenderer::renderIMEPopup(CInputPopup* pPopup, PHLMONITOR pMonitor, tim &renderdata); } -void CHyprRenderer::renderSessionLockSurface(SSessionLockSurface* pSurface, PHLMONITOR pMonitor, timespec* time) { +void CHyprRenderer::renderSessionLockSurface(WP pSurface, PHLMONITOR pMonitor, timespec* time) { CSurfacePassElement::SRenderData renderdata = {pMonitor, time, pMonitor->vecPosition, pMonitor->vecPosition}; renderdata.blur = false; diff --git a/src/render/Renderer.hpp b/src/render/Renderer.hpp index 1ef1eecc..30fba3ca 100644 --- a/src/render/Renderer.hpp +++ b/src/render/Renderer.hpp @@ -120,7 +120,7 @@ class CHyprRenderer { void renderWorkspaceWindows(PHLMONITOR, PHLWORKSPACE, timespec*); // renders workspace windows (no fullscreen) (tiled, floating, pinned, but no special) void renderWindow(PHLWINDOW, PHLMONITOR, timespec*, bool, eRenderPassMode, bool ignorePosition = false, bool standalone = false); void renderLayer(PHLLS, PHLMONITOR, timespec*, bool popups = false); - void renderSessionLockSurface(SSessionLockSurface*, PHLMONITOR, timespec*); + void renderSessionLockSurface(WP, PHLMONITOR, timespec*); void renderDragIcon(PHLMONITOR, timespec*); void renderIMEPopup(CInputPopup*, PHLMONITOR, timespec*); void renderWorkspace(PHLMONITOR pMonitor, PHLWORKSPACE pWorkspace, timespec* now, const CBox& geometry); From 45c3787e75323999d2f43b6f83972f4cb11a81f9 Mon Sep 17 00:00:00 2001 From: Vaxry Date: Sat, 25 Jan 2025 19:37:33 +0000 Subject: [PATCH 0910/2181] window: revert only set m_iMonitorMovedFrom, when moving to a different monitor This reverts commit 089fdd1ea0d991da5b068db51531f54c90a2df25. Great commit. --- src/Compositor.cpp | 1 + src/desktop/Window.cpp | 5 ++--- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/Compositor.cpp b/src/Compositor.cpp index e1ded6b6..fa73be66 100644 --- a/src/Compositor.cpp +++ b/src/Compositor.cpp @@ -1867,6 +1867,7 @@ void CCompositor::updateWindowAnimatedDecorationValues(PHLWINDOW pWindow) { } // opacity + const auto PWORKSPACE = pWindow->m_pWorkspace; if (pWindow->isEffectiveInternalFSMode(FSMODE_FULLSCREEN)) { *pWindow->m_fActiveInactiveAlpha = pWindow->m_sWindowData.alphaFullscreen.valueOrDefault().applyAlpha(*PFULLSCREENALPHA); } else { diff --git a/src/desktop/Window.cpp b/src/desktop/Window.cpp index 962386c8..5f84aa3a 100644 --- a/src/desktop/Window.cpp +++ b/src/desktop/Window.cpp @@ -420,13 +420,12 @@ void CWindow::moveToWorkspace(PHLWORKSPACE pWorkspace) { static auto PCLOSEONLASTSPECIAL = CConfigValue("misc:close_special_on_empty"); - const auto OLDWORKSPACE = m_pWorkspace; - const bool TOANOTHERMONITOR = OLDWORKSPACE && OLDWORKSPACE->monitorID() != pWorkspace->monitorID(); + const auto OLDWORKSPACE = m_pWorkspace; m_fMovingToWorkspaceAlpha->setValueAndWarp(1.F); *m_fMovingToWorkspaceAlpha = 0.F; m_fMovingToWorkspaceAlpha->setCallbackOnEnd([this](auto) { m_iMonitorMovedFrom = -1; }); - m_iMonitorMovedFrom = TOANOTHERMONITOR ? OLDWORKSPACE->monitorID() : -1; + m_iMonitorMovedFrom = OLDWORKSPACE ? OLDWORKSPACE->monitorID() : -1; m_pWorkspace = pWorkspace; From 445acec2a29adbb30196d8b92f86270a038b7ee5 Mon Sep 17 00:00:00 2001 From: Vaxry Date: Sat, 25 Jan 2025 20:36:44 +0000 Subject: [PATCH 0911/2181] core: move sendWindowSize off of xwaylandmgr additionally fixes that one weird x11 issue with floating windows being mis-sized on open --- src/Compositor.cpp | 2 +- src/desktop/Window.cpp | 45 +++++++++++++++++-- src/desktop/Window.hpp | 2 + src/desktop/Workspace.cpp | 2 +- src/events/Windows.cpp | 10 +++-- src/layout/DwindleLayout.cpp | 4 +- src/layout/IHyprLayout.cpp | 10 ++--- src/layout/MasterLayout.cpp | 4 +- src/managers/KeybindManager.cpp | 2 +- src/managers/XWaylandManager.cpp | 40 +---------------- src/managers/XWaylandManager.hpp | 1 - .../decorations/CHyprGroupBarDecoration.cpp | 2 +- 12 files changed, 64 insertions(+), 60 deletions(-) diff --git a/src/Compositor.cpp b/src/Compositor.cpp index fa73be66..3f9126b7 100644 --- a/src/Compositor.cpp +++ b/src/Compositor.cpp @@ -2325,7 +2325,7 @@ void CCompositor::setWindowFullscreenState(const PHLWINDOW PWINDOW, SFullscreenS updateFullscreenFadeOnWorkspace(PWORKSPACE); - g_pXWaylandManager->setWindowSize(PWINDOW, PWINDOW->m_vRealSize->goal(), true); + PWINDOW->sendWindowSize(PWINDOW->m_vRealSize->goal(), true); PWORKSPACE->forceReportSizesToWindows(); diff --git a/src/desktop/Window.cpp b/src/desktop/Window.cpp index 5f84aa3a..96b87205 100644 --- a/src/desktop/Window.cpp +++ b/src/desktop/Window.cpp @@ -453,7 +453,7 @@ void CWindow::moveToWorkspace(PHLWORKSPACE pWorkspace) { } // update xwayland coords - g_pXWaylandManager->setWindowSize(m_pSelf.lock(), m_vRealSize->goal()); + sendWindowSize(m_vRealSize->goal()); if (OLDWORKSPACE && g_pCompositor->isWorkspaceSpecial(OLDWORKSPACE->m_iID) && OLDWORKSPACE->getWindows() == 0 && *PCLOSEONLASTSPECIAL) { if (const auto PMONITOR = OLDWORKSPACE->m_pMonitor.lock(); PMONITOR) @@ -1309,7 +1309,7 @@ void CWindow::clampWindowSize(const std::optional minSize, const std:: *m_vRealPosition = m_vRealPosition->goal() + DELTA / 2.0; *m_vRealSize = NEWSIZE; - g_pXWaylandManager->setWindowSize(m_pSelf.lock(), NEWSIZE); + sendWindowSize(NEWSIZE); } bool CWindow::isFullscreen() { @@ -1533,7 +1533,7 @@ void CWindow::onX11Configure(CBox box) { g_pHyprRenderer->damageWindow(m_pSelf.lock()); if (!m_bIsFloating || isFullscreen() || g_pInputManager->currentlyDraggedWindow == m_pSelf) { - g_pXWaylandManager->setWindowSize(m_pSelf.lock(), m_vRealSize->goal(), true); + sendWindowSize(m_vRealSize->goal(), true); g_pInputManager->refocus(); g_pHyprRenderer->damageWindow(m_pSelf.lock()); return; @@ -1560,7 +1560,7 @@ void CWindow::onX11Configure(CBox box) { m_vPosition = m_vRealPosition->goal(); m_vSize = m_vRealSize->goal(); - g_pXWaylandManager->setWindowSize(m_pSelf.lock(), box.size(), true); + sendWindowSize(box.size(), true); m_vPendingReportedSize = box.size(); m_vReportedSize = box.size(); @@ -1690,3 +1690,40 @@ Vector2D CWindow::requestedMaxSize() { return maxSize; } + +void CWindow::sendWindowSize(Vector2D size, bool force, std::optional overridePos) { + static auto PXWLFORCESCALEZERO = CConfigValue("xwayland:force_zero_scaling"); + + const auto PMONITOR = m_pMonitor.lock(); + + size = size.clamp(Vector2D{0, 0}, Vector2D{std::numeric_limits::infinity(), std::numeric_limits::infinity()}); + + // calculate pos + // TODO: this should be decoupled from setWindowSize IMO + Vector2D windowPos = overridePos.value_or(m_vRealPosition->goal()); + + if (m_bIsX11 && PMONITOR) { + windowPos -= PMONITOR->vecPosition; // normalize to monitor + if (*PXWLFORCESCALEZERO) + windowPos *= PMONITOR->scale; // scale if applicable + windowPos += PMONITOR->vecXWaylandPosition; // move to correct position for xwayland + } + + if (!force && m_vPendingReportedSize == size && (windowPos == m_vReportedPosition || !m_bIsX11)) + return; + + m_vReportedPosition = windowPos; + m_vPendingReportedSize = size; + + m_fX11SurfaceScaledBy = 1.0f; + + if (*PXWLFORCESCALEZERO && m_bIsX11 && PMONITOR) { + size *= PMONITOR->scale; + m_fX11SurfaceScaledBy = PMONITOR->scale; + } + + if (m_bIsX11 && m_pXWaylandSurface) + m_pXWaylandSurface->configure({windowPos, size}); + else if (m_pXDGSurface && m_pXDGSurface->toplevel) + m_vPendingSizeAcks.emplace_back(m_pXDGSurface->toplevel->setSize(size), size.floor()); +} diff --git a/src/desktop/Window.hpp b/src/desktop/Window.hpp index cff13b03..ce2f8eb2 100644 --- a/src/desktop/Window.hpp +++ b/src/desktop/Window.hpp @@ -2,6 +2,7 @@ #include #include +#include #include "../config/ConfigDataValues.hpp" #include "../helpers/AnimatedVariable.hpp" @@ -468,6 +469,7 @@ class CWindow { bool isModal(); Vector2D requestedMinSize(); Vector2D requestedMaxSize(); + void sendWindowSize(Vector2D size, bool force = false, std::optional overridePos = std::nullopt); CBox getWindowMainSurfaceBox() const { return {m_vRealPosition->value().x, m_vRealPosition->value().y, m_vRealSize->value().x, m_vRealSize->value().y}; diff --git a/src/desktop/Workspace.cpp b/src/desktop/Workspace.cpp index 99ba441d..8dbf30b7 100644 --- a/src/desktop/Workspace.cpp +++ b/src/desktop/Workspace.cpp @@ -624,7 +624,7 @@ void CWorkspace::forceReportSizesToWindows() { if (w->m_pWorkspace != m_pSelf || !w->m_bIsMapped || w->isHidden()) continue; - g_pXWaylandManager->setWindowSize(w, w->m_vRealSize->goal(), true); + w->sendWindowSize(w->m_vRealSize->goal(), true); } } diff --git a/src/events/Windows.cpp b/src/events/Windows.cpp index 525adc02..9ecf3652 100644 --- a/src/events/Windows.cpp +++ b/src/events/Windows.cpp @@ -681,8 +681,12 @@ void Events::listener_mapWindow(void* owner, void* data) { if (PMONITOR && PWINDOW->isX11OverrideRedirect()) PWINDOW->m_fX11SurfaceScaledBy = PMONITOR->scale; - if (!PWINDOW->isX11OverrideRedirect() && PWINDOW->m_bIsX11 && PWINDOW->m_bIsFloating) - g_pXWaylandManager->setWindowSize(PWINDOW, PWINDOW->m_vRealSize->goal(), true); + // Fix some X11 popups being invisible / having incorrect size on open. + // What the ACTUAL FUCK is going on?????? I HATE X11 + if (!PWINDOW->isX11OverrideRedirect() && PWINDOW->m_bIsX11 && PWINDOW->m_bIsFloating) { + PWINDOW->sendWindowSize(PWINDOW->m_vRealSize->goal(), true, PWINDOW->m_vRealPosition->goal() - Vector2D{1, 1}); + PWINDOW->sendWindowSize(PWINDOW->m_vRealSize->goal(), true); + } } void Events::listener_unmapWindow(void* owner, void* data) { @@ -949,7 +953,7 @@ void Events::listener_unmanagedSetGeometry(void* owner, void* data) { PWINDOW->setHidden(true); if (PWINDOW->isFullscreen() || !PWINDOW->m_bIsFloating) { - g_pXWaylandManager->setWindowSize(PWINDOW, PWINDOW->m_vRealSize->goal(), true); + PWINDOW->sendWindowSize(PWINDOW->m_vRealSize->goal(), true); g_pHyprRenderer->damageWindow(PWINDOW); return; } diff --git a/src/layout/DwindleLayout.cpp b/src/layout/DwindleLayout.cpp index 6d06a3a1..df6c3bde 100644 --- a/src/layout/DwindleLayout.cpp +++ b/src/layout/DwindleLayout.cpp @@ -199,7 +199,7 @@ void CHyprDwindleLayout::applyNodeDataToWindow(SDwindleNodeData* pNode, bool for *PWINDOW->m_vRealPosition = wb.pos(); *PWINDOW->m_vRealSize = wb.size(); - g_pXWaylandManager->setWindowSize(PWINDOW, wb.size()); + PWINDOW->sendWindowSize(wb.size()); } else { CBox wb = {calcPos, calcSize}; wb.round(); // avoid rounding mess @@ -207,7 +207,7 @@ void CHyprDwindleLayout::applyNodeDataToWindow(SDwindleNodeData* pNode, bool for *PWINDOW->m_vRealSize = wb.size(); *PWINDOW->m_vRealPosition = wb.pos(); - g_pXWaylandManager->setWindowSize(PWINDOW, wb.size()); + PWINDOW->sendWindowSize(wb.size()); } if (force) { diff --git a/src/layout/IHyprLayout.cpp b/src/layout/IHyprLayout.cpp index ffc08e46..81392be9 100644 --- a/src/layout/IHyprLayout.cpp +++ b/src/layout/IHyprLayout.cpp @@ -179,7 +179,7 @@ void IHyprLayout::onWindowCreatedFloating(PHLWINDOW pWindow) { } if (!pWindow->isX11OverrideRedirect()) { - g_pXWaylandManager->setWindowSize(pWindow, pWindow->m_vRealSize->goal()); + pWindow->sendWindowSize(pWindow->m_vRealSize->goal()); g_pCompositor->changeWindowZOrder(pWindow, true); } else { @@ -365,7 +365,7 @@ void IHyprLayout::onEndDragWindow() { DRAGGINGWINDOW->m_bDraggingTiled = false; if (pWindow->m_bIsFloating) - g_pXWaylandManager->setWindowSize(DRAGGINGWINDOW, pWindow->m_vRealSize->goal()); // match the size of the window + DRAGGINGWINDOW->sendWindowSize(DRAGGINGWINDOW->m_vRealSize->goal()); // match the size of the window static auto USECURRPOS = CConfigValue("group:insert_after_current"); (*USECURRPOS ? pWindow : pWindow->getGroupTail())->insertWindowToGroup(DRAGGINGWINDOW); @@ -611,7 +611,7 @@ void IHyprLayout::onMouseMove(const Vector2D& mousePos) { else DRAGGINGWINDOW->m_vRealPosition->setValueAndWarp(wb.pos()); - g_pXWaylandManager->setWindowSize(DRAGGINGWINDOW, DRAGGINGWINDOW->m_vRealSize->goal()); + DRAGGINGWINDOW->sendWindowSize(DRAGGINGWINDOW->m_vRealSize->goal()); } else if (g_pInputManager->dragMode == MBIND_RESIZE || g_pInputManager->dragMode == MBIND_RESIZE_FORCE_RATIO || g_pInputManager->dragMode == MBIND_RESIZE_BLOCK_RATIO) { if (DRAGGINGWINDOW->m_bIsFloating) { @@ -683,7 +683,7 @@ void IHyprLayout::onMouseMove(const Vector2D& mousePos) { DRAGGINGWINDOW->m_vRealPosition->setValueAndWarp(wb.pos()); } - g_pXWaylandManager->setWindowSize(DRAGGINGWINDOW, DRAGGINGWINDOW->m_vRealSize->goal()); + DRAGGINGWINDOW->sendWindowSize(DRAGGINGWINDOW->m_vRealSize->goal()); } else { resizeActiveWindow(TICKDELTA, m_eGrabbedCorner, DRAGGINGWINDOW); } @@ -789,7 +789,7 @@ void IHyprLayout::changeWindowFloatingMode(PHLWINDOW pWindow) { g_pCompositor->updateWindowAnimatedDecorationValues(pWindow); pWindow->updateToplevel(); - g_pXWaylandManager->setWindowSize(pWindow, pWindow->m_vRealSize->goal()); + pWindow->sendWindowSize(pWindow->m_vRealSize->goal()); g_pHyprRenderer->damageWindow(pWindow); } diff --git a/src/layout/MasterLayout.cpp b/src/layout/MasterLayout.cpp index 3b8ff734..8aa15e42 100644 --- a/src/layout/MasterLayout.cpp +++ b/src/layout/MasterLayout.cpp @@ -679,7 +679,7 @@ void CHyprMasterLayout::applyNodeDataToWindow(SMasterNodeData* pNode) { *PWINDOW->m_vRealPosition = wb.pos(); *PWINDOW->m_vRealSize = wb.size(); - g_pXWaylandManager->setWindowSize(PWINDOW, wb.size()); + PWINDOW->sendWindowSize(wb.size()); } else { CBox wb = {calcPos, calcSize}; wb.round(); // avoid rounding mess @@ -687,7 +687,7 @@ void CHyprMasterLayout::applyNodeDataToWindow(SMasterNodeData* pNode) { *PWINDOW->m_vRealPosition = wb.pos(); *PWINDOW->m_vRealSize = wb.size(); - g_pXWaylandManager->setWindowSize(PWINDOW, wb.size()); + PWINDOW->sendWindowSize(wb.size()); } if (m_bForceWarps && !*PANIMATE) { diff --git a/src/managers/KeybindManager.cpp b/src/managers/KeybindManager.cpp index e2191bc6..2cb77d21 100644 --- a/src/managers/KeybindManager.cpp +++ b/src/managers/KeybindManager.cpp @@ -1914,7 +1914,7 @@ SDispatchResult CKeybindManager::workspaceOpt(std::string args) { if (PWORKSPACE->m_bDefaultFloating) { w->m_vRealPosition->setValueAndWarp(SAVEDPOS); w->m_vRealSize->setValueAndWarp(SAVEDSIZE); - g_pXWaylandManager->setWindowSize(w, SAVEDSIZE); + w->sendWindowSize(SAVEDSIZE); *w->m_vRealSize = w->m_vRealSize->value() + Vector2D(4, 4); *w->m_vRealPosition = w->m_vRealPosition->value() - Vector2D(2, 2); } diff --git a/src/managers/XWaylandManager.cpp b/src/managers/XWaylandManager.cpp index 8956cf3a..ea2a47ea 100644 --- a/src/managers/XWaylandManager.cpp +++ b/src/managers/XWaylandManager.cpp @@ -55,7 +55,7 @@ void CHyprXWaylandManager::activateWindow(PHLWINDOW pWindow, bool activate) { if (pWindow->m_bIsX11) { if (activate) { - setWindowSize(pWindow, pWindow->m_vRealSize->value(), true); // update xwayland output pos + pWindow->sendWindowSize(pWindow->m_vRealSize->value(), true); // update xwayland output pos pWindow->m_pXWaylandSurface->setMinimized(false); if (!pWindow->isX11OverrideRedirect()) @@ -113,44 +113,6 @@ void CHyprXWaylandManager::sendCloseWindow(PHLWINDOW pWindow) { pWindow->m_pXDGSurface->toplevel->close(); } -void CHyprXWaylandManager::setWindowSize(PHLWINDOW pWindow, Vector2D size, bool force) { - - static auto PXWLFORCESCALEZERO = CConfigValue("xwayland:force_zero_scaling"); - - const auto PMONITOR = pWindow->m_pMonitor.lock(); - - size = size.clamp(Vector2D{0, 0}, Vector2D{std::numeric_limits::infinity(), std::numeric_limits::infinity()}); - - // calculate pos - // TODO: this should be decoupled from setWindowSize IMO - Vector2D windowPos = pWindow->m_vRealPosition->goal(); - - if (pWindow->m_bIsX11 && PMONITOR) { - windowPos -= PMONITOR->vecPosition; // normalize to monitor - if (*PXWLFORCESCALEZERO) - windowPos *= PMONITOR->scale; // scale if applicable - windowPos += PMONITOR->vecXWaylandPosition; // move to correct position for xwayland - } - - if (!force && pWindow->m_vPendingReportedSize == size && (windowPos == pWindow->m_vReportedPosition || !pWindow->m_bIsX11)) - return; - - pWindow->m_vReportedPosition = windowPos; - pWindow->m_vPendingReportedSize = size; - - pWindow->m_fX11SurfaceScaledBy = 1.0f; - - if (*PXWLFORCESCALEZERO && pWindow->m_bIsX11 && PMONITOR) { - size *= PMONITOR->scale; - pWindow->m_fX11SurfaceScaledBy = PMONITOR->scale; - } - - if (pWindow->m_bIsX11) - pWindow->m_pXWaylandSurface->configure({windowPos, size}); - else if (pWindow->m_pXDGSurface->toplevel) - pWindow->m_vPendingSizeAcks.emplace_back(pWindow->m_pXDGSurface->toplevel->setSize(size), size.floor()); -} - bool CHyprXWaylandManager::shouldBeFloated(PHLWINDOW pWindow, bool pending) { if (pWindow->m_bIsX11) { for (const auto& a : pWindow->m_pXWaylandSurface->atoms) diff --git a/src/managers/XWaylandManager.hpp b/src/managers/XWaylandManager.hpp index 8ce239f6..edbdd243 100644 --- a/src/managers/XWaylandManager.hpp +++ b/src/managers/XWaylandManager.hpp @@ -17,7 +17,6 @@ class CHyprXWaylandManager { void activateWindow(PHLWINDOW, bool); void getGeometryForWindow(PHLWINDOW, CBox*); void sendCloseWindow(PHLWINDOW); - void setWindowSize(PHLWINDOW, Vector2D, bool force = false); void setWindowFullscreen(PHLWINDOW, bool); bool shouldBeFloated(PHLWINDOW, bool pending = false); void checkBorders(PHLWINDOW); diff --git a/src/render/decorations/CHyprGroupBarDecoration.cpp b/src/render/decorations/CHyprGroupBarDecoration.cpp index 36846fd4..7cef21b8 100644 --- a/src/render/decorations/CHyprGroupBarDecoration.cpp +++ b/src/render/decorations/CHyprGroupBarDecoration.cpp @@ -408,7 +408,7 @@ bool CHyprGroupBarDecoration::onEndWindowDragOnDeco(const Vector2D& pos, PHLWIND pDraggedWindow->m_bIsFloating = pWindowInsertAfter->m_bIsFloating; // match the floating state of the window if (pWindowInsertAfter->m_bIsFloating) - g_pXWaylandManager->setWindowSize(pDraggedWindow, pWindowInsertAfter->m_vRealSize->goal()); // match the size of the window + pDraggedWindow->sendWindowSize(pWindowInsertAfter->m_vRealSize->goal()); // match the size of the window pWindowInsertAfter->insertWindowToGroup(pDraggedWindow); From 8b1d6e3009c540457068e23e6c2bc201d20ce4d1 Mon Sep 17 00:00:00 2001 From: Vaxry Date: Sat, 25 Jan 2025 21:57:58 +0000 Subject: [PATCH 0912/2181] subsurface: damage the entire parent on size change the previous method doesn't exactly work, idk todo fix fixes #8784 --- src/desktop/Subsurface.cpp | 17 +++++++++++++---- 1 file changed, 13 insertions(+), 4 deletions(-) diff --git a/src/desktop/Subsurface.cpp b/src/desktop/Subsurface.cpp index 9cdf3685..eb18ee39 100644 --- a/src/desktop/Subsurface.cpp +++ b/src/desktop/Subsurface.cpp @@ -101,10 +101,19 @@ void CSubsurface::onCommit() { checkSiblingDamage(); if (m_vLastSize != m_pWLSurface->resource()->current.size) { - CBox box{COORDS, m_vLastSize}; - g_pHyprRenderer->damageBox(&box); - m_vLastSize = m_pWLSurface->resource()->current.size; - box = {COORDS, m_vLastSize}; + // TODO: fix this + // CBox box{COORDS, m_vLastSize}; + // g_pHyprRenderer->damageBox(&box); + // m_vLastSize = m_pWLSurface->resource()->current.size; + // box = {COORDS, m_vLastSize}; + // g_pHyprRenderer->damageBox(&box); + + CBox box; + if (m_pPopupParent) + box = m_pPopupParent->m_pWLSurface->getSurfaceBoxGlobal().value_or(CBox{}); + else if (m_pWindowParent) + box = m_pWindowParent->getWindowMainSurfaceBox(); + g_pHyprRenderer->damageBox(&box); } } From 3cd6e3960f0cbf500786497017ff3084cc9deb17 Mon Sep 17 00:00:00 2001 From: Maximilian Seidler <78690852+PaideiaDilemma@users.noreply.github.com> Date: Sun, 26 Jan 2025 12:23:39 +0000 Subject: [PATCH 0913/2181] xwayland: fix pointer mismatches with multiple monitors (#9179) --- src/desktop/Window.cpp | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/src/desktop/Window.cpp b/src/desktop/Window.cpp index 96b87205..b1b3c66c 100644 --- a/src/desktop/Window.cpp +++ b/src/desktop/Window.cpp @@ -1702,11 +1702,9 @@ void CWindow::sendWindowSize(Vector2D size, bool force, std::optional // TODO: this should be decoupled from setWindowSize IMO Vector2D windowPos = overridePos.value_or(m_vRealPosition->goal()); - if (m_bIsX11 && PMONITOR) { - windowPos -= PMONITOR->vecPosition; // normalize to monitor - if (*PXWLFORCESCALEZERO) - windowPos *= PMONITOR->scale; // scale if applicable - windowPos += PMONITOR->vecXWaylandPosition; // move to correct position for xwayland + if (m_bIsX11) { + if (const auto XWAYLANDPOS = g_pXWaylandManager->waylandToXWaylandCoords(windowPos); XWAYLANDPOS != Vector2D{}) + windowPos = XWAYLANDPOS; } if (!force && m_vPendingReportedSize == size && (windowPos == m_vReportedPosition || !m_bIsX11)) From 0a28e13787a83a48cbca9641a02b8ea4857c733c Mon Sep 17 00:00:00 2001 From: Vaxry Date: Sun, 26 Jan 2025 12:54:32 +0000 Subject: [PATCH 0914/2181] desktop: move desktop types to memory-safe pointers --- src/Compositor.cpp | 1 - src/desktop/LayerSurface.cpp | 11 ++++++----- src/desktop/Popup.cpp | 35 +++++++++++++++++++---------------- src/desktop/Popup.hpp | 11 ++++++----- src/desktop/Subsurface.cpp | 14 ++++++++------ src/desktop/Subsurface.hpp | 30 ++++++++++++++++-------------- src/desktop/Window.cpp | 12 +++++++----- src/main.cpp | 2 ++ src/render/Renderer.cpp | 4 ++-- 9 files changed, 66 insertions(+), 54 deletions(-) diff --git a/src/Compositor.cpp b/src/Compositor.cpp index 3f9126b7..43efdac1 100644 --- a/src/Compositor.cpp +++ b/src/Compositor.cpp @@ -571,7 +571,6 @@ void CCompositor::cleanup() { g_pLayoutManager.reset(); g_pHyprError.reset(); g_pConfigManager.reset(); - g_pAnimationManager.reset(); g_pKeybindManager.reset(); g_pHookSystem.reset(); g_pWatchdog.reset(); diff --git a/src/desktop/LayerSurface.cpp b/src/desktop/LayerSurface.cpp index dd30aa7c..c2b07c5d 100644 --- a/src/desktop/LayerSurface.cpp +++ b/src/desktop/LayerSurface.cpp @@ -31,9 +31,10 @@ PHLLS CLayerSurface::create(SP resource) { pLS->szNamespace = resource->layerNamespace; - pLS->layer = resource->current.layer; - pLS->popupHead = makeUnique(pLS); - pLS->monitor = pMonitor; + pLS->layer = resource->current.layer; + pLS->popupHead = makeUnique(pLS); + pLS->popupHead->m_pSelf = pLS->popupHead; + pLS->monitor = pMonitor; pMonitor->m_aLayerSurfaceLayers[resource->current.layer].emplace_back(pLS); pLS->forceBlur = g_pConfigManager->shouldBlurLS(pLS->szNamespace); @@ -331,7 +332,7 @@ void CLayerSurface::onCommit() { nullptr); if (!WASLASTFOCUS && popupHead) { popupHead->breadthfirst( - [&WASLASTFOCUS](CPopup* popup, void* data) { + [&WASLASTFOCUS](WP popup, void* data) { WASLASTFOCUS = WASLASTFOCUS || (popup->m_pWLSurface && g_pSeatManager->state.keyboardFocus == popup->m_pWLSurface->resource()); }, nullptr); @@ -576,7 +577,7 @@ int CLayerSurface::popupsCount() { return 0; int no = -1; // we have one dummy - popupHead->breadthfirst([](CPopup* p, void* data) { *(int*)data += 1; }, &no); + popupHead->breadthfirst([](WP p, void* data) { *(int*)data += 1; }, &no); return no; } diff --git a/src/desktop/Popup.cpp b/src/desktop/Popup.cpp index 831619a5..0c7c72a4 100644 --- a/src/desktop/Popup.cpp +++ b/src/desktop/Popup.cpp @@ -20,7 +20,8 @@ CPopup::CPopup(PHLLS pOwner) : m_pLayerOwner(pOwner) { initAllSignals(); } -CPopup::CPopup(SP popup, CPopup* pOwner) : m_pWindowOwner(pOwner->m_pWindowOwner), m_pLayerOwner(pOwner->m_pLayerOwner), m_pParent(pOwner), m_pResource(popup) { +CPopup::CPopup(SP popup, WP pOwner) : + m_pWindowOwner(pOwner->m_pWindowOwner), m_pLayerOwner(pOwner->m_pLayerOwner), m_pParent(pOwner), m_pResource(popup) { m_pWLSurface = CWLSurface::create(); m_pWLSurface->assign(popup->surface->surface.lock(), this); @@ -58,7 +59,8 @@ void CPopup::initAllSignals() { } void CPopup::onNewPopup(SP popup) { - const auto POPUP = m_vChildren.emplace_back(makeShared(popup, this)).get(); + const auto& POPUP = m_vChildren.emplace_back(makeShared(popup, m_pSelf)); + POPUP->m_pSelf = POPUP; Debug::log(LOG, "New popup at {:x}", (uintptr_t)POPUP); } @@ -89,7 +91,8 @@ void CPopup::onMap() { g_pInputManager->simulateMouseMovement(); - m_pSubsurfaceHead = makeUnique(this); + m_pSubsurfaceHead = makeUnique(m_pSelf); + m_pSubsurfaceHead->m_pSelf = m_pSubsurfaceHead; //unconstrain(); sendScale(); @@ -126,7 +129,7 @@ void CPopup::onUnmap() { // damage all children breadthfirst( - [](CPopup* p, void* data) { + [](WP p, void* data) { if (!p->m_pResource) return; @@ -223,7 +226,7 @@ Vector2D CPopup::coordsRelativeToParent() { if (!m_pResource) return {}; - CPopup* current = this; + WP current = m_pSelf; offset -= current->m_pResource->surface->current.geometry.pos(); while (current->m_pParent && current->m_pResource) { @@ -256,7 +259,7 @@ Vector2D CPopup::t1ParentCoords() { } void CPopup::recheckTree() { - CPopup* curr = this; + WP curr = m_pSelf; while (curr->m_pParent) { curr = curr->m_pParent; } @@ -296,17 +299,17 @@ bool CPopup::visible() { return false; } -void CPopup::bfHelper(std::vector const& nodes, std::function fn, void* data) { +void CPopup::bfHelper(std::vector> const& nodes, std::function, void*)> fn, void* data) { for (auto const& n : nodes) { fn(n, data); } - std::vector nodes2; + std::vector> nodes2; nodes2.reserve(nodes.size() * 2); for (auto const& n : nodes) { for (auto const& c : n->m_vChildren) { - nodes2.push_back(c.get()); + nodes2.push_back(c->m_pSelf); } } @@ -314,15 +317,15 @@ void CPopup::bfHelper(std::vector const& nodes, std::function fn, void* data) { - std::vector popups; - popups.push_back(this); +void CPopup::breadthfirst(std::function, void*)> fn, void* data) { + std::vector> popups; + popups.push_back(m_pSelf); bfHelper(popups, fn, data); } -CPopup* CPopup::at(const Vector2D& globalCoords, bool allowsInput) { - std::vector popups; - breadthfirst([](CPopup* popup, void* data) { ((std::vector*)data)->push_back(popup); }, &popups); +WP CPopup::at(const Vector2D& globalCoords, bool allowsInput) { + std::vector> popups; + breadthfirst([](WP popup, void* data) { ((std::vector>*)data)->push_back(popup); }, &popups); for (auto const& p : popups | std::views::reverse) { if (!p->m_pResource || !p->m_bMapped) @@ -344,5 +347,5 @@ CPopup* CPopup::at(const Vector2D& globalCoords, bool allowsInput) { } } - return nullptr; + return {}; } diff --git a/src/desktop/Popup.hpp b/src/desktop/Popup.hpp index 2b7b4e82..6051f7eb 100644 --- a/src/desktop/Popup.hpp +++ b/src/desktop/Popup.hpp @@ -14,7 +14,7 @@ class CPopup { CPopup(PHLLS pOwner); // real nodes - CPopup(SP popup, CPopup* pOwner); + CPopup(SP popup, WP pOwner); ~CPopup(); @@ -36,11 +36,12 @@ class CPopup { bool visible(); // will also loop over this node - void breadthfirst(std::function fn, void* data); - CPopup* at(const Vector2D& globalCoords, bool allowsInput = false); + void breadthfirst(std::function, void*)> fn, void* data); + WP at(const Vector2D& globalCoords, bool allowsInput = false); // SP m_pWLSurface; + WP m_pSelf; bool m_bMapped = false; private: @@ -49,7 +50,7 @@ class CPopup { PHLLSREF m_pLayerOwner; // T2 owners - CPopup* m_pParent = nullptr; + WP m_pParent; WP m_pResource; @@ -81,5 +82,5 @@ class CPopup { Vector2D localToGlobal(const Vector2D& rel); Vector2D t1ParentCoords(); - static void bfHelper(std::vector const& nodes, std::function fn, void* data); + static void bfHelper(std::vector> const& nodes, std::function, void*)> fn, void* data); }; diff --git a/src/desktop/Subsurface.cpp b/src/desktop/Subsurface.cpp index eb18ee39..5657cb39 100644 --- a/src/desktop/Subsurface.cpp +++ b/src/desktop/Subsurface.cpp @@ -12,7 +12,7 @@ CSubsurface::CSubsurface(PHLWINDOW pOwner) : m_pWindowParent(pOwner) { initExistingSubsurfaces(pOwner->m_pWLSurface->resource()); } -CSubsurface::CSubsurface(CPopup* pOwner) : m_pPopupParent(pOwner) { +CSubsurface::CSubsurface(WP pOwner) : m_pPopupParent(pOwner) { initSignals(); initExistingSubsurfaces(pOwner->m_pWLSurface->resource()); } @@ -24,7 +24,7 @@ CSubsurface::CSubsurface(SP pSubsurface, PHLWINDOW pOwner initExistingSubsurfaces(pSubsurface->surface.lock()); } -CSubsurface::CSubsurface(SP pSubsurface, CPopup* pOwner) : m_pSubsurface(pSubsurface), m_pPopupParent(pOwner) { +CSubsurface::CSubsurface(SP pSubsurface, WP pOwner) : m_pSubsurface(pSubsurface), m_pPopupParent(pOwner) { m_pWLSurface = CWLSurface::create(); m_pWLSurface->assign(pSubsurface->surface.lock(), this); initSignals(); @@ -132,16 +132,18 @@ void CSubsurface::onDestroy() { } void CSubsurface::onNewSubsurface(SP pSubsurface) { - CSubsurface* PSUBSURFACE = nullptr; + WP PSUBSURFACE; if (!m_pWindowParent.expired()) - PSUBSURFACE = m_vChildren.emplace_back(makeUnique(pSubsurface, m_pWindowParent.lock())).get(); + PSUBSURFACE = m_vChildren.emplace_back(makeUnique(pSubsurface, m_pWindowParent.lock())); else if (m_pPopupParent) - PSUBSURFACE = m_vChildren.emplace_back(makeUnique(pSubsurface, m_pPopupParent)).get(); + PSUBSURFACE = m_vChildren.emplace_back(makeUnique(pSubsurface, m_pPopupParent)); + + PSUBSURFACE->m_pSelf = PSUBSURFACE; ASSERT(PSUBSURFACE); - PSUBSURFACE->m_pParent = this; + PSUBSURFACE->m_pParent = PSUBSURFACE; } void CSubsurface::onMap() { diff --git a/src/desktop/Subsurface.hpp b/src/desktop/Subsurface.hpp index aacbad91..f16a11ea 100644 --- a/src/desktop/Subsurface.hpp +++ b/src/desktop/Subsurface.hpp @@ -11,28 +11,30 @@ class CSubsurface { public: // root dummy nodes CSubsurface(PHLWINDOW pOwner); - CSubsurface(CPopup* pOwner); + CSubsurface(WP pOwner); // real nodes CSubsurface(SP pSubsurface, PHLWINDOW pOwner); - CSubsurface(SP pSubsurface, CPopup* pOwner); + CSubsurface(SP pSubsurface, WP pOwner); ~CSubsurface(); - Vector2D coordsRelativeToParent(); - Vector2D coordsGlobal(); + Vector2D coordsRelativeToParent(); + Vector2D coordsGlobal(); - Vector2D size(); + Vector2D size(); - void onCommit(); - void onDestroy(); - void onNewSubsurface(SP pSubsurface); - void onMap(); - void onUnmap(); + void onCommit(); + void onDestroy(); + void onNewSubsurface(SP pSubsurface); + void onMap(); + void onUnmap(); - bool visible(); + bool visible(); - void recheckDamageForSubsurfaces(); + void recheckDamageForSubsurfaces(); + + WP m_pSelf; private: struct { @@ -48,10 +50,10 @@ class CSubsurface { Vector2D m_vLastSize = {}; // if nullptr, means it's a dummy node - CSubsurface* m_pParent = nullptr; + WP m_pParent; PHLWINDOWREF m_pWindowParent; - CPopup* m_pPopupParent = nullptr; + WP m_pPopupParent; std::vector> m_vChildren; diff --git a/src/desktop/Window.cpp b/src/desktop/Window.cpp index b1b3c66c..9dcdb385 100644 --- a/src/desktop/Window.cpp +++ b/src/desktop/Window.cpp @@ -154,7 +154,7 @@ SBoxExtents CWindow::getFullWindowExtents() { CBox surfaceExtents = {0, 0, 0, 0}; // TODO: this could be better, perhaps make a getFullWindowRegion? m_pPopupHead->breadthfirst( - [](CPopup* popup, void* data) { + [](WP popup, void* data) { if (!popup->m_pWLSurface || !popup->m_pWLSurface->resource()) return; @@ -569,8 +569,10 @@ void CWindow::onMap() { if (m_bIsX11) return; - m_pSubsurfaceHead = makeUnique(m_pSelf.lock()); - m_pPopupHead = makeUnique(m_pSelf.lock()); + m_pSubsurfaceHead = makeUnique(m_pSelf.lock()); + m_pSubsurfaceHead->m_pSelf = m_pSubsurfaceHead; + m_pPopupHead = makeUnique(m_pSelf.lock()); + m_pPopupHead->m_pSelf = m_pPopupHead; } void CWindow::onBorderAngleAnimEnd(WP pav) { @@ -847,7 +849,7 @@ bool CWindow::hasPopupAt(const Vector2D& pos) { if (m_bIsX11) return false; - CPopup* popup = m_pPopupHead->at(pos); + auto popup = m_pPopupHead->at(pos); return popup && popup->m_pWLSurface->resource(); } @@ -1289,7 +1291,7 @@ int CWindow::popupsCount() { return 0; int no = -1; - m_pPopupHead->breadthfirst([](CPopup* p, void* d) { *((int*)d) += 1; }, &no); + m_pPopupHead->breadthfirst([](WP p, void* d) { *((int*)d) += 1; }, &no); return no; } diff --git a/src/main.cpp b/src/main.cpp index d244f10f..464ed978 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -181,6 +181,8 @@ int main(int argc, char** argv) { g_pCompositor->cleanup(); + g_pCompositor.reset(); + Debug::log(LOG, "Hyprland has reached the end."); return EXIT_SUCCESS; diff --git a/src/render/Renderer.cpp b/src/render/Renderer.cpp index d82d79d1..f897379a 100644 --- a/src/render/Renderer.cpp +++ b/src/render/Renderer.cpp @@ -615,7 +615,7 @@ void CHyprRenderer::renderWindow(PHLWINDOW pWindow, PHLMONITOR pMonitor, timespe renderdata.surfaceCounter = 0; pWindow->m_pPopupHead->breadthfirst( - [this, &renderdata](CPopup* popup, void* data) { + [this, &renderdata](WP popup, void* data) { if (!popup->m_pWLSurface || !popup->m_pWLSurface->resource() || !popup->m_bMapped) return; const auto pos = popup->coordsRelativeToParent(); @@ -718,7 +718,7 @@ void CHyprRenderer::renderLayer(PHLLS pLayer, PHLMONITOR pMonitor, timespec* tim renderdata.surfaceCounter = 0; if (popups) { pLayer->popupHead->breadthfirst( - [this, &renderdata](CPopup* popup, void* data) { + [this, &renderdata](WP popup, void* data) { if (!popup->m_pWLSurface || !popup->m_pWLSurface->resource() || !popup->m_bMapped) return; From 4abf9155ee67ee09116948b1d9efef58c08697d9 Mon Sep 17 00:00:00 2001 From: Maximilian Seidler <78690852+PaideiaDilemma@users.noreply.github.com> Date: Sun, 26 Jan 2025 13:00:52 +0000 Subject: [PATCH 0915/2181] window: only set m_iMonitorMovedFrom when the workspace is visible (#9178) --- src/desktop/Window.cpp | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/src/desktop/Window.cpp b/src/desktop/Window.cpp index 9dcdb385..e59a8d4e 100644 --- a/src/desktop/Window.cpp +++ b/src/desktop/Window.cpp @@ -422,10 +422,12 @@ void CWindow::moveToWorkspace(PHLWORKSPACE pWorkspace) { const auto OLDWORKSPACE = m_pWorkspace; - m_fMovingToWorkspaceAlpha->setValueAndWarp(1.F); - *m_fMovingToWorkspaceAlpha = 0.F; - m_fMovingToWorkspaceAlpha->setCallbackOnEnd([this](auto) { m_iMonitorMovedFrom = -1; }); - m_iMonitorMovedFrom = OLDWORKSPACE ? OLDWORKSPACE->monitorID() : -1; + if (OLDWORKSPACE->isVisible()) { + m_fMovingToWorkspaceAlpha->setValueAndWarp(1.F); + *m_fMovingToWorkspaceAlpha = 0.F; + m_fMovingToWorkspaceAlpha->setCallbackOnEnd([this](auto) { m_iMonitorMovedFrom = -1; }); + m_iMonitorMovedFrom = OLDWORKSPACE ? OLDWORKSPACE->monitorID() : -1; + } m_pWorkspace = pWorkspace; From 74d0f34cf396f4fc41ee98b000e7d0a4e277c066 Mon Sep 17 00:00:00 2001 From: Vaxry Date: Sun, 26 Jan 2025 14:25:49 +0000 Subject: [PATCH 0916/2181] pointer: always scale the cpu cursor to the right size fixes #9003 --- src/managers/PointerManager.cpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/managers/PointerManager.cpp b/src/managers/PointerManager.cpp index df145f6d..5fdfa553 100644 --- a/src/managers/PointerManager.cpp +++ b/src/managers/PointerManager.cpp @@ -507,6 +507,10 @@ SP CPointerManager::renderHWCursorBuffer(SPmonitor->transform; + // we need to scale the cursor to the right size, because it might not be (esp with XCursor) + const auto SCALE = texture->m_vSize / (currentCursorImage.size / currentCursorImage.scale * state->monitor->scale); + cairo_matrix_scale(&matrixPre, SCALE.x, SCALE.y); + if (TR) { cairo_matrix_rotate(&matrixPre, M_PI_2 * (double)TR); From 16aeb24bc1395b46d675ec3522ed452e487f5b69 Mon Sep 17 00:00:00 2001 From: Vaxry Date: Sun, 26 Jan 2025 14:40:42 +0000 Subject: [PATCH 0917/2181] core: make persistent workspaces always follow the config instead of just staying after open, they will now be enforced on their respective monitors fixes #8769 --- src/Compositor.cpp | 43 ++++++++++++++++++++++++++++++++++++ src/Compositor.hpp | 2 ++ src/config/ConfigManager.cpp | 8 +++++++ src/config/ConfigManager.hpp | 1 + src/helpers/Monitor.cpp | 2 ++ 5 files changed, 56 insertions(+) diff --git a/src/Compositor.cpp b/src/Compositor.cpp index 43efdac1..3421c314 100644 --- a/src/Compositor.cpp +++ b/src/Compositor.cpp @@ -3024,3 +3024,46 @@ bool CCompositor::shouldChangePreferredImageDescription() { Debug::log(WARN, "FIXME: color management protocol is enabled and outputs changed, check preferred image description changes"); return false; } + +void CCompositor::ensurePersistentWorkspacesPresent(const std::vector& rules) { + for (const auto& rule : rules) { + if (!rule.isPersistent) + continue; + + const auto PMONITOR = getMonitorFromString(rule.monitor); + + if (!PMONITOR) { + Debug::log(ERR, "ensurePersistentWorkspacesPresent: couldn't resolve monitor for {}, skipping", rule.monitor); + continue; + } + + WORKSPACEID id = rule.workspaceId; + std::string wsname = rule.workspaceName; + if (id == WORKSPACE_INVALID) { + const auto R = getWorkspaceIDNameFromString(rule.workspaceString); + id = R.id; + wsname = R.name; + } + + if (id == WORKSPACE_INVALID) { + Debug::log(ERR, "ensurePersistentWorkspacesPresent: couldn't resolve id for workspace {}", rule.workspaceString); + continue; + } + + if (const auto PWORKSPACE = getWorkspaceByID(id); PWORKSPACE) { + if (PWORKSPACE->m_pMonitor == PMONITOR) { + Debug::log(LOG, "ensurePersistentWorkspacesPresent: workspace persistent {} already on {}", rule.workspaceString, PMONITOR->szName); + continue; + } + + Debug::log(LOG, "ensurePersistentWorkspacesPresent: workspace persistent {} not on {}, moving", rule.workspaceString, PMONITOR->szName); + moveWorkspaceToMonitor(PWORKSPACE, PMONITOR); + continue; + } + + createNewWorkspace(id, PMONITOR ? PMONITOR : m_pLastMonitor.lock(), wsname, false); + } + + // cleanup old + sanityCheckWorkspaces(); +} diff --git a/src/Compositor.hpp b/src/Compositor.hpp index 295878df..e55d7e1e 100644 --- a/src/Compositor.hpp +++ b/src/Compositor.hpp @@ -15,6 +15,7 @@ #include class CWLSurfaceResource; +struct SWorkspaceRule; enum eManagersInitStage : uint8_t { STAGE_PRIORITY = 0, @@ -151,6 +152,7 @@ class CCompositor { void setPreferredTransformForSurface(SP pSurface, wl_output_transform transform); void updateSuspendedStates(); void onNewMonitor(SP output); + void ensurePersistentWorkspacesPresent(const std::vector& rules); SImageDescription getPreferredImageDescription(); bool shouldChangePreferredImageDescription(); diff --git a/src/config/ConfigManager.cpp b/src/config/ConfigManager.cpp index fd4783da..93289bf7 100644 --- a/src/config/ConfigManager.cpp +++ b/src/config/ConfigManager.cpp @@ -1034,6 +1034,10 @@ void CConfigManager::postConfigReload(const Hyprlang::CParseResult& result) { // update plugins handlePluginLoads(); + // update persistent workspaces + if (!isFirstLaunch) + ensurePersistentWorkspacesPresent(); + EMIT_HOOK_EVENT("configReloaded", nullptr); if (g_pEventManager) g_pEventManager->postEvent(SHyprIPCEvent{"configreloaded", ""}); @@ -2830,3 +2834,7 @@ std::string SConfigOptionDescription::jsonify() const { return json; } + +void CConfigManager::ensurePersistentWorkspacesPresent() { + g_pCompositor->ensurePersistentWorkspacesPresent(m_vWorkspaceRules); +} diff --git a/src/config/ConfigManager.hpp b/src/config/ConfigManager.hpp index 564c1ebf..ae0ba759 100644 --- a/src/config/ConfigManager.hpp +++ b/src/config/ConfigManager.hpp @@ -169,6 +169,7 @@ class CConfigManager { std::vector> getMatchingRules(PHLWINDOW, bool dynamic = true, bool shadowExec = false); std::vector> getMatchingRules(PHLLS); + void ensurePersistentWorkspacesPresent(); const std::vector& getAllDescriptions(); diff --git a/src/helpers/Monitor.cpp b/src/helpers/Monitor.cpp index 1f00e4ad..6fcaeeee 100644 --- a/src/helpers/Monitor.cpp +++ b/src/helpers/Monitor.cpp @@ -51,6 +51,8 @@ void CMonitor::onConnect(bool noRule) { EMIT_HOOK_EVENT("preMonitorAdded", self.lock()); CScopeGuard x = {[]() { g_pCompositor->arrangeMonitors(); }}; + g_pEventLoopManager->doLater([] { g_pConfigManager->ensurePersistentWorkspacesPresent(); }); + if (output->supportsExplicit) { inTimeline = CSyncTimeline::create(output->getBackend()->drmFD()); outTimeline = CSyncTimeline::create(output->getBackend()->drmFD()); From e9510115039e7ae9fcf2778e8455e7beed3424ea Mon Sep 17 00:00:00 2001 From: Vaxry Date: Sun, 26 Jan 2025 15:05:34 +0000 Subject: [PATCH 0918/2181] renderer/internal: stop using box pointers in favor of const refs --- src/debug/HyprDebugOverlay.cpp | 4 +- src/debug/HyprNotificationOverlay.cpp | 6 +- src/desktop/LayerSurface.cpp | 10 +- src/desktop/Popup.cpp | 10 +- src/desktop/Subsurface.cpp | 10 +- src/events/Windows.cpp | 5 +- src/helpers/Monitor.cpp | 8 +- src/helpers/Monitor.hpp | 4 +- src/hyprerror/HyprError.cpp | 4 +- src/layout/IHyprLayout.cpp | 8 +- src/managers/AnimationManager.cpp | 8 +- src/managers/PointerManager.cpp | 6 +- src/managers/XWaylandManager.cpp | 24 ++- src/managers/XWaylandManager.hpp | 2 +- src/managers/input/InputMethodPopup.cpp | 2 +- src/protocols/AlphaModifier.cpp | 2 +- src/protocols/HyprlandSurface.cpp | 2 +- src/protocols/Screencopy.cpp | 4 +- src/protocols/core/DataDevice.cpp | 2 +- src/render/OpenGL.cpp | 182 ++++++++---------- src/render/OpenGL.hpp | 130 ++++++------- src/render/Renderer.cpp | 25 ++- src/render/Renderer.hpp | 2 +- .../decorations/CHyprDropShadowDecoration.cpp | 16 +- .../decorations/CHyprDropShadowDecoration.hpp | 2 +- .../decorations/CHyprGroupBarDecoration.cpp | 2 +- src/render/pass/BorderPassElement.cpp | 4 +- src/render/pass/Pass.cpp | 14 +- src/render/pass/RectPassElement.cpp | 4 +- src/render/pass/SurfacePassElement.cpp | 8 +- src/render/pass/TexPassElement.cpp | 2 +- src/render/pass/TextureMatteElement.cpp | 4 +- 32 files changed, 252 insertions(+), 264 deletions(-) diff --git a/src/debug/HyprDebugOverlay.cpp b/src/debug/HyprDebugOverlay.cpp index 6e7a0407..9ea7f1bc 100644 --- a/src/debug/HyprDebugOverlay.cpp +++ b/src/debug/HyprDebugOverlay.cpp @@ -198,10 +198,10 @@ int CHyprMonitorDebugOverlay::draw(int offset) { double posX = 0, posY = 0; cairo_get_current_point(cr, &posX, &posY); - g_pHyprRenderer->damageBox(&m_wbLastDrawnBox); + g_pHyprRenderer->damageBox(m_wbLastDrawnBox); m_wbLastDrawnBox = {(int)g_pCompositor->m_vMonitors.front()->vecPosition.x + MARGIN_LEFT - 1, (int)g_pCompositor->m_vMonitors.front()->vecPosition.y + offset + MARGIN_TOP - 1, (int)maxTextW + 2, posY - offset - MARGIN_TOP + 2}; - g_pHyprRenderer->damageBox(&m_wbLastDrawnBox); + g_pHyprRenderer->damageBox(m_wbLastDrawnBox); return posY - offset; } diff --git a/src/debug/HyprNotificationOverlay.cpp b/src/debug/HyprNotificationOverlay.cpp index 66c68d08..4081af84 100644 --- a/src/debug/HyprNotificationOverlay.cpp +++ b/src/debug/HyprNotificationOverlay.cpp @@ -26,7 +26,7 @@ CHyprNotificationOverlay::CHyprNotificationOverlay() { if (m_vNotifications.size() == 0) return; - g_pHyprRenderer->damageBox(&m_bLastDamage); + g_pHyprRenderer->damageBox(m_bLastDamage); }); m_pTexture = makeShared(); @@ -225,8 +225,8 @@ void CHyprNotificationOverlay::draw(PHLMONITOR pMonitor) { CBox damage = drawNotifications(pMonitor); - g_pHyprRenderer->damageBox(&damage); - g_pHyprRenderer->damageBox(&m_bLastDamage); + g_pHyprRenderer->damageBox(damage); + g_pHyprRenderer->damageBox(m_bLastDamage); g_pCompositor->scheduleFrameForMonitor(pMonitor); diff --git a/src/desktop/LayerSurface.cpp b/src/desktop/LayerSurface.cpp index c2b07c5d..e2d0177b 100644 --- a/src/desktop/LayerSurface.cpp +++ b/src/desktop/LayerSurface.cpp @@ -115,7 +115,7 @@ void CLayerSurface::onDestroy() { // and damage CBox geomFixed = {geometry.x + PMONITOR->vecPosition.x, geometry.y + PMONITOR->vecPosition.y, geometry.width, geometry.height}; - g_pHyprRenderer->damageBox(&geomFixed); + g_pHyprRenderer->damageBox(geomFixed); } readyToDelete = true; @@ -179,7 +179,7 @@ void CLayerSurface::onMap() { position = Vector2D(geometry.x, geometry.y); CBox geomFixed = {geometry.x + PMONITOR->vecPosition.x, geometry.y + PMONITOR->vecPosition.y, geometry.width, geometry.height}; - g_pHyprRenderer->damageBox(&geomFixed); + g_pHyprRenderer->damageBox(geomFixed); const bool FULLSCREEN = PMONITOR->activeWorkspace && PMONITOR->activeWorkspace->m_bHasFullscreenWindow && PMONITOR->activeWorkspace->m_efFullscreenMode == FSMODE_FULLSCREEN; startAnimation(!(layer == ZWLR_LAYER_SHELL_V1_LAYER_TOP && FULLSCREEN && !GRABSFOCUS)); @@ -240,11 +240,11 @@ void CLayerSurface::onUnmap() { g_pSeatManager->setKeyboardFocus(g_pCompositor->m_pLastFocus.lock()); CBox geomFixed = {geometry.x + PMONITOR->vecPosition.x, geometry.y + PMONITOR->vecPosition.y, geometry.width, geometry.height}; - g_pHyprRenderer->damageBox(&geomFixed); + g_pHyprRenderer->damageBox(geomFixed); geomFixed = {geometry.x + (int)PMONITOR->vecPosition.x, geometry.y + (int)PMONITOR->vecPosition.y, (int)layerSurface->surface->current.size.x, (int)layerSurface->surface->current.size.y}; - g_pHyprRenderer->damageBox(&geomFixed); + g_pHyprRenderer->damageBox(geomFixed); g_pInputManager->simulateMouseMovement(); @@ -275,7 +275,7 @@ void CLayerSurface::onCommit() { g_pHyprOpenGL->markBlurDirtyForMonitor(PMONITOR); // so that blur is recalc'd CBox geomFixed = {geometry.x, geometry.y, geometry.width, geometry.height}; - g_pHyprRenderer->damageBox(&geomFixed); + g_pHyprRenderer->damageBox(geomFixed); if (layerSurface->current.committed != 0) { if (layerSurface->current.committed & CLayerShellResource::eCommittedState::STATE_LAYER) { diff --git a/src/desktop/Popup.cpp b/src/desktop/Popup.cpp index 0c7c72a4..93a810ff 100644 --- a/src/desktop/Popup.cpp +++ b/src/desktop/Popup.cpp @@ -85,7 +85,7 @@ void CPopup::onMap() { CBox box = m_pWLSurface->resource()->extends(); box.translate(COORDS).expand(4); - g_pHyprRenderer->damageBox(&box); + g_pHyprRenderer->damageBox(box); m_vLastPos = coordsRelativeToParent(); @@ -120,7 +120,7 @@ void CPopup::onUnmap() { CBox box = m_pWLSurface->resource()->extends(); box.translate(COORDS).expand(4); - g_pHyprRenderer->damageBox(&box); + g_pHyprRenderer->damageBox(box); m_pSubsurfaceHead.reset(); @@ -134,7 +134,7 @@ void CPopup::onUnmap() { return; auto box = CBox{p->coordsGlobal(), p->size()}; - g_pHyprRenderer->damageBox(&box); + g_pHyprRenderer->damageBox(box); }, nullptr); @@ -173,10 +173,10 @@ void CPopup::onCommit(bool ignoreSiblings) { if (m_vLastSize != m_pResource->surface->surface->current.size || m_bRequestedReposition || m_vLastPos != COORDSLOCAL) { CBox box = {localToGlobal(m_vLastPos), m_vLastSize}; - g_pHyprRenderer->damageBox(&box); + g_pHyprRenderer->damageBox(box); m_vLastSize = m_pResource->surface->surface->current.size; box = {COORDS, m_vLastSize}; - g_pHyprRenderer->damageBox(&box); + g_pHyprRenderer->damageBox(box); m_vLastPos = COORDSLOCAL; } diff --git a/src/desktop/Subsurface.cpp b/src/desktop/Subsurface.cpp index 5657cb39..a68cf8f3 100644 --- a/src/desktop/Subsurface.cpp +++ b/src/desktop/Subsurface.cpp @@ -103,10 +103,10 @@ void CSubsurface::onCommit() { if (m_vLastSize != m_pWLSurface->resource()->current.size) { // TODO: fix this // CBox box{COORDS, m_vLastSize}; - // g_pHyprRenderer->damageBox(&box); + // g_pHyprRenderer->damageBox(box); // m_vLastSize = m_pWLSurface->resource()->current.size; // box = {COORDS, m_vLastSize}; - // g_pHyprRenderer->damageBox(&box); + // g_pHyprRenderer->damageBox(box); CBox box; if (m_pPopupParent) @@ -114,7 +114,7 @@ void CSubsurface::onCommit() { else if (m_pWindowParent) box = m_pWindowParent->getWindowMainSurfaceBox(); - g_pHyprRenderer->damageBox(&box); + g_pHyprRenderer->damageBox(box); } } @@ -152,7 +152,7 @@ void CSubsurface::onMap() { const auto COORDS = coordsGlobal(); CBox box{COORDS, m_vLastSize}; box.expand(4); - g_pHyprRenderer->damageBox(&box); + g_pHyprRenderer->damageBox(box); if (!m_pWindowParent.expired()) m_pWindowParent->updateSurfaceScaleTransformDetails(); @@ -162,7 +162,7 @@ void CSubsurface::onUnmap() { const auto COORDS = coordsGlobal(); CBox box{COORDS, m_vLastSize}; box.expand(4); - g_pHyprRenderer->damageBox(&box); + g_pHyprRenderer->damageBox(box); if (m_pWLSurface->resource() == g_pCompositor->m_pLastFocus) g_pInputManager->releaseAllMouseButtons(); diff --git a/src/events/Windows.cpp b/src/events/Windows.cpp index 9ecf3652..f6ef9ced 100644 --- a/src/events/Windows.cpp +++ b/src/events/Windows.cpp @@ -376,9 +376,8 @@ void Events::listener_mapWindow(void* owner, void* data) { if (PWORKSPACE->m_bDefaultPseudo) { PWINDOW->m_bIsPseudotiled = true; - CBox desiredGeometry = {0}; - g_pXWaylandManager->getGeometryForWindow(PWINDOW, &desiredGeometry); - PWINDOW->m_vPseudoSize = Vector2D(desiredGeometry.width, desiredGeometry.height); + CBox desiredGeometry = g_pXWaylandManager->getGeometryForWindow(PWINDOW); + PWINDOW->m_vPseudoSize = Vector2D(desiredGeometry.width, desiredGeometry.height); } PWINDOW->updateWindowData(); diff --git a/src/helpers/Monitor.cpp b/src/helpers/Monitor.cpp index 6fcaeeee..19d68a56 100644 --- a/src/helpers/Monitor.cpp +++ b/src/helpers/Monitor.cpp @@ -766,18 +766,18 @@ void CMonitor::addDamage(const pixman_region32_t* rg) { g_pCompositor->scheduleFrameForMonitor(self.lock(), Aquamarine::IOutput::AQ_SCHEDULE_DAMAGE); } -void CMonitor::addDamage(const CRegion* rg) { - addDamage(const_cast(rg)->pixman()); +void CMonitor::addDamage(const CRegion& rg) { + addDamage(const_cast(&rg)->pixman()); } -void CMonitor::addDamage(const CBox* box) { +void CMonitor::addDamage(const CBox& box) { static auto PZOOMFACTOR = CConfigValue("cursor:zoom_factor"); if (*PZOOMFACTOR != 1.f && g_pCompositor->getMonitorFromCursor() == self) { damage.damageEntire(); g_pCompositor->scheduleFrameForMonitor(self.lock(), Aquamarine::IOutput::AQ_SCHEDULE_DAMAGE); } - if (damage.damage(*box)) + if (damage.damage(box)) g_pCompositor->scheduleFrameForMonitor(self.lock(), Aquamarine::IOutput::AQ_SCHEDULE_DAMAGE); } diff --git a/src/helpers/Monitor.hpp b/src/helpers/Monitor.hpp index e07d62c6..7c19b57c 100644 --- a/src/helpers/Monitor.hpp +++ b/src/helpers/Monitor.hpp @@ -166,8 +166,8 @@ class CMonitor { void onDisconnect(bool destroy = false); bool applyMonitorRule(SMonitorRule* pMonitorRule, bool force = false); void addDamage(const pixman_region32_t* rg); - void addDamage(const CRegion* rg); - void addDamage(const CBox* box); + void addDamage(const CRegion& rg); + void addDamage(const CBox& box); bool shouldSkipScheduleFrameOnMouseEvent(); void setMirror(const std::string&); bool isMirror(); diff --git a/src/hyprerror/HyprError.cpp b/src/hyprerror/HyprError.cpp index d14173bf..4076ed3a 100644 --- a/src/hyprerror/HyprError.cpp +++ b/src/hyprerror/HyprError.cpp @@ -26,7 +26,7 @@ CHyprError::CHyprError() { return; if (m_fFadeOpacity->isBeingAnimated() || m_bMonitorChanged) - g_pHyprRenderer->damageBox(&m_bDamageBox); + g_pHyprRenderer->damageBox(m_bDamageBox); }); m_pTexture = makeShared(); @@ -203,7 +203,7 @@ void CHyprError::draw() { m_bDamageBox.y = (int)PMONITOR->vecPosition.y; if (m_fFadeOpacity->isBeingAnimated() || m_bMonitorChanged) - g_pHyprRenderer->damageBox(&m_bDamageBox); + g_pHyprRenderer->damageBox(m_bDamageBox); m_bMonitorChanged = false; diff --git a/src/layout/IHyprLayout.cpp b/src/layout/IHyprLayout.cpp index 81392be9..5e5669b8 100644 --- a/src/layout/IHyprLayout.cpp +++ b/src/layout/IHyprLayout.cpp @@ -14,8 +14,7 @@ #include "../managers/HookSystemManager.hpp" void IHyprLayout::onWindowCreated(PHLWINDOW pWindow, eDirection direction) { - CBox desiredGeometry = {}; - g_pXWaylandManager->getGeometryForWindow(pWindow, &desiredGeometry); + CBox desiredGeometry = g_pXWaylandManager->getGeometryForWindow(pWindow); if (desiredGeometry.width <= 5 || desiredGeometry.height <= 5) { const auto PMONITOR = pWindow->m_pMonitor.lock(); @@ -91,9 +90,8 @@ void IHyprLayout::onWindowRemovedFloating(PHLWINDOW pWindow) { void IHyprLayout::onWindowCreatedFloating(PHLWINDOW pWindow) { - CBox desiredGeometry = {0}; - g_pXWaylandManager->getGeometryForWindow(pWindow, &desiredGeometry); - const auto PMONITOR = pWindow->m_pMonitor.lock(); + CBox desiredGeometry = g_pXWaylandManager->getGeometryForWindow(pWindow); + const auto PMONITOR = pWindow->m_pMonitor.lock(); if (pWindow->m_bIsX11) { Vector2D xy = {desiredGeometry.x, desiredGeometry.y}; diff --git a/src/managers/AnimationManager.cpp b/src/managers/AnimationManager.cpp index 964f7cfa..5be7aa33 100644 --- a/src/managers/AnimationManager.cpp +++ b/src/managers/AnimationManager.cpp @@ -41,7 +41,7 @@ CHyprAnimationManager::CHyprAnimationManager() { } template -void updateVariable(CAnimatedVariable& av, const float POINTY, bool warp = false) { +static void updateVariable(CAnimatedVariable& av, const float POINTY, bool warp = false) { if (warp || av.value() == av.goal()) { av.warp(); return; @@ -51,7 +51,7 @@ void updateVariable(CAnimatedVariable& av, const float POINTY, bool war av.value() = av.begun() + DELTA * POINTY; } -void updateColorVariable(CAnimatedVariable& av, const float POINTY, bool warp) { +static void updateColorVariable(CAnimatedVariable& av, const float POINTY, bool warp) { if (warp || av.value() == av.goal()) { av.warp(); return; @@ -137,7 +137,7 @@ static void handleUpdate(CAnimatedVariable& av, bool warp) { // "some fucking layers miss 1 pixel???" -- vaxry CBox expandBox = CBox{PLAYER->realPosition->value(), PLAYER->realSize->value()}; expandBox.expand(5); - g_pHyprRenderer->damageBox(&expandBox); + g_pHyprRenderer->damageBox(expandBox); PMONITOR = g_pCompositor->getMonitorFromVector(PLAYER->realPosition->goal() + PLAYER->realSize->goal() / 2.F); if (!PMONITOR) @@ -180,7 +180,7 @@ static void handleUpdate(CAnimatedVariable& av, bool warp) { // some fucking layers miss 1 pixel??? CBox expandBox = CBox{PLAYER->realPosition->value(), PLAYER->realSize->value()}; expandBox.expand(5); - g_pHyprRenderer->damageBox(&expandBox); + g_pHyprRenderer->damageBox(expandBox); } break; } diff --git a/src/managers/PointerManager.cpp b/src/managers/PointerManager.cpp index 5fdfa553..48ef5e16 100644 --- a/src/managers/PointerManager.cpp +++ b/src/managers/PointerManager.cpp @@ -566,7 +566,7 @@ SP CPointerManager::renderHWCursorBuffer(SPmonitor->szName, currentCursorImage.size, cursorSize, currentCursorImage.scale, state->monitor->scale, xbox.size()); - g_pHyprOpenGL->renderTexture(texture, &xbox, 1.F); + g_pHyprOpenGL->renderTexture(texture, xbox, 1.F); g_pHyprOpenGL->end(); glFlush(); @@ -730,7 +730,7 @@ void CPointerManager::damageIfSoftware() { continue; if ((mw->softwareLocks > 0 || mw->hardwareFailed || g_pConfigManager->shouldUseSoftwareCursors()) && b.overlaps({mw->monitor->vecPosition, mw->monitor->vecSize})) { - g_pHyprRenderer->damageBox(&b, mw->monitor->shouldSkipScheduleFrameOnMouseEvent()); + g_pHyprRenderer->damageBox(b, mw->monitor->shouldSkipScheduleFrameOnMouseEvent()); break; } } @@ -1143,7 +1143,7 @@ void CPointerManager::damageCursor(PHLMONITOR pMonitor) { if (b.empty()) return; - g_pHyprRenderer->damageBox(&b); + g_pHyprRenderer->damageBox(b); return; } diff --git a/src/managers/XWaylandManager.cpp b/src/managers/XWaylandManager.cpp index ea2a47ea..f103266d 100644 --- a/src/managers/XWaylandManager.cpp +++ b/src/managers/XWaylandManager.cpp @@ -76,9 +76,11 @@ void CHyprXWaylandManager::activateWindow(PHLWINDOW pWindow, bool activate) { pWindow->m_pWorkspace->m_pLastFocusedWindow = pWindow; } -void CHyprXWaylandManager::getGeometryForWindow(PHLWINDOW pWindow, CBox* pbox) { +CBox CHyprXWaylandManager::getGeometryForWindow(PHLWINDOW pWindow) { if (!pWindow) - return; + return {}; + + CBox box; if (pWindow->m_bIsX11) { const auto SIZEHINTS = pWindow->m_pXWaylandSurface->sizeHints.get(); @@ -86,24 +88,26 @@ void CHyprXWaylandManager::getGeometryForWindow(PHLWINDOW pWindow, CBox* pbox) { if (SIZEHINTS && !pWindow->isX11OverrideRedirect()) { // WM_SIZE_HINTS' x,y,w,h is deprecated it seems. // Source: https://x.org/releases/X11R7.6/doc/xorg-docs/specs/ICCCM/icccm.html#wm_normal_hints_property - pbox->x = pWindow->m_pXWaylandSurface->geometry.x; - pbox->y = pWindow->m_pXWaylandSurface->geometry.y; + box.x = pWindow->m_pXWaylandSurface->geometry.x; + box.y = pWindow->m_pXWaylandSurface->geometry.y; constexpr int ICCCM_USSize = 0x2; constexpr int ICCCM_PSize = 0x8; if ((SIZEHINTS->flags & ICCCM_USSize) || (SIZEHINTS->flags & ICCCM_PSize)) { - pbox->w = SIZEHINTS->base_width; - pbox->h = SIZEHINTS->base_height; + box.w = SIZEHINTS->base_width; + box.h = SIZEHINTS->base_height; } else { - pbox->w = pWindow->m_pXWaylandSurface->geometry.w; - pbox->h = pWindow->m_pXWaylandSurface->geometry.h; + box.w = pWindow->m_pXWaylandSurface->geometry.w; + box.h = pWindow->m_pXWaylandSurface->geometry.h; } } else - *pbox = pWindow->m_pXWaylandSurface->geometry; + box = pWindow->m_pXWaylandSurface->geometry; } else if (pWindow->m_pXDGSurface) - *pbox = pWindow->m_pXDGSurface->current.geometry; + box = pWindow->m_pXDGSurface->current.geometry; + + return box; } void CHyprXWaylandManager::sendCloseWindow(PHLWINDOW pWindow) { diff --git a/src/managers/XWaylandManager.hpp b/src/managers/XWaylandManager.hpp index edbdd243..e4f1e17a 100644 --- a/src/managers/XWaylandManager.hpp +++ b/src/managers/XWaylandManager.hpp @@ -15,7 +15,7 @@ class CHyprXWaylandManager { SP getWindowSurface(PHLWINDOW); void activateSurface(SP, bool); void activateWindow(PHLWINDOW, bool); - void getGeometryForWindow(PHLWINDOW, CBox*); + CBox getGeometryForWindow(PHLWINDOW); void sendCloseWindow(PHLWINDOW); void setWindowFullscreen(PHLWINDOW, bool); bool shouldBeFloated(PHLWINDOW, bool pending = false); diff --git a/src/managers/input/InputMethodPopup.cpp b/src/managers/input/InputMethodPopup.cpp index 8c55416b..db08c026 100644 --- a/src/managers/input/InputMethodPopup.cpp +++ b/src/managers/input/InputMethodPopup.cpp @@ -61,7 +61,7 @@ void CInputPopup::damageEntire() { return; } CBox box = globalBox(); - g_pHyprRenderer->damageBox(&box); + g_pHyprRenderer->damageBox(box); } void CInputPopup::damageSurface() { diff --git a/src/protocols/AlphaModifier.cpp b/src/protocols/AlphaModifier.cpp index e8766405..60037632 100644 --- a/src/protocols/AlphaModifier.cpp +++ b/src/protocols/AlphaModifier.cpp @@ -38,7 +38,7 @@ void CAlphaModifier::setResource(SP resource) { auto box = surface->getSurfaceBoxGlobal(); if (box.has_value()) - g_pHyprRenderer->damageBox(&*box); + g_pHyprRenderer->damageBox(*box); if (!m_pResource) PROTO::alphaModifier->destroyAlphaModifier(this); diff --git a/src/protocols/HyprlandSurface.cpp b/src/protocols/HyprlandSurface.cpp index e3716f10..8b65f0fa 100644 --- a/src/protocols/HyprlandSurface.cpp +++ b/src/protocols/HyprlandSurface.cpp @@ -60,7 +60,7 @@ void CHyprlandSurface::setResource(SP resource) { auto box = surface->getSurfaceBoxGlobal(); if (box.has_value()) - g_pHyprRenderer->damageBox(&*box); + g_pHyprRenderer->damageBox(*box); if (!m_pResource) PROTO::hyprlandSurface->destroySurface(this); diff --git a/src/protocols/Screencopy.cpp b/src/protocols/Screencopy.cpp index e0e3a559..e086cc76 100644 --- a/src/protocols/Screencopy.cpp +++ b/src/protocols/Screencopy.cpp @@ -214,7 +214,7 @@ bool CScreencopyFrame::copyDmabuf() { .transform(wlTransformToHyprutils(invertTransform(pMonitor->transform)), pMonitor->vecPixelSize.x, pMonitor->vecPixelSize.y); g_pHyprOpenGL->setMonitorTransformEnabled(true); g_pHyprOpenGL->setRenderModifEnabled(false); - g_pHyprOpenGL->renderTexture(TEXTURE, &monbox, 1); + g_pHyprOpenGL->renderTexture(TEXTURE, monbox, 1); g_pHyprOpenGL->setRenderModifEnabled(true); g_pHyprOpenGL->setMonitorTransformEnabled(false); @@ -247,7 +247,7 @@ bool CScreencopyFrame::copyShm() { CBox monbox = CBox{0, 0, pMonitor->vecTransformedSize.x, pMonitor->vecTransformedSize.y}.translate({-box.x, -box.y}); g_pHyprOpenGL->setMonitorTransformEnabled(true); g_pHyprOpenGL->setRenderModifEnabled(false); - g_pHyprOpenGL->renderTexture(TEXTURE, &monbox, 1); + g_pHyprOpenGL->renderTexture(TEXTURE, monbox, 1); g_pHyprOpenGL->setRenderModifEnabled(true); g_pHyprOpenGL->setMonitorTransformEnabled(false); diff --git a/src/protocols/core/DataDevice.cpp b/src/protocols/core/DataDevice.cpp index 36437dd4..e17b5612 100644 --- a/src/protocols/core/DataDevice.cpp +++ b/src/protocols/core/DataDevice.cpp @@ -806,7 +806,7 @@ void CWLDataDeviceProtocol::renderDND(PHLMONITOR pMonitor, timespec* when) { g_pHyprRenderer->m_sRenderPass.add(makeShared(data)); box = CBox{POS, dnd.dndSurface->current.size}.translate(g_pPointerManager->cursorSizeLogical() / 2.F).expand(5); - g_pHyprRenderer->damageBox(&box); + g_pHyprRenderer->damageBox(box); dnd.dndSurface->frame(when); } diff --git a/src/render/OpenGL.cpp b/src/render/OpenGL.cpp index 0fe9565f..f0b2f447 100644 --- a/src/render/OpenGL.cpp +++ b/src/render/OpenGL.cpp @@ -935,15 +935,15 @@ void CHyprOpenGLImpl::end() { // copy the damaged areas into the mirror buffer // we can't use the offloadFB for mirroring, as it contains artifacts from blurring if (!m_RenderData.pMonitor->mirrors.empty() && !m_bFakeFrame) - saveBufferForMirror(&monbox); + saveBufferForMirror(monbox); m_RenderData.outFB->bind(); blend(false); if (m_sFinalScreenShader.program < 1 && !g_pHyprRenderer->m_bCrashingInProgress) - renderTexturePrimitive(m_RenderData.pCurrentMonData->offloadFB.getTexture(), &monbox); + renderTexturePrimitive(m_RenderData.pCurrentMonData->offloadFB.getTexture(), monbox); else - renderTexture(m_RenderData.pCurrentMonData->offloadFB.getTexture(), &monbox, 1.f); + renderTexture(m_RenderData.pCurrentMonData->offloadFB.getTexture(), monbox, 1.f); blend(true); @@ -1214,7 +1214,7 @@ void CHyprOpenGLImpl::clear(const CHyprColor& color) { } } - scissor((CBox*)nullptr); + scissor(nullptr); } void CHyprOpenGLImpl::blend(bool enabled) { @@ -1227,22 +1227,19 @@ void CHyprOpenGLImpl::blend(bool enabled) { m_bBlend = enabled; } -void CHyprOpenGLImpl::scissor(const CBox* pBox, bool transform) { +void CHyprOpenGLImpl::scissor(const CBox& originalBox, bool transform) { RASSERT(m_RenderData.pMonitor, "Tried to scissor without begin()!"); - if (!pBox) { - glDisable(GL_SCISSOR_TEST); + if (transform) { + CBox box = originalBox; + const auto TR = wlTransformToHyprutils(invertTransform(m_RenderData.pMonitor->transform)); + box.transform(TR, m_RenderData.pMonitor->vecTransformedSize.x, m_RenderData.pMonitor->vecTransformedSize.y); + glScissor(box.x, box.y, box.width, box.height); + glEnable(GL_SCISSOR_TEST); return; } - CBox newBox = *pBox; - - if (transform) { - const auto TR = wlTransformToHyprutils(invertTransform(m_RenderData.pMonitor->transform)); - newBox.transform(TR, m_RenderData.pMonitor->vecTransformedSize.x, m_RenderData.pMonitor->vecTransformedSize.y); - } - - glScissor(newBox.x, newBox.y, newBox.width, newBox.height); + glScissor(originalBox.x, originalBox.y, originalBox.width, originalBox.height); glEnable(GL_SCISSOR_TEST); } @@ -1256,32 +1253,32 @@ void CHyprOpenGLImpl::scissor(const pixman_box32* pBox, bool transform) { CBox newBox = {pBox->x1, pBox->y1, pBox->x2 - pBox->x1, pBox->y2 - pBox->y1}; - scissor(&newBox, transform); + scissor(newBox, transform); } void CHyprOpenGLImpl::scissor(const int x, const int y, const int w, const int h, bool transform) { CBox box = {x, y, w, h}; - scissor(&box, transform); + scissor(box, transform); } -void CHyprOpenGLImpl::renderRect(CBox* box, const CHyprColor& col, int round, float roundingPower) { +void CHyprOpenGLImpl::renderRect(const CBox& box, const CHyprColor& col, int round, float roundingPower) { if (!m_RenderData.damage.empty()) renderRectWithDamage(box, col, m_RenderData.damage, round, roundingPower); } -void CHyprOpenGLImpl::renderRectWithBlur(CBox* box, const CHyprColor& col, int round, float roundingPower, float blurA, bool xray) { +void CHyprOpenGLImpl::renderRectWithBlur(const CBox& box, const CHyprColor& col, int round, float roundingPower, float blurA, bool xray) { if (m_RenderData.damage.empty()) return; CRegion damage{m_RenderData.damage}; - damage.intersect(*box); + damage.intersect(box); CFramebuffer* POUTFB = xray ? &m_RenderData.pCurrentMonData->blurFB : blurMainFramebufferWithDamage(blurA, &damage); m_RenderData.currentFB->bind(); // make a stencil for rounded corners to work with blur - scissor((CBox*)nullptr); // allow the entire window and stencil to render + scissor(nullptr); // allow the entire window and stencil to render glClearStencil(0); glClear(GL_STENCIL_BUFFER_BIT); @@ -1302,7 +1299,7 @@ void CHyprOpenGLImpl::renderRectWithBlur(CBox* box, const CHyprColor& col, int r m_bEndFrame = true; // fix transformed const auto SAVEDRENDERMODIF = m_RenderData.renderModif; m_RenderData.renderModif = {}; // fix shit - renderTextureInternalWithDamage(POUTFB->getTexture(), &MONITORBOX, blurA, damage, 0, 2.0f, false, false, false); + renderTextureInternalWithDamage(POUTFB->getTexture(), MONITORBOX, blurA, damage, 0, 2.0f, false, false, false); m_bEndFrame = false; m_RenderData.renderModif = SAVEDRENDERMODIF; @@ -1311,22 +1308,20 @@ void CHyprOpenGLImpl::renderRectWithBlur(CBox* box, const CHyprColor& col, int r glDisable(GL_STENCIL_TEST); glStencilMask(0xFF); glStencilFunc(GL_ALWAYS, 1, 0xFF); - scissor((CBox*)nullptr); + scissor(nullptr); renderRectWithDamage(box, col, m_RenderData.damage, round, roundingPower); } -void CHyprOpenGLImpl::renderRectWithDamage(CBox* box, const CHyprColor& col, const CRegion& damage, int round, float roundingPower) { - RASSERT((box->width > 0 && box->height > 0), "Tried to render rect with width/height < 0!"); +void CHyprOpenGLImpl::renderRectWithDamage(const CBox& box, const CHyprColor& col, const CRegion& damage, int round, float roundingPower) { + RASSERT((box.width > 0 && box.height > 0), "Tried to render rect with width/height < 0!"); RASSERT(m_RenderData.pMonitor, "Tried to render rect without begin()!"); TRACY_GPU_ZONE("RenderRectWithDamage"); - CBox newBox = *box; + CBox newBox = box; m_RenderData.renderModif.applyToBox(newBox); - box = &newBox; - Mat3x3 matrix = m_RenderData.monitorProjection.projectBox( newBox, wlTransformToHyprutils(invertTransform(!m_bEndFrame ? WL_OUTPUT_TRANSFORM_NORMAL : m_RenderData.pMonitor->transform)), newBox.rot); Mat3x3 glMatrix = m_RenderData.projection.copy().multiply(matrix); @@ -1343,7 +1338,7 @@ void CHyprOpenGLImpl::renderRectWithDamage(CBox* box, const CHyprColor& col, con // premultiply the color as well as we don't work with straight alpha glUniform4f(m_RenderData.pCurrentMonData->m_shQUAD.color, col.r * col.a, col.g * col.a, col.b * col.a, col.a); - CBox transformedBox = *box; + CBox transformedBox = box; transformedBox.transform(wlTransformToHyprutils(invertTransform(m_RenderData.pMonitor->transform)), m_RenderData.pMonitor->vecTransformedSize.x, m_RenderData.pMonitor->vecTransformedSize.y); @@ -1379,27 +1374,27 @@ void CHyprOpenGLImpl::renderRectWithDamage(CBox* box, const CHyprColor& col, con glDisableVertexAttribArray(m_RenderData.pCurrentMonData->m_shQUAD.posAttrib); - scissor((CBox*)nullptr); + scissor(nullptr); } -void CHyprOpenGLImpl::renderTexture(SP tex, CBox* pBox, float alpha, int round, float roundingPower, bool discardActive, bool allowCustomUV) { +void CHyprOpenGLImpl::renderTexture(SP tex, const CBox& box, float alpha, int round, float roundingPower, bool discardActive, bool allowCustomUV) { RASSERT(m_RenderData.pMonitor, "Tried to render texture without begin()!"); - renderTextureInternalWithDamage(tex, pBox, alpha, m_RenderData.damage, round, roundingPower, discardActive, false, allowCustomUV, true); + renderTextureInternalWithDamage(tex, box, alpha, m_RenderData.damage, round, roundingPower, discardActive, false, allowCustomUV, true); - scissor((CBox*)nullptr); + scissor(nullptr); } -void CHyprOpenGLImpl::renderTextureWithDamage(SP tex, CBox* pBox, const CRegion& damage, float alpha, int round, float roundingPower, bool discardActive, +void CHyprOpenGLImpl::renderTextureWithDamage(SP tex, const CBox& box, const CRegion& damage, float alpha, int round, float roundingPower, bool discardActive, bool allowCustomUV, SP waitTimeline, uint64_t waitPoint) { RASSERT(m_RenderData.pMonitor, "Tried to render texture without begin()!"); - renderTextureInternalWithDamage(tex, pBox, alpha, damage, round, roundingPower, discardActive, false, allowCustomUV, true, waitTimeline, waitPoint); + renderTextureInternalWithDamage(tex, box, alpha, damage, round, roundingPower, discardActive, false, allowCustomUV, true, waitTimeline, waitPoint); - scissor((CBox*)nullptr); + scissor(nullptr); } -void CHyprOpenGLImpl::renderTextureInternalWithDamage(SP tex, CBox* pBox, float alpha, const CRegion& damage, int round, float roundingPower, bool discardActive, +void CHyprOpenGLImpl::renderTextureInternalWithDamage(SP tex, const CBox& box, float alpha, const CRegion& damage, int round, float roundingPower, bool discardActive, bool noAA, bool allowCustomUV, bool allowDim, SP waitTimeline, uint64_t waitPoint) { RASSERT(m_RenderData.pMonitor, "Tried to render texture without begin()!"); RASSERT((tex->m_iTexID > 0), "Attempted to draw nullptr texture!"); @@ -1411,7 +1406,7 @@ void CHyprOpenGLImpl::renderTextureInternalWithDamage(SP tex, CBox* pB if (damage.empty()) return; - CBox newBox = *pBox; + CBox newBox = box; m_RenderData.renderModif.applyToBox(newBox); static auto PDT = CConfigValue("debug:damage_tracking"); @@ -1584,7 +1579,7 @@ void CHyprOpenGLImpl::renderTextureInternalWithDamage(SP tex, CBox* pB glBindTexture(tex->m_iTarget, 0); } -void CHyprOpenGLImpl::renderTexturePrimitive(SP tex, CBox* pBox) { +void CHyprOpenGLImpl::renderTexturePrimitive(SP tex, const CBox& box) { RASSERT(m_RenderData.pMonitor, "Tried to render texture without begin()!"); RASSERT((tex->m_iTexID > 0), "Attempted to draw nullptr texture!"); @@ -1593,7 +1588,7 @@ void CHyprOpenGLImpl::renderTexturePrimitive(SP tex, CBox* pBox) { if (m_RenderData.damage.empty()) return; - CBox newBox = *pBox; + CBox newBox = box; m_RenderData.renderModif.applyToBox(newBox); // get transform @@ -1627,7 +1622,7 @@ void CHyprOpenGLImpl::renderTexturePrimitive(SP tex, CBox* pBox) { glDrawArrays(GL_TRIANGLE_STRIP, 0, 4); } - scissor((CBox*)nullptr); + scissor(nullptr); glDisableVertexAttribArray(shader->posAttrib); glDisableVertexAttribArray(shader->texAttrib); @@ -1635,7 +1630,7 @@ void CHyprOpenGLImpl::renderTexturePrimitive(SP tex, CBox* pBox) { glBindTexture(tex->m_iTarget, 0); } -void CHyprOpenGLImpl::renderTextureMatte(SP tex, CBox* pBox, CFramebuffer& matte) { +void CHyprOpenGLImpl::renderTextureMatte(SP tex, const CBox& box, CFramebuffer& matte) { RASSERT(m_RenderData.pMonitor, "Tried to render texture without begin()!"); RASSERT((tex->m_iTexID > 0), "Attempted to draw nullptr texture!"); @@ -1644,7 +1639,7 @@ void CHyprOpenGLImpl::renderTextureMatte(SP tex, CBox* pBox, CFramebuf if (m_RenderData.damage.empty()) return; - CBox newBox = *pBox; + CBox newBox = box; m_RenderData.renderModif.applyToBox(newBox); // get transform @@ -1683,7 +1678,7 @@ void CHyprOpenGLImpl::renderTextureMatte(SP tex, CBox* pBox, CFramebuf glDrawArrays(GL_TRIANGLE_STRIP, 0, 4); } - scissor((CBox*)nullptr); + scissor(nullptr); glDisableVertexAttribArray(shader->posAttrib); glDisableVertexAttribArray(shader->texAttrib); @@ -2013,8 +2008,7 @@ void CHyprOpenGLImpl::preBlurForCurrentMonitor() { // make the fake dmg CRegion fakeDamage{0, 0, m_RenderData.pMonitor->vecTransformedSize.x, m_RenderData.pMonitor->vecTransformedSize.y}; - CBox wholeMonitor = {0, 0, m_RenderData.pMonitor->vecTransformedSize.x, m_RenderData.pMonitor->vecTransformedSize.y}; - const auto POUTFB = blurMainFramebufferWithDamage(1, &fakeDamage); + const auto POUTFB = blurMainFramebufferWithDamage(1, &fakeDamage); // render onto blurFB m_RenderData.pCurrentMonData->blurFB.alloc(m_RenderData.pMonitor->vecPixelSize.x, m_RenderData.pMonitor->vecPixelSize.y, @@ -2024,7 +2018,8 @@ void CHyprOpenGLImpl::preBlurForCurrentMonitor() { clear(CHyprColor(0, 0, 0, 0)); m_bEndFrame = true; // fix transformed - renderTextureInternalWithDamage(POUTFB->getTexture(), &wholeMonitor, 1, fakeDamage, 0, 2.0f, false, true, false); + renderTextureInternalWithDamage(POUTFB->getTexture(), CBox{0, 0, m_RenderData.pMonitor->vecTransformedSize.x, m_RenderData.pMonitor->vecTransformedSize.y}, 1, fakeDamage, 0, + 2.0f, false, true, false); m_bEndFrame = false; m_RenderData.currentFB->bind(); @@ -2072,7 +2067,7 @@ bool CHyprOpenGLImpl::shouldUseNewBlurOptimizations(PHLLS pLayer, PHLWINDOW pWin return false; } -void CHyprOpenGLImpl::renderTextureWithBlur(SP tex, CBox* pBox, float a, SP pSurface, int round, float roundingPower, bool blockBlurOptimization, +void CHyprOpenGLImpl::renderTextureWithBlur(SP tex, const CBox& box, float a, SP pSurface, int round, float roundingPower, bool blockBlurOptimization, float blurA, float overallA) { RASSERT(m_RenderData.pMonitor, "Tried to render texture with blur without begin()!"); @@ -2082,7 +2077,7 @@ void CHyprOpenGLImpl::renderTextureWithBlur(SP tex, CBox* pBox, float // make a damage region for this window CRegion texDamage{m_RenderData.damage}; - texDamage.intersect(pBox->x, pBox->y, pBox->width, pBox->height); + texDamage.intersect(box.x, box.y, box.width, box.height); // While renderTextureInternalWithDamage will clip the blur as well, // clipping texDamage here allows blur generation to be optimized. @@ -2095,24 +2090,23 @@ void CHyprOpenGLImpl::renderTextureWithBlur(SP tex, CBox* pBox, float m_RenderData.renderModif.applyToRegion(texDamage); if (*PNOBLUROVERSIZED && m_RenderData.primarySurfaceUVTopLeft != Vector2D(-1, -1)) { - renderTexture(tex, pBox, a, round, roundingPower, false, true); + renderTexture(tex, box, a, round, roundingPower, false, true); return; } // amazing hack: the surface has an opaque region! CRegion inverseOpaque; - if (a >= 1.f && std::round(pSurface->current.size.x * m_RenderData.pMonitor->scale) == pBox->w && - std::round(pSurface->current.size.y * m_RenderData.pMonitor->scale) == pBox->h) { + if (a >= 1.f && std::round(pSurface->current.size.x * m_RenderData.pMonitor->scale) == box.w && std::round(pSurface->current.size.y * m_RenderData.pMonitor->scale) == box.h) { pixman_box32_t surfbox = {0, 0, pSurface->current.size.x * pSurface->current.scale, pSurface->current.size.y * pSurface->current.scale}; inverseOpaque = pSurface->current.opaque; inverseOpaque.invert(&surfbox).intersect(0, 0, pSurface->current.size.x * pSurface->current.scale, pSurface->current.size.y * pSurface->current.scale); if (inverseOpaque.empty()) { - renderTexture(tex, pBox, a, round, roundingPower, false, true); + renderTexture(tex, box, a, round, roundingPower, false, true); return; } } else { - inverseOpaque = {0, 0, pBox->width, pBox->height}; + inverseOpaque = {0, 0, box.width, box.height}; } inverseOpaque.scale(m_RenderData.pMonitor->scale); @@ -2122,7 +2116,7 @@ void CHyprOpenGLImpl::renderTextureWithBlur(SP tex, CBox* pBox, float CFramebuffer* POUTFB = nullptr; if (!USENEWOPTIMIZE) { - inverseOpaque.translate({pBox->x, pBox->y}); + inverseOpaque.translate(box.pos()); m_RenderData.renderModif.applyToRegion(inverseOpaque); inverseOpaque.intersect(texDamage); @@ -2133,7 +2127,7 @@ void CHyprOpenGLImpl::renderTextureWithBlur(SP tex, CBox* pBox, float m_RenderData.currentFB->bind(); // make a stencil for rounded corners to work with blur - scissor((CBox*)nullptr); // allow the entire window and stencil to render + scissor(nullptr); // allow the entire window and stencil to render glClearStencil(0); glClear(GL_STENCIL_BUFFER_BIT); @@ -2144,9 +2138,9 @@ void CHyprOpenGLImpl::renderTextureWithBlur(SP tex, CBox* pBox, float glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE); if (USENEWOPTIMIZE && !(m_RenderData.discardMode & DISCARD_ALPHA)) - renderRect(pBox, CHyprColor(0, 0, 0, 0), round, roundingPower); + renderRect(box, CHyprColor(0, 0, 0, 0), round, roundingPower); else - renderTexture(tex, pBox, a, round, roundingPower, true, true); // discard opaque + renderTexture(tex, box, a, round, roundingPower, true, true); // discard opaque glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE); glStencilFunc(GL_EQUAL, 1, 0xFF); @@ -2159,14 +2153,14 @@ void CHyprOpenGLImpl::renderTextureWithBlur(SP tex, CBox* pBox, float const auto LASTTL = m_RenderData.primarySurfaceUVTopLeft; const auto LASTBR = m_RenderData.primarySurfaceUVBottomRight; - m_RenderData.primarySurfaceUVTopLeft = pBox->pos() / MONITORBOX.size(); - m_RenderData.primarySurfaceUVBottomRight = (pBox->pos() + pBox->size()) / MONITORBOX.size(); + m_RenderData.primarySurfaceUVTopLeft = box.pos() / MONITORBOX.size(); + m_RenderData.primarySurfaceUVBottomRight = (box.pos() + box.size()) / MONITORBOX.size(); static auto PBLURIGNOREOPACITY = CConfigValue("decoration:blur:ignore_opacity"); setMonitorTransformEnabled(true); if (!USENEWOPTIMIZE) setRenderModifEnabled(false); - renderTextureInternalWithDamage(POUTFB->getTexture(), pBox, (*PBLURIGNOREOPACITY ? blurA : a * blurA) * overallA, texDamage, round, roundingPower, false, false, true); + renderTextureInternalWithDamage(POUTFB->getTexture(), box, (*PBLURIGNOREOPACITY ? blurA : a * blurA) * overallA, texDamage, round, roundingPower, false, false, true); if (!USENEWOPTIMIZE) setRenderModifEnabled(true); setMonitorTransformEnabled(false); @@ -2180,15 +2174,15 @@ void CHyprOpenGLImpl::renderTextureWithBlur(SP tex, CBox* pBox, float // draw window glDisable(GL_STENCIL_TEST); - renderTextureInternalWithDamage(tex, pBox, a * overallA, texDamage, round, roundingPower, false, false, true, true); + renderTextureInternalWithDamage(tex, box, a * overallA, texDamage, round, roundingPower, false, false, true, true); glStencilMask(0xFF); glStencilFunc(GL_ALWAYS, 1, 0xFF); - scissor((CBox*)nullptr); + scissor(nullptr); } -void CHyprOpenGLImpl::renderBorder(CBox* box, const CGradientValueData& grad, int round, float roundingPower, int borderSize, float a, int outerRound) { - RASSERT((box->width > 0 && box->height > 0), "Tried to render rect with width/height < 0!"); +void CHyprOpenGLImpl::renderBorder(const CBox& box, const CGradientValueData& grad, int round, float roundingPower, int borderSize, float a, int outerRound) { + RASSERT((box.width > 0 && box.height > 0), "Tried to render rect with width/height < 0!"); RASSERT(m_RenderData.pMonitor, "Tried to render rect without begin()!"); TRACY_GPU_ZONE("RenderBorder"); @@ -2196,11 +2190,9 @@ void CHyprOpenGLImpl::renderBorder(CBox* box, const CGradientValueData& grad, in if (m_RenderData.damage.empty() || (m_RenderData.currentWindow && m_RenderData.currentWindow->m_sWindowData.noBorder.valueOrDefault())) return; - CBox newBox = *box; + CBox newBox = box; m_RenderData.renderModif.applyToBox(newBox); - box = &newBox; - if (borderSize < 1) return; @@ -2208,10 +2200,10 @@ void CHyprOpenGLImpl::renderBorder(CBox* box, const CGradientValueData& grad, in scaledBorderSize = std::round(scaledBorderSize * m_RenderData.renderModif.combinedScale()); // adjust box - box->x -= scaledBorderSize; - box->y -= scaledBorderSize; - box->width += 2 * scaledBorderSize; - box->height += 2 * scaledBorderSize; + newBox.x -= scaledBorderSize; + newBox.y -= scaledBorderSize; + newBox.width += 2 * scaledBorderSize; + newBox.height += 2 * scaledBorderSize; round += round == 0 ? 0 : scaledBorderSize; @@ -2237,7 +2229,7 @@ void CHyprOpenGLImpl::renderBorder(CBox* box, const CGradientValueData& grad, in glUniform1f(m_RenderData.pCurrentMonData->m_shBORDER1.alpha, a); glUniform1i(m_RenderData.pCurrentMonData->m_shBORDER1.gradient2Length, 0); - CBox transformedBox = *box; + CBox transformedBox = box; transformedBox.transform(wlTransformToHyprutils(invertTransform(m_RenderData.pMonitor->transform)), m_RenderData.pMonitor->vecTransformedSize.x, m_RenderData.pMonitor->vecTransformedSize.y); @@ -2246,7 +2238,7 @@ void CHyprOpenGLImpl::renderBorder(CBox* box, const CGradientValueData& grad, in glUniform2f(m_RenderData.pCurrentMonData->m_shBORDER1.topLeft, (float)TOPLEFT.x, (float)TOPLEFT.y); glUniform2f(m_RenderData.pCurrentMonData->m_shBORDER1.fullSize, (float)FULLSIZE.x, (float)FULLSIZE.y); - glUniform2f(m_RenderData.pCurrentMonData->m_shBORDER1.fullSizeUntransformed, (float)box->width, (float)box->height); + glUniform2f(m_RenderData.pCurrentMonData->m_shBORDER1.fullSizeUntransformed, (float)box.width, (float)box.height); glUniform1f(m_RenderData.pCurrentMonData->m_shBORDER1.radius, round); glUniform1f(m_RenderData.pCurrentMonData->m_shBORDER1.radiusOuter, outerRound == -1 ? round : outerRound); glUniform1f(m_RenderData.pCurrentMonData->m_shBORDER1.roundingPower, roundingPower); @@ -2281,9 +2273,9 @@ void CHyprOpenGLImpl::renderBorder(CBox* box, const CGradientValueData& grad, in blend(BLEND); } -void CHyprOpenGLImpl::renderBorder(CBox* box, const CGradientValueData& grad1, const CGradientValueData& grad2, float lerp, int round, float roundingPower, int borderSize, float a, - int outerRound) { - RASSERT((box->width > 0 && box->height > 0), "Tried to render rect with width/height < 0!"); +void CHyprOpenGLImpl::renderBorder(const CBox& box, const CGradientValueData& grad1, const CGradientValueData& grad2, float lerp, int round, float roundingPower, int borderSize, + float a, int outerRound) { + RASSERT((box.width > 0 && box.height > 0), "Tried to render rect with width/height < 0!"); RASSERT(m_RenderData.pMonitor, "Tried to render rect without begin()!"); TRACY_GPU_ZONE("RenderBorder2"); @@ -2291,11 +2283,9 @@ void CHyprOpenGLImpl::renderBorder(CBox* box, const CGradientValueData& grad1, c if (m_RenderData.damage.empty() || (m_RenderData.currentWindow && m_RenderData.currentWindow->m_sWindowData.noBorder.valueOrDefault())) return; - CBox newBox = *box; + CBox newBox = box; m_RenderData.renderModif.applyToBox(newBox); - box = &newBox; - if (borderSize < 1) return; @@ -2303,10 +2293,10 @@ void CHyprOpenGLImpl::renderBorder(CBox* box, const CGradientValueData& grad1, c scaledBorderSize = std::round(scaledBorderSize * m_RenderData.renderModif.combinedScale()); // adjust box - box->x -= scaledBorderSize; - box->y -= scaledBorderSize; - box->width += 2 * scaledBorderSize; - box->height += 2 * scaledBorderSize; + newBox.x -= scaledBorderSize; + newBox.y -= scaledBorderSize; + newBox.width += 2 * scaledBorderSize; + newBox.height += 2 * scaledBorderSize; round += round == 0 ? 0 : scaledBorderSize; @@ -2336,7 +2326,7 @@ void CHyprOpenGLImpl::renderBorder(CBox* box, const CGradientValueData& grad1, c glUniform1f(m_RenderData.pCurrentMonData->m_shBORDER1.alpha, a); glUniform1f(m_RenderData.pCurrentMonData->m_shBORDER1.gradientLerp, lerp); - CBox transformedBox = *box; + CBox transformedBox = box; transformedBox.transform(wlTransformToHyprutils(invertTransform(m_RenderData.pMonitor->transform)), m_RenderData.pMonitor->vecTransformedSize.x, m_RenderData.pMonitor->vecTransformedSize.y); @@ -2345,7 +2335,7 @@ void CHyprOpenGLImpl::renderBorder(CBox* box, const CGradientValueData& grad1, c glUniform2f(m_RenderData.pCurrentMonData->m_shBORDER1.topLeft, (float)TOPLEFT.x, (float)TOPLEFT.y); glUniform2f(m_RenderData.pCurrentMonData->m_shBORDER1.fullSize, (float)FULLSIZE.x, (float)FULLSIZE.y); - glUniform2f(m_RenderData.pCurrentMonData->m_shBORDER1.fullSizeUntransformed, (float)box->width, (float)box->height); + glUniform2f(m_RenderData.pCurrentMonData->m_shBORDER1.fullSizeUntransformed, (float)box.width, (float)box.height); glUniform1f(m_RenderData.pCurrentMonData->m_shBORDER1.radius, round); glUniform1f(m_RenderData.pCurrentMonData->m_shBORDER1.radiusOuter, outerRound == -1 ? round : outerRound); glUniform1f(m_RenderData.pCurrentMonData->m_shBORDER1.roundingPower, roundingPower); @@ -2380,9 +2370,9 @@ void CHyprOpenGLImpl::renderBorder(CBox* box, const CGradientValueData& grad1, c blend(BLEND); } -void CHyprOpenGLImpl::renderRoundedShadow(CBox* box, int round, float roundingPower, int range, const CHyprColor& color, float a) { +void CHyprOpenGLImpl::renderRoundedShadow(const CBox& box, int round, float roundingPower, int range, const CHyprColor& color, float a) { RASSERT(m_RenderData.pMonitor, "Tried to render shadow without begin()!"); - RASSERT((box->width > 0 && box->height > 0), "Tried to render shadow with width/height < 0!"); + RASSERT((box.width > 0 && box.height > 0), "Tried to render shadow with width/height < 0!"); RASSERT(m_RenderData.currentWindow, "Tried to render shadow without a window!"); if (m_RenderData.damage.empty()) @@ -2390,11 +2380,9 @@ void CHyprOpenGLImpl::renderRoundedShadow(CBox* box, int round, float roundingPo TRACY_GPU_ZONE("RenderShadow"); - CBox newBox = *box; + CBox newBox = box; m_RenderData.renderModif.applyToBox(newBox); - box = &newBox; - static auto PSHADOWPOWER = CConfigValue("decoration:shadow:render_power"); const auto SHADOWPOWER = std::clamp((int)*PSHADOWPOWER, 1, 4); @@ -2418,8 +2406,8 @@ void CHyprOpenGLImpl::renderRoundedShadow(CBox* box, int round, float roundingPo glUniform4f(m_RenderData.pCurrentMonData->m_shSHADOW.color, col.r, col.g, col.b, col.a * a); const auto TOPLEFT = Vector2D(range + round, range + round); - const auto BOTTOMRIGHT = Vector2D(box->width - (range + round), box->height - (range + round)); - const auto FULLSIZE = Vector2D(box->width, box->height); + const auto BOTTOMRIGHT = Vector2D(newBox.width - (range + round), newBox.height - (range + round)); + const auto FULLSIZE = Vector2D(newBox.width, newBox.height); // Rounded corners glUniform2f(m_RenderData.pCurrentMonData->m_shSHADOW.topLeft, (float)TOPLEFT.x, (float)TOPLEFT.y); @@ -2457,7 +2445,7 @@ void CHyprOpenGLImpl::renderRoundedShadow(CBox* box, int round, float roundingPo glDisableVertexAttribArray(m_RenderData.pCurrentMonData->m_shSHADOW.texAttrib); } -void CHyprOpenGLImpl::saveBufferForMirror(CBox* box) { +void CHyprOpenGLImpl::saveBufferForMirror(const CBox& box) { if (!m_RenderData.pCurrentMonData->monitorMirrorFB.isAllocated()) m_RenderData.pCurrentMonData->monitorMirrorFB.alloc(m_RenderData.pMonitor->vecPixelSize.x, m_RenderData.pMonitor->vecPixelSize.y, @@ -2850,11 +2838,11 @@ void CHyprOpenGLImpl::createBGTextureForMonitor(PHLMONITOR pMonitor) { } CBox texbox = CBox{origin, m_pBackgroundTexture->m_vSize * scale}; - renderTextureInternalWithDamage(m_pBackgroundTexture, &texbox, 1.0, fakeDamage); + renderTextureInternalWithDamage(m_pBackgroundTexture, texbox, 1.0, fakeDamage); } CBox monbox = {{}, pMonitor->vecPixelSize}; - renderTextureInternalWithDamage(tex, &monbox, 1.0, fakeDamage); + renderTextureInternalWithDamage(tex, monbox, 1.0, fakeDamage); // bind back if (m_RenderData.currentFB) @@ -2936,7 +2924,7 @@ void CHyprOpenGLImpl::bindOffMain() { void CHyprOpenGLImpl::renderOffToMain(CFramebuffer* off) { CBox monbox = {0, 0, m_RenderData.pMonitor->vecTransformedSize.x, m_RenderData.pMonitor->vecTransformedSize.y}; - renderTexturePrimitive(off->getTexture(), &monbox); + renderTexturePrimitive(off->getTexture(), monbox); } void CHyprOpenGLImpl::bindBackOnMain() { diff --git a/src/render/OpenGL.hpp b/src/render/OpenGL.hpp index fd84d478..1ebb0162 100644 --- a/src/render/OpenGL.hpp +++ b/src/render/OpenGL.hpp @@ -166,86 +166,86 @@ class CHyprOpenGLImpl { CHyprOpenGLImpl(); ~CHyprOpenGLImpl(); - void begin(PHLMONITOR, const CRegion& damage, CFramebuffer* fb = nullptr, std::optional finalDamage = {}); - void beginSimple(PHLMONITOR, const CRegion& damage, SP rb = nullptr, CFramebuffer* fb = nullptr); - void end(); + void begin(PHLMONITOR, const CRegion& damage, CFramebuffer* fb = nullptr, std::optional finalDamage = {}); + void beginSimple(PHLMONITOR, const CRegion& damage, SP rb = nullptr, CFramebuffer* fb = nullptr); + void end(); - void renderRect(CBox*, const CHyprColor&, int round = 0, float roundingPower = 2.0f); - void renderRectWithBlur(CBox*, const CHyprColor&, int round = 0, float roundingPower = 2.0f, float blurA = 1.f, bool xray = false); - void renderRectWithDamage(CBox*, const CHyprColor&, const CRegion& damage, int round = 0, float roundingPower = 2.0f); - void renderTexture(SP, CBox*, float a, int round = 0, float roundingPower = 2.0f, bool discardActive = false, bool allowCustomUV = false); - void renderTextureWithDamage(SP, CBox*, const CRegion& damage, float a, int round = 0, float roundingPower = 2.0f, bool discardActive = false, - bool allowCustomUV = false, SP waitTimeline = nullptr, uint64_t waitPoint = 0); - void renderTextureWithBlur(SP, CBox*, float a, SP pSurface, int round = 0, float roundingPower = 2.0f, bool blockBlurOptimization = false, - float blurA = 1.f, float overallA = 1.f); - void renderRoundedShadow(CBox*, int round, float roundingPower, int range, const CHyprColor& color, float a = 1.0); - void renderBorder(CBox*, const CGradientValueData&, int round, float roundingPower, int borderSize, float a = 1.0, int outerRound = -1 /* use round */); - void renderBorder(CBox*, const CGradientValueData&, const CGradientValueData&, float lerp, int round, float roundingPower, int borderSize, float a = 1.0, - int outerRound = -1 /* use round */); - void renderTextureMatte(SP tex, CBox* pBox, CFramebuffer& matte); + void renderRect(const CBox&, const CHyprColor&, int round = 0, float roundingPower = 2.0f); + void renderRectWithBlur(const CBox&, const CHyprColor&, int round = 0, float roundingPower = 2.0f, float blurA = 1.f, bool xray = false); + void renderRectWithDamage(const CBox&, const CHyprColor&, const CRegion& damage, int round = 0, float roundingPower = 2.0f); + void renderTexture(SP, const CBox&, float a, int round = 0, float roundingPower = 2.0f, bool discardActive = false, bool allowCustomUV = false); + void renderTextureWithDamage(SP, const CBox&, const CRegion& damage, float a, int round = 0, float roundingPower = 2.0f, bool discardActive = false, + bool allowCustomUV = false, SP waitTimeline = nullptr, uint64_t waitPoint = 0); + void renderTextureWithBlur(SP, const CBox&, float a, SP pSurface, int round = 0, float roundingPower = 2.0f, bool blockBlurOptimization = false, + float blurA = 1.f, float overallA = 1.f); + void renderRoundedShadow(const CBox&, int round, float roundingPower, int range, const CHyprColor& color, float a = 1.0); + void renderBorder(const CBox&, const CGradientValueData&, int round, float roundingPower, int borderSize, float a = 1.0, int outerRound = -1 /* use round */); + void renderBorder(const CBox&, const CGradientValueData&, const CGradientValueData&, float lerp, int round, float roundingPower, int borderSize, float a = 1.0, + int outerRound = -1 /* use round */); + void renderTextureMatte(SP tex, const CBox& pBox, CFramebuffer& matte); - void setMonitorTransformEnabled(bool enabled); - void setRenderModifEnabled(bool enabled); + void setMonitorTransformEnabled(bool enabled); + void setRenderModifEnabled(bool enabled); - void saveMatrix(); - void setMatrixScaleTranslate(const Vector2D& translate, const float& scale); - void restoreMatrix(); + void saveMatrix(); + void setMatrixScaleTranslate(const Vector2D& translate, const float& scale); + void restoreMatrix(); - void blend(bool enabled); + void blend(bool enabled); - bool shouldUseNewBlurOptimizations(PHLLS pLayer, PHLWINDOW pWindow); + bool shouldUseNewBlurOptimizations(PHLLS pLayer, PHLWINDOW pWindow); - void clear(const CHyprColor&); - void clearWithTex(); - void scissor(const CBox*, bool transform = true); - void scissor(const pixman_box32*, bool transform = true); - void scissor(const int x, const int y, const int w, const int h, bool transform = true); + void clear(const CHyprColor&); + void clearWithTex(); + void scissor(const CBox&, bool transform = true); + void scissor(const pixman_box32*, bool transform = true); + void scissor(const int x, const int y, const int w, const int h, bool transform = true); - void destroyMonitorResources(PHLMONITOR); + void destroyMonitorResources(PHLMONITOR); - void markBlurDirtyForMonitor(PHLMONITOR); + void markBlurDirtyForMonitor(PHLMONITOR); - void preWindowPass(); - bool preBlurQueued(); - void preRender(PHLMONITOR); + void preWindowPass(); + bool preBlurQueued(); + void preRender(PHLMONITOR); - void saveBufferForMirror(CBox*); - void renderMirrored(); + void saveBufferForMirror(const CBox&); + void renderMirrored(); - void applyScreenShader(const std::string& path); + void applyScreenShader(const std::string& path); - void bindOffMain(); - void renderOffToMain(CFramebuffer* off); - void bindBackOnMain(); + void bindOffMain(); + void renderOffToMain(CFramebuffer* off); + void bindBackOnMain(); - SP loadAsset(const std::string& file); - SP renderText(const std::string& text, CHyprColor col, int pt, bool italic = false, const std::string& fontFamily = "", int maxWidth = 0); + SP loadAsset(const std::string& file); + SP renderText(const std::string& text, CHyprColor col, int pt, bool italic = false, const std::string& fontFamily = "", int maxWidth = 0); - void setDamage(const CRegion& damage, std::optional finalDamage = {}); + void setDamage(const CRegion& damage, std::optional finalDamage = {}); - void ensureBackgroundTexturePresence(); + void ensureBackgroundTexturePresence(); - uint32_t getPreferredReadFormat(PHLMONITOR pMonitor); - std::vector getDRMFormats(); - EGLImageKHR createEGLImage(const Aquamarine::SDMABUFAttrs& attrs); - SP createEGLSync(int fenceFD); - bool waitForTimelinePoint(SP timeline, uint64_t point); + uint32_t getPreferredReadFormat(PHLMONITOR pMonitor); + std::vector getDRMFormats(); + EGLImageKHR createEGLImage(const Aquamarine::SDMABUFAttrs& attrs); + SP createEGLSync(int fenceFD); + bool waitForTimelinePoint(SP timeline, uint64_t point); - SCurrentRenderData m_RenderData; + SCurrentRenderData m_RenderData; - GLint m_iCurrentOutputFb = 0; + GLint m_iCurrentOutputFb = 0; - int m_iGBMFD = -1; - gbm_device* m_pGbmDevice = nullptr; - EGLContext m_pEglContext = nullptr; - EGLDisplay m_pEglDisplay = nullptr; - EGLDeviceEXT m_pEglDevice = nullptr; - uint failedAssetsNo = 0; + int m_iGBMFD = -1; + gbm_device* m_pGbmDevice = nullptr; + EGLContext m_pEglContext = nullptr; + EGLDisplay m_pEglDisplay = nullptr; + EGLDeviceEXT m_pEglDevice = nullptr; + uint failedAssetsNo = 0; - bool m_bReloadScreenShader = true; // at launch it can be set + bool m_bReloadScreenShader = true; // at launch it can be set - std::map m_mWindowFramebuffers; - std::map m_mLayerFramebuffers; + std::map m_mWindowFramebuffers; + std::map m_mLayerFramebuffers; std::map m_mMonitorRenderResources; std::map m_mMonitorBGFBs; @@ -314,14 +314,14 @@ class CHyprOpenGLImpl { // returns the out FB, can be either Mirror or MirrorSwap CFramebuffer* blurMainFramebufferWithDamage(float a, CRegion* damage); - void renderTextureInternalWithDamage(SP, CBox* pBox, float a, const CRegion& damage, int round = 0, float roundingPower = 2.0f, bool discardOpaque = false, - bool noAA = false, bool allowCustomUV = false, bool allowDim = false, SP = nullptr, uint64_t waitPoint = 0); - void renderTexturePrimitive(SP tex, CBox* pBox); - void renderSplash(cairo_t* const, cairo_surface_t* const, double offset, const Vector2D& size); + void renderTextureInternalWithDamage(SP, const CBox& box, float a, const CRegion& damage, int round = 0, float roundingPower = 2.0f, bool discardOpaque = false, + bool noAA = false, bool allowCustomUV = false, bool allowDim = false, SP = nullptr, uint64_t waitPoint = 0); + void renderTexturePrimitive(SP tex, const CBox& box); + void renderSplash(cairo_t* const, cairo_surface_t* const, double offset, const Vector2D& size); - void preBlurForCurrentMonitor(); + void preBlurForCurrentMonitor(); - bool passRequiresIntrospection(PHLMONITOR pMonitor); + bool passRequiresIntrospection(PHLMONITOR pMonitor); friend class CHyprRenderer; friend class CTexPassElement; diff --git a/src/render/Renderer.cpp b/src/render/Renderer.cpp index f897379a..41ab0b37 100644 --- a/src/render/Renderer.cpp +++ b/src/render/Renderer.cpp @@ -978,15 +978,15 @@ void CHyprRenderer::renderSessionLockMissing(PHLMONITOR pMonitor) { if (ANY_PRESENT) { // render image2, without instructions. Lock still "alive", unless texture dead - g_pHyprOpenGL->renderTexture(g_pHyprOpenGL->m_pLockDead2Texture, &monbox, ALPHA); + g_pHyprOpenGL->renderTexture(g_pHyprOpenGL->m_pLockDead2Texture, monbox, ALPHA); } else { // render image, with instructions. Lock is gone. - g_pHyprOpenGL->renderTexture(g_pHyprOpenGL->m_pLockDeadTexture, &monbox, ALPHA); + g_pHyprOpenGL->renderTexture(g_pHyprOpenGL->m_pLockDeadTexture, monbox, ALPHA); // also render text for the tty number if (g_pHyprOpenGL->m_pLockTtyTextTexture) { CBox texbox = {{}, g_pHyprOpenGL->m_pLockTtyTextTexture->m_vSize}; - g_pHyprOpenGL->renderTexture(g_pHyprOpenGL->m_pLockTtyTextTexture, &texbox, 1.F); + g_pHyprOpenGL->renderTexture(g_pHyprOpenGL->m_pLockTtyTextTexture, texbox, 1.F); } } @@ -1836,7 +1836,7 @@ void CHyprRenderer::damageSurface(SP pSurface, double x, dou damageBoxForEach.set(damageBox); damageBoxForEach.translate({-m->vecPosition.x, -m->vecPosition.y}).scale(m->scale); - m->addDamage(&damageBoxForEach); + m->addDamage(damageBoxForEach); } static auto PLOGDAMAGE = CConfigValue("debug:log_damage"); @@ -1860,7 +1860,7 @@ void CHyprRenderer::damageWindow(PHLWINDOW pWindow, bool forceFull) { if (forceFull || shouldRenderWindow(pWindow, m)) { // only damage if window is rendered on monitor CBox fixedDamageBox = {windowBox.x - m->vecPosition.x, windowBox.y - m->vecPosition.y, windowBox.width, windowBox.height}; fixedDamageBox.scale(m->scale); - m->addDamage(&fixedDamageBox); + m->addDamage(fixedDamageBox); } } @@ -1878,7 +1878,7 @@ void CHyprRenderer::damageMonitor(PHLMONITOR pMonitor) { return; CBox damageBox = {0, 0, INT16_MAX, INT16_MAX}; - pMonitor->addDamage(&damageBox); + pMonitor->addDamage(damageBox); static auto PLOGDAMAGE = CConfigValue("debug:log_damage"); @@ -1886,7 +1886,7 @@ void CHyprRenderer::damageMonitor(PHLMONITOR pMonitor) { Debug::log(LOG, "Damage: Monitor {}", pMonitor->szName); } -void CHyprRenderer::damageBox(CBox* pBox, bool skipFrameSchedule) { +void CHyprRenderer::damageBox(const CBox& box, bool skipFrameSchedule) { if (g_pCompositor->m_bUnsafeState) return; @@ -1895,21 +1895,20 @@ void CHyprRenderer::damageBox(CBox* pBox, bool skipFrameSchedule) { continue; // don't damage mirrors traditionally if (!skipFrameSchedule) { - CBox damageBox = {pBox->x - m->vecPosition.x, pBox->y - m->vecPosition.y, pBox->width, pBox->height}; - damageBox.scale(m->scale); - m->addDamage(&damageBox); + CBox damageBox = box.copy().translate(-m->vecPosition).scale(m->scale); + m->addDamage(damageBox); } } static auto PLOGDAMAGE = CConfigValue("debug:log_damage"); if (*PLOGDAMAGE) - Debug::log(LOG, "Damage: Box: xy: {}, {} wh: {}, {}", pBox->x, pBox->y, pBox->width, pBox->height); + Debug::log(LOG, "Damage: Box: xy: {}, {} wh: {}, {}", box.x, box.y, box.w, box.h); } void CHyprRenderer::damageBox(const int& x, const int& y, const int& w, const int& h) { CBox box = {x, y, w, h}; - damageBox(&box); + damageBox(box); } void CHyprRenderer::damageRegion(const CRegion& rg) { @@ -1936,7 +1935,7 @@ void CHyprRenderer::damageMirrorsWith(PHLMONITOR pMonitor, const CRegion& pRegio transformed.transform(wlTransformToHyprutils(pMonitor->transform), pMonitor->vecPixelSize.x * scale, pMonitor->vecPixelSize.y * scale); transformed.translate(Vector2D(monbox.x, monbox.y)); - mirror->addDamage(&transformed); + mirror->addDamage(transformed); g_pCompositor->scheduleFrameForMonitor(mirror.lock(), Aquamarine::IOutput::AQ_SCHEDULE_DAMAGE); } diff --git a/src/render/Renderer.hpp b/src/render/Renderer.hpp index 30fba3ca..e64d41c1 100644 --- a/src/render/Renderer.hpp +++ b/src/render/Renderer.hpp @@ -53,7 +53,7 @@ class CHyprRenderer { void arrangeLayersForMonitor(const MONITORID&); void damageSurface(SP, double, double, double scale = 1.0); void damageWindow(PHLWINDOW, bool forceFull = false); - void damageBox(CBox*, bool skipFrameSchedule = false); + void damageBox(const CBox&, bool skipFrameSchedule = false); void damageBox(const int& x, const int& y, const int& w, const int& h); void damageRegion(const CRegion&); void damageMonitor(PHLMONITOR); diff --git a/src/render/decorations/CHyprDropShadowDecoration.cpp b/src/render/decorations/CHyprDropShadowDecoration.cpp index c576b966..8a934086 100644 --- a/src/render/decorations/CHyprDropShadowDecoration.cpp +++ b/src/render/decorations/CHyprDropShadowDecoration.cpp @@ -149,7 +149,7 @@ void CHyprDropShadowDecoration::render(PHLMONITOR pMonitor, float const& a) { if (fullBox.width < 1 || fullBox.height < 1) return; // don't draw invisible shadows - g_pHyprOpenGL->scissor((CBox*)nullptr); + g_pHyprOpenGL->scissor(nullptr); g_pHyprOpenGL->m_RenderData.currentWindow = m_pWindow; // we'll take the liberty of using this as it should not be used rn @@ -191,18 +191,18 @@ void CHyprDropShadowDecoration::render(PHLMONITOR pMonitor, float const& a) { // build the matte // 10-bit formats have dogshit alpha channels, so we have to use the matte to its fullest. // first, clear region of interest with black (fully transparent) - g_pHyprOpenGL->renderRect(&fullBox, CHyprColor(0, 0, 0, 1), 0); + g_pHyprOpenGL->renderRect(fullBox, CHyprColor(0, 0, 0, 1), 0); // render white shadow with the alpha of the shadow color (otherwise we clear with alpha later and shit it to 2 bit) - drawShadowInternal(&fullBox, ROUNDING * pMonitor->scale, ROUNDINGPOWER, *PSHADOWSIZE * pMonitor->scale, CHyprColor(1, 1, 1, PWINDOW->m_cRealShadowColor->value().a), a); + drawShadowInternal(fullBox, ROUNDING * pMonitor->scale, ROUNDINGPOWER, *PSHADOWSIZE * pMonitor->scale, CHyprColor(1, 1, 1, PWINDOW->m_cRealShadowColor->value().a), a); // render black window box ("clip") - g_pHyprOpenGL->renderRect(&windowBox, CHyprColor(0, 0, 0, 1.0), (ROUNDING + 1 /* This fixes small pixel gaps. */) * pMonitor->scale, ROUNDINGPOWER); + g_pHyprOpenGL->renderRect(windowBox, CHyprColor(0, 0, 0, 1.0), (ROUNDING + 1 /* This fixes small pixel gaps. */) * pMonitor->scale, ROUNDINGPOWER); alphaSwapFB.bind(); // alpha swap just has the shadow color. It will be the "texture" to render. - g_pHyprOpenGL->renderRect(&fullBox, PWINDOW->m_cRealShadowColor->value().stripA(), 0); + g_pHyprOpenGL->renderRect(fullBox, PWINDOW->m_cRealShadowColor->value().stripA(), 0); LASTFB->bind(); @@ -210,13 +210,13 @@ void CHyprDropShadowDecoration::render(PHLMONITOR pMonitor, float const& a) { g_pHyprOpenGL->setMonitorTransformEnabled(true); g_pHyprOpenGL->setRenderModifEnabled(false); - g_pHyprOpenGL->renderTextureMatte(alphaSwapFB.getTexture(), &monbox, alphaFB); + g_pHyprOpenGL->renderTextureMatte(alphaSwapFB.getTexture(), monbox, alphaFB); g_pHyprOpenGL->setRenderModifEnabled(true); g_pHyprOpenGL->setMonitorTransformEnabled(false); g_pHyprOpenGL->m_RenderData.damage = saveDamage; } else - drawShadowInternal(&fullBox, ROUNDING * pMonitor->scale, ROUNDINGPOWER, *PSHADOWSIZE * pMonitor->scale, PWINDOW->m_cRealShadowColor->value(), a); + drawShadowInternal(fullBox, ROUNDING * pMonitor->scale, ROUNDINGPOWER, *PSHADOWSIZE * pMonitor->scale, PWINDOW->m_cRealShadowColor->value(), a); if (m_seExtents != m_seReportedExtents) g_pDecorationPositioner->repositionDeco(this); @@ -228,7 +228,7 @@ eDecorationLayer CHyprDropShadowDecoration::getDecorationLayer() { return DECORATION_LAYER_BOTTOM; } -void CHyprDropShadowDecoration::drawShadowInternal(CBox* box, int round, float roundingPower, int range, CHyprColor color, float a) { +void CHyprDropShadowDecoration::drawShadowInternal(const CBox& box, int round, float roundingPower, int range, CHyprColor color, float a) { static auto PSHADOWSHARP = CConfigValue("decoration:shadow:sharp"); g_pHyprOpenGL->blend(true); diff --git a/src/render/decorations/CHyprDropShadowDecoration.hpp b/src/render/decorations/CHyprDropShadowDecoration.hpp index 93fa3d1a..3b1c67c5 100644 --- a/src/render/decorations/CHyprDropShadowDecoration.hpp +++ b/src/render/decorations/CHyprDropShadowDecoration.hpp @@ -36,7 +36,7 @@ class CHyprDropShadowDecoration : public IHyprWindowDecoration { Vector2D m_vLastWindowPos; Vector2D m_vLastWindowSize; - void drawShadowInternal(CBox* box, int round, float roundingPower, int range, CHyprColor color, float a); + void drawShadowInternal(const CBox& box, int round, float roundingPower, int range, CHyprColor color, float a); CBox m_bLastWindowBox = {0}; CBox m_bLastWindowBoxWithDecos = {0}; diff --git a/src/render/decorations/CHyprGroupBarDecoration.cpp b/src/render/decorations/CHyprGroupBarDecoration.cpp index 7cef21b8..4e7c3cbc 100644 --- a/src/render/decorations/CHyprGroupBarDecoration.cpp +++ b/src/render/decorations/CHyprGroupBarDecoration.cpp @@ -94,7 +94,7 @@ void CHyprGroupBarDecoration::updateWindow(PHLWINDOW pWindow) { void CHyprGroupBarDecoration::damageEntire() { auto box = assignedBoxGlobal(); box.translate(m_pWindow->m_vFloatingOffset); - g_pHyprRenderer->damageBox(&box); + g_pHyprRenderer->damageBox(box); } void CHyprGroupBarDecoration::draw(PHLMONITOR pMonitor, float const& a) { diff --git a/src/render/pass/BorderPassElement.cpp b/src/render/pass/BorderPassElement.cpp index ceeec6f3..31042c28 100644 --- a/src/render/pass/BorderPassElement.cpp +++ b/src/render/pass/BorderPassElement.cpp @@ -7,9 +7,9 @@ CBorderPassElement::CBorderPassElement(const CBorderPassElement::SBorderData& da void CBorderPassElement::draw(const CRegion& damage) { if (data.hasGrad2) - g_pHyprOpenGL->renderBorder(&data.box, data.grad1, data.grad2, data.lerp, data.round, data.roundingPower, data.borderSize, data.a, data.outerRound); + g_pHyprOpenGL->renderBorder(data.box, data.grad1, data.grad2, data.lerp, data.round, data.roundingPower, data.borderSize, data.a, data.outerRound); else - g_pHyprOpenGL->renderBorder(&data.box, data.grad1, data.round, data.roundingPower, data.borderSize, data.a, data.outerRound); + g_pHyprOpenGL->renderBorder(data.box, data.grad1, data.round, data.roundingPower, data.borderSize, data.a, data.outerRound); } bool CBorderPassElement::needsLiveBlur() { diff --git a/src/render/pass/Pass.cpp b/src/render/pass/Pass.cpp index 5b133b7d..81b918ac 100644 --- a/src/render/pass/Pass.cpp +++ b/src/render/pass/Pass.cpp @@ -202,9 +202,9 @@ CRegion CRenderPass::render(const CRegion& damage_) { void CRenderPass::renderDebugData() { CBox box = {{}, g_pHyprOpenGL->m_RenderData.pMonitor->vecTransformedSize}; for (const auto& rg : occludedRegions) { - g_pHyprOpenGL->renderRectWithDamage(&box, Colors::RED.modifyA(0.1F), rg); + g_pHyprOpenGL->renderRectWithDamage(box, Colors::RED.modifyA(0.1F), rg); } - g_pHyprOpenGL->renderRectWithDamage(&box, Colors::GREEN.modifyA(0.1F), totalLiveBlurRegion); + g_pHyprOpenGL->renderRectWithDamage(box, Colors::GREEN.modifyA(0.1F), totalLiveBlurRegion); std::unordered_map offsets; @@ -227,7 +227,7 @@ void CRenderPass::renderDebugData() { if (box.intersection(CBox{{}, g_pHyprOpenGL->m_RenderData.pMonitor->vecSize}).empty()) return; - g_pHyprOpenGL->renderRectWithDamage(&box, color, CRegion{0, 0, INT32_MAX, INT32_MAX}); + g_pHyprOpenGL->renderRectWithDamage(box, color, CRegion{0, 0, INT32_MAX, INT32_MAX}); if (offsets.contains(surface.get())) box.translate(Vector2D{0.F, offsets[surface.get()]}); @@ -235,8 +235,8 @@ void CRenderPass::renderDebugData() { offsets[surface.get()] = 0; box = {box.pos(), texture->m_vSize}; - g_pHyprOpenGL->renderRectWithDamage(&box, CHyprColor{0.F, 0.F, 0.F, 0.2F}, CRegion{0, 0, INT32_MAX, INT32_MAX}, std::min(5.0, box.size().y)); - g_pHyprOpenGL->renderTexture(texture, &box, 1.F); + g_pHyprOpenGL->renderRectWithDamage(box, CHyprColor{0.F, 0.F, 0.F, 0.2F}, CRegion{0, 0, INT32_MAX, INT32_MAX}, std::min(5.0, box.size().y)); + g_pHyprOpenGL->renderTexture(texture, box, 1.F); offsets[surface.get()] += texture->m_vSize.y; }; @@ -253,7 +253,7 @@ void CRenderPass::renderDebugData() { if (tex) { box = CBox{{0.F, g_pHyprOpenGL->m_RenderData.pMonitor->vecSize.y - tex->m_vSize.y}, tex->m_vSize}.scale(g_pHyprOpenGL->m_RenderData.pMonitor->scale); - g_pHyprOpenGL->renderTexture(tex, &box, 1.F); + g_pHyprOpenGL->renderTexture(tex, box, 1.F); } std::string passStructure; @@ -271,7 +271,7 @@ void CRenderPass::renderDebugData() { if (tex) { box = CBox{{g_pHyprOpenGL->m_RenderData.pMonitor->vecSize.x - tex->m_vSize.x, g_pHyprOpenGL->m_RenderData.pMonitor->vecSize.y - tex->m_vSize.y}, tex->m_vSize}.scale( g_pHyprOpenGL->m_RenderData.pMonitor->scale); - g_pHyprOpenGL->renderTexture(tex, &box, 1.F); + g_pHyprOpenGL->renderTexture(tex, box, 1.F); } } diff --git a/src/render/pass/RectPassElement.cpp b/src/render/pass/RectPassElement.cpp index 55471e78..a9ab737d 100644 --- a/src/render/pass/RectPassElement.cpp +++ b/src/render/pass/RectPassElement.cpp @@ -10,9 +10,9 @@ void CRectPassElement::draw(const CRegion& damage) { return; if (data.color.a == 1.F || !data.blur) - g_pHyprOpenGL->renderRectWithDamage(&data.box, data.color, damage, data.round, data.roundingPower); + g_pHyprOpenGL->renderRectWithDamage(data.box, data.color, damage, data.round, data.roundingPower); else - g_pHyprOpenGL->renderRectWithBlur(&data.box, data.color, data.round, data.roundingPower, data.blurA, data.xray); + g_pHyprOpenGL->renderRectWithBlur(data.box, data.color, data.round, data.roundingPower, data.blurA, data.xray); } bool CRectPassElement::needsLiveBlur() { diff --git a/src/render/pass/SurfacePassElement.cpp b/src/render/pass/SurfacePassElement.cpp index b79407c8..a5d3d7c0 100644 --- a/src/render/pass/SurfacePassElement.cpp +++ b/src/render/pass/SurfacePassElement.cpp @@ -122,14 +122,14 @@ void CSurfacePassElement::draw(const CRegion& damage) { // to what we do for misaligned surfaces (blur the entire thing and then render shit without blur) if (data.surfaceCounter == 0 && !data.popup) { if (BLUR) - g_pHyprOpenGL->renderTextureWithBlur(TEXTURE, &windowBox, ALPHA, data.surface, rounding, roundingPower, data.blockBlurOptimization, data.fadeAlpha, OVERALL_ALPHA); + g_pHyprOpenGL->renderTextureWithBlur(TEXTURE, windowBox, ALPHA, data.surface, rounding, roundingPower, data.blockBlurOptimization, data.fadeAlpha, OVERALL_ALPHA); else - g_pHyprOpenGL->renderTexture(TEXTURE, &windowBox, ALPHA * OVERALL_ALPHA, rounding, roundingPower, false, true); + g_pHyprOpenGL->renderTexture(TEXTURE, windowBox, ALPHA * OVERALL_ALPHA, rounding, roundingPower, false, true); } else { if (BLUR && data.popup) - g_pHyprOpenGL->renderTextureWithBlur(TEXTURE, &windowBox, ALPHA, data.surface, rounding, roundingPower, true, data.fadeAlpha, OVERALL_ALPHA); + g_pHyprOpenGL->renderTextureWithBlur(TEXTURE, windowBox, ALPHA, data.surface, rounding, roundingPower, true, data.fadeAlpha, OVERALL_ALPHA); else - g_pHyprOpenGL->renderTexture(TEXTURE, &windowBox, ALPHA * OVERALL_ALPHA, rounding, roundingPower, false, true); + g_pHyprOpenGL->renderTexture(TEXTURE, windowBox, ALPHA * OVERALL_ALPHA, rounding, roundingPower, false, true); } if (!g_pHyprRenderer->m_bBlockSurfaceFeedback) diff --git a/src/render/pass/TexPassElement.cpp b/src/render/pass/TexPassElement.cpp index 0624a786..c7eab292 100644 --- a/src/render/pass/TexPassElement.cpp +++ b/src/render/pass/TexPassElement.cpp @@ -18,7 +18,7 @@ void CTexPassElement::draw(const CRegion& damage) { if (data.replaceProjection) g_pHyprOpenGL->m_RenderData.monitorProjection = *data.replaceProjection; - g_pHyprOpenGL->renderTextureInternalWithDamage(data.tex, &data.box, data.a, data.damage.empty() ? damage : data.damage, data.round, data.roundingPower, data.syncTimeline, + g_pHyprOpenGL->renderTextureInternalWithDamage(data.tex, data.box, data.a, data.damage.empty() ? damage : data.damage, data.round, data.roundingPower, data.syncTimeline, data.syncPoint); if (data.replaceProjection) g_pHyprOpenGL->m_RenderData.monitorProjection = g_pHyprOpenGL->m_RenderData.pMonitor->projMatrix; diff --git a/src/render/pass/TextureMatteElement.cpp b/src/render/pass/TextureMatteElement.cpp index 5aed1c9a..3d927357 100644 --- a/src/render/pass/TextureMatteElement.cpp +++ b/src/render/pass/TextureMatteElement.cpp @@ -9,11 +9,11 @@ void CTextureMatteElement::draw(const CRegion& damage) { if (data.disableTransformAndModify) { g_pHyprOpenGL->setMonitorTransformEnabled(true); g_pHyprOpenGL->setRenderModifEnabled(false); - g_pHyprOpenGL->renderTextureMatte(data.tex, &data.box, *data.fb); + g_pHyprOpenGL->renderTextureMatte(data.tex, data.box, *data.fb); g_pHyprOpenGL->setRenderModifEnabled(true); g_pHyprOpenGL->setMonitorTransformEnabled(false); } else - g_pHyprOpenGL->renderTextureMatte(data.tex, &data.box, *data.fb); + g_pHyprOpenGL->renderTextureMatte(data.tex, data.box, *data.fb); } bool CTextureMatteElement::needsLiveBlur() { From efe29a24616d4de41dd8f2f70e1493ed6b581e33 Mon Sep 17 00:00:00 2001 From: Vaxry Date: Sun, 26 Jan 2025 15:15:54 +0000 Subject: [PATCH 0919/2181] shadow: avoid drawing empty shadows --- src/render/decorations/CHyprDropShadowDecoration.cpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/render/decorations/CHyprDropShadowDecoration.cpp b/src/render/decorations/CHyprDropShadowDecoration.cpp index 8a934086..0b2a96d9 100644 --- a/src/render/decorations/CHyprDropShadowDecoration.cpp +++ b/src/render/decorations/CHyprDropShadowDecoration.cpp @@ -231,6 +231,9 @@ eDecorationLayer CHyprDropShadowDecoration::getDecorationLayer() { void CHyprDropShadowDecoration::drawShadowInternal(const CBox& box, int round, float roundingPower, int range, CHyprColor color, float a) { static auto PSHADOWSHARP = CConfigValue("decoration:shadow:sharp"); + if (box.w < 1 || box.h < 1) + return; + g_pHyprOpenGL->blend(true); color.a *= a; From bb5b09def0645838456eb7eb1f52b471441acba1 Mon Sep 17 00:00:00 2001 From: Vaxry Date: Sun, 26 Jan 2025 15:19:42 +0000 Subject: [PATCH 0920/2181] renderer: fix funky corners oopsie --- src/render/OpenGL.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/render/OpenGL.cpp b/src/render/OpenGL.cpp index f0b2f447..ee5d9a86 100644 --- a/src/render/OpenGL.cpp +++ b/src/render/OpenGL.cpp @@ -2229,7 +2229,7 @@ void CHyprOpenGLImpl::renderBorder(const CBox& box, const CGradientValueData& gr glUniform1f(m_RenderData.pCurrentMonData->m_shBORDER1.alpha, a); glUniform1i(m_RenderData.pCurrentMonData->m_shBORDER1.gradient2Length, 0); - CBox transformedBox = box; + CBox transformedBox = newBox; transformedBox.transform(wlTransformToHyprutils(invertTransform(m_RenderData.pMonitor->transform)), m_RenderData.pMonitor->vecTransformedSize.x, m_RenderData.pMonitor->vecTransformedSize.y); @@ -2238,7 +2238,7 @@ void CHyprOpenGLImpl::renderBorder(const CBox& box, const CGradientValueData& gr glUniform2f(m_RenderData.pCurrentMonData->m_shBORDER1.topLeft, (float)TOPLEFT.x, (float)TOPLEFT.y); glUniform2f(m_RenderData.pCurrentMonData->m_shBORDER1.fullSize, (float)FULLSIZE.x, (float)FULLSIZE.y); - glUniform2f(m_RenderData.pCurrentMonData->m_shBORDER1.fullSizeUntransformed, (float)box.width, (float)box.height); + glUniform2f(m_RenderData.pCurrentMonData->m_shBORDER1.fullSizeUntransformed, (float)newBox.width, (float)newBox.height); glUniform1f(m_RenderData.pCurrentMonData->m_shBORDER1.radius, round); glUniform1f(m_RenderData.pCurrentMonData->m_shBORDER1.radiusOuter, outerRound == -1 ? round : outerRound); glUniform1f(m_RenderData.pCurrentMonData->m_shBORDER1.roundingPower, roundingPower); @@ -2326,7 +2326,7 @@ void CHyprOpenGLImpl::renderBorder(const CBox& box, const CGradientValueData& gr glUniform1f(m_RenderData.pCurrentMonData->m_shBORDER1.alpha, a); glUniform1f(m_RenderData.pCurrentMonData->m_shBORDER1.gradientLerp, lerp); - CBox transformedBox = box; + CBox transformedBox = newBox; transformedBox.transform(wlTransformToHyprutils(invertTransform(m_RenderData.pMonitor->transform)), m_RenderData.pMonitor->vecTransformedSize.x, m_RenderData.pMonitor->vecTransformedSize.y); @@ -2335,7 +2335,7 @@ void CHyprOpenGLImpl::renderBorder(const CBox& box, const CGradientValueData& gr glUniform2f(m_RenderData.pCurrentMonData->m_shBORDER1.topLeft, (float)TOPLEFT.x, (float)TOPLEFT.y); glUniform2f(m_RenderData.pCurrentMonData->m_shBORDER1.fullSize, (float)FULLSIZE.x, (float)FULLSIZE.y); - glUniform2f(m_RenderData.pCurrentMonData->m_shBORDER1.fullSizeUntransformed, (float)box.width, (float)box.height); + glUniform2f(m_RenderData.pCurrentMonData->m_shBORDER1.fullSizeUntransformed, (float)newBox.width, (float)newBox.height); glUniform1f(m_RenderData.pCurrentMonData->m_shBORDER1.radius, round); glUniform1f(m_RenderData.pCurrentMonData->m_shBORDER1.radiusOuter, outerRound == -1 ? round : outerRound); glUniform1f(m_RenderData.pCurrentMonData->m_shBORDER1.roundingPower, roundingPower); From 6bd6c5512e1e413013044257e54581c237ca6fa0 Mon Sep 17 00:00:00 2001 From: Vaxry Date: Sun, 26 Jan 2025 18:35:35 +0000 Subject: [PATCH 0921/2181] hooksystem: avoid huge include for HANDLE --- src/managers/HookSystemManager.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/managers/HookSystemManager.hpp b/src/managers/HookSystemManager.hpp index 6d72a02d..c679c380 100644 --- a/src/managers/HookSystemManager.hpp +++ b/src/managers/HookSystemManager.hpp @@ -9,7 +9,7 @@ #include -#include "../plugins/PluginAPI.hpp" +#define HANDLE void* // global typedef for hooked functions. Passes itself as a ptr when called, and `data` additionally. From 3b207d29bdaf4c718a8878456bb17f2a67f2d9f4 Mon Sep 17 00:00:00 2001 From: user111111111111111111111111111111111 <192911676+user111111111111111111111111111111111@users.noreply.github.com> Date: Sun, 26 Jan 2025 19:06:50 +0000 Subject: [PATCH 0922/2181] core: update groups on movewindow (#9183) --- src/layout/DwindleLayout.cpp | 9 +++++++++ src/layout/MasterLayout.cpp | 9 +++++++++ 2 files changed, 18 insertions(+) diff --git a/src/layout/DwindleLayout.cpp b/src/layout/DwindleLayout.cpp index df6c3bde..8aaafaa3 100644 --- a/src/layout/DwindleLayout.cpp +++ b/src/layout/DwindleLayout.cpp @@ -847,6 +847,15 @@ void CHyprDwindleLayout::moveWindowTo(PHLWINDOW pWindow, const std::string& dir, pWindow->m_pMonitor = PMONITORFOCAL; } + pWindow->updateGroupOutputs(); + if (!pWindow->m_sGroupData.pNextWindow.expired()) { + PHLWINDOW next = pWindow->m_sGroupData.pNextWindow.lock(); + while (next != pWindow) { + next->updateToplevel(); + next = next->m_sGroupData.pNextWindow.lock(); + } + } + onWindowCreatedTiling(pWindow); m_vOverrideFocalPoint.reset(); diff --git a/src/layout/MasterLayout.cpp b/src/layout/MasterLayout.cpp index 8aa15e42..4773147f 100644 --- a/src/layout/MasterLayout.cpp +++ b/src/layout/MasterLayout.cpp @@ -945,6 +945,15 @@ void CHyprMasterLayout::moveWindowTo(PHLWINDOW pWindow, const std::string& dir, if (silent) g_pCompositor->focusWindow(PWINDOW2); } + + pWindow->updateGroupOutputs(); + if (!pWindow->m_sGroupData.pNextWindow.expired()) { + PHLWINDOW next = pWindow->m_sGroupData.pNextWindow.lock(); + while (next != pWindow) { + next->updateToplevel(); + next = next->m_sGroupData.pNextWindow.lock(); + } + } } void CHyprMasterLayout::switchWindows(PHLWINDOW pWindow, PHLWINDOW pWindow2) { From 2f55806d6f11a1e81e3e821cb0327779d5cc50e6 Mon Sep 17 00:00:00 2001 From: Vaxry Date: Sun, 26 Jan 2025 21:06:19 +0000 Subject: [PATCH 0923/2181] renderer: fix rare case when a tiled window would be rendered over fs --- src/render/Renderer.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/render/Renderer.cpp b/src/render/Renderer.cpp index 41ab0b37..3f6448d5 100644 --- a/src/render/Renderer.cpp +++ b/src/render/Renderer.cpp @@ -337,7 +337,7 @@ void CHyprRenderer::renderWorkspaceWindowsFullscreen(PHLMONITOR pMonitor, PHLWOR // then render windows over fullscreen. for (auto const& w : g_pCompositor->m_vWindows) { - if (w->m_pWorkspace != pWorkspaceWindow->m_pWorkspace || (!w->m_bCreatedOverFullscreen && !w->m_bPinned) || (!w->m_bIsMapped && !w->m_bFadingOut) || w->isFullscreen()) + if (w->m_pWorkspace != pWorkspaceWindow->m_pWorkspace || !w->m_bIsFloating || (!w->m_bCreatedOverFullscreen && !w->m_bPinned) || (!w->m_bIsMapped && !w->m_bFadingOut) || w->isFullscreen()) continue; if (w->m_pMonitor == pWorkspace->m_pMonitor && pWorkspace->m_bIsSpecialWorkspace != w->onSpecialWorkspace()) From 04ac46c54357278fc68f0a95d26347ea0db99496 Mon Sep 17 00:00:00 2001 From: Vaxry Date: Mon, 27 Jan 2025 11:43:43 +0000 Subject: [PATCH 0924/2181] version: bump to 0.47.0 --- VERSION | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/VERSION b/VERSION index 30109231..421ab545 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -0.46.0 +0.47.0 From 2a478c30cab89c8c608936ca966155da5b16728d Mon Sep 17 00:00:00 2001 From: Vaxry Date: Mon, 27 Jan 2025 13:41:38 +0000 Subject: [PATCH 0925/2181] core: fix clang-format --- src/render/Renderer.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/render/Renderer.cpp b/src/render/Renderer.cpp index 3f6448d5..67d8b58b 100644 --- a/src/render/Renderer.cpp +++ b/src/render/Renderer.cpp @@ -337,7 +337,8 @@ void CHyprRenderer::renderWorkspaceWindowsFullscreen(PHLMONITOR pMonitor, PHLWOR // then render windows over fullscreen. for (auto const& w : g_pCompositor->m_vWindows) { - if (w->m_pWorkspace != pWorkspaceWindow->m_pWorkspace || !w->m_bIsFloating || (!w->m_bCreatedOverFullscreen && !w->m_bPinned) || (!w->m_bIsMapped && !w->m_bFadingOut) || w->isFullscreen()) + if (w->m_pWorkspace != pWorkspaceWindow->m_pWorkspace || !w->m_bIsFloating || (!w->m_bCreatedOverFullscreen && !w->m_bPinned) || (!w->m_bIsMapped && !w->m_bFadingOut) || + w->isFullscreen()) continue; if (w->m_pMonitor == pWorkspace->m_pMonitor && pWorkspace->m_bIsSpecialWorkspace != w->onSpecialWorkspace()) From cb7ed4f62b195ab7d5f21fa393218170cfbb95c8 Mon Sep 17 00:00:00 2001 From: littleblack111 Date: Tue, 28 Jan 2025 00:41:26 +0800 Subject: [PATCH 0926/2181] ci: clang-format fix (#9145) * move * revert, comment via peter-evans/commit-comment@v3 * remove --- .github/workflows/ci.yaml | 24 --------------- .github/workflows/clang-format.yml | 48 ++++++++++++++++++++++++++++++ 2 files changed, 48 insertions(+), 24 deletions(-) create mode 100644 .github/workflows/clang-format.yml diff --git a/.github/workflows/ci.yaml b/.github/workflows/ci.yaml index 34c45d6b..416ea93b 100644 --- a/.github/workflows/ci.yaml +++ b/.github/workflows/ci.yaml @@ -127,27 +127,3 @@ jobs: - name: clang-format check run: ninja -C build clang-format-check - - - name: clang-format apply - if: ${{ failure() && github.event_name == 'pull_request' }} - run: ninja -C build clang-format - - - name: Create patch - if: ${{ failure() && github.event_name == 'pull_request' }} - run: | - echo 'Please fix the formatting issues by running [`clang-format`](https://wiki.hyprland.org/Contributing-and-Debugging/PR-Guidelines/#code-style), or directly apply this patch:' > clang-format.patch - echo '
' >> clang-format.patch - echo 'clang-format.patch' >> clang-format.patch - echo >> clang-format.patch - echo '```diff' >> clang-format.patch - git diff >> clang-format.patch - echo '```' >> clang-format.patch - echo >> clang-format.patch - echo '
' >> clang-format.patch - - - name: Comment patch - if: ${{ failure() && github.event_name == 'pull_request' }} - uses: mshick/add-pr-comment@v2 - with: - message-path: | - clang-format.patch diff --git a/.github/workflows/clang-format.yml b/.github/workflows/clang-format.yml new file mode 100644 index 00000000..e935a605 --- /dev/null +++ b/.github/workflows/clang-format.yml @@ -0,0 +1,48 @@ +name: clang-format +on: pull_request_target +jobs: + clang-format: + permissions: write-all + if: github.event_name != 'pull_request' || github.event.pull_request.head.repo.fork + name: "Code Style (Arch)" + runs-on: ubuntu-latest + container: + image: archlinux + steps: + - name: Checkout repository actions + uses: actions/checkout@v4 + with: + sparse-checkout: .github/actions + + - name: Setup base + uses: ./.github/actions/setup_base + + - name: Configure + run: meson setup build -Ddefault_library=static + + - name: clang-format check + run: ninja -C build clang-format-check + + - name: clang-format apply + if: ${{ failure() && github.event_name == 'pull_request' }} + run: ninja -C build clang-format + + - name: Create patch + if: ${{ failure() && github.event_name == 'pull_request' }} + run: | + echo 'Please fix the formatting issues by running [`clang-format`](https://wiki.hyprland.org/Contributing-and-Debugging/PR-Guidelines/#code-style), or directly apply this patch:' > clang-format.patch + echo '
' >> clang-format.patch + echo 'clang-format.patch' >> clang-format.patch + echo >> clang-format.patch + echo '```diff' >> clang-format.patch + git diff >> clang-format.patch + echo '```' >> clang-format.patch + echo >> clang-format.patch + echo '
' >> clang-format.patch + + - name: Comment patch + if: ${{ failure() && github.event_name == 'pull_request' }} + uses: mshick/add-pr-comment@v2 + with: + message-path: | + clang-format.patch From e7a72de9b5550784ea804c7bb4e84a28a74326a8 Mon Sep 17 00:00:00 2001 From: DDoSolitary Date: Tue, 28 Jan 2025 00:45:15 +0800 Subject: [PATCH 0927/2181] xwayland: send synthetic configure events (#9193) --- src/xwayland/XSurface.cpp | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/src/xwayland/XSurface.cpp b/src/xwayland/XSurface.cpp index b5ee75f6..91f20be5 100644 --- a/src/xwayland/XSurface.cpp +++ b/src/xwayland/XSurface.cpp @@ -169,6 +169,22 @@ void CXWaylandSurface::configure(const CBox& box) { uint32_t values[] = {box.x, box.y, box.width, box.height, 0}; xcb_configure_window(g_pXWayland->pWM->connection, xID, mask, values); + if (geometry.width == box.width && geometry.height == box.height) { + // ICCCM requires a synthetic event when window size is not changed + xcb_configure_notify_event_t e; + e.response_type = XCB_CONFIGURE_NOTIFY; + e.event = xID; + e.window = xID; + e.x = box.x; + e.y = box.y; + e.width = box.width; + e.height = box.height; + e.border_width = 0; + e.above_sibling = XCB_NONE; + e.override_redirect = overrideRedirect; + xcb_send_event(g_pXWayland->pWM->connection, false, xID, XCB_EVENT_MASK_STRUCTURE_NOTIFY, (const char*)&e); + } + g_pXWayland->pWM->updateClientList(); xcb_flush(g_pXWayland->pWM->connection); From 25d5ce4833a481325a2a948f51cabb6f4a6e1896 Mon Sep 17 00:00:00 2001 From: Mihai Fufezan Date: Mon, 27 Jan 2025 22:25:27 +0200 Subject: [PATCH 0928/2181] CI/setup_base: add libspng --- .github/actions/setup_base/action.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/actions/setup_base/action.yml b/.github/actions/setup_base/action.yml index 6df442b3..b4c9cf78 100644 --- a/.github/actions/setup_base/action.yml +++ b/.github/actions/setup_base/action.yml @@ -35,6 +35,7 @@ runs: libinput \ libjxl \ libliftoff \ + libspng \ libwebp \ libxcursor \ libxcvt \ From 5fd90548dc99d79dd2677e027a620c8ada9f4869 Mon Sep 17 00:00:00 2001 From: matt1432 Date: Mon, 27 Jan 2025 14:19:47 -0500 Subject: [PATCH 0929/2181] nix: fix duplicate inputs and update flake.lock --- flake.lock | 95 +++++++++++++----------------------------------------- flake.nix | 2 +- 2 files changed, 24 insertions(+), 73 deletions(-) diff --git a/flake.lock b/flake.lock index 34249b0a..ac73e5f7 100644 --- a/flake.lock +++ b/flake.lock @@ -105,11 +105,11 @@ ] }, "locked": { - "lastModified": 1737634889, - "narHash": "sha256-9JZE3KxcXOqZH9zs3UeadngDiK/yIACTiAR8HSA/TNI=", + "lastModified": 1737985436, + "narHash": "sha256-zx8FdI4zr2GhNyD1YGAqa2ymodAObTSAdwuWwVucewo=", "owner": "hyprwm", "repo": "hyprgraphics", - "rev": "0d77b4895ad5f1bb3b0ee43103a5246c58b65591", + "rev": "23783b96036f5506fdaf8b2250a1ef849d57f0d3", "type": "github" }, "original": { @@ -143,7 +143,10 @@ }, "hyprland-qt-support": { "inputs": { - "hyprlang": "hyprlang", + "hyprlang": [ + "hyprland-qtutils", + "hyprlang" + ], "nixpkgs": [ "hyprland-qtutils", "nixpkgs" @@ -170,7 +173,12 @@ "hyprland-qtutils": { "inputs": { "hyprland-qt-support": "hyprland-qt-support", + "hyprlang": [ + "hyprlang" + ], "hyprutils": [ + "hyprland-qtutils", + "hyprlang", "hyprutils" ], "nixpkgs": [ @@ -181,11 +189,11 @@ ] }, "locked": { - "lastModified": 1737811848, - "narHash": "sha256-WZ7LeiKHk5Y94MU5gHIWn0r8asWxYOvie4LqfCjVIZU=", + "lastModified": 1737981711, + "narHash": "sha256-lh6cL5D8nPplB3WovCQjLUZ7k7MViiBrMlpkfm4R7/c=", "owner": "hyprwm", "repo": "hyprland-qtutils", - "rev": "9c0831ff98856c0f312fcb8b57553fbe3dd34d5b", + "rev": "96bf0677fa9cd13508294e3d4559dfbbc8beff73", "type": "github" }, "original": { @@ -195,34 +203,6 @@ } }, "hyprlang": { - "inputs": { - "hyprutils": "hyprutils", - "nixpkgs": [ - "hyprland-qtutils", - "hyprland-qt-support", - "nixpkgs" - ], - "systems": [ - "hyprland-qtutils", - "hyprland-qt-support", - "systems" - ] - }, - "locked": { - "lastModified": 1737634606, - "narHash": "sha256-W7W87Cv6wqZ9PHegI6rH1+ve3zJPiyevMFf0/HwdbCQ=", - "owner": "hyprwm", - "repo": "hyprlang", - "rev": "f41271d35cc0f370d300413d756c2677f386af9d", - "type": "github" - }, - "original": { - "owner": "hyprwm", - "repo": "hyprlang", - "type": "github" - } - }, - "hyprlang_2": { "inputs": { "hyprutils": [ "hyprutils" @@ -249,35 +229,6 @@ } }, "hyprutils": { - "inputs": { - "nixpkgs": [ - "hyprland-qtutils", - "hyprland-qt-support", - "hyprlang", - "nixpkgs" - ], - "systems": [ - "hyprland-qtutils", - "hyprland-qt-support", - "hyprlang", - "systems" - ] - }, - "locked": { - "lastModified": 1737632363, - "narHash": "sha256-X9I8POSlHxBVjD0fiX1O2j7U9Zi1+4rIkrsyHP0uHXY=", - "owner": "hyprwm", - "repo": "hyprutils", - "rev": "006620eb29d54ea9086538891404c78563d1bae1", - "type": "github" - }, - "original": { - "owner": "hyprwm", - "repo": "hyprutils", - "type": "github" - } - }, - "hyprutils_2": { "inputs": { "nixpkgs": [ "nixpkgs" @@ -287,11 +238,11 @@ ] }, "locked": { - "lastModified": 1737725508, - "narHash": "sha256-jGmcPc6y/prg/4A8KGYqJ27nSPaProCMiFadaxNAKvA=", + "lastModified": 1737978343, + "narHash": "sha256-TfFS0HCEJh63Kahrkp1h9hVDMdLU8a37Zz+IFucxyfA=", "owner": "hyprwm", "repo": "hyprutils", - "rev": "fb0c2d1de3d1ef7396d19c18ac09e12bd956929e", + "rev": "6a8bc9d2a4451df12f5179dc0b1d2d46518a90ab", "type": "github" }, "original": { @@ -325,11 +276,11 @@ }, "nixpkgs": { "locked": { - "lastModified": 1737632463, - "narHash": "sha256-38J9QfeGSej341ouwzqf77WIHAScihAKCt8PQJ+NH28=", + "lastModified": 1737885589, + "narHash": "sha256-Zf0hSrtzaM1DEz8//+Xs51k/wdSajticVrATqDrfQjg=", "owner": "NixOS", "repo": "nixpkgs", - "rev": "0aa475546ed21629c4f5bbf90e38c846a99ec9e9", + "rev": "852ff1d9e153d8875a83602e03fdef8a63f0ecf8", "type": "github" }, "original": { @@ -368,8 +319,8 @@ "hyprgraphics": "hyprgraphics", "hyprland-protocols": "hyprland-protocols", "hyprland-qtutils": "hyprland-qtutils", - "hyprlang": "hyprlang_2", - "hyprutils": "hyprutils_2", + "hyprlang": "hyprlang", + "hyprutils": "hyprutils", "hyprwayland-scanner": "hyprwayland-scanner", "nixpkgs": "nixpkgs", "pre-commit-hooks": "pre-commit-hooks", diff --git a/flake.nix b/flake.nix index 821a5f90..c1c580ae 100644 --- a/flake.nix +++ b/flake.nix @@ -39,7 +39,7 @@ url = "github:hyprwm/hyprland-qtutils"; inputs.nixpkgs.follows = "nixpkgs"; inputs.systems.follows = "systems"; - inputs.hyprutils.follows = "hyprutils"; + inputs.hyprlang.follows = "hyprlang"; }; hyprlang = { From d2773d7a4ecde7111af4ec71b51b1996ec1d96bf Mon Sep 17 00:00:00 2001 From: Jan Beich Date: Mon, 27 Jan 2025 22:06:48 +0000 Subject: [PATCH 0930/2181] deps: add libinotify-kqueue on BSDs after 8dd2cd41fb4c (#9197) src/config/ConfigWatcher.cpp:2:10: fatal error: 'sys/inotify.h' file not found 2 | #include | ^~~~~~~~~~~~~~~ --- CMakeLists.txt | 6 ++++++ meson.build | 1 + src/meson.build | 1 + 3 files changed, 8 insertions(+) diff --git a/CMakeLists.txt b/CMakeLists.txt index 3cfb8688..a34d677c 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -197,6 +197,12 @@ if(NOT HAS_TIMERFD AND epoll_FOUND) target_link_libraries(Hyprland PkgConfig::epoll) endif() +check_include_file("sys/inotify.h" HAS_INOTIFY) +pkg_check_modules(inotify IMPORTED_TARGET libinotify) +if(NOT HAS_INOTIFY AND inotify_FOUND) + target_link_libraries(Hyprland PkgConfig::inotify) +endif() + if(LEGACY_RENDERER) message(STATUS "Using the legacy GLES2 renderer!") add_compile_definitions(LEGACY_RENDERER) diff --git a/meson.build b/meson.build index 6b50ff2d..ae6e3940 100644 --- a/meson.build +++ b/meson.build @@ -58,6 +58,7 @@ endif backtrace_dep = cpp_compiler.find_library('execinfo', required: false) epoll_dep = dependency('epoll-shim', required: false) # timerfd on BSDs +inotify_dep = dependency('libinotify', required: false) # inotify on BSDs re2 = dependency('re2', required: true) diff --git a/src/meson.build b/src/meson.build index 7054d8e4..3973dc4c 100644 --- a/src/meson.build +++ b/src/meson.build @@ -32,6 +32,7 @@ executable( xcb_xfixes_dep, backtrace_dep, epoll_dep, + inotify_dep, gio_dep, tracy, From d3042e5358a91287d6ff9d8c745dc70af1ebdc90 Mon Sep 17 00:00:00 2001 From: DDoSolitary Date: Tue, 28 Jan 2025 18:04:57 +0800 Subject: [PATCH 0931/2181] xwayland: respect window size set by configure requests (#9190) --- src/managers/XWaylandManager.cpp | 26 +++----------------------- src/xwayland/XWM.cpp | 4 ++-- 2 files changed, 5 insertions(+), 25 deletions(-) diff --git a/src/managers/XWaylandManager.cpp b/src/managers/XWaylandManager.cpp index f103266d..a5506329 100644 --- a/src/managers/XWaylandManager.cpp +++ b/src/managers/XWaylandManager.cpp @@ -82,29 +82,9 @@ CBox CHyprXWaylandManager::getGeometryForWindow(PHLWINDOW pWindow) { CBox box; - if (pWindow->m_bIsX11) { - const auto SIZEHINTS = pWindow->m_pXWaylandSurface->sizeHints.get(); - - if (SIZEHINTS && !pWindow->isX11OverrideRedirect()) { - // WM_SIZE_HINTS' x,y,w,h is deprecated it seems. - // Source: https://x.org/releases/X11R7.6/doc/xorg-docs/specs/ICCCM/icccm.html#wm_normal_hints_property - box.x = pWindow->m_pXWaylandSurface->geometry.x; - box.y = pWindow->m_pXWaylandSurface->geometry.y; - - constexpr int ICCCM_USSize = 0x2; - constexpr int ICCCM_PSize = 0x8; - - if ((SIZEHINTS->flags & ICCCM_USSize) || (SIZEHINTS->flags & ICCCM_PSize)) { - box.w = SIZEHINTS->base_width; - box.h = SIZEHINTS->base_height; - } else { - box.w = pWindow->m_pXWaylandSurface->geometry.w; - box.h = pWindow->m_pXWaylandSurface->geometry.h; - } - } else - box = pWindow->m_pXWaylandSurface->geometry; - - } else if (pWindow->m_pXDGSurface) + if (pWindow->m_bIsX11) + box = pWindow->m_pXWaylandSurface->geometry; + else if (pWindow->m_pXDGSurface) box = pWindow->m_pXDGSurface->current.geometry; return box; diff --git a/src/xwayland/XWM.cpp b/src/xwayland/XWM.cpp index ef139b38..6673105e 100644 --- a/src/xwayland/XWM.cpp +++ b/src/xwayland/XWM.cpp @@ -102,8 +102,8 @@ void CXWM::handleMapRequest(xcb_map_request_event_t* e) { const bool HAS_HINTS = XSURF->sizeHints && Vector2D{XSURF->sizeHints->base_width, XSURF->sizeHints->base_height} > Vector2D{5, 5}; const auto DESIREDSIZE = HAS_HINTS ? Vector2D{XSURF->sizeHints->base_width, XSURF->sizeHints->base_height} : Vector2D{800, 800}; - // if it's too small, or its base size is set, configure it. - if ((SMALL || HAS_HINTS) && !XSURF->overrideRedirect) // default to 800 x 800 + // if it's too small, configure it. + if (SMALL && !XSURF->overrideRedirect) // default to 800 x 800 XSURF->configure({XSURF->geometry.pos(), DESIREDSIZE}); Debug::log(LOG, "[xwm] Mapping window {} in X (geometry {}x{} at {}x{}))", e->window, XSURF->geometry.width, XSURF->geometry.height, XSURF->geometry.x, XSURF->geometry.y); From 529ad4eaf450e558998e7417db5db6602e7fb497 Mon Sep 17 00:00:00 2001 From: Tom Englund Date: Tue, 28 Jan 2025 10:15:08 +0100 Subject: [PATCH 0932/2181] ikeyboard: free xkbSymState in clearManuallyAllocd asan reported a leak on xkbSymState on destruction, because it wasnt beeing unrefed, was only being unrefed on calls to updateXKBTranslationState. --- src/devices/IKeyboard.cpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/devices/IKeyboard.cpp b/src/devices/IKeyboard.cpp index d1119772..4623fe84 100644 --- a/src/devices/IKeyboard.cpp +++ b/src/devices/IKeyboard.cpp @@ -44,6 +44,10 @@ void IKeyboard::clearManuallyAllocd() { if (xkbKeymapFD >= 0) close(xkbKeymapFD); + if (xkbSymState) + xkb_state_unref(xkbSymState); + + xkbSymState = nullptr; xkbKeymap = nullptr; xkbState = nullptr; xkbStaticState = nullptr; From 1d3904c3e7a8b74ea83669f73ee408bd38390b11 Mon Sep 17 00:00:00 2001 From: Tom Englund Date: Tue, 28 Jan 2025 10:20:54 +0100 Subject: [PATCH 0933/2181] configmgr: properly free glob memory globfree is only freeing internally allocated resources, so also call free the on glob_t memory we allocated. --- src/config/ConfigManager.cpp | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/src/config/ConfigManager.cpp b/src/config/ConfigManager.cpp index 93289bf7..daff9285 100644 --- a/src/config/ConfigManager.cpp +++ b/src/config/ConfigManager.cpp @@ -2690,8 +2690,14 @@ std::optional CConfigManager::handleSource(const std::string& comma Debug::log(ERR, "source= path garbage"); return "source= path " + rawpath + " bogus!"; } - std::unique_ptr glob_buf{new glob_t, [](glob_t* g) { globfree(g); }}; - memset(glob_buf.get(), 0, sizeof(glob_t)); + + std::unique_ptr glob_buf{static_cast(calloc(1, sizeof(glob_t))), // allocate and zero-initialize + [](glob_t* g) { + if (g) { + globfree(g); // free internal resources allocated by glob() + free(g); // free the memory for the glob_t structure + } + }}; if (auto r = glob(absolutePath(rawpath, configCurrentPath).c_str(), GLOB_TILDE, nullptr, glob_buf.get()); r != 0) { std::string err = std::format("source= globbing error: {}", r == GLOB_NOMATCH ? "found no match" : GLOB_ABORTED ? "read error" : "out of memory"); From 3d1dd6b5c7b90e513e86c1ad27c6c01a5c69e4f8 Mon Sep 17 00:00:00 2001 From: Vaxry Date: Tue, 28 Jan 2025 23:43:26 +0000 Subject: [PATCH 0934/2181] presentation: log a fixme when there is a feedback leak ref #8087 --- src/protocols/PresentationTime.cpp | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/protocols/PresentationTime.cpp b/src/protocols/PresentationTime.cpp index a9139ac0..05fda8ea 100644 --- a/src/protocols/PresentationTime.cpp +++ b/src/protocols/PresentationTime.cpp @@ -130,6 +130,11 @@ void CPresentationProtocol::onPresented(PHLMONITOR pMonitor, timespec* when, uin } } + if (m_vFeedbacks.size() > 10000 /* arbitrary number I chose as fitting */) { + LOGM(ERR, "FIXME: presentation has a feedback leak, and has grown to {} pending entries!!! Dropping!!!!!", m_vFeedbacks.size()); + m_vFeedbacks = {m_vFeedbacks.begin() + 9000, m_vFeedbacks.end()}; + } + std::erase_if(m_vFeedbacks, [](const auto& other) { return !other->surface || other->done; }); std::erase_if(m_vQueue, [pMonitor](const auto& other) { return !other->surface || other->pMonitor == pMonitor || !other->pMonitor || other->done; }); } From b884f1f7c88b798ba5d1b6a794615bf046ff1f14 Mon Sep 17 00:00:00 2001 From: nyx Date: Wed, 29 Jan 2025 03:41:56 -0500 Subject: [PATCH 0935/2181] renderer: calculate UV using both pixel and monitor dimensions (#9210) --- src/render/OpenGL.cpp | 16 +++++++++++----- 1 file changed, 11 insertions(+), 5 deletions(-) diff --git a/src/render/OpenGL.cpp b/src/render/OpenGL.cpp index ee5d9a86..78b53c9b 100644 --- a/src/render/OpenGL.cpp +++ b/src/render/OpenGL.cpp @@ -2147,14 +2147,20 @@ void CHyprOpenGLImpl::renderTextureWithBlur(SP tex, const CBox& box, f glStencilOp(GL_KEEP, GL_KEEP, GL_REPLACE); // stencil done. Render everything. - CBox MONITORBOX = {0, 0, m_RenderData.pMonitor->vecTransformedSize.x, m_RenderData.pMonitor->vecTransformedSize.y}; - // render our great blurred FB - // calculate the uv for it const auto LASTTL = m_RenderData.primarySurfaceUVTopLeft; const auto LASTBR = m_RenderData.primarySurfaceUVBottomRight; - m_RenderData.primarySurfaceUVTopLeft = box.pos() / MONITORBOX.size(); - m_RenderData.primarySurfaceUVBottomRight = (box.pos() + box.size()) / MONITORBOX.size(); + CBox transformedBox = box; + transformedBox.transform(wlTransformToHyprutils(invertTransform(m_RenderData.pMonitor->transform)), m_RenderData.pMonitor->vecTransformedSize.x, + m_RenderData.pMonitor->vecTransformedSize.y); + + CBox monitorSpaceBox = {transformedBox.pos().x / m_RenderData.pMonitor->vecPixelSize.x * m_RenderData.pMonitor->vecTransformedSize.x, + transformedBox.pos().y / m_RenderData.pMonitor->vecPixelSize.y * m_RenderData.pMonitor->vecTransformedSize.y, + transformedBox.width / m_RenderData.pMonitor->vecPixelSize.x * m_RenderData.pMonitor->vecTransformedSize.x, + transformedBox.height / m_RenderData.pMonitor->vecPixelSize.y * m_RenderData.pMonitor->vecTransformedSize.y}; + + m_RenderData.primarySurfaceUVTopLeft = monitorSpaceBox.pos() / m_RenderData.pMonitor->vecTransformedSize; + m_RenderData.primarySurfaceUVBottomRight = (monitorSpaceBox.pos() + monitorSpaceBox.size()) / m_RenderData.pMonitor->vecTransformedSize; static auto PBLURIGNOREOPACITY = CConfigValue("decoration:blur:ignore_opacity"); setMonitorTransformEnabled(true); From d41135d07c15f122d1ca2a03ace9ed3e080b2e28 Mon Sep 17 00:00:00 2001 From: "Owen L." <32573897+mageowl@users.noreply.github.com> Date: Wed, 29 Jan 2025 01:27:34 -0800 Subject: [PATCH 0936/2181] input: change window grab cursor to closed hand (#9196) --- src/layout/IHyprLayout.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/layout/IHyprLayout.cpp b/src/layout/IHyprLayout.cpp index 5e5669b8..57ae5f40 100644 --- a/src/layout/IHyprLayout.cpp +++ b/src/layout/IHyprLayout.cpp @@ -307,7 +307,7 @@ void IHyprLayout::onBeginDragWindow() { } if (g_pInputManager->dragMode != MBIND_RESIZE && g_pInputManager->dragMode != MBIND_RESIZE_FORCE_RATIO && g_pInputManager->dragMode != MBIND_RESIZE_BLOCK_RATIO) - g_pInputManager->setCursorImageUntilUnset("grab"); + g_pInputManager->setCursorImageUntilUnset("grabbing"); g_pHyprRenderer->damageWindow(DRAGGINGWINDOW); From 344e32d71bf115a32434da3fa72b2b6238706625 Mon Sep 17 00:00:00 2001 From: vaxerski Date: Wed, 29 Jan 2025 10:42:46 +0000 Subject: [PATCH 0937/2181] pass/rect: fix bounding / opaque regions fixes #9212 --- src/render/pass/PassElement.hpp | 4 ++-- src/render/pass/RectPassElement.cpp | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/render/pass/PassElement.hpp b/src/render/pass/PassElement.hpp index b45970aa..a006ce9e 100644 --- a/src/render/pass/PassElement.hpp +++ b/src/render/pass/PassElement.hpp @@ -13,7 +13,7 @@ class IPassElement { virtual const char* passName() = 0; virtual void discard(); virtual bool undiscardable(); - virtual std::optional boundingBox(); - virtual CRegion opaqueRegion(); + virtual std::optional boundingBox(); // in monitor-local logical coordinates + virtual CRegion opaqueRegion(); // in monitor-local logical coordinates virtual bool disableSimplification(); }; diff --git a/src/render/pass/RectPassElement.cpp b/src/render/pass/RectPassElement.cpp index a9ab737d..fba06286 100644 --- a/src/render/pass/RectPassElement.cpp +++ b/src/render/pass/RectPassElement.cpp @@ -24,7 +24,7 @@ bool CRectPassElement::needsPrecomputeBlur() { } std::optional CRectPassElement::boundingBox() { - return data.box; + return data.box.copy().scale(1.F / g_pHyprOpenGL->m_RenderData.pMonitor->scale).round(); } CRegion CRectPassElement::opaqueRegion() { From aaa5573c73636a76dd3ae4758bfd89ae4d5eeb8a Mon Sep 17 00:00:00 2001 From: vaxerski Date: Wed, 29 Jan 2025 10:50:39 +0000 Subject: [PATCH 0938/2181] config/hyprctl: fix keyword not updating autoreload ref #9139 --- src/config/ConfigManager.cpp | 8 ++++++-- src/config/ConfigManager.hpp | 1 + src/debug/HyprCtl.cpp | 3 +++ 3 files changed, 10 insertions(+), 2 deletions(-) diff --git a/src/config/ConfigManager.cpp b/src/config/ConfigManager.cpp index daff9285..047c58d9 100644 --- a/src/config/ConfigManager.cpp +++ b/src/config/ConfigManager.cpp @@ -912,12 +912,16 @@ std::optional CConfigManager::resetHLConfig() { return RET; } +void CConfigManager::updateWatcher() { + static const auto PDISABLEAUTORELOAD = CConfigValue("misc:disable_autoreload"); + g_pConfigWatcher->setWatchList(*PDISABLEAUTORELOAD ? std::vector{} : m_configPaths); +} + void CConfigManager::postConfigReload(const Hyprlang::CParseResult& result) { static const auto PENABLEEXPLICIT = CConfigValue("render:explicit_sync"); - static const auto PDISABLEAUTORELOAD = CConfigValue("misc:disable_autoreload"); static int prevEnabledExplicit = *PENABLEEXPLICIT; - g_pConfigWatcher->setWatchList(*PDISABLEAUTORELOAD ? std::vector{} : m_configPaths); + updateWatcher(); for (auto const& w : g_pCompositor->m_vWindows) { w->uncacheWindowDecos(); diff --git a/src/config/ConfigManager.hpp b/src/config/ConfigManager.hpp index ae0ba759..f0696882 100644 --- a/src/config/ConfigManager.hpp +++ b/src/config/ConfigManager.hpp @@ -190,6 +190,7 @@ class CConfigManager { void ensureVRR(PHLMONITOR pMonitor = nullptr); bool shouldUseSoftwareCursors(); + void updateWatcher(); std::string parseKeyword(const std::string&, const std::string&); diff --git a/src/debug/HyprCtl.cpp b/src/debug/HyprCtl.cpp index cfdba100..359428b1 100644 --- a/src/debug/HyprCtl.cpp +++ b/src/debug/HyprCtl.cpp @@ -1100,6 +1100,9 @@ static std::string dispatchKeyword(eHyprCtlOutputFormat format, std::string in) } } + if (COMMAND.contains("misc:disable_autoreload")) + g_pConfigManager->updateWatcher(); + // decorations will probably need a repaint if (COMMAND.contains("decoration:") || COMMAND.contains("border") || COMMAND == "workspace" || COMMAND.contains("zoom_factor") || COMMAND == "source" || COMMAND.starts_with("windowrule")) { From 61319197155cbcb3b8d5f004f46c2249029ec1f3 Mon Sep 17 00:00:00 2001 From: Vaxry Date: Wed, 29 Jan 2025 13:16:50 +0000 Subject: [PATCH 0939/2181] monitor: round refresh rates in sorting modes fixes #9209 --- src/helpers/Monitor.cpp | 7 ++++--- src/helpers/Monitor.hpp | 4 ++-- 2 files changed, 6 insertions(+), 5 deletions(-) diff --git a/src/helpers/Monitor.cpp b/src/helpers/Monitor.cpp index 19d68a56..9ea85bca 100644 --- a/src/helpers/Monitor.cpp +++ b/src/helpers/Monitor.cpp @@ -456,9 +456,9 @@ bool CMonitor::applyMonitorRule(SMonitorRule* pMonitorRule, bool force) { // sort prioritizing refresh rate 1st and resolution 2nd, then add best 3 addBest3Modes([](auto const& a, auto const& b) { - if (a->refreshRate > b->refreshRate) + if (std::round(a->refreshRate) > std::round(b->refreshRate)) return true; - else if (DELTALESSTHAN((float)a->refreshRate, (float)b->refreshRate, 1000) && a->pixelSize.x > b->pixelSize.x && a->pixelSize.y > b->pixelSize.y) + else if (DELTALESSTHAN((float)a->refreshRate, (float)b->refreshRate, 1.F) && a->pixelSize.x > b->pixelSize.x && a->pixelSize.y > b->pixelSize.y) return true; return false; }); @@ -469,7 +469,8 @@ bool CMonitor::applyMonitorRule(SMonitorRule* pMonitorRule, bool force) { addBest3Modes([](auto const& a, auto const& b) { if (a->pixelSize.x > b->pixelSize.x && a->pixelSize.y > b->pixelSize.y) return true; - else if (DELTALESSTHAN(a->pixelSize.x, b->pixelSize.x, 1) && DELTALESSTHAN(a->pixelSize.y, b->pixelSize.y, 1) && a->refreshRate > b->refreshRate) + else if (DELTALESSTHAN(a->pixelSize.x, b->pixelSize.x, 1) && DELTALESSTHAN(a->pixelSize.y, b->pixelSize.y, 1) && + std::round(a->refreshRate) > std::round(b->refreshRate)) return true; return false; }); diff --git a/src/helpers/Monitor.hpp b/src/helpers/Monitor.hpp index 7c19b57c..1b207f7d 100644 --- a/src/helpers/Monitor.hpp +++ b/src/helpers/Monitor.hpp @@ -33,7 +33,7 @@ struct SMonitorRule { Vector2D resolution = Vector2D(1280, 720); Vector2D offset = Vector2D(0, 0); float scale = 1; - float refreshRate = 60; + float refreshRate = 60; // Hz bool disabled = false; wl_output_transform transform = WL_OUTPUT_TRANSFORM_NORMAL; std::string mirrorOf = ""; @@ -92,7 +92,7 @@ class CMonitor { CDamageRing damage; SP output; - float refreshRate = 60; + float refreshRate = 60; // Hz int forceFullFrames = 0; bool scheduledRecalc = false; wl_output_transform transform = WL_OUTPUT_TRANSFORM_NORMAL; From 6fc9c8e4797a272c688fc74b872db5d828c21f02 Mon Sep 17 00:00:00 2001 From: Mihai Fufezan Date: Wed, 29 Jan 2025 22:45:38 +0200 Subject: [PATCH 0940/2181] flake.lock: update --- flake.lock | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/flake.lock b/flake.lock index ac73e5f7..dfdd8c5b 100644 --- a/flake.lock +++ b/flake.lock @@ -16,11 +16,11 @@ ] }, "locked": { - "lastModified": 1737636397, - "narHash": "sha256-F5MbBj3QVorycVSFE9qjuOTLtIQBqt2VWbXa0uwzm98=", + "lastModified": 1738183445, + "narHash": "sha256-C1He3N1SA8D2u+TSlldbA9wiYwDvXI4GxX3zKaeD7qU=", "owner": "hyprwm", "repo": "aquamarine", - "rev": "7fe006981fae53e931f513026fc754e322f13145", + "rev": "48a000cf35dd10bfeb231152735aebbe875f4b74", "type": "github" }, "original": { @@ -79,11 +79,11 @@ ] }, "locked": { - "lastModified": 1737634937, - "narHash": "sha256-Ffw4ujFpi++6pPHe+gCBOfDgAoNlzVPZN6MReC1beu8=", + "lastModified": 1738178255, + "narHash": "sha256-+D6Nu2ewXbMTFzx/Q4jDOo+LAOUPr0cxQJg5k33daIE=", "owner": "hyprwm", "repo": "hyprcursor", - "rev": "9c5dd1f7c825ee47f72727ad0a4e16ca46a2688e", + "rev": "dcadd3398abe146d60c67e0d9ee6e27b301cae82", "type": "github" }, "original": { @@ -105,11 +105,11 @@ ] }, "locked": { - "lastModified": 1737985436, - "narHash": "sha256-zx8FdI4zr2GhNyD1YGAqa2ymodAObTSAdwuWwVucewo=", + "lastModified": 1738018829, + "narHash": "sha256-5Ol5iahMlELx3lWuChyZsqqLk6sP6aqaJCJFw92OZGo=", "owner": "hyprwm", "repo": "hyprgraphics", - "rev": "23783b96036f5506fdaf8b2250a1ef849d57f0d3", + "rev": "12cd7034e441a5ebfdef1a090c0788413b4a635b", "type": "github" }, "original": { From 09ec1cca51e1880dfc855c168a0dd810ff1ddcd6 Mon Sep 17 00:00:00 2001 From: Vaxry Date: Wed, 29 Jan 2025 23:05:54 +0000 Subject: [PATCH 0941/2181] popup: stop refocusing at unmap fixes #9018 --- src/desktop/Popup.cpp | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/src/desktop/Popup.cpp b/src/desktop/Popup.cpp index 93a810ff..dea94f55 100644 --- a/src/desktop/Popup.cpp +++ b/src/desktop/Popup.cpp @@ -138,10 +138,11 @@ void CPopup::onUnmap() { }, nullptr); - const bool WASLASTFOCUS = g_pSeatManager->state.keyboardFocus == m_pWLSurface->resource() || g_pSeatManager->state.pointerFocus == m_pWLSurface->resource(); + // TODO: probably refocus, but without a motion event? + // const bool WASLASTFOCUS = g_pSeatManager->state.keyboardFocus == m_pWLSurface->resource() || g_pSeatManager->state.pointerFocus == m_pWLSurface->resource(); - if (WASLASTFOCUS) - g_pInputManager->simulateMouseMovement(); + // if (WASLASTFOCUS) + // g_pInputManager->simulateMouseMovement(); } void CPopup::onCommit(bool ignoreSiblings) { From d462cc7fa166e1e6a6f14b58a2dd1e8b92e15426 Mon Sep 17 00:00:00 2001 From: Vaxry Date: Wed, 29 Jan 2025 23:16:25 +0000 Subject: [PATCH 0942/2181] subsurface: fix invalid parent typo fixes #9224 --- src/desktop/Subsurface.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/desktop/Subsurface.cpp b/src/desktop/Subsurface.cpp index a68cf8f3..d7a53954 100644 --- a/src/desktop/Subsurface.cpp +++ b/src/desktop/Subsurface.cpp @@ -143,7 +143,7 @@ void CSubsurface::onNewSubsurface(SP pSubsurface) { ASSERT(PSUBSURFACE); - PSUBSURFACE->m_pParent = PSUBSURFACE; + PSUBSURFACE->m_pParent = m_pSelf; } void CSubsurface::onMap() { From 7d1c78f4a3720b693fedeb5d4f2d3f4da37f7fd3 Mon Sep 17 00:00:00 2001 From: Honkazel <169346573+Honkazel@users.noreply.github.com> Date: Thu, 30 Jan 2025 16:07:06 +0500 Subject: [PATCH 0943/2181] core,hyprctl: clang, clang-tidy, typo fixes and dtors changes (#9233) * declare dtor once + DMABBUF typo fix * dup include + clang moment * linux-dmabuf: last minute nit change --- hyprctl/main.cpp | 3 --- src/Compositor.cpp | 1 - src/config/ConfigDataValues.hpp | 2 +- src/config/ConfigManager.cpp | 4 ---- src/desktop/Subsurface.cpp | 4 ---- src/desktop/Subsurface.hpp | 4 ++-- src/helpers/Monitor.cpp | 4 ---- src/helpers/Monitor.hpp | 3 +-- src/hyprerror/HyprError.cpp | 2 -- src/hyprerror/HyprError.hpp | 2 +- src/layout/IHyprLayout.cpp | 2 -- src/layout/IHyprLayout.hpp | 2 +- src/layout/MasterLayout.hpp | 1 - src/managers/EventManager.hpp | 1 - src/managers/XCursorManager.hpp | 8 +++---- src/protocols/FocusGrab.cpp | 4 ---- src/protocols/FocusGrab.hpp | 2 +- src/protocols/LinuxDMABUF.cpp | 22 ++++++------------- src/protocols/LinuxDMABUF.hpp | 16 +++++++------- src/protocols/SinglePixel.cpp | 8 ------- src/protocols/SinglePixel.hpp | 6 ++--- src/protocols/core/Shm.cpp | 4 ---- src/protocols/core/Shm.hpp | 2 +- .../decorations/CHyprBorderDecoration.cpp | 4 ---- .../decorations/CHyprBorderDecoration.hpp | 2 +- .../decorations/CHyprDropShadowDecoration.cpp | 2 -- .../decorations/CHyprDropShadowDecoration.hpp | 2 +- .../decorations/CHyprGroupBarDecoration.cpp | 4 ---- .../decorations/CHyprGroupBarDecoration.hpp | 4 ++-- .../decorations/IHyprWindowDecoration.cpp | 2 -- .../decorations/IHyprWindowDecoration.hpp | 2 +- 31 files changed, 35 insertions(+), 94 deletions(-) diff --git a/hyprctl/main.cpp b/hyprctl/main.cpp index 16d66223..4cc73bdf 100644 --- a/hyprctl/main.cpp +++ b/hyprctl/main.cpp @@ -21,13 +21,10 @@ #include #include #include -#include #include #include #include -#include #include -#include using namespace Hyprutils::String; #include "Strings.hpp" diff --git a/src/Compositor.cpp b/src/Compositor.cpp index 3421c314..1daccbfd 100644 --- a/src/Compositor.cpp +++ b/src/Compositor.cpp @@ -22,7 +22,6 @@ #include #include #include -#include #include #include "debug/HyprCtl.hpp" #include "debug/CrashReporter.hpp" diff --git a/src/config/ConfigDataValues.hpp b/src/config/ConfigDataValues.hpp index 80e45a05..901fb317 100644 --- a/src/config/ConfigDataValues.hpp +++ b/src/config/ConfigDataValues.hpp @@ -11,7 +11,7 @@ enum eConfigValueDataTypes : int8_t { class ICustomConfigValueData { public: - virtual ~ICustomConfigValueData() = 0; + virtual ~ICustomConfigValueData() = default; virtual eConfigValueDataTypes getDataType() = 0; diff --git a/src/config/ConfigManager.cpp b/src/config/ConfigManager.cpp index 047c58d9..86581b10 100644 --- a/src/config/ConfigManager.cpp +++ b/src/config/ConfigManager.cpp @@ -1709,10 +1709,6 @@ void CConfigManager::handlePluginLoads() { } } -ICustomConfigValueData::~ICustomConfigValueData() { - ; // empty -} - const std::unordered_map>& CConfigManager::getAnimationConfig() { return m_AnimationTree.getFullConfig(); } diff --git a/src/desktop/Subsurface.cpp b/src/desktop/Subsurface.cpp index d7a53954..1d938f39 100644 --- a/src/desktop/Subsurface.cpp +++ b/src/desktop/Subsurface.cpp @@ -31,10 +31,6 @@ CSubsurface::CSubsurface(SP pSubsurface, WP pOwne initExistingSubsurfaces(pSubsurface->surface.lock()); } -CSubsurface::~CSubsurface() { - ; -} - void CSubsurface::initSignals() { if (m_pSubsurface) { listeners.commitSubsurface = m_pSubsurface->surface->events.commit.registerListener([this](std::any d) { onCommit(); }); diff --git a/src/desktop/Subsurface.hpp b/src/desktop/Subsurface.hpp index f16a11ea..41958671 100644 --- a/src/desktop/Subsurface.hpp +++ b/src/desktop/Subsurface.hpp @@ -17,7 +17,7 @@ class CSubsurface { CSubsurface(SP pSubsurface, PHLWINDOW pOwner); CSubsurface(SP pSubsurface, WP pOwner); - ~CSubsurface(); + ~CSubsurface() = default; Vector2D coordsRelativeToParent(); Vector2D coordsGlobal(); @@ -62,4 +62,4 @@ class CSubsurface { void initSignals(); void initExistingSubsurfaces(SP pSurface); void checkSiblingDamage(); -}; \ No newline at end of file +}; diff --git a/src/helpers/Monitor.cpp b/src/helpers/Monitor.cpp index 9ea85bca..42acf485 100644 --- a/src/helpers/Monitor.cpp +++ b/src/helpers/Monitor.cpp @@ -1434,10 +1434,6 @@ CMonitorState::CMonitorState(CMonitor* owner) : m_pOwner(owner) { ; } -CMonitorState::~CMonitorState() { - ; -} - void CMonitorState::ensureBufferPresent() { const auto STATE = m_pOwner->output->state->state(); if (!STATE.enabled) { diff --git a/src/helpers/Monitor.hpp b/src/helpers/Monitor.hpp index 1b207f7d..2b02c30a 100644 --- a/src/helpers/Monitor.hpp +++ b/src/helpers/Monitor.hpp @@ -6,7 +6,6 @@ #include "../SharedDefs.hpp" #include "MiscFunctions.hpp" #include "WLClasses.hpp" -#include #include #include @@ -48,7 +47,7 @@ class CSyncTimeline; class CMonitorState { public: CMonitorState(CMonitor* owner); - ~CMonitorState(); + ~CMonitorState() = default; bool commit(); bool test(); diff --git a/src/hyprerror/HyprError.cpp b/src/hyprerror/HyprError.cpp index 4076ed3a..9f889fdf 100644 --- a/src/hyprerror/HyprError.cpp +++ b/src/hyprerror/HyprError.cpp @@ -32,8 +32,6 @@ CHyprError::CHyprError() { m_pTexture = makeShared(); } -CHyprError::~CHyprError() = default; - void CHyprError::queueCreate(std::string message, const CHyprColor& color) { m_szQueued = message; m_cQueued = color; diff --git a/src/hyprerror/HyprError.hpp b/src/hyprerror/HyprError.hpp index 771e50f0..12de0c81 100644 --- a/src/hyprerror/HyprError.hpp +++ b/src/hyprerror/HyprError.hpp @@ -9,7 +9,7 @@ class CHyprError { public: CHyprError(); - ~CHyprError(); + ~CHyprError() = default; void queueCreate(std::string message, const CHyprColor& color); void draw(); diff --git a/src/layout/IHyprLayout.cpp b/src/layout/IHyprLayout.cpp index 57ae5f40..9a0ba6ee 100644 --- a/src/layout/IHyprLayout.cpp +++ b/src/layout/IHyprLayout.cpp @@ -950,5 +950,3 @@ Vector2D IHyprLayout::predictSizeForNewWindow(PHLWINDOW pWindow) { return sizePredicted; } - -IHyprLayout::~IHyprLayout() = default; diff --git a/src/layout/IHyprLayout.hpp b/src/layout/IHyprLayout.hpp index ab188b9b..e31bb63e 100644 --- a/src/layout/IHyprLayout.hpp +++ b/src/layout/IHyprLayout.hpp @@ -43,7 +43,7 @@ enum eDirection : int8_t { class IHyprLayout { public: - virtual ~IHyprLayout() = 0; + virtual ~IHyprLayout() = default; virtual void onEnable() = 0; virtual void onDisable() = 0; diff --git a/src/layout/MasterLayout.hpp b/src/layout/MasterLayout.hpp index 381ccc9d..f658fdaa 100644 --- a/src/layout/MasterLayout.hpp +++ b/src/layout/MasterLayout.hpp @@ -5,7 +5,6 @@ #include "../helpers/varlist/VarList.hpp" #include #include -#include #include enum eFullscreenMode : int8_t; diff --git a/src/managers/EventManager.hpp b/src/managers/EventManager.hpp index 5a88963e..6b506d33 100644 --- a/src/managers/EventManager.hpp +++ b/src/managers/EventManager.hpp @@ -1,6 +1,5 @@ #pragma once #include -#include #include "../defines.hpp" #include "../helpers/memory/Memory.hpp" diff --git a/src/managers/XCursorManager.hpp b/src/managers/XCursorManager.hpp index 2517e85e..3052206f 100644 --- a/src/managers/XCursorManager.hpp +++ b/src/managers/XCursorManager.hpp @@ -13,10 +13,10 @@ extern "C" { // gangsta bootleg XCursor impl. adidas balkanized struct SXCursorImage { - Vector2D size; - Vector2D hotspot; - std::vector pixels; // XPixel is a u32 - uint32_t delay; // animation delay to next frame (ms) + Hyprutils::Math::Vector2D size; + Hyprutils::Math::Vector2D hotspot; + std::vector pixels; // XPixel is a u32 + uint32_t delay; // animation delay to next frame (ms) }; struct SXCursors { diff --git a/src/protocols/FocusGrab.cpp b/src/protocols/FocusGrab.cpp index ab9d22ef..bef69f62 100644 --- a/src/protocols/FocusGrab.cpp +++ b/src/protocols/FocusGrab.cpp @@ -11,10 +11,6 @@ CFocusGrabSurfaceState::CFocusGrabSurfaceState(CFocusGrab* grab, SPevents.destroy.registerListener([=](std::any d) { grab->eraseSurface(surface); }); } -CFocusGrabSurfaceState::~CFocusGrabSurfaceState() { - ; -} - CFocusGrab::CFocusGrab(SP resource_) : resource(resource_) { if UNLIKELY (!resource->resource()) return; diff --git a/src/protocols/FocusGrab.hpp b/src/protocols/FocusGrab.hpp index 3c907ed0..1445a24c 100644 --- a/src/protocols/FocusGrab.hpp +++ b/src/protocols/FocusGrab.hpp @@ -15,7 +15,7 @@ class CWLSurfaceResource; class CFocusGrabSurfaceState { public: CFocusGrabSurfaceState(CFocusGrab* grab, SP surface); - ~CFocusGrabSurfaceState(); + ~CFocusGrabSurfaceState() = default; enum State { PendingAddition, diff --git a/src/protocols/LinuxDMABUF.cpp b/src/protocols/LinuxDMABUF.cpp index 82d31c84..d3135da0 100644 --- a/src/protocols/LinuxDMABUF.cpp +++ b/src/protocols/LinuxDMABUF.cpp @@ -125,7 +125,7 @@ bool CLinuxDMABuffer::good() { return buffer && buffer->good(); } -CLinuxDMABBUFParamsResource::CLinuxDMABBUFParamsResource(SP resource_) : resource(resource_) { +CLinuxDMABUFParamsResource::CLinuxDMABUFParamsResource(SP resource_) : resource(resource_) { if UNLIKELY (!good()) return; @@ -197,15 +197,11 @@ CLinuxDMABBUFParamsResource::CLinuxDMABBUFParamsResource(SPresource(); } -void CLinuxDMABBUFParamsResource::create(uint32_t id) { +void CLinuxDMABUFParamsResource::create(uint32_t id) { used = true; if UNLIKELY (!verify()) { @@ -237,7 +233,7 @@ void CLinuxDMABBUFParamsResource::create(uint32_t id) { createdBuffer = buf; } -bool CLinuxDMABBUFParamsResource::commence() { +bool CLinuxDMABUFParamsResource::commence() { if (PROTO::linuxDma->mainDeviceFD < 0) return true; @@ -258,7 +254,7 @@ bool CLinuxDMABBUFParamsResource::commence() { return true; } -bool CLinuxDMABBUFParamsResource::verify() { +bool CLinuxDMABUFParamsResource::verify() { if UNLIKELY (attrs->planes <= 0) { resource->error(ZWP_LINUX_BUFFER_PARAMS_V1_ERROR_INCOMPLETE, "No planes added"); return false; @@ -311,10 +307,6 @@ CLinuxDMABUFFeedbackResource::CLinuxDMABUFFeedbackResource(SPresource(); } @@ -384,7 +376,7 @@ CLinuxDMABUFResource::CLinuxDMABUFResource(SP resource_) : re }); resource->setCreateParams([](CZwpLinuxDmabufV1* r, uint32_t id) { - const auto RESOURCE = PROTO::linuxDma->m_vParams.emplace_back(makeShared(makeShared(r->client(), r->version(), id))); + const auto RESOURCE = PROTO::linuxDma->m_vParams.emplace_back(makeShared(makeShared(r->client(), r->version(), id))); if UNLIKELY (!RESOURCE->good()) { r->noMemory(); @@ -550,7 +542,7 @@ void CLinuxDMABufV1Protocol::destroyResource(CLinuxDMABUFFeedbackResource* resou std::erase_if(m_vFeedbacks, [&](const auto& other) { return other.get() == resource; }); } -void CLinuxDMABufV1Protocol::destroyResource(CLinuxDMABBUFParamsResource* resource) { +void CLinuxDMABufV1Protocol::destroyResource(CLinuxDMABUFParamsResource* resource) { std::erase_if(m_vParams, [&](const auto& other) { return other.get() == resource; }); } diff --git a/src/protocols/LinuxDMABUF.hpp b/src/protocols/LinuxDMABUF.hpp index 8c574dbc..91cf3283 100644 --- a/src/protocols/LinuxDMABUF.hpp +++ b/src/protocols/LinuxDMABUF.hpp @@ -27,7 +27,7 @@ class CLinuxDMABuffer { CHyprSignalListener bufferResourceDestroy; } listeners; - friend class CLinuxDMABBUFParamsResource; + friend class CLinuxDMABUFParamsResource; }; #pragma pack(push, 1) @@ -56,10 +56,10 @@ class CDMABUFFormatTable { std::vector> monitorTranches; }; -class CLinuxDMABBUFParamsResource { +class CLinuxDMABUFParamsResource { public: - CLinuxDMABBUFParamsResource(SP resource_); - ~CLinuxDMABBUFParamsResource(); + CLinuxDMABUFParamsResource(SP resource_); + ~CLinuxDMABUFParamsResource() = default; bool good(); void create(uint32_t id); // 0 means not immed @@ -78,7 +78,7 @@ class CLinuxDMABBUFParamsResource { class CLinuxDMABUFFeedbackResource { public: CLinuxDMABUFFeedbackResource(SP resource_, SP surface_); - ~CLinuxDMABUFFeedbackResource(); + ~CLinuxDMABUFFeedbackResource() = default; bool good(); void sendDefaultFeedback(); @@ -115,7 +115,7 @@ class CLinuxDMABufV1Protocol : public IWaylandProtocol { private: void destroyResource(CLinuxDMABUFResource* resource); void destroyResource(CLinuxDMABUFFeedbackResource* resource); - void destroyResource(CLinuxDMABBUFParamsResource* resource); + void destroyResource(CLinuxDMABUFParamsResource* resource); void destroyResource(CLinuxDMABuffer* resource); void resetFormatTable(); @@ -123,7 +123,7 @@ class CLinuxDMABufV1Protocol : public IWaylandProtocol { // std::vector> m_vManagers; std::vector> m_vFeedbacks; - std::vector> m_vParams; + std::vector> m_vParams; std::vector> m_vBuffers; UP formatTable; @@ -132,7 +132,7 @@ class CLinuxDMABufV1Protocol : public IWaylandProtocol { friend class CLinuxDMABUFResource; friend class CLinuxDMABUFFeedbackResource; - friend class CLinuxDMABBUFParamsResource; + friend class CLinuxDMABUFParamsResource; friend class CLinuxDMABuffer; }; diff --git a/src/protocols/SinglePixel.cpp b/src/protocols/SinglePixel.cpp index 2fbfc93d..4d643a53 100644 --- a/src/protocols/SinglePixel.cpp +++ b/src/protocols/SinglePixel.cpp @@ -24,10 +24,6 @@ CSinglePixelBuffer::CSinglePixelBuffer(uint32_t id, wl_client* client, CHyprColo Debug::log(ERR, "Failed creating a single pixel texture: null texture id"); } -CSinglePixelBuffer::~CSinglePixelBuffer() { - ; -} - Aquamarine::eBufferCapability CSinglePixelBuffer::caps() { return Aquamarine::eBufferCapability::BUFFER_CAPABILITY_DATAPTR; } @@ -74,10 +70,6 @@ CSinglePixelBufferResource::CSinglePixelBufferResource(uint32_t id, wl_client* c }); } -CSinglePixelBufferResource::~CSinglePixelBufferResource() { - ; -} - bool CSinglePixelBufferResource::good() { return buffer->good(); } diff --git a/src/protocols/SinglePixel.hpp b/src/protocols/SinglePixel.hpp index 2a86d050..bd0607d6 100644 --- a/src/protocols/SinglePixel.hpp +++ b/src/protocols/SinglePixel.hpp @@ -9,7 +9,7 @@ class CSinglePixelBuffer : public IHLBuffer { public: CSinglePixelBuffer(uint32_t id, wl_client* client, CHyprColor col); - virtual ~CSinglePixelBuffer(); + virtual ~CSinglePixelBuffer() = default; virtual Aquamarine::eBufferCapability caps(); virtual Aquamarine::eBufferType type(); @@ -33,7 +33,7 @@ class CSinglePixelBuffer : public IHLBuffer { class CSinglePixelBufferResource { public: CSinglePixelBufferResource(uint32_t id, wl_client* client, CHyprColor color); - ~CSinglePixelBufferResource(); + ~CSinglePixelBufferResource() = default; bool good(); @@ -75,4 +75,4 @@ class CSinglePixelProtocol : public IWaylandProtocol { namespace PROTO { inline UP singlePixel; -}; \ No newline at end of file +}; diff --git a/src/protocols/core/Shm.cpp b/src/protocols/core/Shm.cpp index 28585aeb..1649f82f 100644 --- a/src/protocols/core/Shm.cpp +++ b/src/protocols/core/Shm.cpp @@ -36,10 +36,6 @@ CWLSHMBuffer::CWLSHMBuffer(SP pool_, uint32_t id, int32_t of Debug::log(ERR, "Failed creating a shm texture: null texture id"); } -CWLSHMBuffer::~CWLSHMBuffer() { - ; -} - Aquamarine::eBufferCapability CWLSHMBuffer::caps() { return Aquamarine::eBufferCapability::BUFFER_CAPABILITY_DATAPTR; } diff --git a/src/protocols/core/Shm.hpp b/src/protocols/core/Shm.hpp index 23a465fb..d7e81367 100644 --- a/src/protocols/core/Shm.hpp +++ b/src/protocols/core/Shm.hpp @@ -31,7 +31,7 @@ class CSHMPool { class CWLSHMBuffer : public IHLBuffer { public: CWLSHMBuffer(SP pool, uint32_t id, int32_t offset, const Vector2D& size, int32_t stride, uint32_t fmt); - virtual ~CWLSHMBuffer(); + virtual ~CWLSHMBuffer() = default; virtual Aquamarine::eBufferCapability caps(); virtual Aquamarine::eBufferType type(); diff --git a/src/render/decorations/CHyprBorderDecoration.cpp b/src/render/decorations/CHyprBorderDecoration.cpp index 6fb0ff88..5f2fdbda 100644 --- a/src/render/decorations/CHyprBorderDecoration.cpp +++ b/src/render/decorations/CHyprBorderDecoration.cpp @@ -10,10 +10,6 @@ CHyprBorderDecoration::CHyprBorderDecoration(PHLWINDOW pWindow) : IHyprWindowDec ; } -CHyprBorderDecoration::~CHyprBorderDecoration() { - ; -} - SDecorationPositioningInfo CHyprBorderDecoration::getPositioningInfo() { const auto BORDERSIZE = m_pWindow->getRealBorderSize(); m_seExtents = {{BORDERSIZE, BORDERSIZE}, {BORDERSIZE, BORDERSIZE}}; diff --git a/src/render/decorations/CHyprBorderDecoration.hpp b/src/render/decorations/CHyprBorderDecoration.hpp index bc9d7836..332c08b7 100644 --- a/src/render/decorations/CHyprBorderDecoration.hpp +++ b/src/render/decorations/CHyprBorderDecoration.hpp @@ -5,7 +5,7 @@ class CHyprBorderDecoration : public IHyprWindowDecoration { public: CHyprBorderDecoration(PHLWINDOW); - virtual ~CHyprBorderDecoration(); + virtual ~CHyprBorderDecoration() = default; virtual SDecorationPositioningInfo getPositioningInfo(); diff --git a/src/render/decorations/CHyprDropShadowDecoration.cpp b/src/render/decorations/CHyprDropShadowDecoration.cpp index 0b2a96d9..60b1b33a 100644 --- a/src/render/decorations/CHyprDropShadowDecoration.cpp +++ b/src/render/decorations/CHyprDropShadowDecoration.cpp @@ -9,8 +9,6 @@ CHyprDropShadowDecoration::CHyprDropShadowDecoration(PHLWINDOW pWindow) : IHyprW ; } -CHyprDropShadowDecoration::~CHyprDropShadowDecoration() = default; - eDecorationType CHyprDropShadowDecoration::getDecorationType() { return DECORATION_SHADOW; } diff --git a/src/render/decorations/CHyprDropShadowDecoration.hpp b/src/render/decorations/CHyprDropShadowDecoration.hpp index 3b1c67c5..b5ee7276 100644 --- a/src/render/decorations/CHyprDropShadowDecoration.hpp +++ b/src/render/decorations/CHyprDropShadowDecoration.hpp @@ -5,7 +5,7 @@ class CHyprDropShadowDecoration : public IHyprWindowDecoration { public: CHyprDropShadowDecoration(PHLWINDOW); - virtual ~CHyprDropShadowDecoration(); + virtual ~CHyprDropShadowDecoration() = default; virtual SDecorationPositioningInfo getPositioningInfo(); diff --git a/src/render/decorations/CHyprGroupBarDecoration.cpp b/src/render/decorations/CHyprGroupBarDecoration.cpp index 4e7c3cbc..88501d74 100644 --- a/src/render/decorations/CHyprGroupBarDecoration.cpp +++ b/src/render/decorations/CHyprGroupBarDecoration.cpp @@ -29,8 +29,6 @@ CHyprGroupBarDecoration::CHyprGroupBarDecoration(PHLWINDOW pWindow) : IHyprWindo refreshGroupBarGradients(); } -CHyprGroupBarDecoration::~CHyprGroupBarDecoration() = default; - SDecorationPositioningInfo CHyprGroupBarDecoration::getPositioningInfo() { static auto PHEIGHT = CConfigValue("group:groupbar:height"); static auto PENABLED = CConfigValue("group:groupbar:enabled"); @@ -231,8 +229,6 @@ CTitleTex::CTitleTex(PHLWINDOW pWindow, const Vector2D& bufferSize, const float texSize = tex->m_vSize; } -CTitleTex::~CTitleTex() = default; - void renderGradientTo(SP tex, CGradientValueData* grad) { if (!g_pCompositor->m_pLastMonitor) diff --git a/src/render/decorations/CHyprGroupBarDecoration.hpp b/src/render/decorations/CHyprGroupBarDecoration.hpp index 7277955d..0cdf8a6b 100644 --- a/src/render/decorations/CHyprGroupBarDecoration.hpp +++ b/src/render/decorations/CHyprGroupBarDecoration.hpp @@ -10,7 +10,7 @@ class CTitleTex { public: CTitleTex(PHLWINDOW pWindow, const Vector2D& bufferSize, const float monitorScale); - ~CTitleTex(); + ~CTitleTex() = default; SP tex; std::string szContent; @@ -24,7 +24,7 @@ void refreshGroupBarGradients(); class CHyprGroupBarDecoration : public IHyprWindowDecoration { public: CHyprGroupBarDecoration(PHLWINDOW); - virtual ~CHyprGroupBarDecoration(); + virtual ~CHyprGroupBarDecoration() = default; virtual SDecorationPositioningInfo getPositioningInfo(); diff --git a/src/render/decorations/IHyprWindowDecoration.cpp b/src/render/decorations/IHyprWindowDecoration.cpp index cb9e166b..c71ee186 100644 --- a/src/render/decorations/IHyprWindowDecoration.cpp +++ b/src/render/decorations/IHyprWindowDecoration.cpp @@ -6,8 +6,6 @@ IHyprWindowDecoration::IHyprWindowDecoration(PHLWINDOW pWindow) : m_pWindow(pWin ; } -IHyprWindowDecoration::~IHyprWindowDecoration() = default; - bool IHyprWindowDecoration::onInputOnDeco(const eInputType, const Vector2D&, std::any) { return false; } diff --git a/src/render/decorations/IHyprWindowDecoration.hpp b/src/render/decorations/IHyprWindowDecoration.hpp index 10145f40..2703eb61 100644 --- a/src/render/decorations/IHyprWindowDecoration.hpp +++ b/src/render/decorations/IHyprWindowDecoration.hpp @@ -33,7 +33,7 @@ class CDecorationPositioner; class IHyprWindowDecoration { public: IHyprWindowDecoration(PHLWINDOW); - virtual ~IHyprWindowDecoration() = 0; + virtual ~IHyprWindowDecoration() = default; virtual SDecorationPositioningInfo getPositioningInfo() = 0; From 32c0fa2f2fe02254d5887b38cf2cffa72ddfd769 Mon Sep 17 00:00:00 2001 From: Tom Englund Date: Thu, 30 Jan 2025 12:30:12 +0100 Subject: [PATCH 0944/2181] core: begin using CFileDescriptor from hyprutils (#9122) * config: make fd use CFileDescriptor make use of the new hyprutils CFileDescriptor instead of manual FD handling. * hyprctl: make fd use CFileDescriptor make use of the new hyprutils CFileDescriptor instead of manual FD handling. * ikeyboard: make fd use CFileDescriptor make use of the new CFileDescriptor instead of manual FD handling, also in sendKeymap remove dead code, it already early returns if keyboard isnt valid, and dont try to close the FD that ikeyboard owns. * core: make SHMFile functions use CFileDescriptor make SHMFile misc functions use CFileDescriptor and its associated usage in dmabuf and keyboard. * core: make explicit sync use CFileDescriptor begin using CFileDescriptor in explicit sync and its timelines and eglsync usage in opengl, there is still a bit left with manual handling that requires future aquamarine change aswell. * eventmgr: make fd and sockets use CFileDescriptor make use of the hyprutils CFileDescriptor instead of manual FD and socket handling and closing. * eventloopmgr: make timerfd use CFileDescriptor make the timerfd use CFileDescriptor instead of manual fd handling * opengl: make gbm fd use CFileDescriptor make the gbm rendernode fd use CFileDescriptor instead of manual fd handling * core: make selection source/offer use CFileDescriptor make data selection source and offers use CFileDescriptor and its associated use in xwm and protocols * protocols: convert protocols fd to CFileDescriptor make most fd handling use CFileDescriptor in protocols * shm: make SHMPool use CfileDescriptor make SHMPool use CFileDescriptor instead of manual fd handling. * opengl: duplicate fd with CFileDescriptor duplicate fenceFD with CFileDescriptor duplicate instead. * xwayland: make sockets and fds use CFileDescriptor instead of manual opening/closing make sockets and fds use CFileDescriptor * keybindmgr: make sockets and fds use CFileDescriptor make sockets and fds use CFileDescriptor instead of manual handling. --- src/config/ConfigWatcher.cpp | 25 ++- src/config/ConfigWatcher.hpp | 15 +- src/debug/HyprCtl.cpp | 18 +- src/debug/HyprCtl.hpp | 11 +- src/devices/IKeyboard.cpp | 26 ++- src/devices/IKeyboard.hpp | 3 +- src/helpers/MiscFunctions.cpp | 44 +++-- src/helpers/MiscFunctions.hpp | 5 +- src/helpers/Monitor.cpp | 17 +- src/helpers/Monitor.hpp | 1 + src/helpers/sync/SyncTimeline.cpp | 26 ++- src/helpers/sync/SyncTimeline.hpp | 28 ++-- src/managers/EventManager.cpp | 44 +++-- src/managers/EventManager.hpp | 14 +- src/managers/KeybindManager.cpp | 29 ++-- src/managers/eventLoop/EventLoopManager.cpp | 13 +- src/managers/eventLoop/EventLoopManager.hpp | 3 +- src/protocols/DRMLease.cpp | 17 +- src/protocols/DRMLease.hpp | 1 + src/protocols/DRMSyncobj.cpp | 12 +- src/protocols/DRMSyncobj.hpp | 7 +- src/protocols/DataDeviceWlr.cpp | 12 +- src/protocols/DataDeviceWlr.hpp | 3 +- src/protocols/GammaControl.cpp | 15 +- src/protocols/InputMethodV2.cpp | 11 +- src/protocols/LinuxDMABUF.cpp | 37 ++--- src/protocols/LinuxDMABUF.hpp | 9 +- src/protocols/PrimarySelection.cpp | 12 +- src/protocols/PrimarySelection.hpp | 3 +- src/protocols/SecurityContext.cpp | 21 ++- src/protocols/SecurityContext.hpp | 19 ++- src/protocols/VirtualKeyboard.cpp | 10 +- src/protocols/VirtualKeyboard.hpp | 1 + src/protocols/core/DataDevice.cpp | 12 +- src/protocols/core/DataDevice.hpp | 3 +- src/protocols/core/Seat.cpp | 29 +--- src/protocols/core/Shm.cpp | 23 +-- src/protocols/core/Shm.hpp | 14 +- src/protocols/types/DataDevice.hpp | 9 +- src/render/OpenGL.cpp | 41 ++--- src/render/OpenGL.hpp | 13 +- src/render/Renderer.cpp | 20 +-- src/xwayland/Dnd.cpp | 4 +- src/xwayland/Dnd.hpp | 3 +- src/xwayland/Server.cpp | 173 +++++++------------- src/xwayland/Server.hpp | 27 +-- src/xwayland/XDataSource.cpp | 13 +- src/xwayland/XDataSource.hpp | 5 +- src/xwayland/XWM.cpp | 20 +-- src/xwayland/XWM.hpp | 27 +-- 50 files changed, 422 insertions(+), 526 deletions(-) diff --git a/src/config/ConfigWatcher.cpp b/src/config/ConfigWatcher.cpp index c0a9c591..8d086bac 100644 --- a/src/config/ConfigWatcher.cpp +++ b/src/config/ConfigWatcher.cpp @@ -5,27 +5,24 @@ #include #include +using namespace Hyprutils::OS; + CConfigWatcher::CConfigWatcher() : m_inotifyFd(inotify_init()) { - if (m_inotifyFd < 0) { + if (!m_inotifyFd.isValid()) { Debug::log(ERR, "CConfigWatcher couldn't open an inotify node. Config will not be automatically reloaded"); return; } - const int FLAGS = fcntl(m_inotifyFd, F_GETFL, 0); - if (fcntl(m_inotifyFd, F_SETFL, FLAGS | O_NONBLOCK) < 0) { + // TODO: make CFileDescriptor take F_GETFL, F_SETFL + const int FLAGS = fcntl(m_inotifyFd.get(), F_GETFL, 0); + if (fcntl(m_inotifyFd.get(), F_SETFL, FLAGS | O_NONBLOCK) < 0) { Debug::log(ERR, "CConfigWatcher couldn't non-block inotify node. Config will not be automatically reloaded"); - close(m_inotifyFd); - m_inotifyFd = -1; + m_inotifyFd.reset(); return; } } -CConfigWatcher::~CConfigWatcher() { - if (m_inotifyFd >= 0) - close(m_inotifyFd); -} - -int CConfigWatcher::getInotifyFD() { +CFileDescriptor& CConfigWatcher::getInotifyFD() { return m_inotifyFd; } @@ -38,7 +35,7 @@ void CConfigWatcher::setWatchList(const std::vector& paths) { // cleanup old paths for (auto& watch : m_watches) { - inotify_rm_watch(m_inotifyFd, watch.wd); + inotify_rm_watch(m_inotifyFd.get(), watch.wd); } m_watches.clear(); @@ -46,7 +43,7 @@ void CConfigWatcher::setWatchList(const std::vector& paths) { // add new paths for (const auto& path : paths) { m_watches.emplace_back(SInotifyWatch{ - .wd = inotify_add_watch(m_inotifyFd, path.c_str(), IN_MODIFY), + .wd = inotify_add_watch(m_inotifyFd.get(), path.c_str(), IN_MODIFY), .file = path, }); } @@ -58,7 +55,7 @@ void CConfigWatcher::setOnChange(const std::function 0) { + while (read(m_inotifyFd.get(), &ev, sizeof(ev)) > 0) { const auto WD = std::ranges::find_if(m_watches.begin(), m_watches.end(), [wd = ev.wd](const auto& e) { return e.wd == wd; }); if (WD == m_watches.end()) { diff --git a/src/config/ConfigWatcher.hpp b/src/config/ConfigWatcher.hpp index c36ecd17..97945689 100644 --- a/src/config/ConfigWatcher.hpp +++ b/src/config/ConfigWatcher.hpp @@ -3,20 +3,21 @@ #include #include #include +#include class CConfigWatcher { public: CConfigWatcher(); - ~CConfigWatcher(); + ~CConfigWatcher() = default; struct SConfigWatchEvent { std::string file; }; - int getInotifyFD(); - void setWatchList(const std::vector& paths); - void setOnChange(const std::function& fn); - void onInotifyEvent(); + Hyprutils::OS::CFileDescriptor& getInotifyFD(); + void setWatchList(const std::vector& paths); + void setOnChange(const std::function& fn); + void onInotifyEvent(); private: struct SInotifyWatch { @@ -26,7 +27,7 @@ class CConfigWatcher { std::function m_watchCallback; std::vector m_watches; - int m_inotifyFd = -1; + Hyprutils::OS::CFileDescriptor m_inotifyFd; }; -inline UP g_pConfigWatcher = makeUnique(); \ No newline at end of file +inline UP g_pConfigWatcher = makeUnique(); diff --git a/src/debug/HyprCtl.cpp b/src/debug/HyprCtl.cpp index 359428b1..cd6451e2 100644 --- a/src/debug/HyprCtl.cpp +++ b/src/debug/HyprCtl.cpp @@ -25,6 +25,7 @@ #include using namespace Hyprutils::String; +using namespace Hyprutils::OS; #include #include "../config/ConfigDataValues.hpp" @@ -1680,8 +1681,6 @@ CHyprCtl::CHyprCtl() { CHyprCtl::~CHyprCtl() { if (m_eventSource) wl_event_source_remove(m_eventSource); - if (m_iSocketFD >= 0) - close(m_iSocketFD); if (!m_socketPath.empty()) unlink(m_socketPath.c_str()); } @@ -1840,10 +1839,13 @@ static int hyprCtlFDTick(int fd, uint32_t mask, void* data) { if (mask & WL_EVENT_ERROR || mask & WL_EVENT_HANGUP) return 0; + if (!g_pHyprCtl->m_iSocketFD.isValid()) + return 0; + sockaddr_in clientAddress; socklen_t clientSize = sizeof(clientAddress); - const auto ACCEPTEDCONNECTION = accept4(g_pHyprCtl->m_iSocketFD, (sockaddr*)&clientAddress, &clientSize, SOCK_CLOEXEC); + const auto ACCEPTEDCONNECTION = accept4(g_pHyprCtl->m_iSocketFD.get(), (sockaddr*)&clientAddress, &clientSize, SOCK_CLOEXEC); std::array readBuffer; @@ -1900,9 +1902,9 @@ static int hyprCtlFDTick(int fd, uint32_t mask, void* data) { } void CHyprCtl::startHyprCtlSocket() { - m_iSocketFD = socket(AF_UNIX, SOCK_STREAM | SOCK_CLOEXEC, 0); + m_iSocketFD = CFileDescriptor{socket(AF_UNIX, SOCK_STREAM | SOCK_CLOEXEC, 0)}; - if (m_iSocketFD < 0) { + if (!m_iSocketFD.isValid()) { Debug::log(ERR, "Couldn't start the Hyprland Socket. (1) IPC will not work."); return; } @@ -1913,15 +1915,15 @@ void CHyprCtl::startHyprCtlSocket() { strcpy(SERVERADDRESS.sun_path, m_socketPath.c_str()); - if (bind(m_iSocketFD, (sockaddr*)&SERVERADDRESS, SUN_LEN(&SERVERADDRESS)) < 0) { + if (bind(m_iSocketFD.get(), (sockaddr*)&SERVERADDRESS, SUN_LEN(&SERVERADDRESS)) < 0) { Debug::log(ERR, "Couldn't start the Hyprland Socket. (2) IPC will not work."); return; } // 10 max queued. - listen(m_iSocketFD, 10); + listen(m_iSocketFD.get(), 10); Debug::log(LOG, "Hypr socket started at {}", m_socketPath); - m_eventSource = wl_event_loop_add_fd(g_pCompositor->m_sWLEventLoop, m_iSocketFD, WL_EVENT_READABLE, hyprCtlFDTick, nullptr); + m_eventSource = wl_event_loop_add_fd(g_pCompositor->m_sWLEventLoop, m_iSocketFD.get(), WL_EVENT_READABLE, hyprCtlFDTick, nullptr); } diff --git a/src/debug/HyprCtl.hpp b/src/debug/HyprCtl.hpp index eed8265c..a95a5f93 100644 --- a/src/debug/HyprCtl.hpp +++ b/src/debug/HyprCtl.hpp @@ -4,6 +4,7 @@ #include "../helpers/MiscFunctions.hpp" #include "../desktop/Window.hpp" #include +#include // exposed for main.cpp std::string systemInfoRequest(eHyprCtlOutputFormat format, std::string request); @@ -14,12 +15,12 @@ class CHyprCtl { CHyprCtl(); ~CHyprCtl(); - std::string makeDynamicCall(const std::string& input); - SP registerCommand(SHyprCtlCommand cmd); - void unregisterCommand(const SP& cmd); - std::string getReply(std::string); + std::string makeDynamicCall(const std::string& input); + SP registerCommand(SHyprCtlCommand cmd); + void unregisterCommand(const SP& cmd); + std::string getReply(std::string); - int m_iSocketFD = -1; + Hyprutils::OS::CFileDescriptor m_iSocketFD; struct { bool all = false; diff --git a/src/devices/IKeyboard.cpp b/src/devices/IKeyboard.cpp index 4623fe84..307d840b 100644 --- a/src/devices/IKeyboard.cpp +++ b/src/devices/IKeyboard.cpp @@ -8,6 +8,8 @@ #include #include +using namespace Hyprutils::OS; + #define LED_COUNT 3 constexpr static std::array MODNAMES = { @@ -41,9 +43,6 @@ void IKeyboard::clearManuallyAllocd() { if (xkbKeymap) xkb_keymap_unref(xkbKeymap); - if (xkbKeymapFD >= 0) - close(xkbKeymapFD); - if (xkbSymState) xkb_state_unref(xkbSymState); @@ -51,7 +50,7 @@ void IKeyboard::clearManuallyAllocd() { xkbKeymap = nullptr; xkbState = nullptr; xkbStaticState = nullptr; - xkbKeymapFD = -1; + xkbKeymapFD.reset(); } void IKeyboard::setKeymap(const SStringRuleNames& rules) { @@ -147,31 +146,30 @@ void IKeyboard::setKeymap(const SStringRuleNames& rules) { void IKeyboard::updateKeymapFD() { Debug::log(LOG, "Updating keymap fd for keyboard {}", deviceName); - if (xkbKeymapFD >= 0) - close(xkbKeymapFD); - xkbKeymapFD = -1; + if (xkbKeymapFD.isValid()) + xkbKeymapFD.reset(); auto cKeymapStr = xkb_keymap_get_as_string(xkbKeymap, XKB_KEYMAP_FORMAT_TEXT_V1); xkbKeymapString = cKeymapStr; free(cKeymapStr); - int rw, ro; - if (!allocateSHMFilePair(xkbKeymapString.length() + 1, &rw, &ro)) + CFileDescriptor rw, ro; + if (!allocateSHMFilePair(xkbKeymapString.length() + 1, rw, ro)) Debug::log(ERR, "IKeyboard: failed to allocate shm pair for the keymap"); else { - auto keymapFDDest = mmap(nullptr, xkbKeymapString.length() + 1, PROT_READ | PROT_WRITE, MAP_SHARED, rw, 0); - close(rw); + auto keymapFDDest = mmap(nullptr, xkbKeymapString.length() + 1, PROT_READ | PROT_WRITE, MAP_SHARED, rw.get(), 0); + rw.reset(); if (keymapFDDest == MAP_FAILED) { Debug::log(ERR, "IKeyboard: failed to mmap a shm pair for the keymap"); - close(ro); + ro.reset(); } else { memcpy(keymapFDDest, xkbKeymapString.c_str(), xkbKeymapString.length()); munmap(keymapFDDest, xkbKeymapString.length() + 1); - xkbKeymapFD = ro; + xkbKeymapFD = std::move(ro); } } - Debug::log(LOG, "Updated keymap fd to {}", xkbKeymapFD); + Debug::log(LOG, "Updated keymap fd to {}", xkbKeymapFD.get()); } void IKeyboard::updateXKBTranslationState(xkb_keymap* const keymap) { diff --git a/src/devices/IKeyboard.hpp b/src/devices/IKeyboard.hpp index dce2127a..aabf4cc2 100644 --- a/src/devices/IKeyboard.hpp +++ b/src/devices/IKeyboard.hpp @@ -6,6 +6,7 @@ #include #include +#include AQUAMARINE_FORWARD(IKeyboard); @@ -96,7 +97,7 @@ class IKeyboard : public IHID { std::string xkbFilePath = ""; std::string xkbKeymapString = ""; - int xkbKeymapFD = -1; + Hyprutils::OS::CFileDescriptor xkbKeymapFD; SStringRuleNames currentRules; int repeatRate = 0; diff --git a/src/helpers/MiscFunctions.cpp b/src/helpers/MiscFunctions.cpp index 5ebb0842..f532617c 100644 --- a/src/helpers/MiscFunctions.cpp +++ b/src/helpers/MiscFunctions.cpp @@ -836,50 +836,48 @@ bool envEnabled(const std::string& env) { return std::string(ENV) == "1"; } -std::pair openExclusiveShm() { +std::pair openExclusiveShm() { // Only absolute paths can be shared across different shm_open() calls std::string name = "/" + g_pTokenManager->getRandomUUID(); for (size_t i = 0; i < 69; ++i) { - int fd = shm_open(name.c_str(), O_RDWR | O_CREAT | O_EXCL, 0600); - if (fd >= 0) - return {fd, name}; + CFileDescriptor fd{shm_open(name.c_str(), O_RDWR | O_CREAT | O_EXCL, 0600)}; + if (fd.isValid()) + return {std::move(fd), name}; } - return {-1, ""}; + return {{}, ""}; } -int allocateSHMFile(size_t len) { +CFileDescriptor allocateSHMFile(size_t len) { auto [fd, name] = openExclusiveShm(); - if (fd < 0) - return -1; + if (!fd.isValid()) + return {}; shm_unlink(name.c_str()); int ret; do { - ret = ftruncate(fd, len); + ret = ftruncate(fd.get(), len); } while (ret < 0 && errno == EINTR); if (ret < 0) { - close(fd); - return -1; + return {}; } - return fd; + return std::move(fd); } -bool allocateSHMFilePair(size_t size, int* rw_fd_ptr, int* ro_fd_ptr) { +bool allocateSHMFilePair(size_t size, CFileDescriptor& rw_fd_ptr, CFileDescriptor& ro_fd_ptr) { auto [fd, name] = openExclusiveShm(); - if (fd < 0) { + if (!fd.isValid()) { return false; } // CLOEXEC is guaranteed to be set by shm_open - int ro_fd = shm_open(name.c_str(), O_RDONLY, 0); - if (ro_fd < 0) { + CFileDescriptor ro_fd{shm_open(name.c_str(), O_RDONLY, 0)}; + if (!ro_fd.isValid()) { shm_unlink(name.c_str()); - close(fd); return false; } @@ -887,24 +885,20 @@ bool allocateSHMFilePair(size_t size, int* rw_fd_ptr, int* ro_fd_ptr) { // Make sure the file cannot be re-opened in read-write mode (e.g. via // "/proc/self/fd/" on Linux) - if (fchmod(fd, 0) != 0) { - close(fd); - close(ro_fd); + if (fchmod(fd.get(), 0) != 0) { return false; } int ret; do { - ret = ftruncate(fd, size); + ret = ftruncate(fd.get(), size); } while (ret < 0 && errno == EINTR); if (ret < 0) { - close(fd); - close(ro_fd); return false; } - *rw_fd_ptr = fd; - *ro_fd_ptr = ro_fd; + rw_fd_ptr = std::move(fd); + ro_fd_ptr = std::move(ro_fd); return true; } diff --git a/src/helpers/MiscFunctions.hpp b/src/helpers/MiscFunctions.hpp index d0824284..bd288638 100644 --- a/src/helpers/MiscFunctions.hpp +++ b/src/helpers/MiscFunctions.hpp @@ -5,6 +5,7 @@ #include #include #include +#include #include "../SharedDefs.hpp" #include "../macros.hpp" @@ -35,8 +36,8 @@ double normalizeAngleRad(double ang); std::vector getBacktrace(); void throwError(const std::string& err); bool envEnabled(const std::string& env); -int allocateSHMFile(size_t len); -bool allocateSHMFilePair(size_t size, int* rw_fd_ptr, int* ro_fd_ptr); +Hyprutils::OS::CFileDescriptor allocateSHMFile(size_t len); +bool allocateSHMFilePair(size_t size, Hyprutils::OS::CFileDescriptor& rw_fd_ptr, Hyprutils::OS::CFileDescriptor& ro_fd_ptr); float stringToPercentage(const std::string& VALUE, const float REL); template diff --git a/src/helpers/Monitor.cpp b/src/helpers/Monitor.cpp index 42acf485..fc3de3aa 100644 --- a/src/helpers/Monitor.cpp +++ b/src/helpers/Monitor.cpp @@ -32,6 +32,7 @@ #include using namespace Hyprutils::String; using namespace Hyprutils::Utils; +using namespace Hyprutils::OS; static int ratHandler(void* data) { g_pHyprRenderer->renderMonitor(((CMonitor*)data)->self.lock()); @@ -1301,19 +1302,15 @@ bool CMonitor::attemptDirectScanout() { // wait for the explicit fence if present, and if kms explicit is allowed bool DOEXPLICIT = PSURFACE->syncobj && PSURFACE->syncobj->current.acquireTimeline && PSURFACE->syncobj->current.acquireTimeline->timeline && explicitOptions.explicitKMSEnabled; - int explicitWaitFD = -1; + CFileDescriptor explicitWaitFD; if (DOEXPLICIT) { explicitWaitFD = PSURFACE->syncobj->current.acquireTimeline->timeline->exportAsSyncFileFD(PSURFACE->syncobj->current.acquirePoint); - if (explicitWaitFD < 0) + if (!explicitWaitFD.isValid()) Debug::log(TRACE, "attemptDirectScanout: failed to acquire an explicit wait fd"); } - DOEXPLICIT = DOEXPLICIT && explicitWaitFD >= 0; + DOEXPLICIT = DOEXPLICIT && explicitWaitFD.isValid(); - auto cleanup = CScopeGuard([explicitWaitFD, this]() { - output->state->resetExplicitFences(); - if (explicitWaitFD >= 0) - close(explicitWaitFD); - }); + auto cleanup = CScopeGuard([this]() { output->state->resetExplicitFences(); }); timespec now; clock_gettime(CLOCK_MONOTONIC, &now); @@ -1323,8 +1320,8 @@ bool CMonitor::attemptDirectScanout() { output->state->resetExplicitFences(); if (DOEXPLICIT) { - Debug::log(TRACE, "attemptDirectScanout: setting IN_FENCE for aq to {}", explicitWaitFD); - output->state->setExplicitInFence(explicitWaitFD); + Debug::log(TRACE, "attemptDirectScanout: setting IN_FENCE for aq to {}", explicitWaitFD.get()); + output->state->setExplicitInFence(explicitWaitFD.get()); } bool ok = output->commit(); diff --git a/src/helpers/Monitor.hpp b/src/helpers/Monitor.hpp index 2b02c30a..c67bccc5 100644 --- a/src/helpers/Monitor.hpp +++ b/src/helpers/Monitor.hpp @@ -16,6 +16,7 @@ #include "DamageRing.hpp" #include #include +#include // Enum for the different types of auto directions, e.g. auto-left, auto-up. enum eAutoDirs : uint8_t { diff --git a/src/helpers/sync/SyncTimeline.cpp b/src/helpers/sync/SyncTimeline.cpp index 16b5bd92..46b617bc 100644 --- a/src/helpers/sync/SyncTimeline.cpp +++ b/src/helpers/sync/SyncTimeline.cpp @@ -4,6 +4,7 @@ #include #include +using namespace Hyprutils::OS; SP CSyncTimeline::create(int drmFD_) { auto timeline = SP(new CSyncTimeline); @@ -85,10 +86,9 @@ bool CSyncTimeline::addWaiter(const std::function& waiter, uint64_t poin auto w = makeShared(); w->fn = waiter; w->timeline = self; + w->eventFd = CFileDescriptor{eventfd(0, EFD_CLOEXEC)}; - int eventFD = eventfd(0, EFD_CLOEXEC); - - if (eventFD < 0) { + if (!w->eventFd.isValid()) { Debug::log(ERR, "CSyncTimeline::addWaiter: failed to acquire an eventfd"); return false; } @@ -97,19 +97,17 @@ bool CSyncTimeline::addWaiter(const std::function& waiter, uint64_t poin .handle = handle, .flags = flags, .point = point, - .fd = eventFD, + .fd = w->eventFd.get(), }; if (drmIoctl(drmFD, DRM_IOCTL_SYNCOBJ_EVENTFD, &syncobjEventFD) != 0) { Debug::log(ERR, "CSyncTimeline::addWaiter: drmIoctl failed"); - close(eventFD); return false; } - w->source = wl_event_loop_add_fd(g_pEventLoopManager->m_sWayland.loop, eventFD, WL_EVENT_READABLE, ::handleWaiterFD, w.get()); + w->source = wl_event_loop_add_fd(g_pEventLoopManager->m_sWayland.loop, w->eventFd.get(), WL_EVENT_READABLE, ::handleWaiterFD, w.get()); if (!w->source) { Debug::log(ERR, "CSyncTimeline::addWaiter: wl_event_loop_add_fd failed"); - close(eventFD); return false; } @@ -126,32 +124,32 @@ void CSyncTimeline::removeWaiter(SWaiter* w) { std::erase_if(waiters, [w](const auto& e) { return e.get() == w; }); } -int CSyncTimeline::exportAsSyncFileFD(uint64_t src) { +CFileDescriptor CSyncTimeline::exportAsSyncFileFD(uint64_t src) { int sync = -1; uint32_t syncHandle = 0; if (drmSyncobjCreate(drmFD, 0, &syncHandle)) { Debug::log(ERR, "exportAsSyncFileFD: drmSyncobjCreate failed"); - return -1; + return {}; } if (drmSyncobjTransfer(drmFD, syncHandle, 0, handle, src, 0)) { Debug::log(ERR, "exportAsSyncFileFD: drmSyncobjTransfer failed"); drmSyncobjDestroy(drmFD, syncHandle); - return -1; + return {}; } if (drmSyncobjExportSyncFile(drmFD, syncHandle, &sync)) { Debug::log(ERR, "exportAsSyncFileFD: drmSyncobjExportSyncFile failed"); drmSyncobjDestroy(drmFD, syncHandle); - return -1; + return {}; } drmSyncobjDestroy(drmFD, syncHandle); - return sync; + return CFileDescriptor{sync}; } -bool CSyncTimeline::importFromSyncFileFD(uint64_t dst, int fd) { +bool CSyncTimeline::importFromSyncFileFD(uint64_t dst, CFileDescriptor& fd) { uint32_t syncHandle = 0; if (drmSyncobjCreate(drmFD, 0, &syncHandle)) { @@ -159,7 +157,7 @@ bool CSyncTimeline::importFromSyncFileFD(uint64_t dst, int fd) { return false; } - if (drmSyncobjImportSyncFile(drmFD, syncHandle, fd)) { + if (drmSyncobjImportSyncFile(drmFD, syncHandle, fd.get())) { Debug::log(ERR, "importFromSyncFileFD: drmSyncobjImportSyncFile failed"); drmSyncobjDestroy(drmFD, syncHandle); return false; diff --git a/src/helpers/sync/SyncTimeline.hpp b/src/helpers/sync/SyncTimeline.hpp index 88ad4921..ba65e004 100644 --- a/src/helpers/sync/SyncTimeline.hpp +++ b/src/helpers/sync/SyncTimeline.hpp @@ -4,6 +4,7 @@ #include #include #include +#include #include "../memory/Memory.hpp" /* @@ -20,26 +21,27 @@ class CSyncTimeline { ~CSyncTimeline(); struct SWaiter { - std::function fn; - wl_event_source* source = nullptr; - WP timeline; + std::function fn; + wl_event_source* source = nullptr; + WP timeline; + Hyprutils::OS::CFileDescriptor eventFd; }; // check if the timeline point has been signaled // flags: DRM_SYNCOBJ_WAIT_FLAGS_WAIT_FOR_SUBMIT or DRM_SYNCOBJ_WAIT_FLAGS_WAIT_AVAILABLE // std::nullopt on fail - std::optional check(uint64_t point, uint32_t flags); + std::optional check(uint64_t point, uint32_t flags); - bool addWaiter(const std::function& waiter, uint64_t point, uint32_t flags); - void removeWaiter(SWaiter*); - int exportAsSyncFileFD(uint64_t src); - bool importFromSyncFileFD(uint64_t dst, int fd); - bool transfer(SP from, uint64_t fromPoint, uint64_t toPoint); - void signal(uint64_t point); + bool addWaiter(const std::function& waiter, uint64_t point, uint32_t flags); + void removeWaiter(SWaiter*); + Hyprutils::OS::CFileDescriptor exportAsSyncFileFD(uint64_t src); + bool importFromSyncFileFD(uint64_t dst, Hyprutils::OS::CFileDescriptor& fd); + bool transfer(SP from, uint64_t fromPoint, uint64_t toPoint); + void signal(uint64_t point); - int drmFD = -1; - uint32_t handle = 0; - WP self; + int drmFD = -1; + uint32_t handle = 0; + WP self; private: CSyncTimeline() = default; diff --git a/src/managers/EventManager.cpp b/src/managers/EventManager.cpp index fc55b472..6231f0bc 100644 --- a/src/managers/EventManager.cpp +++ b/src/managers/EventManager.cpp @@ -9,9 +9,10 @@ #include #include #include +using namespace Hyprutils::OS; CEventManager::CEventManager() : m_iSocketFD(socket(AF_UNIX, SOCK_STREAM | SOCK_CLOEXEC | SOCK_NONBLOCK, 0)) { - if (m_iSocketFD < 0) { + if (!m_iSocketFD.isValid()) { Debug::log(ERR, "Couldn't start the Hyprland Socket 2. (1) IPC will not work."); return; } @@ -25,31 +26,27 @@ CEventManager::CEventManager() : m_iSocketFD(socket(AF_UNIX, SOCK_STREAM | SOCK_ strncpy(SERVERADDRESS.sun_path, PATH.c_str(), sizeof(SERVERADDRESS.sun_path) - 1); - if (bind(m_iSocketFD, (sockaddr*)&SERVERADDRESS, SUN_LEN(&SERVERADDRESS)) < 0) { + if (bind(m_iSocketFD.get(), (sockaddr*)&SERVERADDRESS, SUN_LEN(&SERVERADDRESS)) < 0) { Debug::log(ERR, "Couldn't bind the Hyprland Socket 2. (3) IPC will not work."); return; } // 10 max queued. - if (listen(m_iSocketFD, 10) < 0) { + if (listen(m_iSocketFD.get(), 10) < 0) { Debug::log(ERR, "Couldn't listen on the Hyprland Socket 2. (4) IPC will not work."); return; } - m_pEventSource = wl_event_loop_add_fd(g_pCompositor->m_sWLEventLoop, m_iSocketFD, WL_EVENT_READABLE, onClientEvent, nullptr); + m_pEventSource = wl_event_loop_add_fd(g_pCompositor->m_sWLEventLoop, m_iSocketFD.get(), WL_EVENT_READABLE, onClientEvent, nullptr); } CEventManager::~CEventManager() { for (const auto& client : m_vClients) { wl_event_source_remove(client.eventSource); - close(client.fd); } if (m_pEventSource != nullptr) wl_event_source_remove(m_pEventSource); - - if (m_iSocketFD >= 0) - close(m_iSocketFD); } int CEventManager::onServerEvent(int fd, uint32_t mask, void* data) { @@ -66,33 +63,31 @@ int CEventManager::onServerEvent(int fd, uint32_t mask) { wl_event_source_remove(m_pEventSource); m_pEventSource = nullptr; - close(fd); - m_iSocketFD = -1; + m_iSocketFD.reset(); return 0; } - sockaddr_in clientAddress; - socklen_t clientSize = sizeof(clientAddress); - const auto ACCEPTEDCONNECTION = accept4(m_iSocketFD, (sockaddr*)&clientAddress, &clientSize, SOCK_CLOEXEC | SOCK_NONBLOCK); - if (ACCEPTEDCONNECTION < 0) { + sockaddr_in clientAddress; + socklen_t clientSize = sizeof(clientAddress); + CFileDescriptor ACCEPTEDCONNECTION{accept4(m_iSocketFD.get(), (sockaddr*)&clientAddress, &clientSize, SOCK_CLOEXEC | SOCK_NONBLOCK)}; + if (!ACCEPTEDCONNECTION.isValid()) { if (errno != EAGAIN) { Debug::log(ERR, "Socket2 failed receiving connection, errno: {}", errno); wl_event_source_remove(m_pEventSource); m_pEventSource = nullptr; - close(fd); - m_iSocketFD = -1; + m_iSocketFD.reset(); } return 0; } - Debug::log(LOG, "Socket2 accepted a new client at FD {}", ACCEPTEDCONNECTION); + Debug::log(LOG, "Socket2 accepted a new client at FD {}", ACCEPTEDCONNECTION.get()); // add to event loop so we can close it when we need to - auto* eventSource = wl_event_loop_add_fd(g_pCompositor->m_sWLEventLoop, ACCEPTEDCONNECTION, 0, onServerEvent, nullptr); + auto* eventSource = wl_event_loop_add_fd(g_pCompositor->m_sWLEventLoop, ACCEPTEDCONNECTION.get(), 0, onServerEvent, nullptr); m_vClients.emplace_back(SClient{ - ACCEPTEDCONNECTION, + std::move(ACCEPTEDCONNECTION), {}, eventSource, }); @@ -113,7 +108,7 @@ int CEventManager::onClientEvent(int fd, uint32_t mask) { // send all queued events while (!CLIENTIT->events.empty()) { const auto& event = CLIENTIT->events.front(); - if (write(CLIENTIT->fd, event->c_str(), event->length()) < 0) + if (write(CLIENTIT->fd.get(), event->c_str(), event->length()) < 0) break; CLIENTIT->events.erase(CLIENTIT->events.begin()); @@ -128,13 +123,12 @@ int CEventManager::onClientEvent(int fd, uint32_t mask) { } std::vector::iterator CEventManager::findClientByFD(int fd) { - return std::find_if(m_vClients.begin(), m_vClients.end(), [fd](const auto& client) { return client.fd == fd; }); + return std::find_if(m_vClients.begin(), m_vClients.end(), [fd](const auto& client) { return client.fd.get() == fd; }); } std::vector::iterator CEventManager::removeClientByFD(int fd) { const auto CLIENTIT = findClientByFD(fd); wl_event_source_remove(CLIENTIT->eventSource); - close(fd); return m_vClients.erase(CLIENTIT); } @@ -157,11 +151,11 @@ void CEventManager::postEvent(const SHyprIPCEvent& event) { for (auto it = m_vClients.begin(); it != m_vClients.end();) { // try to send the event immediately if the queue is empty const auto QUEUESIZE = it->events.size(); - if (QUEUESIZE > 0 || write(it->fd, sharedEvent->c_str(), sharedEvent->length()) < 0) { + if (QUEUESIZE > 0 || write(it->fd.get(), sharedEvent->c_str(), sharedEvent->length()) < 0) { if (QUEUESIZE >= MAX_QUEUED_EVENTS) { // too many events queued, remove the client - Debug::log(ERR, "Socket2 fd {} overflowed event queue, removing", it->fd); - it = removeClientByFD(it->fd); + Debug::log(ERR, "Socket2 fd {} overflowed event queue, removing", it->fd.get()); + it = removeClientByFD(it->fd.get()); continue; } diff --git a/src/managers/EventManager.hpp b/src/managers/EventManager.hpp index 6b506d33..c8335d20 100644 --- a/src/managers/EventManager.hpp +++ b/src/managers/EventManager.hpp @@ -1,6 +1,6 @@ #pragma once #include - +#include #include "../defines.hpp" #include "../helpers/memory/Memory.hpp" @@ -26,19 +26,19 @@ class CEventManager { int onClientEvent(int fd, uint32_t mask); struct SClient { - int fd = -1; - std::vector> events; - wl_event_source* eventSource = nullptr; + Hyprutils::OS::CFileDescriptor fd; + std::vector> events; + wl_event_source* eventSource = nullptr; }; std::vector::iterator findClientByFD(int fd); std::vector::iterator removeClientByFD(int fd); private: - int m_iSocketFD = -1; - wl_event_source* m_pEventSource = nullptr; + Hyprutils::OS::CFileDescriptor m_iSocketFD; + wl_event_source* m_pEventSource = nullptr; - std::vector m_vClients; + std::vector m_vClients; }; inline UP g_pEventManager; diff --git a/src/managers/KeybindManager.cpp b/src/managers/KeybindManager.cpp index 2cb77d21..247550ae 100644 --- a/src/managers/KeybindManager.cpp +++ b/src/managers/KeybindManager.cpp @@ -28,7 +28,9 @@ #include #include +#include using namespace Hyprutils::String; +using namespace Hyprutils::OS; #include #include @@ -853,19 +855,18 @@ bool CKeybindManager::handleVT(xkb_keysym_t keysym) { const unsigned int TTY = keysym - XKB_KEY_XF86Switch_VT_1 + 1; // vtnr is bugged for some reason. - unsigned int ttynum = 0; - int fd; - if ((fd = open("/dev/tty", O_RDONLY | O_NOCTTY)) >= 0) { + unsigned int ttynum = 0; + Hyprutils::OS::CFileDescriptor fd{open("/dev/tty", O_RDONLY | O_NOCTTY)}; + if (fd.isValid()) { #if defined(VT_GETSTATE) struct vt_stat st; - if (!ioctl(fd, VT_GETSTATE, &st)) + if (!ioctl(fd.get(), VT_GETSTATE, &st)) ttynum = st.v_active; #elif defined(VT_GETACTIVE) int vt; - if (!ioctl(fd, VT_GETACTIVE, &vt)) + if (!ioctl(fd.get(), VT_GETACTIVE, &vt)) ttynum = vt; #endif - close(fd); } if (ttynum == TTY) @@ -944,11 +945,11 @@ uint64_t CKeybindManager::spawnRawProc(std::string args, PHLWORKSPACE pInitialWo Debug::log(LOG, "Unable to create pipe for fork"); } - pid_t child, grandchild; + CFileDescriptor pipeSock[2] = {CFileDescriptor{socket[0]}, CFileDescriptor{socket[1]}}; + + pid_t child, grandchild; child = fork(); if (child < 0) { - close(socket[0]); - close(socket[1]); Debug::log(LOG, "Fail to create the first fork"); return 0; } @@ -967,22 +968,16 @@ uint64_t CKeybindManager::spawnRawProc(std::string args, PHLWORKSPACE pInitialWo setenv(e.first.c_str(), e.second.c_str(), 1); } setenv("WAYLAND_DISPLAY", g_pCompositor->m_szWLDisplaySocket.c_str(), 1); - close(socket[0]); - close(socket[1]); execl("/bin/sh", "/bin/sh", "-c", args.c_str(), nullptr); // exit grandchild _exit(0); } - close(socket[0]); - write(socket[1], &grandchild, sizeof(grandchild)); - close(socket[1]); + write(pipeSock[1].get(), &grandchild, sizeof(grandchild)); // exit child _exit(0); } // run in parent - close(socket[1]); - read(socket[0], &grandchild, sizeof(grandchild)); - close(socket[0]); + read(pipeSock[0].get(), &grandchild, sizeof(grandchild)); // clear child and leave grandchild to init waitpid(child, nullptr, 0); if (grandchild < 0) { diff --git a/src/managers/eventLoop/EventLoopManager.cpp b/src/managers/eventLoop/EventLoopManager.cpp index 4021c171..83bdf4a0 100644 --- a/src/managers/eventLoop/EventLoopManager.cpp +++ b/src/managers/eventLoop/EventLoopManager.cpp @@ -11,11 +11,12 @@ #include #include +using namespace Hyprutils::OS; #define TIMESPEC_NSEC_PER_SEC 1000000000L CEventLoopManager::CEventLoopManager(wl_display* display, wl_event_loop* wlEventLoop) { - m_sTimers.timerfd = timerfd_create(CLOCK_MONOTONIC, TFD_CLOEXEC); + m_sTimers.timerfd = CFileDescriptor{timerfd_create(CLOCK_MONOTONIC, TFD_CLOEXEC)}; m_sWayland.loop = wlEventLoop; m_sWayland.display = display; } @@ -31,8 +32,6 @@ CEventLoopManager::~CEventLoopManager() { wl_event_source_remove(m_sIdle.eventSource); if (m_configWatcherInotifySource) wl_event_source_remove(m_configWatcherInotifySource); - if (m_sTimers.timerfd >= 0) - close(m_sTimers.timerfd); } static int timerWrite(int fd, uint32_t mask, void* data) { @@ -52,10 +51,10 @@ static int configWatcherWrite(int fd, uint32_t mask, void* data) { } void CEventLoopManager::enterLoop() { - m_sWayland.eventSource = wl_event_loop_add_fd(m_sWayland.loop, m_sTimers.timerfd, WL_EVENT_READABLE, timerWrite, nullptr); + m_sWayland.eventSource = wl_event_loop_add_fd(m_sWayland.loop, m_sTimers.timerfd.get(), WL_EVENT_READABLE, timerWrite, nullptr); - if (const auto FD = g_pConfigWatcher->getInotifyFD(); FD >= 0) - m_configWatcherInotifySource = wl_event_loop_add_fd(m_sWayland.loop, FD, WL_EVENT_READABLE, configWatcherWrite, nullptr); + if (const auto& FD = g_pConfigWatcher->getInotifyFD(); FD.isValid()) + m_configWatcherInotifySource = wl_event_loop_add_fd(m_sWayland.loop, FD.get(), WL_EVENT_READABLE, configWatcherWrite, nullptr); syncPollFDs(); m_sListeners.pollFDsChanged = g_pCompositor->m_pAqBackend->events.pollFDsChanged.registerListener([this](std::any d) { syncPollFDs(); }); @@ -120,7 +119,7 @@ void CEventLoopManager::nudgeTimers() { itimerspec ts = {.it_value = now}; - timerfd_settime(m_sTimers.timerfd, TFD_TIMER_ABSTIME, &ts, nullptr); + timerfd_settime(m_sTimers.timerfd.get(), TFD_TIMER_ABSTIME, &ts, nullptr); } void CEventLoopManager::doLater(const std::function& fn) { diff --git a/src/managers/eventLoop/EventLoopManager.hpp b/src/managers/eventLoop/EventLoopManager.hpp index 95cc6109..ebeb2160 100644 --- a/src/managers/eventLoop/EventLoopManager.hpp +++ b/src/managers/eventLoop/EventLoopManager.hpp @@ -6,6 +6,7 @@ #include #include #include "helpers/signal/Signal.hpp" +#include #include "EventLoopTimer.hpp" @@ -54,7 +55,7 @@ class CEventLoopManager { struct { std::vector> timers; - int timerfd = -1; + Hyprutils::OS::CFileDescriptor timerfd; } m_sTimers; SIdleData m_sIdle; diff --git a/src/protocols/DRMLease.cpp b/src/protocols/DRMLease.cpp index 6fdbaf4b..e70f0441 100644 --- a/src/protocols/DRMLease.cpp +++ b/src/protocols/DRMLease.cpp @@ -4,6 +4,7 @@ #include "managers/eventLoop/EventLoopManager.hpp" #include #include +using namespace Hyprutils::OS; CDRMLeaseResource::CDRMLeaseResource(SP resource_, SP request) : resource(resource_) { if UNLIKELY (!good()) @@ -185,15 +186,14 @@ CDRMLeaseDeviceResource::CDRMLeaseDeviceResource(SP resourc RESOURCE->parent = self; }); - int fd = ((Aquamarine::CDRMBackend*)PROTO::lease->primaryDevice->backend.get())->getNonMasterFD(); - if (fd < 0) { + CFileDescriptor fd{((Aquamarine::CDRMBackend*)PROTO::lease->primaryDevice->backend.get())->getNonMasterFD()}; + if (!fd.isValid()) { LOGM(ERR, "Failed to dup fd in lease"); return; } - LOGM(LOG, "Sending DRMFD {} to new lease device", fd); - resource->sendDrmFd(fd); - close(fd); + LOGM(LOG, "Sending DRMFD {} to new lease device", fd.get()); + resource->sendDrmFd(fd.get()); for (auto const& m : PROTO::lease->primaryDevice->offeredOutputs) { if (m) @@ -231,16 +231,15 @@ void CDRMLeaseDeviceResource::sendConnector(PHLMONITOR monitor) { } CDRMLeaseDevice::CDRMLeaseDevice(SP drmBackend) : backend(drmBackend) { - auto drm = (Aquamarine::CDRMBackend*)drmBackend.get(); + auto drm = (Aquamarine::CDRMBackend*)drmBackend.get(); - auto fd = drm->getNonMasterFD(); + CFileDescriptor fd{drm->getNonMasterFD()}; - if (fd < 0) { + if (!fd.isValid()) { LOGM(ERR, "Failed to dup fd for drm node {}", drm->gpuName); return; } - close(fd); success = true; name = drm->gpuName; } diff --git a/src/protocols/DRMLease.hpp b/src/protocols/DRMLease.hpp index ec1e73f2..c7849149 100644 --- a/src/protocols/DRMLease.hpp +++ b/src/protocols/DRMLease.hpp @@ -5,6 +5,7 @@ #include "WaylandProtocol.hpp" #include "drm-lease-v1.hpp" #include "../helpers/signal/Signal.hpp" +#include /* TODO: this protocol is not made for systems with multiple DRM nodes (e.g. multigpu) diff --git a/src/protocols/DRMSyncobj.cpp b/src/protocols/DRMSyncobj.cpp index ce598385..23dafbca 100644 --- a/src/protocols/DRMSyncobj.cpp +++ b/src/protocols/DRMSyncobj.cpp @@ -6,6 +6,7 @@ #include "../Compositor.hpp" #include +using namespace Hyprutils::OS; CDRMSyncobjSurfaceResource::CDRMSyncobjSurfaceResource(SP resource_, SP surface_) : surface(surface_), resource(resource_) { if UNLIKELY (!good()) @@ -103,7 +104,7 @@ bool CDRMSyncobjSurfaceResource::good() { return resource->resource(); } -CDRMSyncobjTimelineResource::CDRMSyncobjTimelineResource(SP resource_, int fd_) : fd(fd_), resource(resource_) { +CDRMSyncobjTimelineResource::CDRMSyncobjTimelineResource(SP resource_, CFileDescriptor fd_) : fd(std::move(fd_)), resource(resource_) { if UNLIKELY (!good()) return; @@ -112,7 +113,7 @@ CDRMSyncobjTimelineResource::CDRMSyncobjTimelineResource(SPsetOnDestroy([this](CWpLinuxDrmSyncobjTimelineV1* r) { PROTO::sync->destroyResource(this); }); resource->setDestroy([this](CWpLinuxDrmSyncobjTimelineV1* r) { PROTO::sync->destroyResource(this); }); - timeline = CSyncTimeline::create(PROTO::sync->drmFD, fd); + timeline = CSyncTimeline::create(PROTO::sync->drmFD, fd.get()); if (!timeline) { resource->error(WP_LINUX_DRM_SYNCOBJ_MANAGER_V1_ERROR_INVALID_TIMELINE, "Timeline failed importing"); @@ -120,11 +121,6 @@ CDRMSyncobjTimelineResource::CDRMSyncobjTimelineResource(SP= 0) - close(fd); -} - SP CDRMSyncobjTimelineResource::fromResource(wl_resource* res) { auto data = (CDRMSyncobjTimelineResource*)(((CWpLinuxDrmSyncobjTimelineV1*)wl_resource_get_user_data(res))->data()); return data ? data->self.lock() : nullptr; @@ -171,7 +167,7 @@ CDRMSyncobjManagerResource::CDRMSyncobjManagerResource(SPsetImportTimeline([this](CWpLinuxDrmSyncobjManagerV1* r, uint32_t id, int32_t fd) { - auto RESOURCE = makeShared(makeShared(resource->client(), resource->version(), id), fd); + auto RESOURCE = makeShared(makeShared(resource->client(), resource->version(), id), CFileDescriptor{fd}); if UNLIKELY (!RESOURCE->good()) { resource->noMemory(); return; diff --git a/src/protocols/DRMSyncobj.hpp b/src/protocols/DRMSyncobj.hpp index 42ecdb3e..8677576f 100644 --- a/src/protocols/DRMSyncobj.hpp +++ b/src/protocols/DRMSyncobj.hpp @@ -4,6 +4,7 @@ #include "WaylandProtocol.hpp" #include "linux-drm-syncobj-v1.hpp" #include "../helpers/signal/Signal.hpp" +#include class CWLSurfaceResource; class CDRMSyncobjTimelineResource; @@ -32,14 +33,14 @@ class CDRMSyncobjSurfaceResource { class CDRMSyncobjTimelineResource { public: - CDRMSyncobjTimelineResource(SP resource_, int fd_); - ~CDRMSyncobjTimelineResource(); + CDRMSyncobjTimelineResource(SP resource_, Hyprutils::OS::CFileDescriptor fd_); + ~CDRMSyncobjTimelineResource() = default; static SP fromResource(wl_resource*); bool good(); WP self; - int fd = -1; + Hyprutils::OS::CFileDescriptor fd; SP timeline; private: diff --git a/src/protocols/DataDeviceWlr.cpp b/src/protocols/DataDeviceWlr.cpp index 71ee1c4a..3da5afd6 100644 --- a/src/protocols/DataDeviceWlr.cpp +++ b/src/protocols/DataDeviceWlr.cpp @@ -2,6 +2,7 @@ #include #include "../managers/SeatManager.hpp" #include "core/Seat.hpp" +using namespace Hyprutils::OS; CWLRDataOffer::CWLRDataOffer(SP resource_, SP source_) : source(source_), resource(resource_) { if UNLIKELY (!good()) @@ -11,21 +12,20 @@ CWLRDataOffer::CWLRDataOffer(SP resource_, SPsetOnDestroy([this](CZwlrDataControlOfferV1* r) { PROTO::dataWlr->destroyResource(this); }); resource->setReceive([this](CZwlrDataControlOfferV1* r, const char* mime, int32_t fd) { + CFileDescriptor sendFd{fd}; if (!source) { LOGM(WARN, "Possible bug: Receive on an offer w/o a source"); - close(fd); return; } if (dead) { LOGM(WARN, "Possible bug: Receive on an offer that's dead"); - close(fd); return; } LOGM(LOG, "Offer {:x} asks to send data from source {:x}", (uintptr_t)this, (uintptr_t)source.get()); - source->send(mime, fd); + source->send(mime, std::move(sendFd)); }); } @@ -77,15 +77,13 @@ std::vector CWLRDataSource::mimes() { return mimeTypes; } -void CWLRDataSource::send(const std::string& mime, uint32_t fd) { +void CWLRDataSource::send(const std::string& mime, CFileDescriptor fd) { if (std::find(mimeTypes.begin(), mimeTypes.end(), mime) == mimeTypes.end()) { LOGM(ERR, "Compositor/App bug: CWLRDataSource::sendAskSend with non-existent mime"); - close(fd); return; } - resource->sendSend(mime.c_str(), fd); - close(fd); + resource->sendSend(mime.c_str(), fd.get()); } void CWLRDataSource::accepted(const std::string& mime) { diff --git a/src/protocols/DataDeviceWlr.hpp b/src/protocols/DataDeviceWlr.hpp index 5eef163c..7f14b320 100644 --- a/src/protocols/DataDeviceWlr.hpp +++ b/src/protocols/DataDeviceWlr.hpp @@ -5,6 +5,7 @@ #include "WaylandProtocol.hpp" #include "wlr-data-control-unstable-v1.hpp" #include "types/DataDevice.hpp" +#include class CWLRDataControlManagerResource; class CWLRDataSource; @@ -38,7 +39,7 @@ class CWLRDataSource : public IDataSource { bool good(); virtual std::vector mimes(); - virtual void send(const std::string& mime, uint32_t fd); + virtual void send(const std::string& mime, Hyprutils::OS::CFileDescriptor fd); virtual void accepted(const std::string& mime); virtual void cancelled(); virtual void error(uint32_t code, const std::string& msg); diff --git a/src/protocols/GammaControl.cpp b/src/protocols/GammaControl.cpp index 43ba9d41..0a383e2e 100644 --- a/src/protocols/GammaControl.cpp +++ b/src/protocols/GammaControl.cpp @@ -4,6 +4,7 @@ #include "../helpers/Monitor.hpp" #include "../protocols/core/Output.hpp" #include "../render/Renderer.hpp" +using namespace Hyprutils::OS; CGammaControl::CGammaControl(SP resource_, wl_resource* output) : resource(resource_) { if UNLIKELY (!resource_->resource()) @@ -46,34 +47,33 @@ CGammaControl::CGammaControl(SP resource_, wl_resource* out resource->setOnDestroy([this](CZwlrGammaControlV1* gamma) { PROTO::gamma->destroyGammaControl(this); }); resource->setSetGamma([this](CZwlrGammaControlV1* gamma, int32_t fd) { + CFileDescriptor gammaFd{fd}; if UNLIKELY (!pMonitor) { LOGM(ERR, "setGamma for a dead monitor"); resource->sendFailed(); - close(fd); return; } LOGM(LOG, "setGamma for {}", pMonitor->szName); - int fdFlags = fcntl(fd, F_GETFL, 0); + // TODO: make CFileDescriptor getflags use F_GETFL + int fdFlags = fcntl(gammaFd.get(), F_GETFL, 0); if UNLIKELY (fdFlags < 0) { LOGM(ERR, "Failed to get fd flags"); resource->sendFailed(); - close(fd); return; } - if UNLIKELY (fcntl(fd, F_SETFL, fdFlags | O_NONBLOCK) < 0) { + // TODO: make CFileDescriptor setflags use F_SETFL + if UNLIKELY (fcntl(gammaFd.get(), F_SETFL, fdFlags | O_NONBLOCK) < 0) { LOGM(ERR, "Failed to set fd flags"); resource->sendFailed(); - close(fd); return; } - ssize_t readBytes = pread(fd, gammaTable.data(), gammaTable.size() * sizeof(uint16_t), 0); + ssize_t readBytes = pread(gammaFd.get(), gammaTable.data(), gammaTable.size() * sizeof(uint16_t), 0); if (readBytes < 0 || (size_t)readBytes != gammaTable.size() * sizeof(uint16_t)) { LOGM(ERR, "Failed to read bytes"); - close(fd); if ((size_t)readBytes != gammaTable.size() * sizeof(uint16_t)) { gamma->error(ZWLR_GAMMA_CONTROL_V1_ERROR_INVALID_GAMMA, "Gamma ramps size mismatch"); @@ -85,7 +85,6 @@ CGammaControl::CGammaControl(SP resource_, wl_resource* out } gammaTableSet = true; - close(fd); // translate the table to AQ format std::vector red, green, blue; diff --git a/src/protocols/InputMethodV2.cpp b/src/protocols/InputMethodV2.cpp index 796cec06..33121ecd 100644 --- a/src/protocols/InputMethodV2.cpp +++ b/src/protocols/InputMethodV2.cpp @@ -33,25 +33,22 @@ void CInputMethodKeyboardGrabV2::sendKeyboardData(SP keyboard) { pLastKeyboard = keyboard; - int keymapFD = allocateSHMFile(keyboard->xkbKeymapString.length() + 1); - if UNLIKELY (keymapFD < 0) { + auto keymapFD = allocateSHMFile(keyboard->xkbKeymapString.length() + 1); + if UNLIKELY (!keymapFD.isValid()) { LOGM(ERR, "Failed to create a keymap file for keyboard grab"); return; } - void* data = mmap(nullptr, keyboard->xkbKeymapString.length() + 1, PROT_READ | PROT_WRITE, MAP_SHARED, keymapFD, 0); + void* data = mmap(nullptr, keyboard->xkbKeymapString.length() + 1, PROT_READ | PROT_WRITE, MAP_SHARED, keymapFD.get(), 0); if UNLIKELY (data == MAP_FAILED) { LOGM(ERR, "Failed to mmap a keymap file for keyboard grab"); - close(keymapFD); return; } memcpy(data, keyboard->xkbKeymapString.c_str(), keyboard->xkbKeymapString.length()); munmap(data, keyboard->xkbKeymapString.length() + 1); - resource->sendKeymap(WL_KEYBOARD_KEYMAP_FORMAT_XKB_V1, keymapFD, keyboard->xkbKeymapString.length() + 1); - - close(keymapFD); + resource->sendKeymap(WL_KEYBOARD_KEYMAP_FORMAT_XKB_V1, keymapFD.get(), keyboard->xkbKeymapString.length() + 1); sendMods(keyboard->modifiersState.depressed, keyboard->modifiersState.latched, keyboard->modifiersState.locked, keyboard->modifiersState.group); diff --git a/src/protocols/LinuxDMABUF.cpp b/src/protocols/LinuxDMABUF.cpp index d3135da0..b7b91594 100644 --- a/src/protocols/LinuxDMABUF.cpp +++ b/src/protocols/LinuxDMABUF.cpp @@ -14,6 +14,8 @@ #include "../render/OpenGL.hpp" #include "../Compositor.hpp" +using namespace Hyprutils::OS; + static std::optional devIDFromFD(int fd) { struct stat stat; if (fstat(fd, &stat) != 0) @@ -77,29 +79,21 @@ CDMABUFFormatTable::CDMABUFFormatTable(SDMABUFTranche _rendererTranche, std::vec tableSize = formatsVec.size() * sizeof(SDMABUFFormatTableEntry); - int fds[2] = {0}; - allocateSHMFilePair(tableSize, &fds[0], &fds[1]); + CFileDescriptor fds[2]; + allocateSHMFilePair(tableSize, fds[0], fds[1]); - auto arr = (SDMABUFFormatTableEntry*)mmap(nullptr, tableSize, PROT_READ | PROT_WRITE, MAP_SHARED, fds[0], 0); + auto arr = (SDMABUFFormatTableEntry*)mmap(nullptr, tableSize, PROT_READ | PROT_WRITE, MAP_SHARED, fds[0].get(), 0); if (arr == MAP_FAILED) { LOGM(ERR, "mmap failed"); - close(fds[0]); - close(fds[1]); return; } - close(fds[0]); - std::copy(formatsVec.begin(), formatsVec.end(), arr); munmap(arr, tableSize); - tableFD = fds[1]; -} - -CDMABUFFormatTable::~CDMABUFFormatTable() { - close(tableFD); + tableFD = std::move(fds[1]); } CLinuxDMABuffer::CLinuxDMABuffer(uint32_t id, wl_client* client, Aquamarine::SDMABUFAttrs attrs) { @@ -234,18 +228,18 @@ void CLinuxDMABUFParamsResource::create(uint32_t id) { } bool CLinuxDMABUFParamsResource::commence() { - if (PROTO::linuxDma->mainDeviceFD < 0) + if (!PROTO::linuxDma->mainDeviceFD.isValid()) return true; for (int i = 0; i < attrs->planes; i++) { uint32_t handle = 0; - if (drmPrimeFDToHandle(PROTO::linuxDma->mainDeviceFD, attrs->fds.at(i), &handle)) { + if (drmPrimeFDToHandle(PROTO::linuxDma->mainDeviceFD.get(), attrs->fds.at(i), &handle)) { LOGM(ERR, "Failed to import dmabuf fd"); return false; } - if (drmCloseBufferHandle(PROTO::linuxDma->mainDeviceFD, handle)) { + if (drmCloseBufferHandle(PROTO::linuxDma->mainDeviceFD.get(), handle)) { LOGM(ERR, "Failed to close dmabuf handle"); return false; } @@ -303,7 +297,7 @@ CLinuxDMABUFFeedbackResource::CLinuxDMABUFFeedbackResource(SPsetDestroy([this](CZwpLinuxDmabufFeedbackV1* r) { PROTO::linuxDma->destroyResource(this); }); auto& formatTable = PROTO::linuxDma->formatTable; - resource->sendFormatTable(formatTable->tableFD, formatTable->tableSize); + resource->sendFormatTable(formatTable->tableFD.get(), formatTable->tableSize); sendDefaultFeedback(); } @@ -472,9 +466,9 @@ CLinuxDMABufV1Protocol::CLinuxDMABufV1Protocol(const wl_interface* iface, const if (device->available_nodes & (1 << DRM_NODE_RENDER)) { const char* name = device->nodes[DRM_NODE_RENDER]; - mainDeviceFD = open(name, O_RDWR | O_CLOEXEC); + mainDeviceFD = CFileDescriptor{open(name, O_RDWR | O_CLOEXEC)}; drmFreeDevice(&device); - if (mainDeviceFD < 0) { + if (!mainDeviceFD.isValid()) { LOGM(ERR, "failed to open drm dev, disabling linux dmabuf"); removeGlobal(); return; @@ -496,7 +490,7 @@ void CLinuxDMABufV1Protocol::resetFormatTable() { auto newFormatTable = makeUnique(formatTable->rendererTranche, formatTable->monitorTranches); for (auto const& feedback : m_vFeedbacks) { - feedback->resource->sendFormatTable(newFormatTable->tableFD, newFormatTable->tableSize); + feedback->resource->sendFormatTable(newFormatTable->tableFD.get(), newFormatTable->tableSize); if (feedback->lastFeedbackWasScanout) { PHLMONITOR mon; auto HLSurface = CWLSurface::fromResource(feedback->surface); @@ -519,11 +513,6 @@ void CLinuxDMABufV1Protocol::resetFormatTable() { formatTable = std::move(newFormatTable); } -CLinuxDMABufV1Protocol::~CLinuxDMABufV1Protocol() { - if (mainDeviceFD >= 0) - close(mainDeviceFD); -} - void CLinuxDMABufV1Protocol::bindManager(wl_client* client, void* data, uint32_t ver, uint32_t id) { const auto RESOURCE = m_vManagers.emplace_back(makeShared(makeShared(client, ver, id))); diff --git a/src/protocols/LinuxDMABUF.hpp b/src/protocols/LinuxDMABUF.hpp index 91cf3283..6c967878 100644 --- a/src/protocols/LinuxDMABUF.hpp +++ b/src/protocols/LinuxDMABUF.hpp @@ -9,6 +9,7 @@ #include "../helpers/Format.hpp" #include "../helpers/Monitor.hpp" #include +#include class CDMABuffer; class CWLSurfaceResource; @@ -48,9 +49,9 @@ struct SDMABUFTranche { class CDMABUFFormatTable { public: CDMABUFFormatTable(SDMABUFTranche rendererTranche, std::vector> tranches); - ~CDMABUFFormatTable(); + ~CDMABUFFormatTable() = default; - int tableFD = -1; + Hyprutils::OS::CFileDescriptor tableFD; size_t tableSize = 0; SDMABUFTranche rendererTranche; std::vector> monitorTranches; @@ -107,7 +108,7 @@ class CLinuxDMABUFResource { class CLinuxDMABufV1Protocol : public IWaylandProtocol { public: CLinuxDMABufV1Protocol(const wl_interface* iface, const int& ver, const std::string& name); - ~CLinuxDMABufV1Protocol(); + ~CLinuxDMABufV1Protocol() = default; virtual void bindManager(wl_client* client, void* data, uint32_t ver, uint32_t id); void updateScanoutTranche(SP surface, PHLMONITOR pMonitor); @@ -128,7 +129,7 @@ class CLinuxDMABufV1Protocol : public IWaylandProtocol { UP formatTable; dev_t mainDevice; - int mainDeviceFD = -1; + Hyprutils::OS::CFileDescriptor mainDeviceFD; friend class CLinuxDMABUFResource; friend class CLinuxDMABUFFeedbackResource; diff --git a/src/protocols/PrimarySelection.cpp b/src/protocols/PrimarySelection.cpp index 567bfdd2..620f262e 100644 --- a/src/protocols/PrimarySelection.cpp +++ b/src/protocols/PrimarySelection.cpp @@ -3,6 +3,7 @@ #include "../managers/SeatManager.hpp" #include "core/Seat.hpp" #include "../config/ConfigValue.hpp" +using namespace Hyprutils::OS; CPrimarySelectionOffer::CPrimarySelectionOffer(SP resource_, SP source_) : source(source_), resource(resource_) { if UNLIKELY (!good()) @@ -12,21 +13,20 @@ CPrimarySelectionOffer::CPrimarySelectionOffer(SP r resource->setOnDestroy([this](CZwpPrimarySelectionOfferV1* r) { PROTO::primarySelection->destroyResource(this); }); resource->setReceive([this](CZwpPrimarySelectionOfferV1* r, const char* mime, int32_t fd) { + CFileDescriptor sendFd{fd}; if (!source) { LOGM(WARN, "Possible bug: Receive on an offer w/o a source"); - close(fd); return; } if (dead) { LOGM(WARN, "Possible bug: Receive on an offer that's dead"); - close(fd); return; } LOGM(LOG, "Offer {:x} asks to send data from source {:x}", (uintptr_t)this, (uintptr_t)source.get()); - source->send(mime, fd); + source->send(mime, std::move(sendFd)); }); } @@ -78,15 +78,13 @@ std::vector CPrimarySelectionSource::mimes() { return mimeTypes; } -void CPrimarySelectionSource::send(const std::string& mime, uint32_t fd) { +void CPrimarySelectionSource::send(const std::string& mime, CFileDescriptor fd) { if (std::find(mimeTypes.begin(), mimeTypes.end(), mime) == mimeTypes.end()) { LOGM(ERR, "Compositor/App bug: CPrimarySelectionSource::sendAskSend with non-existent mime"); - close(fd); return; } - resource->sendSend(mime.c_str(), fd); - close(fd); + resource->sendSend(mime.c_str(), fd.get()); } void CPrimarySelectionSource::accepted(const std::string& mime) { diff --git a/src/protocols/PrimarySelection.hpp b/src/protocols/PrimarySelection.hpp index aeebe03c..0ecc962b 100644 --- a/src/protocols/PrimarySelection.hpp +++ b/src/protocols/PrimarySelection.hpp @@ -5,6 +5,7 @@ #include "WaylandProtocol.hpp" #include "primary-selection-unstable-v1.hpp" #include "types/DataDevice.hpp" +#include class CPrimarySelectionOffer; class CPrimarySelectionSource; @@ -38,7 +39,7 @@ class CPrimarySelectionSource : public IDataSource { bool good(); virtual std::vector mimes(); - virtual void send(const std::string& mime, uint32_t fd); + virtual void send(const std::string& mime, Hyprutils::OS::CFileDescriptor fd); virtual void accepted(const std::string& mime); virtual void cancelled(); virtual void error(uint32_t code, const std::string& msg); diff --git a/src/protocols/SecurityContext.cpp b/src/protocols/SecurityContext.cpp index e5b3cf2a..30fca260 100644 --- a/src/protocols/SecurityContext.cpp +++ b/src/protocols/SecurityContext.cpp @@ -1,6 +1,7 @@ #include "SecurityContext.hpp" #include "../Compositor.hpp" #include +using namespace Hyprutils::OS; static int onListenFdEvent(int fd, uint32_t mask, void* data) { auto sc = (CSecurityContext*)data; @@ -14,8 +15,8 @@ static int onCloseFdEvent(int fd, uint32_t mask, void* data) { return 0; } -SP CSecurityContextSandboxedClient::create(int clientFD_) { - auto p = SP(new CSecurityContextSandboxedClient(clientFD_)); +SP CSecurityContextSandboxedClient::create(CFileDescriptor clientFD_) { + auto p = SP(new CSecurityContextSandboxedClient(std::move(clientFD_))); if (!p->client) return nullptr; return p; @@ -27,8 +28,8 @@ static void onSecurityContextClientDestroy(wl_listener* l, void* d) { client->onDestroy(); } -CSecurityContextSandboxedClient::CSecurityContextSandboxedClient(int clientFD_) : clientFD(clientFD_) { - client = wl_client_create(g_pCompositor->m_sWLDisplay, clientFD); +CSecurityContextSandboxedClient::CSecurityContextSandboxedClient(CFileDescriptor clientFD_) : clientFD(std::move(clientFD_)) { + client = wl_client_create(g_pCompositor->m_sWLDisplay, clientFD.get()); if (!client) return; @@ -41,7 +42,6 @@ CSecurityContextSandboxedClient::CSecurityContextSandboxedClient(int clientFD_) CSecurityContextSandboxedClient::~CSecurityContextSandboxedClient() { wl_list_remove(&destroyListener.listener.link); wl_list_init(&destroyListener.listener.link); - close(clientFD); } void CSecurityContextSandboxedClient::onDestroy() { @@ -113,8 +113,8 @@ CSecurityContext::CSecurityContext(SP resource_, int liste LOGM(LOG, "security_context at 0x{:x} commits", (uintptr_t)this); - listenSource = wl_event_loop_add_fd(g_pCompositor->m_sWLEventLoop, listenFD, WL_EVENT_READABLE, ::onListenFdEvent, this); - closeSource = wl_event_loop_add_fd(g_pCompositor->m_sWLEventLoop, closeFD, 0, ::onCloseFdEvent, this); + listenSource = wl_event_loop_add_fd(g_pCompositor->m_sWLEventLoop, listenFD.get(), WL_EVENT_READABLE, ::onListenFdEvent, this); + closeSource = wl_event_loop_add_fd(g_pCompositor->m_sWLEventLoop, closeFD.get(), 0, ::onCloseFdEvent, this); if (!listenSource || !closeSource) { r->noMemory(); @@ -144,16 +144,15 @@ void CSecurityContext::onListen(uint32_t mask) { if (!(mask & WL_EVENT_READABLE)) return; - int clientFD = accept(listenFD, nullptr, nullptr); - if UNLIKELY (clientFD < 0) { + CFileDescriptor clientFD{accept(listenFD.get(), nullptr, nullptr)}; + if UNLIKELY (!clientFD.isValid()) { LOGM(ERR, "security_context at 0x{:x} couldn't accept", (uintptr_t)this); return; } - auto newClient = CSecurityContextSandboxedClient::create(clientFD); + auto newClient = CSecurityContextSandboxedClient::create(std::move(clientFD)); if UNLIKELY (!newClient) { LOGM(ERR, "security_context at 0x{:x} couldn't create a client", (uintptr_t)this); - close(clientFD); return; } diff --git a/src/protocols/SecurityContext.hpp b/src/protocols/SecurityContext.hpp index 2bec08d4..56d4f7b4 100644 --- a/src/protocols/SecurityContext.hpp +++ b/src/protocols/SecurityContext.hpp @@ -4,19 +4,20 @@ #include #include "WaylandProtocol.hpp" #include "security-context-v1.hpp" +#include class CSecurityContext { public: CSecurityContext(SP resource_, int listenFD_, int closeFD_); ~CSecurityContext(); - bool good(); + bool good(); - std::string sandboxEngine, appID, instanceID; - int listenFD = -1, closeFD = -1; + std::string sandboxEngine, appID, instanceID; + Hyprutils::OS::CFileDescriptor listenFD, closeFD; - void onListen(uint32_t mask); - void onClose(uint32_t mask); + void onListen(uint32_t mask); + void onClose(uint32_t mask); private: SP resource; @@ -44,7 +45,7 @@ struct SCSecurityContextSandboxedClientDestroyWrapper { class CSecurityContextSandboxedClient { public: - static SP create(int clientFD); + static SP create(Hyprutils::OS::CFileDescriptor clientFD); ~CSecurityContextSandboxedClient(); void onDestroy(); @@ -52,10 +53,10 @@ class CSecurityContextSandboxedClient { SCSecurityContextSandboxedClientDestroyWrapper destroyListener; private: - CSecurityContextSandboxedClient(int clientFD_); + CSecurityContextSandboxedClient(Hyprutils::OS::CFileDescriptor clientFD_); - wl_client* client = nullptr; - int clientFD = -1; + wl_client* client = nullptr; + Hyprutils::OS::CFileDescriptor clientFD; friend class CSecurityContextProtocol; friend class CSecurityContext; diff --git a/src/protocols/VirtualKeyboard.cpp b/src/protocols/VirtualKeyboard.cpp index 4fec57c0..00aca041 100644 --- a/src/protocols/VirtualKeyboard.cpp +++ b/src/protocols/VirtualKeyboard.cpp @@ -1,6 +1,7 @@ #include "VirtualKeyboard.hpp" #include #include "../devices/IKeyboard.hpp" +using namespace Hyprutils::OS; CVirtualKeyboardV1Resource::CVirtualKeyboardV1Resource(SP resource_) : resource(resource_) { if UNLIKELY (!good()) @@ -51,20 +52,19 @@ CVirtualKeyboardV1Resource::CVirtualKeyboardV1Resource(SP }); resource->setKeymap([this](CZwpVirtualKeyboardV1* r, uint32_t fmt, int32_t fd, uint32_t len) { - auto xkbContext = xkb_context_new(XKB_CONTEXT_NO_FLAGS); + auto xkbContext = xkb_context_new(XKB_CONTEXT_NO_FLAGS); + CFileDescriptor keymapFd{fd}; if UNLIKELY (!xkbContext) { LOGM(ERR, "xkbContext creation failed"); r->noMemory(); - close(fd); return; } - auto keymapData = mmap(nullptr, len, PROT_READ, MAP_PRIVATE, fd, 0); + auto keymapData = mmap(nullptr, len, PROT_READ, MAP_PRIVATE, keymapFd.get(), 0); if UNLIKELY (keymapData == MAP_FAILED) { LOGM(ERR, "keymapData alloc failed"); xkb_context_unref(xkbContext); r->noMemory(); - close(fd); return; } @@ -75,7 +75,6 @@ CVirtualKeyboardV1Resource::CVirtualKeyboardV1Resource(SP LOGM(ERR, "xkbKeymap creation failed"); xkb_context_unref(xkbContext); r->noMemory(); - close(fd); return; } @@ -86,7 +85,6 @@ CVirtualKeyboardV1Resource::CVirtualKeyboardV1Resource(SP xkb_keymap_unref(xkbKeymap); xkb_context_unref(xkbContext); - close(fd); }); name = "hl-virtual-keyboard"; diff --git a/src/protocols/VirtualKeyboard.hpp b/src/protocols/VirtualKeyboard.hpp index 8157b276..0a13003b 100644 --- a/src/protocols/VirtualKeyboard.hpp +++ b/src/protocols/VirtualKeyboard.hpp @@ -5,6 +5,7 @@ #include "WaylandProtocol.hpp" #include "virtual-keyboard-unstable-v1.hpp" #include "../helpers/signal/Signal.hpp" +#include class CVirtualKeyboardV1Resource { public: diff --git a/src/protocols/core/DataDevice.cpp b/src/protocols/core/DataDevice.cpp index e17b5612..0931608a 100644 --- a/src/protocols/core/DataDevice.cpp +++ b/src/protocols/core/DataDevice.cpp @@ -13,6 +13,7 @@ #include "../../managers/HookSystemManager.hpp" #include "../../helpers/Monitor.hpp" #include "../../render/Renderer.hpp" +using namespace Hyprutils::OS; CWLDataOfferResource::CWLDataOfferResource(SP resource_, SP source_) : source(source_), resource(resource_) { if UNLIKELY (!good()) @@ -39,15 +40,14 @@ CWLDataOfferResource::CWLDataOfferResource(SP resource_, SPsetReceive([this](CWlDataOffer* r, const char* mime, uint32_t fd) { + CFileDescriptor sendFd{fd}; if (!source) { LOGM(WARN, "Possible bug: Receive on an offer w/o a source"); - close(fd); return; } if (dead) { LOGM(WARN, "Possible bug: Receive on an offer that's dead"); - close(fd); return; } @@ -58,7 +58,7 @@ CWLDataOfferResource::CWLDataOfferResource(SP resource_, SPaccepted(mime ? mime : ""); } - source->send(mime ? mime : "", fd); + source->send(mime ? mime : "", std::move(sendFd)); recvd = true; @@ -182,15 +182,13 @@ std::vector CWLDataSourceResource::mimes() { return mimeTypes; } -void CWLDataSourceResource::send(const std::string& mime, uint32_t fd) { +void CWLDataSourceResource::send(const std::string& mime, CFileDescriptor fd) { if (std::find(mimeTypes.begin(), mimeTypes.end(), mime) == mimeTypes.end()) { LOGM(ERR, "Compositor/App bug: CWLDataSourceResource::sendAskSend with non-existent mime"); - close(fd); return; } - resource->sendSend(mime.c_str(), fd); - close(fd); + resource->sendSend(mime.c_str(), fd.get()); } void CWLDataSourceResource::cancelled() { diff --git a/src/protocols/core/DataDevice.hpp b/src/protocols/core/DataDevice.hpp index d8bc2b9c..dfea4a71 100644 --- a/src/protocols/core/DataDevice.hpp +++ b/src/protocols/core/DataDevice.hpp @@ -16,6 +16,7 @@ #include "../../helpers/signal/Signal.hpp" #include "../../helpers/math/Math.hpp" #include "../types/DataDevice.hpp" +#include class CWLDataDeviceResource; class CWLDataDeviceManagerResource; @@ -63,7 +64,7 @@ class CWLDataSourceResource : public IDataSource { bool good(); virtual std::vector mimes(); - virtual void send(const std::string& mime, uint32_t fd); + virtual void send(const std::string& mime, Hyprutils::OS::CFileDescriptor fd); virtual void accepted(const std::string& mime); virtual void cancelled(); virtual bool hasDnd(); diff --git a/src/protocols/core/Seat.cpp b/src/protocols/core/Seat.cpp index c6b2de05..1f07a15e 100644 --- a/src/protocols/core/Seat.cpp +++ b/src/protocols/core/Seat.cpp @@ -321,35 +321,18 @@ void CWLKeyboardResource::sendKeymap(SP keyboard) { if (!(PROTO::seat->currentCaps & eHIDCapabilityType::HID_INPUT_CAPABILITY_KEYBOARD)) return; - std::string_view keymap; - int fd; - uint32_t size; - if (keyboard) { - keymap = keyboard->xkbKeymapString; - fd = keyboard->xkbKeymapFD; - size = keyboard->xkbKeymapString.length() + 1; - } else { - fd = open("/dev/null", O_RDONLY | O_CLOEXEC); - if (fd < 0) { - LOGM(ERR, "Failed to open /dev/null"); - return; - } - size = 0; - } + std::string_view keymap = keyboard->xkbKeymapString; + Hyprutils::OS::CFileDescriptor& fd = keyboard->xkbKeymapFD; + uint32_t size = keyboard->xkbKeymapString.length() + 1; - if (keymap == lastKeymap) { - if (!keyboard) - close(fd); + if (keymap == lastKeymap) return; - } + lastKeymap = keymap; const wl_keyboard_keymap_format format = keyboard ? WL_KEYBOARD_KEYMAP_FORMAT_XKB_V1 : WL_KEYBOARD_KEYMAP_FORMAT_NO_KEYMAP; - resource->sendKeymap(format, fd, size); - - if (!keyboard) - close(fd); + resource->sendKeymap(format, fd.get(), size); } void CWLKeyboardResource::sendEnter(SP surface) { diff --git a/src/protocols/core/Shm.cpp b/src/protocols/core/Shm.cpp index 1649f82f..e0e62560 100644 --- a/src/protocols/core/Shm.cpp +++ b/src/protocols/core/Shm.cpp @@ -7,6 +7,7 @@ #include "../types/WLBuffer.hpp" #include "../../helpers/Format.hpp" #include "../../render/Renderer.hpp" +using namespace Hyprutils::OS; CWLSHMBuffer::CWLSHMBuffer(SP pool_, uint32_t id, int32_t offset_, const Vector2D& size_, int32_t stride_, uint32_t fmt_) { if UNLIKELY (!pool_->pool->data) @@ -51,7 +52,7 @@ bool CWLSHMBuffer::isSynchronous() { Aquamarine::SSHMAttrs CWLSHMBuffer::shm() { Aquamarine::SSHMAttrs attrs; attrs.success = true; - attrs.fd = pool->fd; + attrs.fd = pool->fd.get(); attrs.format = NFormatUtils::shmToDRM(fmt); attrs.size = size; attrs.stride = stride; @@ -75,13 +76,12 @@ void CWLSHMBuffer::update(const CRegion& damage) { texture->update(NFormatUtils::shmToDRM(fmt), (uint8_t*)pool->data + offset, stride, damage); } -CSHMPool::CSHMPool(int fd_, size_t size_) : fd(fd_), size(size_), data(mmap(nullptr, size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0)) { +CSHMPool::CSHMPool(CFileDescriptor fd_, size_t size_) : fd(std::move(fd_)), size(size_), data(mmap(nullptr, size, PROT_READ | PROT_WRITE, MAP_SHARED, fd.get(), 0)) { ; } CSHMPool::~CSHMPool() { munmap(data, size); - close(fd); } void CSHMPool::resize(size_t size_) { @@ -90,23 +90,23 @@ void CSHMPool::resize(size_t size_) { if (data) munmap(data, size); size = size_; - data = mmap(nullptr, size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0); + data = mmap(nullptr, size, PROT_READ | PROT_WRITE, MAP_SHARED, fd.get(), 0); if UNLIKELY (data == MAP_FAILED) - LOGM(ERR, "Couldn't mmap {} bytes from fd {} of shm client", size, fd); + LOGM(ERR, "Couldn't mmap {} bytes from fd {} of shm client", size, fd.get()); } -static int shmIsSizeValid(int fd, size_t size) { +static int shmIsSizeValid(CFileDescriptor& fd, size_t size) { struct stat st; - if UNLIKELY (fstat(fd, &st) == -1) { - LOGM(ERR, "Couldn't get stat for fd {} of shm client", fd); + if UNLIKELY (fstat(fd.get(), &st) == -1) { + LOGM(ERR, "Couldn't get stat for fd {} of shm client", fd.get()); return 0; } return (size_t)st.st_size >= size; } -CWLSHMPoolResource::CWLSHMPoolResource(SP resource_, int fd_, size_t size_) : resource(resource_) { +CWLSHMPoolResource::CWLSHMPoolResource(SP resource_, CFileDescriptor fd_, size_t size_) : resource(resource_) { if UNLIKELY (!good()) return; @@ -115,7 +115,7 @@ CWLSHMPoolResource::CWLSHMPoolResource(SP resource_, int fd_, size_t return; } - pool = makeShared(fd_, size_); + pool = makeShared(std::move(fd_), size_); resource->setDestroy([this](CWlShmPool* r) { PROTO::shm->destroyResource(this); }); resource->setOnDestroy([this](CWlShmPool* r) { PROTO::shm->destroyResource(this); }); @@ -176,7 +176,8 @@ CWLSHMResource::CWLSHMResource(SP resource_) : resource(resource_) { resource->setOnDestroy([this](CWlShm* r) { PROTO::shm->destroyResource(this); }); resource->setCreatePool([](CWlShm* r, uint32_t id, int32_t fd, int32_t size) { - const auto RESOURCE = PROTO::shm->m_vPools.emplace_back(makeShared(makeShared(r->client(), r->version(), id), fd, size)); + CFileDescriptor poolFd{fd}; + const auto RESOURCE = PROTO::shm->m_vPools.emplace_back(makeShared(makeShared(r->client(), r->version(), id), std::move(poolFd), size)); if UNLIKELY (!RESOURCE->good()) { r->noMemory(); diff --git a/src/protocols/core/Shm.hpp b/src/protocols/core/Shm.hpp index d7e81367..fef821cb 100644 --- a/src/protocols/core/Shm.hpp +++ b/src/protocols/core/Shm.hpp @@ -7,6 +7,8 @@ - wl_buffer with shm */ +#include +#include #include #include #include "../WaylandProtocol.hpp" @@ -18,14 +20,14 @@ class CWLSHMPoolResource; class CSHMPool { public: - CSHMPool(int fd, size_t size); + CSHMPool(Hyprutils::OS::CFileDescriptor fd, size_t size); ~CSHMPool(); - int fd = 0; - size_t size = 0; - void* data = nullptr; + Hyprutils::OS::CFileDescriptor fd; + size_t size = 0; + void* data = nullptr; - void resize(size_t size); + void resize(size_t size); }; class CWLSHMBuffer : public IHLBuffer { @@ -57,7 +59,7 @@ class CWLSHMBuffer : public IHLBuffer { class CWLSHMPoolResource { public: - CWLSHMPoolResource(SP resource_, int fd, size_t size); + CWLSHMPoolResource(SP resource_, Hyprutils::OS::CFileDescriptor fd, size_t size); bool good(); diff --git a/src/protocols/types/DataDevice.hpp b/src/protocols/types/DataDevice.hpp index 62f10de2..cbb4b271 100644 --- a/src/protocols/types/DataDevice.hpp +++ b/src/protocols/types/DataDevice.hpp @@ -7,6 +7,7 @@ #include #include "../../helpers/memory/Memory.hpp" #include "../../helpers/math/Math.hpp" +#include class CWLDataOfferResource; class CX11DataOffer; @@ -24,10 +25,10 @@ class IDataSource { IDataSource() = default; virtual ~IDataSource() = default; - virtual std::vector mimes() = 0; - virtual void send(const std::string& mime, uint32_t fd) = 0; - virtual void accepted(const std::string& mime) = 0; - virtual void cancelled() = 0; + virtual std::vector mimes() = 0; + virtual void send(const std::string& mime, Hyprutils::OS::CFileDescriptor fd) = 0; + virtual void accepted(const std::string& mime) = 0; + virtual void cancelled() = 0; virtual bool hasDnd(); virtual bool dndDone(); virtual void sendDndFinished(); diff --git a/src/render/OpenGL.cpp b/src/render/OpenGL.cpp index 78b53c9b..e4aadd63 100644 --- a/src/render/OpenGL.cpp +++ b/src/render/OpenGL.cpp @@ -19,6 +19,7 @@ #include #include #include +using namespace Hyprutils::OS; const std::vector ASSET_PATHS = { #ifdef DATAROOTDIR @@ -301,11 +302,11 @@ CHyprOpenGLImpl::CHyprOpenGLImpl() : m_iDRMFD(g_pCompositor->m_iDRMFD) { Debug::log(WARN, "EGL: EXT_platform_device or EGL_EXT_device_query not supported, using gbm"); if (EGLEXTENSIONS.contains("KHR_platform_gbm")) { success = true; - m_iGBMFD = openRenderNode(m_iDRMFD); - if (m_iGBMFD < 0) + m_iGBMFD = CFileDescriptor{openRenderNode(m_iDRMFD)}; + if (!m_iGBMFD.isValid()) RASSERT(false, "Couldn't open a gbm fd"); - m_pGbmDevice = gbm_create_device(m_iGBMFD); + m_pGbmDevice = gbm_create_device(m_iGBMFD.get()); if (!m_pGbmDevice) RASSERT(false, "Couldn't open a gbm device"); @@ -371,9 +372,6 @@ CHyprOpenGLImpl::~CHyprOpenGLImpl() { if (m_pGbmDevice) gbm_device_destroy(m_pGbmDevice); - - if (m_iGBMFD >= 0) - close(m_iGBMFD); } std::optional> CHyprOpenGLImpl::getModsForFormat(EGLint format) { @@ -2954,29 +2952,28 @@ std::vector CHyprOpenGLImpl::getDRMFormats() { return drmFormats; } -SP CHyprOpenGLImpl::createEGLSync(int fenceFD) { +SP CHyprOpenGLImpl::createEGLSync(CFileDescriptor fenceFD) { std::vector attribs; - int dupFd = -1; - if (fenceFD > 0) { - dupFd = fcntl(fenceFD, F_DUPFD_CLOEXEC, 0); - if (dupFd < 0) { + CFileDescriptor dupFd; + if (fenceFD.isValid()) { + dupFd = fenceFD.duplicate(); + if (!dupFd.isValid()) { Debug::log(ERR, "createEGLSync: dup failed"); return nullptr; } // reserve number of elements to avoid reallocations attribs.reserve(3); attribs.push_back(EGL_SYNC_NATIVE_FENCE_FD_ANDROID); - attribs.push_back(dupFd); + attribs.push_back(dupFd.get()); attribs.push_back(EGL_NONE); } EGLSyncKHR sync = m_sProc.eglCreateSyncKHR(m_pEglDisplay, EGL_SYNC_NATIVE_FENCE_ANDROID, attribs.data()); if (sync == EGL_NO_SYNC_KHR) { Debug::log(ERR, "eglCreateSyncKHR failed"); - if (dupFd >= 0) - close(dupFd); return nullptr; - } + } else + dupFd.take(); // eglCreateSyncKHR only takes ownership on success // we need to flush otherwise we might not get a valid fd glFlush(); @@ -2989,19 +2986,18 @@ SP CHyprOpenGLImpl::createEGLSync(int fenceFD) { auto eglsync = SP(new CEGLSync); eglsync->sync = sync; - eglsync->m_iFd = fd; + eglsync->m_iFd = CFileDescriptor{fd}; return eglsync; } bool CHyprOpenGLImpl::waitForTimelinePoint(SP timeline, uint64_t point) { - int fd = timeline->exportAsSyncFileFD(point); - if (fd < 0) { + auto fd = timeline->exportAsSyncFileFD(point); + if (!fd.isValid()) { Debug::log(ERR, "waitForTimelinePoint: failed to get a fd from explicit timeline"); return false; } - auto sync = g_pHyprOpenGL->createEGLSync(fd); - close(fd); + auto sync = g_pHyprOpenGL->createEGLSync(std::move(fd)); if (!sync) { Debug::log(ERR, "waitForTimelinePoint: failed to get an eglsync from explicit timeline"); return false; @@ -3082,12 +3078,9 @@ CEGLSync::~CEGLSync() { if (g_pHyprOpenGL->m_sProc.eglDestroySyncKHR(g_pHyprOpenGL->m_pEglDisplay, sync) != EGL_TRUE) Debug::log(ERR, "eglDestroySyncKHR failed"); - - if (m_iFd >= 0) - close(m_iFd); } -int CEGLSync::fd() { +CFileDescriptor& CEGLSync::fd() { return m_iFd; } diff --git a/src/render/OpenGL.hpp b/src/render/OpenGL.hpp index 1ebb0162..d7abdf63 100644 --- a/src/render/OpenGL.hpp +++ b/src/render/OpenGL.hpp @@ -24,6 +24,7 @@ #include #include #include +#include #include "../debug/TracyDefines.hpp" @@ -146,15 +147,15 @@ class CEGLSync { public: ~CEGLSync(); - EGLSyncKHR sync = nullptr; + EGLSyncKHR sync = nullptr; - int fd(); - bool wait(); + Hyprutils::OS::CFileDescriptor& fd(); + bool wait(); private: CEGLSync() = default; - int m_iFd = -1; + Hyprutils::OS::CFileDescriptor m_iFd; friend class CHyprOpenGLImpl; }; @@ -228,14 +229,14 @@ class CHyprOpenGLImpl { uint32_t getPreferredReadFormat(PHLMONITOR pMonitor); std::vector getDRMFormats(); EGLImageKHR createEGLImage(const Aquamarine::SDMABUFAttrs& attrs); - SP createEGLSync(int fenceFD); + SP createEGLSync(Hyprutils::OS::CFileDescriptor fenceFD); bool waitForTimelinePoint(SP timeline, uint64_t point); SCurrentRenderData m_RenderData; GLint m_iCurrentOutputFb = 0; - int m_iGBMFD = -1; + Hyprutils::OS::CFileDescriptor m_iGBMFD; gbm_device* m_pGbmDevice = nullptr; EGLContext m_pEglContext = nullptr; EGLDisplay m_pEglDisplay = nullptr; diff --git a/src/render/Renderer.cpp b/src/render/Renderer.cpp index 67d8b58b..42445728 100644 --- a/src/render/Renderer.cpp +++ b/src/render/Renderer.cpp @@ -36,6 +36,7 @@ #include using namespace Hyprutils::Utils; +using namespace Hyprutils::OS; extern "C" { #include @@ -1462,10 +1463,10 @@ static hdr_output_metadata createHDRMetadata(SImageDescription settings, Aquamar bool CHyprRenderer::commitPendingAndDoExplicitSync(PHLMONITOR pMonitor) { // apply timelines for explicit sync // save inFD otherwise reset will reset it - auto inFD = pMonitor->output->state->state().explicitInFence; + CFileDescriptor inFD{pMonitor->output->state->state().explicitInFence}; pMonitor->output->state->resetExplicitFences(); - if (inFD >= 0) - pMonitor->output->state->setExplicitInFence(inFD); + if (inFD.isValid()) + pMonitor->output->state->setExplicitInFence(inFD.get()); static auto PHDR = CConfigValue("experimental:hdr"); @@ -1515,7 +1516,7 @@ bool CHyprRenderer::commitPendingAndDoExplicitSync(PHLMONITOR pMonitor) { bool ok = pMonitor->state.commit(); if (!ok) { - if (inFD >= 0) { + if (inFD.isValid()) { Debug::log(TRACE, "Monitor state commit failed, retrying without a fence"); pMonitor->output->state->resetExplicitFences(); ok = pMonitor->state.commit(); @@ -1534,11 +1535,8 @@ bool CHyprRenderer::commitPendingAndDoExplicitSync(PHLMONITOR pMonitor) { if (!explicitOptions.explicitEnabled) return ok; - if (inFD >= 0) - close(inFD); - Debug::log(TRACE, "Explicit: {} presented", explicitPresented.size()); - auto sync = g_pHyprOpenGL->createEGLSync(-1); + auto sync = g_pHyprOpenGL->createEGLSync({}); if (!sync) Debug::log(TRACE, "Explicit: can't add sync, EGLSync failed"); @@ -2272,7 +2270,7 @@ void CHyprRenderer::endRender() { auto explicitOptions = getExplicitSyncSettings(); if (PMONITOR->inTimeline && explicitOptions.explicitEnabled && explicitOptions.explicitKMSEnabled) { - auto sync = g_pHyprOpenGL->createEGLSync(-1); + auto sync = g_pHyprOpenGL->createEGLSync({}); if (!sync) { Debug::log(ERR, "renderer: couldn't create an EGLSync for out in endRender"); return; @@ -2285,12 +2283,12 @@ void CHyprRenderer::endRender() { } auto fd = PMONITOR->inTimeline->exportAsSyncFileFD(PMONITOR->commitSeq); - if (fd <= 0) { + if (!fd.isValid()) { Debug::log(ERR, "renderer: couldn't export from sync timeline in endRender"); return; } - PMONITOR->output->state->setExplicitInFence(fd); + PMONITOR->output->state->setExplicitInFence(fd.take()); } else { if (isNvidia() && *PNVIDIAANTIFLICKER) glFinish(); diff --git a/src/xwayland/Dnd.cpp b/src/xwayland/Dnd.cpp index d4ae3780..16d166ce 100644 --- a/src/xwayland/Dnd.cpp +++ b/src/xwayland/Dnd.cpp @@ -7,6 +7,8 @@ #include "../managers/XWaylandManager.hpp" #include "../desktop/WLSurface.hpp" +using namespace Hyprutils::OS; + #ifndef NO_XWAYLAND static xcb_atom_t dndActionToAtom(uint32_t actions) { if (actions & WL_DATA_DEVICE_MANAGER_DND_ACTION_COPY) @@ -172,7 +174,7 @@ std::vector CX11DataSource::mimes() { return mimeTypes; } -void CX11DataSource::send(const std::string& mime, uint32_t fd) { +void CX11DataSource::send(const std::string& mime, CFileDescriptor fd) { ; } diff --git a/src/xwayland/Dnd.hpp b/src/xwayland/Dnd.hpp index 8da60ddd..fb030796 100644 --- a/src/xwayland/Dnd.hpp +++ b/src/xwayland/Dnd.hpp @@ -2,6 +2,7 @@ #include "../protocols/types/DataDevice.hpp" #include +#include #define XDND_VERSION 5 @@ -35,7 +36,7 @@ class CX11DataSource : public IDataSource { ~CX11DataSource() = default; virtual std::vector mimes(); - virtual void send(const std::string& mime, uint32_t fd); + virtual void send(const std::string& mime, Hyprutils::OS::CFileDescriptor fd); virtual void accepted(const std::string& mime); virtual void cancelled(); virtual bool hasDnd(); diff --git a/src/xwayland/Server.cpp b/src/xwayland/Server.cpp index d5dce333..99bcdf62 100644 --- a/src/xwayland/Server.cpp +++ b/src/xwayland/Server.cpp @@ -24,70 +24,41 @@ #include "../defines.hpp" #include "../Compositor.hpp" #include "../managers/CursorManager.hpp" +using namespace Hyprutils::OS; // Constants -constexpr int SOCKET_DIR_PERMISSIONS = 0755; -constexpr int SOCKET_BACKLOG = 1; -constexpr int MAX_SOCKET_RETRIES = 32; -constexpr int LOCK_FILE_MODE = 0444; +constexpr int SOCKET_DIR_PERMISSIONS = 0755; +constexpr int SOCKET_BACKLOG = 1; +constexpr int MAX_SOCKET_RETRIES = 32; +constexpr int LOCK_FILE_MODE = 0444; -static bool setCloseOnExec(int fd, bool cloexec) { - int flags = fcntl(fd, F_GETFD); - if (flags == -1) { - Debug::log(ERR, "fcntl failed"); - return false; - } - - if (cloexec) - flags = flags | FD_CLOEXEC; - else - flags = flags & ~FD_CLOEXEC; - - if (fcntl(fd, F_SETFD, flags) == -1) { - Debug::log(ERR, "fcntl failed"); - return false; - } - - return true; -} - -static void cleanUpSocket(int fd, const char* path) { - close(fd); - if (path[0]) - unlink(path); -} - -static inline void closeSocketSafely(int& fd) { - if (fd >= 0) - close(fd); -} - -static int createSocket(struct sockaddr_un* addr, size_t path_size) { - socklen_t size = offsetof(struct sockaddr_un, sun_path) + path_size + 1; - int fd = socket(AF_UNIX, SOCK_STREAM, 0); - if (fd < 0) { +static CFileDescriptor createSocket(struct sockaddr_un* addr, size_t path_size) { + socklen_t size = offsetof(struct sockaddr_un, sun_path) + path_size + 1; + CFileDescriptor fd{socket(AF_UNIX, SOCK_STREAM, 0)}; + if (!fd.isValid()) { Debug::log(ERR, "Failed to create socket {}{}", addr->sun_path[0] ? addr->sun_path[0] : '@', addr->sun_path + 1); - return -1; + return {}; } - if (!setCloseOnExec(fd, true)) { - close(fd); - return -1; + if (!fd.setFlags(fd.getFlags() | FD_CLOEXEC)) { + return {}; } if (addr->sun_path[0]) unlink(addr->sun_path); - if (bind(fd, (struct sockaddr*)addr, size) < 0) { + if (bind(fd.get(), (struct sockaddr*)addr, size) < 0) { Debug::log(ERR, "Failed to bind socket {}{}", addr->sun_path[0] ? addr->sun_path[0] : '@', addr->sun_path + 1); - cleanUpSocket(fd, addr->sun_path); - return -1; + if (addr->sun_path[0]) + unlink(addr->sun_path); + return {}; } - if (listen(fd, SOCKET_BACKLOG) < 0) { + if (listen(fd.get(), SOCKET_BACKLOG) < 0) { Debug::log(ERR, "Failed to listen to socket {}{}", addr->sun_path[0] ? addr->sun_path[0] : '@', addr->sun_path + 1); - cleanUpSocket(fd, addr->sun_path); - return -1; + if (addr->sun_path[0]) + unlink(addr->sun_path); + return {}; } return fd; @@ -141,7 +112,7 @@ static std::string getSocketPath(int display, bool isLinux) { return std::format("/tmp/.X11-unix/X{}_", display); } -static bool openSockets(std::array& sockets, int display) { +static bool openSockets(std::array& sockets, int display) { if (!ensureSocketDirExists()) return false; @@ -151,17 +122,16 @@ static bool openSockets(std::array& sockets, int display) { path = getSocketPath(display, false); strncpy(addr.sun_path, path.c_str(), path.length() + 1); - sockets[0] = createSocket(&addr, path.length()); - if (sockets[0] < 0) + sockets[0] = CFileDescriptor{createSocket(&addr, path.length())}; + if (!sockets[0].isValid()) return false; path = getSocketPath(display, true); strncpy(addr.sun_path, path.c_str(), path.length() + 1); - sockets[1] = createSocket(&addr, path.length()); - if (sockets[1] < 0) { - close(sockets[0]); - sockets[0] = -1; + sockets[1] = CFileDescriptor{createSocket(&addr, path.length())}; + if (!sockets[1].isValid()) { + sockets[0].reset(); return false; } @@ -174,7 +144,8 @@ static void startServer(void* data) { } static int xwaylandReady(int fd, uint32_t mask, void* data) { - return g_pXWayland->pServer->ready(fd, mask); + CFileDescriptor xwlFd{fd}; + return g_pXWayland->pServer->ready(std::move(xwlFd), mask); } static bool safeRemove(const std::string& path) { @@ -186,38 +157,34 @@ static bool safeRemove(const std::string& path) { bool CXWaylandServer::tryOpenSockets() { for (size_t i = 0; i <= MAX_SOCKET_RETRIES; ++i) { - std::string lockPath = std::format("/tmp/.X{}-lock", i); + std::string lockPath = std::format("/tmp/.X{}-lock", i); - int fd = open(lockPath.c_str(), O_WRONLY | O_CREAT | O_EXCL | O_CLOEXEC, LOCK_FILE_MODE); - if (fd >= 0) { + CFileDescriptor fd{open(lockPath.c_str(), O_WRONLY | O_CREAT | O_EXCL | O_CLOEXEC, LOCK_FILE_MODE)}; + if (fd.isValid()) { // we managed to open the lock if (!openSockets(xFDs, i)) { safeRemove(lockPath); - close(fd); continue; } const std::string pidStr = std::to_string(getpid()); - if (write(fd, pidStr.c_str(), pidStr.length()) != (long)pidStr.length()) { + if (write(fd.get(), pidStr.c_str(), pidStr.length()) != (long)pidStr.length()) { safeRemove(lockPath); - close(fd); continue; } - close(fd); display = i; displayName = std::format(":{}", display); break; } - fd = open(lockPath.c_str(), O_RDONLY | O_CLOEXEC); + fd = CFileDescriptor{open(lockPath.c_str(), O_RDONLY | O_CLOEXEC)}; - if (fd < 0) + if (!fd.isValid()) continue; char pidstr[12] = {0}; - read(fd, pidstr, sizeof(pidstr) - 1); - close(fd); + read(fd.get(), pidstr, sizeof(pidstr) - 1); int32_t pid = 0; try { @@ -249,9 +216,6 @@ CXWaylandServer::~CXWaylandServer() { if (display < 0) return; - closeSocketSafely(xFDs[0]); - closeSocketSafely(xFDs[1]); - std::string lockPath = std::format("/tmp/.X{}-lock", display); safeRemove(lockPath); @@ -277,21 +241,11 @@ void CXWaylandServer::die() { if (pipeSource) wl_event_source_remove(pipeSource); - if (pipeFd >= 0) - close(pipeFd); - - closeSocketSafely(waylandFDs[0]); - closeSocketSafely(waylandFDs[1]); - closeSocketSafely(xwmFDs[0]); - closeSocketSafely(xwmFDs[1]); - // possible crash. Better to leak a bit. //if (xwaylandClient) // wl_client_destroy(xwaylandClient); xwaylandClient = nullptr; - waylandFDs = {-1, -1}; - xwmFDs = {-1, -1}; } bool CXWaylandServer::create() { @@ -307,15 +261,17 @@ bool CXWaylandServer::create() { return true; } -void CXWaylandServer::runXWayland(int notifyFD) { - if (!setCloseOnExec(xFDs[0], false) || !setCloseOnExec(xFDs[1], false) || !setCloseOnExec(waylandFDs[1], false) || !setCloseOnExec(xwmFDs[1], false)) { +void CXWaylandServer::runXWayland(CFileDescriptor& notifyFD) { + if (!xFDs[0].setFlags(xFDs[0].getFlags() & ~FD_CLOEXEC) || !xFDs[1].setFlags(xFDs[1].getFlags() & ~FD_CLOEXEC) || + !waylandFDs[1].setFlags(waylandFDs[1].getFlags() & ~FD_CLOEXEC) || !xwmFDs[1].setFlags(xwmFDs[1].getFlags() & ~FD_CLOEXEC)) { Debug::log(ERR, "Failed to unset cloexec on fds"); _exit(EXIT_FAILURE); } - auto cmd = std::format("Xwayland {} -rootless -core -listenfd {} -listenfd {} -displayfd {} -wm {}", displayName, xFDs[0], xFDs[1], notifyFD, xwmFDs[1]); + auto cmd = + std::format("Xwayland {} -rootless -core -listenfd {} -listenfd {} -displayfd {} -wm {}", displayName, xFDs[0].get(), xFDs[1].get(), notifyFD.get(), xwmFDs[1].get()); - auto waylandSocket = std::format("{}", waylandFDs[1]); + auto waylandSocket = std::format("{}", waylandFDs[1].get()); setenv("WAYLAND_SOCKET", waylandSocket.c_str(), true); Debug::log(LOG, "Starting XWayland with \"{}\", bon voyage!", cmd); @@ -327,40 +283,46 @@ void CXWaylandServer::runXWayland(int notifyFD) { } bool CXWaylandServer::start() { - idleSource = nullptr; - - if (socketpair(AF_UNIX, SOCK_STREAM, 0, waylandFDs.data()) != 0) { + idleSource = nullptr; + int wlPair[2] = {-1, -1}; + if (socketpair(AF_UNIX, SOCK_STREAM, 0, wlPair) != 0) { Debug::log(ERR, "socketpair failed (1)"); die(); return false; } + waylandFDs[0] = CFileDescriptor{wlPair[0]}; + waylandFDs[1] = CFileDescriptor{wlPair[1]}; - if (!setCloseOnExec(waylandFDs[0], true) || !setCloseOnExec(waylandFDs[1], true)) { + if (!waylandFDs[0].setFlags(waylandFDs[0].getFlags() | FD_CLOEXEC) || !waylandFDs[1].setFlags(waylandFDs[1].getFlags() | FD_CLOEXEC)) { Debug::log(ERR, "set_cloexec failed (1)"); die(); return false; } - if (socketpair(AF_UNIX, SOCK_STREAM, 0, xwmFDs.data()) != 0) { + int xwmPair[2] = {-1, -1}; + if (socketpair(AF_UNIX, SOCK_STREAM, 0, xwmPair) != 0) { Debug::log(ERR, "socketpair failed (2)"); die(); return false; } - if (!setCloseOnExec(xwmFDs[0], true) || !setCloseOnExec(xwmFDs[1], true)) { + xwmFDs[0] = CFileDescriptor{xwmPair[0]}; + xwmFDs[1] = CFileDescriptor{xwmPair[1]}; + + if (!xwmFDs[0].setFlags(xwmFDs[0].getFlags() | FD_CLOEXEC) || !xwmFDs[1].setFlags(xwmFDs[1].getFlags() | FD_CLOEXEC)) { Debug::log(ERR, "set_cloexec failed (2)"); die(); return false; } - xwaylandClient = wl_client_create(g_pCompositor->m_sWLDisplay, waylandFDs[0]); + xwaylandClient = wl_client_create(g_pCompositor->m_sWLDisplay, waylandFDs[0].get()); if (!xwaylandClient) { Debug::log(ERR, "wl_client_create failed"); die(); return false; } - waylandFDs[0] = -1; + waylandFDs[0].take(); // does this leak? int notify[2] = {-1, -1}; if (pipe(notify) < 0) { @@ -369,22 +331,20 @@ bool CXWaylandServer::start() { return false; } - if (!setCloseOnExec(notify[0], true)) { + CFileDescriptor notifyFds[2] = {CFileDescriptor{notify[0]}, CFileDescriptor{notify[1]}}; + + if (!notifyFds[0].setFlags(notifyFds[0].getFlags() | FD_CLOEXEC)) { Debug::log(ERR, "set_cloexec failed (3)"); - close(notify[0]); - close(notify[1]); die(); return false; } - pipeSource = wl_event_loop_add_fd(g_pCompositor->m_sWLEventLoop, notify[0], WL_EVENT_READABLE, ::xwaylandReady, nullptr); - pipeFd = notify[0]; + pipeSource = wl_event_loop_add_fd(g_pCompositor->m_sWLEventLoop, notifyFds[0].get(), WL_EVENT_READABLE, ::xwaylandReady, nullptr); + pipeFd = std::move(notifyFds[0]); serverPID = fork(); if (serverPID < 0) { Debug::log(ERR, "fork failed"); - close(notify[0]); - close(notify[1]); die(); return false; } else if (serverPID == 0) { @@ -393,25 +353,19 @@ bool CXWaylandServer::start() { Debug::log(ERR, "second fork failed"); _exit(1); } else if (pid == 0) - runXWayland(notify[1]); + runXWayland(notifyFds[1]); _exit(0); } - close(notify[1]); - close(waylandFDs[1]); - closeSocketSafely(xwmFDs[1]); - waylandFDs[1] = -1; - xwmFDs[1] = -1; - return true; } -int CXWaylandServer::ready(int fd, uint32_t mask) { +int CXWaylandServer::ready(CFileDescriptor fd, uint32_t mask) { if (mask & WL_EVENT_READABLE) { // xwayland writes twice char buf[64]; - ssize_t n = read(fd, buf, sizeof(buf)); + ssize_t n = read(fd.get(), buf, sizeof(buf)); if (n < 0 && errno != EINTR) { Debug::log(ERR, "Xwayland: read from displayFd failed"); mask = 0; @@ -436,7 +390,6 @@ int CXWaylandServer::ready(int fd, uint32_t mask) { Debug::log(LOG, "XWayland is ready"); - close(fd); wl_event_source_remove(pipeSource); pipeSource = nullptr; diff --git a/src/xwayland/Server.hpp b/src/xwayland/Server.hpp index 7a36a965..ccbcf6ea 100644 --- a/src/xwayland/Server.hpp +++ b/src/xwayland/Server.hpp @@ -1,6 +1,7 @@ #pragma once #include +#include #include "../helpers/signal/Signal.hpp" struct wl_event_source; @@ -19,7 +20,7 @@ class CXWaylandServer { bool start(); // called on ready - int ready(int fd, uint32_t mask); + int ready(Hyprutils::OS::CFileDescriptor fd, uint32_t mask); void die(); @@ -30,20 +31,20 @@ class CXWaylandServer { wl_client* xwaylandClient = nullptr; private: - bool tryOpenSockets(); - void runXWayland(int notifyFD); + bool tryOpenSockets(); + void runXWayland(Hyprutils::OS::CFileDescriptor& notifyFD); - pid_t serverPID = 0; + pid_t serverPID = 0; - std::string displayName; - int display = -1; - std::array xFDs = {-1, -1}; - std::array xFDReadEvents = {nullptr, nullptr}; - wl_event_source* idleSource = nullptr; - wl_event_source* pipeSource = nullptr; - int pipeFd = -1; - std::array xwmFDs = {-1, -1}; - std::array waylandFDs = {-1, -1}; + std::string displayName; + int display = -1; + std::array xFDs; + std::array xFDReadEvents = {nullptr, nullptr}; + wl_event_source* idleSource = nullptr; + wl_event_source* pipeSource = nullptr; + Hyprutils::OS::CFileDescriptor pipeFd; + std::array xwmFDs; + std::array waylandFDs; friend class CXWM; }; diff --git a/src/xwayland/XDataSource.cpp b/src/xwayland/XDataSource.cpp index 4b0c5a29..e6282dcb 100644 --- a/src/xwayland/XDataSource.cpp +++ b/src/xwayland/XDataSource.cpp @@ -5,6 +5,7 @@ #include "XDataSource.hpp" #include +using namespace Hyprutils::OS; CXDataSource::CXDataSource(SXSelection& sel_) : selection(sel_) { xcb_get_property_cookie_t cookie = xcb_get_property(g_pXWayland->pWM->connection, @@ -47,7 +48,7 @@ std::vector CXDataSource::mimes() { return mimeTypes; } -void CXDataSource::send(const std::string& mime, uint32_t fd) { +void CXDataSource::send(const std::string& mime, CFileDescriptor fd) { xcb_atom_t mimeAtom = 0; if (mime == "text/plain") @@ -65,11 +66,10 @@ void CXDataSource::send(const std::string& mime, uint32_t fd) { if (!mimeAtom) { Debug::log(ERR, "[XDataSource] mime atom not found"); - close(fd); return; } - Debug::log(LOG, "[XDataSource] send with mime {} to fd {}", mime, fd); + Debug::log(LOG, "[XDataSource] send with mime {} to fd {}", mime, fd.get()); selection.transfer = makeUnique(selection); selection.transfer->incomingWindow = xcb_generate_id(g_pXWayland->pWM->connection); @@ -81,8 +81,9 @@ void CXDataSource::send(const std::string& mime, uint32_t fd) { xcb_flush(g_pXWayland->pWM->connection); - fcntl(fd, F_SETFL, O_WRONLY | O_NONBLOCK); - selection.transfer->wlFD = fd; + //TODO: make CFileDescriptor setflags take SETFL aswell + fcntl(fd.get(), F_SETFL, O_WRONLY | O_NONBLOCK); + selection.transfer->wlFD = std::move(fd); } void CXDataSource::accepted(const std::string& mime) { @@ -101,4 +102,4 @@ eDataSourceType CXDataSource::type() { return DATA_SOURCE_TYPE_X11; } -#endif \ No newline at end of file +#endif diff --git a/src/xwayland/XDataSource.hpp b/src/xwayland/XDataSource.hpp index c629aa2a..a61ffcc9 100644 --- a/src/xwayland/XDataSource.hpp +++ b/src/xwayland/XDataSource.hpp @@ -1,6 +1,7 @@ #pragma once #include "../protocols/types/DataDevice.hpp" +#include struct SXSelection; @@ -9,7 +10,7 @@ class CXDataSource : public IDataSource { CXDataSource(SXSelection&); virtual std::vector mimes(); - virtual void send(const std::string& mime, uint32_t fd); + virtual void send(const std::string& mime, Hyprutils::OS::CFileDescriptor fd); virtual void accepted(const std::string& mime); virtual void cancelled(); virtual void error(uint32_t code, const std::string& msg); @@ -19,4 +20,4 @@ class CXDataSource : public IDataSource { SXSelection& selection; std::vector mimeTypes; // these two have shared idx std::vector mimeAtoms; // -}; \ No newline at end of file +}; diff --git a/src/xwayland/XWM.cpp b/src/xwayland/XWM.cpp index 6673105e..81900c7b 100644 --- a/src/xwayland/XWM.cpp +++ b/src/xwayland/XWM.cpp @@ -17,6 +17,7 @@ #include "../managers/SeatManager.hpp" #include "../protocols/XWaylandShell.hpp" #include "../protocols/core/Compositor.hpp" +using namespace Hyprutils::OS; #define XCB_EVENT_RESPONSE_TYPE_MASK 0x7f #define INCR_CHUNK_SIZE (64 * 1024) @@ -883,7 +884,7 @@ void CXWM::getRenderFormat() { free(reply); } -CXWM::CXWM() : connection(g_pXWayland->pServer->xwmFDs[0]) { +CXWM::CXWM() : connection(g_pXWayland->pServer->xwmFDs[0].get()) { if (connection.hasError()) { Debug::log(ERR, "[xwm] Couldn't start, error {}", connection.hasError()); @@ -901,7 +902,7 @@ CXWM::CXWM() : connection(g_pXWayland->pServer->xwmFDs[0]) { xcb_screen_iterator_t screen_iterator = xcb_setup_roots_iterator(xcb_get_setup(connection)); screen = screen_iterator.data; - eventSource = wl_event_loop_add_fd(g_pCompositor->m_sWLEventLoop, g_pXWayland->pServer->xwmFDs[0], WL_EVENT_READABLE, ::onX11Event, nullptr); + eventSource = wl_event_loop_add_fd(g_pCompositor->m_sWLEventLoop, g_pXWayland->pServer->xwmFDs[0].get(), WL_EVENT_READABLE, ::onX11Event, nullptr); wl_event_source_check(eventSource); gatherResources(); @@ -1180,13 +1181,12 @@ void CXWM::getTransferData(SXSelection& sel) { if (sel.transfer->propertyReply->type == HYPRATOMS["INCR"]) { Debug::log(ERR, "[xwm] Transfer is INCR, which we don't support :("); - close(sel.transfer->wlFD); sel.transfer.reset(); return; } else { sel.onWrite(); if (sel.transfer) - sel.transfer->eventSource = wl_event_loop_add_fd(g_pCompositor->m_sWLEventLoop, sel.transfer->wlFD, WL_EVENT_WRITABLE, ::writeDataSource, &sel); + sel.transfer->eventSource = wl_event_loop_add_fd(g_pCompositor->m_sWLEventLoop, sel.transfer->wlFD.get(), WL_EVENT_WRITABLE, ::writeDataSource, &sel); } } @@ -1361,13 +1361,13 @@ bool SXSelection::sendData(xcb_selection_request_event_t* e, std::string mime) { // the wayland client might not expect a non-blocking fd // fcntl(p[1], F_SETFL, O_NONBLOCK); - transfer->wlFD = p[0]; + transfer->wlFD = CFileDescriptor{p[0]}; Debug::log(LOG, "[xwm] sending wayland selection to xwayland with mime {}, target {}, fds {} {}", mime, e->target, p[0], p[1]); - selection->send(mime, p[1]); + selection->send(mime, CFileDescriptor{p[1]}); - transfer->eventSource = wl_event_loop_add_fd(g_pCompositor->m_sWLEventLoop, transfer->wlFD, WL_EVENT_READABLE, ::readDataSource, this); + transfer->eventSource = wl_event_loop_add_fd(g_pCompositor->m_sWLEventLoop, transfer->wlFD.get(), WL_EVENT_READABLE, ::readDataSource, this); return true; } @@ -1376,10 +1376,9 @@ int SXSelection::onWrite() { char* property = (char*)xcb_get_property_value(transfer->propertyReply); int remainder = xcb_get_property_value_length(transfer->propertyReply) - transfer->propertyStart; - ssize_t len = write(transfer->wlFD, property + transfer->propertyStart, remainder); + ssize_t len = write(transfer->wlFD.get(), property + transfer->propertyStart, remainder); if (len == -1) { Debug::log(ERR, "[xwm] write died in transfer get"); - close(transfer->wlFD); transfer.reset(); return 0; } @@ -1389,7 +1388,6 @@ int SXSelection::onWrite() { Debug::log(LOG, "[xwm] wl client read partially: len {}", len); } else { Debug::log(LOG, "[xwm] cb transfer to wl client complete, read {} bytes", len); - close(transfer->wlFD); transfer.reset(); } @@ -1397,8 +1395,6 @@ int SXSelection::onWrite() { } SXTransfer::~SXTransfer() { - if (wlFD) - close(wlFD); if (eventSource) wl_event_source_remove(eventSource); if (incomingWindow) diff --git a/src/xwayland/XWM.hpp b/src/xwayland/XWM.hpp index dfaf33b9..73a02a86 100644 --- a/src/xwayland/XWM.hpp +++ b/src/xwayland/XWM.hpp @@ -10,6 +10,7 @@ #include #include #include +#include struct wl_event_source; class CXWaylandSurfaceResource; @@ -18,25 +19,25 @@ struct SXSelection; struct SXTransfer { ~SXTransfer(); - SXSelection& selection; - bool out = true; + SXSelection& selection; + bool out = true; - bool incremental = false; - bool flushOnDelete = false; - bool propertySet = false; + bool incremental = false; + bool flushOnDelete = false; + bool propertySet = false; - int wlFD = -1; - wl_event_source* eventSource = nullptr; + Hyprutils::OS::CFileDescriptor wlFD; + wl_event_source* eventSource = nullptr; - std::vector data; + std::vector data; - xcb_selection_request_event_t request; + xcb_selection_request_event_t request; - int propertyStart; - xcb_get_property_reply_t* propertyReply; - xcb_window_t incomingWindow; + int propertyStart; + xcb_get_property_reply_t* propertyReply; + xcb_window_t incomingWindow; - bool getIncomingSelectionProp(bool erase); + bool getIncomingSelectionProp(bool erase); }; struct SXSelection { From ef03f6911694413b1b06aba727ad9ab089a511f7 Mon Sep 17 00:00:00 2001 From: nyx Date: Thu, 30 Jan 2025 16:36:42 -0500 Subject: [PATCH 0945/2181] xwayland: handle window coords correctly (#9238) --- src/desktop/Window.cpp | 19 +++++++++++-------- 1 file changed, 11 insertions(+), 8 deletions(-) diff --git a/src/desktop/Window.cpp b/src/desktop/Window.cpp index e59a8d4e..09037cbd 100644 --- a/src/desktop/Window.cpp +++ b/src/desktop/Window.cpp @@ -1706,9 +1706,15 @@ void CWindow::sendWindowSize(Vector2D size, bool force, std::optional // TODO: this should be decoupled from setWindowSize IMO Vector2D windowPos = overridePos.value_or(m_vRealPosition->goal()); - if (m_bIsX11) { - if (const auto XWAYLANDPOS = g_pXWaylandManager->waylandToXWaylandCoords(windowPos); XWAYLANDPOS != Vector2D{}) - windowPos = XWAYLANDPOS; + if (m_bIsX11 && PMONITOR) { + windowPos -= PMONITOR->vecPosition; + + if (*PXWLFORCESCALEZERO) { + windowPos *= PMONITOR->scale; + size *= PMONITOR->scale; + } + + windowPos += PMONITOR->vecXWaylandPosition; } if (!force && m_vPendingReportedSize == size && (windowPos == m_vReportedPosition || !m_bIsX11)) @@ -1716,13 +1722,10 @@ void CWindow::sendWindowSize(Vector2D size, bool force, std::optional m_vReportedPosition = windowPos; m_vPendingReportedSize = size; + m_fX11SurfaceScaledBy = 1.0f; - m_fX11SurfaceScaledBy = 1.0f; - - if (*PXWLFORCESCALEZERO && m_bIsX11 && PMONITOR) { - size *= PMONITOR->scale; + if (*PXWLFORCESCALEZERO && m_bIsX11 && PMONITOR) m_fX11SurfaceScaledBy = PMONITOR->scale; - } if (m_bIsX11 && m_pXWaylandSurface) m_pXWaylandSurface->configure({windowPos, size}); From e6a9cfab9199788ee0dcefd8b1bda46f93e6a001 Mon Sep 17 00:00:00 2001 From: Ikalco <73481042+ikalco@users.noreply.github.com> Date: Fri, 31 Jan 2025 06:23:32 -0600 Subject: [PATCH 0946/2181] monitor: preferred mode now tries first 3 modes if preferred fails before erroring (#9246) --- src/helpers/Monitor.cpp | 17 ++++++++++++++--- 1 file changed, 14 insertions(+), 3 deletions(-) diff --git a/src/helpers/Monitor.cpp b/src/helpers/Monitor.cpp index fc3de3aa..9aa6efce 100644 --- a/src/helpers/Monitor.cpp +++ b/src/helpers/Monitor.cpp @@ -435,7 +435,7 @@ bool CMonitor::applyMonitorRule(SMonitorRule* pMonitorRule, bool force) { // accumulate requested modes in reverse order (cause inesrting at front is inefficient) std::vector> requestedModes; - std::string requestedStr = "preferred"; + std::string requestedStr = "unknown"; // use sortFunc, add best 3 to requestedModes in reverse, since we test in reverse auto addBest3Modes = [&](auto const& sortFunc) { @@ -446,13 +446,24 @@ bool CMonitor::applyMonitorRule(SMonitorRule* pMonitorRule, bool force) { requestedModes.insert(requestedModes.end(), sortedModes.rbegin(), sortedModes.rend()); }; - // last fallback is preferred mode, btw this covers resolution == Vector2D() + // last fallback is always preferred mode if (!output->preferredMode()) Debug::log(ERR, "Monitor {} has NO PREFERRED MODE", output->name); else requestedModes.push_back(output->preferredMode()); - if (RULE->resolution == Vector2D(-1, -1)) { + if (RULE->resolution == Vector2D()) { + requestedStr = "preferred"; + + // fallback to first 3 modes if preferred fails/doesn't exist + requestedModes = output->modes; + if (requestedModes.size() > 3) + requestedModes.erase(requestedModes.begin() + 3, requestedModes.end()); + std::ranges::reverse(requestedModes.begin(), requestedModes.end()); + + if (output->preferredMode()) + requestedModes.push_back(output->preferredMode()); + } else if (RULE->resolution == Vector2D(-1, -1)) { requestedStr = "highrr"; // sort prioritizing refresh rate 1st and resolution 2nd, then add best 3 From ea16b64ec169afcd21020dfb819a73c37428c7f2 Mon Sep 17 00:00:00 2001 From: nyx Date: Fri, 31 Jan 2025 07:26:08 -0500 Subject: [PATCH 0947/2181] xwayland: prevent invalid window configurations for X11 apps (#9253) * fix(xwayland): prevent invalid window configurations for X11 apps * refact(xwayland): remove unneeded line --- src/desktop/Window.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/desktop/Window.cpp b/src/desktop/Window.cpp index 09037cbd..91c76e7c 100644 --- a/src/desktop/Window.cpp +++ b/src/desktop/Window.cpp @@ -1700,7 +1700,7 @@ void CWindow::sendWindowSize(Vector2D size, bool force, std::optional const auto PMONITOR = m_pMonitor.lock(); - size = size.clamp(Vector2D{0, 0}, Vector2D{std::numeric_limits::infinity(), std::numeric_limits::infinity()}); + size = size.clamp(Vector2D{1, 1}, Vector2D{std::numeric_limits::infinity(), std::numeric_limits::infinity()}); // calculate pos // TODO: this should be decoupled from setWindowSize IMO From 7d51dee103e22742d425d14faebb0273a64ac8c1 Mon Sep 17 00:00:00 2001 From: Aaron Tulino <13600347+aaronjamt@users.noreply.github.com> Date: Fri, 31 Jan 2025 05:33:36 -0700 Subject: [PATCH 0948/2181] hyprctl: Extract IPC code to separate method (#9223) This makes it possible to use the same IPC code for more projects in the future --- hyprctl/main.cpp | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/hyprctl/main.cpp b/hyprctl/main.cpp index 4cc73bdf..ac88f1da 100644 --- a/hyprctl/main.cpp +++ b/hyprctl/main.cpp @@ -225,7 +225,7 @@ int request(std::string arg, int minArgs = 0, bool needRoll = false) { return 0; } -int requestHyprpaper(std::string arg) { +int requestIPC(std::string filename, std::string arg) { const auto SERVERSOCKET = socket(AF_UNIX, SOCK_STREAM, 0); if (SERVERSOCKET < 0) { @@ -243,7 +243,7 @@ int requestHyprpaper(std::string arg) { const std::string USERID = std::to_string(getUID()); - std::string socketPath = getRuntimeDir() + "/" + instanceSignature + "/.hyprpaper.sock"; + std::string socketPath = getRuntimeDir() + "/" + instanceSignature + "/" + filename; strncpy(serverAddress.sun_path, socketPath.c_str(), sizeof(serverAddress.sun_path) - 1); @@ -278,6 +278,10 @@ int requestHyprpaper(std::string arg) { return 0; } +int requestHyprpaper(std::string arg) { + return requestIPC(".hyprpaper.sock", arg); +} + void batchRequest(std::string arg, bool json) { std::string commands = arg.substr(arg.find_first_of(' ') + 1); From ac5668192ed56c50b5612c7670e397a2128eeba6 Mon Sep 17 00:00:00 2001 From: Brayden Zee Date: Fri, 31 Jan 2025 07:33:51 -0500 Subject: [PATCH 0949/2181] desktop: fix segfault when destroying a partially create layer surface (#9247) --- src/desktop/LayerSurface.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/desktop/LayerSurface.cpp b/src/desktop/LayerSurface.cpp index e2d0177b..78dae0a9 100644 --- a/src/desktop/LayerSurface.cpp +++ b/src/desktop/LayerSurface.cpp @@ -98,7 +98,8 @@ void CLayerSurface::onDestroy() { onUnmap(); } else { Debug::log(LOG, "Removing LayerSurface that wasn't mapped."); - alpha->setValueAndWarp(0.f); + if (alpha) + alpha->setValueAndWarp(0.f); fadingOut = true; g_pCompositor->addToFadingOutSafe(self.lock()); } From 9c38287410b305503f921e411eb39686b23ccc42 Mon Sep 17 00:00:00 2001 From: Vaxry Date: Fri, 31 Jan 2025 13:32:36 +0000 Subject: [PATCH 0950/2181] groupbar: various visual improvements added rounding, round at edges, and indicator height --- src/config/ConfigDescriptions.hpp | 32 ++++++- src/config/ConfigManager.cpp | 7 +- .../decorations/CHyprGroupBarDecoration.cpp | 91 +++++++++++++++---- src/render/pass/RectPassElement.cpp | 5 + src/render/pass/RectPassElement.hpp | 1 + src/render/pass/TexPassElement.cpp | 6 +- src/render/pass/TexPassElement.hpp | 1 + 7 files changed, 121 insertions(+), 22 deletions(-) diff --git a/src/config/ConfigDescriptions.hpp b/src/config/ConfigDescriptions.hpp index 483f1f1f..01ef392e 100644 --- a/src/config/ConfigDescriptions.hpp +++ b/src/config/ConfigDescriptions.hpp @@ -883,7 +883,7 @@ inline static const std::vector CONFIG_OPTIONS = { .value = "group:groupbar:gradients", .description = "enables gradients", .type = CONFIG_OPTION_BOOL, - .data = SConfigOptionDescription::SBoolData{true}, + .data = SConfigOptionDescription::SBoolData{false}, }, SConfigOptionDescription{ .value = "group:groupbar:height", @@ -891,6 +891,12 @@ inline static const std::vector CONFIG_OPTIONS = { .type = CONFIG_OPTION_INT, .data = SConfigOptionDescription::SRangeData{14, 1, 64}, }, + SConfigOptionDescription{ + .value = "group:groupbar:indicator_height", + .description = "height of the groupbar indicator", + .type = CONFIG_OPTION_INT, + .data = SConfigOptionDescription::SRangeData{3, 1, 64}, + }, SConfigOptionDescription{ .value = "group:groupbar:stacked", .description = "render the groupbar as a vertical stack", @@ -915,6 +921,30 @@ inline static const std::vector CONFIG_OPTIONS = { .type = CONFIG_OPTION_BOOL, .data = SConfigOptionDescription::SBoolData{true}, }, + SConfigOptionDescription{ + .value = "group:groupbar:rounding", + .description = "how much to round the groupbar", + .type = CONFIG_OPTION_INT, + .data = SConfigOptionDescription::SRangeData{1, 0, 20}, + }, + SConfigOptionDescription{ + .value = "group:groupbar:gradient_rounding", + .description = "how much to round the groupbar gradient", + .type = CONFIG_OPTION_INT, + .data = SConfigOptionDescription::SRangeData{1, 0, 20}, + }, + SConfigOptionDescription{ + .value = "group:groupbar:round_only_edges", + .description = "if yes, will only round at the groupbar edges", + .type = CONFIG_OPTION_BOOL, + .data = SConfigOptionDescription::SBoolData{true}, + }, + SConfigOptionDescription{ + .value = "group:groupbar:groupbar_round_only_edges", + .description = "if yes, will only round at the groupbar gradient edges", + .type = CONFIG_OPTION_BOOL, + .data = SConfigOptionDescription::SBoolData{true}, + }, SConfigOptionDescription{ .value = "group:groupbar:text_color", .description = "controls the group bar text color", diff --git a/src/config/ConfigManager.cpp b/src/config/ConfigManager.cpp index 86581b10..e36a2914 100644 --- a/src/config/ConfigManager.cpp +++ b/src/config/ConfigManager.cpp @@ -441,13 +441,18 @@ CConfigManager::CConfigManager() { m_pConfig->addConfigValue("group:groupbar:enabled", Hyprlang::INT{1}); m_pConfig->addConfigValue("group:groupbar:font_family", {STRVAL_EMPTY}); m_pConfig->addConfigValue("group:groupbar:font_size", Hyprlang::INT{8}); - m_pConfig->addConfigValue("group:groupbar:gradients", Hyprlang::INT{1}); + m_pConfig->addConfigValue("group:groupbar:gradients", Hyprlang::INT{0}); m_pConfig->addConfigValue("group:groupbar:height", Hyprlang::INT{14}); + m_pConfig->addConfigValue("group:groupbar:indicator_height", Hyprlang::INT{3}); m_pConfig->addConfigValue("group:groupbar:priority", Hyprlang::INT{3}); m_pConfig->addConfigValue("group:groupbar:render_titles", Hyprlang::INT{1}); m_pConfig->addConfigValue("group:groupbar:scrolling", Hyprlang::INT{1}); m_pConfig->addConfigValue("group:groupbar:text_color", Hyprlang::INT{0xffffffff}); m_pConfig->addConfigValue("group:groupbar:stacked", Hyprlang::INT{0}); + m_pConfig->addConfigValue("group:groupbar:rounding", Hyprlang::INT{1}); + m_pConfig->addConfigValue("group:groupbar:gradient_rounding", Hyprlang::INT{2}); + m_pConfig->addConfigValue("group:groupbar:round_only_edges", Hyprlang::INT{1}); + m_pConfig->addConfigValue("group:groupbar:gradient_round_only_edges", Hyprlang::INT{1}); m_pConfig->addConfigValue("debug:int", Hyprlang::INT{0}); m_pConfig->addConfigValue("debug:log_damage", Hyprlang::INT{0}); diff --git a/src/render/decorations/CHyprGroupBarDecoration.cpp b/src/render/decorations/CHyprGroupBarDecoration.cpp index 88501d74..1a64b024 100644 --- a/src/render/decorations/CHyprGroupBarDecoration.cpp +++ b/src/render/decorations/CHyprGroupBarDecoration.cpp @@ -15,7 +15,6 @@ static SP m_tGradientInactive = makeShared(); static SP m_tGradientLockedActive = makeShared(); static SP m_tGradientLockedInactive = makeShared(); -constexpr int BAR_INDICATOR_HEIGHT = 3; constexpr int BAR_PADDING_OUTER_VERT = 2; constexpr int BAR_PADDING_OUTER_HORZ = 2; constexpr int BAR_TEXT_PAD = 2; @@ -30,12 +29,13 @@ CHyprGroupBarDecoration::CHyprGroupBarDecoration(PHLWINDOW pWindow) : IHyprWindo } SDecorationPositioningInfo CHyprGroupBarDecoration::getPositioningInfo() { - static auto PHEIGHT = CConfigValue("group:groupbar:height"); - static auto PENABLED = CConfigValue("group:groupbar:enabled"); - static auto PRENDERTITLES = CConfigValue("group:groupbar:render_titles"); - static auto PGRADIENTS = CConfigValue("group:groupbar:gradients"); - static auto PPRIORITY = CConfigValue("group:groupbar:priority"); - static auto PSTACKED = CConfigValue("group:groupbar:stacked"); + static auto PHEIGHT = CConfigValue("group:groupbar:height"); + static auto PINDICATORHEIGHT = CConfigValue("group:groupbar:indicator_height"); + static auto PENABLED = CConfigValue("group:groupbar:enabled"); + static auto PRENDERTITLES = CConfigValue("group:groupbar:render_titles"); + static auto PGRADIENTS = CConfigValue("group:groupbar:gradients"); + static auto PPRIORITY = CConfigValue("group:groupbar:priority"); + static auto PSTACKED = CConfigValue("group:groupbar:stacked"); SDecorationPositioningInfo info; info.policy = DECORATION_POSITION_STICKY; @@ -45,10 +45,10 @@ SDecorationPositioningInfo CHyprGroupBarDecoration::getPositioningInfo() { if (*PENABLED && m_pWindow->m_sWindowData.decorate.valueOrDefault()) { if (*PSTACKED) { - const auto ONEBARHEIGHT = BAR_PADDING_OUTER_VERT + BAR_INDICATOR_HEIGHT + (*PGRADIENTS || *PRENDERTITLES ? *PHEIGHT : 0); + const auto ONEBARHEIGHT = BAR_PADDING_OUTER_VERT + *PINDICATORHEIGHT + (*PGRADIENTS || *PRENDERTITLES ? *PHEIGHT : 0); info.desiredExtents = {{0, (ONEBARHEIGHT * m_dwGroupMembers.size()) + 2 + BAR_PADDING_OUTER_VERT}, {0, 0}}; } else - info.desiredExtents = {{0, BAR_PADDING_OUTER_VERT * 2 + BAR_INDICATOR_HEIGHT + (*PGRADIENTS || *PRENDERTITLES ? *PHEIGHT : 0) + 2}, {0, 0}}; + info.desiredExtents = {{0, BAR_PADDING_OUTER_VERT * 2 + *PINDICATORHEIGHT + (*PGRADIENTS || *PRENDERTITLES ? *PHEIGHT : 0) + 2}, {0, 0}}; } else info.desiredExtents = {{0, 0}, {0, 0}}; return info; @@ -99,19 +99,24 @@ void CHyprGroupBarDecoration::draw(PHLMONITOR pMonitor, float const& a) { // get how many bars we will draw int barsToDraw = m_dwGroupMembers.size(); - static auto PENABLED = CConfigValue("group:groupbar:enabled"); - static auto PRENDERTITLES = CConfigValue("group:groupbar:render_titles"); - static auto PTITLEFONTSIZE = CConfigValue("group:groupbar:font_size"); - static auto PHEIGHT = CConfigValue("group:groupbar:height"); - static auto PGRADIENTS = CConfigValue("group:groupbar:gradients"); - static auto PSTACKED = CConfigValue("group:groupbar:stacked"); + static auto PENABLED = CConfigValue("group:groupbar:enabled"); + static auto PRENDERTITLES = CConfigValue("group:groupbar:render_titles"); + static auto PTITLEFONTSIZE = CConfigValue("group:groupbar:font_size"); + static auto PHEIGHT = CConfigValue("group:groupbar:height"); + static auto PINDICATORHEIGHT = CConfigValue("group:groupbar:indicator_height"); + static auto PGRADIENTS = CConfigValue("group:groupbar:gradients"); + static auto PSTACKED = CConfigValue("group:groupbar:stacked"); + static auto PROUNDING = CConfigValue("group:groupbar:rounding"); + static auto PGRADIENTROUNDING = CConfigValue("group:groupbar:gradient_rounding"); + static auto PGRADIENTROUNDINGONLYEDGES = CConfigValue("group:groupbar:gradient_round_only_edges"); + static auto PROUNDONLYEDGES = CConfigValue("group:groupbar:round_only_edges"); if (!*PENABLED || !m_pWindow->m_sWindowData.decorate.valueOrDefault()) return; const auto ASSIGNEDBOX = assignedBoxGlobal(); - const auto ONEBARHEIGHT = BAR_PADDING_OUTER_VERT + BAR_INDICATOR_HEIGHT + (*PGRADIENTS || *PRENDERTITLES ? *PHEIGHT : 0); + const auto ONEBARHEIGHT = BAR_PADDING_OUTER_VERT + *PINDICATORHEIGHT + (*PGRADIENTS || *PRENDERTITLES ? *PHEIGHT : 0); m_fBarWidth = *PSTACKED ? ASSIGNEDBOX.w : (ASSIGNEDBOX.w - BAR_HORIZONTAL_PADDING * (barsToDraw - 1)) / barsToDraw; m_fBarHeight = *PSTACKED ? ((ASSIGNEDBOX.h - 2 - BAR_PADDING_OUTER_VERT) - BAR_PADDING_OUTER_VERT * (barsToDraw)) / barsToDraw : ASSIGNEDBOX.h - BAR_PADDING_OUTER_VERT; @@ -126,8 +131,8 @@ void CHyprGroupBarDecoration::draw(PHLMONITOR pMonitor, float const& a) { const auto WINDOWINDEX = *PSTACKED ? m_dwGroupMembers.size() - i - 1 : i; CBox rect = {ASSIGNEDBOX.x + floor(xoff) - pMonitor->vecPosition.x + m_pWindow->m_vFloatingOffset.x, - ASSIGNEDBOX.y + ASSIGNEDBOX.h - floor(yoff) - BAR_INDICATOR_HEIGHT - BAR_PADDING_OUTER_VERT - pMonitor->vecPosition.y + m_pWindow->m_vFloatingOffset.y, - m_fBarWidth, BAR_INDICATOR_HEIGHT}; + ASSIGNEDBOX.y + ASSIGNEDBOX.h - floor(yoff) - *PINDICATORHEIGHT - BAR_PADDING_OUTER_VERT - pMonitor->vecPosition.y + m_pWindow->m_vFloatingOffset.y, + m_fBarWidth, *PINDICATORHEIGHT}; if (rect.width <= 0 || rect.height <= 0) break; @@ -152,6 +157,30 @@ void CHyprGroupBarDecoration::draw(PHLMONITOR pMonitor, float const& a) { CRectPassElement::SRectData rectdata; rectdata.color = color; rectdata.box = rect; + if (*PROUNDING) { + if (*PROUNDONLYEDGES) { + static constexpr double PADDING = 20; + + if (i == 0 && barsToDraw == 1) + rectdata.round = *PROUNDING; + else if (i == 0) { + double first = rect.w - (*PROUNDING * 2); + rectdata.round = *PROUNDING; + rectdata.clipBox = CBox{rect.pos() - Vector2D{PADDING, 0.F}, Vector2D{first + PADDING, rect.h}}; + g_pHyprRenderer->m_sRenderPass.add(makeShared(rectdata)); + rectdata.round = 0; + rectdata.clipBox = CBox{rect.pos() + Vector2D{first, 0.F}, Vector2D{rect.w - first + PADDING, rect.h}}; + } else if (i == barsToDraw - 1) { + double first = *PROUNDING * 2; + rectdata.round = 0; + rectdata.clipBox = CBox{rect.pos() - Vector2D{PADDING, 0.F}, Vector2D{first + PADDING, rect.h}}; + g_pHyprRenderer->m_sRenderPass.add(makeShared(rectdata)); + rectdata.round = *PROUNDING; + rectdata.clipBox = CBox{rect.pos() + Vector2D{first, 0.F}, Vector2D{rect.w - first + PADDING, rect.h}}; + } + } else + rectdata.round = *PROUNDING; + } g_pHyprRenderer->m_sRenderPass.add(makeShared(rectdata)); rect = {ASSIGNEDBOX.x + floor(xoff) - pMonitor->vecPosition.x + m_pWindow->m_vFloatingOffset.x, @@ -166,6 +195,30 @@ void CHyprGroupBarDecoration::draw(PHLMONITOR pMonitor, float const& a) { CTexPassElement::SRenderData data; data.tex = GRADIENTTEX; data.box = rect; + if (*PGRADIENTROUNDING) { + if (*PGRADIENTROUNDINGONLYEDGES) { + static constexpr double PADDING = 20; + + if (i == 0 && barsToDraw == 1) + data.round = *PGRADIENTROUNDING; + else if (i == 0) { + double first = rect.w - (*PGRADIENTROUNDING * 2); + data.round = *PGRADIENTROUNDING; + data.clipBox = CBox{rect.pos() - Vector2D{PADDING, 0.F}, Vector2D{first + PADDING, rect.h}}; + g_pHyprRenderer->m_sRenderPass.add(makeShared(data)); + data.round = 0; + data.clipBox = CBox{rect.pos() + Vector2D{first, 0.F}, Vector2D{rect.w - first + PADDING, rect.h}}; + } else if (i == barsToDraw - 1) { + double first = *PGRADIENTROUNDING * 2; + data.round = 0; + data.clipBox = CBox{rect.pos() - Vector2D{PADDING, 0.F}, Vector2D{first + PADDING, rect.h}}; + g_pHyprRenderer->m_sRenderPass.add(makeShared(data)); + data.round = *PGRADIENTROUNDING; + data.clipBox = CBox{rect.pos() + Vector2D{first, 0.F}, Vector2D{rect.w - first + PADDING, rect.h}}; + } + } else + rectdata.round = *PGRADIENTROUNDING; + } g_pHyprRenderer->m_sRenderPass.add(makeShared(data)); } } @@ -229,7 +282,7 @@ CTitleTex::CTitleTex(PHLWINDOW pWindow, const Vector2D& bufferSize, const float texSize = tex->m_vSize; } -void renderGradientTo(SP tex, CGradientValueData* grad) { +static void renderGradientTo(SP tex, CGradientValueData* grad) { if (!g_pCompositor->m_pLastMonitor) return; diff --git a/src/render/pass/RectPassElement.cpp b/src/render/pass/RectPassElement.cpp index fba06286..aa024577 100644 --- a/src/render/pass/RectPassElement.cpp +++ b/src/render/pass/RectPassElement.cpp @@ -9,10 +9,15 @@ void CRectPassElement::draw(const CRegion& damage) { if (data.box.w <= 0 || data.box.h <= 0) return; + if (!data.clipBox.empty()) + g_pHyprOpenGL->m_RenderData.clipBox = data.clipBox; + if (data.color.a == 1.F || !data.blur) g_pHyprOpenGL->renderRectWithDamage(data.box, data.color, damage, data.round, data.roundingPower); else g_pHyprOpenGL->renderRectWithBlur(data.box, data.color, data.round, data.roundingPower, data.blurA, data.xray); + + g_pHyprOpenGL->m_RenderData.clipBox = {}; } bool CRectPassElement::needsLiveBlur() { diff --git a/src/render/pass/RectPassElement.hpp b/src/render/pass/RectPassElement.hpp index d27abdcc..f798dbf9 100644 --- a/src/render/pass/RectPassElement.hpp +++ b/src/render/pass/RectPassElement.hpp @@ -10,6 +10,7 @@ class CRectPassElement : public IPassElement { float roundingPower = 2.0f; bool blur = false, xray = false; float blurA = 1.F; + CBox clipBox; }; CRectPassElement(const SRectData& data); diff --git a/src/render/pass/TexPassElement.cpp b/src/render/pass/TexPassElement.cpp index c7eab292..8b577373 100644 --- a/src/render/pass/TexPassElement.cpp +++ b/src/render/pass/TexPassElement.cpp @@ -13,9 +13,13 @@ void CTexPassElement::draw(const CRegion& damage) { CScopeGuard x = {[]() { // - g_pHyprOpenGL->m_bEndFrame = false; + g_pHyprOpenGL->m_bEndFrame = false; + g_pHyprOpenGL->m_RenderData.clipBox = {}; }}; + if (!data.clipBox.empty()) + g_pHyprOpenGL->m_RenderData.clipBox = data.clipBox; + if (data.replaceProjection) g_pHyprOpenGL->m_RenderData.monitorProjection = *data.replaceProjection; g_pHyprOpenGL->renderTextureInternalWithDamage(data.tex, data.box, data.a, data.damage.empty() ? damage : data.damage, data.round, data.roundingPower, data.syncTimeline, diff --git a/src/render/pass/TexPassElement.hpp b/src/render/pass/TexPassElement.hpp index 036b89fe..6faa0872 100644 --- a/src/render/pass/TexPassElement.hpp +++ b/src/render/pass/TexPassElement.hpp @@ -19,6 +19,7 @@ class CTexPassElement : public IPassElement { SP syncTimeline; int64_t syncPoint = 0; std::optional replaceProjection; + CBox clipBox; }; CTexPassElement(const SRenderData& data); From 12b5034c99f28025e6c6be29c33bde9f4a24ac9f Mon Sep 17 00:00:00 2001 From: Mihai Fufezan Date: Fri, 31 Jan 2025 15:36:22 +0200 Subject: [PATCH 0951/2181] configWatcher: watch both symlinks and canonical paths (#9219) --- src/config/ConfigWatcher.cpp | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/src/config/ConfigWatcher.cpp b/src/config/ConfigWatcher.cpp index 8d086bac..e5db1e86 100644 --- a/src/config/ConfigWatcher.cpp +++ b/src/config/ConfigWatcher.cpp @@ -4,6 +4,7 @@ #include #include #include +#include using namespace Hyprutils::OS; @@ -43,9 +44,19 @@ void CConfigWatcher::setWatchList(const std::vector& paths) { // add new paths for (const auto& path : paths) { m_watches.emplace_back(SInotifyWatch{ - .wd = inotify_add_watch(m_inotifyFd.get(), path.c_str(), IN_MODIFY), + .wd = inotify_add_watch(m_inotifyFd.get(), path.c_str(), IN_MODIFY | IN_DONT_FOLLOW), .file = path, }); + + std::error_code ec, ec2; + const auto CANONICAL = std::filesystem::canonical(path, ec); + const auto IS_SYMLINK = std::filesystem::is_symlink(path, ec2); + if (!ec && !ec2 && IS_SYMLINK) { + m_watches.emplace_back(SInotifyWatch{ + .wd = inotify_add_watch(m_inotifyFd.get(), CANONICAL.c_str(), IN_MODIFY), + .file = path, + }); + } } } From a4b7d1c2d7538068ab4832a66f86801f5f75cc65 Mon Sep 17 00:00:00 2001 From: nyx Date: Fri, 31 Jan 2025 08:36:56 -0500 Subject: [PATCH 0952/2181] xwayland: correct pointer coordinate mismatch in X11 windows (#9259) refactor(xwayland): add back comments --- src/desktop/Window.cpp | 12 +++--------- 1 file changed, 3 insertions(+), 9 deletions(-) diff --git a/src/desktop/Window.cpp b/src/desktop/Window.cpp index 91c76e7c..0f6bac99 100644 --- a/src/desktop/Window.cpp +++ b/src/desktop/Window.cpp @@ -1697,8 +1697,7 @@ Vector2D CWindow::requestedMaxSize() { void CWindow::sendWindowSize(Vector2D size, bool force, std::optional overridePos) { static auto PXWLFORCESCALEZERO = CConfigValue("xwayland:force_zero_scaling"); - - const auto PMONITOR = m_pMonitor.lock(); + const auto PMONITOR = m_pMonitor.lock(); size = size.clamp(Vector2D{1, 1}, Vector2D{std::numeric_limits::infinity(), std::numeric_limits::infinity()}); @@ -1707,14 +1706,9 @@ void CWindow::sendWindowSize(Vector2D size, bool force, std::optional Vector2D windowPos = overridePos.value_or(m_vRealPosition->goal()); if (m_bIsX11 && PMONITOR) { - windowPos -= PMONITOR->vecPosition; - - if (*PXWLFORCESCALEZERO) { - windowPos *= PMONITOR->scale; + windowPos = g_pXWaylandManager->waylandToXWaylandCoords(windowPos); + if (*PXWLFORCESCALEZERO) size *= PMONITOR->scale; - } - - windowPos += PMONITOR->vecXWaylandPosition; } if (!force && m_vPendingReportedSize == size && (windowPos == m_vReportedPosition || !m_bIsX11)) From ddf180fa304e71b1d6eaa9f2b250a907131b05d9 Mon Sep 17 00:00:00 2001 From: nyx Date: Fri, 31 Jan 2025 11:08:43 -0500 Subject: [PATCH 0953/2181] render: enforce framebuffer offloading and remove introspection toggle (#9217) --- src/config/ConfigDescriptions.hpp | 7 -- src/config/ConfigManager.cpp | 1 - src/render/OpenGL.cpp | 147 ++---------------------------- src/render/OpenGL.hpp | 3 - src/render/pass/Pass.cpp | 4 - src/render/pass/Pass.hpp | 1 - 6 files changed, 10 insertions(+), 153 deletions(-) diff --git a/src/config/ConfigDescriptions.hpp b/src/config/ConfigDescriptions.hpp index 01ef392e..2fa86817 100644 --- a/src/config/ConfigDescriptions.hpp +++ b/src/config/ConfigDescriptions.hpp @@ -1294,13 +1294,6 @@ inline static const std::vector CONFIG_OPTIONS = { .type = CONFIG_OPTION_BOOL, .data = SConfigOptionDescription::SBoolData{true}, }, - SConfigOptionDescription{ - .value = "opengl:force_introspection", - .description = "forces introspection at all times. Introspection is aimed at reducing GPU usage in certain cases, but might cause graphical glitches on nvidia. 0 - " - "nothing, 1 - force always on, 2 - force always on if nvidia", - .type = CONFIG_OPTION_INT, - .data = SConfigOptionDescription::SRangeData{2, 0, 2}, - }, /* * render: diff --git a/src/config/ConfigManager.cpp b/src/config/ConfigManager.cpp index e36a2914..8bb6d157 100644 --- a/src/config/ConfigManager.cpp +++ b/src/config/ConfigManager.cpp @@ -619,7 +619,6 @@ CConfigManager::CConfigManager() { m_pConfig->addConfigValue("xwayland:force_zero_scaling", Hyprlang::INT{0}); m_pConfig->addConfigValue("opengl:nvidia_anti_flicker", Hyprlang::INT{1}); - m_pConfig->addConfigValue("opengl:force_introspection", Hyprlang::INT{1}); // TODO: remove this. I don't think it does us any good to disable intro. m_pConfig->addConfigValue("cursor:no_hardware_cursors", Hyprlang::INT{0}); m_pConfig->addConfigValue("cursor:no_break_fs_vrr", Hyprlang::INT{0}); diff --git a/src/render/OpenGL.cpp b/src/render/OpenGL.cpp index e4aadd63..75a5eadb 100644 --- a/src/render/OpenGL.cpp +++ b/src/render/OpenGL.cpp @@ -650,112 +650,6 @@ GLuint CHyprOpenGLImpl::compileShader(const GLuint& type, std::string src, bool return shader; } -bool CHyprOpenGLImpl::passRequiresIntrospection(PHLMONITOR pMonitor) { - // passes requiring introspection are the ones that need to render blur, - // or when we are rendering to a multigpu target - - static auto PBLUR = CConfigValue("decoration:blur:enabled"); - static auto PXRAY = CConfigValue("decoration:blur:xray"); - static auto POPTIM = CConfigValue("decoration:blur:new_optimizations"); - static auto PBLURSPECIAL = CConfigValue("decoration:blur:special"); - static auto PBLURPOPUPS = CConfigValue("decoration:blur:popups"); - - if (m_RenderData.mouseZoomFactor != 1.0 || g_pHyprRenderer->m_bCrashingInProgress) - return true; - - // mirrors should not be offloaded (as we then would basically copy the same data twice) - // yes, this breaks mirrors of mirrors - if (pMonitor->isMirror()) - return false; - - // monitors that are mirrored however must be offloaded because we cannot copy from output FBs - if (!pMonitor->mirrors.empty()) - return true; - - if (*PBLUR == 0) - return false; - - if (preBlurQueued()) - return true; - - if (!pMonitor->solitaryClient.expired()) - return false; - - for (auto const& ls : pMonitor->m_aLayerSurfaceLayers[ZWLR_LAYER_SHELL_V1_LAYER_OVERLAY]) { - const auto XRAYMODE = ls->xray == -1 ? *PXRAY : ls->xray; - if (ls->forceBlur && !XRAYMODE) - return true; - - if (ls->popupsCount() > 0 && ls->forceBlurPopups) - return true; - } - - for (auto const& ls : pMonitor->m_aLayerSurfaceLayers[ZWLR_LAYER_SHELL_V1_LAYER_TOP]) { - const auto XRAYMODE = ls->xray == -1 ? *PXRAY : ls->xray; - if (ls->forceBlur && !XRAYMODE) - return true; - - if (ls->popupsCount() > 0 && ls->forceBlurPopups) - return true; - } - - // these two block optimization - for (auto const& ls : pMonitor->m_aLayerSurfaceLayers[ZWLR_LAYER_SHELL_V1_LAYER_BACKGROUND]) { - if (ls->forceBlur) - return true; - - if (ls->popupsCount() > 0 && ls->forceBlurPopups) - return true; - } - - for (auto const& ls : pMonitor->m_aLayerSurfaceLayers[ZWLR_LAYER_SHELL_V1_LAYER_BOTTOM]) { - if (ls->forceBlur) - return true; - - if (ls->popupsCount() > 0 && ls->forceBlurPopups) - return true; - } - - if (*PBLURSPECIAL) { - for (auto const& ws : g_pCompositor->m_vWorkspaces) { - if (!ws->m_bIsSpecialWorkspace || ws->m_pMonitor != pMonitor) - continue; - - if (ws->m_fAlpha->value() == 0) - continue; - - return true; - } - } - - if (*PXRAY) - return false; - - for (auto const& w : g_pCompositor->m_vWindows) { - if (!w->m_bIsMapped || w->isHidden()) - continue; - - if (!g_pHyprRenderer->shouldRenderWindow(w)) - continue; - - if (w->popupsCount() > 0 && *PBLURPOPUPS) - return true; - - if (!w->m_bIsFloating && *POPTIM && !w->onSpecialWorkspace()) - continue; - - if (w->m_sWindowData.noBlur.valueOrDefault() || w->m_sWindowData.xray.valueOrDefault()) - continue; - - if (w->opaque()) - continue; - - return true; - } - - return false; -} - void CHyprOpenGLImpl::beginSimple(PHLMONITOR pMonitor, const CRegion& damage, SP rb, CFramebuffer* fb) { m_RenderData.pMonitor = pMonitor; @@ -811,8 +705,6 @@ void CHyprOpenGLImpl::beginSimple(PHLMONITOR pMonitor, const CRegion& damage, SP void CHyprOpenGLImpl::begin(PHLMONITOR pMonitor, const CRegion& damage_, CFramebuffer* fb, std::optional finalDamage) { m_RenderData.pMonitor = pMonitor; - static auto PFORCEINTROSPECTION = CConfigValue("opengl:force_introspection"); - #ifndef GLES2 const GLenum RESETSTATUS = glGetGraphicsResetStatus(); if (RESETSTATUS != GL_NO_ERROR) { @@ -871,30 +763,12 @@ void CHyprOpenGLImpl::begin(PHLMONITOR pMonitor, const CRegion& damage_, CFrameb applyScreenShader(*PSHADER); } - const auto PRBO = g_pHyprRenderer->getCurrentRBO(); - const bool FBPROPERSIZE = !fb || fb->m_vSize == pMonitor->vecPixelSize; - const bool USERFORCEDINTROSPECTION = *PFORCEINTROSPECTION == 1 ? true : (*PFORCEINTROSPECTION == 2 ? g_pHyprRenderer->isNvidia() : false); // 0 - no, 1 - yes, 2 - nvidia only - - if (USERFORCEDINTROSPECTION || m_RenderData.forceIntrospection || !FBPROPERSIZE || m_sFinalScreenShader.program > 0 || - (PRBO && pMonitor->vecPixelSize != PRBO->getFB()->m_vSize) || passRequiresIntrospection(pMonitor)) { - // we have to offload - // bind the offload Hypr Framebuffer - m_RenderData.pCurrentMonData->offloadFB.bind(); - m_RenderData.currentFB = &m_RenderData.pCurrentMonData->offloadFB; - m_bOffloadedFramebuffer = true; - } else { - // we can render to the rbo / fbo (fake) directly - const auto PFBO = fb ? fb : PRBO->getFB(); - m_RenderData.currentFB = PFBO; - if (PFBO->getStencilTex() != m_RenderData.pCurrentMonData->stencilTex) - PFBO->addStencil(m_RenderData.pCurrentMonData->stencilTex); - - PFBO->bind(); - m_bOffloadedFramebuffer = false; - } + m_RenderData.pCurrentMonData->offloadFB.bind(); + m_RenderData.currentFB = &m_RenderData.pCurrentMonData->offloadFB; + m_bOffloadedFramebuffer = true; m_RenderData.mainFB = m_RenderData.currentFB; - m_RenderData.outFB = fb ? fb : PRBO->getFB(); + m_RenderData.outFB = fb ? fb : g_pHyprRenderer->getCurrentRBO()->getFB(); } void CHyprOpenGLImpl::end() { @@ -952,13 +826,12 @@ void CHyprOpenGLImpl::end() { // reset our data m_RenderData.pMonitor.reset(); - m_RenderData.mouseZoomFactor = 1.f; - m_RenderData.mouseZoomUseMouse = true; - m_RenderData.forceIntrospection = false; - m_RenderData.blockScreenShader = false; - m_RenderData.currentFB = nullptr; - m_RenderData.mainFB = nullptr; - m_RenderData.outFB = nullptr; + m_RenderData.mouseZoomFactor = 1.f; + m_RenderData.mouseZoomUseMouse = true; + m_RenderData.blockScreenShader = false; + m_RenderData.currentFB = nullptr; + m_RenderData.mainFB = nullptr; + m_RenderData.outFB = nullptr; // if we dropped to offMain, release it now. // if there is a plugin constantly using it, this might be a bit slow, diff --git a/src/render/OpenGL.hpp b/src/render/OpenGL.hpp index d7abdf63..7b7b7e6f 100644 --- a/src/render/OpenGL.hpp +++ b/src/render/OpenGL.hpp @@ -126,7 +126,6 @@ struct SCurrentRenderData { float mouseZoomFactor = 1.f; bool mouseZoomUseMouse = true; // true by default bool useNearestNeighbor = false; - bool forceIntrospection = false; // cleaned in ::end() bool blockScreenShader = false; bool simplePass = false; @@ -322,8 +321,6 @@ class CHyprOpenGLImpl { void preBlurForCurrentMonitor(); - bool passRequiresIntrospection(PHLMONITOR pMonitor); - friend class CHyprRenderer; friend class CTexPassElement; friend class CPreBlurElement; diff --git a/src/render/pass/Pass.cpp b/src/render/pass/Pass.cpp index 81b918ac..5068cbbc 100644 --- a/src/render/pass/Pass.cpp +++ b/src/render/pass/Pass.cpp @@ -17,10 +17,6 @@ bool CRenderPass::single() const { return m_vPassElements.size() == 1; } -bool CRenderPass::needsIntrospection() const { - return true; -} - void CRenderPass::add(SP el) { m_vPassElements.emplace_back(makeShared(CRegion{}, el)); } diff --git a/src/render/pass/Pass.hpp b/src/render/pass/Pass.hpp index a0810155..bbc55d2c 100644 --- a/src/render/pass/Pass.hpp +++ b/src/render/pass/Pass.hpp @@ -10,7 +10,6 @@ class CRenderPass { public: bool empty() const; bool single() const; - bool needsIntrospection() const; void add(SP elem); void clear(); From d11d0697155e0896c4ab76406e6d5dcf35abff05 Mon Sep 17 00:00:00 2001 From: Mihai Fufezan Date: Sat, 1 Feb 2025 09:29:06 +0200 Subject: [PATCH 0954/2181] CI/Nix: remove deprecated magic-nix-cache-action --- .github/workflows/nix-build.yml | 1 - 1 file changed, 1 deletion(-) diff --git a/.github/workflows/nix-build.yml b/.github/workflows/nix-build.yml index a98468ac..5b2e81cf 100644 --- a/.github/workflows/nix-build.yml +++ b/.github/workflows/nix-build.yml @@ -19,7 +19,6 @@ jobs: runs-on: ubuntu-latest steps: - uses: DeterminateSystems/nix-installer-action@main - - uses: DeterminateSystems/magic-nix-cache-action@main - uses: cachix/cachix-action@v15 with: From 5b43c106bd1cde9ac0b5626130890cde4de0b245 Mon Sep 17 00:00:00 2001 From: Maximilian Seidler <78690852+PaideiaDilemma@users.noreply.github.com> Date: Sat, 1 Feb 2025 14:44:20 +0000 Subject: [PATCH 0955/2181] animation: don't immediately disconnect active vars during tick (#9272) --- CMakeLists.txt | 2 +- src/managers/AnimationManager.cpp | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index a34d677c..9c286831 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -104,7 +104,7 @@ find_package(OpenGL REQUIRED COMPONENTS ${GLES_VERSION}) pkg_check_modules(aquamarine_dep REQUIRED IMPORTED_TARGET aquamarine>=0.4.5) pkg_check_modules(hyprlang_dep REQUIRED IMPORTED_TARGET hyprlang>=0.3.2) pkg_check_modules(hyprcursor_dep REQUIRED IMPORTED_TARGET hyprcursor>=0.1.7) -pkg_check_modules(hyprutils_dep REQUIRED IMPORTED_TARGET hyprutils>=0.4.0) +pkg_check_modules(hyprutils_dep REQUIRED IMPORTED_TARGET hyprutils>=0.5.0) pkg_check_modules(hyprgraphics_dep REQUIRED IMPORTED_TARGET hyprgraphics>=0.1.1) add_compile_definitions(AQUAMARINE_VERSION="${aquamarine_dep_VERSION}") diff --git a/src/managers/AnimationManager.cpp b/src/managers/AnimationManager.cpp index 5be7aa33..29f669dc 100644 --- a/src/managers/AnimationManager.cpp +++ b/src/managers/AnimationManager.cpp @@ -43,7 +43,7 @@ CHyprAnimationManager::CHyprAnimationManager() { template static void updateVariable(CAnimatedVariable& av, const float POINTY, bool warp = false) { if (warp || av.value() == av.goal()) { - av.warp(); + av.warp(true, false); return; } @@ -53,7 +53,7 @@ static void updateVariable(CAnimatedVariable& av, const float POINTY, b static void updateColorVariable(CAnimatedVariable& av, const float POINTY, bool warp) { if (warp || av.value() == av.goal()) { - av.warp(); + av.warp(true, false); return; } From c6f672257bd2ae98f4fd7a6a273b2d1d3e944baa Mon Sep 17 00:00:00 2001 From: Vaxry Date: Sat, 1 Feb 2025 15:08:30 +0000 Subject: [PATCH 0956/2181] desktop: move popup and subsurface ctors to factories makes sure m_pSelf is set before we do anything like possibly adding children fixes #9275 supersedes #9276 --- src/desktop/LayerSurface.cpp | 7 ++--- src/desktop/LayerSurface.hpp | 2 +- src/desktop/Popup.cpp | 41 ++++++++++++++++++---------- src/desktop/Popup.hpp | 8 ++++-- src/desktop/Subsurface.cpp | 53 ++++++++++++++++++++++++------------ src/desktop/Subsurface.hpp | 10 ++++--- src/desktop/Window.cpp | 6 ++-- src/desktop/Window.hpp | 2 +- 8 files changed, 80 insertions(+), 49 deletions(-) diff --git a/src/desktop/LayerSurface.cpp b/src/desktop/LayerSurface.cpp index 78dae0a9..f4ffaedf 100644 --- a/src/desktop/LayerSurface.cpp +++ b/src/desktop/LayerSurface.cpp @@ -31,10 +31,9 @@ PHLLS CLayerSurface::create(SP resource) { pLS->szNamespace = resource->layerNamespace; - pLS->layer = resource->current.layer; - pLS->popupHead = makeUnique(pLS); - pLS->popupHead->m_pSelf = pLS->popupHead; - pLS->monitor = pMonitor; + pLS->layer = resource->current.layer; + pLS->popupHead = CPopup::create(pLS); + pLS->monitor = pMonitor; pMonitor->m_aLayerSurfaceLayers[resource->current.layer].emplace_back(pLS); pLS->forceBlur = g_pConfigManager->shouldBlurLS(pLS->szNamespace); diff --git a/src/desktop/LayerSurface.hpp b/src/desktop/LayerSurface.hpp index ab259733..f2be7459 100644 --- a/src/desktop/LayerSurface.hpp +++ b/src/desktop/LayerSurface.hpp @@ -59,7 +59,7 @@ class CLayerSurface { CBox geometry = {0, 0, 0, 0}; Vector2D position; std::string szNamespace = ""; - UP popupHead; + SP popupHead; void onDestroy(); void onMap(); diff --git a/src/desktop/Popup.cpp b/src/desktop/Popup.cpp index dea94f55..20ff49d7 100644 --- a/src/desktop/Popup.cpp +++ b/src/desktop/Popup.cpp @@ -12,23 +12,37 @@ #include "../render/OpenGL.hpp" #include -CPopup::CPopup(PHLWINDOW pOwner) : m_pWindowOwner(pOwner) { - initAllSignals(); +SP CPopup::create(PHLWINDOW pOwner) { + auto popup = SP(new CPopup()); + popup->m_pWindowOwner = pOwner; + popup->m_pSelf = popup; + popup->initAllSignals(); + return popup; } -CPopup::CPopup(PHLLS pOwner) : m_pLayerOwner(pOwner) { - initAllSignals(); +SP CPopup::create(PHLLS pOwner) { + auto popup = SP(new CPopup()); + popup->m_pLayerOwner = pOwner; + popup->m_pSelf = popup; + popup->initAllSignals(); + return popup; } -CPopup::CPopup(SP popup, WP pOwner) : - m_pWindowOwner(pOwner->m_pWindowOwner), m_pLayerOwner(pOwner->m_pLayerOwner), m_pParent(pOwner), m_pResource(popup) { - m_pWLSurface = CWLSurface::create(); - m_pWLSurface->assign(popup->surface->surface.lock(), this); +SP CPopup::create(SP resource, WP pOwner) { + auto popup = SP(new CPopup()); + popup->m_pResource = resource; + popup->m_pWindowOwner = pOwner->m_pWindowOwner; + popup->m_pLayerOwner = pOwner->m_pLayerOwner; + popup->m_pParent = pOwner; + popup->m_pSelf = popup; + popup->m_pWLSurface = CWLSurface::create(); + popup->m_pWLSurface->assign(resource->surface->surface.lock(), popup.get()); - m_vLastSize = popup->surface->current.geometry.size(); - reposition(); + popup->m_vLastSize = resource->surface->current.geometry.size(); + popup->reposition(); - initAllSignals(); + popup->initAllSignals(); + return popup; } CPopup::~CPopup() { @@ -59,7 +73,7 @@ void CPopup::initAllSignals() { } void CPopup::onNewPopup(SP popup) { - const auto& POPUP = m_vChildren.emplace_back(makeShared(popup, m_pSelf)); + const auto& POPUP = m_vChildren.emplace_back(CPopup::create(popup, m_pSelf)); POPUP->m_pSelf = POPUP; Debug::log(LOG, "New popup at {:x}", (uintptr_t)POPUP); } @@ -91,8 +105,7 @@ void CPopup::onMap() { g_pInputManager->simulateMouseMovement(); - m_pSubsurfaceHead = makeUnique(m_pSelf); - m_pSubsurfaceHead->m_pSelf = m_pSubsurfaceHead; + m_pSubsurfaceHead = CSubsurface::create(m_pSelf); //unconstrain(); sendScale(); diff --git a/src/desktop/Popup.hpp b/src/desktop/Popup.hpp index 6051f7eb..a64af7eb 100644 --- a/src/desktop/Popup.hpp +++ b/src/desktop/Popup.hpp @@ -10,11 +10,11 @@ class CXDGPopupResource; class CPopup { public: // dummy head nodes - CPopup(PHLWINDOW pOwner); - CPopup(PHLLS pOwner); + static SP create(PHLWINDOW pOwner); + static SP create(PHLLS pOwner); // real nodes - CPopup(SP popup, WP pOwner); + static SP create(SP popup, WP pOwner); ~CPopup(); @@ -45,6 +45,8 @@ class CPopup { bool m_bMapped = false; private: + CPopup() = default; + // T1 owners, each popup has to have one of these PHLWINDOWREF m_pWindowOwner; PHLLSREF m_pLayerOwner; diff --git a/src/desktop/Subsurface.cpp b/src/desktop/Subsurface.cpp index 1d938f39..33ee3553 100644 --- a/src/desktop/Subsurface.cpp +++ b/src/desktop/Subsurface.cpp @@ -7,28 +7,45 @@ #include "../render/Renderer.hpp" #include "../managers/input/InputManager.hpp" -CSubsurface::CSubsurface(PHLWINDOW pOwner) : m_pWindowParent(pOwner) { - initSignals(); - initExistingSubsurfaces(pOwner->m_pWLSurface->resource()); +UP CSubsurface::create(PHLWINDOW pOwner) { + auto subsurface = UP(new CSubsurface()); + subsurface->m_pWindowParent = pOwner; + subsurface->m_pSelf = subsurface; + + subsurface->initSignals(); + subsurface->initExistingSubsurfaces(pOwner->m_pWLSurface->resource()); + return subsurface; } -CSubsurface::CSubsurface(WP pOwner) : m_pPopupParent(pOwner) { - initSignals(); - initExistingSubsurfaces(pOwner->m_pWLSurface->resource()); +UP CSubsurface::create(WP pOwner) { + auto subsurface = UP(new CSubsurface()); + subsurface->m_pPopupParent = pOwner; + subsurface->m_pSelf = subsurface; + subsurface->initSignals(); + subsurface->initExistingSubsurfaces(pOwner->m_pWLSurface->resource()); + return subsurface; } -CSubsurface::CSubsurface(SP pSubsurface, PHLWINDOW pOwner) : m_pSubsurface(pSubsurface), m_pWindowParent(pOwner) { - m_pWLSurface = CWLSurface::create(); - m_pWLSurface->assign(pSubsurface->surface.lock(), this); - initSignals(); - initExistingSubsurfaces(pSubsurface->surface.lock()); +UP CSubsurface::create(SP pSubsurface, PHLWINDOW pOwner) { + auto subsurface = UP(new CSubsurface()); + subsurface->m_pWindowParent = pOwner; + subsurface->m_pSelf = subsurface; + subsurface->m_pWLSurface = CWLSurface::create(); + subsurface->m_pWLSurface->assign(pSubsurface->surface.lock(), subsurface.get()); + subsurface->initSignals(); + subsurface->initExistingSubsurfaces(pSubsurface->surface.lock()); + return subsurface; } -CSubsurface::CSubsurface(SP pSubsurface, WP pOwner) : m_pSubsurface(pSubsurface), m_pPopupParent(pOwner) { - m_pWLSurface = CWLSurface::create(); - m_pWLSurface->assign(pSubsurface->surface.lock(), this); - initSignals(); - initExistingSubsurfaces(pSubsurface->surface.lock()); +UP CSubsurface::create(SP pSubsurface, WP pOwner) { + auto subsurface = UP(new CSubsurface()); + subsurface->m_pPopupParent = pOwner; + subsurface->m_pSelf = subsurface; + subsurface->m_pWLSurface = CWLSurface::create(); + subsurface->m_pWLSurface->assign(pSubsurface->surface.lock(), subsurface.get()); + subsurface->initSignals(); + subsurface->initExistingSubsurfaces(pSubsurface->surface.lock()); + return subsurface; } void CSubsurface::initSignals() { @@ -131,9 +148,9 @@ void CSubsurface::onNewSubsurface(SP pSubsurface) { WP PSUBSURFACE; if (!m_pWindowParent.expired()) - PSUBSURFACE = m_vChildren.emplace_back(makeUnique(pSubsurface, m_pWindowParent.lock())); + PSUBSURFACE = m_vChildren.emplace_back(CSubsurface::create(pSubsurface, m_pWindowParent.lock())); else if (m_pPopupParent) - PSUBSURFACE = m_vChildren.emplace_back(makeUnique(pSubsurface, m_pPopupParent)); + PSUBSURFACE = m_vChildren.emplace_back(CSubsurface::create(pSubsurface, m_pPopupParent)); PSUBSURFACE->m_pSelf = PSUBSURFACE; diff --git a/src/desktop/Subsurface.hpp b/src/desktop/Subsurface.hpp index 41958671..2983c7c1 100644 --- a/src/desktop/Subsurface.hpp +++ b/src/desktop/Subsurface.hpp @@ -10,12 +10,12 @@ class CWLSubsurfaceResource; class CSubsurface { public: // root dummy nodes - CSubsurface(PHLWINDOW pOwner); - CSubsurface(WP pOwner); + static UP create(PHLWINDOW pOwner); + static UP create(WP pOwner); // real nodes - CSubsurface(SP pSubsurface, PHLWINDOW pOwner); - CSubsurface(SP pSubsurface, WP pOwner); + static UP create(SP pSubsurface, PHLWINDOW pOwner); + static UP create(SP pSubsurface, WP pOwner); ~CSubsurface() = default; @@ -37,6 +37,8 @@ class CSubsurface { WP m_pSelf; private: + CSubsurface() = default; + struct { CHyprSignalListener destroySubsurface; CHyprSignalListener commitSubsurface; diff --git a/src/desktop/Window.cpp b/src/desktop/Window.cpp index 0f6bac99..6e580e49 100644 --- a/src/desktop/Window.cpp +++ b/src/desktop/Window.cpp @@ -571,10 +571,8 @@ void CWindow::onMap() { if (m_bIsX11) return; - m_pSubsurfaceHead = makeUnique(m_pSelf.lock()); - m_pSubsurfaceHead->m_pSelf = m_pSubsurfaceHead; - m_pPopupHead = makeUnique(m_pSelf.lock()); - m_pPopupHead->m_pSelf = m_pPopupHead; + m_pSubsurfaceHead = CSubsurface::create(m_pSelf.lock()); + m_pPopupHead = CPopup::create(m_pSelf.lock()); } void CWindow::onBorderAngleAnimEnd(WP pav) { diff --git a/src/desktop/Window.hpp b/src/desktop/Window.hpp index ce2f8eb2..3573d7ab 100644 --- a/src/desktop/Window.hpp +++ b/src/desktop/Window.hpp @@ -298,7 +298,7 @@ class CWindow { // desktop components UP m_pSubsurfaceHead; - UP m_pPopupHead; + SP m_pPopupHead; // Animated border CGradientValueData m_cRealBorderColor = {0}; From 88adae73ba3b57490fdef1041f58fcc6a15a54c8 Mon Sep 17 00:00:00 2001 From: Vaxry Date: Sat, 1 Feb 2025 15:31:31 +0000 Subject: [PATCH 0957/2181] pass: add input region debug --- src/render/pass/Pass.cpp | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/src/render/pass/Pass.cpp b/src/render/pass/Pass.cpp index 5068cbbc..60c1bc30 100644 --- a/src/render/pass/Pass.cpp +++ b/src/render/pass/Pass.cpp @@ -8,6 +8,7 @@ #include "../../managers/eventLoop/EventLoopManager.hpp" #include "../../render/Renderer.hpp" #include "../../Compositor.hpp" +#include "../../protocols/core/Compositor.hpp" bool CRenderPass::empty() const { return false; @@ -242,6 +243,22 @@ void CRenderPass::renderDebugData() { if (g_pCompositor->m_pLastWindow) renderHLSurface(debugData.lastWindowText, g_pCompositor->m_pLastWindow->m_pWLSurface->resource(), Colors::LIGHT_BLUE.modifyA(0.1F)); + if (g_pSeatManager->state.pointerFocus) { + if (g_pSeatManager->state.pointerFocus->current.input.intersect(CBox{{}, g_pSeatManager->state.pointerFocus->current.size}).getExtents().size() != + g_pSeatManager->state.pointerFocus->current.size) { + auto hlSurface = CWLSurface::fromResource(g_pSeatManager->state.pointerFocus.lock()); + if (hlSurface) { + auto BOX = hlSurface->getSurfaceBoxGlobal(); + if (BOX) { + auto region = g_pSeatManager->state.pointerFocus->current.input.copy() + .scale(g_pHyprOpenGL->m_RenderData.pMonitor->scale) + .translate(BOX->pos() - g_pHyprOpenGL->m_RenderData.pMonitor->vecPosition); + g_pHyprOpenGL->renderRectWithDamage(box, CHyprColor{0.8F, 0.8F, 0.2F, 0.4F}, region); + } + } + } + } + const auto DISCARDED_ELEMENTS = std::count_if(m_vPassElements.begin(), m_vPassElements.end(), [](const auto& e) { return e->discard; }); auto tex = g_pHyprOpenGL->renderText(std::format("occlusion layers: {}\npass elements: {} ({} discarded)\nviewport: {:X0}", occludedRegions.size(), m_vPassElements.size(), DISCARDED_ELEMENTS, g_pHyprOpenGL->m_RenderData.pMonitor->vecPixelSize), From e380b6ed66aceeae8fde84b4baed0d91550e9f4c Mon Sep 17 00:00:00 2001 From: Vaxry Date: Sat, 1 Feb 2025 15:49:10 +0000 Subject: [PATCH 0958/2181] popup: take xdg geometry into account in input calcs fixes #9023 --- src/desktop/Popup.cpp | 12 +++++++----- src/protocols/core/Compositor.cpp | 4 +--- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/src/desktop/Popup.cpp b/src/desktop/Popup.cpp index 20ff49d7..e66cebcd 100644 --- a/src/desktop/Popup.cpp +++ b/src/desktop/Popup.cpp @@ -339,22 +339,24 @@ void CPopup::breadthfirst(std::function, void*)> fn, void* data) WP CPopup::at(const Vector2D& globalCoords, bool allowsInput) { std::vector> popups; - breadthfirst([](WP popup, void* data) { ((std::vector>*)data)->push_back(popup); }, &popups); + breadthfirst([&popups](WP popup, void* data) { popups.push_back(popup); }, &popups); for (auto const& p : popups | std::views::reverse) { if (!p->m_pResource || !p->m_bMapped) continue; if (!allowsInput) { - const Vector2D offset = p->m_pResource ? (p->size() - p->m_pResource->geometry.size()) / 2.F : Vector2D{}; - const Vector2D size = p->m_pResource ? p->m_pResource->geometry.size() : p->size(); + const Vector2D offset = + p->m_pResource && p->m_pResource->surface ? (p->size() - p->m_pResource->geometry.size()) / 2.F - p->m_pResource->surface->current.geometry.pos() : Vector2D{}; + const Vector2D size = p->m_pResource ? p->m_pResource->geometry.size() : p->size(); const auto BOX = CBox{p->coordsGlobal() + offset, size}; if (BOX.containsPoint(globalCoords)) return p; } else { - const Vector2D offset = p->m_pResource ? (p->size() - p->m_pResource->geometry.size()) / 2.F : Vector2D{}; - const auto REGION = + const Vector2D offset = + p->m_pResource && p->m_pResource->surface ? (p->size() - p->m_pResource->geometry.size()) / 2.F - p->m_pResource->surface->current.geometry.pos() : Vector2D{}; + const auto REGION = CRegion{p->m_pWLSurface->resource()->current.input}.intersect(CBox{{}, p->m_pWLSurface->resource()->current.size}).translate(p->coordsGlobal() + offset); if (REGION.containsPoint(globalCoords)) return p; diff --git a/src/protocols/core/Compositor.cpp b/src/protocols/core/Compositor.cpp index 93683993..92c3c425 100644 --- a/src/protocols/core/Compositor.cpp +++ b/src/protocols/core/Compositor.cpp @@ -308,9 +308,7 @@ void CWLSurfaceResource::breadthfirst(std::function, std::pair, Vector2D> CWLSurfaceResource::at(const Vector2D& localCoords, bool allowsInput) { std::vector, Vector2D>> surfs; - breadthfirst([](SP surf, const Vector2D& offset, - void* data) { ((std::vector, Vector2D>>*)data)->emplace_back(std::make_pair<>(surf, offset)); }, - &surfs); + breadthfirst([&surfs](SP surf, const Vector2D& offset, void* data) { surfs.emplace_back(std::make_pair<>(surf, offset)); }, &surfs); for (auto const& [surf, pos] : surfs | std::views::reverse) { if (!allowsInput) { From 64fefa3749868e6170b6275963c6528456a7d9f2 Mon Sep 17 00:00:00 2001 From: Vaxry Date: Sat, 1 Feb 2025 19:10:19 +0000 Subject: [PATCH 0959/2181] desktop: move popups to UPs and fix missing subsurface resource fixes #9283 --- src/desktop/LayerSurface.hpp | 2 +- src/desktop/Popup.cpp | 15 ++++++++------- src/desktop/Popup.hpp | 8 ++++---- src/desktop/Subsurface.cpp | 2 ++ src/desktop/Window.hpp | 2 +- 5 files changed, 16 insertions(+), 13 deletions(-) diff --git a/src/desktop/LayerSurface.hpp b/src/desktop/LayerSurface.hpp index f2be7459..ab259733 100644 --- a/src/desktop/LayerSurface.hpp +++ b/src/desktop/LayerSurface.hpp @@ -59,7 +59,7 @@ class CLayerSurface { CBox geometry = {0, 0, 0, 0}; Vector2D position; std::string szNamespace = ""; - SP popupHead; + UP popupHead; void onDestroy(); void onMap(); diff --git a/src/desktop/Popup.cpp b/src/desktop/Popup.cpp index e66cebcd..4accb58f 100644 --- a/src/desktop/Popup.cpp +++ b/src/desktop/Popup.cpp @@ -12,24 +12,24 @@ #include "../render/OpenGL.hpp" #include -SP CPopup::create(PHLWINDOW pOwner) { - auto popup = SP(new CPopup()); +UP CPopup::create(PHLWINDOW pOwner) { + auto popup = UP(new CPopup()); popup->m_pWindowOwner = pOwner; popup->m_pSelf = popup; popup->initAllSignals(); return popup; } -SP CPopup::create(PHLLS pOwner) { - auto popup = SP(new CPopup()); +UP CPopup::create(PHLLS pOwner) { + auto popup = UP(new CPopup()); popup->m_pLayerOwner = pOwner; popup->m_pSelf = popup; popup->initAllSignals(); return popup; } -SP CPopup::create(SP resource, WP pOwner) { - auto popup = SP(new CPopup()); +UP CPopup::create(SP resource, WP pOwner) { + auto popup = UP(new CPopup()); popup->m_pResource = resource; popup->m_pWindowOwner = pOwner->m_pWindowOwner; popup->m_pLayerOwner = pOwner->m_pLayerOwner; @@ -282,7 +282,8 @@ void CPopup::recheckTree() { } void CPopup::recheckChildrenRecursive() { - auto cpy = m_vChildren; + std::vector> cpy; + std::ranges::for_each(m_vChildren, [&cpy](const auto& el) { cpy.emplace_back(el); }); for (auto const& c : cpy) { c->onCommit(true); c->recheckChildrenRecursive(); diff --git a/src/desktop/Popup.hpp b/src/desktop/Popup.hpp index a64af7eb..0bca436c 100644 --- a/src/desktop/Popup.hpp +++ b/src/desktop/Popup.hpp @@ -10,11 +10,11 @@ class CXDGPopupResource; class CPopup { public: // dummy head nodes - static SP create(PHLWINDOW pOwner); - static SP create(PHLLS pOwner); + static UP create(PHLWINDOW pOwner); + static UP create(PHLLS pOwner); // real nodes - static SP create(SP popup, WP pOwner); + static UP create(SP popup, WP pOwner); ~CPopup(); @@ -64,7 +64,7 @@ class CPopup { bool m_bInert = false; // - std::vector> m_vChildren; + std::vector> m_vChildren; UP m_pSubsurfaceHead; struct { diff --git a/src/desktop/Subsurface.cpp b/src/desktop/Subsurface.cpp index 33ee3553..db106a09 100644 --- a/src/desktop/Subsurface.cpp +++ b/src/desktop/Subsurface.cpp @@ -29,6 +29,7 @@ UP CSubsurface::create(WP pOwner) { UP CSubsurface::create(SP pSubsurface, PHLWINDOW pOwner) { auto subsurface = UP(new CSubsurface()); subsurface->m_pWindowParent = pOwner; + subsurface->m_pSubsurface = pSubsurface; subsurface->m_pSelf = subsurface; subsurface->m_pWLSurface = CWLSurface::create(); subsurface->m_pWLSurface->assign(pSubsurface->surface.lock(), subsurface.get()); @@ -40,6 +41,7 @@ UP CSubsurface::create(SP pSubsurface, PHLWI UP CSubsurface::create(SP pSubsurface, WP pOwner) { auto subsurface = UP(new CSubsurface()); subsurface->m_pPopupParent = pOwner; + subsurface->m_pSubsurface = pSubsurface; subsurface->m_pSelf = subsurface; subsurface->m_pWLSurface = CWLSurface::create(); subsurface->m_pWLSurface->assign(pSubsurface->surface.lock(), subsurface.get()); diff --git a/src/desktop/Window.hpp b/src/desktop/Window.hpp index 3573d7ab..ce2f8eb2 100644 --- a/src/desktop/Window.hpp +++ b/src/desktop/Window.hpp @@ -298,7 +298,7 @@ class CWindow { // desktop components UP m_pSubsurfaceHead; - SP m_pPopupHead; + UP m_pPopupHead; // Animated border CGradientValueData m_cRealBorderColor = {0}; From 97a24ec6f3abd2b2ce4c2e00627679a2713848dd Mon Sep 17 00:00:00 2001 From: micha4w Date: Sun, 2 Feb 2025 12:39:32 +0100 Subject: [PATCH 0960/2181] Nix: change meson buildtype from debugoptimized to debug --- nix/default.nix | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/nix/default.nix b/nix/default.nix index a4ddc63b..6a703713 100644 --- a/nix/default.nix +++ b/nix/default.nix @@ -155,7 +155,7 @@ in mesonBuildType = if debug - then "debugoptimized" + then "debug" else "release"; mesonFlags = flatten [ From 373108102c85f9568a8f28b7a85c5500634ca9a4 Mon Sep 17 00:00:00 2001 From: outfoxxed Date: Sun, 2 Feb 2025 09:31:04 -0800 Subject: [PATCH 0961/2181] protocols: implement hyprland-ctm-control rev 2 (#9267) * protocols: implement hyprland-ctm-control v2 * bump h-p and nix --- CMakeLists.txt | 2 +- flake.lock | 24 ++++++++++++------------ protocols/meson.build | 2 +- src/managers/ProtocolManager.cpp | 2 +- src/protocols/CTMControl.cpp | 22 +++++++++++++++++++++- src/protocols/CTMControl.hpp | 5 ++++- subprojects/hyprland-protocols | 2 +- 7 files changed, 41 insertions(+), 18 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 9c286831..34e9a8ed 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -304,7 +304,7 @@ endfunction() target_link_libraries(Hyprland OpenGL::EGL OpenGL::GL Threads::Threads) -pkg_check_modules(hyprland_protocols_dep hyprland-protocols>=0.6.0) +pkg_check_modules(hyprland_protocols_dep hyprland-protocols>=0.6.2) if(hyprland_protocols_dep_FOUND) pkg_get_variable(HYPRLAND_PROTOCOLS hyprland-protocols pkgdatadir) message(STATUS "hyprland-protocols dependency set to ${HYPRLAND_PROTOCOLS}") diff --git a/flake.lock b/flake.lock index dfdd8c5b..7637a2c7 100644 --- a/flake.lock +++ b/flake.lock @@ -16,11 +16,11 @@ ] }, "locked": { - "lastModified": 1738183445, - "narHash": "sha256-C1He3N1SA8D2u+TSlldbA9wiYwDvXI4GxX3zKaeD7qU=", + "lastModified": 1738456976, + "narHash": "sha256-cufyHbOMnSt9V4w4OVSzNcpJ+8DwzRZRJaca2Q89KVI=", "owner": "hyprwm", "repo": "aquamarine", - "rev": "48a000cf35dd10bfeb231152735aebbe875f4b74", + "rev": "257b2050790ab3b1eb389e0f8bdc400eb9510139", "type": "github" }, "original": { @@ -105,11 +105,11 @@ ] }, "locked": { - "lastModified": 1738018829, - "narHash": "sha256-5Ol5iahMlELx3lWuChyZsqqLk6sP6aqaJCJFw92OZGo=", + "lastModified": 1738437059, + "narHash": "sha256-J+8ecqaP3zD9GHeN8Y4hUapoELSoggp0IZI8laTFt/0=", "owner": "hyprwm", "repo": "hyprgraphics", - "rev": "12cd7034e441a5ebfdef1a090c0788413b4a635b", + "rev": "5ac80e3686a4dfa55d2bd15c81a266b89594a295", "type": "github" }, "original": { @@ -128,11 +128,11 @@ ] }, "locked": { - "lastModified": 1737556638, - "narHash": "sha256-laKgI3mr2qz6tas/q3tuGPxMdsGhBi/w+HO+hO2f1AY=", + "lastModified": 1738422629, + "narHash": "sha256-5v+bv75wJWvahyM2xcMTSNNxmV8a7hb01Eey5zYnBJw=", "owner": "hyprwm", "repo": "hyprland-protocols", - "rev": "4c75dd5c015c8a0e5a34c6d02a018a650f57feb5", + "rev": "755aef8dab49d0fc4663c715fa4ad221b2aedaed", "type": "github" }, "original": { @@ -276,11 +276,11 @@ }, "nixpkgs": { "locked": { - "lastModified": 1737885589, - "narHash": "sha256-Zf0hSrtzaM1DEz8//+Xs51k/wdSajticVrATqDrfQjg=", + "lastModified": 1738410390, + "narHash": "sha256-xvTo0Aw0+veek7hvEVLzErmJyQkEcRk6PSR4zsRQFEc=", "owner": "NixOS", "repo": "nixpkgs", - "rev": "852ff1d9e153d8875a83602e03fdef8a63f0ecf8", + "rev": "3a228057f5b619feb3186e986dbe76278d707b6e", "type": "github" }, "original": { diff --git a/protocols/meson.build b/protocols/meson.build index aa20940d..6ed1b11a 100644 --- a/protocols/meson.build +++ b/protocols/meson.build @@ -7,7 +7,7 @@ wayland_protos = dependency( hyprland_protos = dependency( 'hyprland-protocols', - version: '>=0.6', + version: '>=0.6.2', fallback: 'hyprland-protocols', ) diff --git a/src/managers/ProtocolManager.cpp b/src/managers/ProtocolManager.cpp index d3270fe2..62736ae5 100644 --- a/src/managers/ProtocolManager.cpp +++ b/src/managers/ProtocolManager.cpp @@ -167,7 +167,7 @@ CProtocolManager::CProtocolManager() { PROTO::xdgDialog = makeUnique(&xdg_dialog_v1_interface, 1, "XDGDialog"); PROTO::singlePixel = makeUnique(&wp_single_pixel_buffer_manager_v1_interface, 1, "SinglePixel"); PROTO::securityContext = makeUnique(&wp_security_context_manager_v1_interface, 1, "SecurityContext"); - PROTO::ctm = makeUnique(&hyprland_ctm_control_manager_v1_interface, 1, "CTMControl"); + PROTO::ctm = makeUnique(&hyprland_ctm_control_manager_v1_interface, 2, "CTMControl"); PROTO::hyprlandSurface = makeUnique(&hyprland_surface_manager_v1_interface, 2, "HyprlandSurface"); if (*PENABLEXXCM) { diff --git a/src/protocols/CTMControl.cpp b/src/protocols/CTMControl.cpp index 5560271f..322f95e2 100644 --- a/src/protocols/CTMControl.cpp +++ b/src/protocols/CTMControl.cpp @@ -15,6 +15,9 @@ CHyprlandCTMControlResource::CHyprlandCTMControlResource(SPsetSetCtmForOutput([this](CHyprlandCtmControlManagerV1* r, wl_resource* output, wl_fixed_t mat0, wl_fixed_t mat1, wl_fixed_t mat2, wl_fixed_t mat3, wl_fixed_t mat4, wl_fixed_t mat5, wl_fixed_t mat6, wl_fixed_t mat7, wl_fixed_t mat8) { + if (blocked) + return; + const auto OUTPUTRESOURCE = CWLOutputResource::fromResource(output); if UNLIKELY (!OUTPUTRESOURCE) @@ -41,6 +44,9 @@ CHyprlandCTMControlResource::CHyprlandCTMControlResource(SPsetCommit([this](CHyprlandCtmControlManagerV1* r) { + if (blocked) + return; + LOGM(LOG, "Committing ctms to outputs"); for (auto& m : g_pCompositor->m_vMonitors) { @@ -54,7 +60,17 @@ CHyprlandCTMControlResource::CHyprlandCTMControlResource(SPversion() >= 2) + resource->sendBlocked(); +} + CHyprlandCTMControlResource::~CHyprlandCTMControlResource() { + if (blocked) + return; + for (auto& m : g_pCompositor->m_vMonitors) { PROTO::ctm->setCTM(m, Mat3x3::identity()); } @@ -69,7 +85,6 @@ CHyprlandCTMControlProtocol::CHyprlandCTMControlProtocol(const wl_interface* ifa } void CHyprlandCTMControlProtocol::bindManager(wl_client* client, void* data, uint32_t ver, uint32_t id) { - const auto RESOURCE = m_vManagers.emplace_back(makeShared(makeShared(client, ver, id))); if UNLIKELY (!RESOURCE->good()) { @@ -78,6 +93,11 @@ void CHyprlandCTMControlProtocol::bindManager(wl_client* client, void* data, uin return; } + if (m_pManager) + RESOURCE->block(); + else + m_pManager = RESOURCE; + LOGM(LOG, "New CTM Manager at 0x{:x}", (uintptr_t)RESOURCE.get()); } diff --git a/src/protocols/CTMControl.hpp b/src/protocols/CTMControl.hpp index 2c168acd..eb54a3aa 100644 --- a/src/protocols/CTMControl.hpp +++ b/src/protocols/CTMControl.hpp @@ -16,11 +16,13 @@ class CHyprlandCTMControlResource { ~CHyprlandCTMControlResource(); bool good(); + void block(); private: SP resource; std::unordered_map ctms; + bool blocked = false; }; class CHyprlandCTMControlProtocol : public IWaylandProtocol { @@ -37,6 +39,7 @@ class CHyprlandCTMControlProtocol : public IWaylandProtocol { // std::vector> m_vManagers; + WP m_pManager; // struct SCTMData { @@ -51,4 +54,4 @@ class CHyprlandCTMControlProtocol : public IWaylandProtocol { namespace PROTO { inline UP ctm; -}; \ No newline at end of file +}; diff --git a/subprojects/hyprland-protocols b/subprojects/hyprland-protocols index 4c75dd5c..755aef8d 160000 --- a/subprojects/hyprland-protocols +++ b/subprojects/hyprland-protocols @@ -1 +1 @@ -Subproject commit 4c75dd5c015c8a0e5a34c6d02a018a650f57feb5 +Subproject commit 755aef8dab49d0fc4663c715fa4ad221b2aedaed From 70d94fec134c4b91916812901310e7765acf8405 Mon Sep 17 00:00:00 2001 From: Alexander <51529891+Truenya@users.noreply.github.com> Date: Sun, 2 Feb 2025 20:34:26 +0300 Subject: [PATCH 0962/2181] refactor: clang-tidy in compositor (#9241) Co-authored-by: Alexandr Krylov --- src/Compositor.cpp | 90 ++++++++++++++------------------- src/Compositor.hpp | 5 +- src/macros.hpp | 3 +- src/managers/KeybindManager.cpp | 2 - 4 files changed, 40 insertions(+), 60 deletions(-) diff --git a/src/Compositor.cpp b/src/Compositor.cpp index 1daccbfd..6a241472 100644 --- a/src/Compositor.cpp +++ b/src/Compositor.cpp @@ -1,3 +1,4 @@ +#include #include #include "Compositor.hpp" @@ -21,14 +22,12 @@ #include #include #include -#include #include #include "debug/HyprCtl.hpp" #include "debug/CrashReporter.hpp" #ifdef USES_SYSTEMD #include // for SdNotify #endif -#include "helpers/varlist/VarList.hpp" #include "helpers/fs/FsUtils.hpp" #include "protocols/FractionalScale.hpp" #include "protocols/PointerConstraints.hpp" @@ -264,7 +263,6 @@ static bool filterGlobals(const wl_client* client, const wl_global* global, void // void CCompositor::initServer(std::string socketName, int socketFd) { - if (m_bOnlyConfigVerification) { g_pHookSystem = makeUnique(); g_pKeybindManager = makeUnique(); @@ -500,7 +498,7 @@ void CCompositor::cleanEnvironment() { "dbus-update-activation-environment 2>/dev/null && " #endif "dbus-update-activation-environment --systemd WAYLAND_DISPLAY XDG_CURRENT_DESKTOP HYPRLAND_INSTANCE_SIGNATURE QT_QPA_PLATFORMTHEME PATH XDG_DATA_DIRS"; - g_pKeybindManager->spawn(CMD); + CKeybindManager::spawn(CMD); } } @@ -738,7 +736,7 @@ void CCompositor::startCompositor() { "dbus-update-activation-environment 2>/dev/null && " #endif "dbus-update-activation-environment --systemd WAYLAND_DISPLAY XDG_CURRENT_DESKTOP HYPRLAND_INSTANCE_SIGNATURE QT_QPA_PLATFORMTHEME PATH XDG_DATA_DIRS"; - g_pKeybindManager->spawn(CMD); + CKeybindManager::spawn(CMD); } Debug::log(LOG, "Running on WAYLAND_DISPLAY: {}", m_szWLDisplaySocket); @@ -839,12 +837,7 @@ void CCompositor::removeWindowFromVectorSafe(PHLWINDOW pWindow) { } bool CCompositor::monitorExists(PHLMONITOR pMonitor) { - for (auto const& m : m_vRealMonitors) { - if (m == pMonitor) - return true; - } - - return false; + return std::ranges::any_of(m_vRealMonitors, [&](const PHLMONITOR& m) { return m == pMonitor; }); } PHLWINDOW CCompositor::vectorToWindowUnified(const Vector2D& pos, uint8_t properties, PHLWINDOW pIgnoreWindow) { @@ -1175,8 +1168,8 @@ void CCompositor::focusWindow(PHLWINDOW pWindow, SP pSurface pWindow->m_bIsUrgent = false; // Send an event - g_pEventManager->postEvent(SHyprIPCEvent{"activewindow", pWindow->m_szClass + "," + pWindow->m_szTitle}); - g_pEventManager->postEvent(SHyprIPCEvent{"activewindowv2", std::format("{:x}", (uintptr_t)pWindow.get())}); + g_pEventManager->postEvent(SHyprIPCEvent{.event = "activewindow", .data = pWindow->m_szClass + "," + pWindow->m_szTitle}); + g_pEventManager->postEvent(SHyprIPCEvent{.event = "activewindowv2", .data = std::format("{:x}", (uintptr_t)pWindow.get())}); EMIT_HOOK_EVENT("activeWindow", pWindow); @@ -1217,8 +1210,8 @@ void CCompositor::focusSurface(SP pSurface, PHLWINDOW pWindo if (!pSurface) { g_pSeatManager->setKeyboardFocus(nullptr); - g_pEventManager->postEvent(SHyprIPCEvent{"activewindow", ","}); // unfocused - g_pEventManager->postEvent(SHyprIPCEvent{"activewindowv2", ""}); + g_pEventManager->postEvent(SHyprIPCEvent{.event = "activewindow", .data = ","}); + g_pEventManager->postEvent(SHyprIPCEvent{.event = "activewindowv2", .data = ""}); EMIT_HOOK_EVENT("keyboardFocus", (SP)nullptr); m_pLastFocus.reset(); return; @@ -1395,7 +1388,7 @@ void CCompositor::changeWindowZOrder(PHLWINDOW pWindow, bool top) { toMove.insert(toMove.begin(), pw); for (auto const& w : m_vWindows) { - if (w->m_bIsMapped && !w->isHidden() && w->m_bIsX11 && w->x11TransientFor() == pw && w != pw && std::find(toMove.begin(), toMove.end(), w) == toMove.end()) { + if (w->m_bIsMapped && !w->isHidden() && w->m_bIsX11 && w->x11TransientFor() == pw && w != pw && std::ranges::find(toMove, w) == toMove.end()) { x11Stack(w, top, x11Stack); } } @@ -1454,7 +1447,7 @@ void CCompositor::cleanupFadingOut(const MONITORID& monid) { if (ls->fadingOut && ls->readyToDelete && ls->isFadedOut()) { for (auto const& m : m_vMonitors) { for (auto& lsl : m->m_aLayerSurfaceLayers) { - if (!lsl.empty() && std::find_if(lsl.begin(), lsl.end(), [&](auto& other) { return other == ls; }) != lsl.end()) { + if (!lsl.empty() && std::ranges::find_if(lsl, [&](auto& other) { return other == ls; }) != lsl.end()) { std::erase_if(lsl, [&](auto& other) { return other == ls || !other; }); } } @@ -1477,7 +1470,7 @@ void CCompositor::cleanupFadingOut(const MONITORID& monid) { } void CCompositor::addToFadingOutSafe(PHLLS pLS) { - const auto FOUND = std::find_if(m_vSurfacesFadingOut.begin(), m_vSurfacesFadingOut.end(), [&](auto& other) { return other.lock() == pLS; }); + const auto FOUND = std::ranges::find_if(m_vSurfacesFadingOut, [&](auto& other) { return other.lock() == pLS; }); if (FOUND != m_vSurfacesFadingOut.end()) return; // if it's already added, don't add it. @@ -1490,7 +1483,7 @@ void CCompositor::removeFromFadingOutSafe(PHLLS ls) { } void CCompositor::addToFadingOutSafe(PHLWINDOW pWindow) { - const auto FOUND = std::find_if(m_vWindowsFadingOut.begin(), m_vWindowsFadingOut.end(), [&](PHLWINDOWREF& other) { return other.lock() == pWindow; }); + const auto FOUND = std::ranges::find_if(m_vWindowsFadingOut, [&](PHLWINDOWREF& other) { return other.lock() == pWindow; }); if (FOUND != m_vWindowsFadingOut.end()) return; // if it's already added, don't add it. @@ -1609,7 +1602,7 @@ PHLWINDOW CCompositor::getWindowInDirection(const CBox& box, PHLWORKSPACE pWorks // auto vectorAngles = [](const Vector2D& a, const Vector2D& b) -> double { - double dot = a.x * b.x + a.y * b.y; + double dot = (a.x * b.x) + (a.y * b.y); double ang = std::acos(dot / (a.size() * b.size())); return ang; }; @@ -1728,7 +1721,7 @@ bool CCompositor::isPointOnReservedArea(const Vector2D& point, const PHLMONITOR const auto XY1 = PMONITOR->vecPosition + PMONITOR->vecReservedTopLeft; const auto XY2 = PMONITOR->vecPosition + PMONITOR->vecSize - PMONITOR->vecReservedBottomRight; - return !VECINRECT(point, XY1.x, XY1.y, XY2.x, XY2.y); + return VECNOTINRECT(point, XY1.x, XY1.y, XY2.x, XY2.y); } PHLMONITOR CCompositor::getMonitorInDirection(const char& dir) { @@ -1902,7 +1895,7 @@ void CCompositor::updateWindowAnimatedDecorationValues(PHLWINDOW pWindow) { MONITORID CCompositor::getNextAvailableMonitorID(std::string const& name) { // reuse ID if it's already in the map, and the monitor with that ID is not being used by another monitor - if (m_mMonitorIDMap.contains(name) && !std::any_of(m_vRealMonitors.begin(), m_vRealMonitors.end(), [&](auto m) { return m->ID == m_mMonitorIDMap[name]; })) + if (m_mMonitorIDMap.contains(name) && !std::ranges::any_of(m_vRealMonitors, [&](auto m) { return m->ID == m_mMonitorIDMap[name]; })) return m_mMonitorIDMap[name]; // otherwise, find minimum available ID that is not in the map @@ -1912,7 +1905,7 @@ MONITORID CCompositor::getNextAvailableMonitorID(std::string const& name) { } MONITORID nextID = 0; - while (usedIDs.count(nextID) > 0) { + while (usedIDs.contains(nextID)) { nextID++; } m_mMonitorIDMap[name] = nextID; @@ -1920,7 +1913,6 @@ MONITORID CCompositor::getNextAvailableMonitorID(std::string const& name) { } void CCompositor::swapActiveWorkspaces(PHLMONITOR pMonitorA, PHLMONITOR pMonitorB) { - const auto PWORKSPACEA = pMonitorA->activeWorkspace; const auto PWORKSPACEB = pMonitorB->activeWorkspace; @@ -1992,17 +1984,18 @@ void CCompositor::swapActiveWorkspaces(PHLMONITOR pMonitorA, PHLMONITOR pMonitor (g_pCompositor->vectorToWindowUnified(g_pInputManager->getMouseCoordsInternal(), RESERVED_EXTENTS | INPUT_EXTENTS | ALLOW_FLOATING))); const auto PNEWWORKSPACE = pMonitorA->ID == g_pCompositor->m_pLastMonitor->ID ? PWORKSPACEB : PWORKSPACEA; - g_pEventManager->postEvent(SHyprIPCEvent{"workspace", PNEWWORKSPACE->m_szName}); - g_pEventManager->postEvent(SHyprIPCEvent{"workspacev2", std::format("{},{}", PNEWWORKSPACE->m_iID, PNEWWORKSPACE->m_szName)}); + g_pEventManager->postEvent(SHyprIPCEvent{.event = "workspace", .data = PNEWWORKSPACE->m_szName}); + g_pEventManager->postEvent(SHyprIPCEvent{.event = "workspacev2", .data = std::format("{},{}", PNEWWORKSPACE->m_iID, PNEWWORKSPACE->m_szName)}); EMIT_HOOK_EVENT("workspace", PNEWWORKSPACE); } // event - g_pEventManager->postEvent(SHyprIPCEvent{"moveworkspace", PWORKSPACEA->m_szName + "," + pMonitorB->szName}); - g_pEventManager->postEvent(SHyprIPCEvent{"moveworkspacev2", std::format("{},{},{}", PWORKSPACEA->m_iID, PWORKSPACEA->m_szName, pMonitorB->szName)}); + g_pEventManager->postEvent(SHyprIPCEvent{.event = "moveworkspace", .data = PWORKSPACEA->m_szName + "," + pMonitorB->szName}); + g_pEventManager->postEvent(SHyprIPCEvent{.event = "moveworkspacev2", .data = std::format("{},{},{}", PWORKSPACEA->m_iID, PWORKSPACEA->m_szName, pMonitorB->szName)}); EMIT_HOOK_EVENT("moveWorkspace", (std::vector{PWORKSPACEA, pMonitorB})); - g_pEventManager->postEvent(SHyprIPCEvent{"moveworkspace", PWORKSPACEB->m_szName + "," + pMonitorA->szName}); - g_pEventManager->postEvent(SHyprIPCEvent{"moveworkspacev2", std::format("{},{},{}", PWORKSPACEB->m_iID, PWORKSPACEB->m_szName, pMonitorA->szName)}); + g_pEventManager->postEvent(SHyprIPCEvent{.event = "moveworkspace", .data = PWORKSPACEB->m_szName + "," + pMonitorA->szName}); + g_pEventManager->postEvent(SHyprIPCEvent{.event = "moveworkspacev2", .data = std::format("{},{},{}", PWORKSPACEB->m_iID, PWORKSPACEB->m_szName, pMonitorA->szName)}); + EMIT_HOOK_EVENT("moveWorkspace", (std::vector{PWORKSPACEB, pMonitorA})); } @@ -2081,7 +2074,6 @@ PHLMONITOR CCompositor::getMonitorFromString(const std::string& name) { } void CCompositor::moveWorkspaceToMonitor(PHLWORKSPACE pWorkspace, PHLMONITOR pMonitor, bool noWarpCursor) { - if (!pWorkspace || !pMonitor) return; @@ -2188,8 +2180,8 @@ void CCompositor::moveWorkspaceToMonitor(PHLWORKSPACE pWorkspace, PHLMONITOR pMo updateSuspendedStates(); // event - g_pEventManager->postEvent(SHyprIPCEvent{"moveworkspace", pWorkspace->m_szName + "," + pMonitor->szName}); - g_pEventManager->postEvent(SHyprIPCEvent{"moveworkspacev2", std::format("{},{},{}", pWorkspace->m_iID, pWorkspace->m_szName, pMonitor->szName)}); + g_pEventManager->postEvent(SHyprIPCEvent{.event = "moveworkspace", .data = pWorkspace->m_szName + "," + pMonitor->szName}); + g_pEventManager->postEvent(SHyprIPCEvent{.event = "moveworkspacev2", .data = std::format("{},{},{}", pWorkspace->m_iID, pWorkspace->m_szName, pMonitor->szName)}); EMIT_HOOK_EVENT("moveWorkspace", (std::vector{pWorkspace, pMonitor})); } @@ -2200,12 +2192,8 @@ bool CCompositor::workspaceIDOutOfBounds(const WORKSPACEID& id) { for (auto const& w : m_vWorkspaces) { if (w->m_bIsSpecialWorkspace) continue; - - if (w->m_iID < lowestID) - lowestID = w->m_iID; - - if (w->m_iID > highestID) - highestID = w->m_iID; + lowestID = std::min(w->m_iID, lowestID); + highestID = std::max(w->m_iID, highestID); } return std::clamp(id, lowestID, highestID) != id; @@ -2281,7 +2269,7 @@ void CCompositor::setWindowFullscreenState(const PHLWINDOW PWINDOW, SFullscreenS if (PWORKSPACE->m_bHasFullscreenWindow && !PWINDOW->isFullscreen()) setWindowFullscreenInternal(PWORKSPACE->getFullscreenWindow(), FSMODE_NONE); - const bool CHANGEINTERNAL = !(PWINDOW->m_bPinned || CURRENT_EFFECTIVE_MODE == EFFECTIVE_MODE); + const bool CHANGEINTERNAL = !PWINDOW->m_bPinned && CURRENT_EFFECTIVE_MODE != EFFECTIVE_MODE; if (*PALLOWPINFULLSCREEN && PWINDOW->m_bPinFullscreened && PWINDOW->isFullscreen() && !PWINDOW->m_bPinned && state.internal == FSMODE_NONE) { PWINDOW->m_bPinned = true; @@ -2308,7 +2296,7 @@ void CCompositor::setWindowFullscreenState(const PHLWINDOW PWINDOW, SFullscreenS PWORKSPACE->m_efFullscreenMode = EFFECTIVE_MODE; PWORKSPACE->m_bHasFullscreenWindow = EFFECTIVE_MODE != FSMODE_NONE; - g_pEventManager->postEvent(SHyprIPCEvent{"fullscreen", std::to_string((int)EFFECTIVE_MODE != FSMODE_NONE)}); + g_pEventManager->postEvent(SHyprIPCEvent{.event = "fullscreen", .data = std::to_string((int)EFFECTIVE_MODE != FSMODE_NONE)}); EMIT_HOOK_EVENT("fullscreen", PWINDOW); PWINDOW->updateDynamicRules(); @@ -2575,8 +2563,8 @@ Vector2D CCompositor::parseWindowVectorArgsRelative(const std::string& args, con X = xIsPercent ? std::stof(x) * 0.01 * PMONITOR->vecSize.x : std::stoi(x); Y = yIsPercent ? std::stof(y) * 0.01 * PMONITOR->vecSize.y : std::stoi(y); } else { - X = xIsPercent ? std::stof(x) * 0.01 * relativeTo.x + relativeTo.x : std::stoi(x) + relativeTo.x; - Y = yIsPercent ? std::stof(y) * 0.01 * relativeTo.y + relativeTo.y : std::stoi(y) + relativeTo.y; + X = xIsPercent ? (std::stof(x) * 0.01 * relativeTo.x) + relativeTo.x : std::stoi(x) + relativeTo.x; + Y = yIsPercent ? (std::stof(y) * 0.01 * relativeTo.y) + relativeTo.y : std::stoi(y) + relativeTo.y; } return Vector2D(X, Y); @@ -2613,8 +2601,8 @@ void CCompositor::setActiveMonitor(PHLMONITOR pMonitor) { const auto WORKSPACE_ID = PWORKSPACE ? std::to_string(PWORKSPACE->m_iID) : std::to_string(WORKSPACE_INVALID); const auto WORKSPACE_NAME = PWORKSPACE ? PWORKSPACE->m_szName : "?"; - g_pEventManager->postEvent(SHyprIPCEvent{"focusedmon", pMonitor->szName + "," + WORKSPACE_NAME}); - g_pEventManager->postEvent(SHyprIPCEvent{"focusedmonv2", pMonitor->szName + "," + WORKSPACE_ID}); + g_pEventManager->postEvent(SHyprIPCEvent{.event = "focusedmon", .data = pMonitor->szName + "," + WORKSPACE_NAME}); + g_pEventManager->postEvent(SHyprIPCEvent{.event = "focusedmonv2", .data = pMonitor->szName + "," + WORKSPACE_ID}); EMIT_HOOK_EVENT("focusedMon", pMonitor); m_pLastMonitor = pMonitor->self; @@ -2804,14 +2792,10 @@ void CCompositor::arrangeMonitors() { // Finds the max and min values of explicitely placed monitors. for (auto const& m : arranged) { - if (m->vecPosition.x + m->vecSize.x > maxXOffsetRight) - maxXOffsetRight = m->vecPosition.x + m->vecSize.x; - if (m->vecPosition.x < maxXOffsetLeft) - maxXOffsetLeft = m->vecPosition.x; - if (m->vecPosition.y + m->vecSize.y > maxYOffsetDown) - maxYOffsetDown = m->vecPosition.y + m->vecSize.y; - if (m->vecPosition.y < maxYOffsetUp) - maxYOffsetUp = m->vecPosition.y; + maxXOffsetRight = std::max(m->vecPosition.x + m->vecSize.x, maxXOffsetRight); + maxXOffsetLeft = std::min(m->vecPosition.x, maxXOffsetLeft); + maxYOffsetDown = std::max(m->vecPosition.y + m->vecSize.y, maxYOffsetDown); + maxYOffsetUp = std::min(m->vecPosition.y, maxYOffsetUp); } }; diff --git a/src/Compositor.hpp b/src/Compositor.hpp index e55d7e1e..787ead08 100644 --- a/src/Compositor.hpp +++ b/src/Compositor.hpp @@ -1,15 +1,12 @@ #pragma once -#include #include -#include "defines.hpp" #include "managers/XWaylandManager.hpp" #include "managers/KeybindManager.hpp" #include "managers/SessionLockManager.hpp" #include "desktop/Window.hpp" #include "protocols/types/ColorManagement.hpp" -#include "helpers/memory/Memory.hpp" #include #include @@ -170,7 +167,7 @@ class CCompositor { uint64_t m_iHyprlandPID = 0; wl_event_source* m_critSigSource = nullptr; - rlimit m_sOriginalNofile = {0}; + rlimit m_sOriginalNofile = {}; }; inline UP g_pCompositor; diff --git a/src/macros.hpp b/src/macros.hpp index 0a3be8bc..a5176675 100644 --- a/src/macros.hpp +++ b/src/macros.hpp @@ -38,7 +38,8 @@ #define DYNLISTENER(name) CHyprWLListener hyprListener_##name #define DYNMULTILISTENER(name) wl_listener listen_##name -#define VECINRECT(vec, x1, y1, x2, y2) ((vec).x >= (x1) && (vec).x < (x2) && (vec).y >= (y1) && (vec).y < (y2)) +#define VECINRECT(vec, x1, y1, x2, y2) ((vec).x >= (x1) && (vec).x < (x2) && (vec).y >= (y1) && (vec).y < (y2)) +#define VECNOTINRECT(vec, x1, y1, x2, y2) ((vec).x < (x1) || (vec).x >= (x2) || (vec).y < (y1) || (vec).y >= (y2)) #define DELTALESSTHAN(a, b, delta) (abs((a) - (b)) < (delta)) diff --git a/src/managers/KeybindManager.cpp b/src/managers/KeybindManager.cpp index 247550ae..bc5d36c8 100644 --- a/src/managers/KeybindManager.cpp +++ b/src/managers/KeybindManager.cpp @@ -12,8 +12,6 @@ #include "TokenManager.hpp" #include "eventLoop/EventLoopManager.hpp" #include "debug/Log.hpp" -#include "helpers/varlist/VarList.hpp" -#include "../helpers/signal/Signal.hpp" #include "../managers/HookSystemManager.hpp" #include "../managers/input/InputManager.hpp" #include "../managers/LayoutManager.hpp" From 31431a92714ab7f53c25d2ececb26c5b7264b7e3 Mon Sep 17 00:00:00 2001 From: UjinT34 <41110182+UjinT34@users.noreply.github.com> Date: Sun, 2 Feb 2025 22:25:29 +0300 Subject: [PATCH 0963/2181] protocols: Support content-type-v1 proto (#9226) --- CMakeLists.txt | 9 ++ meson.build | 4 + protocols/meson.build | 1 + src/Compositor.cpp | 3 +- src/config/ConfigDescriptions.hpp | 13 +-- src/config/ConfigManager.cpp | 24 ++++- src/desktop/Window.cpp | 15 +++ src/desktop/Window.hpp | 159 ++++++++++++++-------------- src/desktop/WindowRule.cpp | 7 +- src/desktop/WindowRule.hpp | 2 + src/events/Windows.cpp | 9 +- src/helpers/Monitor.cpp | 5 +- src/macros.hpp | 1 + src/managers/ProtocolManager.cpp | 3 + src/protocols/ContentType.cpp | 95 +++++++++++++++++ src/protocols/ContentType.hpp | 59 +++++++++++ src/protocols/core/Compositor.hpp | 2 + src/protocols/types/ContentType.cpp | 37 +++++++ src/protocols/types/ContentType.hpp | 18 ++++ src/render/Renderer.cpp | 14 ++- 20 files changed, 386 insertions(+), 94 deletions(-) create mode 100644 src/protocols/ContentType.cpp create mode 100644 src/protocols/ContentType.hpp create mode 100644 src/protocols/types/ContentType.cpp create mode 100644 src/protocols/types/ContentType.hpp diff --git a/CMakeLists.txt b/CMakeLists.txt index 34e9a8ed..a98f697d 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -107,7 +107,15 @@ pkg_check_modules(hyprcursor_dep REQUIRED IMPORTED_TARGET hyprcursor>=0.1.7) pkg_check_modules(hyprutils_dep REQUIRED IMPORTED_TARGET hyprutils>=0.5.0) pkg_check_modules(hyprgraphics_dep REQUIRED IMPORTED_TARGET hyprgraphics>=0.1.1) +string(REPLACE "." ";" AQ_VERSION_LIST ${aquamarine_dep_VERSION}) +list(GET AQ_VERSION_LIST 0 AQ_VERSION_MAJOR) +list(GET AQ_VERSION_LIST 1 AQ_VERSION_MINOR) +list(GET AQ_VERSION_LIST 2 AQ_VERSION_PATCH) + add_compile_definitions(AQUAMARINE_VERSION="${aquamarine_dep_VERSION}") +add_compile_definitions(AQUAMARINE_VERSION_MAJOR=${AQ_VERSION_MAJOR}) +add_compile_definitions(AQUAMARINE_VERSION_MINOR=${AQ_VERSION_MINOR}) +add_compile_definitions(AQUAMARINE_VERSION_PATCH=${AQ_VERSION_PATCH}) add_compile_definitions(HYPRLANG_VERSION="${hyprlang_dep_VERSION}") add_compile_definitions(HYPRUTILS_VERSION="${hyprutils_dep_VERSION}") add_compile_definitions(HYPRCURSOR_VERSION="${hyprcursor_dep_VERSION}") @@ -368,6 +376,7 @@ protocolnew("staging/linux-drm-syncobj" "linux-drm-syncobj-v1" false) protocolnew("staging/xdg-dialog" "xdg-dialog-v1" false) protocolnew("staging/single-pixel-buffer" "single-pixel-buffer-v1" false) protocolnew("staging/security-context" "security-context-v1" false) +protocolnew("staging/content-type" "content-type-v1" false) protocolwayland() diff --git a/meson.build b/meson.build index ae6e3940..a367b166 100644 --- a/meson.build +++ b/meson.build @@ -36,7 +36,11 @@ hyprcursor = dependency('hyprcursor', version: '>=0.1.7') hyprgraphics = dependency('hyprgraphics', version: '>= 0.1.1') hyprlang = dependency('hyprlang', version: '>= 0.3.2') hyprutils = dependency('hyprutils', version: '>= 0.2.3') +aquamarine_version_list = aquamarine.version().split('.') add_project_arguments(['-DAQUAMARINE_VERSION="@0@"'.format(aquamarine.version())], language: 'cpp') +add_project_arguments(['-DAQUAMARINE_VERSION_MAJOR=@0@'.format(aquamarine_version_list.get(0))], language: 'cpp') +add_project_arguments(['-DAQUAMARINE_VERSION_MINOR=@0@'.format(aquamarine_version_list.get(1))], language: 'cpp') +add_project_arguments(['-DAQUAMARINE_VERSION_PATCH=@0@'.format(aquamarine_version_list.get(2))], language: 'cpp') add_project_arguments(['-DHYPRCURSOR_VERSION="@0@"'.format(hyprcursor.version())], language: 'cpp') add_project_arguments(['-DHYPRGRAPHICS_VERSION="@0@"'.format(hyprgraphics.version())], language: 'cpp') add_project_arguments(['-DHYPRLANG_VERSION="@0@"'.format(hyprlang.version())], language: 'cpp') diff --git a/protocols/meson.build b/protocols/meson.build index 6ed1b11a..7c57470b 100644 --- a/protocols/meson.build +++ b/protocols/meson.build @@ -70,6 +70,7 @@ protocols = [ wayland_protocol_dir / 'staging/xdg-dialog/xdg-dialog-v1.xml', wayland_protocol_dir / 'staging/single-pixel-buffer/single-pixel-buffer-v1.xml', wayland_protocol_dir / 'staging/security-context/security-context-v1.xml', + wayland_protocol_dir / 'staging/content-type/content-type-v1.xml', ] wl_protocols = [] diff --git a/src/Compositor.cpp b/src/Compositor.cpp index 6a241472..0aa0f13d 100644 --- a/src/Compositor.cpp +++ b/src/Compositor.cpp @@ -72,6 +72,7 @@ using namespace Hyprutils::String; using namespace Aquamarine; +using enum NContentType::eContentType; static int handleCritSignal(int signo, void* data) { Debug::log(LOG, "Hyprland received signal {}", signo); @@ -2323,7 +2324,7 @@ void CCompositor::setWindowFullscreenState(const PHLWINDOW PWINDOW, SFullscreenS // send a scanout tranche if we are entering fullscreen, and send a regular one if we aren't. // ignore if DS is disabled. - if (*PDIRECTSCANOUT) + if (*PDIRECTSCANOUT == 1 || (*PDIRECTSCANOUT == 2 && PWINDOW->getContentType() == CONTENT_TYPE_GAME)) g_pHyprRenderer->setSurfaceScanoutMode(PWINDOW->m_pWLSurface->resource(), EFFECTIVE_MODE != FSMODE_NONE ? PMONITOR->self.lock() : nullptr); g_pConfigManager->ensureVRR(PMONITOR); diff --git a/src/config/ConfigDescriptions.hpp b/src/config/ConfigDescriptions.hpp index 2fa86817..28cd29c4 100644 --- a/src/config/ConfigDescriptions.hpp +++ b/src/config/ConfigDescriptions.hpp @@ -1314,9 +1314,9 @@ inline static const std::vector CONFIG_OPTIONS = { SConfigOptionDescription{ .value = "render:direct_scanout", .description = "Enables direct scanout. Direct scanout attempts to reduce lag when there is only one fullscreen application on a screen (e.g. game). It is also " - "recommended to set this to false if the fullscreen application shows graphical glitches.", - .type = CONFIG_OPTION_BOOL, - .data = SConfigOptionDescription::SBoolData{false}, + "recommended to set this to false if the fullscreen application shows graphical glitches. 0 - off, 1 - on, 2 - auto (on with content type 'game')", + .type = CONFIG_OPTION_INT, + .data = SConfigOptionDescription::SRangeData{.value = 0, .min = 0, .max = 2}, }, SConfigOptionDescription{ .value = "render:expand_undersized_textures", @@ -1362,9 +1362,10 @@ inline static const std::vector CONFIG_OPTIONS = { }, SConfigOptionDescription{ .value = "cursor:no_break_fs_vrr", - .description = "disables scheduling new frames on cursor movement for fullscreen apps with VRR enabled to avoid framerate spikes (requires no_hardware_cursors = true)", - .type = CONFIG_OPTION_BOOL, - .data = SConfigOptionDescription::SBoolData{false}, + .description = "disables scheduling new frames on cursor movement for fullscreen apps with VRR enabled to avoid framerate spikes (may require no_hardware_cursors = true) " + "0 - off, 1 - on, 2 - auto (on with content type 'game')", + .type = CONFIG_OPTION_INT, + .data = SConfigOptionDescription::SRangeData{.value = 2, .min = 0, .max = 2}, }, SConfigOptionDescription{ .value = "cursor:min_refresh_rate", diff --git a/src/config/ConfigManager.cpp b/src/config/ConfigManager.cpp index 8bb6d157..42a1a91c 100644 --- a/src/config/ConfigManager.cpp +++ b/src/config/ConfigManager.cpp @@ -26,6 +26,7 @@ #include "../plugins/PluginSystem.hpp" #include "managers/HookSystemManager.hpp" +#include "protocols/types/ContentType.hpp" #include #include #include @@ -621,7 +622,7 @@ CConfigManager::CConfigManager() { m_pConfig->addConfigValue("opengl:nvidia_anti_flicker", Hyprlang::INT{1}); m_pConfig->addConfigValue("cursor:no_hardware_cursors", Hyprlang::INT{0}); - m_pConfig->addConfigValue("cursor:no_break_fs_vrr", Hyprlang::INT{0}); + m_pConfig->addConfigValue("cursor:no_break_fs_vrr", Hyprlang::INT{2}); m_pConfig->addConfigValue("cursor:min_refresh_rate", Hyprlang::INT{24}); m_pConfig->addConfigValue("cursor:hotspot_padding", Hyprlang::INT{0}); m_pConfig->addConfigValue("cursor:inactive_timeout", {0.f}); @@ -1347,6 +1348,14 @@ std::vector> CConfigManager::getMatchingRules(PHLWINDOW pWindow, continue; } + if (!rule->szContentType.empty()) { + try { + const auto contentType = NContentType::fromString(rule->szContentType); + if (pWindow->getContentType() != contentType) + continue; + } catch (std::exception& e) { Debug::log(ERR, "Rule \"content:{}\" failed with: {}", rule->szContentType, e.what()); } + } + if (!rule->szWorkspace.empty()) { const auto PWORKSPACE = pWindow->m_pWorkspace; @@ -2361,6 +2370,7 @@ std::optional CConfigManager::handleWindowRuleV2(const std::string& const auto FOCUSPOS = VALUE.find("focus:"); const auto FULLSCREENSTATEPOS = VALUE.find("fullscreenstate:"); const auto ONWORKSPACEPOS = VALUE.find("onworkspace:"); + const auto CONTENTTYPEPOS = VALUE.find("content:"); // find workspacepos that isn't onworkspacepos size_t WORKSPACEPOS = std::string::npos; @@ -2373,8 +2383,8 @@ std::optional CConfigManager::handleWindowRuleV2(const std::string& currentPos = VALUE.find("workspace:", currentPos + 1); } - const auto checkPos = std::unordered_set{TAGPOS, TITLEPOS, CLASSPOS, INITIALTITLEPOS, INITIALCLASSPOS, X11POS, FLOATPOS, - FULLSCREENPOS, PINNEDPOS, FULLSCREENSTATEPOS, WORKSPACEPOS, FOCUSPOS, ONWORKSPACEPOS}; + const auto checkPos = std::unordered_set{TAGPOS, TITLEPOS, CLASSPOS, INITIALTITLEPOS, INITIALCLASSPOS, X11POS, FLOATPOS, + FULLSCREENPOS, PINNEDPOS, FULLSCREENSTATEPOS, WORKSPACEPOS, FOCUSPOS, ONWORKSPACEPOS, CONTENTTYPEPOS}; if (checkPos.size() == 1 && checkPos.contains(std::string::npos)) { Debug::log(ERR, "Invalid rulev2 syntax: {}", VALUE); return "Invalid rulev2 syntax: " + VALUE; @@ -2411,6 +2421,8 @@ std::optional CConfigManager::handleWindowRuleV2(const std::string& min = WORKSPACEPOS; if (FOCUSPOS > pos && FOCUSPOS < min) min = FOCUSPOS; + if (CONTENTTYPEPOS > pos && CONTENTTYPEPOS < min) + min = CONTENTTYPEPOS; result = result.substr(0, min - pos); @@ -2469,6 +2481,9 @@ std::optional CConfigManager::handleWindowRuleV2(const std::string& if (ONWORKSPACEPOS != std::string::npos) rule->szOnWorkspace = extract(ONWORKSPACEPOS + 12); + if (CONTENTTYPEPOS != std::string::npos) + rule->szContentType = extract(CONTENTTYPEPOS + 8); + if (RULE == "unset") { std::erase_if(m_vWindowRules, [&](const auto& other) { if (!other->v2) @@ -2513,6 +2528,9 @@ std::optional CConfigManager::handleWindowRuleV2(const std::string& if (!rule->szOnWorkspace.empty() && rule->szOnWorkspace != other->szOnWorkspace) return false; + if (!rule->szContentType.empty() && rule->szContentType != other->szContentType) + return false; + return true; } }); diff --git a/src/desktop/Window.cpp b/src/desktop/Window.cpp index 6e580e49..6a523eec 100644 --- a/src/desktop/Window.cpp +++ b/src/desktop/Window.cpp @@ -15,6 +15,7 @@ #include "../managers/AnimationManager.hpp" #include "../protocols/XDGShell.hpp" #include "../protocols/core/Compositor.hpp" +#include "../protocols/ContentType.hpp" #include "../xwayland/XWayland.hpp" #include "../helpers/Color.hpp" #include "../events/Events.hpp" @@ -29,6 +30,7 @@ using namespace Hyprutils::String; using namespace Hyprutils::Animation; +using enum NContentType::eContentType; PHLWINDOW CWindow::create(SP surface) { PHLWINDOW pWindow = SP(new CWindow(surface)); @@ -1724,3 +1726,16 @@ void CWindow::sendWindowSize(Vector2D size, bool force, std::optional else if (m_pXDGSurface && m_pXDGSurface->toplevel) m_vPendingSizeAcks.emplace_back(m_pXDGSurface->toplevel->setSize(size), size.floor()); } + +NContentType::eContentType CWindow::getContentType() { + return m_pWLSurface->resource()->contentType.valid() ? m_pWLSurface->resource()->contentType->value : CONTENT_TYPE_NONE; +} + +void CWindow::setContentType(NContentType::eContentType contentType) { + if (!m_pWLSurface->resource()->contentType.valid()) + m_pWLSurface->resource()->contentType = PROTO::contentType->getContentType(m_pWLSurface->resource()); + // else disallow content type change if proto is used? + + Debug::log(INFO, "ContentType for window {}", (int)contentType); + m_pWLSurface->resource()->contentType->value = contentType; +} diff --git a/src/desktop/Window.hpp b/src/desktop/Window.hpp index ce2f8eb2..b3c3d84f 100644 --- a/src/desktop/Window.hpp +++ b/src/desktop/Window.hpp @@ -19,6 +19,7 @@ #include "WLSurface.hpp" #include "Workspace.hpp" #include "WindowRule.hpp" +#include "protocols/types/ContentType.hpp" class CXDGSurfaceResource; class CXWaylandSurface; @@ -393,85 +394,87 @@ class CWindow { } // methods - CBox getFullWindowBoundingBox(); - SBoxExtents getFullWindowExtents(); - CBox getWindowBoxUnified(uint64_t props); - CBox getWindowIdealBoundingBoxIgnoreReserved(); - void addWindowDeco(UP deco); - void updateWindowDecos(); - void removeWindowDeco(IHyprWindowDecoration* deco); - void uncacheWindowDecos(); - bool checkInputOnDecos(const eInputType, const Vector2D&, std::any = {}); - pid_t getPID(); - IHyprWindowDecoration* getDecorationByType(eDecorationType); - void updateToplevel(); - void updateSurfaceScaleTransformDetails(bool force = false); - void moveToWorkspace(PHLWORKSPACE); - PHLWINDOW x11TransientFor(); - void onUnmap(); - void onMap(); - void setHidden(bool hidden); - bool isHidden(); - void applyDynamicRule(const SP& r); - void updateDynamicRules(); - SBoxExtents getFullWindowReservedArea(); - Vector2D middle(); - bool opaque(); - float rounding(); - float roundingPower(); - bool canBeTorn(); - void setSuspended(bool suspend); - bool visibleOnMonitor(PHLMONITOR pMonitor); - WORKSPACEID workspaceID(); - MONITORID monitorID(); - bool onSpecialWorkspace(); - void activate(bool force = false); - int surfacesCount(); - void clampWindowSize(const std::optional minSize, const std::optional maxSize); - bool isFullscreen(); - bool isEffectiveInternalFSMode(const eFullscreenMode); - int getRealBorderSize(); - float getScrollMouse(); - float getScrollTouchpad(); - void updateWindowData(); - void updateWindowData(const struct SWorkspaceRule&); - void onBorderAngleAnimEnd(WP pav); - bool isInCurvedCorner(double x, double y); - bool hasPopupAt(const Vector2D& pos); - int popupsCount(); - void applyGroupRules(); - void createGroup(); - void destroyGroup(); - PHLWINDOW getGroupHead(); - PHLWINDOW getGroupTail(); - PHLWINDOW getGroupCurrent(); - PHLWINDOW getGroupPrevious(); - PHLWINDOW getGroupWindowByIndex(int); - int getGroupSize(); - bool canBeGroupedInto(PHLWINDOW pWindow); - void setGroupCurrent(PHLWINDOW pWindow); - void insertWindowToGroup(PHLWINDOW pWindow); - void updateGroupOutputs(); - void switchWithWindowInGroup(PHLWINDOW pWindow); - void setAnimationsToMove(); - void onWorkspaceAnimUpdate(); - void onFocusAnimUpdate(); - void onUpdateState(); - void onUpdateMeta(); - void onX11Configure(CBox box); - void onResourceChangeX11(); - std::string fetchTitle(); - std::string fetchClass(); - void warpCursor(bool force = false); - PHLWINDOW getSwallower(); - void unsetWindowData(eOverridePriority priority); - bool isX11OverrideRedirect(); - bool isModal(); - Vector2D requestedMinSize(); - Vector2D requestedMaxSize(); - void sendWindowSize(Vector2D size, bool force = false, std::optional overridePos = std::nullopt); + CBox getFullWindowBoundingBox(); + SBoxExtents getFullWindowExtents(); + CBox getWindowBoxUnified(uint64_t props); + CBox getWindowIdealBoundingBoxIgnoreReserved(); + void addWindowDeco(UP deco); + void updateWindowDecos(); + void removeWindowDeco(IHyprWindowDecoration* deco); + void uncacheWindowDecos(); + bool checkInputOnDecos(const eInputType, const Vector2D&, std::any = {}); + pid_t getPID(); + IHyprWindowDecoration* getDecorationByType(eDecorationType); + void updateToplevel(); + void updateSurfaceScaleTransformDetails(bool force = false); + void moveToWorkspace(PHLWORKSPACE); + PHLWINDOW x11TransientFor(); + void onUnmap(); + void onMap(); + void setHidden(bool hidden); + bool isHidden(); + void applyDynamicRule(const SP& r); + void updateDynamicRules(); + SBoxExtents getFullWindowReservedArea(); + Vector2D middle(); + bool opaque(); + float rounding(); + float roundingPower(); + bool canBeTorn(); + void setSuspended(bool suspend); + bool visibleOnMonitor(PHLMONITOR pMonitor); + WORKSPACEID workspaceID(); + MONITORID monitorID(); + bool onSpecialWorkspace(); + void activate(bool force = false); + int surfacesCount(); + void clampWindowSize(const std::optional minSize, const std::optional maxSize); + bool isFullscreen(); + bool isEffectiveInternalFSMode(const eFullscreenMode); + int getRealBorderSize(); + float getScrollMouse(); + float getScrollTouchpad(); + void updateWindowData(); + void updateWindowData(const struct SWorkspaceRule&); + void onBorderAngleAnimEnd(WP pav); + bool isInCurvedCorner(double x, double y); + bool hasPopupAt(const Vector2D& pos); + int popupsCount(); + void applyGroupRules(); + void createGroup(); + void destroyGroup(); + PHLWINDOW getGroupHead(); + PHLWINDOW getGroupTail(); + PHLWINDOW getGroupCurrent(); + PHLWINDOW getGroupPrevious(); + PHLWINDOW getGroupWindowByIndex(int); + int getGroupSize(); + bool canBeGroupedInto(PHLWINDOW pWindow); + void setGroupCurrent(PHLWINDOW pWindow); + void insertWindowToGroup(PHLWINDOW pWindow); + void updateGroupOutputs(); + void switchWithWindowInGroup(PHLWINDOW pWindow); + void setAnimationsToMove(); + void onWorkspaceAnimUpdate(); + void onFocusAnimUpdate(); + void onUpdateState(); + void onUpdateMeta(); + void onX11Configure(CBox box); + void onResourceChangeX11(); + std::string fetchTitle(); + std::string fetchClass(); + void warpCursor(bool force = false); + PHLWINDOW getSwallower(); + void unsetWindowData(eOverridePriority priority); + bool isX11OverrideRedirect(); + bool isModal(); + Vector2D requestedMinSize(); + Vector2D requestedMaxSize(); + void sendWindowSize(Vector2D size, bool force = false, std::optional overridePos = std::nullopt); + NContentType::eContentType getContentType(); + void setContentType(NContentType::eContentType contentType); - CBox getWindowMainSurfaceBox() const { + CBox getWindowMainSurfaceBox() const { return {m_vRealPosition->value().x, m_vRealPosition->value().y, m_vRealSize->value().x, m_vRealSize->value().y}; } diff --git a/src/desktop/WindowRule.cpp b/src/desktop/WindowRule.cpp index 306a25ce..fea2d43b 100644 --- a/src/desktop/WindowRule.cpp +++ b/src/desktop/WindowRule.cpp @@ -8,8 +8,9 @@ static const auto RULES = std::unordered_set{ "float", "fullscreen", "maximize", "noinitialfocus", "pin", "stayfocused", "tile", "renderunfocused", }; static const auto RULES_PREFIX = std::unordered_set{ - "animation", "bordercolor", "bordersize", "center", "fullscreenstate", "group", "idleinhibit", "maxsize", "minsize", "monitor", "move", "opacity", - "plugin:", "prop", "pseudo", "rounding", "roundingpower", "scrollmouse", "scrolltouchpad", "size", "suppressevent", "tag", "workspace", "xray", + "animation", "bordercolor", "bordersize", "center", "content", "fullscreenstate", "group", "idleinhibit", "maxsize", "minsize", + "monitor", "move", "opacity", "plugin:", "prop", "pseudo", "rounding", "roundingpower", "scrollmouse", "scrolltouchpad", + "size", "suppressevent", "tag", "workspace", "xray", }; CWindowRule::CWindowRule(const std::string& rule, const std::string& value, bool isV2, bool isExecRule) : szValue(value), szRule(rule), v2(isV2), execRule(isExecRule) { @@ -74,6 +75,8 @@ CWindowRule::CWindowRule(const std::string& rule, const std::string& value, bool ruleType = RULE_WORKSPACE; else if (rule.starts_with("prop")) ruleType = RULE_PROP; + else if (rule.starts_with("content")) + ruleType = RULE_CONTENT; else { // check if this is a prop. const CVarList VARS(rule, 0, 's', true); diff --git a/src/desktop/WindowRule.hpp b/src/desktop/WindowRule.hpp index be9c2d9c..50e221f3 100644 --- a/src/desktop/WindowRule.hpp +++ b/src/desktop/WindowRule.hpp @@ -36,6 +36,7 @@ class CWindowRule { RULE_TAG, RULE_WORKSPACE, RULE_PROP, + RULE_CONTENT, }; eRuleType ruleType = RULE_INVALID; @@ -58,6 +59,7 @@ class CWindowRule { std::string szFullscreenState = ""; // empty means any std::string szOnWorkspace = ""; // empty means any std::string szWorkspace = ""; // empty means any + std::string szContentType = ""; // empty means any // precompiled regexes CRuleRegexContainer rTitle; diff --git a/src/events/Windows.cpp b/src/events/Windows.cpp index f6ef9ced..8eaabd29 100644 --- a/src/events/Windows.cpp +++ b/src/events/Windows.cpp @@ -11,11 +11,11 @@ #include "../protocols/XDGShell.hpp" #include "../protocols/core/Compositor.hpp" #include "../protocols/ToplevelExport.hpp" +#include "protocols/types/ContentType.hpp" #include "../xwayland/XSurface.hpp" #include "managers/AnimationManager.hpp" #include "managers/PointerManager.hpp" #include "../desktop/LayerSurface.hpp" -#include "../managers/input/InputManager.hpp" #include "../managers/LayoutManager.hpp" #include "../managers/EventManager.hpp" #include "../managers/AnimationManager.hpp" @@ -307,6 +307,13 @@ void Events::listener_mapWindow(void* owner, void* data) { } break; } + case CWindowRule::RULE_CONTENT: { + const CVarList VARS(r->szRule, 0, ' '); + try { + PWINDOW->setContentType(NContentType::fromString(VARS[1])); + } catch (std::exception& e) { Debug::log(ERR, "Rule \"{}\" failed with: {}", r->szRule, e.what()); } + break; + } default: break; } diff --git a/src/helpers/Monitor.cpp b/src/helpers/Monitor.cpp index 9aa6efce..3ea6d49b 100644 --- a/src/helpers/Monitor.cpp +++ b/src/helpers/Monitor.cpp @@ -33,6 +33,7 @@ using namespace Hyprutils::String; using namespace Hyprutils::Utils; using namespace Hyprutils::OS; +using enum NContentType::eContentType; static int ratHandler(void* data) { g_pHyprRenderer->renderMonitor(((CMonitor*)data)->self.lock()); @@ -799,8 +800,8 @@ bool CMonitor::shouldSkipScheduleFrameOnMouseEvent() { static auto PMINRR = CConfigValue("cursor:min_refresh_rate"); // skip scheduling extra frames for fullsreen apps with vrr - bool shouldSkip = - *PNOBREAK && output->state->state().adaptiveSync && activeWorkspace && activeWorkspace->m_bHasFullscreenWindow && activeWorkspace->m_efFullscreenMode == FSMODE_FULLSCREEN; + const bool shouldSkip = activeWorkspace && activeWorkspace->m_bHasFullscreenWindow && activeWorkspace->m_efFullscreenMode == FSMODE_FULLSCREEN && + (*PNOBREAK == 1 || (*PNOBREAK == 2 && activeWorkspace->getFullscreenWindow()->getContentType() == CONTENT_TYPE_GAME)) && output->state->state().adaptiveSync; // keep requested minimum refresh rate if (shouldSkip && *PMINRR && lastPresentationTimer.getMillis() > 1000.0f / *PMINRR) { diff --git a/src/macros.hpp b/src/macros.hpp index a5176675..d2cad6b7 100644 --- a/src/macros.hpp +++ b/src/macros.hpp @@ -111,6 +111,7 @@ } \ } +#define AQUAMARINE_VERSION_NUMBER (AQUAMARINE_VERSION_MAJOR * 10000 + AQUAMARINE_VERSION_MINOR * 100 + AQUAMARINE_VERSION_PATCH) #define AQUAMARINE_FORWARD(name) \ namespace Aquamarine { \ class name; \ diff --git a/src/managers/ProtocolManager.cpp b/src/managers/ProtocolManager.cpp index 62736ae5..6cd3a608 100644 --- a/src/managers/ProtocolManager.cpp +++ b/src/managers/ProtocolManager.cpp @@ -58,10 +58,12 @@ #include "../protocols/core/Shm.hpp" #include "../protocols/ColorManagement.hpp" #include "../protocols/FrogColorManagement.hpp" +#include "../protocols/ContentType.hpp" #include "../helpers/Monitor.hpp" #include "../render/Renderer.hpp" #include "../Compositor.hpp" +#include "content-type-v1.hpp" #include #include @@ -169,6 +171,7 @@ CProtocolManager::CProtocolManager() { PROTO::securityContext = makeUnique(&wp_security_context_manager_v1_interface, 1, "SecurityContext"); PROTO::ctm = makeUnique(&hyprland_ctm_control_manager_v1_interface, 2, "CTMControl"); PROTO::hyprlandSurface = makeUnique(&hyprland_surface_manager_v1_interface, 2, "HyprlandSurface"); + PROTO::contentType = makeUnique(&wp_content_type_manager_v1_interface, 1, "ContentType"); if (*PENABLEXXCM) { PROTO::colorManagement = makeUnique(&xx_color_manager_v4_interface, 1, "ColorManagement"); diff --git a/src/protocols/ContentType.cpp b/src/protocols/ContentType.cpp new file mode 100644 index 00000000..0dd5481a --- /dev/null +++ b/src/protocols/ContentType.cpp @@ -0,0 +1,95 @@ +#include "ContentType.hpp" +#include "content-type-v1.hpp" +#include "protocols/types/ContentType.hpp" + +CContentTypeManager::CContentTypeManager(SP resource) : m_resource(resource) { + if UNLIKELY (!good()) + return; + + resource->setDestroy([](CWpContentTypeManagerV1* r) {}); + resource->setOnDestroy([this](CWpContentTypeManagerV1* r) { PROTO::contentType->destroyResource(this); }); + + resource->setGetSurfaceContentType([](CWpContentTypeManagerV1* r, uint32_t id, wl_resource* surface) { + LOGM(TRACE, "Get surface for id={}, surface={}", id, (uintptr_t)surface); + auto SURF = CWLSurfaceResource::fromResource(surface); + + if (!SURF) { + LOGM(ERR, "No surface for resource {}", (uintptr_t)surface); + r->error(-1, "Invalid surface (2)"); + return; + } + + if (SURF->colorManagement) { + r->error(WP_CONTENT_TYPE_MANAGER_V1_ERROR_ALREADY_CONSTRUCTED, "CT manager already exists"); + return; + } + + const auto RESOURCE = PROTO::contentType->m_vContentTypes.emplace_back(makeShared(makeShared(r->client(), r->version(), id))); + if UNLIKELY (!RESOURCE->good()) { + r->noMemory(); + PROTO::contentType->m_vContentTypes.pop_back(); + return; + } + + RESOURCE->self = RESOURCE; + + SURF->contentType = RESOURCE; + }); +} + +bool CContentTypeManager::good() { + return m_resource->resource(); +} + +CContentType::CContentType(WP surface) { + destroy = surface->events.destroy.registerListener([this](std::any d) { PROTO::contentType->destroyResource(this); }); +} + +CContentType::CContentType(SP resource) : m_resource(resource) { + if UNLIKELY (!good()) + return; + + m_pClient = resource->client(); + + resource->setDestroy([this](CWpContentTypeV1* r) { PROTO::contentType->destroyResource(this); }); + resource->setOnDestroy([this](CWpContentTypeV1* r) { PROTO::contentType->destroyResource(this); }); + + resource->setSetContentType([this](CWpContentTypeV1* r, wpContentTypeV1Type type) { value = NContentType::fromWP(type); }); +} + +bool CContentType::good() { + return m_resource && m_resource->resource(); +} + +wl_client* CContentType::client() { + return m_pClient; +} + +CContentTypeProtocol::CContentTypeProtocol(const wl_interface* iface, const int& ver, const std::string& name) : IWaylandProtocol(iface, ver, name) { + ; +} + +void CContentTypeProtocol::bindManager(wl_client* client, void* data, uint32_t ver, uint32_t id) { + const auto RESOURCE = m_vManagers.emplace_back(makeShared(makeShared(client, ver, id))); + + if UNLIKELY (!RESOURCE->good()) { + wl_client_post_no_memory(client); + m_vManagers.pop_back(); + return; + } +} + +SP CContentTypeProtocol::getContentType(WP surface) { + if (surface->contentType.valid()) + return surface->contentType.lock(); + + return m_vContentTypes.emplace_back(makeShared(surface)); +} + +void CContentTypeProtocol::destroyResource(CContentTypeManager* resource) { + std::erase_if(m_vManagers, [&](const auto& other) { return other.get() == resource; }); +} + +void CContentTypeProtocol::destroyResource(CContentType* resource) { + std::erase_if(m_vContentTypes, [&](const auto& other) { return other.get() == resource; }); +} diff --git a/src/protocols/ContentType.hpp b/src/protocols/ContentType.hpp new file mode 100644 index 00000000..c0359bf1 --- /dev/null +++ b/src/protocols/ContentType.hpp @@ -0,0 +1,59 @@ +#pragma once + +#include "WaylandProtocol.hpp" +#include "core/Compositor.hpp" +#include "content-type-v1.hpp" +#include "protocols/types/ContentType.hpp" + +class CContentTypeManager { + public: + CContentTypeManager(SP resource); + + bool good(); + + private: + SP m_resource; +}; + +class CContentType { + public: + CContentType(SP resource); + CContentType(WP surface); + + bool good(); + wl_client* client(); + NContentType::eContentType value = NContentType::CONTENT_TYPE_NONE; + + WP self; + + private: + SP m_resource; + wl_client* m_pClient = nullptr; + + CHyprSignalListener destroy; + + friend class CContentTypeProtocol; +}; + +class CContentTypeProtocol : public IWaylandProtocol { + public: + CContentTypeProtocol(const wl_interface* iface, const int& ver, const std::string& name); + + virtual void bindManager(wl_client* client, void* data, uint32_t ver, uint32_t id); + + SP getContentType(WP surface); + + private: + void destroyResource(CContentTypeManager* resource); + void destroyResource(CContentType* resource); + + std::vector> m_vManagers; + std::vector> m_vContentTypes; + + friend class CContentTypeManager; + friend class CContentType; +}; + +namespace PROTO { + inline UP contentType; +}; diff --git a/src/protocols/core/Compositor.hpp b/src/protocols/core/Compositor.hpp index 20614813..aaaf9b1a 100644 --- a/src/protocols/core/Compositor.hpp +++ b/src/protocols/core/Compositor.hpp @@ -26,6 +26,7 @@ class CViewportResource; class CDRMSyncobjSurfaceResource; class CColorManagementSurface; class CFrogColorManagementSurface; +class CContentType; class CWLCallbackResource { public: @@ -123,6 +124,7 @@ class CWLSurfaceResource { WP viewportResource; WP syncobj; // may not be present WP colorManagement; + WP contentType; void breadthfirst(std::function, const Vector2D&, void*)> fn, void* data); CRegion accumulateCurrentBufferDamage(); diff --git a/src/protocols/types/ContentType.cpp b/src/protocols/types/ContentType.cpp new file mode 100644 index 00000000..c0a3d30f --- /dev/null +++ b/src/protocols/types/ContentType.cpp @@ -0,0 +1,37 @@ +#include "ContentType.hpp" +#include +#include +#include + +namespace NContentType { + static std::unordered_map const table = { + {"none", CONTENT_TYPE_NONE}, {"photo", CONTENT_TYPE_PHOTO}, {"video", CONTENT_TYPE_VIDEO}, {"game", CONTENT_TYPE_GAME}}; + + eContentType fromString(const std::string name) { + auto it = table.find(name); + if (it != table.end()) + return it->second; + else + throw std::invalid_argument(std::format("Unknown content type {}", name)); + } + + eContentType fromWP(wpContentTypeV1Type contentType) { + switch (contentType) { + case WP_CONTENT_TYPE_V1_TYPE_NONE: return CONTENT_TYPE_NONE; + case WP_CONTENT_TYPE_V1_TYPE_PHOTO: return CONTENT_TYPE_PHOTO; + case WP_CONTENT_TYPE_V1_TYPE_VIDEO: return CONTENT_TYPE_VIDEO; + case WP_CONTENT_TYPE_V1_TYPE_GAME: return CONTENT_TYPE_GAME; + default: return CONTENT_TYPE_NONE; + } + } + + uint16_t toDRM(eContentType contentType) { + switch (contentType) { + case CONTENT_TYPE_NONE: return DRM_MODE_CONTENT_TYPE_GRAPHICS; + case CONTENT_TYPE_PHOTO: return DRM_MODE_CONTENT_TYPE_PHOTO; + case CONTENT_TYPE_VIDEO: return DRM_MODE_CONTENT_TYPE_CINEMA; + case CONTENT_TYPE_GAME: return DRM_MODE_CONTENT_TYPE_GAME; + default: return DRM_MODE_CONTENT_TYPE_NO_DATA; + } + } +} \ No newline at end of file diff --git a/src/protocols/types/ContentType.hpp b/src/protocols/types/ContentType.hpp new file mode 100644 index 00000000..66fcbca7 --- /dev/null +++ b/src/protocols/types/ContentType.hpp @@ -0,0 +1,18 @@ +#pragma once + +#include "content-type-v1.hpp" +#include + +namespace NContentType { + + enum eContentType : uint8_t { + CONTENT_TYPE_NONE = 0, + CONTENT_TYPE_PHOTO = 1, + CONTENT_TYPE_VIDEO = 2, + CONTENT_TYPE_GAME = 3, + }; + + eContentType fromString(const std::string name); + eContentType fromWP(wpContentTypeV1Type contentType); + uint16_t toDRM(eContentType contentType); +} \ No newline at end of file diff --git a/src/render/Renderer.cpp b/src/render/Renderer.cpp index 42445728..6d7b409c 100644 --- a/src/render/Renderer.cpp +++ b/src/render/Renderer.cpp @@ -33,10 +33,14 @@ #include "pass/SurfacePassElement.hpp" #include "debug/Log.hpp" #include "protocols/ColorManagement.hpp" +#if AQUAMARINE_VERSION_NUMBER > 702 // >0.7.2 +#include "protocols/types/ContentType.hpp" +#endif #include using namespace Hyprutils::Utils; using namespace Hyprutils::OS; +using enum NContentType::eContentType; extern "C" { #include @@ -1192,7 +1196,7 @@ void CHyprRenderer::renderMonitor(PHLMONITOR pMonitor) { pMonitor->tearingState.activelyTearing = shouldTear; - if (*PDIRECTSCANOUT && !shouldTear) { + if ((*PDIRECTSCANOUT == 1 || (*PDIRECTSCANOUT == 2 && pMonitor->activeWorkspace->getFullscreenWindow()->getContentType() == CONTENT_TYPE_GAME)) && !shouldTear) { if (pMonitor->attemptDirectScanout()) { return; } else if (!pMonitor->lastScanout.expired()) { @@ -1509,6 +1513,14 @@ bool CHyprRenderer::commitPendingAndDoExplicitSync(PHLMONITOR pMonitor) { } } +#if AQUAMARINE_VERSION_NUMBER > 702 // >0.7.2 + if (pMonitor->activeWorkspace && pMonitor->activeWorkspace->m_bHasFullscreenWindow && pMonitor->activeWorkspace->m_efFullscreenMode == FSMODE_FULLSCREEN) { + const auto WINDOW = pMonitor->activeWorkspace->getFullscreenWindow(); + pMonitor->output->state->setContentType(NContentType::toDRM(WINDOW->getContentType())); + } else + pMonitor->output->state->setContentType(NContentType::toDRM(CONTENT_TYPE_NONE)); +#endif + if (pMonitor->ctmUpdated) { pMonitor->ctmUpdated = false; pMonitor->output->state->setCTM(pMonitor->ctm); From 44004abc0189b9ba49444431e2a39d2df7e930bb Mon Sep 17 00:00:00 2001 From: Vaxry Date: Sun, 2 Feb 2025 22:16:00 +0000 Subject: [PATCH 0964/2181] config: fix includes --- src/config/ConfigManager.cpp | 4 ++-- src/desktop/Window.hpp | 2 +- src/events/Windows.cpp | 2 +- src/protocols/ContentType.hpp | 2 +- subprojects/hyprland-protocols | 2 +- 5 files changed, 6 insertions(+), 6 deletions(-) diff --git a/src/config/ConfigManager.cpp b/src/config/ConfigManager.cpp index 42a1a91c..3f45ddfe 100644 --- a/src/config/ConfigManager.cpp +++ b/src/config/ConfigManager.cpp @@ -25,8 +25,8 @@ #include "../debug/HyprNotificationOverlay.hpp" #include "../plugins/PluginSystem.hpp" -#include "managers/HookSystemManager.hpp" -#include "protocols/types/ContentType.hpp" +#include "../managers/HookSystemManager.hpp" +#include "../protocols/types/ContentType.hpp" #include #include #include diff --git a/src/desktop/Window.hpp b/src/desktop/Window.hpp index b3c3d84f..2d004855 100644 --- a/src/desktop/Window.hpp +++ b/src/desktop/Window.hpp @@ -19,7 +19,7 @@ #include "WLSurface.hpp" #include "Workspace.hpp" #include "WindowRule.hpp" -#include "protocols/types/ContentType.hpp" +#include "../protocols/types/ContentType.hpp" class CXDGSurfaceResource; class CXWaylandSurface; diff --git a/src/events/Windows.cpp b/src/events/Windows.cpp index 8eaabd29..a068ba07 100644 --- a/src/events/Windows.cpp +++ b/src/events/Windows.cpp @@ -11,7 +11,7 @@ #include "../protocols/XDGShell.hpp" #include "../protocols/core/Compositor.hpp" #include "../protocols/ToplevelExport.hpp" -#include "protocols/types/ContentType.hpp" +#include "../protocols/types/ContentType.hpp" #include "../xwayland/XSurface.hpp" #include "managers/AnimationManager.hpp" #include "managers/PointerManager.hpp" diff --git a/src/protocols/ContentType.hpp b/src/protocols/ContentType.hpp index c0359bf1..4c0c445f 100644 --- a/src/protocols/ContentType.hpp +++ b/src/protocols/ContentType.hpp @@ -3,7 +3,7 @@ #include "WaylandProtocol.hpp" #include "core/Compositor.hpp" #include "content-type-v1.hpp" -#include "protocols/types/ContentType.hpp" +#include "types/ContentType.hpp" class CContentTypeManager { public: diff --git a/subprojects/hyprland-protocols b/subprojects/hyprland-protocols index 755aef8d..4c75dd5c 160000 --- a/subprojects/hyprland-protocols +++ b/subprojects/hyprland-protocols @@ -1 +1 @@ -Subproject commit 755aef8dab49d0fc4663c715fa4ad221b2aedaed +Subproject commit 4c75dd5c015c8a0e5a34c6d02a018a650f57feb5 From 708d16636047c6a311c4e44424cf7d2090219a47 Mon Sep 17 00:00:00 2001 From: Alexander <51529891+Truenya@users.noreply.github.com> Date: Mon, 3 Feb 2025 04:34:30 +0300 Subject: [PATCH 0965/2181] dispatchers: add cyclenext hist option (#9055) --- src/Compositor.cpp | 83 +++++++++++++++++++-------------- src/Compositor.hpp | 7 ++- src/managers/KeybindManager.cpp | 32 ++++++------- src/managers/KeybindManager.hpp | 2 +- 4 files changed, 67 insertions(+), 57 deletions(-) diff --git a/src/Compositor.cpp b/src/Compositor.cpp index 0aa0f13d..95a57e03 100644 --- a/src/Compositor.cpp +++ b/src/Compositor.cpp @@ -1058,7 +1058,7 @@ PHLMONITOR CCompositor::getRealMonitorFromOutput(SP out) { return nullptr; } -void CCompositor::focusWindow(PHLWINDOW pWindow, SP pSurface) { +void CCompositor::focusWindow(PHLWINDOW pWindow, SP pSurface, bool preserveFocusHistory) { static auto PFOLLOWMOUSE = CConfigValue("input:follow_mouse"); static auto PSPECIALFALLTHROUGH = CConfigValue("input:special_fallthrough"); @@ -1178,12 +1178,13 @@ void CCompositor::focusWindow(PHLWINDOW pWindow, SP pSurface g_pInputManager->recheckIdleInhibitorStatus(); - // move to front of the window history - const auto HISTORYPIVOT = std::find_if(m_vWindowFocusHistory.begin(), m_vWindowFocusHistory.end(), [&](const auto& other) { return other.lock() == pWindow; }); - if (HISTORYPIVOT == m_vWindowFocusHistory.end()) { - Debug::log(ERR, "BUG THIS: {} has no pivot in history", pWindow); - } else { - std::rotate(m_vWindowFocusHistory.begin(), HISTORYPIVOT, HISTORYPIVOT + 1); + if (!preserveFocusHistory) { + // move to front of the window history + const auto HISTORYPIVOT = std::ranges::find_if(m_vWindowFocusHistory, [&](const auto& other) { return other.lock() == pWindow; }); + if (HISTORYPIVOT == m_vWindowFocusHistory.end()) + Debug::log(ERR, "BUG THIS: {} has no pivot in history", pWindow); + else + std::rotate(m_vWindowFocusHistory.begin(), HISTORYPIVOT, HISTORYPIVOT + 1); } if (*PFOLLOWMOUSE == 0) @@ -1396,7 +1397,6 @@ void CCompositor::changeWindowZOrder(PHLWINDOW pWindow, bool top) { }; x11Stack(pWindow, top, x11Stack); - for (const auto& it : toMove) { moveToZ(it, top); } @@ -1647,37 +1647,52 @@ PHLWINDOW CCompositor::getWindowInDirection(const CBox& box, PHLWORKSPACE pWorks return nullptr; } -PHLWINDOW CCompositor::getNextWindowOnWorkspace(PHLWINDOW pWindow, bool focusableOnly, std::optional floating, bool visible) { - auto it = std::ranges::find(m_vWindows, pWindow); - const auto FINDER = [&](const PHLWINDOW& w) { return isWindowAvailableForCycle(pWindow, w, focusableOnly, floating, visible); }; - const auto IN_RIGHT = std::find_if(it, m_vWindows.end(), FINDER); - if (IN_RIGHT != m_vWindows.end()) - return *IN_RIGHT; - const auto IN_LEFT = std::find_if(m_vWindows.begin(), it, FINDER); - return *IN_LEFT; -} - -PHLWINDOW CCompositor::getPrevWindowOnWorkspace(PHLWINDOW pWindow, bool focusableOnly, std::optional floating, bool visible) { - auto it = std::ranges::find(std::ranges::reverse_view(m_vWindows), pWindow); - const auto FINDER = [&](const PHLWINDOW& w) { return isWindowAvailableForCycle(pWindow, w, focusableOnly, floating, visible); }; - const auto IN_LEFT = std::find_if(it, m_vWindows.rend(), FINDER); - if (IN_LEFT != m_vWindows.rend()) - return *IN_LEFT; - const auto IN_RIGHT = std::find_if(m_vWindows.rbegin(), it, FINDER); - return *IN_RIGHT; -} - -inline static bool isWorkspaceMatches(PHLWINDOW pWindow, const PHLWINDOW w, bool anyWorkspace) { +template +static bool isWorkspaceMatches(WINDOWPTR pWindow, const WINDOWPTR w, bool anyWorkspace) { return anyWorkspace ? w->m_pWorkspace && w->m_pWorkspace->isVisible() : w->m_pWorkspace == pWindow->m_pWorkspace; } -inline static bool isFloatingMatches(PHLWINDOW w, std::optional floating) { +template +static bool isFloatingMatches(WINDOWPTR w, std::optional floating) { return !floating.has_value() || w->m_bIsFloating == floating.value(); -}; +} -bool CCompositor::isWindowAvailableForCycle(PHLWINDOW pWindow, const PHLWINDOW w, bool focusableOnly, std::optional floating, bool anyWorkspace) { - return isFloatingMatches(w, floating) && w != pWindow && isWorkspaceMatches(pWindow, w, anyWorkspace) && w->m_bIsMapped && !w->isHidden() && - (!focusableOnly || !w->m_sWindowData.noFocus.valueOrDefault()); +template +static bool isWindowAvailableForCycle(WINDOWPTR pWindow, WINDOWPTR w, bool focusableOnly, std::optional floating, bool anyWorkspace = false) { + return isFloatingMatches(w, floating) && + (w != pWindow && isWorkspaceMatches(pWindow, w, anyWorkspace) && w->m_bIsMapped && !w->isHidden() && (!focusableOnly || !w->m_sWindowData.noFocus.valueOrDefault())); +} + +template +static PHLWINDOW getWindowPred(Iterator cur, Iterator end, Iterator begin, const std::function PRED) { + const auto IN_ONE_SIDE = std::find_if(cur, end, PRED); + if (IN_ONE_SIDE != end) + return *IN_ONE_SIDE; + const auto IN_OTHER_SIDE = std::find_if(begin, cur, PRED); + return *IN_OTHER_SIDE; +} + +template +static PHLWINDOW getWeakWindowPred(Iterator cur, Iterator end, Iterator begin, const std::function PRED) { + const auto IN_ONE_SIDE = std::find_if(cur, end, PRED); + if (IN_ONE_SIDE != end) + return IN_ONE_SIDE->lock(); + const auto IN_OTHER_SIDE = std::find_if(begin, cur, PRED); + return IN_OTHER_SIDE->lock(); +} + +PHLWINDOW CCompositor::getWindowCycleHist(PHLWINDOWREF cur, bool focusableOnly, std::optional floating, bool visible, bool next) { + const auto FINDER = [&](const PHLWINDOWREF& w) { return isWindowAvailableForCycle(cur, w, focusableOnly, floating, visible); }; + // also m_vWindowFocusHistory has reverse order, so when it is next - we need to reverse again + return next ? + getWeakWindowPred(std::ranges::find(std::ranges::reverse_view(m_vWindowFocusHistory), cur), m_vWindowFocusHistory.rend(), m_vWindowFocusHistory.rbegin(), FINDER) : + getWeakWindowPred(std::ranges::find(m_vWindowFocusHistory, cur), m_vWindowFocusHistory.end(), m_vWindowFocusHistory.begin(), FINDER); +} + +PHLWINDOW CCompositor::getWindowCycle(PHLWINDOW cur, bool focusableOnly, std::optional floating, bool visible, bool prev) { + const auto FINDER = [&](const PHLWINDOW& w) { return isWindowAvailableForCycle(cur, w, focusableOnly, floating, visible); }; + return prev ? getWindowPred(std::ranges::find(std::ranges::reverse_view(m_vWindows), cur), m_vWindows.rend(), m_vWindows.rbegin(), FINDER) : + getWindowPred(std::ranges::find(m_vWindows, cur), m_vWindows.end(), m_vWindows.begin(), FINDER); } WORKSPACEID CCompositor::getNextAvailableNamedWorkspace() { diff --git a/src/Compositor.hpp b/src/Compositor.hpp index 787ead08..a57095a3 100644 --- a/src/Compositor.hpp +++ b/src/Compositor.hpp @@ -83,7 +83,7 @@ class CCompositor { PHLMONITOR getMonitorFromCursor(); PHLMONITOR getMonitorFromVector(const Vector2D&); void removeWindowFromVectorSafe(PHLWINDOW); - void focusWindow(PHLWINDOW, SP pSurface = nullptr); + void focusWindow(PHLWINDOW, SP pSurface = nullptr, bool preserveFocusHistory = false); void focusSurface(SP, PHLWINDOW pWindowOwner = nullptr); bool monitorExists(PHLMONITOR); PHLWINDOW vectorToWindowUnified(const Vector2D&, uint8_t properties, PHLWINDOW pIgnoreWindow = nullptr); @@ -105,8 +105,8 @@ class CCompositor { void cleanupFadingOut(const MONITORID& monid); PHLWINDOW getWindowInDirection(PHLWINDOW, char); PHLWINDOW getWindowInDirection(const CBox& box, PHLWORKSPACE pWorkspace, char dir, PHLWINDOW ignoreWindow = nullptr, bool useVectorAngles = false); - PHLWINDOW getNextWindowOnWorkspace(PHLWINDOW, bool focusableOnly = false, std::optional floating = {}, bool visible = false); - PHLWINDOW getPrevWindowOnWorkspace(PHLWINDOW, bool focusableOnly = false, std::optional floating = {}, bool visible = false); + PHLWINDOW getWindowCycle(PHLWINDOW cur, bool focusableOnly = false, std::optional floating = std::nullopt, bool visible = false, bool prev = false); + PHLWINDOW getWindowCycleHist(PHLWINDOWREF cur, bool focusableOnly = false, std::optional floating = std::nullopt, bool visible = false, bool next = false); WORKSPACEID getNextAvailableNamedWorkspace(); bool isPointOnAnyMonitor(const Vector2D&); bool isPointOnReservedArea(const Vector2D& point, const PHLMONITOR monitor = nullptr); @@ -163,7 +163,6 @@ class CCompositor { void setRandomSplash(); void initManagers(eManagersInitStage stage); void prepareFallbackOutput(); - bool isWindowAvailableForCycle(PHLWINDOW pWindow, PHLWINDOW w, bool focusableOnly, std::optional floating, bool anyWorkspace = false); uint64_t m_iHyprlandPID = 0; wl_event_source* m_critSigSource = nullptr; diff --git a/src/managers/KeybindManager.cpp b/src/managers/KeybindManager.cpp index bc5d36c8..47cc4f67 100644 --- a/src/managers/KeybindManager.cpp +++ b/src/managers/KeybindManager.cpp @@ -367,7 +367,7 @@ bool CKeybindManager::tryMoveFocusToMonitor(PHLMONITOR monitor) { return true; } -void CKeybindManager::switchToWindow(PHLWINDOW PWINDOWTOCHANGETO) { +void CKeybindManager::switchToWindow(PHLWINDOW PWINDOWTOCHANGETO, bool preserveFocusHistory) { static auto PFOLLOWMOUSE = CConfigValue("input:follow_mouse"); static auto PNOWARPS = CConfigValue("cursor:no_warps"); @@ -386,7 +386,7 @@ void CKeybindManager::switchToWindow(PHLWINDOW PWINDOWTOCHANGETO) { if (!PWINDOWTOCHANGETO->m_bPinned) g_pCompositor->setWindowFullscreenInternal(PLASTWINDOW, FSMODE_NONE); - g_pCompositor->focusWindow(PWINDOWTOCHANGETO); + g_pCompositor->focusWindow(PWINDOWTOCHANGETO, nullptr, preserveFocusHistory); if (!PWINDOWTOCHANGETO->m_bPinned) g_pCompositor->setWindowFullscreenInternal(PWINDOWTOCHANGETO, MODE); @@ -396,7 +396,7 @@ void CKeybindManager::switchToWindow(PHLWINDOW PWINDOWTOCHANGETO) { PWINDOWTOCHANGETO->m_vRealSize->warp(); } else { updateRelativeCursorCoords(); - g_pCompositor->focusWindow(PWINDOWTOCHANGETO); + g_pCompositor->focusWindow(PWINDOWTOCHANGETO, nullptr, preserveFocusHistory); PWINDOWTOCHANGETO->warpCursor(); // Move mouse focus to the new window if required by current follow_mouse and warp modes @@ -1473,7 +1473,7 @@ SDispatchResult CKeybindManager::moveFocusTo(std::string args) { } const auto PWINDOWTOCHANGETO = *PFULLCYCLE && PLASTWINDOW->isFullscreen() ? - (arg == 'd' || arg == 'b' || arg == 'r' ? g_pCompositor->getNextWindowOnWorkspace(PLASTWINDOW, true) : g_pCompositor->getPrevWindowOnWorkspace(PLASTWINDOW, true)) : + g_pCompositor->getWindowCycle(PLASTWINDOW, true, {}, false, arg != 'd' && arg != 'b' && arg != 'r') : g_pCompositor->getWindowInDirection(PLASTWINDOW, arg); // Prioritize focus change within groups if the window is a part of it. @@ -2221,11 +2221,13 @@ SDispatchResult CKeybindManager::circleNext(std::string arg) { floatStatus = true; const auto VISIBLE = args.contains("visible") || args.contains("v"); - const auto& w = (args.contains("prev") || args.contains("p") || args.contains("last") || args.contains("l")) ? - g_pCompositor->getPrevWindowOnWorkspace(g_pCompositor->m_pLastWindow.lock(), true, floatStatus, VISIBLE) : - g_pCompositor->getNextWindowOnWorkspace(g_pCompositor->m_pLastWindow.lock(), true, floatStatus, VISIBLE); + const auto PREV = args.contains("prev") || args.contains("p") || args.contains("last") || args.contains("l"); + const auto NEXT = args.contains("next") || args.contains("n"); // prev is default in classic alt+tab + const auto HIST = args.contains("hist") || args.contains("h"); + const auto& w = HIST ? g_pCompositor->getWindowCycleHist(g_pCompositor->m_pLastWindow, true, floatStatus, VISIBLE, NEXT) : + g_pCompositor->getWindowCycle(g_pCompositor->m_pLastWindow.lock(), true, floatStatus, VISIBLE, PREV); - switchToWindow(w); + switchToWindow(w, HIST); return {}; } @@ -2620,18 +2622,12 @@ SDispatchResult CKeybindManager::swapnext(std::string arg) { g_pCompositor->m_pLastWindow->m_pLastCycledWindow.lock() : nullptr; - if (arg == "last" || arg == "l" || arg == "prev" || arg == "p") - toSwap = g_pCompositor->getPrevWindowOnWorkspace(PLASTCYCLED ? PLASTCYCLED : PLASTWINDOW, true); - else - toSwap = g_pCompositor->getNextWindowOnWorkspace(PLASTCYCLED ? PLASTCYCLED : PLASTWINDOW, true); + const bool NEED_PREV = arg == "last" || arg == "l" || arg == "prev" || arg == "p"; + toSwap = g_pCompositor->getWindowCycle(PLASTCYCLED ? PLASTCYCLED : PLASTWINDOW, true, std::nullopt, false, NEED_PREV); // sometimes we may come back to ourselves. - if (toSwap == PLASTWINDOW) { - if (arg == "last" || arg == "l" || arg == "prev" || arg == "p") - toSwap = g_pCompositor->getPrevWindowOnWorkspace(PLASTWINDOW, true); - else - toSwap = g_pCompositor->getNextWindowOnWorkspace(PLASTWINDOW, true); - } + if (toSwap == PLASTWINDOW) + toSwap = g_pCompositor->getWindowCycle(PLASTWINDOW, true, std::nullopt, false, NEED_PREV); g_pLayoutManager->getCurrentLayout()->switchWindows(PLASTWINDOW, toSwap); diff --git a/src/managers/KeybindManager.hpp b/src/managers/KeybindManager.hpp index 1848ca78..cea3e3cf 100644 --- a/src/managers/KeybindManager.hpp +++ b/src/managers/KeybindManager.hpp @@ -148,7 +148,7 @@ class CKeybindManager { static bool tryMoveFocusToMonitor(PHLMONITOR monitor); static void moveWindowOutOfGroup(PHLWINDOW pWindow, const std::string& dir = ""); static void moveWindowIntoGroup(PHLWINDOW pWindow, PHLWINDOW pWindowInDirection); - static void switchToWindow(PHLWINDOW PWINDOWTOCHANGETO); + static void switchToWindow(PHLWINDOW PWINDOWTOCHANGETO, bool preserveFocusHistory = false); static uint64_t spawnRawProc(std::string, PHLWORKSPACE pInitialWorkspace); static uint64_t spawnWithRules(std::string, PHLWORKSPACE pInitialWorkspace); From 1da0b2c02e99d3bd35f4d1a6f9a55dc403715913 Mon Sep 17 00:00:00 2001 From: Vaxry Date: Mon, 3 Feb 2025 19:45:26 +0000 Subject: [PATCH 0966/2181] subprojects: update h-p fixes #9309 --- subprojects/hyprland-protocols | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/subprojects/hyprland-protocols b/subprojects/hyprland-protocols index 4c75dd5c..755aef8d 160000 --- a/subprojects/hyprland-protocols +++ b/subprojects/hyprland-protocols @@ -1 +1 @@ -Subproject commit 4c75dd5c015c8a0e5a34c6d02a018a650f57feb5 +Subproject commit 755aef8dab49d0fc4663c715fa4ad221b2aedaed From 70cfc7cc9c4ecadbb9dd9a75f096fc70177a8ca5 Mon Sep 17 00:00:00 2001 From: Vaxry Date: Mon, 3 Feb 2025 19:53:14 +0000 Subject: [PATCH 0967/2181] cmonitor: guard old workspace --- src/helpers/Monitor.cpp | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/src/helpers/Monitor.cpp b/src/helpers/Monitor.cpp index 3ea6d49b..e4843211 100644 --- a/src/helpers/Monitor.cpp +++ b/src/helpers/Monitor.cpp @@ -1019,15 +1019,17 @@ void CMonitor::changeWorkspace(const PHLWORKSPACE& pWorkspace, bool internal, bo if (pWorkspace == activeWorkspace) return; - const auto POLDWORKSPACE = activeWorkspace; - POLDWORKSPACE->m_bVisible = false; - pWorkspace->m_bVisible = true; + const auto POLDWORKSPACE = activeWorkspace; + if (POLDWORKSPACE) + POLDWORKSPACE->m_bVisible = false; + pWorkspace->m_bVisible = true; activeWorkspace = pWorkspace; if (!internal) { - const auto ANIMTOLEFT = pWorkspace->m_iID > POLDWORKSPACE->m_iID; - POLDWORKSPACE->startAnim(false, ANIMTOLEFT); + const auto ANIMTOLEFT = POLDWORKSPACE && pWorkspace->m_iID > POLDWORKSPACE->m_iID; + if (POLDWORKSPACE) + POLDWORKSPACE->startAnim(false, ANIMTOLEFT); pWorkspace->startAnim(true, ANIMTOLEFT); // move pinned windows From 5e7292434a9189d0550187f8a6fb687848194a41 Mon Sep 17 00:00:00 2001 From: Vaxry Date: Mon, 3 Feb 2025 22:36:10 +0000 Subject: [PATCH 0968/2181] compositor: guard null ws in updating fade --- src/Compositor.cpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/Compositor.cpp b/src/Compositor.cpp index 95a57e03..22cb70fb 100644 --- a/src/Compositor.cpp +++ b/src/Compositor.cpp @@ -2217,6 +2217,9 @@ bool CCompositor::workspaceIDOutOfBounds(const WORKSPACEID& id) { void CCompositor::updateFullscreenFadeOnWorkspace(PHLWORKSPACE pWorkspace) { + if (!pWorkspace) + return; + const auto FULLSCREEN = pWorkspace->m_bHasFullscreenWindow; for (auto const& w : g_pCompositor->m_vWindows) { From 3b99e906df8b439d65e740301940e57efc057012 Mon Sep 17 00:00:00 2001 From: vaxerski Date: Tue, 4 Feb 2025 10:18:08 +0000 Subject: [PATCH 0969/2181] compositor: don't iterate over unmapped ls-es in vectorToLS fixes #9312 --- src/Compositor.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Compositor.cpp b/src/Compositor.cpp index 22cb70fb..a8cbae3a 100644 --- a/src/Compositor.cpp +++ b/src/Compositor.cpp @@ -1245,7 +1245,7 @@ void CCompositor::focusSurface(SP pSurface, PHLWINDOW pWindo SP CCompositor::vectorToLayerPopupSurface(const Vector2D& pos, PHLMONITOR monitor, Vector2D* sCoords, PHLLS* ppLayerSurfaceFound) { for (auto const& lsl : monitor->m_aLayerSurfaceLayers | std::views::reverse) { for (auto const& ls : lsl | std::views::reverse) { - if (ls->fadingOut || !ls->layerSurface || (ls->layerSurface && !ls->layerSurface->mapped) || ls->alpha->value() == 0.f) + if (!ls->mapped || ls->fadingOut || !ls->layerSurface || (ls->layerSurface && !ls->layerSurface->mapped) || ls->alpha->value() == 0.f) continue; auto SURFACEAT = ls->popupHead->at(pos, true); @@ -1263,7 +1263,7 @@ SP CCompositor::vectorToLayerPopupSurface(const Vector2D& po SP CCompositor::vectorToLayerSurface(const Vector2D& pos, std::vector* layerSurfaces, Vector2D* sCoords, PHLLS* ppLayerSurfaceFound) { for (auto const& ls : *layerSurfaces | std::views::reverse) { - if (ls->fadingOut || !ls->layerSurface || (ls->layerSurface && !ls->layerSurface->surface->mapped) || ls->alpha->value() == 0.f) + if (!ls->mapped || ls->fadingOut || !ls->layerSurface || (ls->layerSurface && !ls->layerSurface->surface->mapped) || ls->alpha->value() == 0.f) continue; auto [surf, local] = ls->layerSurface->surface->at(pos - ls->geometry.pos(), true); From 84c9baecc6b73f6321b2739061e3c232710f73bf Mon Sep 17 00:00:00 2001 From: Tom Benham <38216488+tomben13@users.noreply.github.com> Date: Wed, 5 Feb 2025 10:56:41 +0100 Subject: [PATCH 0970/2181] keybinds: Added `toggleswallow` dispatcher (#5548) * Added `toggleswallow` dispatcher * clang-format * Removed brackets for 1-line if --- src/desktop/Window.cpp | 6 ++++-- src/desktop/Window.hpp | 3 ++- src/events/Windows.cpp | 13 +++++++++---- src/managers/KeybindManager.cpp | 22 ++++++++++++++++++++++ src/managers/KeybindManager.hpp | 1 + 5 files changed, 38 insertions(+), 7 deletions(-) diff --git a/src/desktop/Window.cpp b/src/desktop/Window.cpp index 6a523eec..c71fe652 100644 --- a/src/desktop/Window.cpp +++ b/src/desktop/Window.cpp @@ -452,8 +452,10 @@ void CWindow::moveToWorkspace(PHLWORKSPACE pWorkspace) { } if (const auto SWALLOWED = m_pSwallowed.lock()) { - SWALLOWED->moveToWorkspace(pWorkspace); - SWALLOWED->m_pMonitor = m_pMonitor; + if (SWALLOWED->m_bCurrentlySwallowed) { + SWALLOWED->moveToWorkspace(pWorkspace); + SWALLOWED->m_pMonitor = m_pMonitor; + } } // update xwayland coords diff --git a/src/desktop/Window.hpp b/src/desktop/Window.hpp index 2d004855..8444a113 100644 --- a/src/desktop/Window.hpp +++ b/src/desktop/Window.hpp @@ -355,7 +355,8 @@ class CWindow { // swallowing PHLWINDOWREF m_pSwallowed; - bool m_bGroupSwallowed = false; + bool m_bCurrentlySwallowed = false; + bool m_bGroupSwallowed = false; // focus stuff bool m_bStayFocused = false; diff --git a/src/events/Windows.cpp b/src/events/Windows.cpp index a068ba07..d96bb332 100644 --- a/src/events/Windows.cpp +++ b/src/events/Windows.cpp @@ -392,6 +392,8 @@ void Events::listener_mapWindow(void* owner, void* data) { // Verify window swallowing. Get the swallower before calling onWindowCreated(PWINDOW) because getSwallower() wouldn't get it after if PWINDOW gets auto grouped. const auto SWALLOWER = PWINDOW->getSwallower(); PWINDOW->m_pSwallowed = SWALLOWER; + if (PWINDOW->m_pSwallowed) + PWINDOW->m_pSwallowed->m_bCurrentlySwallowed = true; if (PWINDOW->m_bIsFloating) { g_pLayoutManager->getCurrentLayout()->onWindowCreated(PWINDOW); @@ -731,12 +733,15 @@ void Events::listener_unmapWindow(void* owner, void* data) { // swallowing if (valid(PWINDOW->m_pSwallowed)) { - PWINDOW->m_pSwallowed->setHidden(false); + if (PWINDOW->m_pSwallowed->m_bCurrentlySwallowed) { + PWINDOW->m_pSwallowed->m_bCurrentlySwallowed = false; + PWINDOW->m_pSwallowed->setHidden(false); - if (PWINDOW->m_sGroupData.pNextWindow.lock()) - PWINDOW->m_pSwallowed->m_bGroupSwallowed = true; // flag for the swallowed window to be created into the group where it belongs when auto_group = false. + if (PWINDOW->m_sGroupData.pNextWindow.lock()) + PWINDOW->m_pSwallowed->m_bGroupSwallowed = true; // flag for the swallowed window to be created into the group where it belongs when auto_group = false. - g_pLayoutManager->getCurrentLayout()->onWindowCreated(PWINDOW->m_pSwallowed.lock()); + g_pLayoutManager->getCurrentLayout()->onWindowCreated(PWINDOW->m_pSwallowed.lock()); + } PWINDOW->m_pSwallowed->m_bGroupSwallowed = false; PWINDOW->m_pSwallowed.reset(); diff --git a/src/managers/KeybindManager.cpp b/src/managers/KeybindManager.cpp index 47cc4f67..2d6b2cb8 100644 --- a/src/managers/KeybindManager.cpp +++ b/src/managers/KeybindManager.cpp @@ -113,6 +113,7 @@ CKeybindManager::CKeybindManager() { m_mDispatchers["focuswindowbyclass"] = focusWindow; m_mDispatchers["focuswindow"] = focusWindow; m_mDispatchers["tagwindow"] = tagWindow; + m_mDispatchers["toggleswallow"] = toggleSwallow; m_mDispatchers["submap"] = setSubmap; m_mDispatchers["pass"] = pass; m_mDispatchers["sendshortcut"] = sendshortcut; @@ -2306,6 +2307,27 @@ SDispatchResult CKeybindManager::tagWindow(std::string args) { return {}; } +SDispatchResult CKeybindManager::toggleSwallow(std::string args) { + PHLWINDOWREF pWindow = g_pCompositor->m_pLastWindow; + + if (!valid(pWindow) || !valid(pWindow->m_pSwallowed)) + return {}; + + if (pWindow->m_pSwallowed->m_bCurrentlySwallowed) { + // Unswallow + pWindow->m_pSwallowed->m_bCurrentlySwallowed = false; + pWindow->m_pSwallowed->setHidden(false); + g_pLayoutManager->getCurrentLayout()->onWindowCreated(pWindow->m_pSwallowed.lock()); + } else { + // Reswallow + pWindow->m_pSwallowed->m_bCurrentlySwallowed = true; + pWindow->m_pSwallowed->setHidden(true); + g_pLayoutManager->getCurrentLayout()->onWindowRemoved(pWindow->m_pSwallowed.lock()); + } + + return {}; +} + SDispatchResult CKeybindManager::setSubmap(std::string submap) { if (submap == "reset" || submap == "") { m_szCurrentSelectedSubmap = ""; diff --git a/src/managers/KeybindManager.hpp b/src/managers/KeybindManager.hpp index cea3e3cf..712fd58d 100644 --- a/src/managers/KeybindManager.hpp +++ b/src/managers/KeybindManager.hpp @@ -199,6 +199,7 @@ class CKeybindManager { static SDispatchResult circleNext(std::string); static SDispatchResult focusWindow(std::string); static SDispatchResult tagWindow(std::string); + static SDispatchResult toggleSwallow(std::string); static SDispatchResult setSubmap(std::string); static SDispatchResult pass(std::string); static SDispatchResult sendshortcut(std::string); From 873bff390e56fb379754221d9652d0c3b850eaad Mon Sep 17 00:00:00 2001 From: nyx Date: Wed, 5 Feb 2025 09:53:09 -0500 Subject: [PATCH 0971/2181] renderer: fix missing null checks to prevent crashes (#9332) --- src/render/Renderer.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/render/Renderer.cpp b/src/render/Renderer.cpp index 6d7b409c..0fcda827 100644 --- a/src/render/Renderer.cpp +++ b/src/render/Renderer.cpp @@ -1196,7 +1196,9 @@ void CHyprRenderer::renderMonitor(PHLMONITOR pMonitor) { pMonitor->tearingState.activelyTearing = shouldTear; - if ((*PDIRECTSCANOUT == 1 || (*PDIRECTSCANOUT == 2 && pMonitor->activeWorkspace->getFullscreenWindow()->getContentType() == CONTENT_TYPE_GAME)) && !shouldTear) { + if ((*PDIRECTSCANOUT == 1 || + (*PDIRECTSCANOUT == 2 && pMonitor->activeWorkspace->getFullscreenWindow() && pMonitor->activeWorkspace->getFullscreenWindow()->getContentType() == CONTENT_TYPE_GAME)) && + !shouldTear) { if (pMonitor->attemptDirectScanout()) { return; } else if (!pMonitor->lastScanout.expired()) { From 64591c85aa212fe06fab90ea2deaccbec529c0c0 Mon Sep 17 00:00:00 2001 From: raf Date: Wed, 5 Feb 2025 14:55:33 +0000 Subject: [PATCH 0972/2181] nix: add hydraJobs output for aggregating Hyprland build jobs --- flake.nix | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/flake.nix b/flake.nix index c1c580ae..801d96ec 100644 --- a/flake.nix +++ b/flake.nix @@ -157,5 +157,11 @@ nixosModules.default = import ./nix/module.nix inputs; homeManagerModules.default = import ./nix/hm-module.nix self; + + # Hydra build jobs + # Recent versions of Hydra can aggregate jobsets from 'hydraJobs' intead of a release.nix + # or similar. Remember to filter large or incompatible attributes here. More eval jobs can + # be added by merging, e.g., self.packages // self.devShells. + hydraJobs = self.packages; }; } From 8a6778f0a087cdfc4bc1d3751b0be2c2bf3322aa Mon Sep 17 00:00:00 2001 From: Vaxry Date: Wed, 5 Feb 2025 15:41:54 +0000 Subject: [PATCH 0973/2181] scripts: don't overwrite generated version if we're not in a git repo --- scripts/generateVersion.sh | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/scripts/generateVersion.sh b/scripts/generateVersion.sh index fdcc4712..e88cef3f 100755 --- a/scripts/generateVersion.sh +++ b/scripts/generateVersion.sh @@ -1,4 +1,13 @@ #!/bin/sh + +# if the git directory doesn't exist, don't gather data to avoid overwriting, unless +# the version file is missing altogether (otherwise compiling will fail) +if [[ ! -d ./.git ]]; then + if [[ -f ./src/version.h ]]; then + exit 0 + fi +fi + cp -fr ./src/version.h.in ./src/version.h HASH=${HASH-$(git rev-parse HEAD)} From 868b2b544abb61764089b0e4e9b0fd153a9db26f Mon Sep 17 00:00:00 2001 From: nyx Date: Thu, 6 Feb 2025 06:16:47 -0500 Subject: [PATCH 0974/2181] window: fix missing surface null checks to prevent crashes (#9350) --- src/desktop/Window.cpp | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/desktop/Window.cpp b/src/desktop/Window.cpp index c71fe652..b5126b67 100644 --- a/src/desktop/Window.cpp +++ b/src/desktop/Window.cpp @@ -1730,7 +1730,10 @@ void CWindow::sendWindowSize(Vector2D size, bool force, std::optional } NContentType::eContentType CWindow::getContentType() { - return m_pWLSurface->resource()->contentType.valid() ? m_pWLSurface->resource()->contentType->value : CONTENT_TYPE_NONE; + if (!m_pWLSurface || !m_pWLSurface->resource() || !m_pWLSurface->resource()->contentType.valid()) + return CONTENT_TYPE_NONE; + + return m_pWLSurface->resource()->contentType->value; } void CWindow::setContentType(NContentType::eContentType contentType) { From f1e32cd122ad64ba7119ee7fe65f7c1074a65b91 Mon Sep 17 00:00:00 2001 From: Tom Englund Date: Thu, 6 Feb 2025 12:18:04 +0100 Subject: [PATCH 0975/2181] core: avoid .at() and use [] operator (#9347) avoid .at() where it makes sense and use [] operator in loops. --- src/desktop/Window.cpp | 8 ++++---- src/devices/IKeyboard.cpp | 20 ++++++++++---------- src/layout/MasterLayout.cpp | 2 +- src/managers/PointerManager.cpp | 2 +- src/managers/XCursorManager.cpp | 2 +- src/render/OpenGL.cpp | 8 ++++---- src/xwayland/XDataSource.cpp | 4 ++-- src/xwayland/XWM.cpp | 4 ++-- 8 files changed, 25 insertions(+), 25 deletions(-) diff --git a/src/desktop/Window.cpp b/src/desktop/Window.cpp index b5126b67..8f6d2cb5 100644 --- a/src/desktop/Window.cpp +++ b/src/desktop/Window.cpp @@ -1626,17 +1626,17 @@ PHLWINDOW CWindow::getSwallower() { if (!(*PSWALLOWREGEX).empty()) std::erase_if(candidates, [&](const auto& other) { return !RE2::FullMatch(other->m_szClass, *PSWALLOWREGEX); }); - if (candidates.size() <= 0) + if (candidates.size() == 0) return nullptr; if (!(*PSWALLOWEXREGEX).empty()) std::erase_if(candidates, [&](const auto& other) { return RE2::FullMatch(other->m_szTitle, *PSWALLOWEXREGEX); }); - if (candidates.size() <= 0) + if (candidates.size() == 0) return nullptr; if (candidates.size() == 1) - return candidates.at(0); + return candidates[0]; // walk up the focus history and find the last focused for (auto const& w : g_pCompositor->m_vWindowFocusHistory) { @@ -1648,7 +1648,7 @@ PHLWINDOW CWindow::getSwallower() { } // if none are found (??) then just return the first one - return candidates.at(0); + return candidates[0]; } void CWindow::unsetWindowData(eOverridePriority priority) { diff --git a/src/devices/IKeyboard.cpp b/src/devices/IKeyboard.cpp index 307d840b..89891ebd 100644 --- a/src/devices/IKeyboard.cpp +++ b/src/devices/IKeyboard.cpp @@ -126,14 +126,14 @@ void IKeyboard::setKeymap(const SStringRuleNames& rules) { updateModifiers(0, 0, modifiersState.locked, modifiersState.group); } - for (size_t i = 0; i < LEDNAMES.size(); ++i) { - ledIndexes.at(i) = xkb_map_led_get_index(xkbKeymap, LEDNAMES.at(i)); - Debug::log(LOG, "xkb: LED index {} (name {}) got index {}", i, LEDNAMES.at(i), ledIndexes.at(i)); + for (size_t i = 0; i < std::min(LEDNAMES.size(), ledIndexes.size()); ++i) { + ledIndexes[i] = xkb_map_led_get_index(xkbKeymap, LEDNAMES[i]); + Debug::log(LOG, "xkb: LED index {} (name {}) got index {}", i, LEDNAMES[i], ledIndexes[i]); } - for (size_t i = 0; i < MODNAMES.size(); ++i) { - modIndexes.at(i) = xkb_map_mod_get_index(xkbKeymap, MODNAMES.at(i)); - Debug::log(LOG, "xkb: Mod index {} (name {}) got index {}", i, MODNAMES.at(i), modIndexes.at(i)); + for (size_t i = 0; i < std::min(MODNAMES.size(), modIndexes.size()); ++i) { + modIndexes[i] = xkb_map_mod_get_index(xkbKeymap, MODNAMES[i]); + Debug::log(LOG, "xkb: Mod index {} (name {}) got index {}", i, MODNAMES[i], modIndexes[i]); } updateKeymapFD(); @@ -289,8 +289,8 @@ std::optional IKeyboard::getLEDs() { return {}; uint32_t leds = 0; - for (uint32_t i = 0; i < LED_COUNT; ++i) { - if (xkb_state_led_index_is_active(xkbState, ledIndexes.at(i))) + for (uint32_t i = 0; i < std::min((size_t)LED_COUNT, ledIndexes.size()); ++i) { + if (xkb_state_led_index_is_active(xkbState, ledIndexes[i])) leds |= (1 << i); } @@ -323,10 +323,10 @@ uint32_t IKeyboard::getModifiers() { uint32_t modMask = modifiersState.depressed | modifiersState.latched; uint32_t mods = 0; for (size_t i = 0; i < modIndexes.size(); ++i) { - if (modIndexes.at(i) == XKB_MOD_INVALID) + if (modIndexes[i] == XKB_MOD_INVALID) continue; - if (!(modMask & (1 << modIndexes.at(i)))) + if (!(modMask & (1 << modIndexes[i]))) continue; mods |= (1 << i); diff --git a/src/layout/MasterLayout.cpp b/src/layout/MasterLayout.cpp index 4773147f..dc301bfa 100644 --- a/src/layout/MasterLayout.cpp +++ b/src/layout/MasterLayout.cpp @@ -1357,7 +1357,7 @@ void CHyprMasterLayout::runOrientationCycle(SLayoutMessageHeader& header, CVarLi int nextOrPrev = 0; for (size_t i = 0; i < cycle.size(); ++i) { - if (PWORKSPACEDATA->orientation == cycle.at(i)) { + if (PWORKSPACEDATA->orientation == cycle[i]) { nextOrPrev = i + direction; break; } diff --git a/src/managers/PointerManager.cpp b/src/managers/PointerManager.cpp index 48ef5e16..1c8e9976 100644 --- a/src/managers/PointerManager.cpp +++ b/src/managers/PointerManager.cpp @@ -475,7 +475,7 @@ SP CPointerManager::renderHWCursorBuffer(SP> CXCursorManager::loadStandardCursors(std::string cons // load the default xcursor shapes that exist in the theme for (size_t i = 0; i < XCURSOR_STANDARD_NAMES.size(); ++i) { - std::string shape{XCURSOR_STANDARD_NAMES.at(i)}; + std::string shape{XCURSOR_STANDARD_NAMES[i]}; auto xImages = XcursorShapeLoadImages(i << 1 /* wtf xcursor? */, name.c_str(), size); if (!xImages) { diff --git a/src/render/OpenGL.cpp b/src/render/OpenGL.cpp index 75a5eadb..3b641c36 100644 --- a/src/render/OpenGL.cpp +++ b/src/render/OpenGL.cpp @@ -402,14 +402,14 @@ std::optional> CHyprOpenGLImpl::getModsForFormat(EGLint fo result.reserve(mods.size()); bool linearIsExternal = false; - for (size_t i = 0; i < mods.size(); ++i) { - if (external.at(i)) { - if (mods.at(i) == DRM_FORMAT_MOD_LINEAR) + for (size_t i = 0; i < std::min(mods.size(), external.size()); ++i) { + if (external[i]) { + if (mods[i] == DRM_FORMAT_MOD_LINEAR) linearIsExternal = true; continue; } - result.push_back(mods.at(i)); + result.push_back(mods[i]); } // if the driver doesn't mark linear as external, add it. It's allowed unless the driver says otherwise. (e.g. nvidia) diff --git a/src/xwayland/XDataSource.cpp b/src/xwayland/XDataSource.cpp index e6282dcb..9384db69 100644 --- a/src/xwayland/XDataSource.cpp +++ b/src/xwayland/XDataSource.cpp @@ -57,8 +57,8 @@ void CXDataSource::send(const std::string& mime, CFileDescriptor fd) { mimeAtom = HYPRATOMS["UTF8_STRING"]; else { for (size_t i = 0; i < mimeTypes.size(); ++i) { - if (mimeTypes.at(i) == mime) { - mimeAtom = mimeAtoms.at(i); + if (mimeTypes[i] == mime) { + mimeAtom = mimeAtoms[i]; break; } } diff --git a/src/xwayland/XWM.cpp b/src/xwayland/XWM.cpp index 81900c7b..68552dd6 100644 --- a/src/xwayland/XWM.cpp +++ b/src/xwayland/XWM.cpp @@ -1051,13 +1051,13 @@ void CXWM::readWindowData(SP surf) { }; for (size_t i = 0; i < interestingProps.size(); i++) { - xcb_get_property_cookie_t cookie = xcb_get_property(connection, 0, surf->xID, interestingProps.at(i), XCB_ATOM_ANY, 0, 2048); + xcb_get_property_cookie_t cookie = xcb_get_property(connection, 0, surf->xID, interestingProps[i], XCB_ATOM_ANY, 0, 2048); xcb_get_property_reply_t* reply = xcb_get_property_reply(connection, cookie, nullptr); if (!reply) { Debug::log(ERR, "[xwm] Failed to get window property"); continue; } - readProp(surf, interestingProps.at(i), reply); + readProp(surf, interestingProps[i], reply); free(reply); } } From ff9e059de6dd30c813270ff5a74053339cc94765 Mon Sep 17 00:00:00 2001 From: Maximilian Seidler <78690852+PaideiaDilemma@users.noreply.github.com> Date: Thu, 6 Feb 2025 11:21:04 +0000 Subject: [PATCH 0976/2181] window: move size reporting to animation begin callback (#9298) * window: fix resizes with an update callback * window: fixup sendWindowSize Remove the size argument from sendWindowSize, since it is now a member of the Window class and we don't want any mismatches between m_vRealSize and what we report. Remove sendWindowSize from mapWindow, since we shouldn't need it. * window: sendWindowSize on animation begin * window: move most calls to sendWindowSize to the animation begin callback * window: remove sendWindowSize in unmanaged if not fullscreen --- src/Compositor.cpp | 2 +- src/desktop/Window.cpp | 26 +++++++++++-------- src/desktop/Window.hpp | 2 +- src/desktop/Workspace.cpp | 2 +- src/events/Windows.cpp | 9 +------ src/layout/DwindleLayout.cpp | 4 --- src/layout/IHyprLayout.cpp | 18 +++++-------- src/layout/MasterLayout.cpp | 4 --- src/managers/KeybindManager.cpp | 1 - src/managers/XWaylandManager.cpp | 2 +- .../decorations/CHyprGroupBarDecoration.cpp | 3 --- 11 files changed, 26 insertions(+), 47 deletions(-) diff --git a/src/Compositor.cpp b/src/Compositor.cpp index a8cbae3a..e460bbca 100644 --- a/src/Compositor.cpp +++ b/src/Compositor.cpp @@ -2330,7 +2330,7 @@ void CCompositor::setWindowFullscreenState(const PHLWINDOW PWINDOW, SFullscreenS updateFullscreenFadeOnWorkspace(PWORKSPACE); - PWINDOW->sendWindowSize(PWINDOW->m_vRealSize->goal(), true); + PWINDOW->sendWindowSize(true); PWORKSPACE->forceReportSizesToWindows(); diff --git a/src/desktop/Window.cpp b/src/desktop/Window.cpp index 8f6d2cb5..b0d7b58c 100644 --- a/src/desktop/Window.cpp +++ b/src/desktop/Window.cpp @@ -458,9 +458,6 @@ void CWindow::moveToWorkspace(PHLWORKSPACE pWorkspace) { } } - // update xwayland coords - sendWindowSize(m_vRealSize->goal()); - if (OLDWORKSPACE && g_pCompositor->isWorkspaceSpecial(OLDWORKSPACE->m_iID) && OLDWORKSPACE->getWindows() == 0 && *PCLOSEONLASTSPECIAL) { if (const auto PMONITOR = OLDWORKSPACE->m_pMonitor.lock(); PMONITOR) PMONITOR->setSpecialWorkspace(nullptr); @@ -563,6 +560,15 @@ void CWindow::onMap() { *m_fBorderAngleAnimationProgress = 1.f; } + m_vRealSize->setCallbackOnBegin( + [this](auto) { + if (!m_bIsMapped || isX11OverrideRedirect()) + return; + + sendWindowSize(); + }, + false); + m_fMovingFromWorkspaceAlpha->setValueAndWarp(1.F); g_pCompositor->m_vWindowFocusHistory.push_back(m_pSelf); @@ -1315,7 +1321,6 @@ void CWindow::clampWindowSize(const std::optional minSize, const std:: *m_vRealPosition = m_vRealPosition->goal() + DELTA / 2.0; *m_vRealSize = NEWSIZE; - sendWindowSize(NEWSIZE); } bool CWindow::isFullscreen() { @@ -1539,7 +1544,7 @@ void CWindow::onX11Configure(CBox box) { g_pHyprRenderer->damageWindow(m_pSelf.lock()); if (!m_bIsFloating || isFullscreen() || g_pInputManager->currentlyDraggedWindow == m_pSelf) { - sendWindowSize(m_vRealSize->goal(), true); + sendWindowSize(true); g_pInputManager->refocus(); g_pHyprRenderer->damageWindow(m_pSelf.lock()); return; @@ -1566,8 +1571,6 @@ void CWindow::onX11Configure(CBox box) { m_vPosition = m_vRealPosition->goal(); m_vSize = m_vRealSize->goal(); - sendWindowSize(box.size(), true); - m_vPendingReportedSize = box.size(); m_vReportedSize = box.size(); @@ -1697,15 +1700,16 @@ Vector2D CWindow::requestedMaxSize() { return maxSize; } -void CWindow::sendWindowSize(Vector2D size, bool force, std::optional overridePos) { +void CWindow::sendWindowSize(bool force) { static auto PXWLFORCESCALEZERO = CConfigValue("xwayland:force_zero_scaling"); const auto PMONITOR = m_pMonitor.lock(); - size = size.clamp(Vector2D{1, 1}, Vector2D{std::numeric_limits::infinity(), std::numeric_limits::infinity()}); + Debug::log(TRACE, "sendWindowSize: window:{:x},title:{} with real pos {}, real size {} (force: {})", (uintptr_t)this, this->m_szTitle, m_vRealPosition->goal(), + m_vRealSize->goal(), force); - // calculate pos // TODO: this should be decoupled from setWindowSize IMO - Vector2D windowPos = overridePos.value_or(m_vRealPosition->goal()); + Vector2D windowPos = m_vRealPosition->goal(); + Vector2D size = m_vRealSize->goal().clamp(Vector2D{1, 1}, Vector2D{std::numeric_limits::infinity(), std::numeric_limits::infinity()}); if (m_bIsX11 && PMONITOR) { windowPos = g_pXWaylandManager->waylandToXWaylandCoords(windowPos); diff --git a/src/desktop/Window.hpp b/src/desktop/Window.hpp index 8444a113..9a4a36c2 100644 --- a/src/desktop/Window.hpp +++ b/src/desktop/Window.hpp @@ -471,7 +471,7 @@ class CWindow { bool isModal(); Vector2D requestedMinSize(); Vector2D requestedMaxSize(); - void sendWindowSize(Vector2D size, bool force = false, std::optional overridePos = std::nullopt); + void sendWindowSize(bool force = false); NContentType::eContentType getContentType(); void setContentType(NContentType::eContentType contentType); diff --git a/src/desktop/Workspace.cpp b/src/desktop/Workspace.cpp index 8dbf30b7..7f8e7fc9 100644 --- a/src/desktop/Workspace.cpp +++ b/src/desktop/Workspace.cpp @@ -624,7 +624,7 @@ void CWorkspace::forceReportSizesToWindows() { if (w->m_pWorkspace != m_pSelf || !w->m_bIsMapped || w->isHidden()) continue; - w->sendWindowSize(w->m_vRealSize->goal(), true); + w->sendWindowSize(true); } } diff --git a/src/events/Windows.cpp b/src/events/Windows.cpp index d96bb332..399894f9 100644 --- a/src/events/Windows.cpp +++ b/src/events/Windows.cpp @@ -688,13 +688,6 @@ void Events::listener_mapWindow(void* owner, void* data) { if (PMONITOR && PWINDOW->isX11OverrideRedirect()) PWINDOW->m_fX11SurfaceScaledBy = PMONITOR->scale; - - // Fix some X11 popups being invisible / having incorrect size on open. - // What the ACTUAL FUCK is going on?????? I HATE X11 - if (!PWINDOW->isX11OverrideRedirect() && PWINDOW->m_bIsX11 && PWINDOW->m_bIsFloating) { - PWINDOW->sendWindowSize(PWINDOW->m_vRealSize->goal(), true, PWINDOW->m_vRealPosition->goal() - Vector2D{1, 1}); - PWINDOW->sendWindowSize(PWINDOW->m_vRealSize->goal(), true); - } } void Events::listener_unmapWindow(void* owner, void* data) { @@ -964,7 +957,7 @@ void Events::listener_unmanagedSetGeometry(void* owner, void* data) { PWINDOW->setHidden(true); if (PWINDOW->isFullscreen() || !PWINDOW->m_bIsFloating) { - PWINDOW->sendWindowSize(PWINDOW->m_vRealSize->goal(), true); + PWINDOW->sendWindowSize(true); g_pHyprRenderer->damageWindow(PWINDOW); return; } diff --git a/src/layout/DwindleLayout.cpp b/src/layout/DwindleLayout.cpp index 8aaafaa3..ecd7abea 100644 --- a/src/layout/DwindleLayout.cpp +++ b/src/layout/DwindleLayout.cpp @@ -198,16 +198,12 @@ void CHyprDwindleLayout::applyNodeDataToWindow(SDwindleNodeData* pNode, bool for *PWINDOW->m_vRealPosition = wb.pos(); *PWINDOW->m_vRealSize = wb.size(); - - PWINDOW->sendWindowSize(wb.size()); } else { CBox wb = {calcPos, calcSize}; wb.round(); // avoid rounding mess *PWINDOW->m_vRealSize = wb.size(); *PWINDOW->m_vRealPosition = wb.pos(); - - PWINDOW->sendWindowSize(wb.size()); } if (force) { diff --git a/src/layout/IHyprLayout.cpp b/src/layout/IHyprLayout.cpp index 9a0ba6ee..e84ffb21 100644 --- a/src/layout/IHyprLayout.cpp +++ b/src/layout/IHyprLayout.cpp @@ -176,11 +176,9 @@ void IHyprLayout::onWindowCreatedFloating(PHLWINDOW pWindow) { pWindow->m_vRealSize->warp(); } - if (!pWindow->isX11OverrideRedirect()) { - pWindow->sendWindowSize(pWindow->m_vRealSize->goal()); - + if (!pWindow->isX11OverrideRedirect()) g_pCompositor->changeWindowZOrder(pWindow, true); - } else { + else { pWindow->m_vPendingReportedSize = pWindow->m_vRealSize->goal(); pWindow->m_vReportedSize = pWindow->m_vPendingReportedSize; } @@ -362,9 +360,6 @@ void IHyprLayout::onEndDragWindow() { DRAGGINGWINDOW->m_vLastFloatingSize = m_vDraggingWindowOriginalFloatSize; DRAGGINGWINDOW->m_bDraggingTiled = false; - if (pWindow->m_bIsFloating) - DRAGGINGWINDOW->sendWindowSize(DRAGGINGWINDOW->m_vRealSize->goal()); // match the size of the window - static auto USECURRPOS = CConfigValue("group:insert_after_current"); (*USECURRPOS ? pWindow : pWindow->getGroupTail())->insertWindowToGroup(DRAGGINGWINDOW); pWindow->setGroupCurrent(DRAGGINGWINDOW); @@ -606,10 +601,11 @@ void IHyprLayout::onMouseMove(const Vector2D& mousePos) { if (*PANIMATEMOUSE) *DRAGGINGWINDOW->m_vRealPosition = wb.pos(); - else + else { DRAGGINGWINDOW->m_vRealPosition->setValueAndWarp(wb.pos()); + DRAGGINGWINDOW->sendWindowSize(); + } - DRAGGINGWINDOW->sendWindowSize(DRAGGINGWINDOW->m_vRealSize->goal()); } else if (g_pInputManager->dragMode == MBIND_RESIZE || g_pInputManager->dragMode == MBIND_RESIZE_FORCE_RATIO || g_pInputManager->dragMode == MBIND_RESIZE_BLOCK_RATIO) { if (DRAGGINGWINDOW->m_bIsFloating) { @@ -679,9 +675,8 @@ void IHyprLayout::onMouseMove(const Vector2D& mousePos) { } else { DRAGGINGWINDOW->m_vRealSize->setValueAndWarp(wb.size()); DRAGGINGWINDOW->m_vRealPosition->setValueAndWarp(wb.pos()); + DRAGGINGWINDOW->sendWindowSize(); } - - DRAGGINGWINDOW->sendWindowSize(DRAGGINGWINDOW->m_vRealSize->goal()); } else { resizeActiveWindow(TICKDELTA, m_eGrabbedCorner, DRAGGINGWINDOW); } @@ -787,7 +782,6 @@ void IHyprLayout::changeWindowFloatingMode(PHLWINDOW pWindow) { g_pCompositor->updateWindowAnimatedDecorationValues(pWindow); pWindow->updateToplevel(); - pWindow->sendWindowSize(pWindow->m_vRealSize->goal()); g_pHyprRenderer->damageWindow(pWindow); } diff --git a/src/layout/MasterLayout.cpp b/src/layout/MasterLayout.cpp index dc301bfa..a429843f 100644 --- a/src/layout/MasterLayout.cpp +++ b/src/layout/MasterLayout.cpp @@ -678,16 +678,12 @@ void CHyprMasterLayout::applyNodeDataToWindow(SMasterNodeData* pNode) { *PWINDOW->m_vRealPosition = wb.pos(); *PWINDOW->m_vRealSize = wb.size(); - - PWINDOW->sendWindowSize(wb.size()); } else { CBox wb = {calcPos, calcSize}; wb.round(); // avoid rounding mess *PWINDOW->m_vRealPosition = wb.pos(); *PWINDOW->m_vRealSize = wb.size(); - - PWINDOW->sendWindowSize(wb.size()); } if (m_bForceWarps && !*PANIMATE) { diff --git a/src/managers/KeybindManager.cpp b/src/managers/KeybindManager.cpp index 2d6b2cb8..8daa6838 100644 --- a/src/managers/KeybindManager.cpp +++ b/src/managers/KeybindManager.cpp @@ -1908,7 +1908,6 @@ SDispatchResult CKeybindManager::workspaceOpt(std::string args) { if (PWORKSPACE->m_bDefaultFloating) { w->m_vRealPosition->setValueAndWarp(SAVEDPOS); w->m_vRealSize->setValueAndWarp(SAVEDSIZE); - w->sendWindowSize(SAVEDSIZE); *w->m_vRealSize = w->m_vRealSize->value() + Vector2D(4, 4); *w->m_vRealPosition = w->m_vRealPosition->value() - Vector2D(2, 2); } diff --git a/src/managers/XWaylandManager.cpp b/src/managers/XWaylandManager.cpp index a5506329..63b14962 100644 --- a/src/managers/XWaylandManager.cpp +++ b/src/managers/XWaylandManager.cpp @@ -55,7 +55,7 @@ void CHyprXWaylandManager::activateWindow(PHLWINDOW pWindow, bool activate) { if (pWindow->m_bIsX11) { if (activate) { - pWindow->sendWindowSize(pWindow->m_vRealSize->value(), true); // update xwayland output pos + pWindow->sendWindowSize(true); // update xwayland output pos pWindow->m_pXWaylandSurface->setMinimized(false); if (!pWindow->isX11OverrideRedirect()) diff --git a/src/render/decorations/CHyprGroupBarDecoration.cpp b/src/render/decorations/CHyprGroupBarDecoration.cpp index 1a64b024..32422e14 100644 --- a/src/render/decorations/CHyprGroupBarDecoration.cpp +++ b/src/render/decorations/CHyprGroupBarDecoration.cpp @@ -456,9 +456,6 @@ bool CHyprGroupBarDecoration::onEndWindowDragOnDeco(const Vector2D& pos, PHLWIND pDraggedWindow->m_bIsFloating = pWindowInsertAfter->m_bIsFloating; // match the floating state of the window - if (pWindowInsertAfter->m_bIsFloating) - pDraggedWindow->sendWindowSize(pWindowInsertAfter->m_vRealSize->goal()); // match the size of the window - pWindowInsertAfter->insertWindowToGroup(pDraggedWindow); if (WINDOWINDEX == -1) From 30b49c75bf04ceffc9fb1652a4d02e4eebacc24c Mon Sep 17 00:00:00 2001 From: vaxerski Date: Thu, 6 Feb 2025 12:13:35 +0000 Subject: [PATCH 0977/2181] popup: improve ::at() behavior --- src/desktop/Popup.cpp | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) diff --git a/src/desktop/Popup.cpp b/src/desktop/Popup.cpp index 4accb58f..82767ead 100644 --- a/src/desktop/Popup.cpp +++ b/src/desktop/Popup.cpp @@ -347,18 +347,19 @@ WP CPopup::at(const Vector2D& globalCoords, bool allowsInput) { continue; if (!allowsInput) { - const Vector2D offset = - p->m_pResource && p->m_pResource->surface ? (p->size() - p->m_pResource->geometry.size()) / 2.F - p->m_pResource->surface->current.geometry.pos() : Vector2D{}; - const Vector2D size = p->m_pResource ? p->m_pResource->geometry.size() : p->size(); + const bool HASSURFACE = p->m_pResource && p->m_pResource->surface; - const auto BOX = CBox{p->coordsGlobal() + offset, size}; + Vector2D offset = HASSURFACE ? p->m_pResource->surface->current.geometry.pos() : Vector2D{}; + Vector2D size = HASSURFACE ? p->m_pResource->surface->current.geometry.size() : p->size(); + + if (size == Vector2D{}) + size = p->size(); + + const auto BOX = CBox{p->coordsGlobal() + offset, size}; if (BOX.containsPoint(globalCoords)) return p; } else { - const Vector2D offset = - p->m_pResource && p->m_pResource->surface ? (p->size() - p->m_pResource->geometry.size()) / 2.F - p->m_pResource->surface->current.geometry.pos() : Vector2D{}; - const auto REGION = - CRegion{p->m_pWLSurface->resource()->current.input}.intersect(CBox{{}, p->m_pWLSurface->resource()->current.size}).translate(p->coordsGlobal() + offset); + const auto REGION = CRegion{p->m_pWLSurface->resource()->current.input}.intersect(CBox{{}, p->m_pWLSurface->resource()->current.size}).translate(p->coordsGlobal()); if (REGION.containsPoint(globalCoords)) return p; } From acbcf0cf115d55ef80a75ded3223a9e098f77541 Mon Sep 17 00:00:00 2001 From: WhySoBad <49595640+WhySoBad@users.noreply.github.com> Date: Thu, 6 Feb 2025 13:42:20 +0100 Subject: [PATCH 0978/2181] toplevelexport: fix transformed origin for shm buffers (#9343) * toplevelexport: fix transformed origin for shm buffers * toplevelexport: fix style nits --- src/protocols/ToplevelExport.cpp | 25 ++++++++++++++++++++++++- 1 file changed, 24 insertions(+), 1 deletion(-) diff --git a/src/protocols/ToplevelExport.cpp b/src/protocols/ToplevelExport.cpp index 8b835b50..a9009aa4 100644 --- a/src/protocols/ToplevelExport.cpp +++ b/src/protocols/ToplevelExport.cpp @@ -11,6 +11,7 @@ #include "../render/Renderer.hpp" #include +#include CToplevelExportClient::CToplevelExportClient(SP resource_) : resource(resource_) { if UNLIKELY (!good()) @@ -289,7 +290,29 @@ bool CToplevelExportFrame::copyShm(timespec* now) { glPixelStorei(GL_PACK_ALIGNMENT, 1); auto glFormat = PFORMAT->flipRB ? GL_BGRA_EXT : GL_RGBA; - glReadPixels(0, 0, box.width, box.height, glFormat, PFORMAT->glType, pixelData); + + auto origin = Vector2D(0, 0); + switch (PMONITOR->transform) { + case WL_OUTPUT_TRANSFORM_FLIPPED_180: + case WL_OUTPUT_TRANSFORM_90: { + origin.y = PMONITOR->vecPixelSize.y - box.height; + break; + } + case WL_OUTPUT_TRANSFORM_FLIPPED_270: + case WL_OUTPUT_TRANSFORM_180: { + origin.x = PMONITOR->vecPixelSize.x - box.width; + origin.y = PMONITOR->vecPixelSize.y - box.height; + break; + } + case WL_OUTPUT_TRANSFORM_FLIPPED: + case WL_OUTPUT_TRANSFORM_270: { + origin.x = PMONITOR->vecPixelSize.x - box.width; + break; + } + default: break; + } + + glReadPixels(origin.x, origin.y, box.width, box.height, glFormat, PFORMAT->glType, pixelData); if (overlayCursor) { g_pPointerManager->unlockSoftwareForMonitor(PMONITOR->self.lock()); From 54441e0c4e51dd182f78876c014446d5d0359ba8 Mon Sep 17 00:00:00 2001 From: Vaxry Date: Thu, 6 Feb 2025 17:45:25 +0000 Subject: [PATCH 0979/2181] renderer: fix fade out on silent moves to special --- src/render/Renderer.cpp | 18 +++++++++++++++--- 1 file changed, 15 insertions(+), 3 deletions(-) diff --git a/src/render/Renderer.cpp b/src/render/Renderer.cpp index 0fcda827..6f0bbe44 100644 --- a/src/render/Renderer.cpp +++ b/src/render/Renderer.cpp @@ -379,7 +379,10 @@ void CHyprRenderer::renderWorkspaceWindows(PHLMONITOR pMonitor, PHLWORKSPACE pWo if (w->m_bIsFloating) continue; // floating are in the second pass - if (pWorkspace->m_bIsSpecialWorkspace != w->onSpecialWorkspace()) + // some things may force us to ignore the special/not special disparity + const bool IGNORE_SPECIAL_CHECK = w->m_iMonitorMovedFrom != -1 && (w->m_pWorkspace && !w->m_pWorkspace->isVisible()); + + if (!IGNORE_SPECIAL_CHECK && pWorkspace->m_bIsSpecialWorkspace != w->onSpecialWorkspace()) continue; // render active window after all others of this pass @@ -390,11 +393,14 @@ void CHyprRenderer::renderWorkspaceWindows(PHLMONITOR pMonitor, PHLWORKSPACE pWo // render the bad boy renderWindow(w.lock(), pMonitor, time, true, RENDER_PASS_MAIN); + w.reset(); } if (lastWindow) renderWindow(lastWindow, pMonitor, time, true, RENDER_PASS_MAIN); + lastWindow.reset(); + // Non-floating popup for (auto& w : windows) { if (!w) @@ -403,7 +409,10 @@ void CHyprRenderer::renderWorkspaceWindows(PHLMONITOR pMonitor, PHLWORKSPACE pWo if (w->m_bIsFloating) continue; // floating are in the second pass - if (pWorkspace->m_bIsSpecialWorkspace != w->onSpecialWorkspace()) + // some things may force us to ignore the special/not special disparity + const bool IGNORE_SPECIAL_CHECK = w->m_iMonitorMovedFrom != -1 && (w->m_pWorkspace && !w->m_pWorkspace->isVisible()); + + if (!IGNORE_SPECIAL_CHECK && pWorkspace->m_bIsSpecialWorkspace != w->onSpecialWorkspace()) continue; // render the bad boy @@ -419,7 +428,10 @@ void CHyprRenderer::renderWorkspaceWindows(PHLMONITOR pMonitor, PHLWORKSPACE pWo if (!w->m_bIsFloating || w->m_bPinned) continue; - if (pWorkspace->m_bIsSpecialWorkspace != w->onSpecialWorkspace()) + // some things may force us to ignore the special/not special disparity + const bool IGNORE_SPECIAL_CHECK = w->m_iMonitorMovedFrom != -1 && (w->m_pWorkspace && !w->m_pWorkspace->isVisible()); + + if (!IGNORE_SPECIAL_CHECK && pWorkspace->m_bIsSpecialWorkspace != w->onSpecialWorkspace()) continue; if (pWorkspace->m_bIsSpecialWorkspace && w->m_pMonitor != pWorkspace->m_pMonitor) From a724332eb82c33308a8cb6127172f128e3afe14c Mon Sep 17 00:00:00 2001 From: Paul Cross <3613973+kreejzak@users.noreply.github.com> Date: Sat, 8 Feb 2025 01:45:13 +0100 Subject: [PATCH 0980/2181] desktop: add ability to target pinned windows in workspace rules (#9344) * desktop: add ability to target pinned windows in workspace rules * desktop: add ability to target pinned windows in workspace rules * fix formating --- src/desktop/Workspace.cpp | 21 +++++++++++++++++---- src/desktop/Workspace.hpp | 4 ++-- 2 files changed, 19 insertions(+), 6 deletions(-) diff --git a/src/desktop/Workspace.cpp b/src/desktop/Workspace.cpp index 7f8e7fc9..f2c22195 100644 --- a/src/desktop/Workspace.cpp +++ b/src/desktop/Workspace.cpp @@ -261,6 +261,7 @@ bool CWorkspace::matchesStaticSelector(const std::string& selector_) { // n - named: n[true] or n[s:string] or n[e:string] // m - monitor: m[monitor_selector] // w - windowCount: w[1-4] or w[1], optional flag t or f for tiled or floating and + // flag p to count only pinned windows, e.g. w[p1-2], w[pg4] // flag g to count groups instead of windows, e.g. w[t1-2], w[fg4] // flag v will count only visible windows // f - fullscreen state : f[-1], f[0], f[1], or f[2] for different fullscreen states @@ -370,6 +371,7 @@ bool CWorkspace::matchesStaticSelector(const std::string& selector_) { prop = prop.substr(2, prop.length() - 3); int wantsOnlyTiled = -1; + int wantsOnlyPinned = false; bool wantsCountGroup = false; bool wantsCountVisible = false; @@ -381,6 +383,9 @@ bool CWorkspace::matchesStaticSelector(const std::string& selector_) { } else if (flag == 'f' && wantsOnlyTiled == -1) { wantsOnlyTiled = 0; flagCount++; + } else if (flag == 'p' && !wantsOnlyPinned) { + wantsOnlyPinned = true; + flagCount++; } else if (flag == 'g' && !wantsCountGroup) { wantsCountGroup = true; flagCount++; @@ -411,9 +416,11 @@ bool CWorkspace::matchesStaticSelector(const std::string& selector_) { int count; if (wantsCountGroup) count = getGroups(wantsOnlyTiled == -1 ? std::nullopt : std::optional((bool)wantsOnlyTiled), + wantsOnlyPinned ? std::optional(wantsOnlyPinned) : std::nullopt, wantsCountVisible ? std::optional(wantsCountVisible) : std::nullopt); else count = getWindows(wantsOnlyTiled == -1 ? std::nullopt : std::optional((bool)wantsOnlyTiled), + wantsOnlyPinned ? std::optional(wantsOnlyPinned) : std::nullopt, wantsCountVisible ? std::optional(wantsCountVisible) : std::nullopt); if (count != from) @@ -444,10 +451,12 @@ bool CWorkspace::matchesStaticSelector(const std::string& selector_) { WORKSPACEID count; if (wantsCountGroup) - count = getGroups(wantsOnlyTiled == -1 ? std::nullopt : std::optional((bool)wantsOnlyTiled), - wantsCountVisible ? std::optional(wantsCountVisible) : std::nullopt); + count = + getGroups(wantsOnlyTiled == -1 ? std::nullopt : std::optional((bool)wantsOnlyTiled), + wantsOnlyPinned ? std::optional(wantsOnlyPinned) : std::nullopt, wantsCountVisible ? std::optional(wantsCountVisible) : std::nullopt); else count = getWindows(wantsOnlyTiled == -1 ? std::nullopt : std::optional((bool)wantsOnlyTiled), + wantsOnlyPinned ? std::optional(wantsOnlyPinned) : std::nullopt, wantsCountVisible ? std::optional(wantsCountVisible) : std::nullopt); if (std::clamp(count, from, to) != count) @@ -535,13 +544,15 @@ bool CWorkspace::isVisibleNotCovered() { return PMONITOR->activeWorkspace->m_iID == m_iID; } -int CWorkspace::getWindows(std::optional onlyTiled, std::optional onlyVisible) { +int CWorkspace::getWindows(std::optional onlyTiled, std::optional onlyPinned, std::optional onlyVisible) { int no = 0; for (auto const& w : g_pCompositor->m_vWindows) { if (w->workspaceID() != m_iID || !w->m_bIsMapped) continue; if (onlyTiled.has_value() && w->m_bIsFloating == onlyTiled.value()) continue; + if (onlyPinned.has_value() && w->m_bPinned != onlyPinned.value()) + continue; if (onlyVisible.has_value() && w->isHidden() == onlyVisible.value()) continue; no++; @@ -550,7 +561,7 @@ int CWorkspace::getWindows(std::optional onlyTiled, std::optional on return no; } -int CWorkspace::getGroups(std::optional onlyTiled, std::optional onlyVisible) { +int CWorkspace::getGroups(std::optional onlyTiled, std::optional onlyPinned, std::optional onlyVisible) { int no = 0; for (auto const& w : g_pCompositor->m_vWindows) { if (w->workspaceID() != m_iID || !w->m_bIsMapped) @@ -559,6 +570,8 @@ int CWorkspace::getGroups(std::optional onlyTiled, std::optional onl continue; if (onlyTiled.has_value() && w->m_bIsFloating == onlyTiled.value()) continue; + if (onlyPinned.has_value() && w->m_bPinned != onlyPinned.value()) + continue; if (onlyVisible.has_value() && w->isHidden() == onlyVisible.value()) continue; no++; diff --git a/src/desktop/Workspace.hpp b/src/desktop/Workspace.hpp index e9859d4f..12dbe328 100644 --- a/src/desktop/Workspace.hpp +++ b/src/desktop/Workspace.hpp @@ -72,8 +72,8 @@ class CWorkspace { SWorkspaceIDName getPrevWorkspaceIDName() const; void updateWindowDecos(); void updateWindowData(); - int getWindows(std::optional onlyTiled = {}, std::optional onlyVisible = {}); - int getGroups(std::optional onlyTiled = {}, std::optional onlyVisible = {}); + int getWindows(std::optional onlyTiled = {}, std::optional onlyPinned = {}, std::optional onlyVisible = {}); + int getGroups(std::optional onlyTiled = {}, std::optional onlyPinned = {}, std::optional onlyVisible = {}); bool hasUrgentWindow(); PHLWINDOW getFirstWindow(); PHLWINDOW getTopLeftWindow(); From f7fcbe32c9f66bcfc86853a5cda95edcf481f573 Mon Sep 17 00:00:00 2001 From: Tom Englund Date: Sat, 8 Feb 2025 01:46:26 +0100 Subject: [PATCH 0981/2181] renderer: various fixes towards improving gpu calls robustness (#9188) ensure framebuffer textures are detached and deleted, avoid leaving framebuffers bound when not needed * render: avoid calling glDeleteProgram on no program its safe to do so but it adds a bunch of unnecessery lines in apitrace when tracing. if guard it and return early. * opengl: ensure texture and buffers are unbound ensure bound buffers are unbound after use, also detach textures from framebuffer before deleting it otherwise it will become dangling and essentially leak. --- src/protocols/Screencopy.cpp | 6 ++++ src/protocols/ToplevelExport.cpp | 6 ++++ src/render/Framebuffer.cpp | 56 +++++++++++++++++--------------- src/render/Framebuffer.hpp | 3 +- src/render/OpenGL.hpp | 2 -- src/render/Renderbuffer.cpp | 8 ++--- src/render/Shader.cpp | 5 ++- 7 files changed, 50 insertions(+), 36 deletions(-) diff --git a/src/protocols/Screencopy.cpp b/src/protocols/Screencopy.cpp index e086cc76..aae5caf1 100644 --- a/src/protocols/Screencopy.cpp +++ b/src/protocols/Screencopy.cpp @@ -289,6 +289,12 @@ bool CScreencopyFrame::copyShm() { g_pHyprOpenGL->m_RenderData.pMonitor.reset(); +#ifndef GLES2 + glBindFramebuffer(GL_READ_FRAMEBUFFER, 0); +#else + glBindFramebuffer(GL_FRAMEBUFFER, 0); +#endif + LOGM(TRACE, "Copied frame via shm"); return true; diff --git a/src/protocols/ToplevelExport.cpp b/src/protocols/ToplevelExport.cpp index a9009aa4..fb0bd9c7 100644 --- a/src/protocols/ToplevelExport.cpp +++ b/src/protocols/ToplevelExport.cpp @@ -319,6 +319,12 @@ bool CToplevelExportFrame::copyShm(timespec* now) { g_pPointerManager->damageCursor(PMONITOR->self.lock()); } + outFB.unbind(); + +#ifndef GLES2 + glBindFramebuffer(GL_READ_FRAMEBUFFER, 0); +#endif + return true; } diff --git a/src/render/Framebuffer.cpp b/src/render/Framebuffer.cpp index 93f8fe7f..6905eb36 100644 --- a/src/render/Framebuffer.cpp +++ b/src/render/Framebuffer.cpp @@ -12,29 +12,26 @@ bool CFramebuffer::alloc(int w, int h, uint32_t drmFormat) { uint32_t glFormat = NFormatUtils::drmFormatToGL(drmFormat); uint32_t glType = NFormatUtils::glFormatToType(glFormat); - if (!m_cTex) + if (!m_cTex) { m_cTex = makeShared(); - - if (!m_iFbAllocated) { - firstAlloc = true; - glGenFramebuffers(1, &m_iFb); - m_iFbAllocated = true; - } - - if (m_cTex->m_iTexID == 0) { - firstAlloc = true; m_cTex->allocate(); glBindTexture(GL_TEXTURE_2D, m_cTex->m_iTexID); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); + firstAlloc = true; + } + + if (!m_iFbAllocated) { + glGenFramebuffers(1, &m_iFb); + m_iFbAllocated = true; + firstAlloc = true; } if (firstAlloc || m_vSize != Vector2D(w, h)) { glBindTexture(GL_TEXTURE_2D, m_cTex->m_iTexID); glTexImage2D(GL_TEXTURE_2D, 0, glFormat, w, h, 0, GL_RGBA, glType, nullptr); - glBindFramebuffer(GL_FRAMEBUFFER, m_iFb); glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, m_cTex->m_iTexID, 0); @@ -43,9 +40,6 @@ bool CFramebuffer::alloc(int w, int h, uint32_t drmFormat) { if (m_pStencilTex) { glBindTexture(GL_TEXTURE_2D, m_pStencilTex->m_iTexID); glTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH24_STENCIL8, w, h, 0, GL_DEPTH_STENCIL, GL_UNSIGNED_INT_24_8, nullptr); - - glBindFramebuffer(GL_FRAMEBUFFER, m_iFb); - glFramebufferTexture2D(GL_FRAMEBUFFER, GL_STENCIL_ATTACHMENT, GL_TEXTURE_2D, m_pStencilTex->m_iTexID, 0); } #endif @@ -57,8 +51,7 @@ bool CFramebuffer::alloc(int w, int h, uint32_t drmFormat) { } glBindTexture(GL_TEXTURE_2D, 0); - if (g_pHyprOpenGL) - glBindFramebuffer(GL_FRAMEBUFFER, g_pHyprOpenGL->m_iCurrentOutputFb); + glBindFramebuffer(GL_FRAMEBUFFER, 0); m_vSize = Vector2D(w, h); @@ -80,7 +73,7 @@ void CFramebuffer::addStencil(SP tex) { RASSERT((status == GL_FRAMEBUFFER_COMPLETE), "Failed adding a stencil to fbo!", status); glBindTexture(GL_TEXTURE_2D, 0); - glBindFramebuffer(GL_FRAMEBUFFER, g_pHyprOpenGL->m_iCurrentOutputFb); + glBindFramebuffer(GL_FRAMEBUFFER, 0); #endif } @@ -90,25 +83,36 @@ void CFramebuffer::bind() { #else glBindFramebuffer(GL_FRAMEBUFFER, m_iFb); #endif + if (g_pHyprOpenGL) glViewport(0, 0, g_pHyprOpenGL->m_RenderData.pMonitor->vecPixelSize.x, g_pHyprOpenGL->m_RenderData.pMonitor->vecPixelSize.y); else glViewport(0, 0, m_vSize.x, m_vSize.y); } +void CFramebuffer::unbind() { +#ifndef GLES2 + glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0); +#else + glBindFramebuffer(GL_FRAMEBUFFER, 0); +#endif +} + void CFramebuffer::release() { - if (!m_iFbAllocated && !m_cTex) - return; + if (m_iFbAllocated) { + glBindFramebuffer(GL_FRAMEBUFFER, m_iFb); + glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, 0, 0); + glBindFramebuffer(GL_FRAMEBUFFER, 0); - Debug::log(TRACE, "fb {} released", m_iFb); - - if (m_iFbAllocated) glDeleteFramebuffers(1, &m_iFb); + m_iFbAllocated = false; + m_iFb = 0; + } - m_cTex.reset(); - m_iFbAllocated = false; - m_vSize = Vector2D(); - m_iFb = 0; + if (m_cTex) + m_cTex.reset(); + + m_vSize = Vector2D(); } CFramebuffer::~CFramebuffer() { diff --git a/src/render/Framebuffer.hpp b/src/render/Framebuffer.hpp index 84dfeef1..092e548e 100644 --- a/src/render/Framebuffer.hpp +++ b/src/render/Framebuffer.hpp @@ -11,6 +11,7 @@ class CFramebuffer { bool alloc(int w, int h, uint32_t format = GL_RGBA); void addStencil(SP tex); void bind(); + void unbind(); void release(); void reset(); bool isAllocated(); @@ -28,4 +29,4 @@ class CFramebuffer { SP m_pStencilTex; friend class CRenderbuffer; -}; \ No newline at end of file +}; diff --git a/src/render/OpenGL.hpp b/src/render/OpenGL.hpp index 7b7b7e6f..cf1d2549 100644 --- a/src/render/OpenGL.hpp +++ b/src/render/OpenGL.hpp @@ -233,8 +233,6 @@ class CHyprOpenGLImpl { SCurrentRenderData m_RenderData; - GLint m_iCurrentOutputFb = 0; - Hyprutils::OS::CFileDescriptor m_iGBMFD; gbm_device* m_pGbmDevice = nullptr; EGLContext m_pEglContext = nullptr; diff --git a/src/render/Renderbuffer.cpp b/src/render/Renderbuffer.cpp index 887f31a9..1ea9f785 100644 --- a/src/render/Renderbuffer.cpp +++ b/src/render/Renderbuffer.cpp @@ -46,7 +46,7 @@ CRenderbuffer::CRenderbuffer(SP buffer, uint32_t format) : return; } - glBindFramebuffer(GL_FRAMEBUFFER, 0); + m_sFramebuffer.unbind(); listeners.destroyBuffer = buffer->events.destroy.registerListener([this](std::any d) { g_pHyprRenderer->onRenderbufferDestroy(this); }); @@ -68,11 +68,7 @@ void CRenderbuffer::bindFB() { void CRenderbuffer::unbind() { glBindRenderbuffer(GL_RENDERBUFFER, 0); -#ifndef GLES2 - glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0); -#else - glBindFramebuffer(GL_FRAMEBUFFER, 0); -#endif + m_sFramebuffer.unbind(); } CFramebuffer* CRenderbuffer::getFB() { diff --git a/src/render/Shader.cpp b/src/render/Shader.cpp index b494d79d..984d8ce3 100644 --- a/src/render/Shader.cpp +++ b/src/render/Shader.cpp @@ -17,7 +17,10 @@ CShader::~CShader() { } void CShader::destroy() { + if (program == 0) + return; + glDeleteProgram(program); program = 0; -} \ No newline at end of file +} From feb8ad48f0153a15b96356f280dbd04849db0e04 Mon Sep 17 00:00:00 2001 From: nyx Date: Sat, 8 Feb 2025 09:05:44 -0500 Subject: [PATCH 0982/2181] groups: deactivate unfocused windows in groups (#9354) --- src/Compositor.cpp | 3 +++ src/desktop/Window.cpp | 16 ++++++++++++++++ src/desktop/Window.hpp | 1 + 3 files changed, 20 insertions(+) diff --git a/src/Compositor.cpp b/src/Compositor.cpp index e460bbca..aebb0ac1 100644 --- a/src/Compositor.cpp +++ b/src/Compositor.cpp @@ -1189,6 +1189,9 @@ void CCompositor::focusWindow(PHLWINDOW pWindow, SP pSurface if (*PFOLLOWMOUSE == 0) g_pInputManager->sendMotionEventsToFocused(); + + if (pWindow->m_sGroupData.pNextWindow) + pWindow->deactivateGroupMembers(); } void CCompositor::focusSurface(SP pSurface, PHLWINDOW pWindowOwner) { diff --git a/src/desktop/Window.cpp b/src/desktop/Window.cpp index b0d7b58c..7c0cb741 100644 --- a/src/desktop/Window.cpp +++ b/src/desktop/Window.cpp @@ -1748,3 +1748,19 @@ void CWindow::setContentType(NContentType::eContentType contentType) { Debug::log(INFO, "ContentType for window {}", (int)contentType); m_pWLSurface->resource()->contentType->value = contentType; } + +void CWindow::deactivateGroupMembers() { + auto curr = getGroupHead(); + while (curr) { + if (curr != m_pSelf.lock()) { + if (curr->m_bIsX11) + curr->m_pXWaylandSurface->activate(false); + else if (curr->m_pXDGSurface && curr->m_pXDGSurface->toplevel) + curr->m_pXDGSurface->toplevel->setActive(false); + } + + curr = curr->m_sGroupData.pNextWindow.lock(); + if (curr == getGroupHead()) + break; + } +} diff --git a/src/desktop/Window.hpp b/src/desktop/Window.hpp index 9a4a36c2..171a15f4 100644 --- a/src/desktop/Window.hpp +++ b/src/desktop/Window.hpp @@ -474,6 +474,7 @@ class CWindow { void sendWindowSize(bool force = false); NContentType::eContentType getContentType(); void setContentType(NContentType::eContentType contentType); + void deactivateGroupMembers(); CBox getWindowMainSurfaceBox() const { return {m_vRealPosition->value().x, m_vRealPosition->value().y, m_vRealSize->value().x, m_vRealSize->value().y}; From 8e10ddb592977ef2e1836e75b0e5550ba8fb56f0 Mon Sep 17 00:00:00 2001 From: Honkazel <169346573+Honkazel@users.noreply.github.com> Date: Sun, 9 Feb 2025 02:00:55 +0500 Subject: [PATCH 0983/2181] datadevice: fix wrong param (#9370) Reason: look at the setReceive parameters and also at the next line(tries to narrow) --- src/protocols/core/DataDevice.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/protocols/core/DataDevice.cpp b/src/protocols/core/DataDevice.cpp index 0931608a..25117265 100644 --- a/src/protocols/core/DataDevice.cpp +++ b/src/protocols/core/DataDevice.cpp @@ -39,7 +39,7 @@ CWLDataOfferResource::CWLDataOfferResource(SP resource_, SPsetReceive([this](CWlDataOffer* r, const char* mime, uint32_t fd) { + resource->setReceive([this](CWlDataOffer* r, const char* mime, int fd) { CFileDescriptor sendFd{fd}; if (!source) { LOGM(WARN, "Possible bug: Receive on an offer w/o a source"); From 56f6f61596a547cdcdfb7aa7c3550e380b487ee3 Mon Sep 17 00:00:00 2001 From: clamydo <13063485+clamydo@users.noreply.github.com> Date: Sun, 9 Feb 2025 15:30:30 +0100 Subject: [PATCH 0984/2181] tablet: take `active_area_size` into account when sending tip event (#9325) * fixes #9322, take `active_area_size` into account when sending tip event * check if `relative_input` is set As suggested by @y47s5s68tq870r7tc1xpp755pabopg * refactoring active area in own function to keep it DRY * coding style * making transformation static --------- Co-authored-by: clamydo --- src/managers/input/Tablets.cpp | 34 +++++++++++++++++++++++----------- 1 file changed, 23 insertions(+), 11 deletions(-) diff --git a/src/managers/input/Tablets.cpp b/src/managers/input/Tablets.cpp index 0952a7d4..e1a2f2aa 100644 --- a/src/managers/input/Tablets.cpp +++ b/src/managers/input/Tablets.cpp @@ -88,6 +88,20 @@ static void refocusTablet(SP tab, SP tool, bool motion = f PROTO::tablet->motion(tool, local); } +static Vector2D transformToActiveRegion(const Vector2D pos, const CBox activeArea) { + auto newPos = pos; + + //Calculate transformations if active area is set + if (!activeArea.empty()) { + if (!std::isnan(pos.x)) + newPos.x = (pos.x - activeArea.x) / (activeArea.w - activeArea.x); + if (!std::isnan(pos.y)) + newPos.y = (pos.y - activeArea.y) / (activeArea.h - activeArea.y); + } + + return newPos; +} + void CInputManager::onTabletAxis(CTablet::SAxisEvent e) { const auto PTAB = e.tablet; const auto PTOOL = ensureTabletToolPresent(e.tool); @@ -113,16 +127,9 @@ void CInputManager::onTabletAxis(CTablet::SAxisEvent e) { if (PTAB->relativeInput) g_pPointerManager->move(delta); - else { - //Calculate transformations if active area is set - if (!PTAB->activeArea.empty()) { - if (!std::isnan(x)) - x = (x - PTAB->activeArea.x) / (PTAB->activeArea.w - PTAB->activeArea.x); - if (!std::isnan(y)) - y = (y - PTAB->activeArea.y) / (PTAB->activeArea.h - PTAB->activeArea.y); - } - g_pPointerManager->warpAbsolute({x, y}, PTAB); - } + else + g_pPointerManager->warpAbsolute(transformToActiveRegion({x, y}, PTAB->activeArea), PTAB); + break; } } @@ -160,7 +167,12 @@ void CInputManager::onTabletTip(CTablet::STipEvent e) { const auto PTAB = e.tablet; const auto PTOOL = ensureTabletToolPresent(e.tool); const auto POS = e.tip; - g_pPointerManager->warpAbsolute(POS, PTAB); + + if (PTAB->relativeInput) + g_pPointerManager->move({0, 0}); + else + g_pPointerManager->warpAbsolute(transformToActiveRegion(POS, PTAB->activeArea), PTAB); + refocusTablet(PTAB, PTOOL, true); if (e.in) From 1f97643e830d513cafc2057860bbefa5cc01a0ee Mon Sep 17 00:00:00 2001 From: Vaxry Date: Sun, 9 Feb 2025 17:38:20 +0000 Subject: [PATCH 0985/2181] core: add mallopt to modify trim threshold --- src/Compositor.cpp | 14 ++++++++++++++ src/Compositor.hpp | 5 +++-- 2 files changed, 17 insertions(+), 2 deletions(-) diff --git a/src/Compositor.cpp b/src/Compositor.cpp index aebb0ac1..88a2530b 100644 --- a/src/Compositor.cpp +++ b/src/Compositor.cpp @@ -69,6 +69,8 @@ #include #include #include +#include +#include using namespace Hyprutils::String; using namespace Aquamarine; @@ -162,10 +164,22 @@ void CCompositor::restoreNofile() { Debug::log(ERR, "Failed restoring NOFILE limits"); } +void CCompositor::setMallocThreshold() { +#ifdef M_TRIM_THRESHOLD + // The default is 128 pages, + // which is very large and can lead to a lot of memory used for no reason + // because trimming hasn't happened + static const int PAGESIZE = sysconf(_SC_PAGESIZE); + mallopt(M_TRIM_THRESHOLD, 6 * PAGESIZE); +#endif +} + CCompositor::CCompositor(bool onlyConfig) : m_bOnlyConfigVerification(onlyConfig), m_iHyprlandPID(getpid()) { if (onlyConfig) return; + setMallocThreshold(); + m_szHyprTempDataRoot = std::string{getenv("XDG_RUNTIME_DIR")} + "/hypr"; if (m_szHyprTempDataRoot.starts_with("/hypr")) { diff --git a/src/Compositor.hpp b/src/Compositor.hpp index a57095a3..893ffadd 100644 --- a/src/Compositor.hpp +++ b/src/Compositor.hpp @@ -52,8 +52,6 @@ class CCompositor { void startCompositor(); void stopCompositor(); void cleanup(); - void createLockFile(); - void removeLockFile(); void bumpNofile(); void restoreNofile(); @@ -163,6 +161,9 @@ class CCompositor { void setRandomSplash(); void initManagers(eManagersInitStage stage); void prepareFallbackOutput(); + void createLockFile(); + void removeLockFile(); + void setMallocThreshold(); uint64_t m_iHyprlandPID = 0; wl_event_source* m_critSigSource = nullptr; From 3a43e7bb9a787755639838d7cb005a9d33f8c6f2 Mon Sep 17 00:00:00 2001 From: Vaxry Date: Sun, 9 Feb 2025 17:50:54 +0000 Subject: [PATCH 0986/2181] config: default movefocus_cycles_fullscreen to false less confusing --- src/config/ConfigDescriptions.hpp | 2 +- src/config/ConfigManager.cpp | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/config/ConfigDescriptions.hpp b/src/config/ConfigDescriptions.hpp index 28cd29c4..8d1b73c4 100644 --- a/src/config/ConfigDescriptions.hpp +++ b/src/config/ConfigDescriptions.hpp @@ -1234,7 +1234,7 @@ inline static const std::vector CONFIG_OPTIONS = { .value = "binds:movefocus_cycles_fullscreen", .description = "If enabled, when on a fullscreen window, movefocus will cycle fullscreen, if not, it will move the focus in a direction.", .type = CONFIG_OPTION_BOOL, - .data = SConfigOptionDescription::SBoolData{true}, + .data = SConfigOptionDescription::SBoolData{false}, }, SConfigOptionDescription{ .value = "binds:movefocus_cycles_groupfirst", diff --git a/src/config/ConfigManager.cpp b/src/config/ConfigManager.cpp index 3f45ddfe..f87a5e6b 100644 --- a/src/config/ConfigManager.cpp +++ b/src/config/ConfigManager.cpp @@ -594,7 +594,7 @@ CConfigManager::CConfigManager() { m_pConfig->addConfigValue("binds:workspace_center_on", Hyprlang::INT{1}); m_pConfig->addConfigValue("binds:focus_preferred_method", Hyprlang::INT{0}); m_pConfig->addConfigValue("binds:ignore_group_lock", Hyprlang::INT{0}); - m_pConfig->addConfigValue("binds:movefocus_cycles_fullscreen", Hyprlang::INT{1}); + m_pConfig->addConfigValue("binds:movefocus_cycles_fullscreen", Hyprlang::INT{0}); m_pConfig->addConfigValue("binds:movefocus_cycles_groupfirst", Hyprlang::INT{0}); m_pConfig->addConfigValue("binds:disable_keybind_grabbing", Hyprlang::INT{0}); m_pConfig->addConfigValue("binds:window_direction_monitor_fallback", Hyprlang::INT{1}); From f261fb6fe028a1427cfd672eee6e7d5705cd696f Mon Sep 17 00:00:00 2001 From: Vaxry Date: Sun, 9 Feb 2025 17:58:09 +0000 Subject: [PATCH 0987/2181] groupbar: fix groupbar missing when indicator_height is <= 0 ref #9291 #9372 --- .../decorations/CHyprGroupBarDecoration.cpp | 188 +++++++++--------- 1 file changed, 95 insertions(+), 93 deletions(-) diff --git a/src/render/decorations/CHyprGroupBarDecoration.cpp b/src/render/decorations/CHyprGroupBarDecoration.cpp index 32422e14..4e430bef 100644 --- a/src/render/decorations/CHyprGroupBarDecoration.cpp +++ b/src/render/decorations/CHyprGroupBarDecoration.cpp @@ -99,7 +99,11 @@ void CHyprGroupBarDecoration::draw(PHLMONITOR pMonitor, float const& a) { // get how many bars we will draw int barsToDraw = m_dwGroupMembers.size(); - static auto PENABLED = CConfigValue("group:groupbar:enabled"); + static auto PENABLED = CConfigValue("group:groupbar:enabled"); + + if (!*PENABLED || !m_pWindow->m_sWindowData.decorate.valueOrDefault()) + return; + static auto PRENDERTITLES = CConfigValue("group:groupbar:render_titles"); static auto PTITLEFONTSIZE = CConfigValue("group:groupbar:font_size"); static auto PHEIGHT = CConfigValue("group:groupbar:height"); @@ -110,14 +114,19 @@ void CHyprGroupBarDecoration::draw(PHLMONITOR pMonitor, float const& a) { static auto PGRADIENTROUNDING = CConfigValue("group:groupbar:gradient_rounding"); static auto PGRADIENTROUNDINGONLYEDGES = CConfigValue("group:groupbar:gradient_round_only_edges"); static auto PROUNDONLYEDGES = CConfigValue("group:groupbar:round_only_edges"); + static auto PGROUPCOLACTIVE = CConfigValue("group:groupbar:col.active"); + static auto PGROUPCOLINACTIVE = CConfigValue("group:groupbar:col.inactive"); + static auto PGROUPCOLACTIVELOCKED = CConfigValue("group:groupbar:col.locked_active"); + static auto PGROUPCOLINACTIVELOCKED = CConfigValue("group:groupbar:col.locked_inactive"); + auto* const GROUPCOLACTIVE = (CGradientValueData*)(PGROUPCOLACTIVE.ptr())->getData(); + auto* const GROUPCOLINACTIVE = (CGradientValueData*)(PGROUPCOLINACTIVE.ptr())->getData(); + auto* const GROUPCOLACTIVELOCKED = (CGradientValueData*)(PGROUPCOLACTIVELOCKED.ptr())->getData(); + auto* const GROUPCOLINACTIVELOCKED = (CGradientValueData*)(PGROUPCOLINACTIVELOCKED.ptr())->getData(); - if (!*PENABLED || !m_pWindow->m_sWindowData.decorate.valueOrDefault()) - return; + const auto ASSIGNEDBOX = assignedBoxGlobal(); - const auto ASSIGNEDBOX = assignedBoxGlobal(); - - const auto ONEBARHEIGHT = BAR_PADDING_OUTER_VERT + *PINDICATORHEIGHT + (*PGRADIENTS || *PRENDERTITLES ? *PHEIGHT : 0); - m_fBarWidth = *PSTACKED ? ASSIGNEDBOX.w : (ASSIGNEDBOX.w - BAR_HORIZONTAL_PADDING * (barsToDraw - 1)) / barsToDraw; + const auto ONEBARHEIGHT = BAR_PADDING_OUTER_VERT + *PINDICATORHEIGHT + (*PGRADIENTS || *PRENDERTITLES ? *PHEIGHT : 0); + m_fBarWidth = *PSTACKED ? ASSIGNEDBOX.w : (ASSIGNEDBOX.w - BAR_HORIZONTAL_PADDING * (barsToDraw - 1)) / barsToDraw; m_fBarHeight = *PSTACKED ? ((ASSIGNEDBOX.h - 2 - BAR_PADDING_OUTER_VERT) - BAR_PADDING_OUTER_VERT * (barsToDraw)) / barsToDraw : ASSIGNEDBOX.h - BAR_PADDING_OUTER_VERT; const auto DESIREDHEIGHT = *PSTACKED ? (ONEBARHEIGHT * m_dwGroupMembers.size()) + 2 + BAR_PADDING_OUTER_VERT : BAR_PADDING_OUTER_VERT * 2L + ONEBARHEIGHT; @@ -134,116 +143,109 @@ void CHyprGroupBarDecoration::draw(PHLMONITOR pMonitor, float const& a) { ASSIGNEDBOX.y + ASSIGNEDBOX.h - floor(yoff) - *PINDICATORHEIGHT - BAR_PADDING_OUTER_VERT - pMonitor->vecPosition.y + m_pWindow->m_vFloatingOffset.y, m_fBarWidth, *PINDICATORHEIGHT}; - if (rect.width <= 0 || rect.height <= 0) - break; - rect.scale(pMonitor->scale); - static auto PGROUPCOLACTIVE = CConfigValue("group:groupbar:col.active"); - static auto PGROUPCOLINACTIVE = CConfigValue("group:groupbar:col.inactive"); - static auto PGROUPCOLACTIVELOCKED = CConfigValue("group:groupbar:col.locked_active"); - static auto PGROUPCOLINACTIVELOCKED = CConfigValue("group:groupbar:col.locked_inactive"); - auto* const GROUPCOLACTIVE = (CGradientValueData*)(PGROUPCOLACTIVE.ptr())->getData(); - auto* const GROUPCOLINACTIVE = (CGradientValueData*)(PGROUPCOLINACTIVE.ptr())->getData(); - auto* const GROUPCOLACTIVELOCKED = (CGradientValueData*)(PGROUPCOLACTIVELOCKED.ptr())->getData(); - auto* const GROUPCOLINACTIVELOCKED = (CGradientValueData*)(PGROUPCOLINACTIVELOCKED.ptr())->getData(); - const bool GROUPLOCKED = m_pWindow->getGroupHead()->m_sGroupData.locked || g_pKeybindManager->m_bGroupsLocked; const auto* const PCOLACTIVE = GROUPLOCKED ? GROUPCOLACTIVELOCKED : GROUPCOLACTIVE; const auto* const PCOLINACTIVE = GROUPLOCKED ? GROUPCOLINACTIVELOCKED : GROUPCOLINACTIVE; CHyprColor color = m_dwGroupMembers[WINDOWINDEX].lock() == g_pCompositor->m_pLastWindow.lock() ? PCOLACTIVE->m_vColors[0] : PCOLINACTIVE->m_vColors[0]; color.a *= a; - CRectPassElement::SRectData rectdata; - rectdata.color = color; - rectdata.box = rect; - if (*PROUNDING) { - if (*PROUNDONLYEDGES) { - static constexpr double PADDING = 20; - if (i == 0 && barsToDraw == 1) + if (!rect.empty()) { + CRectPassElement::SRectData rectdata; + rectdata.color = color; + rectdata.box = rect; + if (*PROUNDING) { + if (*PROUNDONLYEDGES) { + static constexpr double PADDING = 20; + + if (i == 0 && barsToDraw == 1) + rectdata.round = *PROUNDING; + else if (i == 0) { + double first = rect.w - (*PROUNDING * 2); + rectdata.round = *PROUNDING; + rectdata.clipBox = CBox{rect.pos() - Vector2D{PADDING, 0.F}, Vector2D{first + PADDING, rect.h}}; + g_pHyprRenderer->m_sRenderPass.add(makeShared(rectdata)); + rectdata.round = 0; + rectdata.clipBox = CBox{rect.pos() + Vector2D{first, 0.F}, Vector2D{rect.w - first + PADDING, rect.h}}; + } else if (i == barsToDraw - 1) { + double first = *PROUNDING * 2; + rectdata.round = 0; + rectdata.clipBox = CBox{rect.pos() - Vector2D{PADDING, 0.F}, Vector2D{first + PADDING, rect.h}}; + g_pHyprRenderer->m_sRenderPass.add(makeShared(rectdata)); + rectdata.round = *PROUNDING; + rectdata.clipBox = CBox{rect.pos() + Vector2D{first, 0.F}, Vector2D{rect.w - first + PADDING, rect.h}}; + } + } else rectdata.round = *PROUNDING; - else if (i == 0) { - double first = rect.w - (*PROUNDING * 2); - rectdata.round = *PROUNDING; - rectdata.clipBox = CBox{rect.pos() - Vector2D{PADDING, 0.F}, Vector2D{first + PADDING, rect.h}}; - g_pHyprRenderer->m_sRenderPass.add(makeShared(rectdata)); - rectdata.round = 0; - rectdata.clipBox = CBox{rect.pos() + Vector2D{first, 0.F}, Vector2D{rect.w - first + PADDING, rect.h}}; - } else if (i == barsToDraw - 1) { - double first = *PROUNDING * 2; - rectdata.round = 0; - rectdata.clipBox = CBox{rect.pos() - Vector2D{PADDING, 0.F}, Vector2D{first + PADDING, rect.h}}; - g_pHyprRenderer->m_sRenderPass.add(makeShared(rectdata)); - rectdata.round = *PROUNDING; - rectdata.clipBox = CBox{rect.pos() + Vector2D{first, 0.F}, Vector2D{rect.w - first + PADDING, rect.h}}; - } - } else - rectdata.round = *PROUNDING; + } + g_pHyprRenderer->m_sRenderPass.add(makeShared(rectdata)); } - g_pHyprRenderer->m_sRenderPass.add(makeShared(rectdata)); rect = {ASSIGNEDBOX.x + floor(xoff) - pMonitor->vecPosition.x + m_pWindow->m_vFloatingOffset.x, ASSIGNEDBOX.y + ASSIGNEDBOX.h - floor(yoff) - ONEBARHEIGHT - pMonitor->vecPosition.y + m_pWindow->m_vFloatingOffset.y, m_fBarWidth, (*PGRADIENTS || *PRENDERTITLES ? *PHEIGHT : 0)}; rect.scale(pMonitor->scale); - if (*PGRADIENTS) { - const auto GRADIENTTEX = (m_dwGroupMembers[WINDOWINDEX] == g_pCompositor->m_pLastWindow ? (GROUPLOCKED ? m_tGradientLockedActive : m_tGradientActive) : - (GROUPLOCKED ? m_tGradientLockedInactive : m_tGradientInactive)); - if (GRADIENTTEX->m_iTexID) { - CTexPassElement::SRenderData data; - data.tex = GRADIENTTEX; - data.box = rect; - if (*PGRADIENTROUNDING) { - if (*PGRADIENTROUNDINGONLYEDGES) { - static constexpr double PADDING = 20; + if (!rect.empty()) { + if (*PGRADIENTS) { + const auto GRADIENTTEX = (m_dwGroupMembers[WINDOWINDEX] == g_pCompositor->m_pLastWindow ? (GROUPLOCKED ? m_tGradientLockedActive : m_tGradientActive) : + (GROUPLOCKED ? m_tGradientLockedInactive : m_tGradientInactive)); + if (GRADIENTTEX->m_iTexID) { + CTexPassElement::SRenderData data; + data.tex = GRADIENTTEX; + data.box = rect; + if (*PGRADIENTROUNDING) { + if (*PGRADIENTROUNDINGONLYEDGES) { + static constexpr double PADDING = 20; - if (i == 0 && barsToDraw == 1) + if (i == 0 && barsToDraw == 1) + data.round = *PGRADIENTROUNDING; + else if (i == 0) { + double first = rect.w - (*PGRADIENTROUNDING * 2); + data.round = *PGRADIENTROUNDING; + data.clipBox = CBox{rect.pos() - Vector2D{PADDING, 0.F}, Vector2D{first + PADDING, rect.h}}; + g_pHyprRenderer->m_sRenderPass.add(makeShared(data)); + data.round = 0; + data.clipBox = CBox{rect.pos() + Vector2D{first, 0.F}, Vector2D{rect.w - first + PADDING, rect.h}}; + } else if (i == barsToDraw - 1) { + double first = *PGRADIENTROUNDING * 2; + data.round = 0; + data.clipBox = CBox{rect.pos() - Vector2D{PADDING, 0.F}, Vector2D{first + PADDING, rect.h}}; + g_pHyprRenderer->m_sRenderPass.add(makeShared(data)); + data.round = *PGRADIENTROUNDING; + data.clipBox = CBox{rect.pos() + Vector2D{first, 0.F}, Vector2D{rect.w - first + PADDING, rect.h}}; + } + } else data.round = *PGRADIENTROUNDING; - else if (i == 0) { - double first = rect.w - (*PGRADIENTROUNDING * 2); - data.round = *PGRADIENTROUNDING; - data.clipBox = CBox{rect.pos() - Vector2D{PADDING, 0.F}, Vector2D{first + PADDING, rect.h}}; - g_pHyprRenderer->m_sRenderPass.add(makeShared(data)); - data.round = 0; - data.clipBox = CBox{rect.pos() + Vector2D{first, 0.F}, Vector2D{rect.w - first + PADDING, rect.h}}; - } else if (i == barsToDraw - 1) { - double first = *PGRADIENTROUNDING * 2; - data.round = 0; - data.clipBox = CBox{rect.pos() - Vector2D{PADDING, 0.F}, Vector2D{first + PADDING, rect.h}}; - g_pHyprRenderer->m_sRenderPass.add(makeShared(data)); - data.round = *PGRADIENTROUNDING; - data.clipBox = CBox{rect.pos() + Vector2D{first, 0.F}, Vector2D{rect.w - first + PADDING, rect.h}}; - } - } else - rectdata.round = *PGRADIENTROUNDING; + } + g_pHyprRenderer->m_sRenderPass.add(makeShared(data)); } + } + + if (*PRENDERTITLES) { + CTitleTex* pTitleTex = textureFromTitle(m_dwGroupMembers[WINDOWINDEX]->m_szTitle); + + if (!pTitleTex) + pTitleTex = + m_sTitleTexs.titleTexs + .emplace_back(makeUnique(m_dwGroupMembers[WINDOWINDEX].lock(), + Vector2D{m_fBarWidth * pMonitor->scale, (*PTITLEFONTSIZE + 2L * BAR_TEXT_PAD) * pMonitor->scale}, pMonitor->scale)) + .get(); + rect.y += std::ceil((rect.height - pTitleTex->texSize.y) / 2.0); + rect.height = pTitleTex->texSize.y; + rect.width = pTitleTex->texSize.x; + rect.x += std::round(((m_fBarWidth * pMonitor->scale) / 2.0) - (pTitleTex->texSize.x / 2.0)); + rect.round(); + + CTexPassElement::SRenderData data; + data.tex = pTitleTex->tex; + data.box = rect; g_pHyprRenderer->m_sRenderPass.add(makeShared(data)); } } - if (*PRENDERTITLES) { - CTitleTex* pTitleTex = textureFromTitle(m_dwGroupMembers[WINDOWINDEX]->m_szTitle); - - if (!pTitleTex) - pTitleTex = - m_sTitleTexs.titleTexs - .emplace_back(makeUnique(m_dwGroupMembers[WINDOWINDEX].lock(), - Vector2D{m_fBarWidth * pMonitor->scale, (*PTITLEFONTSIZE + 2L * BAR_TEXT_PAD) * pMonitor->scale}, pMonitor->scale)) - .get(); - rect.y += std::ceil((rect.height - pTitleTex->texSize.y) / 2.0); - rect.height = pTitleTex->texSize.y; - rect.width = pTitleTex->texSize.x; - rect.x += std::round((m_fBarWidth * pMonitor->scale) / 2.0 - (pTitleTex->texSize.x / 2.0)); - rect.round(); - - CTexPassElement::SRenderData data; - data.tex = pTitleTex->tex; - data.box = rect; - g_pHyprRenderer->m_sRenderPass.add(makeShared(data)); - } - if (*PSTACKED) yoff += ONEBARHEIGHT; else From e1179b665b307e46a57367493a85ac80f34f2ce4 Mon Sep 17 00:00:00 2001 From: Mihai Fufezan Date: Mon, 10 Feb 2025 20:11:35 +0200 Subject: [PATCH 0988/2181] flake.lock: update --- flake.lock | 48 ++++++++++++++++++++++++------------------------ 1 file changed, 24 insertions(+), 24 deletions(-) diff --git a/flake.lock b/flake.lock index 7637a2c7..38f48983 100644 --- a/flake.lock +++ b/flake.lock @@ -16,11 +16,11 @@ ] }, "locked": { - "lastModified": 1738456976, - "narHash": "sha256-cufyHbOMnSt9V4w4OVSzNcpJ+8DwzRZRJaca2Q89KVI=", + "lastModified": 1739103745, + "narHash": "sha256-c53dcRaw0F4Os9WD05HwIRs9kTDZw4Mxe1XK4edEALo=", "owner": "hyprwm", "repo": "aquamarine", - "rev": "257b2050790ab3b1eb389e0f8bdc400eb9510139", + "rev": "a3dda0d10ce9aa1d1dfb7a6c139ea8c2872c74bd", "type": "github" }, "original": { @@ -79,11 +79,11 @@ ] }, "locked": { - "lastModified": 1738178255, - "narHash": "sha256-+D6Nu2ewXbMTFzx/Q4jDOo+LAOUPr0cxQJg5k33daIE=", + "lastModified": 1738664950, + "narHash": "sha256-xIeGNM+iivwVHkv9tHwOqoUP5dDrtees34bbFKKMZYs=", "owner": "hyprwm", "repo": "hyprcursor", - "rev": "dcadd3398abe146d60c67e0d9ee6e27b301cae82", + "rev": "7c6d165e1eb9045a996551eb9f121b6d1b30adc3", "type": "github" }, "original": { @@ -105,11 +105,11 @@ ] }, "locked": { - "lastModified": 1738437059, - "narHash": "sha256-J+8ecqaP3zD9GHeN8Y4hUapoELSoggp0IZI8laTFt/0=", + "lastModified": 1739049071, + "narHash": "sha256-3+7TpXMrbsUXSwgr5VAKAnmkzMb6JO+Rvc9XRb5NMg4=", "owner": "hyprwm", "repo": "hyprgraphics", - "rev": "5ac80e3686a4dfa55d2bd15c81a266b89594a295", + "rev": "175c6b29b6ff82100539e7c4363a35a02c74dd73", "type": "github" }, "original": { @@ -189,11 +189,11 @@ ] }, "locked": { - "lastModified": 1737981711, - "narHash": "sha256-lh6cL5D8nPplB3WovCQjLUZ7k7MViiBrMlpkfm4R7/c=", + "lastModified": 1739048983, + "narHash": "sha256-REhTcXq4qs3B3cCDtLlYDz0GZvmsBSh947Ub6pQWGTQ=", "owner": "hyprwm", "repo": "hyprland-qtutils", - "rev": "96bf0677fa9cd13508294e3d4559dfbbc8beff73", + "rev": "3504a293c8f8db4127cb0f7cfc1a318ffb4316f8", "type": "github" }, "original": { @@ -215,11 +215,11 @@ ] }, "locked": { - "lastModified": 1737634606, - "narHash": "sha256-W7W87Cv6wqZ9PHegI6rH1+ve3zJPiyevMFf0/HwdbCQ=", + "lastModified": 1739048914, + "narHash": "sha256-vd5rJBTmp2w7SDgfv23Zcd84ktI5eDA7e5UBzx+pKrU=", "owner": "hyprwm", "repo": "hyprlang", - "rev": "f41271d35cc0f370d300413d756c2677f386af9d", + "rev": "a7334904d591f38757c46fbe2ab68651877d9099", "type": "github" }, "original": { @@ -238,11 +238,11 @@ ] }, "locked": { - "lastModified": 1737978343, - "narHash": "sha256-TfFS0HCEJh63Kahrkp1h9hVDMdLU8a37Zz+IFucxyfA=", + "lastModified": 1739048933, + "narHash": "sha256-ck6MaoYvISBQKqZR+HcxXnx0wOhyCauxfVMaV5zhJxQ=", "owner": "hyprwm", "repo": "hyprutils", - "rev": "6a8bc9d2a4451df12f5179dc0b1d2d46518a90ab", + "rev": "e4e018a2ca6f5a9c33511973454199e1c7c85499", "type": "github" }, "original": { @@ -261,11 +261,11 @@ ] }, "locked": { - "lastModified": 1735493474, - "narHash": "sha256-fktzv4NaqKm94VAkAoVqO/nqQlw+X0/tJJNAeCSfzK4=", + "lastModified": 1739049028, + "narHash": "sha256-RleJp7LYbr6s+M1xgbmhtBs+fYa3ZdIiF7+QalJ4D1g=", "owner": "hyprwm", "repo": "hyprwayland-scanner", - "rev": "de913476b59ee88685fdc018e77b8f6637a2ae0b", + "rev": "04146df74a8d5ec0b579657307be01f1e241125f", "type": "github" }, "original": { @@ -276,11 +276,11 @@ }, "nixpkgs": { "locked": { - "lastModified": 1738410390, - "narHash": "sha256-xvTo0Aw0+veek7hvEVLzErmJyQkEcRk6PSR4zsRQFEc=", + "lastModified": 1739020877, + "narHash": "sha256-mIvECo/NNdJJ/bXjNqIh8yeoSjVLAuDuTUzAo7dzs8Y=", "owner": "NixOS", "repo": "nixpkgs", - "rev": "3a228057f5b619feb3186e986dbe76278d707b6e", + "rev": "a79cfe0ebd24952b580b1cf08cd906354996d547", "type": "github" }, "original": { From f2d43e5f2180adb81b3b7b51a7d0f39dace70b05 Mon Sep 17 00:00:00 2001 From: Mihai Fufezan Date: Mon, 10 Feb 2025 20:17:29 +0200 Subject: [PATCH 0989/2181] nix/overlays: add wayland-protocols overlay --- nix/overlays.nix | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/nix/overlays.nix b/nix/overlays.nix index b632d0b4..c5dd1bee 100644 --- a/nix/overlays.nix +++ b/nix/overlays.nix @@ -28,6 +28,7 @@ in { inputs.hyprlang.overlays.default inputs.hyprutils.overlays.default inputs.hyprwayland-scanner.overlays.default + self.overlays.wayland-protocols-bump self.overlays.udis86 # Hyprland packages themselves @@ -89,4 +90,17 @@ in { patches = []; }); }; + + # Temporary bump until https://nixpk.gs/pr-tracker.html?pr=367753 is merged. + # Expect to build the universe. + wayland-protocols-bump = final: prev: { + wayland-protocols = prev.wayland-protocols.overrideAttrs (self: super: { + version = "1.40"; + + src = prev.fetchurl { + url = "https://gitlab.freedesktop.org/wayland/${super.pname}/-/releases/${self.version}/downloads/${super.pname}-${self.version}.tar.xz"; + hash = "sha256-shcReTJHwsQnY5FDkt+p/LnjcoyktKoRCtuNkV/ABok="; + }; + }); + }; } From f83fe9986b34c53c67b113a015d54fe8c084e9bd Mon Sep 17 00:00:00 2001 From: "J. J. Ramsey" Date: Tue, 11 Feb 2025 09:58:43 -0500 Subject: [PATCH 0990/2181] protocols: add version 2 of ext-idle-notify-v1 protocol (#8959) Signed-off-by: James Ramsey Co-authored-by: James Ramsey --- protocols/meson.build | 2 +- src/managers/ProtocolManager.cpp | 2 +- src/protocols/IdleNotify.cpp | 26 ++++++++++++++++++-------- src/protocols/IdleNotify.hpp | 9 ++++++--- 4 files changed, 26 insertions(+), 13 deletions(-) diff --git a/protocols/meson.build b/protocols/meson.build index 7c57470b..f0a6a7e6 100644 --- a/protocols/meson.build +++ b/protocols/meson.build @@ -1,6 +1,6 @@ wayland_protos = dependency( 'wayland-protocols', - version: '>=1.32', + version: '>=1.40', fallback: 'wayland-protocols', default_options: ['tests=false'], ) diff --git a/src/managers/ProtocolManager.cpp b/src/managers/ProtocolManager.cpp index 6cd3a608..6474d661 100644 --- a/src/managers/ProtocolManager.cpp +++ b/src/managers/ProtocolManager.cpp @@ -147,7 +147,7 @@ CProtocolManager::CProtocolManager() { PROTO::constraints = makeUnique(&zwp_pointer_constraints_v1_interface, 1, "PointerConstraints"); PROTO::outputPower = makeUnique(&zwlr_output_power_manager_v1_interface, 1, "OutputPower"); PROTO::activation = makeUnique(&xdg_activation_v1_interface, 1, "XDGActivation"); - PROTO::idle = makeUnique(&ext_idle_notifier_v1_interface, 1, "IdleNotify"); + PROTO::idle = makeUnique(&ext_idle_notifier_v1_interface, 2, "IdleNotify"); PROTO::lockNotify = makeUnique(&hyprland_lock_notifier_v1_interface, 1, "IdleNotify"); PROTO::sessionLock = makeUnique(&ext_session_lock_manager_v1_interface, 1, "SessionLock"); PROTO::ime = makeUnique(&zwp_input_method_manager_v2_interface, 1, "IMEv2"); diff --git a/src/protocols/IdleNotify.cpp b/src/protocols/IdleNotify.cpp index bc5aabb1..14a5f3e1 100644 --- a/src/protocols/IdleNotify.cpp +++ b/src/protocols/IdleNotify.cpp @@ -10,7 +10,8 @@ static int onTimer(SP self, void* data) { return 0; } -CExtIdleNotification::CExtIdleNotification(SP resource_, uint32_t timeoutMs_) : resource(resource_), timeoutMs(timeoutMs_) { +CExtIdleNotification::CExtIdleNotification(SP resource_, uint32_t timeoutMs_, bool obeyInhibitors_) : + resource(resource_), timeoutMs(timeoutMs_), obeyInhibitors(obeyInhibitors_) { if UNLIKELY (!resource_->resource()) return; @@ -35,7 +36,7 @@ bool CExtIdleNotification::good() { } void CExtIdleNotification::updateTimer() { - if (PROTO::idle->isInhibited) + if (PROTO::idle->isInhibited && obeyInhibitors) timer->updateTimeout(std::nullopt); else timer->updateTimeout(std::chrono::milliseconds(timeoutMs)); @@ -54,6 +55,10 @@ void CExtIdleNotification::onActivity() { updateTimer(); } +bool CExtIdleNotification::inhibitorsAreObeyed() const { + return obeyInhibitors; +} + CIdleNotifyProtocol::CIdleNotifyProtocol(const wl_interface* iface, const int& ver, const std::string& name) : IWaylandProtocol(iface, ver, name) { ; } @@ -63,7 +68,10 @@ void CIdleNotifyProtocol::bindManager(wl_client* client, void* data, uint32_t ve RESOURCE->setOnDestroy([this](CExtIdleNotifierV1* p) { this->onManagerResourceDestroy(p->resource()); }); RESOURCE->setDestroy([this](CExtIdleNotifierV1* pMgr) { this->onManagerResourceDestroy(pMgr->resource()); }); - RESOURCE->setGetIdleNotification([this](CExtIdleNotifierV1* pMgr, uint32_t id, uint32_t timeout, wl_resource* seat) { this->onGetNotification(pMgr, id, timeout, seat); }); + RESOURCE->setGetIdleNotification( + [this](CExtIdleNotifierV1* pMgr, uint32_t id, uint32_t timeout, wl_resource* seat) { this->onGetNotification(pMgr, id, timeout, seat, true); }); + RESOURCE->setGetInputIdleNotification( + [this](CExtIdleNotifierV1* pMgr, uint32_t id, uint32_t timeout, wl_resource* seat) { this->onGetNotification(pMgr, id, timeout, seat, false); }); } void CIdleNotifyProtocol::onManagerResourceDestroy(wl_resource* res) { @@ -74,9 +82,10 @@ void CIdleNotifyProtocol::destroyNotification(CExtIdleNotification* notif) { std::erase_if(m_vNotifications, [&](const auto& other) { return other.get() == notif; }); } -void CIdleNotifyProtocol::onGetNotification(CExtIdleNotifierV1* pMgr, uint32_t id, uint32_t timeout, wl_resource* seat) { - const auto CLIENT = pMgr->client(); - const auto RESOURCE = m_vNotifications.emplace_back(makeShared(makeShared(CLIENT, pMgr->version(), id), timeout)).get(); +void CIdleNotifyProtocol::onGetNotification(CExtIdleNotifierV1* pMgr, uint32_t id, uint32_t timeout, wl_resource* seat, bool obeyInhibitors) { + const auto CLIENT = pMgr->client(); + const auto RESOURCE = + m_vNotifications.emplace_back(makeShared(makeShared(CLIENT, pMgr->version(), id), timeout, obeyInhibitors)).get(); if UNLIKELY (!RESOURCE->good()) { pMgr->noMemory(); @@ -94,6 +103,7 @@ void CIdleNotifyProtocol::onActivity() { void CIdleNotifyProtocol::setInhibit(bool inhibited) { isInhibited = inhibited; for (auto const& n : m_vNotifications) { - n->onActivity(); + if (n->inhibitorsAreObeyed()) + n->onActivity(); } -} \ No newline at end of file +} diff --git a/src/protocols/IdleNotify.hpp b/src/protocols/IdleNotify.hpp index e3dcdc98..efc3accc 100644 --- a/src/protocols/IdleNotify.hpp +++ b/src/protocols/IdleNotify.hpp @@ -9,19 +9,22 @@ class CEventLoopTimer; class CExtIdleNotification { public: - CExtIdleNotification(SP resource_, uint32_t timeoutMs); + CExtIdleNotification(SP resource_, uint32_t timeoutMs, bool obeyInhibitors); ~CExtIdleNotification(); bool good(); void onTimerFired(); void onActivity(); + bool inhibitorsAreObeyed() const; + private: SP resource; uint32_t timeoutMs = 0; SP timer; - bool idled = false; + bool idled = false; + bool obeyInhibitors = false; void updateTimer(); }; @@ -38,7 +41,7 @@ class CIdleNotifyProtocol : public IWaylandProtocol { private: void onManagerResourceDestroy(wl_resource* res); void destroyNotification(CExtIdleNotification* notif); - void onGetNotification(CExtIdleNotifierV1* pMgr, uint32_t id, uint32_t timeout, wl_resource* seat); + void onGetNotification(CExtIdleNotifierV1* pMgr, uint32_t id, uint32_t timeout, wl_resource* seat, bool obeyInhibitors); bool isInhibited = false; From 68bb3e7f0a1d528a8b2da1f92d2005889587561d Mon Sep 17 00:00:00 2001 From: nyx Date: Wed, 12 Feb 2025 08:54:42 -0500 Subject: [PATCH 0991/2181] env: move XDG_SESSION_TYPE to before backend init (#9390) --- src/Compositor.cpp | 1 - src/main.cpp | 1 + 2 files changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Compositor.cpp b/src/Compositor.cpp index 88a2530b..6d9e8d7e 100644 --- a/src/Compositor.cpp +++ b/src/Compositor.cpp @@ -386,7 +386,6 @@ void CCompositor::initServer(std::string socketName, int socketFd) { } setenv("WAYLAND_DISPLAY", m_szWLDisplaySocket.c_str(), 1); - setenv("XDG_SESSION_TYPE", "wayland", 1); if (!getenv("XDG_CURRENT_DESKTOP")) { setenv("XDG_CURRENT_DESKTOP", "Hyprland", 1); m_bDesktopEnvSet = true; diff --git a/src/main.cpp b/src/main.cpp index 464ed978..397d7463 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -43,6 +43,7 @@ int main(int argc, char** argv) { setenv("HYPRLAND_CMD", cmd.c_str(), 1); setenv("XDG_BACKEND", "wayland", 1); + setenv("XDG_SESSION_TYPE", "wayland", 1); setenv("_JAVA_AWT_WM_NONREPARENTING", "1", 1); setenv("MOZ_ENABLE_WAYLAND", "1", 1); From 17894051634716ab80c6502abdbb90ae2bc68f25 Mon Sep 17 00:00:00 2001 From: Maximilian Seidler <78690852+PaideiaDilemma@users.noreply.github.com> Date: Thu, 13 Feb 2025 11:06:36 +0000 Subject: [PATCH 0992/2181] session-lock: send locked when in unsafe state (#9399) --- src/managers/SessionLockManager.cpp | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/src/managers/SessionLockManager.cpp b/src/managers/SessionLockManager.cpp index 996860a1..40611199 100644 --- a/src/managers/SessionLockManager.cpp +++ b/src/managers/SessionLockManager.cpp @@ -89,6 +89,13 @@ void CSessionLockManager::onNewSessionLock(SP pLock) { g_pCompositor->focusSurface(nullptr); g_pSeatManager->setGrab(nullptr); + + // Normally the locked event is sent after each output rendered a lock screen frame. + // When there are no outputs, send it right away. + if (g_pCompositor->m_bUnsafeState) { + m_pSessionLock->lock->sendLocked(); + m_pSessionLock->m_hasSentLocked = true; + } } bool CSessionLockManager::isSessionLocked() { @@ -131,8 +138,7 @@ void CSessionLockManager::onLockscreenRenderedOnMonitor(uint64_t id) { if (!m_pSessionLock || m_pSessionLock->m_hasSentLocked) return; m_pSessionLock->m_lockedMonitors.emplace(id); - const auto MONITORS = g_pCompositor->m_vMonitors; - const bool LOCKED = std::all_of(MONITORS.begin(), MONITORS.end(), [this](auto m) { return m_pSessionLock->m_lockedMonitors.contains(m->ID); }); + const bool LOCKED = std::ranges::all_of(g_pCompositor->m_vMonitors, [this](auto m) { return m_pSessionLock->m_lockedMonitors.contains(m->ID); }); if (LOCKED && m_pSessionLock->lock->good()) { m_pSessionLock->lock->sendLocked(); m_pSessionLock->m_hasSentLocked = true; From 208f94fe12a30474d6805262524da3da492a0990 Mon Sep 17 00:00:00 2001 From: Maximilian Seidler <78690852+PaideiaDilemma@users.noreply.github.com> Date: Thu, 13 Feb 2025 11:08:03 +0000 Subject: [PATCH 0993/2181] animations: sync inactive/active border angles when using borderangle animations (#9401) --- src/render/decorations/CHyprBorderDecoration.cpp | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/render/decorations/CHyprBorderDecoration.cpp b/src/render/decorations/CHyprBorderDecoration.cpp index 5f2fdbda..0df3acde 100644 --- a/src/render/decorations/CHyprBorderDecoration.cpp +++ b/src/render/decorations/CHyprBorderDecoration.cpp @@ -63,6 +63,11 @@ void CHyprBorderDecoration::draw(PHLMONITOR pMonitor, float const& a) { if (m_pWindow->m_fBorderAngleAnimationProgress->enabled()) { grad.m_fAngle += m_pWindow->m_fBorderAngleAnimationProgress->value() * M_PI * 2; grad.m_fAngle = normalizeAngleRad(grad.m_fAngle); + + // When borderangle is animated, it is counterintuitive to fade between inactive/active gradient angles. + // Instead we sync the angles to avoid fading between them and additionally rotating the border angle. + if (ANIMATED) + m_pWindow->m_cRealBorderColorPrevious.m_fAngle = grad.m_fAngle; } int borderSize = m_pWindow->getRealBorderSize(); From 5d2b00829484684b619a8c0de6b1d2b1d18d31a9 Mon Sep 17 00:00:00 2001 From: Anthony Ruhier Date: Thu, 13 Feb 2025 12:09:25 +0100 Subject: [PATCH 0994/2181] renderer: disable explicit if aquamarine output doesn't support it (#9396) (#9398) The explicit settings ignore the aquamarine output.supportsExplicit attribute, which creates glitches on drivers not supporting explicit sync (example: freedreno). If the output has been set as not supporting explicit, disable the explicit settings. --- src/helpers/Monitor.cpp | 2 +- src/render/Renderer.cpp | 14 +++++++++++--- src/render/Renderer.hpp | 2 +- 3 files changed, 13 insertions(+), 5 deletions(-) diff --git a/src/helpers/Monitor.cpp b/src/helpers/Monitor.cpp index e4843211..fead5db9 100644 --- a/src/helpers/Monitor.cpp +++ b/src/helpers/Monitor.cpp @@ -1312,7 +1312,7 @@ bool CMonitor::attemptDirectScanout() { return false; } - auto explicitOptions = g_pHyprRenderer->getExplicitSyncSettings(); + auto explicitOptions = g_pHyprRenderer->getExplicitSyncSettings(output); // wait for the explicit fence if present, and if kms explicit is allowed bool DOEXPLICIT = PSURFACE->syncobj && PSURFACE->syncobj->current.acquireTimeline && PSURFACE->syncobj->current.acquireTimeline->timeline && explicitOptions.explicitKMSEnabled; diff --git a/src/render/Renderer.cpp b/src/render/Renderer.cpp index 6f0bbe44..531ceb33 100644 --- a/src/render/Renderer.cpp +++ b/src/render/Renderer.cpp @@ -1557,7 +1557,7 @@ bool CHyprRenderer::commitPendingAndDoExplicitSync(PHLMONITOR pMonitor) { } } - auto explicitOptions = getExplicitSyncSettings(); + auto explicitOptions = getExplicitSyncSettings(pMonitor->output); if (!explicitOptions.explicitEnabled) return ok; @@ -2293,7 +2293,7 @@ void CHyprRenderer::endRender() { if (m_eRenderMode == RENDER_MODE_NORMAL) { PMONITOR->output->state->setBuffer(m_pCurrentBuffer); - auto explicitOptions = getExplicitSyncSettings(); + auto explicitOptions = getExplicitSyncSettings(PMONITOR->output); if (PMONITOR->inTimeline && explicitOptions.explicitEnabled && explicitOptions.explicitKMSEnabled) { auto sync = g_pHyprOpenGL->createEGLSync({}); @@ -2336,7 +2336,7 @@ bool CHyprRenderer::isNvidia() { return m_bNvidia; } -SExplicitSyncSettings CHyprRenderer::getExplicitSyncSettings() { +SExplicitSyncSettings CHyprRenderer::getExplicitSyncSettings(SP output) { static auto PENABLEEXPLICIT = CConfigValue("render:explicit_sync"); static auto PENABLEEXPLICITKMS = CConfigValue("render:explicit_sync_kms"); @@ -2344,6 +2344,14 @@ SExplicitSyncSettings CHyprRenderer::getExplicitSyncSettings() { settings.explicitEnabled = *PENABLEEXPLICIT; settings.explicitKMSEnabled = *PENABLEEXPLICITKMS; + if (!output->supportsExplicit) { + Debug::log(LOG, "Renderer: the aquamarine output does not support explicit, explicit settings are disabled."); + settings.explicitEnabled = false; + settings.explicitKMSEnabled = false; + + return settings; + } + if (*PENABLEEXPLICIT == 2 /* auto */) settings.explicitEnabled = true; if (*PENABLEEXPLICITKMS == 2 /* auto */) { diff --git a/src/render/Renderer.hpp b/src/render/Renderer.hpp index e64d41c1..731ed926 100644 --- a/src/render/Renderer.hpp +++ b/src/render/Renderer.hpp @@ -75,7 +75,7 @@ class CHyprRenderer { bool isNvidia(); void makeEGLCurrent(); void unsetEGL(); - SExplicitSyncSettings getExplicitSyncSettings(); + SExplicitSyncSettings getExplicitSyncSettings(SP output); void addWindowToRenderUnfocused(PHLWINDOW window); void makeWindowSnapshot(PHLWINDOW); void makeRawWindowSnapshot(PHLWINDOW, CFramebuffer*); From 40adb3dfb4b6f8cf0c5093f095954e3ef162a8eb Mon Sep 17 00:00:00 2001 From: Maximilian Seidler <78690852+PaideiaDilemma@users.noreply.github.com> Date: Thu, 13 Feb 2025 11:37:59 +0000 Subject: [PATCH 0995/2181] config: actually set initial beziers (#9400) --- src/config/ConfigManager.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/config/ConfigManager.cpp b/src/config/ConfigManager.cpp index f87a5e6b..43abcb1f 100644 --- a/src/config/ConfigManager.cpp +++ b/src/config/ConfigManager.cpp @@ -885,9 +885,9 @@ void CConfigManager::setDefaultAnimationVars() { m_AnimationTree.createNode("specialWorkspaceOut", "specialWorkspace"); // init the root nodes - m_AnimationTree.setConfigForNode("global", 1, 8.f, "", "default"); - m_AnimationTree.setConfigForNode("__internal_fadeCTM", 1, 5.f, "", "linear"); - m_AnimationTree.setConfigForNode("borderangle", 0, 0.f, "", "default"); + m_AnimationTree.setConfigForNode("global", 1, 8.f, "default"); + m_AnimationTree.setConfigForNode("__internal_fadeCTM", 1, 5.f, "linear"); + m_AnimationTree.setConfigForNode("borderangle", 0, 1, "default"); } std::optional CConfigManager::resetHLConfig() { From df3fba157279de53c582344b59699a21ac5d62b5 Mon Sep 17 00:00:00 2001 From: Honkazel <169346573+Honkazel@users.noreply.github.com> Date: Fri, 14 Feb 2025 20:31:03 +0500 Subject: [PATCH 0996/2181] internal: remove unused variable (#9402) --- src/helpers/MiscFunctions.cpp | 91 ----------------------------------- 1 file changed, 91 deletions(-) diff --git a/src/helpers/MiscFunctions.cpp b/src/helpers/MiscFunctions.cpp index f532617c..9e398fd9 100644 --- a/src/helpers/MiscFunctions.cpp +++ b/src/helpers/MiscFunctions.cpp @@ -49,97 +49,6 @@ using namespace Hyprutils::OS; #endif #endif -static const float transforms[][9] = { - { - 1.0f, - 0.0f, - 0.0f, - 0.0f, - 1.0f, - 0.0f, - 0.0f, - 0.0f, - 1.0f, - }, - { - 0.0f, - 1.0f, - 0.0f, - -1.0f, - 0.0f, - 0.0f, - 0.0f, - 0.0f, - 1.0f, - }, - { - -1.0f, - 0.0f, - 0.0f, - 0.0f, - -1.0f, - 0.0f, - 0.0f, - 0.0f, - 1.0f, - }, - { - 0.0f, - -1.0f, - 0.0f, - 1.0f, - 0.0f, - 0.0f, - 0.0f, - 0.0f, - 1.0f, - }, - { - -1.0f, - 0.0f, - 0.0f, - 0.0f, - 1.0f, - 0.0f, - 0.0f, - 0.0f, - 1.0f, - }, - { - 0.0f, - 1.0f, - 0.0f, - 1.0f, - 0.0f, - 0.0f, - 0.0f, - 0.0f, - 1.0f, - }, - { - 1.0f, - 0.0f, - 0.0f, - 0.0f, - -1.0f, - 0.0f, - 0.0f, - 0.0f, - 1.0f, - }, - { - 0.0f, - -1.0f, - 0.0f, - -1.0f, - 0.0f, - 0.0f, - 0.0f, - 0.0f, - 1.0f, - }, -}; - std::string absolutePath(const std::string& rawpath, const std::string& currentPath) { auto value = rawpath; From fb36815b0146d7b494cd648be0dfaa67a14d164a Mon Sep 17 00:00:00 2001 From: Vaxry Date: Fri, 14 Feb 2025 22:51:36 +0000 Subject: [PATCH 0997/2181] renderer: remove spammy log --- src/render/Renderer.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/src/render/Renderer.cpp b/src/render/Renderer.cpp index 531ceb33..b61f1c3e 100644 --- a/src/render/Renderer.cpp +++ b/src/render/Renderer.cpp @@ -2345,7 +2345,6 @@ SExplicitSyncSettings CHyprRenderer::getExplicitSyncSettings(SPsupportsExplicit) { - Debug::log(LOG, "Renderer: the aquamarine output does not support explicit, explicit settings are disabled."); settings.explicitEnabled = false; settings.explicitKMSEnabled = false; From 1309b59f2cb5179a4c59c111c35c7feede535eb6 Mon Sep 17 00:00:00 2001 From: Vaxry Date: Sat, 15 Feb 2025 00:18:43 +0000 Subject: [PATCH 0998/2181] monitor: report a scheduled frame when tearing on cursor move --- src/helpers/Monitor.cpp | 18 ++++++++++++++++++ src/helpers/Monitor.hpp | 1 + src/managers/PointerManager.cpp | 10 +++++++++- 3 files changed, 28 insertions(+), 1 deletion(-) diff --git a/src/helpers/Monitor.cpp b/src/helpers/Monitor.cpp index fead5db9..24db3ea4 100644 --- a/src/helpers/Monitor.cpp +++ b/src/helpers/Monitor.cpp @@ -1441,6 +1441,24 @@ void CMonitor::onMonitorFrame() { g_pHyprRenderer->renderMonitor(self.lock()); } +void CMonitor::onCursorMovedOnMonitor() { + if (!tearingState.activelyTearing || !solitaryClient || !g_pHyprRenderer->shouldRenderCursor()) + return; + + // submit a frame immediately. This will only update the cursor pos. + // output->state->setBuffer(output->state->state().buffer); + // output->state->addDamage(CRegion{}); + // output->state->setPresentationMode(Aquamarine::eOutputPresentationMode::AQ_OUTPUT_PRESENTATION_IMMEDIATE); + // if (!output->commit()) + // Debug::log(ERR, "onCursorMovedOnMonitor: tearing and wanted to update cursor, failed."); + + // FIXME: try to do the above. We currently can't just render because drm is a fucking bitch + // and throws a "nO pRoP cAn Be ChAnGeD dUrInG AsYnC fLiP" on crtc_x + // this will throw too but fix it if we use sw cursors + + tearingState.frameScheduledWhileBusy = true; +} + CMonitorState::CMonitorState(CMonitor* owner) : m_pOwner(owner) { ; } diff --git a/src/helpers/Monitor.hpp b/src/helpers/Monitor.hpp index c67bccc5..690b8c4a 100644 --- a/src/helpers/Monitor.hpp +++ b/src/helpers/Monitor.hpp @@ -186,6 +186,7 @@ class CMonitor { void scheduleDone(); bool attemptDirectScanout(); void setCTM(const Mat3x3& ctm); + void onCursorMovedOnMonitor(); void debugLastPresentation(const std::string& message); void onMonitorFrame(); diff --git a/src/managers/PointerManager.cpp b/src/managers/PointerManager.cpp index 1c8e9976..24f2b35d 100644 --- a/src/managers/PointerManager.cpp +++ b/src/managers/PointerManager.cpp @@ -17,6 +17,9 @@ #include #include #include +#include + +using namespace Hyprutils::Utils; CPointerManager::CPointerManager() { hooks.monitorAdded = g_pHookSystem->hookDynamic("monitorAdded", [this](void* self, SCallbackInfo& info, std::any data) { @@ -310,7 +313,12 @@ void CPointerManager::onCursorMoved() { recalc = true; } - if (state->hardwareFailed || !state->entered) + if (!state->entered) + continue; + + CScopeGuard x([m] { m->onCursorMovedOnMonitor(); }); + + if (state->hardwareFailed) continue; const auto CURSORPOS = getCursorPosForMonitor(m); From 2f967037aa00c4aecce62222e5e21c1790148eb0 Mon Sep 17 00:00:00 2001 From: Vaxry Date: Sat, 15 Feb 2025 00:21:50 +0000 Subject: [PATCH 0999/2181] config: set no_hw_cursors to auto by default and disable on tearing when tearing, updates to the overlay plane may be ignored by the kernel. To avoid the cursor being a slideshow, disable hw cursors --- src/config/ConfigDescriptions.hpp | 2 +- src/config/ConfigManager.cpp | 5 +++-- src/config/ConfigManager.hpp | 2 +- src/managers/PointerManager.cpp | 5 +++-- 4 files changed, 8 insertions(+), 6 deletions(-) diff --git a/src/config/ConfigDescriptions.hpp b/src/config/ConfigDescriptions.hpp index 8d1b73c4..23635760 100644 --- a/src/config/ConfigDescriptions.hpp +++ b/src/config/ConfigDescriptions.hpp @@ -1356,7 +1356,7 @@ inline static const std::vector CONFIG_OPTIONS = { }, SConfigOptionDescription{ .value = "cursor:no_hardware_cursors", - .description = "disables hardware cursors", + .description = "disables hardware cursors. Auto = disable when tearing", .type = CONFIG_OPTION_CHOICE, .data = SConfigOptionDescription::SChoiceData{0, "Disabled,Enabled,Auto"}, }, diff --git a/src/config/ConfigManager.cpp b/src/config/ConfigManager.cpp index 43abcb1f..00dba200 100644 --- a/src/config/ConfigManager.cpp +++ b/src/config/ConfigManager.cpp @@ -621,7 +621,7 @@ CConfigManager::CConfigManager() { m_pConfig->addConfigValue("opengl:nvidia_anti_flicker", Hyprlang::INT{1}); - m_pConfig->addConfigValue("cursor:no_hardware_cursors", Hyprlang::INT{0}); + m_pConfig->addConfigValue("cursor:no_hardware_cursors", Hyprlang::INT{2}); m_pConfig->addConfigValue("cursor:no_break_fs_vrr", Hyprlang::INT{2}); m_pConfig->addConfigValue("cursor:min_refresh_rate", Hyprlang::INT{24}); m_pConfig->addConfigValue("cursor:hotspot_padding", Hyprlang::INT{0}); @@ -2798,12 +2798,13 @@ const std::vector& CConfigManager::getAllDescriptions( return CONFIG_OPTIONS; } -bool CConfigManager::shouldUseSoftwareCursors() { +bool CConfigManager::shouldUseSoftwareCursors(PHLMONITOR pMonitor) { static auto PNOHW = CConfigValue("cursor:no_hardware_cursors"); switch (*PNOHW) { case 0: return false; case 1: return true; + case 2: return pMonitor->tearingState.activelyTearing; default: break; } diff --git a/src/config/ConfigManager.hpp b/src/config/ConfigManager.hpp index f0696882..b914a3a3 100644 --- a/src/config/ConfigManager.hpp +++ b/src/config/ConfigManager.hpp @@ -189,7 +189,7 @@ class CConfigManager { void ensureMonitorStatus(); void ensureVRR(PHLMONITOR pMonitor = nullptr); - bool shouldUseSoftwareCursors(); + bool shouldUseSoftwareCursors(PHLMONITOR pMonitor); void updateWatcher(); std::string parseKeyword(const std::string&, const std::string&); diff --git a/src/managers/PointerManager.cpp b/src/managers/PointerManager.cpp index 24f2b35d..048719b8 100644 --- a/src/managers/PointerManager.cpp +++ b/src/managers/PointerManager.cpp @@ -274,7 +274,7 @@ void CPointerManager::updateCursorBackend() { continue; } - if (state->softwareLocks > 0 || g_pConfigManager->shouldUseSoftwareCursors() || !attemptHardwareCursor(state)) { + if (state->softwareLocks > 0 || g_pConfigManager->shouldUseSoftwareCursors(m) || !attemptHardwareCursor(state)) { Debug::log(TRACE, "Output {} rejected hardware cursors, falling back to sw", m->szName); state->box = getCursorBoxLogicalForMonitor(state->monitor.lock()); state->hardwareFailed = true; @@ -737,7 +737,8 @@ void CPointerManager::damageIfSoftware() { if (mw->monitor.expired() || !mw->monitor->output) continue; - if ((mw->softwareLocks > 0 || mw->hardwareFailed || g_pConfigManager->shouldUseSoftwareCursors()) && b.overlaps({mw->monitor->vecPosition, mw->monitor->vecSize})) { + if ((mw->softwareLocks > 0 || mw->hardwareFailed || g_pConfigManager->shouldUseSoftwareCursors(mw->monitor.lock())) && + b.overlaps({mw->monitor->vecPosition, mw->monitor->vecSize})) { g_pHyprRenderer->damageBox(b, mw->monitor->shouldSkipScheduleFrameOnMouseEvent()); break; } From 3eb6cb1875bd2f0850d19b1ad1b554c61b06bcec Mon Sep 17 00:00:00 2001 From: Tom Englund Date: Sat, 15 Feb 2025 14:48:52 +0100 Subject: [PATCH 1000/2181] syncobj: ensure we only add waiters on succesful checks (#9412) timeline check only returns nullopt on ETIME_ERR , meaning the if check later on returns true if drmSyncobjTimelineWait returns anything else like EINVAL/EPERM/EACCESS etc, so actually check the returned .value() of the std::optional. also move the fd to rvalue references. --- src/protocols/DRMSyncobj.cpp | 4 ++-- src/protocols/DRMSyncobj.hpp | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/protocols/DRMSyncobj.cpp b/src/protocols/DRMSyncobj.cpp index 23dafbca..38aab305 100644 --- a/src/protocols/DRMSyncobj.cpp +++ b/src/protocols/DRMSyncobj.cpp @@ -75,7 +75,7 @@ CDRMSyncobjSurfaceResource::CDRMSyncobjSurfaceResource(SPlockPendingState(); @@ -104,7 +104,7 @@ bool CDRMSyncobjSurfaceResource::good() { return resource->resource(); } -CDRMSyncobjTimelineResource::CDRMSyncobjTimelineResource(SP resource_, CFileDescriptor fd_) : fd(std::move(fd_)), resource(resource_) { +CDRMSyncobjTimelineResource::CDRMSyncobjTimelineResource(SP resource_, CFileDescriptor&& fd_) : fd(std::move(fd_)), resource(resource_) { if UNLIKELY (!good()) return; diff --git a/src/protocols/DRMSyncobj.hpp b/src/protocols/DRMSyncobj.hpp index 8677576f..9895dff1 100644 --- a/src/protocols/DRMSyncobj.hpp +++ b/src/protocols/DRMSyncobj.hpp @@ -33,7 +33,7 @@ class CDRMSyncobjSurfaceResource { class CDRMSyncobjTimelineResource { public: - CDRMSyncobjTimelineResource(SP resource_, Hyprutils::OS::CFileDescriptor fd_); + CDRMSyncobjTimelineResource(SP resource_, Hyprutils::OS::CFileDescriptor&& fd_); ~CDRMSyncobjTimelineResource() = default; static SP fromResource(wl_resource*); From 7a6fde8414ae200759ac41569f189ac5e1ba0fbb Mon Sep 17 00:00:00 2001 From: nyx Date: Sat, 15 Feb 2025 08:51:17 -0500 Subject: [PATCH 1001/2181] internal: redirect exec'd app output to /dev/null (#9411) --- src/managers/KeybindManager.cpp | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/src/managers/KeybindManager.cpp b/src/managers/KeybindManager.cpp index 8daa6838..4bfd1454 100644 --- a/src/managers/KeybindManager.cpp +++ b/src/managers/KeybindManager.cpp @@ -967,6 +967,14 @@ uint64_t CKeybindManager::spawnRawProc(std::string args, PHLWORKSPACE pInitialWo setenv(e.first.c_str(), e.second.c_str(), 1); } setenv("WAYLAND_DISPLAY", g_pCompositor->m_szWLDisplaySocket.c_str(), 1); + + int devnull = open("/dev/null", O_WRONLY | O_CLOEXEC); + if (devnull != -1) { + dup2(devnull, STDOUT_FILENO); + dup2(devnull, STDERR_FILENO); + close(devnull); + } + execl("/bin/sh", "/bin/sh", "-c", args.c_str(), nullptr); // exit grandchild _exit(0); From 410da2e46fc44d93196cd902a070391a416cff01 Mon Sep 17 00:00:00 2001 From: Roberto Previdi Date: Sat, 15 Feb 2025 15:01:52 +0100 Subject: [PATCH 1002/2181] workspaces: update persistence on workspace rename (#9368) --- src/Compositor.cpp | 51 ++++++++++++++++++++++++++------------- src/Compositor.hpp | 2 +- src/debug/HyprCtl.cpp | 14 ++++++----- src/desktop/Workspace.cpp | 6 +++++ 4 files changed, 49 insertions(+), 24 deletions(-) diff --git a/src/Compositor.cpp b/src/Compositor.cpp index 6d9e8d7e..5389844f 100644 --- a/src/Compositor.cpp +++ b/src/Compositor.cpp @@ -3043,34 +3043,53 @@ bool CCompositor::shouldChangePreferredImageDescription() { return false; } -void CCompositor::ensurePersistentWorkspacesPresent(const std::vector& rules) { +void CCompositor::ensurePersistentWorkspacesPresent(const std::vector& rules, PHLWORKSPACE pWorkspace) { + for (const auto& rule : rules) { if (!rule.isPersistent) continue; + PHLWORKSPACE PWORKSPACE = nullptr; + if (pWorkspace) { + if (pWorkspace->matchesStaticSelector(rule.workspaceString)) + PWORKSPACE = pWorkspace; + else + continue; + } + const auto PMONITOR = getMonitorFromString(rule.monitor); + if (!PWORKSPACE) { + WORKSPACEID id = rule.workspaceId; + std::string wsname = rule.workspaceName; + + if (id == WORKSPACE_INVALID) { + const auto R = getWorkspaceIDNameFromString(rule.workspaceString); + id = R.id; + wsname = R.name; + } + + if (id == WORKSPACE_INVALID) { + Debug::log(ERR, "ensurePersistentWorkspacesPresent: couldn't resolve id for workspace {}", rule.workspaceString); + continue; + } + PWORKSPACE = getWorkspaceByID(id); + if (!PWORKSPACE) + createNewWorkspace(id, PMONITOR ? PMONITOR : m_pLastMonitor.lock(), wsname, false); + } + + if (PWORKSPACE) + PWORKSPACE->m_bPersistent = true; + if (!PMONITOR) { Debug::log(ERR, "ensurePersistentWorkspacesPresent: couldn't resolve monitor for {}, skipping", rule.monitor); continue; } - WORKSPACEID id = rule.workspaceId; - std::string wsname = rule.workspaceName; - if (id == WORKSPACE_INVALID) { - const auto R = getWorkspaceIDNameFromString(rule.workspaceString); - id = R.id; - wsname = R.name; - } - - if (id == WORKSPACE_INVALID) { - Debug::log(ERR, "ensurePersistentWorkspacesPresent: couldn't resolve id for workspace {}", rule.workspaceString); - continue; - } - - if (const auto PWORKSPACE = getWorkspaceByID(id); PWORKSPACE) { + if (PWORKSPACE) { if (PWORKSPACE->m_pMonitor == PMONITOR) { Debug::log(LOG, "ensurePersistentWorkspacesPresent: workspace persistent {} already on {}", rule.workspaceString, PMONITOR->szName); + continue; } @@ -3078,8 +3097,6 @@ void CCompositor::ensurePersistentWorkspacesPresent(const std::vector pSurface, wl_output_transform transform); void updateSuspendedStates(); void onNewMonitor(SP output); - void ensurePersistentWorkspacesPresent(const std::vector& rules); + void ensurePersistentWorkspacesPresent(const std::vector& rules, PHLWORKSPACE pWorkspace = nullptr); SImageDescription getPreferredImageDescription(); bool shouldChangePreferredImageDescription(); diff --git a/src/debug/HyprCtl.cpp b/src/debug/HyprCtl.cpp index cd6451e2..a155474d 100644 --- a/src/debug/HyprCtl.cpp +++ b/src/debug/HyprCtl.cpp @@ -319,15 +319,17 @@ std::string CHyprCtl::getWorkspaceData(PHLWORKSPACE w, eHyprCtlOutputFormat form "windows": {}, "hasfullscreen": {}, "lastwindow": "0x{:x}", - "lastwindowtitle": "{}" + "lastwindowtitle": "{}", + "ispersistent": {} }})#", w->m_iID, escapeJSONStrings(w->m_szName), escapeJSONStrings(PMONITOR ? PMONITOR->szName : "?"), - escapeJSONStrings(PMONITOR ? std::to_string(PMONITOR->ID) : "null"), w->getWindows(), ((int)w->m_bHasFullscreenWindow == 1 ? "true" : "false"), - (uintptr_t)PLASTW.get(), PLASTW ? escapeJSONStrings(PLASTW->m_szTitle) : ""); + escapeJSONStrings(PMONITOR ? std::to_string(PMONITOR->ID) : "null"), w->getWindows(), w->m_bHasFullscreenWindow ? "true" : "false", + (uintptr_t)PLASTW.get(), PLASTW ? escapeJSONStrings(PLASTW->m_szTitle) : "", w->m_bPersistent ? "true" : "false"); } else { - return std::format("workspace ID {} ({}) on monitor {}:\n\tmonitorID: {}\n\twindows: {}\n\thasfullscreen: {}\n\tlastwindow: 0x{:x}\n\tlastwindowtitle: {}\n\n", w->m_iID, - w->m_szName, PMONITOR ? PMONITOR->szName : "?", PMONITOR ? std::to_string(PMONITOR->ID) : "null", w->getWindows(), (int)w->m_bHasFullscreenWindow, - (uintptr_t)PLASTW.get(), PLASTW ? PLASTW->m_szTitle : ""); + return std::format( + "workspace ID {} ({}) on monitor {}:\n\tmonitorID: {}\n\twindows: {}\n\thasfullscreen: {}\n\tlastwindow: 0x{:x}\n\tlastwindowtitle: {}\n\tispersistent: {}\n\n", + w->m_iID, w->m_szName, PMONITOR ? PMONITOR->szName : "?", PMONITOR ? std::to_string(PMONITOR->ID) : "null", w->getWindows(), (int)w->m_bHasFullscreenWindow, + (uintptr_t)PLASTW.get(), PLASTW ? PLASTW->m_szTitle : "", (int)w->m_bPersistent); } } diff --git a/src/desktop/Workspace.cpp b/src/desktop/Workspace.cpp index f2c22195..322c4e33 100644 --- a/src/desktop/Workspace.cpp +++ b/src/desktop/Workspace.cpp @@ -648,6 +648,12 @@ void CWorkspace::rename(const std::string& name) { Debug::log(LOG, "CWorkspace::rename: Renaming workspace {} to '{}'", m_iID, name); m_szName = name; + const auto WORKSPACERULE = g_pConfigManager->getWorkspaceRuleFor(m_pSelf.lock()); + m_bPersistent = WORKSPACERULE.isPersistent; + + if (WORKSPACERULE.isPersistent) + g_pCompositor->ensurePersistentWorkspacesPresent(std::vector{WORKSPACERULE}, m_pSelf.lock()); + g_pEventManager->postEvent({"renameworkspace", std::to_string(m_iID) + "," + m_szName}); } From 9228116c9aa682477aae1a52d2d7d023bb075352 Mon Sep 17 00:00:00 2001 From: nyx Date: Sat, 15 Feb 2025 14:03:37 -0500 Subject: [PATCH 1003/2181] xwayland: fix a possible clipboard race condition (#9394) --- src/xwayland/XDataSource.cpp | 15 ++++--- src/xwayland/XWM.cpp | 85 ++++++++++++++++++++++++++++-------- src/xwayland/XWM.hpp | 2 +- 3 files changed, 75 insertions(+), 27 deletions(-) diff --git a/src/xwayland/XDataSource.cpp b/src/xwayland/XDataSource.cpp index 9384db69..003f6c9f 100644 --- a/src/xwayland/XDataSource.cpp +++ b/src/xwayland/XDataSource.cpp @@ -71,19 +71,20 @@ void CXDataSource::send(const std::string& mime, CFileDescriptor fd) { Debug::log(LOG, "[XDataSource] send with mime {} to fd {}", mime, fd.get()); - selection.transfer = makeUnique(selection); - selection.transfer->incomingWindow = xcb_generate_id(g_pXWayland->pWM->connection); - const uint32_t MASK = XCB_EVENT_MASK_SUBSTRUCTURE_NOTIFY | XCB_EVENT_MASK_PROPERTY_CHANGE; - xcb_create_window(g_pXWayland->pWM->connection, XCB_COPY_FROM_PARENT, selection.transfer->incomingWindow, g_pXWayland->pWM->screen->root, 0, 0, 10, 10, 0, - XCB_WINDOW_CLASS_INPUT_OUTPUT, g_pXWayland->pWM->screen->root_visual, XCB_CW_EVENT_MASK, &MASK); + auto transfer = makeUnique(selection); + transfer->incomingWindow = xcb_generate_id(g_pXWayland->pWM->connection); + const uint32_t MASK = XCB_EVENT_MASK_SUBSTRUCTURE_NOTIFY | XCB_EVENT_MASK_PROPERTY_CHANGE; + xcb_create_window(g_pXWayland->pWM->connection, XCB_COPY_FROM_PARENT, transfer->incomingWindow, g_pXWayland->pWM->screen->root, 0, 0, 10, 10, 0, XCB_WINDOW_CLASS_INPUT_OUTPUT, + g_pXWayland->pWM->screen->root_visual, XCB_CW_EVENT_MASK, &MASK); - xcb_convert_selection(g_pXWayland->pWM->connection, selection.transfer->incomingWindow, HYPRATOMS["CLIPBOARD"], mimeAtom, HYPRATOMS["_WL_SELECTION"], XCB_TIME_CURRENT_TIME); + xcb_convert_selection(g_pXWayland->pWM->connection, transfer->incomingWindow, HYPRATOMS["CLIPBOARD"], mimeAtom, HYPRATOMS["_WL_SELECTION"], XCB_TIME_CURRENT_TIME); xcb_flush(g_pXWayland->pWM->connection); //TODO: make CFileDescriptor setflags take SETFL aswell fcntl(fd.get(), F_SETFL, O_WRONLY | O_NONBLOCK); - selection.transfer->wlFD = std::move(fd); + transfer->wlFD = std::move(fd); + selection.transfers.emplace_back(std::move(transfer)); } void CXDataSource::accepted(const std::string& mime) { diff --git a/src/xwayland/XWM.cpp b/src/xwayland/XWM.cpp index 68552dd6..f2a9b794 100644 --- a/src/xwayland/XWM.cpp +++ b/src/xwayland/XWM.cpp @@ -571,9 +571,10 @@ void CXWM::handleSelectionNotify(xcb_selection_notify_event_t* e) { SXSelection* sel = getSelection(e->selection); if (e->property == XCB_ATOM_NONE) { - if (sel->transfer) { + auto it = std::ranges::find_if(sel->transfers, [](const auto& t) { return !t->propertyReply; }); + if (it != sel->transfers.end()) { Debug::log(TRACE, "[xwm] converting selection failed"); - sel->transfer.reset(); + sel->transfers.erase(it); } } else if (e->target == HYPRATOMS["TARGETS"] && sel == &clipboard) { if (!focusedSurface) { @@ -582,7 +583,7 @@ void CXWM::handleSelectionNotify(xcb_selection_notify_event_t* e) { } setClipboardToWayland(*sel); - } else if (sel->transfer) + } else if (!sel->transfers.empty()) getTransferData(*sel); } @@ -1177,17 +1178,50 @@ static int writeDataSource(int fd, uint32_t mask, void* data) { void CXWM::getTransferData(SXSelection& sel) { Debug::log(LOG, "[xwm] getTransferData"); - sel.transfer->getIncomingSelectionProp(true); - - if (sel.transfer->propertyReply->type == HYPRATOMS["INCR"]) { - Debug::log(ERR, "[xwm] Transfer is INCR, which we don't support :("); - sel.transfer.reset(); + auto it = std::ranges::find_if(sel.transfers, [](const auto& t) { return !t->propertyReply; }); + if (it == sel.transfers.end()) { + Debug::log(ERR, "[xwm] No pending transfer found"); return; - } else { - sel.onWrite(); - if (sel.transfer) - sel.transfer->eventSource = wl_event_loop_add_fd(g_pCompositor->m_sWLEventLoop, sel.transfer->wlFD.get(), WL_EVENT_WRITABLE, ::writeDataSource, &sel); } + + auto& transfer = *it; + if (!transfer || !transfer->incomingWindow) { + Debug::log(ERR, "[xwm] Invalid transfer state"); + sel.transfers.erase(it); + return; + } + + if (!transfer->getIncomingSelectionProp(true)) { + Debug::log(ERR, "[xwm] Failed to get property data"); + sel.transfers.erase(it); + return; + } + + if (!transfer->propertyReply) { + Debug::log(ERR, "[xwm] No property reply"); + sel.transfers.erase(it); + return; + } + + if (transfer->propertyReply->type == HYPRATOMS["INCR"]) { + Debug::log(ERR, "[xwm] Transfer is INCR, which we don't support :("); + sel.transfers.erase(it); + return; + } + + const size_t pos = std::distance(sel.transfers.begin(), it); + sel.onWrite(); + + if (pos >= sel.transfers.size()) + return; + + auto newIt = sel.transfers.begin() + pos; + if (newIt == sel.transfers.end() || !(*newIt)) + return; + + auto& updatedTransfer = *newIt; + if (updatedTransfer->eventSource && updatedTransfer->wlFD.get() != -1) + updatedTransfer->eventSource = wl_event_loop_add_fd(g_pCompositor->m_sWLEventLoop, updatedTransfer->wlFD.get(), WL_EVENT_WRITABLE, ::writeDataSource, &sel); } void CXWM::setCursor(unsigned char* pixData, uint32_t stride, const Vector2D& size, const Vector2D& hotspot) { @@ -1290,16 +1324,21 @@ void SXSelection::onKeyboardFocus() { } int SXSelection::onRead(int fd, uint32_t mask) { - // TODO: support INCR + auto it = std::ranges::find_if(transfers, [fd](const auto& t) { return t->wlFD.get() == fd; }); + if (it == transfers.end()) { + Debug::log(ERR, "[xwm] No transfer found for fd {}", fd); + return 0; + } - size_t pre = transfer->data.size(); + auto& transfer = *it; + size_t pre = transfer->data.size(); transfer->data.resize(INCR_CHUNK_SIZE + pre); auto len = read(fd, transfer->data.data() + pre, INCR_CHUNK_SIZE - 1); if (len < 0) { Debug::log(ERR, "[xwm] readDataSource died"); g_pXWayland->pWM->selectionSendNotify(&transfer->request, false); - transfer.reset(); + transfers.erase(it); return 0; } @@ -1311,7 +1350,7 @@ int SXSelection::onRead(int fd, uint32_t mask) { transfer->data.size(), transfer->data.data()); xcb_flush(g_pXWayland->pWM->connection); g_pXWayland->pWM->selectionSendNotify(&transfer->request, true); - transfer.reset(); + transfers.erase(it); } else Debug::log(LOG, "[xwm] Received {} bytes, waiting...", len); @@ -1346,7 +1385,7 @@ bool SXSelection::sendData(xcb_selection_request_event_t* e, std::string mime) { mime = *MIMES.begin(); } - transfer = makeUnique(*this); + auto transfer = makeUnique(*this); transfer->request = *e; int p[2]; @@ -1368,18 +1407,26 @@ bool SXSelection::sendData(xcb_selection_request_event_t* e, std::string mime) { selection->send(mime, CFileDescriptor{p[1]}); transfer->eventSource = wl_event_loop_add_fd(g_pCompositor->m_sWLEventLoop, transfer->wlFD.get(), WL_EVENT_READABLE, ::readDataSource, this); + transfers.emplace_back(std::move(transfer)); return true; } int SXSelection::onWrite() { + auto it = std::ranges::find_if(transfers, [](const auto& t) { return t->propertyReply; }); + if (it == transfers.end()) { + Debug::log(ERR, "[xwm] No transfer with property data found"); + return 0; + } + + auto& transfer = *it; char* property = (char*)xcb_get_property_value(transfer->propertyReply); int remainder = xcb_get_property_value_length(transfer->propertyReply) - transfer->propertyStart; ssize_t len = write(transfer->wlFD.get(), property + transfer->propertyStart, remainder); if (len == -1) { Debug::log(ERR, "[xwm] write died in transfer get"); - transfer.reset(); + transfers.erase(it); return 0; } @@ -1388,7 +1435,7 @@ int SXSelection::onWrite() { Debug::log(LOG, "[xwm] wl client read partially: len {}", len); } else { Debug::log(LOG, "[xwm] cb transfer to wl client complete, read {} bytes", len); - transfer.reset(); + transfers.erase(it); } return 1; diff --git a/src/xwayland/XWM.hpp b/src/xwayland/XWM.hpp index 73a02a86..f6dcee54 100644 --- a/src/xwayland/XWM.hpp +++ b/src/xwayland/XWM.hpp @@ -58,7 +58,7 @@ struct SXSelection { CHyprSignalListener keyboardFocusChange; } listeners; - UP transfer; + std::vector> transfers; }; class CXCBConnection { From 94a30889a78fa7c7f87fe8134c18357855824c35 Mon Sep 17 00:00:00 2001 From: andrewandreii <63286820+andrewandreii@users.noreply.github.com> Date: Sat, 15 Feb 2025 21:04:02 +0200 Subject: [PATCH 1004/2181] keybinds: fix some errors not returning a failure (#9416) --- src/managers/KeybindManager.cpp | 65 ++++++++++++++++++++++----------- 1 file changed, 43 insertions(+), 22 deletions(-) diff --git a/src/managers/KeybindManager.cpp b/src/managers/KeybindManager.cpp index 4bfd1454..4e63e6dc 100644 --- a/src/managers/KeybindManager.cpp +++ b/src/managers/KeybindManager.cpp @@ -1723,7 +1723,7 @@ SDispatchResult CKeybindManager::changeGroupActive(std::string args) { // index starts from '1'; '0' means last window const int INDEX = std::stoi(args); if (INDEX > PWINDOW->getGroupSize()) - return {}; + return {.success = false, .error = "Index too big, there aren't that many windows in this group"}; if (INDEX == 0) PWINDOW->setGroupCurrent(PWINDOW->getGroupTail()); else @@ -1986,7 +1986,7 @@ SDispatchResult CKeybindManager::moveCurrentWorkspaceToMonitor(std::string args) SDispatchResult CKeybindManager::moveWorkspaceToMonitor(std::string args) { if (!args.contains(' ')) - return {}; + return {.success = false, .error = "Invalid arguments, expected: workspace monitor"}; std::string workspace = args.substr(0, args.find_first_of(' ')); std::string monitor = args.substr(args.find_first_of(' ') + 1); @@ -2129,13 +2129,16 @@ SDispatchResult CKeybindManager::forceRendererReload(std::string args) { SDispatchResult CKeybindManager::resizeActive(std::string args) { const auto PLASTWINDOW = g_pCompositor->m_pLastWindow.lock(); - if (!PLASTWINDOW || PLASTWINDOW->isFullscreen()) - return {}; + if (!PLASTWINDOW) + return {.success = false, .error = "No window found"}; + + if (PLASTWINDOW->isFullscreen()) + return {.success = false, .error = "Window is fullscreen"}; const auto SIZ = g_pCompositor->parseWindowVectorArgsRelative(args, PLASTWINDOW->m_vRealSize->goal()); if (SIZ.x < 1 || SIZ.y < 1) - return {}; + return {.success = false, .error = "Invalid size provided"}; g_pLayoutManager->getCurrentLayout()->resizeActiveWindow(SIZ - PLASTWINDOW->m_vRealSize->goal()); @@ -2148,8 +2151,11 @@ SDispatchResult CKeybindManager::resizeActive(std::string args) { SDispatchResult CKeybindManager::moveActive(std::string args) { const auto PLASTWINDOW = g_pCompositor->m_pLastWindow.lock(); - if (!PLASTWINDOW || PLASTWINDOW->isFullscreen()) - return {}; + if (!PLASTWINDOW) + return {.success = false, .error = "No window found"}; + + if (PLASTWINDOW->isFullscreen()) + return {.success = false, .error = "Window is fullscreen"}; const auto POS = g_pCompositor->parseWindowVectorArgsRelative(args, PLASTWINDOW->m_vRealPosition->goal()); @@ -2171,7 +2177,7 @@ SDispatchResult CKeybindManager::moveWindow(std::string args) { } if (PWINDOW->isFullscreen()) - return {}; + return {.success = false, .error = "Window is fullscreen"}; const auto POS = g_pCompositor->parseWindowVectorArgsRelative(MOVECMD, PWINDOW->m_vRealPosition->goal()); @@ -2193,12 +2199,12 @@ SDispatchResult CKeybindManager::resizeWindow(std::string args) { } if (PWINDOW->isFullscreen()) - return {}; + return {.success = false, .error = "Window is fullscreen"}; const auto SIZ = g_pCompositor->parseWindowVectorArgsRelative(MOVECMD, PWINDOW->m_vRealSize->goal()); if (SIZ.x < 1 || SIZ.y < 1) - return {}; + return {.success = false, .error = "Invalid size provided"}; g_pLayoutManager->getCurrentLayout()->resizeActiveWindow(SIZ - PWINDOW->m_vRealSize->goal(), CORNER_NONE, PWINDOW); @@ -2244,7 +2250,7 @@ SDispatchResult CKeybindManager::focusWindow(std::string regexp) { const auto PWINDOW = g_pCompositor->getWindowByRegex(regexp); if (!PWINDOW) - return {}; + return {.success = false, .error = "No such window found"}; Debug::log(LOG, "Focusing to window name: {}", PWINDOW->m_szTitle); @@ -2304,7 +2310,7 @@ SDispatchResult CKeybindManager::tagWindow(std::string args) { else if (vars.size() == 2) PWINDOW = g_pCompositor->getWindowByRegex(vars[1]); else - return {}; + return {.success = false, .error = "Invalid number of arguments, expected 1 or 2 arguments"}; if (PWINDOW && PWINDOW->m_tags.applyTag(vars[0])) { PWINDOW->updateDynamicRules(); @@ -2674,7 +2680,10 @@ SDispatchResult CKeybindManager::swapActiveWorkspaces(std::string args) { const auto PMON1 = g_pCompositor->getMonitorFromString(MON1); const auto PMON2 = g_pCompositor->getMonitorFromString(MON2); - if (!PMON1 || !PMON2 || PMON1 == PMON2) + if (!PMON1 || !PMON2) + return {.success = false, .error = "No such monitor found"}; + + if (PMON1 == PMON2) return {}; g_pCompositor->swapActiveWorkspaces(PMON1, PMON2); @@ -2697,7 +2706,7 @@ SDispatchResult CKeybindManager::pinActive(std::string args) { } if (!PWINDOW->m_bIsFloating || PWINDOW->isFullscreen()) - return {}; + return {.success = false, .error = "Window does not qualify to be pinned"}; PWINDOW->m_bPinned = !PWINDOW->m_bPinned; @@ -2825,8 +2834,11 @@ SDispatchResult CKeybindManager::lockGroups(std::string args) { SDispatchResult CKeybindManager::lockActiveGroup(std::string args) { const auto PWINDOW = g_pCompositor->m_pLastWindow.lock(); - if (!PWINDOW || !PWINDOW->m_sGroupData.pNextWindow.lock()) - return {}; + if (!PWINDOW) + return {.success = false, .error = "No window found"}; + + if (!PWINDOW->m_sGroupData.pNextWindow.lock()) + return {.success = false, .error = "Not a group"}; const auto PHEAD = PWINDOW->getGroupHead(); @@ -2947,7 +2959,7 @@ SDispatchResult CKeybindManager::moveOutOfGroup(std::string args) { static auto PIGNOREGROUPLOCK = CConfigValue("binds:ignore_group_lock"); if (!*PIGNOREGROUPLOCK && g_pKeybindManager->m_bGroupsLocked) - return {}; + return {.success = false, .error = "Groups locked"}; PHLWINDOW PWINDOW = nullptr; @@ -2956,8 +2968,11 @@ SDispatchResult CKeybindManager::moveOutOfGroup(std::string args) { else PWINDOW = g_pCompositor->m_pLastWindow.lock(); - if (!PWINDOW || !PWINDOW->m_sGroupData.pNextWindow.lock()) - return {}; + if (!PWINDOW) + return {.success = false, .error = "No window found"}; + + if (!PWINDOW->m_sGroupData.pNextWindow.lock()) + return {.success = false, .error = "Window not in a group"}; moveWindowOutOfGroup(PWINDOW); @@ -2975,7 +2990,10 @@ SDispatchResult CKeybindManager::moveWindowOrGroup(std::string args) { } const auto PWINDOW = g_pCompositor->m_pLastWindow.lock(); - if (!PWINDOW || PWINDOW->isFullscreen()) + if (!PWINDOW) + return {.success = false, .error = "No window found"}; + + if (PWINDOW->isFullscreen()) return {}; if (!*PIGNOREGROUPLOCK && g_pKeybindManager->m_bGroupsLocked) { @@ -3064,8 +3082,11 @@ SDispatchResult CKeybindManager::moveGroupWindow(std::string args) { const auto PLASTWINDOW = g_pCompositor->m_pLastWindow.lock(); - if (!PLASTWINDOW || !PLASTWINDOW->m_sGroupData.pNextWindow.lock()) - return {}; + if (!PLASTWINDOW) + return {.success = false, .error = "No window found"}; + + if (!PLASTWINDOW->m_sGroupData.pNextWindow.lock()) + return {.success = false, .error = "Window not in a group"}; if ((!BACK && PLASTWINDOW->m_sGroupData.pNextWindow->m_sGroupData.head) || (BACK && PLASTWINDOW->m_sGroupData.head)) { std::swap(PLASTWINDOW->m_sGroupData.head, PLASTWINDOW->m_sGroupData.pNextWindow->m_sGroupData.head); From 897ee276dc0a8a6b11a8102b225a9e969faac0bf Mon Sep 17 00:00:00 2001 From: Maximilian Seidler <78690852+PaideiaDilemma@users.noreply.github.com> Date: Sun, 16 Feb 2025 00:20:42 +0000 Subject: [PATCH 1005/2181] xwayland: configure on a configure request and cleanup geometry conversion (#9375) * xwayland: configure the window on a configure request * xwayland: move coordinate conversion handling to their own functions * xwayland: rename configure to configureRequest --- src/desktop/Window.cpp | 120 ++++++++++++++++++++++++-------------- src/desktop/Window.hpp | 9 ++- src/xwayland/XSurface.hpp | 4 +- src/xwayland/XWM.cpp | 9 +-- src/xwayland/XWM.hpp | 2 +- 5 files changed, 91 insertions(+), 53 deletions(-) diff --git a/src/desktop/Window.cpp b/src/desktop/Window.cpp index 7c0cb741..7b7f954d 100644 --- a/src/desktop/Window.cpp +++ b/src/desktop/Window.cpp @@ -95,15 +95,15 @@ CWindow::CWindow(SP resource) : m_pXDGSurface(resource) { CWindow::CWindow(SP surface) : m_pXWaylandSurface(surface) { m_pWLSurface = CWLSurface::create(); - listeners.map = m_pXWaylandSurface->events.map.registerListener([this](std::any d) { Events::listener_mapWindow(this, nullptr); }); - listeners.unmap = m_pXWaylandSurface->events.unmap.registerListener([this](std::any d) { Events::listener_unmapWindow(this, nullptr); }); - listeners.destroy = m_pXWaylandSurface->events.destroy.registerListener([this](std::any d) { Events::listener_destroyWindow(this, nullptr); }); - listeners.commit = m_pXWaylandSurface->events.commit.registerListener([this](std::any d) { Events::listener_commitWindow(this, nullptr); }); - listeners.configure = m_pXWaylandSurface->events.configure.registerListener([this](std::any d) { onX11Configure(std::any_cast(d)); }); - listeners.updateState = m_pXWaylandSurface->events.stateChanged.registerListener([this](std::any d) { onUpdateState(); }); - listeners.updateMetadata = m_pXWaylandSurface->events.metadataChanged.registerListener([this](std::any d) { onUpdateMeta(); }); - listeners.resourceChange = m_pXWaylandSurface->events.resourceChange.registerListener([this](std::any d) { onResourceChangeX11(); }); - listeners.activate = m_pXWaylandSurface->events.activate.registerListener([this](std::any d) { Events::listener_activateX11(this, nullptr); }); + listeners.map = m_pXWaylandSurface->events.map.registerListener([this](std::any d) { Events::listener_mapWindow(this, nullptr); }); + listeners.unmap = m_pXWaylandSurface->events.unmap.registerListener([this](std::any d) { Events::listener_unmapWindow(this, nullptr); }); + listeners.destroy = m_pXWaylandSurface->events.destroy.registerListener([this](std::any d) { Events::listener_destroyWindow(this, nullptr); }); + listeners.commit = m_pXWaylandSurface->events.commit.registerListener([this](std::any d) { Events::listener_commitWindow(this, nullptr); }); + listeners.configureRequest = m_pXWaylandSurface->events.configureRequest.registerListener([this](std::any d) { onX11ConfigureRequest(std::any_cast(d)); }); + listeners.updateState = m_pXWaylandSurface->events.stateChanged.registerListener([this](std::any d) { onUpdateState(); }); + listeners.updateMetadata = m_pXWaylandSurface->events.metadataChanged.registerListener([this](std::any d) { onUpdateMeta(); }); + listeners.resourceChange = m_pXWaylandSurface->events.resourceChange.registerListener([this](std::any d) { onResourceChangeX11(); }); + listeners.activate = m_pXWaylandSurface->events.activate.registerListener([this](std::any d) { Events::listener_activateX11(this, nullptr); }); if (m_pXWaylandSurface->overrideRedirect) listeners.setGeometry = m_pXWaylandSurface->events.setGeometry.registerListener([this](std::any d) { Events::listener_unmanagedSetGeometry(this, nullptr); }); @@ -1530,14 +1530,14 @@ void CWindow::onResourceChangeX11() { Debug::log(LOG, "xwayland window {:x} -> association to {:x}", (uintptr_t)m_pXWaylandSurface.get(), (uintptr_t)m_pWLSurface->resource().get()); } -void CWindow::onX11Configure(CBox box) { +void CWindow::onX11ConfigureRequest(CBox box) { if (!m_pXWaylandSurface->surface || !m_pXWaylandSurface->mapped || !m_bIsMapped) { m_pXWaylandSurface->configure(box); m_vPendingReportedSize = box.size(); m_vReportedSize = box.size(); - if (const auto PMONITOR = m_pMonitor.lock(); PMONITOR) - m_fX11SurfaceScaledBy = PMONITOR->scale; + m_vReportedPosition = box.pos(); + updateX11SurfaceScale(); return; } @@ -1555,25 +1555,20 @@ void CWindow::onX11Configure(CBox box) { else setHidden(true); - const auto LOGICALPOS = g_pXWaylandManager->xwaylandToWaylandCoords(box.pos()); - - m_vRealPosition->setValueAndWarp(LOGICALPOS); - m_vRealSize->setValueAndWarp(box.size()); - - static auto PXWLFORCESCALEZERO = CConfigValue("xwayland:force_zero_scaling"); - if (*PXWLFORCESCALEZERO) { - if (const auto PMONITOR = m_pMonitor.lock(); PMONITOR) { - m_vRealSize->setValueAndWarp(m_vRealSize->goal() / PMONITOR->scale); - m_fX11SurfaceScaledBy = PMONITOR->scale; - } - } + m_vRealPosition->setValueAndWarp(xwaylandPositionToReal(box.pos())); + m_vRealSize->setValueAndWarp(xwaylandSizeToReal(box.size())); m_vPosition = m_vRealPosition->goal(); m_vSize = m_vRealSize->goal(); - m_vPendingReportedSize = box.size(); - m_vReportedSize = box.size(); + if (m_vPendingReportedSize != box.size() || m_vReportedPosition != box.pos()) { + m_pXWaylandSurface->configure(box); + m_vReportedSize = box.size(); + m_vPendingReportedSize = box.size(); + m_vReportedPosition = box.pos(); + } + updateX11SurfaceScale(); updateWindowDecos(); if (!m_pWorkspace || !m_pWorkspace->isVisible()) @@ -1700,37 +1695,74 @@ Vector2D CWindow::requestedMaxSize() { return maxSize; } -void CWindow::sendWindowSize(bool force) { +Vector2D CWindow::realToReportSize() { + if (!m_bIsX11) + return m_vRealSize->goal().clamp(Vector2D{0, 0}, Vector2D{std::numeric_limits::infinity(), std::numeric_limits::infinity()}); + static auto PXWLFORCESCALEZERO = CConfigValue("xwayland:force_zero_scaling"); - const auto PMONITOR = m_pMonitor.lock(); + + const auto REPORTSIZE = m_vRealSize->goal().clamp(Vector2D{1, 1}, Vector2D{std::numeric_limits::infinity(), std::numeric_limits::infinity()}); + const auto PMONITOR = m_pMonitor.lock(); + + if (*PXWLFORCESCALEZERO && PMONITOR) + return REPORTSIZE * PMONITOR->scale; + + return REPORTSIZE; +} + +Vector2D CWindow::realToReportPosition() { + if (!m_bIsX11) + return m_vRealPosition->goal(); + + return g_pXWaylandManager->waylandToXWaylandCoords(m_vRealPosition->goal()); +} + +Vector2D CWindow::xwaylandSizeToReal(Vector2D size) { + static auto PXWLFORCESCALEZERO = CConfigValue("xwayland:force_zero_scaling"); + + const auto PMONITOR = m_pMonitor.lock(); + const auto SIZE = size.clamp(Vector2D{1, 1}, Vector2D{std::numeric_limits::infinity(), std::numeric_limits::infinity()}); + const auto SCALE = *PXWLFORCESCALEZERO ? PMONITOR->scale : 1.0f; + + return SIZE / SCALE; +} + +Vector2D CWindow::xwaylandPositionToReal(Vector2D pos) { + return g_pXWaylandManager->xwaylandToWaylandCoords(pos); +} + +void CWindow::updateX11SurfaceScale() { + static auto PXWLFORCESCALEZERO = CConfigValue("xwayland:force_zero_scaling"); + + m_fX11SurfaceScaledBy = 1.0f; + if (m_bIsX11 && *PXWLFORCESCALEZERO) { + if (const auto PMONITOR = m_pMonitor.lock(); PMONITOR) + m_fX11SurfaceScaledBy = PMONITOR->scale; + } +} + +void CWindow::sendWindowSize(bool force) { + const auto PMONITOR = m_pMonitor.lock(); Debug::log(TRACE, "sendWindowSize: window:{:x},title:{} with real pos {}, real size {} (force: {})", (uintptr_t)this, this->m_szTitle, m_vRealPosition->goal(), m_vRealSize->goal(), force); // TODO: this should be decoupled from setWindowSize IMO - Vector2D windowPos = m_vRealPosition->goal(); - Vector2D size = m_vRealSize->goal().clamp(Vector2D{1, 1}, Vector2D{std::numeric_limits::infinity(), std::numeric_limits::infinity()}); + const auto REPORTPOS = realToReportPosition(); - if (m_bIsX11 && PMONITOR) { - windowPos = g_pXWaylandManager->waylandToXWaylandCoords(windowPos); - if (*PXWLFORCESCALEZERO) - size *= PMONITOR->scale; - } + const auto REPORTSIZE = realToReportSize(); - if (!force && m_vPendingReportedSize == size && (windowPos == m_vReportedPosition || !m_bIsX11)) + if (!force && m_vPendingReportedSize == REPORTSIZE && (m_vReportedPosition == REPORTPOS || !m_bIsX11)) return; - m_vReportedPosition = windowPos; - m_vPendingReportedSize = size; - m_fX11SurfaceScaledBy = 1.0f; - - if (*PXWLFORCESCALEZERO && m_bIsX11 && PMONITOR) - m_fX11SurfaceScaledBy = PMONITOR->scale; + m_vReportedPosition = REPORTPOS; + m_vPendingReportedSize = REPORTSIZE; + updateX11SurfaceScale(); if (m_bIsX11 && m_pXWaylandSurface) - m_pXWaylandSurface->configure({windowPos, size}); + m_pXWaylandSurface->configure({REPORTPOS, REPORTSIZE}); else if (m_pXDGSurface && m_pXDGSurface->toplevel) - m_vPendingSizeAcks.emplace_back(m_pXDGSurface->toplevel->setSize(size), size.floor()); + m_vPendingSizeAcks.emplace_back(m_pXDGSurface->toplevel->setSize(REPORTSIZE), REPORTPOS.floor()); } NContentType::eContentType CWindow::getContentType() { diff --git a/src/desktop/Window.hpp b/src/desktop/Window.hpp index 171a15f4..bc32bab4 100644 --- a/src/desktop/Window.hpp +++ b/src/desktop/Window.hpp @@ -460,7 +460,7 @@ class CWindow { void onFocusAnimUpdate(); void onUpdateState(); void onUpdateMeta(); - void onX11Configure(CBox box); + void onX11ConfigureRequest(CBox box); void onResourceChangeX11(); std::string fetchTitle(); std::string fetchClass(); @@ -471,6 +471,11 @@ class CWindow { bool isModal(); Vector2D requestedMinSize(); Vector2D requestedMaxSize(); + Vector2D realToReportSize(); + Vector2D realToReportPosition(); + Vector2D xwaylandSizeToReal(Vector2D size); + Vector2D xwaylandPositionToReal(Vector2D size); + void updateX11SurfaceScale(); void sendWindowSize(bool force = false); NContentType::eContentType getContentType(); void setContentType(NContentType::eContentType contentType); @@ -497,7 +502,7 @@ class CWindow { CHyprSignalListener commit; CHyprSignalListener destroy; CHyprSignalListener activate; - CHyprSignalListener configure; + CHyprSignalListener configureRequest; CHyprSignalListener setGeometry; CHyprSignalListener updateState; CHyprSignalListener updateMetadata; diff --git a/src/xwayland/XSurface.hpp b/src/xwayland/XSurface.hpp index 7584354e..55e96078 100644 --- a/src/xwayland/XSurface.hpp +++ b/src/xwayland/XSurface.hpp @@ -50,7 +50,7 @@ class CXWaylandSurface { CSignal resourceChange; // associated / dissociated CSignal setGeometry; - CSignal configure; // CBox + CSignal configureRequest; // CBox CSignal map; CSignal unmap; @@ -116,4 +116,4 @@ class CXWaylandSurface { } listeners; friend class CXWM; -}; \ No newline at end of file +}; diff --git a/src/xwayland/XWM.cpp b/src/xwayland/XWM.cpp index f2a9b794..a4e3289b 100644 --- a/src/xwayland/XWM.cpp +++ b/src/xwayland/XWM.cpp @@ -59,7 +59,7 @@ void CXWM::handleDestroy(xcb_destroy_notify_event_t* e) { std::erase_if(surfaces, [XSURF](const auto& other) { return XSURF == other; }); } -void CXWM::handleConfigure(xcb_configure_request_event_t* e) { +void CXWM::handleConfigureRequest(xcb_configure_request_event_t* e) { const auto XSURF = windowForXID(e->window); if (!XSURF) @@ -70,8 +70,9 @@ void CXWM::handleConfigure(xcb_configure_request_event_t* e) { if (!(MASK & GEOMETRY)) return; - XSURF->events.configure.emit(CBox{MASK & XCB_CONFIG_WINDOW_X ? e->x : XSURF->geometry.x, MASK & XCB_CONFIG_WINDOW_Y ? e->y : XSURF->geometry.y, - MASK & XCB_CONFIG_WINDOW_WIDTH ? e->width : XSURF->geometry.width, MASK & XCB_CONFIG_WINDOW_HEIGHT ? e->height : XSURF->geometry.height}); + XSURF->events.configureRequest.emit(CBox{MASK & XCB_CONFIG_WINDOW_X ? e->x : XSURF->geometry.x, MASK & XCB_CONFIG_WINDOW_Y ? e->y : XSURF->geometry.y, + MASK & XCB_CONFIG_WINDOW_WIDTH ? e->width : XSURF->geometry.width, + MASK & XCB_CONFIG_WINDOW_HEIGHT ? e->height : XSURF->geometry.height}); } void CXWM::handleConfigureNotify(xcb_configure_notify_event_t* e) { @@ -758,7 +759,7 @@ int CXWM::onEvent(int fd, uint32_t mask) { switch (event->response_type & XCB_EVENT_RESPONSE_TYPE_MASK) { case XCB_CREATE_NOTIFY: handleCreate((xcb_create_notify_event_t*)event); break; case XCB_DESTROY_NOTIFY: handleDestroy((xcb_destroy_notify_event_t*)event); break; - case XCB_CONFIGURE_REQUEST: handleConfigure((xcb_configure_request_event_t*)event); break; + case XCB_CONFIGURE_REQUEST: handleConfigureRequest((xcb_configure_request_event_t*)event); break; case XCB_CONFIGURE_NOTIFY: handleConfigureNotify((xcb_configure_notify_event_t*)event); break; case XCB_MAP_REQUEST: handleMapRequest((xcb_map_request_event_t*)event); break; case XCB_MAP_NOTIFY: handleMapNotify((xcb_map_notify_event_t*)event); break; diff --git a/src/xwayland/XWM.hpp b/src/xwayland/XWM.hpp index f6dcee54..4326c77b 100644 --- a/src/xwayland/XWM.hpp +++ b/src/xwayland/XWM.hpp @@ -148,7 +148,7 @@ class CXWM { // event handlers void handleCreate(xcb_create_notify_event_t* e); void handleDestroy(xcb_destroy_notify_event_t* e); - void handleConfigure(xcb_configure_request_event_t* e); + void handleConfigureRequest(xcb_configure_request_event_t* e); void handleConfigureNotify(xcb_configure_notify_event_t* e); void handleMapRequest(xcb_map_request_event_t* e); void handleMapNotify(xcb_map_notify_event_t* e); From e2a9271150f9f1a2cba825f6f21bb130effc6b11 Mon Sep 17 00:00:00 2001 From: Vaxry Date: Sun, 16 Feb 2025 20:53:49 +0000 Subject: [PATCH 1006/2181] animations: add the gnomed animation style for windows --- src/managers/AnimationManager.cpp | 23 +++++++++++++++++++++-- src/managers/AnimationManager.hpp | 1 + 2 files changed, 22 insertions(+), 2 deletions(-) diff --git a/src/managers/AnimationManager.cpp b/src/managers/AnimationManager.cpp index 29f669dc..18dae2a4 100644 --- a/src/managers/AnimationManager.cpp +++ b/src/managers/AnimationManager.cpp @@ -357,6 +357,21 @@ void CHyprAnimationManager::animationSlide(PHLWINDOW pWindow, std::string force, *pWindow->m_vRealPosition = posOffset; } +void CHyprAnimationManager::animationGnomed(PHLWINDOW pWindow, bool close) { + const auto GOALPOS = pWindow->m_vRealPosition->goal(); + const auto GOALSIZE = pWindow->m_vRealSize->goal(); + + if (close) { + *pWindow->m_vRealPosition = GOALPOS + Vector2D{0.F, GOALSIZE.y / 2.F}; + *pWindow->m_vRealSize = Vector2D{GOALSIZE.x, 0.F}; + } else { + pWindow->m_vRealPosition->setValueAndWarp(GOALPOS + Vector2D{0.F, GOALSIZE.y / 2.F}); + pWindow->m_vRealSize->setValueAndWarp(Vector2D{GOALSIZE.x, 0.F}); + *pWindow->m_vRealPosition = GOALPOS; + *pWindow->m_vRealSize = GOALSIZE; + } +} + void CHyprAnimationManager::onWindowPostCreateClose(PHLWINDOW pWindow, bool close) { if (!close) { pWindow->m_vRealPosition->setConfig(g_pConfigManager->getAnimationPropertyConfig("windowsIn")); @@ -387,7 +402,9 @@ void CHyprAnimationManager::onWindowPostCreateClose(PHLWINDOW pWindow, bool clos if (STYLE.starts_with("slide")) { CVarList animList2(STYLE, 0, 's'); animationSlide(pWindow, animList2[1], close); - } else { + } else if (STYLE == "gnomed" || STYLE == "gnome") + animationGnomed(pWindow, close); + else { // anim popin, fallback float minPerc = 0.f; @@ -405,6 +422,8 @@ void CHyprAnimationManager::onWindowPostCreateClose(PHLWINDOW pWindow, bool clos } else { if (animList[0] == "slide") animationSlide(pWindow, animList[1], close); + else if (animList[0] == "gnomed" || animList[0] == "gnome") + animationGnomed(pWindow, close); else { // anim popin, fallback @@ -425,7 +444,7 @@ void CHyprAnimationManager::onWindowPostCreateClose(PHLWINDOW pWindow, bool clos std::string CHyprAnimationManager::styleValidInConfigVar(const std::string& config, const std::string& style) { if (config.starts_with("window")) { - if (style.starts_with("slide")) + if (style.starts_with("slide") || style == "gnome" || style == "gnomed") return ""; else if (style.starts_with("popin")) { // try parsing diff --git a/src/managers/AnimationManager.hpp b/src/managers/AnimationManager.hpp index 067fa676..833087d7 100644 --- a/src/managers/AnimationManager.hpp +++ b/src/managers/AnimationManager.hpp @@ -59,6 +59,7 @@ class CHyprAnimationManager : public Hyprutils::Animation::CAnimationManager { // Anim stuff void animationPopin(PHLWINDOW, bool close = false, float minPerc = 0.f); void animationSlide(PHLWINDOW, std::string force = "", bool close = false); + void animationGnomed(PHLWINDOW, bool close = false); }; inline UP g_pAnimationManager; From 59c615c321c45302491de3b1c003844c86aefca7 Mon Sep 17 00:00:00 2001 From: andrewandreii <63286820+andrewandreii@users.noreply.github.com> Date: Mon, 17 Feb 2025 04:03:27 +0200 Subject: [PATCH 1007/2181] input: add follow_mouse_threshold (#9392) --- src/config/ConfigDescriptions.hpp | 6 ++++++ src/config/ConfigManager.cpp | 1 + src/managers/input/InputManager.cpp | 29 ++++++++++++++++++----------- src/managers/input/InputManager.hpp | 1 + 4 files changed, 26 insertions(+), 11 deletions(-) diff --git a/src/config/ConfigDescriptions.hpp b/src/config/ConfigDescriptions.hpp index 23635760..1283050d 100644 --- a/src/config/ConfigDescriptions.hpp +++ b/src/config/ConfigDescriptions.hpp @@ -501,6 +501,12 @@ inline static const std::vector CONFIG_OPTIONS = { .type = CONFIG_OPTION_INT, .data = SConfigOptionDescription::SRangeData{1, 0, 3}, }, + SConfigOptionDescription{ + .value = "input:follow_mouse_threshold", + .description = "The smallest distance in logical pixels the mouse needs to travel for the window under it to get focused. Works only with follow_mouse = 1.", + .type = CONFIG_OPTION_FLOAT, + .data = SConfigOptionDescription::SFloatData{}, + }, SConfigOptionDescription{ .value = "input:focus_on_close", .description = "Controls the window focus behavior when a window is closed. When set to 0, focus will shift to the next window candidate. When set to 1, focus will shift " diff --git a/src/config/ConfigManager.cpp b/src/config/ConfigManager.cpp index 00dba200..dc56d73f 100644 --- a/src/config/ConfigManager.cpp +++ b/src/config/ConfigManager.cpp @@ -539,6 +539,7 @@ CConfigManager::CConfigManager() { m_pConfig->addConfigValue("animations:first_launch_animation", Hyprlang::INT{1}); m_pConfig->addConfigValue("input:follow_mouse", Hyprlang::INT{1}); + m_pConfig->addConfigValue("input:follow_mouse_threshold", Hyprlang::FLOAT{0}); m_pConfig->addConfigValue("input:focus_on_close", Hyprlang::INT{0}); m_pConfig->addConfigValue("input:mouse_refocus", Hyprlang::INT{1}); m_pConfig->addConfigValue("input:special_fallthrough", Hyprlang::INT{0}); diff --git a/src/managers/input/InputManager.cpp b/src/managers/input/InputManager.cpp index 3d8c6de8..1d16f915 100644 --- a/src/managers/input/InputManager.cpp +++ b/src/managers/input/InputManager.cpp @@ -161,17 +161,23 @@ void CInputManager::mouseMoveUnified(uint32_t time, bool refocus, bool mouse) { if (MOUSECOORDSFLOORED == m_vLastCursorPosFloored && !refocus) return; - static auto PFOLLOWMOUSE = CConfigValue("input:follow_mouse"); - static auto PMOUSEREFOCUS = CConfigValue("input:mouse_refocus"); - static auto PFOLLOWONDND = CConfigValue("misc:always_follow_on_dnd"); - static auto PFLOATBEHAVIOR = CConfigValue("input:float_switch_override_focus"); - static auto PMOUSEFOCUSMON = CConfigValue("misc:mouse_move_focuses_monitor"); - static auto PRESIZEONBORDER = CConfigValue("general:resize_on_border"); - static auto PRESIZECURSORICON = CConfigValue("general:hover_icon_on_border"); - static auto PZOOMFACTOR = CConfigValue("cursor:zoom_factor"); + static auto PFOLLOWMOUSE = CConfigValue("input:follow_mouse"); + static auto PFOLLOWMOUSETHRESHOLD = CConfigValue("input:follow_mouse_threshold"); + static auto PMOUSEREFOCUS = CConfigValue("input:mouse_refocus"); + static auto PFOLLOWONDND = CConfigValue("misc:always_follow_on_dnd"); + static auto PFLOATBEHAVIOR = CConfigValue("input:float_switch_override_focus"); + static auto PMOUSEFOCUSMON = CConfigValue("misc:mouse_move_focuses_monitor"); + static auto PRESIZEONBORDER = CConfigValue("general:resize_on_border"); + static auto PRESIZECURSORICON = CConfigValue("general:hover_icon_on_border"); + static auto PZOOMFACTOR = CConfigValue("cursor:zoom_factor"); const auto FOLLOWMOUSE = *PFOLLOWONDND && PROTO::data->dndActive() ? 1 : *PFOLLOWMOUSE; + if (FOLLOWMOUSE == 1 && m_tmrLastCursorMovement.getSeconds() < 0.5) + m_fMousePosDelta += MOUSECOORDSFLOORED.distance(m_vLastCursorPosFloored); + else + m_fMousePosDelta = 0; + m_pFoundSurfaceToFocus.reset(); m_pFoundLSToFocus.reset(); m_pFoundWindowToFocus.reset(); @@ -513,9 +519,10 @@ void CInputManager::mouseMoveUnified(uint32_t time, bool refocus, bool mouse) { // TODO: this looks wrong. When over a popup, it constantly is switching. // Temp fix until that's figured out. Otherwise spams windowrule lookups and other shit. - if (m_pLastMouseFocus.lock() != pFoundWindow || g_pCompositor->m_pLastWindow.lock() != pFoundWindow) - g_pCompositor->focusWindow(pFoundWindow, foundSurface); - else + if (m_pLastMouseFocus.lock() != pFoundWindow || g_pCompositor->m_pLastWindow.lock() != pFoundWindow) { + if (m_fMousePosDelta > *PFOLLOWMOUSETHRESHOLD || refocus) + g_pCompositor->focusWindow(pFoundWindow, foundSurface); + } else g_pCompositor->focusSurface(foundSurface, pFoundWindow); } } diff --git a/src/managers/input/InputManager.hpp b/src/managers/input/InputManager.hpp index 3afb1b88..7774a6db 100644 --- a/src/managers/input/InputManager.hpp +++ b/src/managers/input/InputManager.hpp @@ -255,6 +255,7 @@ class CInputManager { // used for warping back after non-mouse input Vector2D m_vLastMousePos = {}; + double m_fMousePosDelta = 0; bool m_bLastInputMouse = true; // for holding focus on buttons held From d01f9943e1d401b09fc53be3c161279ab4f2c5ba Mon Sep 17 00:00:00 2001 From: nyx Date: Mon, 17 Feb 2025 13:02:32 -0500 Subject: [PATCH 1008/2181] subsurfaces: dont try to access popup surfaces when handling subsurface updates (#9421) --- src/desktop/Popup.cpp | 7 +++++++ src/desktop/Popup.hpp | 1 + src/desktop/Subsurface.cpp | 4 ++-- 3 files changed, 10 insertions(+), 2 deletions(-) diff --git a/src/desktop/Popup.cpp b/src/desktop/Popup.cpp index 82767ead..912069e7 100644 --- a/src/desktop/Popup.cpp +++ b/src/desktop/Popup.cpp @@ -282,6 +282,9 @@ void CPopup::recheckTree() { } void CPopup::recheckChildrenRecursive() { + if (m_bInert || !m_pWLSurface) + return; + std::vector> cpy; std::ranges::for_each(m_vChildren, [&cpy](const auto& el) { cpy.emplace_back(el); }); for (auto const& c : cpy) { @@ -367,3 +370,7 @@ WP CPopup::at(const Vector2D& globalCoords, bool allowsInput) { return {}; } + +bool CPopup::inert() const { + return m_bInert; +} diff --git a/src/desktop/Popup.hpp b/src/desktop/Popup.hpp index 0bca436c..f6ca65da 100644 --- a/src/desktop/Popup.hpp +++ b/src/desktop/Popup.hpp @@ -34,6 +34,7 @@ class CPopup { void recheckTree(); bool visible(); + bool inert() const; // will also loop over this node void breadthfirst(std::function, void*)> fn, void* data); diff --git a/src/desktop/Subsurface.cpp b/src/desktop/Subsurface.cpp index db106a09..9846764c 100644 --- a/src/desktop/Subsurface.cpp +++ b/src/desktop/Subsurface.cpp @@ -107,7 +107,7 @@ void CSubsurface::onCommit() { g_pHyprRenderer->damageSurface(m_pWLSurface->resource(), COORDS.x, COORDS.y); - if (m_pPopupParent) + if (m_pPopupParent && !m_pPopupParent->inert() && m_pPopupParent->m_pWLSurface) m_pPopupParent->recheckTree(); if (!m_pWindowParent.expired()) // I hate you firefox why are you doing this m_pWindowParent->m_pPopupHead->recheckTree(); @@ -124,7 +124,7 @@ void CSubsurface::onCommit() { // g_pHyprRenderer->damageBox(box); CBox box; - if (m_pPopupParent) + if (m_pPopupParent && !m_pPopupParent->inert() && m_pPopupParent->m_pWLSurface) box = m_pPopupParent->m_pWLSurface->getSurfaceBoxGlobal().value_or(CBox{}); else if (m_pWindowParent) box = m_pWindowParent->getWindowMainSurfaceBox(); From e59623d1d564089543cddb496fbed30fbd6ab247 Mon Sep 17 00:00:00 2001 From: Vaxry Date: Tue, 18 Feb 2025 00:33:27 +0000 Subject: [PATCH 1009/2181] hyprctl: don't return empty str if there are no global shortcuts fixes #6043 --- src/debug/HyprCtl.cpp | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/debug/HyprCtl.cpp b/src/debug/HyprCtl.cpp index a155474d..174eb932 100644 --- a/src/debug/HyprCtl.cpp +++ b/src/debug/HyprCtl.cpp @@ -811,8 +811,11 @@ static std::string globalShortcutsRequest(eHyprCtlOutputFormat format, std::stri std::string ret = ""; const auto SHORTCUTS = PROTO::globalShortcuts->getAllShortcuts(); if (format == eHyprCtlOutputFormat::FORMAT_NORMAL) { - for (auto const& sh : SHORTCUTS) + for (auto const& sh : SHORTCUTS) { ret += std::format("{}:{} -> {}\n", sh.appid, sh.id, sh.description); + } + if (ret.empty()) + ret = "none"; } else { ret += "["; for (auto const& sh : SHORTCUTS) { From 3352317ca827dfb2dfd222274dfaf5941c78c086 Mon Sep 17 00:00:00 2001 From: nyx Date: Tue, 18 Feb 2025 09:18:22 -0500 Subject: [PATCH 1010/2181] scripts/generateVersion.sh: convert to posix (#9433) --- scripts/generateVersion.sh | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/scripts/generateVersion.sh b/scripts/generateVersion.sh index e88cef3f..9313815d 100755 --- a/scripts/generateVersion.sh +++ b/scripts/generateVersion.sh @@ -2,8 +2,8 @@ # if the git directory doesn't exist, don't gather data to avoid overwriting, unless # the version file is missing altogether (otherwise compiling will fail) -if [[ ! -d ./.git ]]; then - if [[ -f ./src/version.h ]]; then +if [ ! -d ./.git ]; then + if [ -f ./src/version.h ]; then exit 0 fi fi From fb8eaba83f2d114fb346730e789a559ccc366887 Mon Sep 17 00:00:00 2001 From: Vaxry Date: Tue, 18 Feb 2025 15:10:40 +0000 Subject: [PATCH 1011/2181] core: add an ANR dialog for xdg-shell, we can ping the wm_base, and thus render an ANR dialog if an app dies for XWayland, there probably is a similar method, but I don't know about it and don't care. --- CMakeLists.txt | 2 +- src/Compositor.cpp | 5 + src/config/ConfigManager.cpp | 1 + src/desktop/Window.cpp | 10 ++ src/desktop/Window.hpp | 4 + src/managers/ANRManager.cpp | 173 +++++++++++++++++++++++++++++++++++ src/managers/ANRManager.hpp | 46 ++++++++++ src/protocols/XDGShell.cpp | 10 ++ src/protocols/XDGShell.hpp | 5 + src/render/OpenGL.cpp | 16 +++- src/render/Renderer.cpp | 6 ++ 11 files changed, 272 insertions(+), 6 deletions(-) create mode 100644 src/managers/ANRManager.cpp create mode 100644 src/managers/ANRManager.hpp diff --git a/CMakeLists.txt b/CMakeLists.txt index a98f697d..22bc7498 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -104,7 +104,7 @@ find_package(OpenGL REQUIRED COMPONENTS ${GLES_VERSION}) pkg_check_modules(aquamarine_dep REQUIRED IMPORTED_TARGET aquamarine>=0.4.5) pkg_check_modules(hyprlang_dep REQUIRED IMPORTED_TARGET hyprlang>=0.3.2) pkg_check_modules(hyprcursor_dep REQUIRED IMPORTED_TARGET hyprcursor>=0.1.7) -pkg_check_modules(hyprutils_dep REQUIRED IMPORTED_TARGET hyprutils>=0.5.0) +pkg_check_modules(hyprutils_dep REQUIRED IMPORTED_TARGET hyprutils>=0.5.1) pkg_check_modules(hyprgraphics_dep REQUIRED IMPORTED_TARGET hyprgraphics>=0.1.1) string(REPLACE "." ";" AQ_VERSION_LIST ${aquamarine_dep_VERSION}) diff --git a/src/Compositor.cpp b/src/Compositor.cpp index 5389844f..a35e4216 100644 --- a/src/Compositor.cpp +++ b/src/Compositor.cpp @@ -13,6 +13,7 @@ #include "managers/SeatManager.hpp" #include "managers/VersionKeeperManager.hpp" #include "managers/DonationNagManager.hpp" +#include "managers/ANRManager.hpp" #include "managers/eventLoop/EventLoopManager.hpp" #include #include @@ -592,6 +593,7 @@ void CCompositor::cleanup() { g_pEventLoopManager.reset(); g_pVersionKeeperMgr.reset(); g_pDonationNagManager.reset(); + g_pANRManager.reset(); g_pConfigWatcher.reset(); if (m_pAqBackend) @@ -694,6 +696,9 @@ void CCompositor::initManagers(eManagersInitStage stage) { Debug::log(LOG, "Creating the DonationNag!"); g_pDonationNagManager = makeUnique(); + Debug::log(LOG, "Creating the ANRManager!"); + g_pANRManager = makeUnique(); + Debug::log(LOG, "Starting XWayland"); g_pXWayland = makeUnique(g_pCompositor->m_bWantsXwayland); } break; diff --git a/src/config/ConfigManager.cpp b/src/config/ConfigManager.cpp index dc56d73f..9b547ffb 100644 --- a/src/config/ConfigManager.cpp +++ b/src/config/ConfigManager.cpp @@ -430,6 +430,7 @@ CConfigManager::CConfigManager() { m_pConfig->addConfigValue("misc:disable_xdg_env_checks", Hyprlang::INT{0}); m_pConfig->addConfigValue("misc:disable_hyprland_qtutils_check", Hyprlang::INT{0}); m_pConfig->addConfigValue("misc:lockdead_screen_delay", Hyprlang::INT{1000}); + m_pConfig->addConfigValue("misc:enable_anr_dialog", Hyprlang::INT{1}); m_pConfig->addConfigValue("group:insert_after_current", Hyprlang::INT{1}); m_pConfig->addConfigValue("group:focus_removed_window", Hyprlang::INT{1}); diff --git a/src/desktop/Window.cpp b/src/desktop/Window.cpp index 7b7f954d..7c0693bf 100644 --- a/src/desktop/Window.cpp +++ b/src/desktop/Window.cpp @@ -13,6 +13,7 @@ #include "../config/ConfigValue.hpp" #include "../managers/TokenManager.hpp" #include "../managers/AnimationManager.hpp" +#include "../managers/ANRManager.hpp" #include "../protocols/XDGShell.hpp" #include "../protocols/core/Compositor.hpp" #include "../protocols/ContentType.hpp" @@ -48,6 +49,7 @@ PHLWINDOW CWindow::create(SP surface) { g_pAnimationManager->createAnimation(0.f, pWindow->m_fDimPercent, g_pConfigManager->getAnimationPropertyConfig("fadeDim"), pWindow, AVARDAMAGE_ENTIRE); g_pAnimationManager->createAnimation(0.f, pWindow->m_fMovingToWorkspaceAlpha, g_pConfigManager->getAnimationPropertyConfig("fadeOut"), pWindow, AVARDAMAGE_ENTIRE); g_pAnimationManager->createAnimation(0.f, pWindow->m_fMovingFromWorkspaceAlpha, g_pConfigManager->getAnimationPropertyConfig("fadeIn"), pWindow, AVARDAMAGE_ENTIRE); + g_pAnimationManager->createAnimation(0.f, pWindow->m_notRespondingTint, g_pConfigManager->getAnimationPropertyConfig("fade"), pWindow, AVARDAMAGE_ENTIRE); pWindow->addWindowDeco(makeUnique(pWindow)); pWindow->addWindowDeco(makeUnique(pWindow)); @@ -71,6 +73,7 @@ PHLWINDOW CWindow::create(SP resource) { g_pAnimationManager->createAnimation(0.f, pWindow->m_fDimPercent, g_pConfigManager->getAnimationPropertyConfig("fadeDim"), pWindow, AVARDAMAGE_ENTIRE); g_pAnimationManager->createAnimation(0.f, pWindow->m_fMovingToWorkspaceAlpha, g_pConfigManager->getAnimationPropertyConfig("fadeOut"), pWindow, AVARDAMAGE_ENTIRE); g_pAnimationManager->createAnimation(0.f, pWindow->m_fMovingFromWorkspaceAlpha, g_pConfigManager->getAnimationPropertyConfig("fadeIn"), pWindow, AVARDAMAGE_ENTIRE); + g_pAnimationManager->createAnimation(0.f, pWindow->m_notRespondingTint, g_pConfigManager->getAnimationPropertyConfig("fade"), pWindow, AVARDAMAGE_ENTIRE); pWindow->addWindowDeco(makeUnique(pWindow)); pWindow->addWindowDeco(makeUnique(pWindow)); @@ -1796,3 +1799,10 @@ void CWindow::deactivateGroupMembers() { break; } } + +bool CWindow::isNotResponding() { + if (!m_pXDGSurface) + return false; + + return g_pANRManager->isNotResponding(m_pXDGSurface->owner.lock()); +} diff --git a/src/desktop/Window.hpp b/src/desktop/Window.hpp index bc32bab4..50b61050 100644 --- a/src/desktop/Window.hpp +++ b/src/desktop/Window.hpp @@ -388,6 +388,9 @@ class CWindow { // window tags CTagKeeper m_tags; + // ANR + PHLANIMVAR m_notRespondingTint; + // For the list lookup bool operator==(const CWindow& rhs) const { return m_pXDGSurface == rhs.m_pXDGSurface && m_pXWaylandSurface == rhs.m_pXWaylandSurface && m_vPosition == rhs.m_vPosition && m_vSize == rhs.m_vSize && @@ -480,6 +483,7 @@ class CWindow { NContentType::eContentType getContentType(); void setContentType(NContentType::eContentType contentType); void deactivateGroupMembers(); + bool isNotResponding(); CBox getWindowMainSurfaceBox() const { return {m_vRealPosition->value().x, m_vRealPosition->value().y, m_vRealSize->value().x, m_vRealSize->value().y}; diff --git a/src/managers/ANRManager.cpp b/src/managers/ANRManager.cpp new file mode 100644 index 00000000..e2b276ee --- /dev/null +++ b/src/managers/ANRManager.cpp @@ -0,0 +1,173 @@ +#include "ANRManager.hpp" +#include "../helpers/fs/FsUtils.hpp" +#include "../debug/Log.hpp" +#include "../macros.hpp" +#include "HookSystemManager.hpp" +#include "../Compositor.hpp" +#include "../protocols/XDGShell.hpp" +#include "./eventLoop/EventLoopManager.hpp" +#include "../config/ConfigValue.hpp" + +using namespace Hyprutils::OS; + +static constexpr auto TIMER_TIMEOUT = std::chrono::milliseconds(1500); + +CANRManager::CANRManager() { + if (!NFsUtils::executableExistsInPath("hyprland-dialog")) { + Debug::log(ERR, "hyprland-dialog missing from PATH, cannot start ANRManager"); + return; + } + + m_timer = makeShared(TIMER_TIMEOUT, [this](SP self, void* data) { onTick(); }, this); + g_pEventLoopManager->addTimer(m_timer); + + m_active = true; + + static auto P = g_pHookSystem->hookDynamic("openWindow", [this](void* self, SCallbackInfo& info, std::any data) { + auto window = std::any_cast(data); + + if (window->m_bIsX11) + return; + + for (const auto& w : g_pCompositor->m_vWindows) { + if (w->m_bIsX11 || w == window || !w->m_pXDGSurface) + continue; + + if (w->m_pXDGSurface->owner == window->m_pXDGSurface->owner) + return; + } + + m_data[window->m_pXDGSurface->owner] = makeShared(); + }); + + m_timer->updateTimeout(TIMER_TIMEOUT); +} + +void CANRManager::onTick() { + std::erase_if(m_data, [](const auto& e) { return e.first.expired(); }); + + static auto PENABLEANR = CConfigValue("misc:enable_anr_dialog"); + + if (!*PENABLEANR) { + m_timer->updateTimeout(TIMER_TIMEOUT * 10); + return; + } + + for (auto& [wmBase, data] : m_data) { + PHLWINDOW firstWindow; + int count = 0; + for (const auto& w : g_pCompositor->m_vWindows) { + if (!w->m_bIsMapped || w->m_bIsX11 || !w->m_pXDGSurface) + continue; + + if (w->m_pXDGSurface->owner != wmBase) + continue; + + count++; + if (!firstWindow) + firstWindow = w; + } + + if (count == 0) + continue; + + if (data->missedResponses > 0) { + if (!data->isThreadRunning() && !data->dialogThreadSaidWait) { + pid_t pid = 0; + wl_client_get_credentials(wmBase->client(), &pid, nullptr, nullptr); + data->runDialog("Application Not Responding", firstWindow->m_szTitle, firstWindow->m_szClass, pid); + + for (const auto& w : g_pCompositor->m_vWindows) { + if (!w->m_bIsMapped || w->m_bIsX11 || !w->m_pXDGSurface) + continue; + + if (w->m_pXDGSurface->owner != wmBase) + continue; + + *w->m_notRespondingTint = 0.2F; + } + } + } else if (data->isThreadRunning()) + data->killDialog(); + + if (data->missedResponses == 0) + data->dialogThreadSaidWait = false; + + data->missedResponses++; + + wmBase->ping(); + } + + m_timer->updateTimeout(TIMER_TIMEOUT); +} + +void CANRManager::onResponse(SP wmBase) { + if (!m_data.contains(wmBase)) + return; + + auto& data = m_data.at(wmBase); + data->missedResponses = 0; + if (data->isThreadRunning()) + data->killDialog(); +} + +void CANRManager::SANRData::runDialog(const std::string& title, const std::string& appName, const std::string appClass, pid_t dialogWmPID) { + if (!dialogThreadExited) + killDialog(); + + // dangerous: might lock if the above failed!! + if (dialogThread.joinable()) + dialogThread.join(); + + dialogThreadExited = false; + dialogThreadSaidWait = false; + dialogThread = std::thread([title, appName, appClass, dialogWmPID, this]() { + SP proc = + makeShared("hyprland-dialog", + std::vector{"--title", title, "--text", + std::format("Application {} with class of {} is not responding.\nWhat do you want to do with it?", appName, appClass), + "--buttons", "terminate;wait"}); + + dialogProc = proc; + proc->runSync(); + + dialogThreadExited = true; + + if (proc->stdOut().empty()) + return; + + if (proc->stdOut().starts_with("terminate")) + kill(dialogWmPID, SIGKILL); + if (proc->stdOut().starts_with("wait")) + dialogThreadSaidWait = true; + }); +} + +bool CANRManager::SANRData::isThreadRunning() { + if (dialogThread.native_handle() == 0) + return false; + if (dialogThreadExited) + return false; + return pthread_kill(dialogThread.native_handle(), 0) != ESRCH; +} + +void CANRManager::SANRData::killDialog() const { + if (!dialogProc) + return; + + kill(dialogProc->pid(), SIGKILL); +} + +CANRManager::SANRData::~SANRData() { + if (dialogThread.joinable()) { + killDialog(); + // dangerous: might lock if the above failed!! + dialogThread.join(); + } +} + +bool CANRManager::isNotResponding(SP wmBase) { + if (!m_data.contains(wmBase)) + return false; + return m_data[wmBase]->missedResponses > 1; +} diff --git a/src/managers/ANRManager.hpp b/src/managers/ANRManager.hpp new file mode 100644 index 00000000..7d67e872 --- /dev/null +++ b/src/managers/ANRManager.hpp @@ -0,0 +1,46 @@ +#pragma once + +#include "../helpers/memory/Memory.hpp" +#include "../desktop/DesktopTypes.hpp" +#include +#include +#include +#include +#include "./eventLoop/EventLoopTimer.hpp" +#include "../helpers/signal/Signal.hpp" +#include +#include + +class CXDGWMBase; + +class CANRManager { + public: + CANRManager(); + + void onResponse(SP wmBase); + bool isNotResponding(SP wmBase); + + private: + bool m_active = false; + SP m_timer; + + void onTick(); + + struct SANRData { + ~SANRData(); + + int missedResponses = 0; + std::thread dialogThread; + SP dialogProc; + std::atomic dialogThreadExited = false; + std::atomic dialogThreadSaidWait = false; + + void runDialog(const std::string& title, const std::string& appName, const std::string appClass, pid_t dialogWmPID); + bool isThreadRunning(); + void killDialog() const; + }; + + std::map, SP> m_data; +}; + +inline UP g_pANRManager; \ No newline at end of file diff --git a/src/protocols/XDGShell.cpp b/src/protocols/XDGShell.cpp index f5d1a8fa..9424a9d6 100644 --- a/src/protocols/XDGShell.cpp +++ b/src/protocols/XDGShell.cpp @@ -3,6 +3,7 @@ #include #include "../Compositor.hpp" #include "../managers/SeatManager.hpp" +#include "../managers/ANRManager.hpp" #include "../helpers/Monitor.hpp" #include "core/Seat.hpp" #include "core/Compositor.hpp" @@ -740,6 +741,11 @@ CXDGWMBase::CXDGWMBase(SP resource_) : resource(resource_) { LOGM(LOG, "New xdg_surface at {:x}", (uintptr_t)RESOURCE.get()); }); + + resource->setPong([this](CXdgWmBase* r, uint32_t serial) { + g_pANRManager->onResponse(self.lock()); + events.pong.emit(); + }); } bool CXDGWMBase::good() { @@ -750,6 +756,10 @@ wl_client* CXDGWMBase::client() { return pClient; } +void CXDGWMBase::ping() { + resource->sendPing(1337); +} + CXDGShellProtocol::CXDGShellProtocol(const wl_interface* iface, const int& ver, const std::string& name) : IWaylandProtocol(iface, ver, name) { grab = makeShared(); grab->keyboard = true; diff --git a/src/protocols/XDGShell.hpp b/src/protocols/XDGShell.hpp index 4c2b8100..b46e0236 100644 --- a/src/protocols/XDGShell.hpp +++ b/src/protocols/XDGShell.hpp @@ -241,12 +241,17 @@ class CXDGWMBase { bool good(); wl_client* client(); + void ping(); std::vector> positioners; std::vector> surfaces; WP self; + struct { + CSignal pong; + } events; + private: SP resource; wl_client* pClient = nullptr; diff --git a/src/render/OpenGL.cpp b/src/render/OpenGL.cpp index 3b641c36..1a296b65 100644 --- a/src/render/OpenGL.cpp +++ b/src/render/OpenGL.cpp @@ -1396,12 +1396,18 @@ void CHyprOpenGLImpl::renderTextureInternalWithDamage(SP tex, const CB glUniform1f(shader->roundingPower, roundingPower); if (allowDim && m_RenderData.currentWindow) { - glUniform1i(shader->applyTint, 1); - const auto DIM = m_RenderData.currentWindow->m_fDimPercent->value(); - glUniform3f(shader->tint, 1.f - DIM, 1.f - DIM, 1.f - DIM); - } else { + if (m_RenderData.currentWindow->m_notRespondingTint->value() > 0) { + const auto DIM = m_RenderData.currentWindow->m_notRespondingTint->value(); + glUniform1i(shader->applyTint, 1); + glUniform3f(shader->tint, 1.f - DIM, 1.f - DIM, 1.f - DIM); + } else if (m_RenderData.currentWindow->m_fDimPercent->value() > 0) { + glUniform1i(shader->applyTint, 1); + const auto DIM = m_RenderData.currentWindow->m_fDimPercent->value(); + glUniform3f(shader->tint, 1.f - DIM, 1.f - DIM, 1.f - DIM); + } else + glUniform1i(shader->applyTint, 0); + } else glUniform1i(shader->applyTint, 0); - } } const float verts[] = { diff --git a/src/render/Renderer.cpp b/src/render/Renderer.cpp index b61f1c3e..f01a0d12 100644 --- a/src/render/Renderer.cpp +++ b/src/render/Renderer.cpp @@ -473,6 +473,12 @@ void CHyprRenderer::renderWindow(PHLWINDOW pWindow, PHLMONITOR pMonitor, timespe if (ignorePosition) { renderdata.pos.x = pMonitor->vecPosition.x; renderdata.pos.y = pMonitor->vecPosition.y; + } else { + const bool ANR = pWindow->isNotResponding(); + if (ANR && pWindow->m_notRespondingTint->goal() != 0.2F) + *pWindow->m_notRespondingTint = 0.2F; + else if (!ANR && pWindow->m_notRespondingTint->goal() != 0.F) + *pWindow->m_notRespondingTint = 0.F; } if (standalone) From 3c1a2e9fcae6575e1f17627047c93d6e9fcc8634 Mon Sep 17 00:00:00 2001 From: Vaxry Date: Tue, 18 Feb 2025 15:18:34 +0000 Subject: [PATCH 1012/2181] config/descriptions: add enable_anr_dialog --- src/config/ConfigDescriptions.hpp | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/config/ConfigDescriptions.hpp b/src/config/ConfigDescriptions.hpp index 1283050d..4e591fa8 100644 --- a/src/config/ConfigDescriptions.hpp +++ b/src/config/ConfigDescriptions.hpp @@ -1187,6 +1187,12 @@ inline static const std::vector CONFIG_OPTIONS = { .type = CONFIG_OPTION_INT, .data = SConfigOptionDescription::SRangeData{1000, 0, 5000}, }, + SConfigOptionDescription{ + .value = "misc:enable_anr_dialog", + .description = "whether to enable the ANR (app not responding) dialog when your apps hang", + .type = CONFIG_OPTION_BOOL, + .data = SConfigOptionDescription::SBoolData{true}, + }, /* * binds: From 0137a5f6cdd24d5a10f813572791f1e641221a5b Mon Sep 17 00:00:00 2001 From: Vaxry Date: Tue, 18 Feb 2025 15:20:00 +0000 Subject: [PATCH 1013/2181] anr: capitalize options --- src/managers/ANRManager.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/managers/ANRManager.cpp b/src/managers/ANRManager.cpp index e2b276ee..af1cb93a 100644 --- a/src/managers/ANRManager.cpp +++ b/src/managers/ANRManager.cpp @@ -126,7 +126,7 @@ void CANRManager::SANRData::runDialog(const std::string& title, const std::strin makeShared("hyprland-dialog", std::vector{"--title", title, "--text", std::format("Application {} with class of {} is not responding.\nWhat do you want to do with it?", appName, appClass), - "--buttons", "terminate;wait"}); + "--buttons", "Terminate;Wait"}); dialogProc = proc; proc->runSync(); @@ -136,9 +136,9 @@ void CANRManager::SANRData::runDialog(const std::string& title, const std::strin if (proc->stdOut().empty()) return; - if (proc->stdOut().starts_with("terminate")) + if (proc->stdOut().starts_with("Terminate")) kill(dialogWmPID, SIGKILL); - if (proc->stdOut().starts_with("wait")) + if (proc->stdOut().starts_with("Wait")) dialogThreadSaidWait = true; }); } From 6d25ef09cd6a33bcd589bd0f1e88e86fcff2dc67 Mon Sep 17 00:00:00 2001 From: nyx Date: Wed, 19 Feb 2025 10:29:39 -0500 Subject: [PATCH 1014/2181] xwayland: add INCR support for clipboard transfers (#9434) add INCR protocol support for large transfers fix write handling for partial transfers fix an issue where wayland windows could die from a paste from an xwayland window --- src/xwayland/XWM.cpp | 29 ++++++++++++++++++++++++----- 1 file changed, 24 insertions(+), 5 deletions(-) diff --git a/src/xwayland/XWM.cpp b/src/xwayland/XWM.cpp index a4e3289b..0899261a 100644 --- a/src/xwayland/XWM.cpp +++ b/src/xwayland/XWM.cpp @@ -589,9 +589,18 @@ void CXWM::handleSelectionNotify(xcb_selection_notify_event_t* e) { } bool CXWM::handleSelectionPropertyNotify(xcb_property_notify_event_t* e) { - // Debug::log(LOG, "[xwm] Selection property notify for {} target {}", e->atom, e->window); + if (e->state != XCB_PROPERTY_DELETE) + return false; - // Debug::log(ERR, "[xwm] FIXME: CXWM::handleSelectionPropertyNotify stub"); + auto it = std::ranges::find_if(clipboard.transfers, [e](const auto& t) { return t->incomingWindow == e->window; }); + if (it != clipboard.transfers.end()) { + if (!(*it)->getIncomingSelectionProp(true)) { + clipboard.transfers.erase(it); + return false; + } + getTransferData(clipboard); + return true; + } return false; } @@ -1205,8 +1214,10 @@ void CXWM::getTransferData(SXSelection& sel) { } if (transfer->propertyReply->type == HYPRATOMS["INCR"]) { - Debug::log(ERR, "[xwm] Transfer is INCR, which we don't support :("); - sel.transfers.erase(it); + transfer->incremental = true; + transfer->propertyStart = 0; + free(transfer->propertyReply); + transfer->propertyReply = nullptr; return; } @@ -1426,6 +1437,8 @@ int SXSelection::onWrite() { ssize_t len = write(transfer->wlFD.get(), property + transfer->propertyStart, remainder); if (len == -1) { + if (errno == EAGAIN) + return 1; Debug::log(ERR, "[xwm] write died in transfer get"); transfers.erase(it); return 0; @@ -1436,7 +1449,13 @@ int SXSelection::onWrite() { Debug::log(LOG, "[xwm] wl client read partially: len {}", len); } else { Debug::log(LOG, "[xwm] cb transfer to wl client complete, read {} bytes", len); - transfers.erase(it); + if (!transfer->incremental) { + transfers.erase(it); + } else { + free(transfer->propertyReply); + transfer->propertyReply = nullptr; + transfer->propertyStart = 0; + } } return 1; From fa246cb6ed5f486aad27c11dd46b3a26768a15d1 Mon Sep 17 00:00:00 2001 From: Mihai Fufezan Date: Thu, 20 Feb 2025 14:56:17 +0200 Subject: [PATCH 1015/2181] flake.lock: update hyprutils and aquamarine --- flake.lock | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/flake.lock b/flake.lock index 38f48983..76eee761 100644 --- a/flake.lock +++ b/flake.lock @@ -16,11 +16,11 @@ ] }, "locked": { - "lastModified": 1739103745, - "narHash": "sha256-c53dcRaw0F4Os9WD05HwIRs9kTDZw4Mxe1XK4edEALo=", + "lastModified": 1739298463, + "narHash": "sha256-oAFv9jKwwA7d7384d2LeywDSgwhvb3ZnrwbfoWPhXsI=", "owner": "hyprwm", "repo": "aquamarine", - "rev": "a3dda0d10ce9aa1d1dfb7a6c139ea8c2872c74bd", + "rev": "f239e5aadd6d23c48e085c2de3397e2058e54d16", "type": "github" }, "original": { @@ -238,11 +238,11 @@ ] }, "locked": { - "lastModified": 1739048933, - "narHash": "sha256-ck6MaoYvISBQKqZR+HcxXnx0wOhyCauxfVMaV5zhJxQ=", + "lastModified": 1739891528, + "narHash": "sha256-h8HOCZ/rw2Buzku+GKF77VXxrGjCSOQkLhptiEKMYg0=", "owner": "hyprwm", "repo": "hyprutils", - "rev": "e4e018a2ca6f5a9c33511973454199e1c7c85499", + "rev": "61a5382f4b1ab578064d470b1b3d3f0df396b8ba", "type": "github" }, "original": { From 2cfa5d2408cd3e213aa0c87076ce9ada0dc08e20 Mon Sep 17 00:00:00 2001 From: Aaron Tulino <13600347+aaronjamt@users.noreply.github.com> Date: Fri, 21 Feb 2025 07:20:11 -0700 Subject: [PATCH 1016/2181] hyprctl: Add IPC support for Hyprsunset (#9315) * Add IPC support for Hyprsunset * clang-format * Add documentation --- hyprctl/Strings.hpp | 11 +++++++++++ hyprctl/main.cpp | 8 ++++++++ 2 files changed, 19 insertions(+) diff --git a/hyprctl/Strings.hpp b/hyprctl/Strings.hpp index f77626a5..c70ca737 100644 --- a/hyprctl/Strings.hpp +++ b/hyprctl/Strings.hpp @@ -22,6 +22,7 @@ commands: getoption
({})", binaryName, binaryPath)); } else if (pid >= 0) { if (type == PERMISSION_TYPE_PLUGIN) { const auto LOOKUP = binaryNameForPid(pid); - description = std::format("An application {} is {}:
{}", LOOKUP.value_or("Unknown"), permissionToHumanString(type), binaryPath); + description = std::format(std::runtime_format(permissionToHumanString(type)), LOOKUP.value_or("Unknown"), binaryPath); } else { const auto LOOKUP = binaryNameForPid(pid); - description = std::format("An application {} ({}) is {}.", LOOKUP.value_or("Unknown"), binaryPath, permissionToHumanString(type)); + description = std::format(std::runtime_format(permissionToHumanString(type)), LOOKUP.value_or("Unknown"), binaryPath); } } else - description = std::format("An application is {}:
{}", permissionToHumanString(type), binaryPath); - - description += "

Do you want to allow this?"; + description = std::format(std::runtime_format(permissionToHumanString(type)), binaryPath); std::vector options; diff --git a/src/managers/permissions/DynamicPermissionManager.hpp b/src/managers/permissions/DynamicPermissionManager.hpp index f8cfe3ad..a61f256e 100644 --- a/src/managers/permissions/DynamicPermissionManager.hpp +++ b/src/managers/permissions/DynamicPermissionManager.hpp @@ -17,6 +17,7 @@ enum eDynamicPermissionType : uint8_t { PERMISSION_TYPE_UNKNOWN = 0, PERMISSION_TYPE_SCREENCOPY, PERMISSION_TYPE_PLUGIN, + PERMISSION_TYPE_KEYBOARD, }; enum eDynamicPermissionRuleSource : uint8_t { From d9c8a378118d954932eb9906b07150ccd9a3a434 Mon Sep 17 00:00:00 2001 From: Vaxry Date: Sun, 18 May 2025 19:34:14 +0200 Subject: [PATCH 1308/2181] input: always allow focus to permission popups --- src/Compositor.cpp | 31 ++++++++++++++----- src/desktop/Window.cpp | 4 +++ src/desktop/Window.hpp | 2 ++ src/helpers/AsyncDialogBox.cpp | 19 +++++++++--- src/helpers/AsyncDialogBox.hpp | 6 +++- src/managers/input/InputManager.cpp | 9 ++++-- .../permissions/DynamicPermissionManager.cpp | 3 +- 7 files changed, 58 insertions(+), 16 deletions(-) diff --git a/src/Compositor.cpp b/src/Compositor.cpp index 973cb26b..c6593923 100644 --- a/src/Compositor.cpp +++ b/src/Compositor.cpp @@ -870,10 +870,14 @@ PHLWINDOW CCompositor::vectorToWindowUnified(const Vector2D& pos, uint8_t proper static auto PBORDERGRABEXTEND = CConfigValue("general:extend_border_grab_area"); static auto PSPECIALFALLTHRU = CConfigValue("input:special_fallthrough"); const auto BORDER_GRAB_AREA = *PRESIZEONBORDER ? *PBORDERSIZE + *PBORDERGRABEXTEND : 0; + const bool ONLY_PRIORITY = properties & FOCUS_PRIORITY; // pinned windows on top of floating regardless if (properties & ALLOW_FLOATING) { for (auto const& w : m_windows | std::views::reverse) { + if (ONLY_PRIORITY && !w->priorityFocus()) + continue; + if (w->m_isFloating && w->m_isMapped && !w->isHidden() && !w->m_X11ShouldntFocus && w->m_pinned && !w->m_windowData.noFocus.valueOrDefault() && w != pIgnoreWindow) { const auto BB = w->getWindowBoxUnified(properties); CBox box = BB.copy().expand(!w->isX11OverrideRedirect() ? BORDER_GRAB_AREA : 0); @@ -898,6 +902,9 @@ PHLWINDOW CCompositor::vectorToWindowUnified(const Vector2D& pos, uint8_t proper if (!w->m_workspace) continue; + if (ONLY_PRIORITY && !w->priorityFocus()) + continue; + const auto PWINDOWMONITOR = w->m_monitor.lock(); // to avoid focusing windows behind special workspaces from other monitors @@ -950,7 +957,7 @@ PHLWINDOW CCompositor::vectorToWindowUnified(const Vector2D& pos, uint8_t proper const WORKSPACEID WSPID = special ? PMONITOR->activeSpecialWorkspaceID() : PMONITOR->activeWorkspaceID(); const auto PWORKSPACE = getWorkspaceByID(WSPID); - if (PWORKSPACE->m_hasFullscreenWindow && !(properties & SKIP_FULLSCREEN_PRIORITY)) + if (PWORKSPACE->m_hasFullscreenWindow && !(properties & SKIP_FULLSCREEN_PRIORITY) && !ONLY_PRIORITY) return PWORKSPACE->getFullscreenWindow(); auto found = floating(false); @@ -959,6 +966,9 @@ PHLWINDOW CCompositor::vectorToWindowUnified(const Vector2D& pos, uint8_t proper // for windows, we need to check their extensions too, first. for (auto const& w : m_windows) { + if (ONLY_PRIORITY && !w->priorityFocus()) + continue; + if (special != w->onSpecialWorkspace()) continue; @@ -973,6 +983,9 @@ PHLWINDOW CCompositor::vectorToWindowUnified(const Vector2D& pos, uint8_t proper } for (auto const& w : m_windows) { + if (ONLY_PRIORITY && !w->priorityFocus()) + continue; + if (special != w->onSpecialWorkspace()) continue; @@ -1083,14 +1096,16 @@ void CCompositor::focusWindow(PHLWINDOW pWindow, SP pSurface static auto PFOLLOWMOUSE = CConfigValue("input:follow_mouse"); static auto PSPECIALFALLTHROUGH = CConfigValue("input:special_fallthrough"); - if (g_pSessionLockManager->isSessionLocked()) { - Debug::log(LOG, "Refusing a keyboard focus to a window because of a sessionlock"); - return; - } + if (!pWindow || !pWindow->priorityFocus()) { + if (g_pSessionLockManager->isSessionLocked()) { + Debug::log(LOG, "Refusing a keyboard focus to a window because of a sessionlock"); + return; + } - if (!g_pInputManager->m_exclusiveLSes.empty()) { - Debug::log(LOG, "Refusing a keyboard focus to a window because of an exclusive ls"); - return; + if (!g_pInputManager->m_exclusiveLSes.empty()) { + Debug::log(LOG, "Refusing a keyboard focus to a window because of an exclusive ls"); + return; + } } if (pWindow && pWindow->m_isX11 && pWindow->isX11OverrideRedirect() && !pWindow->m_xwaylandSurface->wantsFocus()) diff --git a/src/desktop/Window.cpp b/src/desktop/Window.cpp index 7ef54da0..9f69e364 100644 --- a/src/desktop/Window.cpp +++ b/src/desktop/Window.cpp @@ -1836,3 +1836,7 @@ PHLWINDOW CWindow::parent() { return m_xdgSurface->m_toplevel->m_parent->m_window.lock(); } + +bool CWindow::priorityFocus() { + return !m_isX11 && CAsyncDialogBox::isPriorityDialogBox(getPID()); +} diff --git a/src/desktop/Window.hpp b/src/desktop/Window.hpp index 47d28db2..0d06b69c 100644 --- a/src/desktop/Window.hpp +++ b/src/desktop/Window.hpp @@ -51,6 +51,7 @@ enum eGetWindowProperties : uint8_t { ALLOW_FLOATING = 1 << 4, USE_PROP_TILED = 1 << 5, SKIP_FULLSCREEN_PRIORITY = 1 << 6, + FOCUS_PRIORITY = 1 << 7, }; enum eSuppressEvents : uint8_t { @@ -408,6 +409,7 @@ class CWindow { std::optional xdgTag(); std::optional xdgDescription(); PHLWINDOW parent(); + bool priorityFocus(); CBox getWindowMainSurfaceBox() const { return {m_realPosition->value().x, m_realPosition->value().y, m_realSize->value().x, m_realSize->value().y}; diff --git a/src/helpers/AsyncDialogBox.cpp b/src/helpers/AsyncDialogBox.cpp index 42dac469..697d61ba 100644 --- a/src/helpers/AsyncDialogBox.cpp +++ b/src/helpers/AsyncDialogBox.cpp @@ -7,7 +7,7 @@ using namespace Hyprutils::OS; -static std::vector asyncDialogBoxes; +static std::vector>> asyncDialogBoxes; // SP CAsyncDialogBox::create(const std::string& title, const std::string& description, std::vector buttons) { @@ -24,7 +24,18 @@ SP CAsyncDialogBox::create(const std::string& title, const std: } bool CAsyncDialogBox::isAsyncDialogBox(pid_t pid) { - return std::ranges::contains(asyncDialogBoxes, pid); + return std::ranges::find_if(asyncDialogBoxes, [pid](const auto& e) { return e.first == pid; }) != asyncDialogBoxes.end(); +} + +bool CAsyncDialogBox::isPriorityDialogBox(pid_t pid) { + for (const auto& [p, db] : asyncDialogBoxes) { + if (p != pid) + continue; + + return db && db->m_priority; + } + + return false; } CAsyncDialogBox::CAsyncDialogBox(const std::string& title, const std::string& description, std::vector buttons) : @@ -68,7 +79,7 @@ void CAsyncDialogBox::onWrite(int fd, uint32_t mask) { Debug::log(LOG, "CAsyncDialogBox: dialog {:x} hung up, closed."); m_promiseResolver->resolve(m_stdout); - std::erase(asyncDialogBoxes, m_dialogPid); + std::erase_if(asyncDialogBoxes, [this](const auto& e) { return e.first == m_dialogPid; }); wl_event_source_remove(m_readEventSource); m_selfReference.reset(); @@ -112,7 +123,7 @@ SP> CAsyncDialogBox::open() { } m_dialogPid = proc.pid(); - asyncDialogBoxes.emplace_back(m_dialogPid); + asyncDialogBoxes.emplace_back(std::make_pair<>(m_dialogPid, m_selfWeakReference)); // close the write fd, only the dialog owns it now close(outPipe[1]); diff --git a/src/helpers/AsyncDialogBox.hpp b/src/helpers/AsyncDialogBox.hpp index 4018a857..0ee0144e 100644 --- a/src/helpers/AsyncDialogBox.hpp +++ b/src/helpers/AsyncDialogBox.hpp @@ -16,6 +16,7 @@ class CAsyncDialogBox { public: static SP create(const std::string& title, const std::string& description, std::vector buttons); static bool isAsyncDialogBox(pid_t pid); + static bool isPriorityDialogBox(pid_t pid); CAsyncDialogBox(const CAsyncDialogBox&) = delete; CAsyncDialogBox(CAsyncDialogBox&&) = delete; @@ -26,7 +27,10 @@ class CAsyncDialogBox { void kill(); bool isRunning() const; - void onWrite(int fd, uint32_t mask); + // focus priority, only permission popups + bool m_priority = false; + + void onWrite(int fd, uint32_t mask); private: CAsyncDialogBox(const std::string& title, const std::string& description, std::vector buttons); diff --git a/src/managers/input/InputManager.cpp b/src/managers/input/InputManager.cpp index f9f36cf2..2d50dbcf 100644 --- a/src/managers/input/InputManager.cpp +++ b/src/managers/input/InputManager.cpp @@ -250,7 +250,12 @@ void CInputManager::mouseMoveUnified(uint32_t time, bool refocus, bool mouse) { if (PMONITOR != g_pCompositor->m_lastMonitor && (*PMOUSEFOCUSMON || refocus) && m_forcedFocus.expired()) g_pCompositor->setActiveMonitor(PMONITOR); - if (g_pSessionLockManager->isSessionLocked()) { + // check for windows that have focus priority like our permission popups + pFoundWindow = g_pCompositor->vectorToWindowUnified(mouseCoords, FOCUS_PRIORITY); + if (pFoundWindow) + foundSurface = g_pCompositor->vectorWindowToSurface(mouseCoords, pFoundWindow, surfaceCoords); + + if (!foundSurface && g_pSessionLockManager->isSessionLocked()) { // set keyboard focus on session lock surface regardless of layers const auto PSESSIONLOCKSURFACE = g_pSessionLockManager->getSessionLockSurfaceForMonitor(PMONITOR->m_id); @@ -288,7 +293,7 @@ void CInputManager::mouseMoveUnified(uint32_t time, bool refocus, bool mouse) { if (!forcedFocus) forcedFocus = g_pCompositor->getForceFocus(); - if (forcedFocus) { + if (forcedFocus && !foundSurface) { pFoundWindow = forcedFocus; surfacePos = pFoundWindow->m_realPosition->value(); foundSurface = pFoundWindow->m_wlSurface->resource(); diff --git a/src/managers/permissions/DynamicPermissionManager.cpp b/src/managers/permissions/DynamicPermissionManager.cpp index dd1fd4cf..c015adfe 100644 --- a/src/managers/permissions/DynamicPermissionManager.cpp +++ b/src/managers/permissions/DynamicPermissionManager.cpp @@ -296,7 +296,8 @@ void CDynamicPermissionManager::askForPermission(wl_client* client, const std::s } else options = {"Deny", "Allow"}; - rule->m_dialogBox = CAsyncDialogBox::create("Permission request", description, options); + rule->m_dialogBox = CAsyncDialogBox::create("Permission request", description, options); + rule->m_dialogBox->m_priority = true; if (!rule->m_dialogBox) { Debug::log(ERR, "CDynamicPermissionManager::askForPermission: hyprland-qtutils likely missing, cannot ask! Disabling permission control..."); From eb3b38d40baca5c05ddbc1507b3d3f02a0ccb164 Mon Sep 17 00:00:00 2001 From: Vaxry Date: Mon, 19 May 2025 01:27:30 +0200 Subject: [PATCH 1309/2181] eventLoop: fixup event source callbacks --- src/managers/eventLoop/EventLoopManager.cpp | 20 ++++++++++++-------- 1 file changed, 12 insertions(+), 8 deletions(-) diff --git a/src/managers/eventLoop/EventLoopManager.cpp b/src/managers/eventLoop/EventLoopManager.cpp index 338b75e3..6233a2d0 100644 --- a/src/managers/eventLoop/EventLoopManager.cpp +++ b/src/managers/eventLoop/EventLoopManager.cpp @@ -70,16 +70,20 @@ static int handleWaiterFD(int fd, uint32_t mask, void* data) { void CEventLoopManager::onFdReadable(SReadableWaiter* waiter) { auto it = std::ranges::find_if(m_readableWaiters, [waiter](const UP& w) { return waiter == w.get() && w->fd == waiter->fd && w->source == waiter->source; }); - if (waiter->source) { - wl_event_source_remove(waiter->source); - waiter->source = nullptr; + // ??? + if (it == m_readableWaiters.end()) + return; + + UP taken = std::move(*it); + m_readableWaiters.erase(it); + + if (taken->source) { + wl_event_source_remove(taken->source); + taken->source = nullptr; } - if (waiter->fn) - waiter->fn(); - - if (it != m_readableWaiters.end()) - m_readableWaiters.erase(it); + if (taken->fn) + taken->fn(); } void CEventLoopManager::enterLoop() { From b90910c0dcc6db9d7529d02190b0a19f69cb46e3 Mon Sep 17 00:00:00 2001 From: zacoons <73414084+zacoons@users.noreply.github.com> Date: Thu, 22 May 2025 01:41:40 +1000 Subject: [PATCH 1310/2181] renderer: add wrapping options to renderTexture method (#10497) --- src/render/OpenGL.cpp | 11 ++++++----- src/render/OpenGL.hpp | 5 +++-- 2 files changed, 9 insertions(+), 7 deletions(-) diff --git a/src/render/OpenGL.cpp b/src/render/OpenGL.cpp index 20862a7a..855da879 100644 --- a/src/render/OpenGL.cpp +++ b/src/render/OpenGL.cpp @@ -1409,10 +1409,11 @@ void CHyprOpenGLImpl::renderRectWithDamage(const CBox& box, const CHyprColor& co scissor(nullptr); } -void CHyprOpenGLImpl::renderTexture(SP tex, const CBox& box, float alpha, int round, float roundingPower, bool discardActive, bool allowCustomUV) { +void CHyprOpenGLImpl::renderTexture(SP tex, const CBox& box, float alpha, int round, float roundingPower, bool discardActive, bool allowCustomUV, GLenum wrapX, + GLenum wrapY) { RASSERT(m_renderData.pMonitor, "Tried to render texture without begin()!"); - renderTextureInternalWithDamage(tex, box, alpha, m_renderData.damage, round, roundingPower, discardActive, false, allowCustomUV, true); + renderTextureInternalWithDamage(tex, box, alpha, m_renderData.damage, round, roundingPower, discardActive, false, allowCustomUV, true, wrapX, wrapY); scissor(nullptr); } @@ -1477,7 +1478,7 @@ void CHyprOpenGLImpl::passCMUniforms(const SShader& shader, const SImageDescript } void CHyprOpenGLImpl::renderTextureInternalWithDamage(SP tex, const CBox& box, float alpha, const CRegion& damage, int round, float roundingPower, bool discardActive, - bool noAA, bool allowCustomUV, bool allowDim) { + bool noAA, bool allowCustomUV, bool allowDim, GLenum wrapX, GLenum wrapY) { RASSERT(m_renderData.pMonitor, "Tried to render texture without begin()!"); RASSERT((tex->m_texID > 0), "Attempted to draw nullptr texture!"); @@ -1541,8 +1542,8 @@ void CHyprOpenGLImpl::renderTextureInternalWithDamage(SP tex, const CB glActiveTexture(GL_TEXTURE0); glBindTexture(tex->m_target, tex->m_texID); - glTexParameteri(tex->m_target, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); - glTexParameteri(tex->m_target, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); + glTexParameteri(tex->m_target, GL_TEXTURE_WRAP_S, wrapX); + glTexParameteri(tex->m_target, GL_TEXTURE_WRAP_T, wrapY); if (m_renderData.useNearestNeighbor) { glTexParameteri(tex->m_target, GL_TEXTURE_MAG_FILTER, GL_NEAREST); diff --git a/src/render/OpenGL.hpp b/src/render/OpenGL.hpp index 09aff9da..fade4a9d 100644 --- a/src/render/OpenGL.hpp +++ b/src/render/OpenGL.hpp @@ -183,7 +183,8 @@ class CHyprOpenGLImpl { void renderRect(const CBox&, const CHyprColor&, int round = 0, float roundingPower = 2.0f); void renderRectWithBlur(const CBox&, const CHyprColor&, int round = 0, float roundingPower = 2.0f, float blurA = 1.f, bool xray = false); void renderRectWithDamage(const CBox&, const CHyprColor&, const CRegion& damage, int round = 0, float roundingPower = 2.0f); - void renderTexture(SP, const CBox&, float a, int round = 0, float roundingPower = 2.0f, bool discardActive = false, bool allowCustomUV = false); + void renderTexture(SP, const CBox&, float a, int round = 0, float roundingPower = 2.0f, bool discardActive = false, bool allowCustomUV = false, + GLenum wrapX = GL_CLAMP_TO_EDGE, GLenum wrapY = GL_CLAMP_TO_EDGE); void renderTextureWithDamage(SP, const CBox&, const CRegion& damage, float a, int round = 0, float roundingPower = 2.0f, bool discardActive = false, bool allowCustomUV = false); void renderTextureWithBlur(SP, const CBox&, float a, SP pSurface, int round = 0, float roundingPower = 2.0f, bool blockBlurOptimization = false, @@ -344,7 +345,7 @@ class CHyprOpenGLImpl { bool modifySDR = false); void passCMUniforms(const SShader&, const NColorManagement::SImageDescription& imageDescription); void renderTextureInternalWithDamage(SP, const CBox& box, float a, const CRegion& damage, int round = 0, float roundingPower = 2.0f, bool discardOpaque = false, - bool noAA = false, bool allowCustomUV = false, bool allowDim = false); + bool noAA = false, bool allowCustomUV = false, bool allowDim = false, GLenum wrapX = GL_CLAMP_TO_EDGE, GLenum wrapY = GL_CLAMP_TO_EDGE); void renderTexturePrimitive(SP tex, const CBox& box); void renderSplash(cairo_t* const, cairo_surface_t* const, double offset, const Vector2D& size); From 185c96849ef59da3e101116662d942dea16b468a Mon Sep 17 00:00:00 2001 From: darkwater Date: Wed, 21 May 2025 23:44:21 +0200 Subject: [PATCH 1311/2181] input: unhide cursor on tablet events after touch events (#10484) --- src/managers/input/Tablets.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/src/managers/input/Tablets.cpp b/src/managers/input/Tablets.cpp index 5b9ca378..b0fe7c64 100644 --- a/src/managers/input/Tablets.cpp +++ b/src/managers/input/Tablets.cpp @@ -134,6 +134,7 @@ void CInputManager::onTabletAxis(CTablet::SAxisEvent e) { } } + m_lastInputTouch = false; simulateMouseMovement(); refocusTablet(PTAB, PTOOL, true); m_lastCursorMovement.reset(); From 4f161da3d6a3eb16cffd8c7706e2b916c82c93a7 Mon Sep 17 00:00:00 2001 From: nezu <29180158+dumbasPL@users.noreply.github.com> Date: Thu, 22 May 2025 13:54:02 +0200 Subject: [PATCH 1312/2181] hyprpm: ignore pins when adding a package with a git rev (#10502) ref #10436 --- hyprpm/src/core/PluginManager.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/hyprpm/src/core/PluginManager.cpp b/hyprpm/src/core/PluginManager.cpp index 76f20110..90eba579 100644 --- a/hyprpm/src/core/PluginManager.cpp +++ b/hyprpm/src/core/PluginManager.cpp @@ -256,7 +256,7 @@ bool CPluginManager::addNewPluginRepo(const std::string& url, const std::string& progress.printMessageAbove(message); } - if (!pManifest->m_repository.commitPins.empty()) { + if (rev.empty() && !pManifest->m_repository.commitPins.empty()) { // check commit pins progress.printMessageAbove(infoString("Manifest has {} pins, checking", pManifest->m_repository.commitPins.size())); From bd4733a0ff2b89fd3f22dc6ec9ff00e070753662 Mon Sep 17 00:00:00 2001 From: Mihai Fufezan Date: Thu, 22 May 2025 18:02:18 +0300 Subject: [PATCH 1313/2181] flake.lock: update nix/overlays: remove wayland-protocols overlay. PR landed in master a while ago --- flake.lock | 24 ++++++++++++------------ nix/overlays.nix | 13 ------------- 2 files changed, 12 insertions(+), 25 deletions(-) diff --git a/flake.lock b/flake.lock index 1be8e6d4..de57aab4 100644 --- a/flake.lock +++ b/flake.lock @@ -16,11 +16,11 @@ ] }, "locked": { - "lastModified": 1745357003, - "narHash": "sha256-jYwzQkv1r7HN/4qrAuKp+NR4YYNp2xDrOX5O9YVqkWo=", + "lastModified": 1747864449, + "narHash": "sha256-PIjVAWghZhr3L0EFM2UObhX84UQxIACbON0IC0zzSKA=", "owner": "hyprwm", "repo": "aquamarine", - "rev": "a19cf76ee1a15c1c12083fa372747ce46387289f", + "rev": "389372c5f4dc1ac0e7645ed29a35fd6d71672ef5", "type": "github" }, "original": { @@ -215,11 +215,11 @@ ] }, "locked": { - "lastModified": 1746655412, - "narHash": "sha256-kVQ0bHVtX6baYxRWWIh4u3LNJZb9Zcm2xBeDPOGz5BY=", + "lastModified": 1747484975, + "narHash": "sha256-+LAQ81HBwG0lwshHlWe0kfWg4KcChIPpnwtnwqmnoEU=", "owner": "hyprwm", "repo": "hyprlang", - "rev": "557241780c179cf7ef224df392f8e67dab6cef83", + "rev": "163c83b3db48a17c113729c220a60b94596c9291", "type": "github" }, "original": { @@ -261,11 +261,11 @@ ] }, "locked": { - "lastModified": 1739870480, - "narHash": "sha256-SiDN5BGxa/1hAsqhgJsS03C3t2QrLgBT8u+ENJ0Qzwc=", + "lastModified": 1747584298, + "narHash": "sha256-PH9qZqWLHvSBQiUnA0NzAyQA3tu2no2z8kz0ZeHWj4w=", "owner": "hyprwm", "repo": "hyprwayland-scanner", - "rev": "206367a08dc5ac4ba7ad31bdca391d098082e64b", + "rev": "e511882b9c2e1d7a75d45d8fddd2160daeafcbc3", "type": "github" }, "original": { @@ -276,11 +276,11 @@ }, "nixpkgs": { "locked": { - "lastModified": 1747327360, - "narHash": "sha256-LSmTbiq/nqZR9B2t4MRnWG7cb0KVNU70dB7RT4+wYK4=", + "lastModified": 1747744144, + "narHash": "sha256-W7lqHp0qZiENCDwUZ5EX/lNhxjMdNapFnbErcbnP11Q=", "owner": "NixOS", "repo": "nixpkgs", - "rev": "e06158e58f3adee28b139e9c2bcfcc41f8625b46", + "rev": "2795c506fe8fb7b03c36ccb51f75b6df0ab2553f", "type": "github" }, "original": { diff --git a/nix/overlays.nix b/nix/overlays.nix index 687a49d4..6085bf80 100644 --- a/nix/overlays.nix +++ b/nix/overlays.nix @@ -29,7 +29,6 @@ in { inputs.hyprutils.overlays.default inputs.hyprwayland-scanner.overlays.default self.overlays.udis86 - self.overlays.wayland-protocols # Hyprland packages themselves (final: _prev: let @@ -96,16 +95,4 @@ in { patches = []; }); }; - - # TODO: remove when https://github.com/NixOS/nixpkgs/pull/397497 lands in master - wayland-protocols = final: prev: { - wayland-protocols = prev.wayland-protocols.overrideAttrs (self: super: { - version = "1.43"; - - src = final.fetchurl { - url = "https://gitlab.freedesktop.org/wayland/${self.pname}/-/releases/${self.version}/downloads/${self.pname}-${self.version}.tar.xz"; - hash = "sha256-ujw0Jd0nxXtSkek9upe+EkeWAeALyrJNJkcZSMtkNlM="; - }; - }); - }; } From 81cd526f923f4a9074bbfef59b4c7e9f3350c349 Mon Sep 17 00:00:00 2001 From: Virt <41426325+VirtCode@users.noreply.github.com> Date: Fri, 23 May 2025 23:41:35 +0200 Subject: [PATCH 1314/2181] cursor: fix screencopy cursor pos and duplicate shape with sw cursors (#10519) * cursor: account for hotspot with overridePos * cursor: don't draw cursor on screencopy if using sw anyways --- src/managers/PointerManager.cpp | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/src/managers/PointerManager.cpp b/src/managers/PointerManager.cpp index 7bd66c5d..f42fd686 100644 --- a/src/managers/PointerManager.cpp +++ b/src/managers/PointerManager.cpp @@ -603,10 +603,17 @@ void CPointerManager::renderSoftwareCursorsFor(PHLMONITOR pMonitor, const Time:: return; } + // don't render cursor if forced but we are already using sw cursors for the monitor + // otherwise we draw the cursor again for screencopy when using sw cursors + if (forceRender && (state->hardwareFailed || state->softwareLocks != 0)) + return; + auto box = state->box.copy(); if (overridePos.has_value()) { box.x = overridePos->x; box.y = overridePos->y; + + box.translate(-m_currentCursorImage.hotspot); } if (box.intersection(CBox{{}, {pMonitor->m_size}}).empty()) From 55076edaac38865562d647e22b42566822264218 Mon Sep 17 00:00:00 2001 From: Vaxry Date: Sat, 24 May 2025 20:39:36 +0200 Subject: [PATCH 1315/2181] versionkeeper: don't pop up on initial launch --- src/managers/VersionKeeperManager.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/src/managers/VersionKeeperManager.cpp b/src/managers/VersionKeeperManager.cpp index ef9c274d..93f820f4 100644 --- a/src/managers/VersionKeeperManager.cpp +++ b/src/managers/VersionKeeperManager.cpp @@ -31,6 +31,7 @@ CVersionKeeperManager::CVersionKeeperManager() { if (!LASTVER) { NFsUtils::writeToFile(*DATAROOT + "/" + VERSION_FILE_NAME, "0.0.0"); LASTVER = "0.0.0"; + return; } if (!isVersionOlderThanRunning(*LASTVER)) { From 28c9122adbb9cba2ba19ad723eb0f36c19b21f2d Mon Sep 17 00:00:00 2001 From: vaxerski <43317083+vaxerski@users.noreply.github.com> Date: Sat, 24 May 2025 18:41:03 +0000 Subject: [PATCH 1316/2181] [gha] Nix: update inputs --- flake.lock | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/flake.lock b/flake.lock index de57aab4..22f246d5 100644 --- a/flake.lock +++ b/flake.lock @@ -276,11 +276,11 @@ }, "nixpkgs": { "locked": { - "lastModified": 1747744144, - "narHash": "sha256-W7lqHp0qZiENCDwUZ5EX/lNhxjMdNapFnbErcbnP11Q=", + "lastModified": 1748026106, + "narHash": "sha256-6m1Y3/4pVw1RWTsrkAK2VMYSzG4MMIj7sqUy7o8th1o=", "owner": "NixOS", "repo": "nixpkgs", - "rev": "2795c506fe8fb7b03c36ccb51f75b6df0ab2553f", + "rev": "063f43f2dbdef86376cc29ad646c45c46e93234c", "type": "github" }, "original": { From cc0792c1dce250311a19e92bad204eefae072592 Mon Sep 17 00:00:00 2001 From: Vladimir-csp <4061903+Vladimir-csp@users.noreply.github.com> Date: Sat, 24 May 2025 17:26:10 +0300 Subject: [PATCH 1317/2181] hyprland-uwsm.desktop: Add TryExec This should hide this entry when uwsm is missing (at least in DMs that handle TryExec) --- systemd/hyprland-uwsm.desktop | 1 + 1 file changed, 1 insertion(+) diff --git a/systemd/hyprland-uwsm.desktop b/systemd/hyprland-uwsm.desktop index e00f4aa2..3f37532d 100644 --- a/systemd/hyprland-uwsm.desktop +++ b/systemd/hyprland-uwsm.desktop @@ -2,5 +2,6 @@ Name=Hyprland (uwsm-managed) Comment=An intelligent dynamic tiling Wayland compositor Exec=uwsm start -- hyprland.desktop +TryExec=uwsm DesktopNames=Hyprland Type=Application From a58ab20e8bc27a50d55e924b13047db6bbf9dc4a Mon Sep 17 00:00:00 2001 From: Vaxry Date: Sun, 25 May 2025 18:45:23 +0200 Subject: [PATCH 1318/2181] debug/pass: show live/precompile blur in debug --- src/render/pass/Pass.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/render/pass/Pass.cpp b/src/render/pass/Pass.cpp index fc743865..5877d9a9 100644 --- a/src/render/pass/Pass.cpp +++ b/src/render/pass/Pass.cpp @@ -273,8 +273,8 @@ void CRenderPass::renderDebugData() { auto yn = [](const bool val) -> const char* { return val ? "yes" : "no"; }; auto tick = [](const bool val) -> const char* { return val ? "✔" : "✖"; }; for (const auto& el : m_passElements | std::views::reverse) { - passStructure += std::format("{} {} (bb: {} op: {})\n", tick(!el->discard), el->element->passName(), yn(el->element->boundingBox().has_value()), - yn(!el->element->opaqueRegion().empty())); + passStructure += std::format("{} {} (bb: {} op: {}, pb: {}, lb: {})\n", tick(!el->discard), el->element->passName(), yn(el->element->boundingBox().has_value()), + yn(!el->element->opaqueRegion().empty()), yn(el->element->needsPrecomputeBlur()), yn(el->element->needsLiveBlur())); } if (!passStructure.empty()) From 2347050285920925db8bc844e3232bc932eef21e Mon Sep 17 00:00:00 2001 From: Vaxry Date: Sun, 25 May 2025 18:48:32 +0200 Subject: [PATCH 1319/2181] pass/surface: make sure popup blurs are marked for require live blur fixes #10535 --- src/render/pass/SurfacePassElement.cpp | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/render/pass/SurfacePassElement.cpp b/src/render/pass/SurfacePassElement.cpp index d161f909..2163566a 100644 --- a/src/render/pass/SurfacePassElement.cpp +++ b/src/render/pass/SurfacePassElement.cpp @@ -195,6 +195,9 @@ bool CSurfacePassElement::needsLiveBlur() { if (!m_data.pLS && !m_data.pWindow) return BLUR; + if (m_data.popup) + return BLUR; + const bool NEWOPTIM = g_pHyprOpenGL->shouldUseNewBlurOptimizations(m_data.pLS, m_data.pWindow); return BLUR && !NEWOPTIM; @@ -209,6 +212,9 @@ bool CSurfacePassElement::needsPrecomputeBlur() { if (!m_data.pLS && !m_data.pWindow) return BLUR; + if (m_data.popup) + return false; + const bool NEWOPTIM = g_pHyprOpenGL->shouldUseNewBlurOptimizations(m_data.pLS, m_data.pWindow); return BLUR && NEWOPTIM; From 292a7456af9465a57a7fe3ee36d113ae661a9ff3 Mon Sep 17 00:00:00 2001 From: Vaxry Date: Mon, 26 May 2025 16:53:35 +0200 Subject: [PATCH 1320/2181] eventLoop: fixup headers --- src/managers/eventLoop/EventLoopManager.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/managers/eventLoop/EventLoopManager.hpp b/src/managers/eventLoop/EventLoopManager.hpp index a3c755a7..977d2b01 100644 --- a/src/managers/eventLoop/EventLoopManager.hpp +++ b/src/managers/eventLoop/EventLoopManager.hpp @@ -5,7 +5,7 @@ #include #include #include -#include "helpers/signal/Signal.hpp" +#include "../../helpers/signal/Signal.hpp" #include #include "EventLoopTimer.hpp" From 4c4c9bb324b9e17bddb72c4614b451775521ee24 Mon Sep 17 00:00:00 2001 From: littleblack111 Date: Tue, 27 May 2025 01:15:11 +0800 Subject: [PATCH 1321/2181] dwindle: add better automatic window drag and drop direction detection (#9704) --- src/config/ConfigDescriptions.hpp | 6 ++++++ src/config/ConfigManager.cpp | 1 + src/layout/IHyprLayout.cpp | 26 +++++++++++++++++++++++++- 3 files changed, 32 insertions(+), 1 deletion(-) diff --git a/src/config/ConfigDescriptions.hpp b/src/config/ConfigDescriptions.hpp index 8fc6b04b..19c1f74c 100644 --- a/src/config/ConfigDescriptions.hpp +++ b/src/config/ConfigDescriptions.hpp @@ -1757,6 +1757,12 @@ inline static const std::vector CONFIG_OPTIONS = { .type = CONFIG_OPTION_CHOICE, .data = SConfigOptionDescription::SChoiceData{0, "positional,current,opening"}, }, + SConfigOptionDescription{ + .value = "dwindle:precise_move", + .description = "if enabled, bindm movewindow will drop the window more precisely depending on where your mouse is.", + .type = CONFIG_OPTION_BOOL, + .data = SConfigOptionDescription::SBoolData{true}, + }, /* * master: diff --git a/src/config/ConfigManager.cpp b/src/config/ConfigManager.cpp index f5f0bed3..99b4cf85 100644 --- a/src/config/ConfigManager.cpp +++ b/src/config/ConfigManager.cpp @@ -592,6 +592,7 @@ CConfigManager::CConfigManager() { registerConfigVar("dwindle:split_bias", Hyprlang::INT{0}); registerConfigVar("dwindle:smart_split", Hyprlang::INT{0}); registerConfigVar("dwindle:smart_resizing", Hyprlang::INT{1}); + registerConfigVar("dwindle:precise_move", Hyprlang::INT{0}); registerConfigVar("master:special_scale_factor", {1.f}); registerConfigVar("master:mfact", {0.55f}); diff --git a/src/layout/IHyprLayout.cpp b/src/layout/IHyprLayout.cpp index 8d32e44e..93b09c87 100644 --- a/src/layout/IHyprLayout.cpp +++ b/src/layout/IHyprLayout.cpp @@ -362,9 +362,33 @@ void IHyprLayout::onEndDragWindow() { } if (DRAGGINGWINDOW->m_draggingTiled) { + static auto PPRECISEMOUSE = CConfigValue("dwindle:precise_mouse_move"); DRAGGINGWINDOW->m_isFloating = false; g_pInputManager->refocus(); - changeWindowFloatingMode(DRAGGINGWINDOW); + + if (*PPRECISEMOUSE) { + eDirection direction = DIRECTION_DEFAULT; + + const auto MOUSECOORDS = g_pInputManager->getMouseCoordsInternal(); + const PHLWINDOW pReferenceWindow = g_pCompositor->vectorToWindowUnified(MOUSECOORDS, RESERVED_EXTENTS | INPUT_EXTENTS | ALLOW_FLOATING, DRAGGINGWINDOW); + + if (pReferenceWindow && pReferenceWindow != DRAGGINGWINDOW) { + const Vector2D draggedCenter = DRAGGINGWINDOW->m_realPosition->goal() + DRAGGINGWINDOW->m_realSize->goal() / 2.f; + const Vector2D referenceCenter = pReferenceWindow->m_realPosition->goal() + pReferenceWindow->m_realSize->goal() / 2.f; + const float xDiff = draggedCenter.x - referenceCenter.x; + const float yDiff = draggedCenter.y - referenceCenter.y; + + if (fabs(xDiff) > fabs(yDiff)) + direction = xDiff < 0 ? DIRECTION_LEFT : DIRECTION_RIGHT; + else + direction = yDiff < 0 ? DIRECTION_UP : DIRECTION_DOWN; + } + + onWindowRemovedTiling(DRAGGINGWINDOW); + onWindowCreatedTiling(DRAGGINGWINDOW, direction); + } else + changeWindowFloatingMode(DRAGGINGWINDOW); + DRAGGINGWINDOW->m_lastFloatingSize = m_draggingWindowOriginalFloatSize; } From c2805aad92978577a4d89b14f1c4f51e50247547 Mon Sep 17 00:00:00 2001 From: Nikolaos Karaolidis Date: Mon, 26 May 2025 18:25:58 +0100 Subject: [PATCH 1322/2181] config: add maxwidth monitor resolution mode (#10528) Signed-off-by: Nikolaos Karaolidis --- src/config/ConfigManager.cpp | 2 ++ src/helpers/Monitor.cpp | 13 ++++++++++++- 2 files changed, 14 insertions(+), 1 deletion(-) diff --git a/src/config/ConfigManager.cpp b/src/config/ConfigManager.cpp index 99b4cf85..a8d70bb6 100644 --- a/src/config/ConfigManager.cpp +++ b/src/config/ConfigManager.cpp @@ -2014,6 +2014,8 @@ std::optional CConfigManager::handleMonitor(const std::string& comm newrule.resolution = Vector2D(-1, -1); } else if (ARGS[1].starts_with("highres")) { newrule.resolution = Vector2D(-1, -2); + } else if (ARGS[1].starts_with("maxwidth")) { + newrule.resolution = Vector2D(-1, -3); } else if (parseModeLine(ARGS[1], newrule.drmMode)) { newrule.resolution = Vector2D(newrule.drmMode.hdisplay, newrule.drmMode.vdisplay); newrule.refreshRate = float(newrule.drmMode.vrefresh) / 1000; diff --git a/src/helpers/Monitor.cpp b/src/helpers/Monitor.cpp index 4dc0942d..72a221f5 100644 --- a/src/helpers/Monitor.cpp +++ b/src/helpers/Monitor.cpp @@ -515,7 +515,7 @@ bool CMonitor::applyMonitorRule(SMonitorRule* pMonitorRule, bool force) { } else if (RULE->resolution == Vector2D(-1, -2)) { requestedStr = "highres"; - // sort prioritizing resultion 1st and refresh rate 2nd, then add best 3 + // sort prioritizing resolution 1st and refresh rate 2nd, then add best 3 addBest3Modes([](auto const& a, auto const& b) { if (a->pixelSize.x > b->pixelSize.x && a->pixelSize.y > b->pixelSize.y) return true; @@ -524,6 +524,17 @@ bool CMonitor::applyMonitorRule(SMonitorRule* pMonitorRule, bool force) { return true; return false; }); + } else if (RULE->resolution == Vector2D(-1, -3)) { + requestedStr = "maxwidth"; + + // sort prioritizing widest resolution 1st and refresh rate 2nd, then add best 3 + addBest3Modes([](auto const& a, auto const& b) { + if (a->pixelSize.x > b->pixelSize.x) + return true; + if (a->pixelSize.x == b->pixelSize.x && std::round(a->refreshRate) > std::round(b->refreshRate)) + return true; + return false; + }); } else if (RULE->resolution != Vector2D()) { // user requested mode requestedStr = std::format("{:X0}@{:.2f}Hz", RULE->resolution, RULE->refreshRate); From be6ee6e55f08387a9e2fbf712c061fb238a70319 Mon Sep 17 00:00:00 2001 From: Vaxry Date: Mon, 26 May 2025 23:33:25 +0200 Subject: [PATCH 1323/2181] cmake: disable gprof by default --- CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 4267a59d..61893803 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -153,7 +153,7 @@ endif() add_executable(Hyprland ${SRCFILES} ${TRACY_CPP_FILES}) -set(USE_GPROF ON) +set(USE_GPROF OFF) if(CMAKE_BUILD_TYPE MATCHES Debug OR CMAKE_BUILD_TYPE MATCHES DEBUG) message(STATUS "Setting debug flags") From a62ccb169aa05ef40c6c215c0638e843740920f3 Mon Sep 17 00:00:00 2001 From: littleblack111 Date: Tue, 27 May 2025 15:33:17 +0800 Subject: [PATCH 1324/2181] config: fix crash on misnamed variable (#10549) --- src/config/ConfigDescriptions.hpp | 2 +- src/config/ConfigManager.cpp | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/config/ConfigDescriptions.hpp b/src/config/ConfigDescriptions.hpp index 19c1f74c..f59bd1a9 100644 --- a/src/config/ConfigDescriptions.hpp +++ b/src/config/ConfigDescriptions.hpp @@ -1758,7 +1758,7 @@ inline static const std::vector CONFIG_OPTIONS = { .data = SConfigOptionDescription::SChoiceData{0, "positional,current,opening"}, }, SConfigOptionDescription{ - .value = "dwindle:precise_move", + .value = "dwindle:precise_mouse_move", .description = "if enabled, bindm movewindow will drop the window more precisely depending on where your mouse is.", .type = CONFIG_OPTION_BOOL, .data = SConfigOptionDescription::SBoolData{true}, diff --git a/src/config/ConfigManager.cpp b/src/config/ConfigManager.cpp index a8d70bb6..a4f09d65 100644 --- a/src/config/ConfigManager.cpp +++ b/src/config/ConfigManager.cpp @@ -592,7 +592,7 @@ CConfigManager::CConfigManager() { registerConfigVar("dwindle:split_bias", Hyprlang::INT{0}); registerConfigVar("dwindle:smart_split", Hyprlang::INT{0}); registerConfigVar("dwindle:smart_resizing", Hyprlang::INT{1}); - registerConfigVar("dwindle:precise_move", Hyprlang::INT{0}); + registerConfigVar("dwindle:precise_mouse_move", Hyprlang::INT{0}); registerConfigVar("master:special_scale_factor", {1.f}); registerConfigVar("master:mfact", {0.55f}); From ddb9f8394df01eaa575955e7f0eee99065441e4b Mon Sep 17 00:00:00 2001 From: littleblack111 Date: Tue, 27 May 2025 22:50:00 +0800 Subject: [PATCH 1325/2181] config: fix inconsistant hint of default value (#10556) similar to https://github.com/hyprwm/hyprland-wiki/pull/1093 --- src/config/ConfigDescriptions.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/config/ConfigDescriptions.hpp b/src/config/ConfigDescriptions.hpp index f59bd1a9..5e18233d 100644 --- a/src/config/ConfigDescriptions.hpp +++ b/src/config/ConfigDescriptions.hpp @@ -1761,7 +1761,7 @@ inline static const std::vector CONFIG_OPTIONS = { .value = "dwindle:precise_mouse_move", .description = "if enabled, bindm movewindow will drop the window more precisely depending on where your mouse is.", .type = CONFIG_OPTION_BOOL, - .data = SConfigOptionDescription::SBoolData{true}, + .data = SConfigOptionDescription::SBoolData{false}, }, /* From 90d0b8ecae9540c21ce418ef781cf0fc2afc4dff Mon Sep 17 00:00:00 2001 From: Nikolaos Karaolidis Date: Tue, 27 May 2025 15:51:59 +0100 Subject: [PATCH 1326/2181] core: add auto-center arrangements (#10527) Signed-off-by: Nikolaos Karaolidis --- src/Compositor.cpp | 24 ++++++++++++++++++++++++ src/config/ConfigManager.cpp | 12 +++++++++++- src/helpers/Monitor.hpp | 6 +++++- 3 files changed, 40 insertions(+), 2 deletions(-) diff --git a/src/Compositor.cpp b/src/Compositor.cpp index c6593923..b4d3aaea 100644 --- a/src/Compositor.cpp +++ b/src/Compositor.cpp @@ -2890,6 +2890,30 @@ void CCompositor::arrangeMonitors() { case eAutoDirs::DIR_AUTO_LEFT: newPosition.x = maxXOffsetLeft - m->m_size.x; break; case eAutoDirs::DIR_AUTO_RIGHT: case eAutoDirs::DIR_AUTO_NONE: newPosition.x = maxXOffsetRight; break; + case eAutoDirs::DIR_AUTO_CENTER_UP: { + int width = maxXOffsetRight - maxXOffsetLeft; + newPosition.y = maxYOffsetUp - m->m_size.y; + newPosition.x = maxXOffsetLeft + (width - m->m_size.x) / 2; + break; + } + case eAutoDirs::DIR_AUTO_CENTER_DOWN: { + int width = maxXOffsetRight - maxXOffsetLeft; + newPosition.y = maxYOffsetDown; + newPosition.x = maxXOffsetLeft + (width - m->m_size.x) / 2; + break; + } + case eAutoDirs::DIR_AUTO_CENTER_LEFT: { + int height = maxYOffsetDown - maxYOffsetUp; + newPosition.x = maxXOffsetLeft - m->m_size.x; + newPosition.y = maxYOffsetUp + (height - m->m_size.y) / 2; + break; + } + case eAutoDirs::DIR_AUTO_CENTER_RIGHT: { + int height = maxYOffsetDown - maxYOffsetUp; + newPosition.x = maxXOffsetRight; + newPosition.y = maxYOffsetUp + (height - m->m_size.y) / 2; + break; + } default: UNREACHABLE(); } Debug::log(LOG, "arrangeMonitors: {} auto {:j}", m->m_name, m->m_position); diff --git a/src/config/ConfigManager.cpp b/src/config/ConfigManager.cpp index a4f09d65..a79afb35 100644 --- a/src/config/ConfigManager.cpp +++ b/src/config/ConfigManager.cpp @@ -2049,10 +2049,20 @@ std::optional CConfigManager::handleMonitor(const std::string& comm newrule.autoDir = eAutoDirs::DIR_AUTO_UP; else if (ARGS[2] == "auto-down") newrule.autoDir = eAutoDirs::DIR_AUTO_DOWN; + else if (ARGS[2] == "auto-center-right") + newrule.autoDir = eAutoDirs::DIR_AUTO_CENTER_RIGHT; + else if (ARGS[2] == "auto-center-left") + newrule.autoDir = eAutoDirs::DIR_AUTO_CENTER_LEFT; + else if (ARGS[2] == "auto-center-up") + newrule.autoDir = eAutoDirs::DIR_AUTO_CENTER_UP; + else if (ARGS[2] == "auto-center-down") + newrule.autoDir = eAutoDirs::DIR_AUTO_CENTER_DOWN; else { Debug::log(WARN, "Invalid auto direction. Valid options are 'auto'," - "'auto-up', 'auto-down', 'auto-left', and 'auto-right'."); + "'auto-up', 'auto-down', 'auto-left', 'auto-right'," + "'auto-center-up', 'auto-center-down'," + "'auto-center-left', and 'auto-center-right'."); error += "invalid auto direction "; } } else { diff --git a/src/helpers/Monitor.hpp b/src/helpers/Monitor.hpp index 31777b0c..019a5547 100644 --- a/src/helpers/Monitor.hpp +++ b/src/helpers/Monitor.hpp @@ -25,7 +25,11 @@ enum eAutoDirs : uint8_t { DIR_AUTO_UP, DIR_AUTO_DOWN, DIR_AUTO_LEFT, - DIR_AUTO_RIGHT + DIR_AUTO_RIGHT, + DIR_AUTO_CENTER_UP, + DIR_AUTO_CENTER_DOWN, + DIR_AUTO_CENTER_LEFT, + DIR_AUTO_CENTER_RIGHT }; enum eCMType : uint8_t { From 24915a3a9b0bb8c4dc8b5a365cc0bc3a03ee36f0 Mon Sep 17 00:00:00 2001 From: Kamikadze <40305144+Kam1k4dze@users.noreply.github.com> Date: Tue, 27 May 2025 20:10:22 +0500 Subject: [PATCH 1327/2181] windowrules: Add noscreenshare (#10482) --- src/desktop/Window.hpp | 2 ++ src/protocols/Screencopy.cpp | 54 ++++++++++++++++++++++++++++++++ src/protocols/ToplevelExport.cpp | 17 +++++----- 3 files changed, 66 insertions(+), 7 deletions(-) diff --git a/src/desktop/Window.hpp b/src/desktop/Window.hpp index 0d06b69c..3f73c468 100644 --- a/src/desktop/Window.hpp +++ b/src/desktop/Window.hpp @@ -104,6 +104,7 @@ struct SWindowData { CWindowOverridableVar xray = false; CWindowOverridableVar renderUnfocused = false; CWindowOverridableVar noFollowMouse = false; + CWindowOverridableVar noScreenShare = false; CWindowOverridableVar borderSize = {std::string("general:border_size"), Hyprlang::INT(0), std::nullopt}; CWindowOverridableVar rounding = {std::string("decoration:rounding"), Hyprlang::INT(0), std::nullopt}; @@ -489,6 +490,7 @@ namespace NWindowProperties { {"immediate", [](const PHLWINDOW& pWindow) { return &pWindow->m_windowData.tearing; }}, {"xray", [](const PHLWINDOW& pWindow) { return &pWindow->m_windowData.xray; }}, {"nofollowmouse", [](const PHLWINDOW& pWindow) { return &pWindow->m_windowData.noFollowMouse; }}, + {"noscreenshare", [](const PHLWINDOW& pWindow) { return &pWindow->m_windowData.noScreenShare; }}, }; const std::unordered_map*(const PHLWINDOW&)>> intWindowProperties = { diff --git a/src/protocols/Screencopy.cpp b/src/protocols/Screencopy.cpp index 5fa7c84e..8002776a 100644 --- a/src/protocols/Screencopy.cpp +++ b/src/protocols/Screencopy.cpp @@ -13,6 +13,7 @@ #include "types/Buffer.hpp" #include "../helpers/Format.hpp" #include "../helpers/time/Time.hpp" +#include "XDGShell.hpp" #include #include @@ -200,6 +201,59 @@ void CScreencopyFrame::renderMon() { g_pHyprOpenGL->renderTexture(TEXTURE, monbox, 1); g_pHyprOpenGL->setRenderModifEnabled(true); g_pHyprOpenGL->setMonitorTransformEnabled(false); + + for (auto const& w : g_pCompositor->m_windows) { + if (!w->m_windowData.noScreenShare.valueOrDefault()) + continue; + + if (!g_pHyprRenderer->shouldRenderWindow(w)) + continue; + + const auto PWORKSPACE = w->m_workspace; + + if UNLIKELY (!PWORKSPACE) + continue; + + const auto REALPOS = w->m_realPosition->value() + (w->m_pinned ? Vector2D{} : PWORKSPACE->m_renderOffset->value()); + const auto noScreenShareBox = CBox{REALPOS.x, REALPOS.y, std::max(w->m_realSize->value().x, 5.0), std::max(w->m_realSize->value().y, 5.0)} + .scale(m_monitor->m_scale) + .translate({-m_monitor->m_position.x, -m_monitor->m_position.y}) + .translate({-m_box.x, -m_box.y}); + + const auto dontRound = w->isEffectiveInternalFSMode(FSMODE_FULLSCREEN) || w->m_windowData.noRounding.valueOrDefault(); + const auto rounding = dontRound ? 0 : w->rounding() * m_monitor->m_scale; + const auto roundingPower = dontRound ? 2.0f : w->roundingPower(); + + g_pHyprOpenGL->renderRect(noScreenShareBox, {0, 0, 0, 255}, rounding, roundingPower); + + if (w->m_isX11 || !w->m_popupHead) + continue; + + const auto geom = w->m_xdgSurface->m_current.geometry; + const Vector2D popupBaseOffset = REALPOS - Vector2D{geom.pos().x, geom.pos().y}; + + w->m_popupHead->breadthfirst( + [&](WP popup, void*) { + if (!popup->m_wlSurface || !popup->m_wlSurface->resource() || !popup->m_mapped) + return; + + const auto popRel = popup->coordsRelativeToParent(); + popup->m_wlSurface->resource()->breadthfirst( + [&](SP surf, const Vector2D& localOff, void*) { + const auto size = surf->m_current.size; + const auto surfBox = CBox{popupBaseOffset.x + popRel.x + localOff.x, popupBaseOffset.y + popRel.y + localOff.y, size.x, size.y} + .scale(m_monitor->m_scale) + .translate({-m_monitor->m_position.x, -m_monitor->m_position.y}) + .translate({-m_box.x, -m_box.y}); + + if LIKELY (surfBox.w > 0 && surfBox.h > 0) + g_pHyprOpenGL->renderRect(surfBox, {0, 0, 0, 255}); + }, + nullptr); + }, + nullptr); + } + if (m_overlayCursor) g_pPointerManager->renderSoftwareCursorsFor(m_monitor.lock(), Time::steadyNow(), fakeDamage, g_pInputManager->getMouseCoordsInternal() - m_monitor->m_position - m_box.pos(), true); diff --git a/src/protocols/ToplevelExport.cpp b/src/protocols/ToplevelExport.cpp index e50f1fce..4d0ee0f8 100644 --- a/src/protocols/ToplevelExport.cpp +++ b/src/protocols/ToplevelExport.cpp @@ -257,10 +257,11 @@ bool CToplevelExportFrame::copyShm(const Time::steady_tp& now) { // render client at 0,0 if (PERM == PERMISSION_RULE_ALLOW_MODE_ALLOW) { - g_pHyprRenderer->m_bBlockSurfaceFeedback = g_pHyprRenderer->shouldRenderWindow(m_window); // block the feedback to avoid spamming the surface if it's visible - g_pHyprRenderer->renderWindow(m_window, PMONITOR, now, false, RENDER_PASS_ALL, true, true); - g_pHyprRenderer->m_bBlockSurfaceFeedback = false; - + if (!m_window->m_windowData.noScreenShare.valueOrDefault()) { + g_pHyprRenderer->m_bBlockSurfaceFeedback = g_pHyprRenderer->shouldRenderWindow(m_window); // block the feedback to avoid spamming the surface if it's visible + g_pHyprRenderer->renderWindow(m_window, PMONITOR, now, false, RENDER_PASS_ALL, true, true); + g_pHyprRenderer->m_bBlockSurfaceFeedback = false; + } if (overlayCursor) g_pPointerManager->renderSoftwareCursorsFor(PMONITOR->m_self.lock(), now, fakeDamage, g_pInputManager->getMouseCoordsInternal() - m_window->m_realPosition->value()); } else if (PERM == PERMISSION_RULE_ALLOW_MODE_DENY) { @@ -338,9 +339,11 @@ bool CToplevelExportFrame::copyDmabuf(const Time::steady_tp& now) { g_pHyprOpenGL->clear(CHyprColor(0, 0, 0, 1.0)); if (PERM == PERMISSION_RULE_ALLOW_MODE_ALLOW) { - g_pHyprRenderer->m_bBlockSurfaceFeedback = g_pHyprRenderer->shouldRenderWindow(m_window); // block the feedback to avoid spamming the surface if it's visible - g_pHyprRenderer->renderWindow(m_window, PMONITOR, now, false, RENDER_PASS_ALL, true, true); - g_pHyprRenderer->m_bBlockSurfaceFeedback = false; + if (!m_window->m_windowData.noScreenShare.valueOrDefault()) { + g_pHyprRenderer->m_bBlockSurfaceFeedback = g_pHyprRenderer->shouldRenderWindow(m_window); // block the feedback to avoid spamming the surface if it's visible + g_pHyprRenderer->renderWindow(m_window, PMONITOR, now, false, RENDER_PASS_ALL, true, true); + g_pHyprRenderer->m_bBlockSurfaceFeedback = false; + } if (overlayCursor) g_pPointerManager->renderSoftwareCursorsFor(PMONITOR->m_self.lock(), now, fakeDamage, g_pInputManager->getMouseCoordsInternal() - m_window->m_realPosition->value()); From 9b327ddfd1ad4cfef7a04a178e9f0aed16e95e0a Mon Sep 17 00:00:00 2001 From: vaxerski Date: Tue, 27 May 2025 21:26:47 +0200 Subject: [PATCH 1328/2181] monitor: mark 0, 0 presentation timestamps as invalid fixes #10562 --- src/helpers/Monitor.cpp | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) diff --git a/src/helpers/Monitor.cpp b/src/helpers/Monitor.cpp index 72a221f5..d7536a39 100644 --- a/src/helpers/Monitor.cpp +++ b/src/helpers/Monitor.cpp @@ -74,11 +74,16 @@ void CMonitor::onConnect(bool noRule) { auto E = std::any_cast(d); timespec* ts = E.when; - if (!ts) { - timespec now; - clock_gettime(CLOCK_MONOTONIC, &now); - PROTO::presentation->onPresented(m_self.lock(), Time::fromTimespec(&now), E.refresh, E.seq, E.flags); - } else + + if (ts && ts->tv_sec <= 2) { + // drop this timestamp, it's not valid. Likely drm is cringe. We can't push it further because + // a) it's wrong, b) our translations aren't 100% accurate and risk underflows + ts = nullptr; + } + + if (!ts) + PROTO::presentation->onPresented(m_self.lock(), Time::steadyNow(), E.refresh, E.seq, E.flags); + else PROTO::presentation->onPresented(m_self.lock(), Time::fromTimespec(E.when), E.refresh, E.seq, E.flags); }); From 5cc6cb49458634bd277ada22dfffe6f189cd7d34 Mon Sep 17 00:00:00 2001 From: vaxerski Date: Wed, 28 May 2025 15:18:30 +0200 Subject: [PATCH 1329/2181] groupbar: force recalc on visibility changes fixes #10566 --- .../decorations/CHyprGroupBarDecoration.cpp | 17 ++++++++++++----- .../decorations/CHyprGroupBarDecoration.hpp | 3 +++ 2 files changed, 15 insertions(+), 5 deletions(-) diff --git a/src/render/decorations/CHyprGroupBarDecoration.cpp b/src/render/decorations/CHyprGroupBarDecoration.cpp index 84060e0d..65d7d7ff 100644 --- a/src/render/decorations/CHyprGroupBarDecoration.cpp +++ b/src/render/decorations/CHyprGroupBarDecoration.cpp @@ -29,7 +29,6 @@ SDecorationPositioningInfo CHyprGroupBarDecoration::getPositioningInfo() { static auto PHEIGHT = CConfigValue("group:groupbar:height"); static auto PINDICATORGAP = CConfigValue("group:groupbar:indicator_gap"); static auto PINDICATORHEIGHT = CConfigValue("group:groupbar:indicator_height"); - static auto PENABLED = CConfigValue("group:groupbar:enabled"); static auto PRENDERTITLES = CConfigValue("group:groupbar:render_titles"); static auto PGRADIENTS = CConfigValue("group:groupbar:gradients"); static auto PPRIORITY = CConfigValue("group:groupbar:priority"); @@ -43,7 +42,7 @@ SDecorationPositioningInfo CHyprGroupBarDecoration::getPositioningInfo() { info.priority = *PPRIORITY; info.reserved = true; - if (*PENABLED && m_window->m_windowData.decorate.valueOrDefault()) { + if (visible()) { if (*PSTACKED) { const auto ONEBARHEIGHT = *POUTERGAP + *PINDICATORHEIGHT + *PINDICATORGAP + (*PGRADIENTS || *PRENDERTITLES ? *PHEIGHT : 0); info.desiredExtents = {{0, (ONEBARHEIGHT * m_dwGroupMembers.size()) + (*PKEEPUPPERGAP * *POUTERGAP)}, {0, 0}}; @@ -96,11 +95,14 @@ void CHyprGroupBarDecoration::damageEntire() { void CHyprGroupBarDecoration::draw(PHLMONITOR pMonitor, float const& a) { // get how many bars we will draw - int barsToDraw = m_dwGroupMembers.size(); + int barsToDraw = m_dwGroupMembers.size(); - static auto PENABLED = CConfigValue("group:groupbar:enabled"); + const bool VISIBLE = visible(); - if (!*PENABLED || !m_window->m_windowData.decorate.valueOrDefault()) + if (VISIBLE != m_bLastVisibilityStatus) + g_pDecorationPositioner->repositionDeco(this); + + if (!VISIBLE) return; static auto PRENDERTITLES = CConfigValue("group:groupbar:render_titles"); @@ -583,3 +585,8 @@ CBox CHyprGroupBarDecoration::assignedBoxGlobal() { return box.round(); } + +bool CHyprGroupBarDecoration::visible() { + static auto PENABLED = CConfigValue("group:groupbar:enabled"); + return *PENABLED && m_window->m_windowData.decorate.valueOrDefault(); +} diff --git a/src/render/decorations/CHyprGroupBarDecoration.hpp b/src/render/decorations/CHyprGroupBarDecoration.hpp index feb304f2..5e1abc5a 100644 --- a/src/render/decorations/CHyprGroupBarDecoration.hpp +++ b/src/render/decorations/CHyprGroupBarDecoration.hpp @@ -56,10 +56,13 @@ class CHyprGroupBarDecoration : public IHyprWindowDecoration { float m_barWidth; float m_barHeight; + bool m_bLastVisibilityStatus = true; + CTitleTex* textureFromTitle(const std::string&); void invalidateTextures(); CBox assignedBoxGlobal(); + bool visible(); bool onBeginWindowDragOnDeco(const Vector2D&); bool onEndWindowDragOnDeco(const Vector2D&, PHLWINDOW); From 9bf1b491440eac6f9c0d6853013ad5666c12d1d9 Mon Sep 17 00:00:00 2001 From: littleblack111 Date: Wed, 28 May 2025 21:20:03 +0800 Subject: [PATCH 1330/2181] snap: add option to respect gaps (#10524) --- src/config/ConfigDescriptions.hpp | 6 ++++ src/config/ConfigManager.cpp | 1 + src/layout/IHyprLayout.cpp | 48 +++++++++++++++++++------------ 3 files changed, 37 insertions(+), 18 deletions(-) diff --git a/src/config/ConfigDescriptions.hpp b/src/config/ConfigDescriptions.hpp index 5e18233d..a77cf757 100644 --- a/src/config/ConfigDescriptions.hpp +++ b/src/config/ConfigDescriptions.hpp @@ -128,6 +128,12 @@ inline static const std::vector CONFIG_OPTIONS = { .type = CONFIG_OPTION_BOOL, .data = SConfigOptionDescription::SBoolData{false}, }, + SConfigOptionDescription{ + .value = "general:snap:respect_gaps", + .description = "if true, snapping will respect gaps between windows", + .type = CONFIG_OPTION_BOOL, + .data = SConfigOptionDescription::SBoolData{false}, + }, /* * decoration: diff --git a/src/config/ConfigManager.cpp b/src/config/ConfigManager.cpp index a79afb35..acbc0262 100644 --- a/src/config/ConfigManager.cpp +++ b/src/config/ConfigManager.cpp @@ -456,6 +456,7 @@ CConfigManager::CConfigManager() { registerConfigVar("general:snap:window_gap", Hyprlang::INT{10}); registerConfigVar("general:snap:monitor_gap", Hyprlang::INT{10}); registerConfigVar("general:snap:border_overlap", Hyprlang::INT{0}); + registerConfigVar("general:snap:respect_gaps", Hyprlang::INT{0}); registerConfigVar("general:col.active_border", Hyprlang::CConfigCustomValueType{&configHandleGradientSet, configHandleGradientDestroy, "0xffffffff"}); registerConfigVar("general:col.inactive_border", Hyprlang::CConfigCustomValueType{&configHandleGradientSet, configHandleGradientDestroy, "0xff444444"}); registerConfigVar("general:col.nogroup_border", Hyprlang::CConfigCustomValueType{&configHandleGradientSet, configHandleGradientDestroy, "0xffffaaff"}); diff --git a/src/layout/IHyprLayout.cpp b/src/layout/IHyprLayout.cpp index 93b09c87..1fe3a936 100644 --- a/src/layout/IHyprLayout.cpp +++ b/src/layout/IHyprLayout.cpp @@ -417,6 +417,7 @@ static void performSnap(Vector2D& sourcePos, Vector2D& sourceSize, PHLWINDOW DRA static auto SNAPWINDOWGAP = CConfigValue("general:snap:window_gap"); static auto SNAPMONITORGAP = CConfigValue("general:snap:monitor_gap"); static auto SNAPBORDEROVERLAP = CConfigValue("general:snap:border_overlap"); + static auto SNAPRESPECTGAPS = CConfigValue("general:snap:respect_gaps"); const SnapFn SNAP = (MODE == MBIND_MOVE) ? snapMove : snapResize; int snaps = 0; @@ -444,9 +445,15 @@ static void performSnap(Vector2D& sourcePos, Vector2D& sourceSize, PHLWINDOW DRA const int OTHERBORDERSIZE = other->getRealBorderSize(); const double BORDERSIZE = OVERLAP ? std::max(DRAGGINGBORDERSIZE, OTHERBORDERSIZE) : (DRAGGINGBORDERSIZE + OTHERBORDERSIZE); - const CBox SURF = other->getWindowMainSurfaceBox(); - const SRange SURFBX = {SURF.x - BORDERSIZE, SURF.x + SURF.w + BORDERSIZE}; - const SRange SURFBY = {SURF.y - BORDERSIZE, SURF.y + SURF.h + BORDERSIZE}; + const CBox SURF = other->getWindowMainSurfaceBox(); + double gapOffset = 0; + if (*SNAPRESPECTGAPS) { + static auto PGAPSINDATA = CConfigValue("general:gaps_in"); + auto* PGAPSINPTR = (CCssGapData*)(PGAPSINDATA.ptr())->getData(); + gapOffset = std::max({PGAPSINPTR->m_left, PGAPSINPTR->m_right, PGAPSINPTR->m_top, PGAPSINPTR->m_bottom}); + } + const SRange SURFBX = {SURF.x - BORDERSIZE - gapOffset, SURF.x + SURF.w + BORDERSIZE + gapOffset}; + const SRange SURFBY = {SURF.y - BORDERSIZE - gapOffset, SURF.y + SURF.h + BORDERSIZE + gapOffset}; // only snap windows if their ranges overlap in the opposite axis if (sourceY.start <= SURFBY.end && SURFBY.start <= sourceY.end) { @@ -497,32 +504,37 @@ static void performSnap(Vector2D& sourcePos, Vector2D& sourceSize, PHLWINDOW DRA const double GAPSIZE = *SNAPMONITORGAP; const double BORDERDIFF = OVERLAP ? DRAGGINGBORDERSIZE : 0; const auto MON = DRAGGINGWINDOW->m_monitor.lock(); - - SRange monX = {MON->m_position.x + MON->m_reservedTopLeft.x + DRAGGINGBORDERSIZE, MON->m_position.x + MON->m_size.x - MON->m_reservedBottomRight.x - DRAGGINGBORDERSIZE}; - SRange monY = {MON->m_position.y + MON->m_reservedTopLeft.y + DRAGGINGBORDERSIZE, MON->m_position.y + MON->m_size.y - MON->m_reservedBottomRight.y - DRAGGINGBORDERSIZE}; + double gapOffset = 0; + if (*SNAPRESPECTGAPS) { + static auto PGAPSOUTDATA = CConfigValue("general:gaps_out"); + auto* PGAPSOUTPTR = (CCssGapData*)(PGAPSOUTDATA.ptr())->getData(); + gapOffset = std::max({PGAPSOUTPTR->m_left, PGAPSOUTPTR->m_right, PGAPSOUTPTR->m_top, PGAPSOUTPTR->m_bottom}); + } if (CORNER & (CORNER_TOPLEFT | CORNER_BOTTOMLEFT) && - ((MON->m_reservedTopLeft.x > 0 && canSnap(sourceX.start, monX.start, GAPSIZE)) || - canSnap(sourceX.start, (monX.start -= MON->m_reservedTopLeft.x + BORDERDIFF), GAPSIZE))) { - SNAP(sourceX.start, sourceX.end, monX.start); + ((MON->m_reservedTopLeft.x > 0 && canSnap(sourceX.start, MON->m_position.x + MON->m_reservedTopLeft.x + DRAGGINGBORDERSIZE + gapOffset, GAPSIZE)) || + canSnap(sourceX.start, MON->m_position.x + MON->m_reservedTopLeft.x - BORDERDIFF + gapOffset, GAPSIZE))) { + SNAP(sourceX.start, sourceX.end, MON->m_position.x + MON->m_reservedTopLeft.x + DRAGGINGBORDERSIZE + gapOffset); snaps |= SNAP_LEFT; } if (CORNER & (CORNER_TOPRIGHT | CORNER_BOTTOMRIGHT) && - ((MON->m_reservedBottomRight.x > 0 && canSnap(sourceX.end, monX.end, GAPSIZE)) || - canSnap(sourceX.end, (monX.end += MON->m_reservedBottomRight.x + BORDERDIFF), GAPSIZE))) { - SNAP(sourceX.end, sourceX.start, monX.end); + ((MON->m_reservedBottomRight.x > 0 && + canSnap(sourceX.end, MON->m_position.x + MON->m_size.x - MON->m_reservedBottomRight.x - DRAGGINGBORDERSIZE - gapOffset, GAPSIZE)) || + canSnap(sourceX.end, MON->m_position.x + MON->m_size.x - MON->m_reservedBottomRight.x + BORDERDIFF - gapOffset, GAPSIZE))) { + SNAP(sourceX.end, sourceX.start, MON->m_position.x + MON->m_size.x - MON->m_reservedBottomRight.x - DRAGGINGBORDERSIZE - gapOffset); snaps |= SNAP_RIGHT; } if (CORNER & (CORNER_TOPLEFT | CORNER_TOPRIGHT) && - ((MON->m_reservedTopLeft.y > 0 && canSnap(sourceY.start, monY.start, GAPSIZE)) || - canSnap(sourceY.start, (monY.start -= MON->m_reservedTopLeft.y + BORDERDIFF), GAPSIZE))) { - SNAP(sourceY.start, sourceY.end, monY.start); + ((MON->m_reservedTopLeft.y > 0 && canSnap(sourceY.start, MON->m_position.y + MON->m_reservedTopLeft.y + DRAGGINGBORDERSIZE + gapOffset, GAPSIZE)) || + canSnap(sourceY.start, MON->m_position.y + MON->m_reservedTopLeft.y - BORDERDIFF + gapOffset, GAPSIZE))) { + SNAP(sourceY.start, sourceY.end, MON->m_position.y + MON->m_reservedTopLeft.y + DRAGGINGBORDERSIZE + gapOffset); snaps |= SNAP_UP; } if (CORNER & (CORNER_BOTTOMLEFT | CORNER_BOTTOMRIGHT) && - ((MON->m_reservedBottomRight.y > 0 && canSnap(sourceY.end, monY.end, GAPSIZE)) || - canSnap(sourceY.end, (monY.end += MON->m_reservedBottomRight.y + BORDERDIFF), GAPSIZE))) { - SNAP(sourceY.end, sourceY.start, monY.end); + ((MON->m_reservedBottomRight.y > 0 && + canSnap(sourceY.end, MON->m_position.y + MON->m_size.y - MON->m_reservedBottomRight.y - DRAGGINGBORDERSIZE - gapOffset, GAPSIZE)) || + canSnap(sourceY.end, MON->m_position.y + MON->m_size.y - MON->m_reservedBottomRight.y + BORDERDIFF - gapOffset, GAPSIZE))) { + SNAP(sourceY.end, sourceY.start, MON->m_position.y + MON->m_size.y - MON->m_reservedBottomRight.y - DRAGGINGBORDERSIZE - gapOffset); snaps |= SNAP_DOWN; } } From 9190443d951c21ab24201d033accf90b4d172f46 Mon Sep 17 00:00:00 2001 From: Kamikadze <40305144+Kam1k4dze@users.noreply.github.com> Date: Fri, 30 May 2025 18:25:59 +0500 Subject: [PATCH 1331/2181] refactor: use std::ranges whenever possible (#10584) --- src/Compositor.cpp | 4 ++-- src/config/ConfigDataValues.hpp | 2 +- src/config/ConfigManager.cpp | 12 +++++----- src/debug/HyprCtl.cpp | 11 ++++----- src/debug/HyprNotificationOverlay.cpp | 2 +- src/desktop/Window.cpp | 3 ++- src/devices/IKeyboard.cpp | 2 +- src/events/Windows.cpp | 2 +- src/helpers/MiscFunctions.cpp | 8 +++---- src/helpers/Monitor.cpp | 12 ++++++---- src/hyprerror/HyprError.cpp | 2 +- src/layout/MasterLayout.cpp | 23 +++++++++---------- src/managers/AnimationManager.cpp | 2 +- src/managers/CursorManager.cpp | 2 +- src/managers/EventManager.cpp | 2 +- src/managers/HookSystemManager.cpp | 2 +- src/managers/KeybindManager.cpp | 13 ++++------- src/managers/LayoutManager.cpp | 4 ++-- src/managers/PointerManager.cpp | 2 +- src/managers/SeatManager.cpp | 2 +- src/managers/XCursorManager.cpp | 8 +++---- src/managers/input/InputManager.cpp | 12 +++++----- src/protocols/AlphaModifier.cpp | 2 +- src/protocols/ColorManagement.cpp | 4 ++-- src/protocols/DRMLease.cpp | 6 ++--- src/protocols/DataDeviceWlr.cpp | 6 ++--- src/protocols/FocusGrab.cpp | 4 ++-- src/protocols/ForeignToplevel.cpp | 2 +- src/protocols/ForeignToplevelWlr.cpp | 2 +- src/protocols/HyprlandSurface.cpp | 2 +- src/protocols/LayerShell.cpp | 2 +- src/protocols/LinuxDMABUF.cpp | 16 ++++++------- src/protocols/PointerConstraints.cpp | 2 +- src/protocols/PrimarySelection.cpp | 6 ++--- src/protocols/SecurityContext.cpp | 2 +- src/protocols/VirtualKeyboard.cpp | 2 +- src/protocols/XDGActivation.cpp | 5 ++-- src/protocols/XDGShell.cpp | 8 +++---- src/protocols/XXColorManagement.cpp | 4 ++-- src/protocols/core/Compositor.cpp | 4 ++-- src/protocols/core/DataDevice.cpp | 6 ++--- src/protocols/core/Seat.cpp | 4 ++-- src/protocols/core/Shm.cpp | 2 +- src/protocols/core/Subcompositor.cpp | 14 +++++------ src/render/OpenGL.cpp | 8 +++---- src/render/Renderer.cpp | 10 ++++---- .../decorations/DecorationPositioner.cpp | 16 ++++++------- src/render/pass/Pass.cpp | 2 +- src/xwayland/XSurface.cpp | 2 +- src/xwayland/XWM.cpp | 8 +++---- 50 files changed, 137 insertions(+), 146 deletions(-) diff --git a/src/Compositor.cpp b/src/Compositor.cpp index b4d3aaea..8d53f3d8 100644 --- a/src/Compositor.cpp +++ b/src/Compositor.cpp @@ -1724,13 +1724,13 @@ static PHLWINDOW getWeakWindowPred(Iterator cur, Iterator end, Iterator begin, c PHLWINDOW CCompositor::getWindowCycleHist(PHLWINDOWREF cur, bool focusableOnly, std::optional floating, bool visible, bool next) { const auto FINDER = [&](const PHLWINDOWREF& w) { return isWindowAvailableForCycle(cur, w, focusableOnly, floating, visible); }; // also m_vWindowFocusHistory has reverse order, so when it is next - we need to reverse again - return next ? getWeakWindowPred(std::ranges::find(std::ranges::reverse_view(m_windowFocusHistory), cur), m_windowFocusHistory.rend(), m_windowFocusHistory.rbegin(), FINDER) : + return next ? getWeakWindowPred(std::ranges::find(m_windowFocusHistory | std::views::reverse, cur), m_windowFocusHistory.rend(), m_windowFocusHistory.rbegin(), FINDER) : getWeakWindowPred(std::ranges::find(m_windowFocusHistory, cur), m_windowFocusHistory.end(), m_windowFocusHistory.begin(), FINDER); } PHLWINDOW CCompositor::getWindowCycle(PHLWINDOW cur, bool focusableOnly, std::optional floating, bool visible, bool prev) { const auto FINDER = [&](const PHLWINDOW& w) { return isWindowAvailableForCycle(cur, w, focusableOnly, floating, visible); }; - return prev ? getWindowPred(std::ranges::find(std::ranges::reverse_view(m_windows), cur), m_windows.rend(), m_windows.rbegin(), FINDER) : + return prev ? getWindowPred(std::ranges::find(m_windows | std::views::reverse, cur), m_windows.rend(), m_windows.rbegin(), FINDER) : getWindowPred(std::ranges::find(m_windows, cur), m_windows.end(), m_windows.begin(), FINDER); } diff --git a/src/config/ConfigDataValues.hpp b/src/config/ConfigDataValues.hpp index 2fad9277..d17e7672 100644 --- a/src/config/ConfigDataValues.hpp +++ b/src/config/ConfigDataValues.hpp @@ -158,7 +158,7 @@ class CFontWeightConfigValueData : public ICustomConfigValueData { void parseWeight(const std::string& strWeight) { auto lcWeight{strWeight}; - transform(strWeight.begin(), strWeight.end(), lcWeight.begin(), ::tolower); + std::ranges::transform(strWeight, lcWeight.begin(), ::tolower); // values taken from Pango weight enums const auto WEIGHTS = std::map{ diff --git a/src/config/ConfigManager.cpp b/src/config/ConfigManager.cpp index acbc0262..3ab53a3c 100644 --- a/src/config/ConfigManager.cpp +++ b/src/config/ConfigManager.cpp @@ -1651,7 +1651,7 @@ Hyprlang::CConfigValue* CConfigManager::getHyprlangConfigValuePtr(const std::str bool CConfigManager::deviceConfigExists(const std::string& dev) { auto copy = dev; - std::replace(copy.begin(), copy.end(), ' ', '-'); + std::ranges::replace(copy, ' ', '-'); return m_config->specialCategoryExistsForKey("device", copy.c_str()); } @@ -1902,7 +1902,7 @@ static bool parseModeLine(const std::string& modeline, drmModeModeInfo& mode) { auto args = CVarList(modeline, 0, 's'); auto keyword = args[0]; - std::transform(keyword.begin(), keyword.end(), keyword.begin(), ::tolower); + std::ranges::transform(keyword, keyword.begin(), ::tolower); if (keyword != "modeline") return false; @@ -1938,7 +1938,7 @@ static bool parseModeLine(const std::string& modeline, drmModeModeInfo& mode) { for (; argno < static_cast(args.size()); argno++) { auto key = args[argno]; - std::transform(key.begin(), key.end(), key.begin(), ::tolower); + std::ranges::transform(key, key.begin(), ::tolower); auto it = flagsmap.find(key); @@ -2375,7 +2375,7 @@ std::optional CConfigManager::handleBind(const std::string& command HANDLER = "mouse"; // to lower - std::transform(HANDLER.begin(), HANDLER.end(), HANDLER.begin(), ::tolower); + std::ranges::transform(HANDLER, HANDLER.begin(), ::tolower); const auto DISPATCHER = g_pKeybindManager->m_dispatchers.find(HANDLER); @@ -2798,7 +2798,7 @@ std::optional CConfigManager::handleWorkspaceRules(const std::strin wsRule.workspaceId = id; wsRule.workspaceName = name; - const auto IT = std::find_if(m_workspaceRules.begin(), m_workspaceRules.end(), [&](const auto& other) { return other.workspaceString == wsRule.workspaceString; }); + const auto IT = std::ranges::find_if(m_workspaceRules, [&](const auto& other) { return other.workspaceString == wsRule.workspaceString; }); if (IT == m_workspaceRules.end()) m_workspaceRules.emplace_back(wsRule); @@ -2896,7 +2896,7 @@ std::optional CConfigManager::handleEnv(const std::string& command, } std::optional CConfigManager::handlePlugin(const std::string& command, const std::string& path) { - if (std::find(m_declaredPlugins.begin(), m_declaredPlugins.end(), path) != m_declaredPlugins.end()) + if (std::ranges::find(m_declaredPlugins, path) != m_declaredPlugins.end()) return "plugin '" + path + "' declared twice"; m_declaredPlugins.push_back(path); diff --git a/src/debug/HyprCtl.cpp b/src/debug/HyprCtl.cpp index adfbab1e..c8cc5c59 100644 --- a/src/debug/HyprCtl.cpp +++ b/src/debug/HyprCtl.cpp @@ -216,10 +216,10 @@ static std::string getTagsData(PHLWINDOW w, eHyprCtlOutputFormat format) { const auto tags = w->m_tags.getTags(); if (format == eHyprCtlOutputFormat::FORMAT_JSON) - return std::accumulate(tags.begin(), tags.end(), std::string(), - [](const std::string& a, const std::string& b) { return a.empty() ? std::format("\"{}\"", b) : std::format("{}, \"{}\"", a, b); }); + return std::ranges::fold_left(tags, std::string(), + [](const std::string& a, const std::string& b) { return a.empty() ? std::format("\"{}\"", b) : std::format("{}, \"{}\"", a, b); }); else - return std::accumulate(tags.begin(), tags.end(), std::string(), [](const std::string& a, const std::string& b) { return a.empty() ? b : a + ", " + b; }); + return std::ranges::fold_left(tags, std::string(), [](const std::string& a, const std::string& b) { return a.empty() ? b : a + ", " + b; }); } static std::string getGroupedData(PHLWINDOW w, eHyprCtlOutputFormat format) { @@ -921,7 +921,7 @@ static std::string bindsRequest(eHyprCtlOutputFormat format, std::string request std::string versionRequest(eHyprCtlOutputFormat format, std::string request) { auto commitMsg = trim(GIT_COMMIT_MESSAGE); - std::replace(commitMsg.begin(), commitMsg.end(), '#', ' '); + std::ranges::replace(commitMsg, '#', ' '); if (format == eHyprCtlOutputFormat::FORMAT_NORMAL) { std::string result = std::format("Hyprland {} built from branch {} at commit {} {} ({}).\n" @@ -1296,8 +1296,7 @@ static std::string switchXKBLayoutRequest(eHyprCtlOutputFormat format, std::stri } return result.empty() ? "ok" : result; } else { - auto k = std::find_if(g_pInputManager->m_keyboards.begin(), g_pInputManager->m_keyboards.end(), - [&](const auto& other) { return other->m_hlName == g_pInputManager->deviceNameToInternalString(KB); }); + auto k = std::ranges::find_if(g_pInputManager->m_keyboards, [&](const auto& other) { return other->m_hlName == g_pInputManager->deviceNameToInternalString(KB); }); if (k == g_pInputManager->m_keyboards.end()) return "device not found"; diff --git a/src/debug/HyprNotificationOverlay.cpp b/src/debug/HyprNotificationOverlay.cpp index 4e17e797..bfa5c4e4 100644 --- a/src/debug/HyprNotificationOverlay.cpp +++ b/src/debug/HyprNotificationOverlay.cpp @@ -13,7 +13,7 @@ static inline auto iconBackendFromLayout(PangoLayout* layout) { // preference: Nerd > FontAwesome > text auto eIconBackendChecks = std::array{ICONS_BACKEND_NF, ICONS_BACKEND_FA}; for (auto iconID : eIconBackendChecks) { - auto iconsText = std::accumulate(ICONS_ARRAY[iconID].begin(), ICONS_ARRAY[iconID].end(), std::string()); + auto iconsText = std::ranges::fold_left(ICONS_ARRAY[iconID], std::string(), std::plus<>()); pango_layout_set_text(layout, iconsText.c_str(), -1); if (pango_layout_get_unknown_glyphs_count(layout) == 0) return iconID; diff --git a/src/desktop/Window.cpp b/src/desktop/Window.cpp index 9f69e364..cc3c9390 100644 --- a/src/desktop/Window.cpp +++ b/src/desktop/Window.cpp @@ -1,4 +1,5 @@ #include +#include #include #include @@ -1507,7 +1508,7 @@ std::string CWindow::fetchClass() { } void CWindow::onAck(uint32_t serial) { - const auto SERIAL = std::ranges::find_if(m_pendingSizeAcks.rbegin(), m_pendingSizeAcks.rend(), [serial](const auto& e) { return e.first == serial; }); + const auto SERIAL = std::ranges::find_if(m_pendingSizeAcks | std::views::reverse, [serial](const auto& e) { return e.first == serial; }); if (SERIAL == m_pendingSizeAcks.rend()) return; diff --git a/src/devices/IKeyboard.cpp b/src/devices/IKeyboard.cpp index 597724a6..89ad8c16 100644 --- a/src/devices/IKeyboard.cpp +++ b/src/devices/IKeyboard.cpp @@ -379,7 +379,7 @@ bool IKeyboard::updateModifiersState() { void IKeyboard::updateXkbStateWithKey(uint32_t xkbKey, bool pressed) { - const auto contains = std::find(m_pressedXKB.begin(), m_pressedXKB.end(), xkbKey) != m_pressedXKB.end(); + const auto contains = std::ranges::find(m_pressedXKB, xkbKey) != m_pressedXKB.end(); if (contains && pressed) return; diff --git a/src/events/Windows.cpp b/src/events/Windows.cpp index 4bf54ca8..b019adff 100644 --- a/src/events/Windows.cpp +++ b/src/events/Windows.cpp @@ -742,7 +742,7 @@ void Events::listener_unmapWindow(void* owner, void* data) { EMIT_HOOK_EVENT("closeWindow", PWINDOW); if (PWINDOW->m_isFloating && !PWINDOW->m_isX11 && - std::any_of(PWINDOW->m_matchedRules.begin(), PWINDOW->m_matchedRules.end(), [](const auto& r) { return r->m_ruleType == CWindowRule::RULE_PERSISTENTSIZE; })) { + std::ranges::any_of(PWINDOW->m_matchedRules, [](const auto& r) { return r->m_ruleType == CWindowRule::RULE_PERSISTENTSIZE; })) { Debug::log(LOG, "storing floating size {}x{} for window {}::{} on close", PWINDOW->m_realSize->value().x, PWINDOW->m_realSize->value().y, PWINDOW->m_class, PWINDOW->m_title); g_pConfigManager->storeFloatingSize(PWINDOW, PWINDOW->m_realSize->value()); diff --git a/src/helpers/MiscFunctions.cpp b/src/helpers/MiscFunctions.cpp index ed67618e..ddd16144 100644 --- a/src/helpers/MiscFunctions.cpp +++ b/src/helpers/MiscFunctions.cpp @@ -243,7 +243,7 @@ SWorkspaceIDName getWorkspaceIDNameFromString(const std::string& in) { namedWSes.push_back(ws->m_id); } - std::sort(namedWSes.begin(), namedWSes.end()); + std::ranges::sort(namedWSes); if (absolute) { // 1-index @@ -388,7 +388,7 @@ SWorkspaceIDName getWorkspaceIDNameFromString(const std::string& in) { validWSes.push_back(ws->m_id); } - std::sort(validWSes.begin(), validWSes.end()); + std::ranges::sort(validWSes); ssize_t currentItem = -1; @@ -623,7 +623,7 @@ std::expected configStringToInt(const std::string& VALUE) const auto VALUEWITHOUTFUNC = trim(VALUE.substr(5, VALUE.length() - 6)); // try doing it the comma way first - if (std::count(VALUEWITHOUTFUNC.begin(), VALUEWITHOUTFUNC.end(), ',') == 3) { + if (std::ranges::count(VALUEWITHOUTFUNC, ',') == 3) { // cool std::string rolling = VALUEWITHOUTFUNC; auto r = configStringToInt(trim(rolling.substr(0, rolling.find(',')))); @@ -657,7 +657,7 @@ std::expected configStringToInt(const std::string& VALUE) const auto VALUEWITHOUTFUNC = trim(VALUE.substr(4, VALUE.length() - 5)); // try doing it the comma way first - if (std::count(VALUEWITHOUTFUNC.begin(), VALUEWITHOUTFUNC.end(), ',') == 2) { + if (std::ranges::count(VALUEWITHOUTFUNC, ',') == 2) { // cool std::string rolling = VALUEWITHOUTFUNC; auto r = configStringToInt(trim(rolling.substr(0, rolling.find(',')))); diff --git a/src/helpers/Monitor.cpp b/src/helpers/Monitor.cpp index d7536a39..5afd0123 100644 --- a/src/helpers/Monitor.cpp +++ b/src/helpers/Monitor.cpp @@ -32,6 +32,8 @@ #include #include #include +#include +#include using namespace Hyprutils::String; using namespace Hyprutils::Utils; @@ -189,7 +191,7 @@ void CMonitor::onConnect(bool noRule) { RASSERT(thisWrapper->get(), "CMonitor::onConnect: Had no wrapper???"); - if (std::find_if(g_pCompositor->m_monitors.begin(), g_pCompositor->m_monitors.end(), [&](auto& other) { return other.get() == this; }) == g_pCompositor->m_monitors.end()) + if (std::ranges::find_if(g_pCompositor->m_monitors, [&](auto& other) { return other.get() == this; }) == g_pCompositor->m_monitors.end()) g_pCompositor->m_monitors.push_back(*thisWrapper); m_enabled = true; @@ -320,7 +322,7 @@ void CMonitor::onDisconnect(bool destroy) { // remove mirror if (m_mirrorOf) { - m_mirrorOf->m_mirrors.erase(std::find_if(m_mirrorOf->m_mirrors.begin(), m_mirrorOf->m_mirrors.end(), [&](const auto& other) { return other == m_self; })); + m_mirrorOf->m_mirrors.erase(std::ranges::find_if(m_mirrorOf->m_mirrors, [&](const auto& other) { return other == m_self; })); // unlock software for mirrored monitor g_pPointerManager->unlockSoftwareForMonitor(m_mirrorOf.lock()); @@ -486,7 +488,7 @@ bool CMonitor::applyMonitorRule(SMonitorRule* pMonitorRule, bool force) { std::ranges::sort(sortedModes, sortFunc); if (sortedModes.size() > 3) sortedModes.erase(sortedModes.begin() + 3, sortedModes.end()); - requestedModes.insert(requestedModes.end(), sortedModes.rbegin(), sortedModes.rend()); + requestedModes.insert_range(requestedModes.end(), sortedModes | std::views::reverse); }; // last fallback is always preferred mode @@ -1019,7 +1021,7 @@ void CMonitor::setMirror(const std::string& mirrorOf) { // disable mirroring if (m_mirrorOf) { - m_mirrorOf->m_mirrors.erase(std::find_if(m_mirrorOf->m_mirrors.begin(), m_mirrorOf->m_mirrors.end(), [&](const auto& other) { return other == m_self; })); + m_mirrorOf->m_mirrors.erase(std::ranges::find_if(m_mirrorOf->m_mirrors, [&](const auto& other) { return other == m_self; })); // unlock software for mirrored monitor g_pPointerManager->unlockSoftwareForMonitor(m_mirrorOf.lock()); @@ -1046,7 +1048,7 @@ void CMonitor::setMirror(const std::string& mirrorOf) { RASSERT(thisWrapper->get(), "CMonitor::setMirror: Had no wrapper???"); - if (std::find_if(g_pCompositor->m_monitors.begin(), g_pCompositor->m_monitors.end(), [&](auto& other) { return other.get() == this; }) == g_pCompositor->m_monitors.end()) { + if (std::ranges::find_if(g_pCompositor->m_monitors, [&](auto& other) { return other.get() == this; }) == g_pCompositor->m_monitors.end()) { g_pCompositor->m_monitors.push_back(*thisWrapper); } diff --git a/src/hyprerror/HyprError.cpp b/src/hyprerror/HyprError.cpp index 614fdd2e..22744c93 100644 --- a/src/hyprerror/HyprError.cpp +++ b/src/hyprerror/HyprError.cpp @@ -63,7 +63,7 @@ void CHyprError::createQueued() { cairo_paint(CAIRO); cairo_restore(CAIRO); - const auto LINECOUNT = Hyprlang::INT{1} + std::count(m_queued.begin(), m_queued.end(), '\n'); + const auto LINECOUNT = Hyprlang::INT{1} + std::ranges::count(m_queued, '\n'); static auto LINELIMIT = CConfigValue("debug:error_limit"); static auto BAR_POSITION = CConfigValue("debug:error_position"); diff --git a/src/layout/MasterLayout.cpp b/src/layout/MasterLayout.cpp index 065dcdc2..cb1313a8 100644 --- a/src/layout/MasterLayout.cpp +++ b/src/layout/MasterLayout.cpp @@ -94,7 +94,7 @@ void CHyprMasterLayout::onWindowCreatedTiling(PHLWINDOW pWindow, eDirection dire if (*PNEWONACTIVE != "none" && !BNEWISMASTER) { const auto pLastNode = getNodeFromWindow(g_pCompositor->m_lastWindow.lock()); if (pLastNode && !(pLastNode->isMaster && (getMastersOnWorkspace(pWindow->workspaceID()) == 1 || *PNEWSTATUS == "slave"))) { - auto it = std::find(m_masterNodesData.begin(), m_masterNodesData.end(), *pLastNode); + auto it = std::ranges::find(m_masterNodesData, *pLastNode); if (!BNEWBEFOREACTIVE) ++it; return &(*m_masterNodesData.emplace(it)); @@ -117,7 +117,7 @@ void CHyprMasterLayout::onWindowCreatedTiling(PHLWINDOW pWindow, eDirection dire const auto MOUSECOORDS = g_pInputManager->getMouseCoordsInternal(); static auto PDROPATCURSOR = CConfigValue("master:drop_at_cursor"); eOrientation orientation = getDynamicOrientation(pWindow->m_workspace); - const auto NODEIT = std::find(m_masterNodesData.begin(), m_masterNodesData.end(), *PNODE); + const auto NODEIT = std::ranges::find(m_masterNodesData, *PNODE); bool forceDropAsMaster = false; // if dragging window to move, drop it at the cursor position instead of bottom/top of stack @@ -804,8 +804,8 @@ void CHyprMasterLayout::resizeActiveWindow(const Vector2D& pixResize, eRectCorne if (!*PSMARTRESIZING) { PNODE->percSize = std::clamp(PNODE->percSize + RESIZEDELTA / SIZE, 0.05, 1.95); } else { - const auto NODEIT = std::find(m_masterNodesData.begin(), m_masterNodesData.end(), *PNODE); - const auto REVNODEIT = std::find(m_masterNodesData.rbegin(), m_masterNodesData.rend(), *PNODE); + const auto NODEIT = std::ranges::find(m_masterNodesData, *PNODE); + const auto REVNODEIT = std::ranges::find(m_masterNodesData | std::views::reverse, *PNODE); const float totalSize = isStackVertical ? WSSIZE.y : WSSIZE.x; const float minSize = totalSize / nodesInSameColumn * 0.2; @@ -1026,16 +1026,15 @@ PHLWINDOW CHyprMasterLayout::getNextWindow(PHLWINDOW pWindow, bool next, bool lo auto nodes = m_masterNodesData; if (!next) - std::reverse(nodes.begin(), nodes.end()); + std::ranges::reverse(nodes); - const auto NODEIT = std::find(nodes.begin(), nodes.end(), *PNODE); + const auto NODEIT = std::ranges::find(nodes, *PNODE); const bool ISMASTER = PNODE->isMaster; auto CANDIDATE = std::find_if(NODEIT, nodes.end(), [&](const auto& other) { return other != *PNODE && ISMASTER == other.isMaster && other.workspaceID == PNODE->workspaceID; }); if (CANDIDATE == nodes.end()) - CANDIDATE = - std::find_if(nodes.begin(), nodes.end(), [&](const auto& other) { return other != *PNODE && ISMASTER != other.isMaster && other.workspaceID == PNODE->workspaceID; }); + CANDIDATE = std::ranges::find_if(nodes, [&](const auto& other) { return other != *PNODE && ISMASTER != other.isMaster && other.workspaceID == PNODE->workspaceID; }); if (CANDIDATE != nodes.end() && !loop) { if (CANDIDATE->isMaster && next) @@ -1308,12 +1307,12 @@ std::any CHyprMasterLayout::layoutMessage(SLayoutMessageHeader header, std::stri if (!OLDMASTER) return 0; - const auto OLDMASTERIT = std::find(m_masterNodesData.begin(), m_masterNodesData.end(), *OLDMASTER); + const auto OLDMASTERIT = std::ranges::find(m_masterNodesData, *OLDMASTER); for (auto& nd : m_masterNodesData) { if (nd.workspaceID == PNODE->workspaceID && !nd.isMaster) { nd.isMaster = true; - const auto NEWMASTERIT = std::find(m_masterNodesData.begin(), m_masterNodesData.end(), nd); + const auto NEWMASTERIT = std::ranges::find(m_masterNodesData, nd); m_masterNodesData.splice(OLDMASTERIT, m_masterNodesData, NEWMASTERIT); switchToWindow(nd.pWindow.lock()); OLDMASTER->isMaster = false; @@ -1334,12 +1333,12 @@ std::any CHyprMasterLayout::layoutMessage(SLayoutMessageHeader header, std::stri if (!OLDMASTER) return 0; - const auto OLDMASTERIT = std::find(m_masterNodesData.begin(), m_masterNodesData.end(), *OLDMASTER); + const auto OLDMASTERIT = std::ranges::find(m_masterNodesData, *OLDMASTER); for (auto& nd : m_masterNodesData | std::views::reverse) { if (nd.workspaceID == PNODE->workspaceID && !nd.isMaster) { nd.isMaster = true; - const auto NEWMASTERIT = std::find(m_masterNodesData.begin(), m_masterNodesData.end(), nd); + const auto NEWMASTERIT = std::ranges::find(m_masterNodesData, nd); m_masterNodesData.splice(OLDMASTERIT, m_masterNodesData, NEWMASTERIT); switchToWindow(nd.pWindow.lock()); OLDMASTER->isMaster = false; diff --git a/src/managers/AnimationManager.cpp b/src/managers/AnimationManager.cpp index d12b91a5..f935d3dc 100644 --- a/src/managers/AnimationManager.cpp +++ b/src/managers/AnimationManager.cpp @@ -384,7 +384,7 @@ void CHyprAnimationManager::onWindowPostCreateClose(PHLWINDOW pWindow, bool clos } std::string ANIMSTYLE = pWindow->m_realPosition->getStyle(); - transform(ANIMSTYLE.begin(), ANIMSTYLE.end(), ANIMSTYLE.begin(), ::tolower); + std::ranges::transform(ANIMSTYLE, ANIMSTYLE.begin(), ::tolower); CVarList animList(ANIMSTYLE, 0, 's'); diff --git a/src/managers/CursorManager.cpp b/src/managers/CursorManager.cpp index 77ea5a28..9211fc20 100644 --- a/src/managers/CursorManager.cpp +++ b/src/managers/CursorManager.cpp @@ -186,7 +186,7 @@ void CCursorManager::setCursorFromName(const std::string& name) { if (m_currentCursorShapeData.images.size() < 1) { // try with '_' first (old hc, etc) std::string newName = name; - std::replace(newName.begin(), newName.end(), '-', '_'); + std::ranges::replace(newName, '-', '_'); m_currentCursorShapeData = m_hyprcursor->getShape(newName.c_str(), m_currentStyleInfo); } diff --git a/src/managers/EventManager.cpp b/src/managers/EventManager.cpp index 651bf436..e0d8704b 100644 --- a/src/managers/EventManager.cpp +++ b/src/managers/EventManager.cpp @@ -123,7 +123,7 @@ int CEventManager::onClientEvent(int fd, uint32_t mask) { } std::vector::iterator CEventManager::findClientByFD(int fd) { - return std::find_if(m_clients.begin(), m_clients.end(), [fd](const auto& client) { return client.fd.get() == fd; }); + return std::ranges::find_if(m_clients, [fd](const auto& client) { return client.fd.get() == fd; }); } std::vector::iterator CEventManager::removeClientByFD(int fd) { diff --git a/src/managers/HookSystemManager.cpp b/src/managers/HookSystemManager.cpp index 67e6e732..2f1f3a27 100644 --- a/src/managers/HookSystemManager.cpp +++ b/src/managers/HookSystemManager.cpp @@ -46,7 +46,7 @@ void CHookSystemManager::emit(std::vector* const callbacks, SCal m_currentEventPlugin = true; - if (std::find(faultyHandles.begin(), faultyHandles.end(), cb.handle) != faultyHandles.end()) + if (std::ranges::find(faultyHandles, cb.handle) != faultyHandles.end()) continue; try { diff --git a/src/managers/KeybindManager.cpp b/src/managers/KeybindManager.cpp index c4c6d4ab..58951281 100644 --- a/src/managers/KeybindManager.cpp +++ b/src/managers/KeybindManager.cpp @@ -225,7 +225,7 @@ void CKeybindManager::removeKeybind(uint32_t mod, const SParsedKey& key) { uint32_t CKeybindManager::stringToModMask(std::string mods) { uint32_t modMask = 0; - std::transform(mods.begin(), mods.end(), mods.begin(), ::toupper); + std::ranges::transform(mods, mods.begin(), ::toupper); if (mods.contains("SHIFT")) modMask |= HL_MODIFIER_SHIFT; if (mods.contains("CAPS")) @@ -624,10 +624,8 @@ eMultiKeyCase CKeybindManager::mkKeysymSetMatches(const std::set k std::set boundKeysNotPressed; std::set pressedKeysNotBound; - std::set_difference(keybindKeysyms.begin(), keybindKeysyms.end(), pressedKeysyms.begin(), pressedKeysyms.end(), - std::inserter(boundKeysNotPressed, boundKeysNotPressed.begin())); - std::set_difference(pressedKeysyms.begin(), pressedKeysyms.end(), keybindKeysyms.begin(), keybindKeysyms.end(), - std::inserter(pressedKeysNotBound, pressedKeysNotBound.begin())); + std::ranges::set_difference(keybindKeysyms, pressedKeysyms, std::inserter(boundKeysNotPressed, boundKeysNotPressed.begin())); + std::ranges::set_difference(pressedKeysyms, keybindKeysyms, std::inserter(pressedKeysNotBound, pressedKeysNotBound.begin())); if (boundKeysNotPressed.empty() && pressedKeysNotBound.empty()) return MK_FULL_MATCH; @@ -670,8 +668,7 @@ SDispatchResult CKeybindManager::handleKeybinds(const uint32_t modmask, const SP for (auto& k : m_keybinds) { const bool SPECIALDISPATCHER = k->handler == "global" || k->handler == "pass" || k->handler == "sendshortcut" || k->handler == "mouse"; - const bool SPECIALTRIGGERED = - std::find_if(m_pressedSpecialBinds.begin(), m_pressedSpecialBinds.end(), [&](const auto& other) { return other == k; }) != m_pressedSpecialBinds.end(); + const bool SPECIALTRIGGERED = std::ranges::find_if(m_pressedSpecialBinds, [&](const auto& other) { return other == k; }) != m_pressedSpecialBinds.end(); const bool IGNORECONDITIONS = SPECIALDISPATCHER && !pressed && SPECIALTRIGGERED; // ignore mods. Pass, global dispatchers should be released immediately once the key is released. @@ -1106,7 +1103,7 @@ SDispatchResult CKeybindManager::signalWindow(std::string args) { return {.success = false, .error = "signalWindow: no window"}; } - if (!std::all_of(SIGNAL.begin(), SIGNAL.end(), ::isdigit)) + if (!std::ranges::all_of(SIGNAL, ::isdigit)) return {.success = false, .error = "signalWindow: signal has to be int"}; try { diff --git a/src/managers/LayoutManager.cpp b/src/managers/LayoutManager.cpp index a929b42e..08bbcf44 100644 --- a/src/managers/LayoutManager.cpp +++ b/src/managers/LayoutManager.cpp @@ -26,7 +26,7 @@ void CLayoutManager::switchToLayout(std::string layout) { } bool CLayoutManager::addLayout(const std::string& name, IHyprLayout* layout) { - if (std::find_if(m_layouts.begin(), m_layouts.end(), [&](const auto& other) { return other.first == name || other.second == layout; }) != m_layouts.end()) + if (std::ranges::find_if(m_layouts, [&](const auto& other) { return other.first == name || other.second == layout; }) != m_layouts.end()) return false; m_layouts.emplace_back(std::make_pair<>(name, layout)); @@ -37,7 +37,7 @@ bool CLayoutManager::addLayout(const std::string& name, IHyprLayout* layout) { } bool CLayoutManager::removeLayout(IHyprLayout* layout) { - const auto IT = std::find_if(m_layouts.begin(), m_layouts.end(), [&](const auto& other) { return other.second == layout; }); + const auto IT = std::ranges::find_if(m_layouts, [&](const auto& other) { return other.second == layout; }); if (IT == m_layouts.end() || IT->first == "dwindle" || IT->first == "master") return false; diff --git a/src/managers/PointerManager.cpp b/src/managers/PointerManager.cpp index f42fd686..a82be1b0 100644 --- a/src/managers/PointerManager.cpp +++ b/src/managers/PointerManager.cpp @@ -94,7 +94,7 @@ bool CPointerManager::hasCursor() { } SP CPointerManager::stateFor(PHLMONITOR mon) { - auto it = std::find_if(m_monitorStates.begin(), m_monitorStates.end(), [mon](const auto& other) { return other->monitor == mon; }); + auto it = std::ranges::find_if(m_monitorStates, [mon](const auto& other) { return other->monitor == mon; }); if (it == m_monitorStates.end()) return m_monitorStates.emplace_back(makeShared(mon)); return *it; diff --git a/src/managers/SeatManager.cpp b/src/managers/SeatManager.cpp index 419e8bf4..a7660854 100644 --- a/src/managers/SeatManager.cpp +++ b/src/managers/SeatManager.cpp @@ -653,7 +653,7 @@ void CSeatManager::resendEnterEvents() { } bool CSeatGrab::accepts(SP surf) { - return std::find(m_surfs.begin(), m_surfs.end(), surf) != m_surfs.end(); + return std::ranges::find(m_surfs, surf) != m_surfs.end(); } void CSeatGrab::add(SP surf) { diff --git a/src/managers/XCursorManager.cpp b/src/managers/XCursorManager.cpp index 79bb7a5d..9bbf531b 100644 --- a/src/managers/XCursorManager.cpp +++ b/src/managers/XCursorManager.cpp @@ -127,8 +127,8 @@ void CXCursorManager::loadTheme(std::string const& name, int size, float scale) for (auto const& p : paths) { try { auto dirCursors = loadAllFromDir(p, m_lastLoadSize); - std::copy_if(dirCursors.begin(), dirCursors.end(), std::back_inserter(m_cursors), - [this](auto const& p) { return std::none_of(m_cursors.begin(), m_cursors.end(), [&p](auto const& dp) { return dp->shape == p->shape; }); }); + std::ranges::copy_if(dirCursors, std::back_inserter(m_cursors), + [this](auto const& p) { return std::ranges::none_of(m_cursors, [&p](auto const& dp) { return dp->shape == p->shape; }); }); } catch (std::exception& e) { Debug::log(ERR, "XCursor path {} can't be loaded: threw error {}", p, e.what()); } } } @@ -144,14 +144,14 @@ void CXCursorManager::loadTheme(std::string const& name, int size, float scale) if (legacyName.empty()) continue; - auto it = std::find_if(m_cursors.begin(), m_cursors.end(), [&legacyName](auto const& c) { return c->shape == legacyName; }); + auto it = std::ranges::find_if(m_cursors, [&legacyName](auto const& c) { return c->shape == legacyName; }); if (it == m_cursors.end()) { Debug::log(LOG, "XCursor failed to find a legacy shape with name {}, skipping", legacyName); continue; } - if (std::any_of(m_cursors.begin(), m_cursors.end(), [&shape](auto const& dp) { return dp->shape == shape; })) { + if (std::ranges::any_of(m_cursors, [&shape](auto const& dp) { return dp->shape == shape; })) { Debug::log(LOG, "XCursor already has a shape {} loaded, skipping", shape); continue; } diff --git a/src/managers/input/InputManager.cpp b/src/managers/input/InputManager.cpp index 2d50dbcf..cc0485d8 100644 --- a/src/managers/input/InputManager.cpp +++ b/src/managers/input/InputManager.cpp @@ -619,7 +619,7 @@ void CInputManager::onMouseButton(IPointer::SButtonEvent e) { if (e.state == WL_POINTER_BUTTON_STATE_PRESSED) { m_currentlyHeldButtons.push_back(e.button); } else { - if (std::find_if(m_currentlyHeldButtons.begin(), m_currentlyHeldButtons.end(), [&](const auto& other) { return other == e.button; }) == m_currentlyHeldButtons.end()) + if (std::ranges::find_if(m_currentlyHeldButtons, [&](const auto& other) { return other == e.button; }) == m_currentlyHeldButtons.end()) return; std::erase_if(m_currentlyHeldButtons, [&](const auto& other) { return other == e.button; }); } @@ -1552,7 +1552,7 @@ void CInputManager::unconstrainMouse() { } bool CInputManager::isConstrained() { - return std::any_of(m_constraints.begin(), m_constraints.end(), [](auto const& c) { + return std::ranges::any_of(m_constraints, [](auto const& c) { const auto constraint = c.lock(); return constraint && constraint->isActive() && constraint->owner()->resource() == g_pCompositor->m_lastFocus; }); @@ -1773,9 +1773,9 @@ void CInputManager::unsetCursorImage() { } std::string CInputManager::deviceNameToInternalString(std::string in) { - std::replace(in.begin(), in.end(), ' ', '-'); - std::replace(in.begin(), in.end(), '\n', '-'); - std::transform(in.begin(), in.end(), in.begin(), ::tolower); + std::ranges::replace(in, ' ', '-'); + std::ranges::replace(in, '\n', '-'); + std::ranges::transform(in, in.begin(), ::tolower); return in; } @@ -1786,7 +1786,7 @@ std::string CInputManager::getNameForNewDevice(std::string internalName) { auto makeNewName = [&]() { return (proposedNewName.empty() ? "unknown-device" : proposedNewName) + (dupeno == 0 ? "" : ("-" + std::to_string(dupeno))); }; - while (std::find_if(m_hids.begin(), m_hids.end(), [&](const auto& other) { return other->m_hlName == makeNewName(); }) != m_hids.end()) + while (std::ranges::find_if(m_hids, [&](const auto& other) { return other->m_hlName == makeNewName(); }) != m_hids.end()) dupeno++; return makeNewName(); diff --git a/src/protocols/AlphaModifier.cpp b/src/protocols/AlphaModifier.cpp index e2408397..ad4bc107 100644 --- a/src/protocols/AlphaModifier.cpp +++ b/src/protocols/AlphaModifier.cpp @@ -81,7 +81,7 @@ void CAlphaModifierProtocol::destroyAlphaModifier(CAlphaModifier* modifier) { void CAlphaModifierProtocol::getSurface(CWpAlphaModifierV1* manager, uint32_t id, SP surface) { CAlphaModifier* alphaModifier = nullptr; - auto iter = std::find_if(m_alphaModifiers.begin(), m_alphaModifiers.end(), [&](const auto& entry) { return entry.second->m_surface == surface; }); + auto iter = std::ranges::find_if(m_alphaModifiers, [&](const auto& entry) { return entry.second->m_surface == surface; }); if (iter != m_alphaModifiers.end()) { if (iter->second->m_resource) { diff --git a/src/protocols/ColorManagement.cpp b/src/protocols/ColorManagement.cpp index 5ace1f7e..50bded7f 100644 --- a/src/protocols/ColorManagement.cpp +++ b/src/protocols/ColorManagement.cpp @@ -281,8 +281,8 @@ CColorManagementSurface::CColorManagementSurface(SP return; } - const auto imageDescription = std::find_if(PROTO::colorManagement->m_imageDescriptions.begin(), PROTO::colorManagement->m_imageDescriptions.end(), - [&](const auto& other) { return other->resource()->resource() == image_description; }); + const auto imageDescription = + std::ranges::find_if(PROTO::colorManagement->m_imageDescriptions, [&](const auto& other) { return other->resource()->resource() == image_description; }); if (imageDescription == PROTO::colorManagement->m_imageDescriptions.end()) { r->error(WP_COLOR_MANAGEMENT_SURFACE_V1_ERROR_IMAGE_DESCRIPTION, "Image description not found"); return; diff --git a/src/protocols/DRMLease.cpp b/src/protocols/DRMLease.cpp index c4b5a84a..622c907c 100644 --- a/src/protocols/DRMLease.cpp +++ b/src/protocols/DRMLease.cpp @@ -96,7 +96,7 @@ CDRMLeaseRequestResource::CDRMLeaseRequestResource(SP reso auto CONNECTOR = CDRMLeaseConnectorResource::fromResource(conn); - if (std::find(m_requested.begin(), m_requested.end(), CONNECTOR) != m_requested.end()) { + if (std::ranges::find(m_requested, CONNECTOR) != m_requested.end()) { m_resource->error(WP_DRM_LEASE_REQUEST_V1_ERROR_DUPLICATE_CONNECTOR, "Connector already requested"); return; } @@ -208,7 +208,7 @@ bool CDRMLeaseDeviceResource::good() { } void CDRMLeaseDeviceResource::sendConnector(PHLMONITOR monitor) { - if (std::find_if(m_connectorsSent.begin(), m_connectorsSent.end(), [monitor](const auto& e) { return e && !e->m_dead && e->m_monitor == monitor; }) != m_connectorsSent.end()) + if (std::ranges::find_if(m_connectorsSent, [monitor](const auto& e) { return e && !e->m_dead && e->m_monitor == monitor; }) != m_connectorsSent.end()) return; auto RESOURCE = makeShared(makeShared(m_resource->client(), m_resource->version(), 0), monitor); @@ -294,7 +294,7 @@ void CDRMLeaseProtocol::destroyResource(CDRMLeaseResource* resource) { void CDRMLeaseProtocol::offer(PHLMONITOR monitor) { std::erase_if(m_primaryDevice->m_offeredOutputs, [](const auto& e) { return e.expired(); }); - if (std::find(m_primaryDevice->m_offeredOutputs.begin(), m_primaryDevice->m_offeredOutputs.end(), monitor) != m_primaryDevice->m_offeredOutputs.end()) + if (std::ranges::find(m_primaryDevice->m_offeredOutputs, monitor) != m_primaryDevice->m_offeredOutputs.end()) return; if (monitor->m_output->getBackend()->type() != Aquamarine::AQ_BACKEND_DRM) diff --git a/src/protocols/DataDeviceWlr.cpp b/src/protocols/DataDeviceWlr.cpp index 2e9c032b..e169f666 100644 --- a/src/protocols/DataDeviceWlr.cpp +++ b/src/protocols/DataDeviceWlr.cpp @@ -78,7 +78,7 @@ std::vector CWLRDataSource::mimes() { } void CWLRDataSource::send(const std::string& mime, CFileDescriptor fd) { - if (std::find(m_mimeTypes.begin(), m_mimeTypes.end(), mime) == m_mimeTypes.end()) { + if (std::ranges::find(m_mimeTypes, mime) == m_mimeTypes.end()) { LOGM(ERR, "Compositor/App bug: CWLRDataSource::sendAskSend with non-existent mime"); return; } @@ -87,7 +87,7 @@ void CWLRDataSource::send(const std::string& mime, CFileDescriptor fd) { } void CWLRDataSource::accepted(const std::string& mime) { - if (std::find(m_mimeTypes.begin(), m_mimeTypes.end(), mime) == m_mimeTypes.end()) + if (std::ranges::find(m_mimeTypes, mime) == m_mimeTypes.end()) LOGM(ERR, "Compositor/App bug: CWLRDataSource::sendAccepted with non-existent mime"); // wlr has no accepted @@ -315,7 +315,7 @@ void CDataDeviceWLRProtocol::setSelection(SP source, bool primary) } SP CDataDeviceWLRProtocol::dataDeviceForClient(wl_client* c) { - auto it = std::find_if(m_devices.begin(), m_devices.end(), [c](const auto& e) { return e->client() == c; }); + auto it = std::ranges::find_if(m_devices, [c](const auto& e) { return e->client() == c; }); if (it == m_devices.end()) return nullptr; return *it; diff --git a/src/protocols/FocusGrab.cpp b/src/protocols/FocusGrab.cpp index 9f054953..41396459 100644 --- a/src/protocols/FocusGrab.cpp +++ b/src/protocols/FocusGrab.cpp @@ -36,7 +36,7 @@ bool CFocusGrab::good() { } bool CFocusGrab::isSurfaceComitted(SP surface) { - auto iter = std::find_if(m_surfaces.begin(), m_surfaces.end(), [surface](const auto& o) { return o.first == surface; }); + auto iter = std::ranges::find_if(m_surfaces, [surface](const auto& o) { return o.first == surface; }); if (iter == m_surfaces.end()) return false; @@ -70,7 +70,7 @@ void CFocusGrab::finish(bool sendCleared) { } void CFocusGrab::addSurface(SP surface) { - auto iter = std::find_if(m_surfaces.begin(), m_surfaces.end(), [surface](const auto& e) { return e.first == surface; }); + auto iter = std::ranges::find_if(m_surfaces, [surface](const auto& e) { return e.first == surface; }); if (iter == m_surfaces.end()) m_surfaces.emplace(surface, makeUnique(this, surface)); } diff --git a/src/protocols/ForeignToplevel.cpp b/src/protocols/ForeignToplevel.cpp index e48f0722..ec5943af 100644 --- a/src/protocols/ForeignToplevel.cpp +++ b/src/protocols/ForeignToplevel.cpp @@ -69,7 +69,7 @@ void CForeignToplevelList::onMap(PHLWINDOW pWindow) { SP CForeignToplevelList::handleForWindow(PHLWINDOW pWindow) { std::erase_if(m_handles, [](const auto& wp) { return wp.expired(); }); - const auto IT = std::find_if(m_handles.begin(), m_handles.end(), [pWindow](const auto& h) { return h->window() == pWindow; }); + const auto IT = std::ranges::find_if(m_handles, [pWindow](const auto& h) { return h->window() == pWindow; }); return IT == m_handles.end() ? SP{} : IT->lock(); } diff --git a/src/protocols/ForeignToplevelWlr.cpp b/src/protocols/ForeignToplevelWlr.cpp index dccf83b6..600412cb 100644 --- a/src/protocols/ForeignToplevelWlr.cpp +++ b/src/protocols/ForeignToplevelWlr.cpp @@ -247,7 +247,7 @@ void CForeignToplevelWlrManager::onMap(PHLWINDOW pWindow) { SP CForeignToplevelWlrManager::handleForWindow(PHLWINDOW pWindow) { std::erase_if(m_handles, [](const auto& wp) { return wp.expired(); }); - const auto IT = std::find_if(m_handles.begin(), m_handles.end(), [pWindow](const auto& h) { return h->window() == pWindow; }); + const auto IT = std::ranges::find_if(m_handles, [pWindow](const auto& h) { return h->window() == pWindow; }); return IT == m_handles.end() ? SP{} : IT->lock(); } diff --git a/src/protocols/HyprlandSurface.cpp b/src/protocols/HyprlandSurface.cpp index 9c66fba4..2e386027 100644 --- a/src/protocols/HyprlandSurface.cpp +++ b/src/protocols/HyprlandSurface.cpp @@ -109,7 +109,7 @@ void CHyprlandSurfaceProtocol::destroySurface(CHyprlandSurface* surface) { void CHyprlandSurfaceProtocol::getSurface(CHyprlandSurfaceManagerV1* manager, uint32_t id, SP surface) { CHyprlandSurface* hyprlandSurface = nullptr; - auto iter = std::find_if(m_surfaces.begin(), m_surfaces.end(), [&](const auto& entry) { return entry.second->m_surface == surface; }); + auto iter = std::ranges::find_if(m_surfaces, [&](const auto& entry) { return entry.second->m_surface == surface; }); if (iter != m_surfaces.end()) { if (iter->second->m_resource) { diff --git a/src/protocols/LayerShell.cpp b/src/protocols/LayerShell.cpp index 4cb37ff4..bb5480b6 100644 --- a/src/protocols/LayerShell.cpp +++ b/src/protocols/LayerShell.cpp @@ -130,7 +130,7 @@ CLayerShellResource::CLayerShellResource(SP resource_, SPsetAckConfigure([this](CZwlrLayerSurfaceV1* r, uint32_t serial) { - auto serialFound = std::find_if(m_serials.begin(), m_serials.end(), [serial](const auto& e) { return e.first == serial; }); + auto serialFound = std::ranges::find_if(m_serials, [serial](const auto& e) { return e.first == serial; }); if (serialFound == m_serials.end()) { r->error(ZWLR_LAYER_SURFACE_V1_ERROR_INVALID_SURFACE_STATE, "Serial invalid in ack_configure"); diff --git a/src/protocols/LinuxDMABUF.cpp b/src/protocols/LinuxDMABUF.cpp index ee64415b..a0fe571a 100644 --- a/src/protocols/LinuxDMABUF.cpp +++ b/src/protocols/LinuxDMABUF.cpp @@ -46,8 +46,7 @@ CDMABUFFormatTable::CDMABUFFormatTable(SDMABUFTranche _rendererTranche, std::vec }); } else { // if it wasn't inserted then find its index in vec - auto it = - std::find_if(formatsVec.begin(), formatsVec.end(), [fmt, mod](const SDMABUFFormatTableEntry& oth) { return oth.fmt == fmt.drmFormat && oth.modifier == mod; }); + auto it = std::ranges::find_if(formatsVec, [fmt, mod](const SDMABUFFormatTableEntry& oth) { return oth.fmt == fmt.drmFormat && oth.modifier == mod; }); m_rendererTranche.indicies.push_back(it - formatsVec.begin()); } } @@ -69,8 +68,7 @@ CDMABUFFormatTable::CDMABUFFormatTable(SDMABUFTranche _rendererTranche, std::vec .modifier = mod, }); } else { - auto it = std::find_if(formatsVec.begin(), formatsVec.end(), - [fmt, mod](const SDMABUFFormatTableEntry& oth) { return oth.fmt == fmt.drmFormat && oth.modifier == mod; }); + auto it = std::ranges::find_if(formatsVec, [fmt, mod](const SDMABUFFormatTableEntry& oth) { return oth.fmt == fmt.drmFormat && oth.modifier == mod; }); tranche.indicies.push_back(it - formatsVec.begin()); } } @@ -89,7 +87,7 @@ CDMABUFFormatTable::CDMABUFFormatTable(SDMABUFTranche _rendererTranche, std::vec return; } - std::copy(formatsVec.begin(), formatsVec.end(), arr); + std::ranges::copy(formatsVec, arr); munmap(arr, m_tableSize); @@ -169,7 +167,7 @@ CLinuxDMABUFParamsResource::CLinuxDMABUFParamsResource(SPsize = {w, h}; m_attrs->format = fmt; - m_attrs->planes = 4 - std::count(m_attrs->fds.begin(), m_attrs->fds.end(), -1); + m_attrs->planes = 4 - std::ranges::count(m_attrs->fds, -1); create(0); }); @@ -188,7 +186,7 @@ CLinuxDMABUFParamsResource::CLinuxDMABUFParamsResource(SPsize = {w, h}; m_attrs->format = fmt; - m_attrs->planes = 4 - std::count(m_attrs->fds.begin(), m_attrs->fds.end(), -1); + m_attrs->planes = 4 - std::ranges::count(m_attrs->fds, -1); create(id); }); @@ -564,8 +562,8 @@ void CLinuxDMABufV1Protocol::updateScanoutTranche(SP surface return; } - const auto& monitorTranchePair = std::find_if(m_formatTable->m_monitorTranches.begin(), m_formatTable->m_monitorTranches.end(), - [pMonitor](std::pair pair) { return pair.first == pMonitor; }); + const auto& monitorTranchePair = + std::ranges::find_if(m_formatTable->m_monitorTranches, [pMonitor](std::pair pair) { return pair.first == pMonitor; }); if (monitorTranchePair == m_formatTable->m_monitorTranches.end()) { LOGM(LOG, "updateScanoutTranche: monitor has no tranche"); diff --git a/src/protocols/PointerConstraints.cpp b/src/protocols/PointerConstraints.cpp index 425a983d..ea917932 100644 --- a/src/protocols/PointerConstraints.cpp +++ b/src/protocols/PointerConstraints.cpp @@ -229,7 +229,7 @@ void CPointerConstraintsProtocol::onNewConstraint(SP constra const auto OWNER = constraint->owner(); - const auto DUPES = std::count_if(m_constraints.begin(), m_constraints.end(), [OWNER](const auto& c) { return c->owner() == OWNER; }); + const auto DUPES = std::ranges::count_if(m_constraints, [OWNER](const auto& c) { return c->owner() == OWNER; }); if UNLIKELY (DUPES > 1) { LOGM(ERR, "Constraint for surface duped"); diff --git a/src/protocols/PrimarySelection.cpp b/src/protocols/PrimarySelection.cpp index 3c263647..14df7af5 100644 --- a/src/protocols/PrimarySelection.cpp +++ b/src/protocols/PrimarySelection.cpp @@ -79,7 +79,7 @@ std::vector CPrimarySelectionSource::mimes() { } void CPrimarySelectionSource::send(const std::string& mime, CFileDescriptor fd) { - if (std::find(m_mimeTypes.begin(), m_mimeTypes.end(), mime) == m_mimeTypes.end()) { + if (std::ranges::find(m_mimeTypes, mime) == m_mimeTypes.end()) { LOGM(ERR, "Compositor/App bug: CPrimarySelectionSource::sendAskSend with non-existent mime"); return; } @@ -88,7 +88,7 @@ void CPrimarySelectionSource::send(const std::string& mime, CFileDescriptor fd) } void CPrimarySelectionSource::accepted(const std::string& mime) { - if (std::find(m_mimeTypes.begin(), m_mimeTypes.end(), mime) == m_mimeTypes.end()) + if (std::ranges::find(m_mimeTypes, mime) == m_mimeTypes.end()) LOGM(ERR, "Compositor/App bug: CPrimarySelectionSource::sendAccepted with non-existent mime"); // primary sel has no accepted @@ -327,7 +327,7 @@ void CPrimarySelectionProtocol::onPointerFocus() { } SP CPrimarySelectionProtocol::dataDeviceForClient(wl_client* c) { - auto it = std::find_if(m_devices.begin(), m_devices.end(), [c](const auto& e) { return e->client() == c; }); + auto it = std::ranges::find_if(m_devices, [c](const auto& e) { return e->client() == c; }); if (it == m_devices.end()) return nullptr; return *it; diff --git a/src/protocols/SecurityContext.cpp b/src/protocols/SecurityContext.cpp index ae3f41b1..acabe0a1 100644 --- a/src/protocols/SecurityContext.cpp +++ b/src/protocols/SecurityContext.cpp @@ -214,5 +214,5 @@ void CSecurityContextProtocol::destroyContext(CSecurityContext* context) { } bool CSecurityContextProtocol::isClientSandboxed(const wl_client* client) { - return std::find_if(m_sandboxedClients.begin(), m_sandboxedClients.end(), [client](const auto& e) { return e->m_client == client; }) != m_sandboxedClients.end(); + return std::ranges::find_if(m_sandboxedClients, [client](const auto& e) { return e->m_client == client; }) != m_sandboxedClients.end(); } diff --git a/src/protocols/VirtualKeyboard.cpp b/src/protocols/VirtualKeyboard.cpp index 48ed7eeb..7512f9bd 100644 --- a/src/protocols/VirtualKeyboard.cpp +++ b/src/protocols/VirtualKeyboard.cpp @@ -31,7 +31,7 @@ CVirtualKeyboardV1Resource::CVirtualKeyboardV1Resource(SP .state = (wl_keyboard_key_state)state, }); - const bool CONTAINS = std::find(m_pressed.begin(), m_pressed.end(), key) != m_pressed.end(); + const bool CONTAINS = std::ranges::find(m_pressed, key) != m_pressed.end(); if (state && !CONTAINS) m_pressed.emplace_back(key); else if (!state && CONTAINS) diff --git a/src/protocols/XDGActivation.cpp b/src/protocols/XDGActivation.cpp index bae3acc3..f25ffca8 100644 --- a/src/protocols/XDGActivation.cpp +++ b/src/protocols/XDGActivation.cpp @@ -33,8 +33,7 @@ CXDGActivationToken::CXDGActivationToken(SP resource_) : PROTO::activation->m_sentTokens.push_back({m_token, m_resource->client()}); - auto count = std::count_if(PROTO::activation->m_sentTokens.begin(), PROTO::activation->m_sentTokens.end(), - [this](const auto& other) { return other.client == m_resource->client(); }); + auto count = std::ranges::count_if(PROTO::activation->m_sentTokens, [this](const auto& other) { return other.client == m_resource->client(); }); if UNLIKELY (count > 10) { // remove first token. Too many, dear app. @@ -68,7 +67,7 @@ void CXDGActivationProtocol::bindManager(wl_client* client, void* data, uint32_t RESOURCE->setDestroy([this](CXdgActivationV1* pMgr) { this->onManagerResourceDestroy(pMgr->resource()); }); RESOURCE->setGetActivationToken([this](CXdgActivationV1* pMgr, uint32_t id) { this->onGetToken(pMgr, id); }); RESOURCE->setActivate([this](CXdgActivationV1* pMgr, const char* token, wl_resource* surface) { - auto TOKEN = std::find_if(m_sentTokens.begin(), m_sentTokens.end(), [token](const auto& t) { return t.token == token; }); + auto TOKEN = std::ranges::find_if(m_sentTokens, [token](const auto& t) { return t.token == token; }); if UNLIKELY (TOKEN == m_sentTokens.end()) { LOGM(WARN, "activate event for non-existent token {}??", token); diff --git a/src/protocols/XDGShell.cpp b/src/protocols/XDGShell.cpp index d3d5c18e..5351e267 100644 --- a/src/protocols/XDGShell.cpp +++ b/src/protocols/XDGShell.cpp @@ -258,7 +258,7 @@ uint32_t CXDGToplevelResource::setSize(const Vector2D& size) { } uint32_t CXDGToplevelResource::setMaximized(bool maximized) { - bool set = std::find(m_pendingApply.states.begin(), m_pendingApply.states.end(), XDG_TOPLEVEL_STATE_MAXIMIZED) != m_pendingApply.states.end(); + bool set = std::ranges::find(m_pendingApply.states, XDG_TOPLEVEL_STATE_MAXIMIZED) != m_pendingApply.states.end(); if (maximized == set) return m_owner->m_scheduledSerial; @@ -272,7 +272,7 @@ uint32_t CXDGToplevelResource::setMaximized(bool maximized) { } uint32_t CXDGToplevelResource::setFullscreen(bool fullscreen) { - bool set = std::find(m_pendingApply.states.begin(), m_pendingApply.states.end(), XDG_TOPLEVEL_STATE_FULLSCREEN) != m_pendingApply.states.end(); + bool set = std::ranges::find(m_pendingApply.states, XDG_TOPLEVEL_STATE_FULLSCREEN) != m_pendingApply.states.end(); if (fullscreen == set) return m_owner->m_scheduledSerial; @@ -286,7 +286,7 @@ uint32_t CXDGToplevelResource::setFullscreen(bool fullscreen) { } uint32_t CXDGToplevelResource::setActive(bool active) { - bool set = std::find(m_pendingApply.states.begin(), m_pendingApply.states.end(), XDG_TOPLEVEL_STATE_ACTIVATED) != m_pendingApply.states.end(); + bool set = std::ranges::find(m_pendingApply.states, XDG_TOPLEVEL_STATE_ACTIVATED) != m_pendingApply.states.end(); if (active == set) return m_owner->m_scheduledSerial; @@ -303,7 +303,7 @@ uint32_t CXDGToplevelResource::setSuspeneded(bool sus) { if (m_resource->version() < 6) return m_owner->scheduleConfigure(); // SUSPENDED is since 6 - bool set = std::find(m_pendingApply.states.begin(), m_pendingApply.states.end(), XDG_TOPLEVEL_STATE_SUSPENDED) != m_pendingApply.states.end(); + bool set = std::ranges::find(m_pendingApply.states, XDG_TOPLEVEL_STATE_SUSPENDED) != m_pendingApply.states.end(); if (sus == set) return m_owner->m_scheduledSerial; diff --git a/src/protocols/XXColorManagement.cpp b/src/protocols/XXColorManagement.cpp index 5a345f40..23b033a0 100644 --- a/src/protocols/XXColorManagement.cpp +++ b/src/protocols/XXColorManagement.cpp @@ -237,8 +237,8 @@ CXXColorManagementSurface::CXXColorManagementSurface(SPm_imageDescriptions.begin(), PROTO::xxColorManagement->m_imageDescriptions.end(), - [&](const auto& other) { return other->resource()->resource() == image_description; }); + const auto imageDescription = + std::ranges::find_if(PROTO::xxColorManagement->m_imageDescriptions, [&](const auto& other) { return other->resource()->resource() == image_description; }); if (imageDescription == PROTO::xxColorManagement->m_imageDescriptions.end()) { r->error(XX_COLOR_MANAGEMENT_SURFACE_V4_ERROR_IMAGE_DESCRIPTION, "Image description not found"); return; diff --git a/src/protocols/core/Compositor.cpp b/src/protocols/core/Compositor.cpp index 07bad77b..d1efe2e8 100644 --- a/src/protocols/core/Compositor.cpp +++ b/src/protocols/core/Compositor.cpp @@ -268,7 +268,7 @@ wl_client* CWLSurfaceResource::client() { } void CWLSurfaceResource::enter(PHLMONITOR monitor) { - if (std::find(m_enteredOutputs.begin(), m_enteredOutputs.end(), monitor) != m_enteredOutputs.end()) + if (std::ranges::find(m_enteredOutputs, monitor) != m_enteredOutputs.end()) return; if UNLIKELY (!PROTO::outputs.contains(monitor->m_name)) { @@ -295,7 +295,7 @@ void CWLSurfaceResource::enter(PHLMONITOR monitor) { } void CWLSurfaceResource::leave(PHLMONITOR monitor) { - if UNLIKELY (std::find(m_enteredOutputs.begin(), m_enteredOutputs.end(), monitor) == m_enteredOutputs.end()) + if UNLIKELY (std::ranges::find(m_enteredOutputs, monitor) == m_enteredOutputs.end()) return; auto output = PROTO::outputs.at(monitor->m_name)->outputResourceFrom(m_client); diff --git a/src/protocols/core/DataDevice.cpp b/src/protocols/core/DataDevice.cpp index ad580ed1..ec075e8b 100644 --- a/src/protocols/core/DataDevice.cpp +++ b/src/protocols/core/DataDevice.cpp @@ -171,7 +171,7 @@ void CWLDataSourceResource::accepted(const std::string& mime) { return; } - if (std::find(m_mimeTypes.begin(), m_mimeTypes.end(), mime) == m_mimeTypes.end()) { + if (std::ranges::find(m_mimeTypes, mime) == m_mimeTypes.end()) { LOGM(ERR, "Compositor/App bug: CWLDataSourceResource::sendAccepted with non-existent mime"); return; } @@ -184,7 +184,7 @@ std::vector CWLDataSourceResource::mimes() { } void CWLDataSourceResource::send(const std::string& mime, CFileDescriptor fd) { - if (std::find(m_mimeTypes.begin(), m_mimeTypes.end(), mime) == m_mimeTypes.end()) { + if (std::ranges::find(m_mimeTypes, mime) == m_mimeTypes.end()) { LOGM(ERR, "Compositor/App bug: CWLDataSourceResource::sendAskSend with non-existent mime"); return; } @@ -424,7 +424,7 @@ SP CWLDataDeviceProtocol::dataDeviceForClient(wl_client* c) { return g_pXWayland->m_wm->getDataDevice(); #endif - auto it = std::find_if(m_devices.begin(), m_devices.end(), [c](const auto& e) { return e->client() == c; }); + auto it = std::ranges::find_if(m_devices, [c](const auto& e) { return e->client() == c; }); if (it == m_devices.end()) return nullptr; return *it; diff --git a/src/protocols/core/Seat.cpp b/src/protocols/core/Seat.cpp index bc224043..c341f95a 100644 --- a/src/protocols/core/Seat.cpp +++ b/src/protocols/core/Seat.cpp @@ -204,10 +204,10 @@ void CWLPointerResource::sendButton(uint32_t timeMs, uint32_t button, wl_pointer if (!(PROTO::seat->m_currentCaps & eHIDCapabilityType::HID_INPUT_CAPABILITY_POINTER)) return; - if (state == WL_POINTER_BUTTON_STATE_RELEASED && std::find(m_pressedButtons.begin(), m_pressedButtons.end(), button) == m_pressedButtons.end()) { + if (state == WL_POINTER_BUTTON_STATE_RELEASED && std::ranges::find(m_pressedButtons, button) == m_pressedButtons.end()) { LOGM(ERR, "sendButton release on a non-pressed button"); return; - } else if (state == WL_POINTER_BUTTON_STATE_PRESSED && std::find(m_pressedButtons.begin(), m_pressedButtons.end(), button) != m_pressedButtons.end()) { + } else if (state == WL_POINTER_BUTTON_STATE_PRESSED && std::ranges::find(m_pressedButtons, button) != m_pressedButtons.end()) { LOGM(ERR, "sendButton press on a non-pressed button"); return; } diff --git a/src/protocols/core/Shm.cpp b/src/protocols/core/Shm.cpp index 228884b9..8d610fe0 100644 --- a/src/protocols/core/Shm.cpp +++ b/src/protocols/core/Shm.cpp @@ -137,7 +137,7 @@ CWLSHMPoolResource::CWLSHMPoolResource(SP resource_, CFileDescriptor return; } - if UNLIKELY (std::find(PROTO::shm->m_shmFormats.begin(), PROTO::shm->m_shmFormats.end(), fmt) == PROTO::shm->m_shmFormats.end()) { + if UNLIKELY (std::ranges::find(PROTO::shm->m_shmFormats, fmt) == PROTO::shm->m_shmFormats.end()) { r->error(WL_SHM_ERROR_INVALID_FORMAT, "Format invalid"); return; } diff --git a/src/protocols/core/Subcompositor.cpp b/src/protocols/core/Subcompositor.cpp index 4111b5dc..85a0edc4 100644 --- a/src/protocols/core/Subcompositor.cpp +++ b/src/protocols/core/Subcompositor.cpp @@ -30,7 +30,7 @@ CWLSubsurfaceResource::CWLSubsurfaceResource(SP resource_, SPm_subsurfaces, [this](const auto& e) { return e == m_self || !e; }); - auto it = std::find(m_parent->m_subsurfaces.begin(), m_parent->m_subsurfaces.end(), SURF); + auto it = std::ranges::find(m_parent->m_subsurfaces, SURF); if (it == m_parent->m_subsurfaces.end()) { LOGM(ERR, "Invalid surface reference in placeAbove, likely parent"); @@ -43,7 +43,7 @@ CWLSubsurfaceResource::CWLSubsurfaceResource(SP resource_, SPm_subsurfaces.emplace_back(m_self); } - std::sort(m_parent->m_subsurfaces.begin(), m_parent->m_subsurfaces.end(), [](const auto& a, const auto& b) { return a->m_zIndex < b->m_zIndex; }); + std::ranges::sort(m_parent->m_subsurfaces, [](const auto& a, const auto& b) { return a->m_zIndex < b->m_zIndex; }); }); m_resource->setPlaceBelow([this](CWlSubsurface* r, wl_resource* surf) { @@ -61,7 +61,7 @@ CWLSubsurfaceResource::CWLSubsurfaceResource(SP resource_, SPm_subsurfaces, [this](const auto& e) { return e == m_self || !e; }); - auto it = std::find(m_parent->m_subsurfaces.begin(), m_parent->m_subsurfaces.end(), SURF); + auto it = std::ranges::find(m_parent->m_subsurfaces, SURF); if (it == m_parent->m_subsurfaces.end()) { LOGM(ERR, "Invalid surface reference in placeBelow, likely parent"); @@ -74,7 +74,7 @@ CWLSubsurfaceResource::CWLSubsurfaceResource(SP resource_, SPm_subsurfaces.emplace_back(m_self); } - std::sort(m_parent->m_subsurfaces.begin(), m_parent->m_subsurfaces.end(), [](const auto& a, const auto& b) { return a->m_zIndex < b->m_zIndex; }); + std::ranges::sort(m_parent->m_subsurfaces, [](const auto& a, const auto& b) { return a->m_zIndex < b->m_zIndex; }); }); m_listeners.commitSurface = m_surface->m_events.commit.registerListener([this](std::any d) { @@ -116,8 +116,7 @@ Vector2D CWLSubsurfaceResource::posRelativeToParent() { // surfaces we've visited and if we hit a surface we've visited we bail out. std::vector> surfacesVisited; - while (surf->m_role->role() == SURFACE_ROLE_SUBSURFACE && - std::find_if(surfacesVisited.begin(), surfacesVisited.end(), [surf](const auto& other) { return surf == other; }) == surfacesVisited.end()) { + while (surf->m_role->role() == SURFACE_ROLE_SUBSURFACE && std::ranges::find_if(surfacesVisited, [surf](const auto& other) { return surf == other; }) == surfacesVisited.end()) { surfacesVisited.emplace_back(surf); auto subsurface = ((CSubsurfaceRole*)m_parent->m_role.get())->m_subsurface.lock(); pos += subsurface->m_position; @@ -134,8 +133,7 @@ SP CWLSubsurfaceResource::t1Parent() { SP surf = m_parent.lock(); std::vector> surfacesVisited; - while (surf->m_role->role() == SURFACE_ROLE_SUBSURFACE && - std::find_if(surfacesVisited.begin(), surfacesVisited.end(), [surf](const auto& other) { return surf == other; }) == surfacesVisited.end()) { + while (surf->m_role->role() == SURFACE_ROLE_SUBSURFACE && std::ranges::find_if(surfacesVisited, [surf](const auto& other) { return surf == other; }) == surfacesVisited.end()) { surfacesVisited.emplace_back(surf); auto subsurface = ((CSubsurfaceRole*)m_parent->m_role.get())->m_subsurface.lock(); surf = subsurface->m_parent.lock(); diff --git a/src/render/OpenGL.cpp b/src/render/OpenGL.cpp index 855da879..89d769b3 100644 --- a/src/render/OpenGL.cpp +++ b/src/render/OpenGL.cpp @@ -255,7 +255,7 @@ EGLDeviceEXT CHyprOpenGLImpl::eglDeviceFromDRMFD(int drmFD) { CHyprOpenGLImpl::CHyprOpenGLImpl() : m_drmFD(g_pCompositor->m_drmFD) { const std::string EGLEXTENSIONS = (const char*)eglQueryString(EGL_NO_DISPLAY, EGL_EXTENSIONS); - Debug::log(LOG, "Supported EGL extensions: ({}) {}", std::count(EGLEXTENSIONS.begin(), EGLEXTENSIONS.end(), ' '), EGLEXTENSIONS); + Debug::log(LOG, "Supported EGL extensions: ({}) {}", std::ranges::count(EGLEXTENSIONS, ' '), EGLEXTENSIONS); m_exts.KHR_display_reference = EGLEXTENSIONS.contains("KHR_display_reference"); @@ -331,7 +331,7 @@ CHyprOpenGLImpl::CHyprOpenGLImpl() : m_drmFD(g_pCompositor->m_drmFD) { Debug::log(LOG, "Using: {}", (char*)glGetString(GL_VERSION)); Debug::log(LOG, "Vendor: {}", (char*)glGetString(GL_VENDOR)); Debug::log(LOG, "Renderer: {}", (char*)glGetString(GL_RENDERER)); - Debug::log(LOG, "Supported extensions: ({}) {}", std::count(m_extensions.begin(), m_extensions.end(), ' '), m_extensions); + Debug::log(LOG, "Supported extensions: ({}) {}", std::ranges::count(m_extensions, ' '), m_extensions); m_exts.EXT_read_format_bgra = m_extensions.contains("GL_EXT_read_format_bgra"); @@ -415,7 +415,7 @@ std::optional> CHyprOpenGLImpl::getModsForFormat(EGLint fo } // if the driver doesn't mark linear as external, add it. It's allowed unless the driver says otherwise. (e.g. nvidia) - if (!linearIsExternal && std::find(mods.begin(), mods.end(), DRM_FORMAT_MOD_LINEAR) == mods.end() && mods.size() == 0) + if (!linearIsExternal && std::ranges::find(mods, DRM_FORMAT_MOD_LINEAR) == mods.end() && mods.size() == 0) mods.push_back(DRM_FORMAT_MOD_LINEAR); return result; @@ -490,7 +490,7 @@ void CHyprOpenGLImpl::initDRMFormats() { free(fmtName); mods.clear(); - std::sort(modifierData.begin(), modifierData.end(), [](const auto& a, const auto& b) { + std::ranges::sort(modifierData, [](const auto& a, const auto& b) { if (a.first == 0) return false; if (a.second.contains("DCC")) diff --git a/src/render/Renderer.cpp b/src/render/Renderer.cpp index 982e2ed8..28f078aa 100644 --- a/src/render/Renderer.cpp +++ b/src/render/Renderer.cpp @@ -59,7 +59,7 @@ CHyprRenderer::CHyprRenderer() { if (!DRMV) continue; std::string name = std::string{DRMV->name, DRMV->name_len}; - std::transform(name.begin(), name.end(), name.begin(), tolower); + std::ranges::transform(name, name.begin(), tolower); if (name.contains("nvidia")) m_nvidia = true; @@ -76,7 +76,7 @@ CHyprRenderer::CHyprRenderer() { if (DRMV) { std::string name = std::string{DRMV->name, DRMV->name_len}; - std::transform(name.begin(), name.end(), name.begin(), tolower); + std::ranges::transform(name, name.begin(), tolower); if (name.contains("nvidia")) m_nvidia = true; @@ -1794,7 +1794,7 @@ void CHyprRenderer::arrangeLayersForMonitor(const MONITORID& monitor) { } for (auto& la : PMONITOR->m_layerSurfaceLayers) { - std::stable_sort(la.begin(), la.end(), [](const PHLLSREF& a, const PHLLSREF& b) { return a->m_order > b->m_order; }); + std::ranges::stable_sort(la, [](const PHLLSREF& a, const PHLLSREF& b) { return a->m_order > b->m_order; }); } for (auto const& la : PMONITOR->m_layerSurfaceLayers) @@ -2171,7 +2171,7 @@ void CHyprRenderer::recheckSolitaryForMonitor(PHLMONITOR pMonitor) { } SP CHyprRenderer::getOrCreateRenderbuffer(SP buffer, uint32_t fmt) { - auto it = std::find_if(m_renderbuffers.begin(), m_renderbuffers.end(), [&](const auto& other) { return other->m_hlBuffer == buffer; }); + auto it = std::ranges::find_if(m_renderbuffers, [&](const auto& other) { return other->m_hlBuffer == buffer; }); if (it != m_renderbuffers.end()) return *it; @@ -2364,7 +2364,7 @@ SExplicitSyncSettings CHyprRenderer::getExplicitSyncSettings(SP("misc:render_unfocused_fps"); - if (std::find(m_renderUnfocused.begin(), m_renderUnfocused.end(), window) != m_renderUnfocused.end()) + if (std::ranges::find(m_renderUnfocused, window) != m_renderUnfocused.end()) return; m_renderUnfocused.emplace_back(window); diff --git a/src/render/decorations/DecorationPositioner.cpp b/src/render/decorations/DecorationPositioner.cpp index 82f2e5a8..178f3b9b 100644 --- a/src/render/decorations/DecorationPositioner.cpp +++ b/src/render/decorations/DecorationPositioner.cpp @@ -59,7 +59,7 @@ Vector2D CDecorationPositioner::getEdgeDefinedPoint(uint32_t edges, PHLWINDOW pW void CDecorationPositioner::uncacheDecoration(IHyprWindowDecoration* deco) { std::erase_if(m_windowPositioningDatas, [&](const auto& data) { return !data->pWindow.lock() || data->pDecoration == deco; }); - const auto WIT = std::find_if(m_windowDatas.begin(), m_windowDatas.end(), [&](const auto& other) { return other.first.lock() == deco->m_window.lock(); }); + const auto WIT = std::ranges::find_if(m_windowDatas, [&](const auto& other) { return other.first.lock() == deco->m_window.lock(); }); if (WIT == m_windowDatas.end()) return; @@ -72,7 +72,7 @@ void CDecorationPositioner::repositionDeco(IHyprWindowDecoration* deco) { } CDecorationPositioner::SWindowPositioningData* CDecorationPositioner::getDataFor(IHyprWindowDecoration* pDecoration, PHLWINDOW pWindow) { - auto it = std::find_if(m_windowPositioningDatas.begin(), m_windowPositioningDatas.end(), [&](const auto& el) { return el->pDecoration == pDecoration; }); + auto it = std::ranges::find_if(m_windowPositioningDatas, [&](const auto& el) { return el->pDecoration == pDecoration; }); if (it != m_windowPositioningDatas.end()) return it->get(); @@ -89,15 +89,14 @@ void CDecorationPositioner::sanitizeDatas() { std::erase_if(m_windowPositioningDatas, [](const auto& other) { if (!validMapped(other->pWindow)) return true; - if (std::find_if(other->pWindow->m_windowDecorations.begin(), other->pWindow->m_windowDecorations.end(), [&](const auto& el) { return el.get() == other->pDecoration; }) == - other->pWindow->m_windowDecorations.end()) + if (std::ranges::find_if(other->pWindow->m_windowDecorations, [&](const auto& el) { return el.get() == other->pDecoration; }) == other->pWindow->m_windowDecorations.end()) return true; return false; }); } void CDecorationPositioner::forceRecalcFor(PHLWINDOW pWindow) { - const auto WIT = std::find_if(m_windowDatas.begin(), m_windowDatas.end(), [&](const auto& other) { return other.first.lock() == pWindow; }); + const auto WIT = std::ranges::find_if(m_windowDatas, [&](const auto& other) { return other.first.lock() == pWindow; }); if (WIT == m_windowDatas.end()) return; @@ -110,7 +109,7 @@ void CDecorationPositioner::onWindowUpdate(PHLWINDOW pWindow) { if (!validMapped(pWindow)) return; - const auto WIT = std::find_if(m_windowDatas.begin(), m_windowDatas.end(), [&](const auto& other) { return other.first.lock() == pWindow; }); + const auto WIT = std::ranges::find_if(m_windowDatas, [&](const auto& other) { return other.first.lock() == pWindow; }); if (WIT == m_windowDatas.end()) return; @@ -128,8 +127,7 @@ void CDecorationPositioner::onWindowUpdate(PHLWINDOW pWindow) { } if (WINDOWDATA->lastWindowSize == pWindow->m_realSize->value() /* position not changed */ - && std::all_of(m_windowPositioningDatas.begin(), m_windowPositioningDatas.end(), - [pWindow](const auto& data) { return pWindow != data->pWindow.lock() || !data->needsReposition; }) + && std::ranges::all_of(m_windowPositioningDatas, [pWindow](const auto& data) { return pWindow != data->pWindow.lock() || !data->needsReposition; }) /* all window datas are either not for this window or don't need a reposition */ && !WINDOWDATA->needsRecalc /* window doesn't need recalc */ ) @@ -143,7 +141,7 @@ void CDecorationPositioner::onWindowUpdate(PHLWINDOW pWindow) { WINDOWDATA->needsRecalc = false; const bool EPHEMERAL = pWindow->m_realSize->isBeingAnimated(); - std::sort(datas.begin(), datas.end(), [](const auto& a, const auto& b) { return a->positioningInfo.priority > b->positioningInfo.priority; }); + std::ranges::sort(datas, [](const auto& a, const auto& b) { return a->positioningInfo.priority > b->positioningInfo.priority; }); CBox wb = pWindow->getWindowMainSurfaceBox(); diff --git a/src/render/pass/Pass.cpp b/src/render/pass/Pass.cpp index 5877d9a9..32296ad7 100644 --- a/src/render/pass/Pass.cpp +++ b/src/render/pass/Pass.cpp @@ -259,7 +259,7 @@ void CRenderPass::renderDebugData() { } } - const auto DISCARDED_ELEMENTS = std::count_if(m_passElements.begin(), m_passElements.end(), [](const auto& e) { return e->discard; }); + const auto DISCARDED_ELEMENTS = std::ranges::count_if(m_passElements, [](const auto& e) { return e->discard; }); auto tex = g_pHyprOpenGL->renderText(std::format("occlusion layers: {}\npass elements: {} ({} discarded)\nviewport: {:X0}", m_occludedRegions.size(), m_passElements.size(), DISCARDED_ELEMENTS, g_pHyprOpenGL->m_renderData.pMonitor->m_pixelSize), Colors::WHITE, 12); diff --git a/src/xwayland/XSurface.cpp b/src/xwayland/XSurface.cpp index 949649ae..71e710b3 100644 --- a/src/xwayland/XSurface.cpp +++ b/src/xwayland/XSurface.cpp @@ -214,7 +214,7 @@ void CXWaylandSurface::restackToTop() { xcb_configure_window(g_pXWayland->m_wm->m_connection, m_xID, XCB_CONFIG_WINDOW_STACK_MODE, values); auto& stack = g_pXWayland->m_wm->m_mappedSurfacesStacking; - auto it = std::find(stack.begin(), stack.end(), m_self); + auto it = std::ranges::find(stack, m_self); if (it != stack.end()) std::rotate(it, it + 1, stack.end()); diff --git a/src/xwayland/XWM.cpp b/src/xwayland/XWM.cpp index 8e4f9a87..76ae1d88 100644 --- a/src/xwayland/XWM.cpp +++ b/src/xwayland/XWM.cpp @@ -164,7 +164,7 @@ static bool lookupParentExists(SP XSURF, SP XSURF = XSURF->m_parent.lock(); - if (std::find(visited.begin(), visited.end(), XSURF) != visited.end()) + if (std::ranges::find(visited, XSURF) != visited.end()) return false; } @@ -202,7 +202,7 @@ void CXWM::readProp(SP XSURF, uint32_t atom, xcb_get_property_ size_t len = xcb_get_property_value_length(reply); char* string = (char*)xcb_get_property_value(reply); XSURF->m_state.appid = std::string{string, len}; - if (std::count(XSURF->m_state.appid.begin(), XSURF->m_state.appid.end(), '\000') == 2) + if (std::ranges::count(XSURF->m_state.appid, '\000') == 2) XSURF->m_state.appid = XSURF->m_state.appid.substr(XSURF->m_state.appid.find_first_of('\000') + 1); // fuck you X if (!XSURF->m_state.appid.empty()) XSURF->m_state.appid.pop_back(); @@ -1109,7 +1109,7 @@ void CXWM::associate(SP surf, SP wlSurf) { if (surf->m_surface) return; - auto existing = std::find_if(m_surfaces.begin(), m_surfaces.end(), [wlSurf](const auto& e) { return e->m_surface == wlSurf; }); + auto existing = std::ranges::find_if(m_surfaces, [wlSurf](const auto& e) { return e->m_surface == wlSurf; }); if (existing != m_surfaces.end()) { Debug::log(WARN, "[xwm] associate() called but surface is already associated to {:x}, ignoring...", (uintptr_t)surf.get()); @@ -1420,7 +1420,7 @@ bool SXSelection::sendData(xcb_selection_request_event_t* e, std::string mime) { if (MIMES.empty()) return false; - if (std::find(MIMES.begin(), MIMES.end(), mime) == MIMES.end()) { + if (std::ranges::find(MIMES, mime) == MIMES.end()) { Debug::log(ERR, "[xwm] X Client asked for an invalid MIME, sending the first advertised. THIS SHIT MAY BREAK!"); mime = *MIMES.begin(); } From af2fdb5d58f5d3017aafd78a8ddafb40f710e34b Mon Sep 17 00:00:00 2001 From: mitsuru Date: Fri, 30 May 2025 22:40:12 +0100 Subject: [PATCH 1332/2181] nix: use gcc15 resolves Nix build/CI failures introduced in 9190443 bumps flake.lock as gcc15Stdenv wasn't available at the pinned version of nixpkgs --- flake.lock | 6 +++--- nix/overlays.nix | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/flake.lock b/flake.lock index 22f246d5..01b437e6 100644 --- a/flake.lock +++ b/flake.lock @@ -276,11 +276,11 @@ }, "nixpkgs": { "locked": { - "lastModified": 1748026106, - "narHash": "sha256-6m1Y3/4pVw1RWTsrkAK2VMYSzG4MMIj7sqUy7o8th1o=", + "lastModified": 1748460289, + "narHash": "sha256-7doLyJBzCllvqX4gszYtmZUToxKvMUrg45EUWaUYmBg=", "owner": "NixOS", "repo": "nixpkgs", - "rev": "063f43f2dbdef86376cc29ad646c45c46e93234c", + "rev": "96ec055edbe5ee227f28cdbc3f1ddf1df5965102", "type": "github" }, "original": { diff --git a/nix/overlays.nix b/nix/overlays.nix index 6085bf80..ee020eaa 100644 --- a/nix/overlays.nix +++ b/nix/overlays.nix @@ -35,7 +35,7 @@ in { date = mkDate (self.lastModifiedDate or "19700101"); in { hyprland = final.callPackage ./default.nix { - stdenv = final.gcc14Stdenv; + stdenv = final.gcc15Stdenv; version = "${version}+date=${date}_${self.shortRev or "dirty"}"; commit = self.rev or ""; revCount = self.sourceInfo.revCount or ""; From 4078e1d17c0fb1439ee5a0ba1e539f06a8f47aab Mon Sep 17 00:00:00 2001 From: Kamikadze <40305144+Kam1k4dze@users.noreply.github.com> Date: Sat, 31 May 2025 18:02:02 +0500 Subject: [PATCH 1333/2181] refactor: replace all `typedef` with `using` (#10594) --- src/SharedDefs.hpp | 8 ++++---- src/desktop/DesktopTypes.hpp | 16 ++++++++-------- src/helpers/Format.hpp | 6 +++--- src/layout/IHyprLayout.cpp | 2 +- src/managers/HookSystemManager.hpp | 4 ++-- src/managers/XWaylandManager.hpp | 2 +- src/plugins/PluginAPI.hpp | 10 +++++----- src/protocols/types/ColorManagement.hpp | 2 +- src/xwayland/XSurface.hpp | 12 ++++++------ 9 files changed, 31 insertions(+), 31 deletions(-) diff --git a/src/SharedDefs.hpp b/src/SharedDefs.hpp index a46a2429..b8094997 100644 --- a/src/SharedDefs.hpp +++ b/src/SharedDefs.hpp @@ -58,8 +58,8 @@ struct SDispatchResult { std::string error; }; -typedef int64_t WINDOWID; -typedef int64_t MONITORID; -typedef int64_t WORKSPACEID; +using WINDOWID = int64_t; +using MONITORID = int64_t; +using WORKSPACEID = int64_t; -typedef std::function HOOK_CALLBACK_FN; +using HOOK_CALLBACK_FN = std::function; diff --git a/src/desktop/DesktopTypes.hpp b/src/desktop/DesktopTypes.hpp index 080f13d3..f724c7b9 100644 --- a/src/desktop/DesktopTypes.hpp +++ b/src/desktop/DesktopTypes.hpp @@ -6,21 +6,21 @@ class CLayerSurface; class CMonitor; /* Shared pointer to a workspace */ -typedef SP PHLWORKSPACE; +using PHLWORKSPACE = SP; /* Weak pointer to a workspace */ -typedef WP PHLWORKSPACEREF; +using PHLWORKSPACEREF = WP; /* Shared pointer to a window */ -typedef SP PHLWINDOW; +using PHLWINDOW = SP; /* Weak pointer to a window */ -typedef WP PHLWINDOWREF; +using PHLWINDOWREF = WP; /* Shared pointer to a layer surface */ -typedef SP PHLLS; +using PHLLS = SP; /* Weak pointer to a layer surface */ -typedef WP PHLLSREF; +using PHLLSREF = WP; /* Shared pointer to a monitor */ -typedef SP PHLMONITOR; +using PHLMONITOR = SP; /* Weak pointer to a monitor */ -typedef WP PHLMONITORREF; +using PHLMONITORREF = WP; diff --git a/src/helpers/Format.hpp b/src/helpers/Format.hpp index b1353dc7..fe68f763 100644 --- a/src/helpers/Format.hpp +++ b/src/helpers/Format.hpp @@ -5,8 +5,8 @@ #include "math/Math.hpp" #include -typedef uint32_t DRMFormat; -typedef uint32_t SHMFormat; +using DRMFormat = uint32_t; +using SHMFormat = uint32_t; struct SPixelFormat { DRMFormat drmFormat = 0; /* DRM_FORMAT_INVALID */ @@ -20,7 +20,7 @@ struct SPixelFormat { Vector2D blockSize; }; -typedef Aquamarine::SDRMFormat SDRMFormat; +using SDRMFormat = Aquamarine::SDRMFormat; namespace NFormatUtils { SHMFormat drmToShm(DRMFormat drm); diff --git a/src/layout/IHyprLayout.cpp b/src/layout/IHyprLayout.cpp index 1fe3a936..fbde7344 100644 --- a/src/layout/IHyprLayout.cpp +++ b/src/layout/IHyprLayout.cpp @@ -411,7 +411,7 @@ static void snapResize(double& start, double& end, const double P) { start = P; } -typedef std::function SnapFn; +using SnapFn = std::function; static void performSnap(Vector2D& sourcePos, Vector2D& sourceSize, PHLWINDOW DRAGGINGWINDOW, const eMouseBindMode MODE, const int CORNER, const Vector2D& BEGINSIZE) { static auto SNAPWINDOWGAP = CConfigValue("general:snap:window_gap"); diff --git a/src/managers/HookSystemManager.hpp b/src/managers/HookSystemManager.hpp index 69d54a60..647e9670 100644 --- a/src/managers/HookSystemManager.hpp +++ b/src/managers/HookSystemManager.hpp @@ -11,9 +11,9 @@ #define HANDLE void* -// global typedef for hooked functions. Passes itself as a ptr when called, and `data` additionally. +// global type alias for hooked functions. Passes itself as a ptr when called, and `data` additionally. -typedef std::function HOOK_CALLBACK_FN; +using HOOK_CALLBACK_FN = std::function; struct SCallbackFNPtr { WP fn; diff --git a/src/managers/XWaylandManager.hpp b/src/managers/XWaylandManager.hpp index e4f1e17a..59eee4c5 100644 --- a/src/managers/XWaylandManager.hpp +++ b/src/managers/XWaylandManager.hpp @@ -4,7 +4,7 @@ #include class CWindow; // because clangd -typedef SP PHLWINDOW; +using PHLWINDOW = SP; class CWLSurfaceResource; class CHyprXWaylandManager { diff --git a/src/plugins/PluginAPI.hpp b/src/plugins/PluginAPI.hpp index 0f333294..00a1e8b2 100644 --- a/src/plugins/PluginAPI.hpp +++ b/src/plugins/PluginAPI.hpp @@ -31,12 +31,12 @@ Feel like the API is missing something you'd like to use in your plugin? Open an #include #include -typedef struct { +using PLUGIN_DESCRIPTION_INFO = struct { std::string name; std::string description; std::string author; std::string version; -} PLUGIN_DESCRIPTION_INFO; +}; struct SFunctionMatch { void* address = nullptr; @@ -83,7 +83,7 @@ class CWindow; This function should not be modified, see the example plugin. */ -typedef REQUIRED std::string (*PPLUGIN_API_VERSION_FUNC)(); +using PPLUGIN_API_VERSION_FUNC = REQUIRED std::string (*)(); #define PLUGIN_API_VERSION pluginAPIVersion #define PLUGIN_API_VERSION_FUNC_STR "pluginAPIVersion" @@ -93,7 +93,7 @@ typedef REQUIRED std::string (*PPLUGIN_API_VERSION_FUNC)(); Keep in mind this is executed synchronously, and as such any blocking calls to hyprland might hang. (e.g. system("hyprctl ...")) */ -typedef REQUIRED PLUGIN_DESCRIPTION_INFO (*PPLUGIN_INIT_FUNC)(HANDLE); +using PPLUGIN_INIT_FUNC = REQUIRED PLUGIN_DESCRIPTION_INFO (*)(HANDLE); #define PLUGIN_INIT pluginInit #define PLUGIN_INIT_FUNC_STR "pluginInit" @@ -103,7 +103,7 @@ typedef REQUIRED PLUGIN_DESCRIPTION_INFO (*PPLUGIN_INIT_FUNC)(HANDLE); Hooks are unloaded after exit. */ -typedef OPTIONAL void (*PPLUGIN_EXIT_FUNC)(); +using PPLUGIN_EXIT_FUNC = OPTIONAL void (*)(); #define PLUGIN_EXIT pluginExit #define PLUGIN_EXIT_FUNC_STR "pluginExit" diff --git a/src/protocols/types/ColorManagement.hpp b/src/protocols/types/ColorManagement.hpp index 48d8dd31..2dd1c075 100644 --- a/src/protocols/types/ColorManagement.hpp +++ b/src/protocols/types/ColorManagement.hpp @@ -54,7 +54,7 @@ namespace NColorManagement { return (eTransferFunction)tf; } - typedef Hyprgraphics::SPCPRimaries SPCPRimaries; + using SPCPRimaries = Hyprgraphics::SPCPRimaries; namespace NColorPrimaries { static const auto DEFAULT_PRIMARIES = SPCPRimaries{}; diff --git a/src/xwayland/XSurface.hpp b/src/xwayland/XSurface.hpp index dc43acbb..ec71aad3 100644 --- a/src/xwayland/XSurface.hpp +++ b/src/xwayland/XSurface.hpp @@ -9,9 +9,9 @@ class CWLSurfaceResource; class CXWaylandSurfaceResource; #ifdef NO_XWAYLAND -typedef uint32_t xcb_pixmap_t; -typedef uint32_t xcb_window_t; -typedef struct { +using xcb_pixmap_t = uint32_t; +using xcb_window_t = uint32_t; +using xcb_icccm_wm_hints_t = struct { int32_t flags; uint32_t input; int32_t initial_state; @@ -20,8 +20,8 @@ typedef struct { int32_t icon_x, icon_y; xcb_pixmap_t icon_mask; xcb_window_t window_group; -} xcb_icccm_wm_hints_t; -typedef struct { +}; +using xcb_size_hints_t = struct { uint32_t flags; int32_t x, y; int32_t width, height; @@ -32,7 +32,7 @@ typedef struct { int32_t max_aspect_num, max_aspect_den; int32_t base_width, base_height; uint32_t win_gravity; -} xcb_size_hints_t; +}; #else #include #endif From 69c2b2926e128f1fd09080aed43944987a42026f Mon Sep 17 00:00:00 2001 From: Kamikadze <40305144+Kam1k4dze@users.noreply.github.com> Date: Sat, 31 May 2025 23:49:50 +0500 Subject: [PATCH 1334/2181] internal: refactor to use empty() (#10599) --- src/config/ConfigManager.cpp | 22 +++++++++---------- src/debug/HyprCtl.cpp | 8 +++---- src/debug/HyprDebugOverlay.cpp | 8 +++---- src/debug/HyprNotificationOverlay.cpp | 4 ++-- src/desktop/Window.cpp | 4 ++-- src/events/Windows.cpp | 4 ++-- src/helpers/MiscFunctions.cpp | 2 +- src/helpers/Monitor.cpp | 2 +- src/hyprerror/HyprError.cpp | 4 ++-- src/layout/MasterLayout.cpp | 2 +- src/managers/AnimationManager.cpp | 4 ++-- src/managers/CursorManager.cpp | 8 +++---- src/managers/KeybindManager.cpp | 10 ++++----- src/managers/ProtocolManager.cpp | 2 +- src/managers/SeatManager.cpp | 2 +- src/managers/input/InputManager.cpp | 10 ++++----- src/plugins/HookSystem.cpp | 2 +- src/render/OpenGL.cpp | 12 +++++----- src/render/Renderer.cpp | 2 +- .../decorations/CHyprGroupBarDecoration.cpp | 2 +- 20 files changed, 57 insertions(+), 57 deletions(-) diff --git a/src/config/ConfigManager.cpp b/src/config/ConfigManager.cpp index 3ab53a3c..f7fed52f 100644 --- a/src/config/ConfigManager.cpp +++ b/src/config/ConfigManager.cpp @@ -100,7 +100,7 @@ static Hyprlang::CParseResult configHandleGradientSet(const char* VALUE, void** } } - if (DATA->m_colors.size() == 0) { + if (DATA->m_colors.empty()) { Debug::log(WARN, "Error parsing gradient {}", V); if (parseError.empty()) parseError = "Error parsing gradient " + V + ": No colors?"; @@ -2093,7 +2093,7 @@ std::optional CConfigManager::handleMonitor(const std::string& comm int argno = 4; - while (ARGS[argno] != "") { + while (!ARGS[argno].empty()) { if (ARGS[argno] == "mirror") { newrule.mirrorOf = ARGS[argno + 1]; argno++; @@ -2185,23 +2185,23 @@ std::optional CConfigManager::handleBezier(const std::string& comma std::string bezierName = ARGS[0]; - if (ARGS[1] == "") + if (ARGS[1].empty()) return "too few arguments"; float p1x = std::stof(ARGS[1]); - if (ARGS[2] == "") + if (ARGS[2].empty()) return "too few arguments"; float p1y = std::stof(ARGS[2]); - if (ARGS[3] == "") + if (ARGS[3].empty()) return "too few arguments"; float p2x = std::stof(ARGS[3]); - if (ARGS[4] == "") + if (ARGS[4].empty()) return "too few arguments"; float p2y = std::stof(ARGS[4]); - if (ARGS[5] != "") + if (!ARGS[5].empty()) return "too many arguments"; g_pAnimationManager->addBezierWithName(bezierName, Vector2D(p1x, p1y), Vector2D(p2x, p2y)); @@ -2256,10 +2256,10 @@ std::optional CConfigManager::handleAnimation(const std::string& co return "no such bezier"; } - if (ARGS[4] != "") { + if (!ARGS[4].empty()) { auto ERR = g_pAnimationManager->styleValidInConfigVar(ANIMNAME, ARGS[4]); - if (ERR != "") + if (!ERR.empty()) return ERR; } @@ -2384,12 +2384,12 @@ std::optional CConfigManager::handleBind(const std::string& command return "Invalid dispatcher, requested \"" + HANDLER + "\" does not exist"; } - if (MOD == 0 && MODSTR != "") { + if (MOD == 0 && !MODSTR.empty()) { Debug::log(ERR, "Invalid mod: {}", MODSTR); return "Invalid mod, requested mod \"" + MODSTR + "\" is not a valid mod."; } - if ((KEY != "") || multiKey) { + if ((!KEY.empty()) || multiKey) { SParsedKey parsedKey = parseKey(KEY); if (parsedKey.catchAll && m_currentSubmap.empty()) { diff --git a/src/debug/HyprCtl.cpp b/src/debug/HyprCtl.cpp index c8cc5c59..77f54c2b 100644 --- a/src/debug/HyprCtl.cpp +++ b/src/debug/HyprCtl.cpp @@ -516,7 +516,7 @@ static std::string layersRequest(eHyprCtlOutputFormat format, std::string reques trimTrailingComma(result); - if (level.size() > 0) + if (!level.empty()) result += "\n "; result += "],"; @@ -1144,7 +1144,7 @@ static std::string dispatchKeyword(eHyprCtlOutputFormat format, std::string in) Debug::log(LOG, "Hyprctl: keyword {} : {}", COMMAND, VALUE); - if (retval == "") + if (retval.empty()) return "ok"; return retval; @@ -1528,7 +1528,7 @@ static std::string dispatchPlugin(eHyprCtlOutputFormat format, std::string reque if (format == eHyprCtlOutputFormat::FORMAT_JSON) { result += "["; - if (PLUGINS.size() == 0) + if (PLUGINS.empty()) return "[]"; for (auto const& p : PLUGINS) { @@ -1546,7 +1546,7 @@ static std::string dispatchPlugin(eHyprCtlOutputFormat format, std::string reque trimTrailingComma(result); result += "]"; } else { - if (PLUGINS.size() == 0) + if (PLUGINS.empty()) return "no plugins loaded"; for (auto const& p : PLUGINS) { diff --git a/src/debug/HyprDebugOverlay.cpp b/src/debug/HyprDebugOverlay.cpp index 332800dd..6c5d8000 100644 --- a/src/debug/HyprDebugOverlay.cpp +++ b/src/debug/HyprDebugOverlay.cpp @@ -83,7 +83,7 @@ int CHyprMonitorDebugOverlay::draw(int offset) { avgFrametime += ft; } float varFrametime = maxFrametime - minFrametime; - avgFrametime /= m_lastFrametimes.size() == 0 ? 1 : m_lastFrametimes.size(); + avgFrametime /= m_lastFrametimes.empty() ? 1 : m_lastFrametimes.size(); float avgRenderTime = 0; float maxRenderTime = 0; @@ -96,7 +96,7 @@ int CHyprMonitorDebugOverlay::draw(int offset) { avgRenderTime += rt; } float varRenderTime = maxRenderTime - minRenderTime; - avgRenderTime /= m_lastRenderTimes.size() == 0 ? 1 : m_lastRenderTimes.size(); + avgRenderTime /= m_lastRenderTimes.empty() ? 1 : m_lastRenderTimes.size(); float avgRenderTimeNoOverlay = 0; float maxRenderTimeNoOverlay = 0; @@ -109,7 +109,7 @@ int CHyprMonitorDebugOverlay::draw(int offset) { avgRenderTimeNoOverlay += rt; } float varRenderTimeNoOverlay = maxRenderTimeNoOverlay - minRenderTimeNoOverlay; - avgRenderTimeNoOverlay /= m_lastRenderTimes.size() == 0 ? 1 : m_lastRenderTimes.size(); + avgRenderTimeNoOverlay /= m_lastRenderTimes.empty() ? 1 : m_lastRenderTimes.size(); float avgAnimMgrTick = 0; float maxAnimMgrTick = 0; @@ -122,7 +122,7 @@ int CHyprMonitorDebugOverlay::draw(int offset) { avgAnimMgrTick += at; } float varAnimMgrTick = maxAnimMgrTick - minAnimMgrTick; - avgAnimMgrTick /= m_lastAnimationTicks.size() == 0 ? 1 : m_lastAnimationTicks.size(); + avgAnimMgrTick /= m_lastAnimationTicks.empty() ? 1 : m_lastAnimationTicks.size(); const float FPS = 1.f / (avgFrametime / 1000.f); // frametimes are in ms const float idealFPS = m_lastFrametimes.size(); diff --git a/src/debug/HyprNotificationOverlay.cpp b/src/debug/HyprNotificationOverlay.cpp index bfa5c4e4..c50abfe6 100644 --- a/src/debug/HyprNotificationOverlay.cpp +++ b/src/debug/HyprNotificationOverlay.cpp @@ -23,7 +23,7 @@ static inline auto iconBackendFromLayout(PangoLayout* layout) { CHyprNotificationOverlay::CHyprNotificationOverlay() { static auto P = g_pHookSystem->hookDynamic("focusedMon", [&](void* self, SCallbackInfo& info, std::any param) { - if (m_notifications.size() == 0) + if (m_notifications.empty()) return; g_pHyprRenderer->damageBox(m_lastDamage); @@ -210,7 +210,7 @@ void CHyprNotificationOverlay::draw(PHLMONITOR pMonitor) { } // Draw the notifications - if (m_notifications.size() == 0) + if (m_notifications.empty()) return; // Render to the monitor diff --git a/src/desktop/Window.cpp b/src/desktop/Window.cpp index cc3c9390..555b99f0 100644 --- a/src/desktop/Window.cpp +++ b/src/desktop/Window.cpp @@ -1624,13 +1624,13 @@ PHLWINDOW CWindow::getSwallower() { if (!(*PSWALLOWREGEX).empty()) std::erase_if(candidates, [&](const auto& other) { return !RE2::FullMatch(other->m_class, *PSWALLOWREGEX); }); - if (candidates.size() == 0) + if (candidates.empty()) return nullptr; if (!(*PSWALLOWEXREGEX).empty()) std::erase_if(candidates, [&](const auto& other) { return RE2::FullMatch(other->m_title, *PSWALLOWEXREGEX); }); - if (candidates.size() == 0) + if (candidates.empty()) return nullptr; if (candidates.size() == 1) diff --git a/src/events/Windows.cpp b/src/events/Windows.cpp index b019adff..da1e5263 100644 --- a/src/events/Windows.cpp +++ b/src/events/Windows.cpp @@ -418,8 +418,8 @@ void Events::listener_mapWindow(void* owner, void* data) { PWINDOW->m_swallowed->m_currentlySwallowed = true; // emit the IPC event before the layout might focus the window to avoid a focus event first - g_pEventManager->postEvent( - SHyprIPCEvent{"openwindow", std::format("{:x},{},{},{}", PWINDOW, requestedWorkspace != "" ? requestedWorkspace : PWORKSPACE->m_name, PWINDOW->m_class, PWINDOW->m_title)}); + g_pEventManager->postEvent(SHyprIPCEvent{ + "openwindow", std::format("{:x},{},{},{}", PWINDOW, !requestedWorkspace.empty() ? requestedWorkspace : PWORKSPACE->m_name, PWINDOW->m_class, PWINDOW->m_title)}); if (PWINDOW->m_isFloating) { g_pLayoutManager->getCurrentLayout()->onWindowCreated(PWINDOW); diff --git a/src/helpers/MiscFunctions.cpp b/src/helpers/MiscFunctions.cpp index ddd16144..8069d414 100644 --- a/src/helpers/MiscFunctions.cpp +++ b/src/helpers/MiscFunctions.cpp @@ -326,7 +326,7 @@ SWorkspaceIDName getWorkspaceIDNameFromString(const std::string& in) { finalWSID = curID; } if (finalWSID <= 0 || invalidWSes.contains(finalWSID)) { - if (namedWSes.size()) { + if (!namedWSes.empty()) { // Go to the named workspaces // Need remainingWSes more auto namedWSIdx = namedWSes.size() - remainingWSes; diff --git a/src/helpers/Monitor.cpp b/src/helpers/Monitor.cpp index 5afd0123..b0b31526 100644 --- a/src/helpers/Monitor.cpp +++ b/src/helpers/Monitor.cpp @@ -988,7 +988,7 @@ void CMonitor::setupDefaultWS(const SMonitorRule& monitorRule) { g_pLayoutManager->getCurrentLayout()->recalculateMonitor(m_id); PNEWWORKSPACE->startAnim(true, true, true); } else { - if (newDefaultWorkspaceName == "") + if (newDefaultWorkspaceName.empty()) newDefaultWorkspaceName = std::to_string(wsID); PNEWWORKSPACE = g_pCompositor->m_workspaces.emplace_back(CWorkspace::create(wsID, m_self.lock(), newDefaultWorkspaceName)); diff --git a/src/hyprerror/HyprError.cpp b/src/hyprerror/HyprError.cpp index 22744c93..b6080306 100644 --- a/src/hyprerror/HyprError.cpp +++ b/src/hyprerror/HyprError.cpp @@ -165,8 +165,8 @@ void CHyprError::createQueued() { } void CHyprError::draw() { - if (!m_isCreated || m_queued != "") { - if (m_queued != "") + if (!m_isCreated || !m_queued.empty()) { + if (!m_queued.empty()) createQueued(); return; } diff --git a/src/layout/MasterLayout.cpp b/src/layout/MasterLayout.cpp index cb1313a8..abdf8032 100644 --- a/src/layout/MasterLayout.cpp +++ b/src/layout/MasterLayout.cpp @@ -1359,7 +1359,7 @@ void CHyprMasterLayout::runOrientationCycle(SLayoutMessageHeader& header, CVarLi if (vars != nullptr) buildOrientationCycleVectorFromVars(cycle, *vars); - if (cycle.size() == 0) + if (cycle.empty()) buildOrientationCycleVectorFromEOperation(cycle); const auto PWINDOW = header.pWindow; diff --git a/src/managers/AnimationManager.cpp b/src/managers/AnimationManager.cpp index f935d3dc..d1da1a36 100644 --- a/src/managers/AnimationManager.cpp +++ b/src/managers/AnimationManager.cpp @@ -306,7 +306,7 @@ void CHyprAnimationManager::animationSlide(PHLWINDOW pWindow, std::string force, Vector2D posOffset; - if (force != "") { + if (!force.empty()) { if (force == "bottom") posOffset = Vector2D(GOALPOS.x, PMONITOR->m_position.y + PMONITOR->m_size.y); else if (force == "left") @@ -490,7 +490,7 @@ std::string CHyprAnimationManager::styleValidInConfigVar(const std::string& conf return ""; return "unknown style"; } else if (config.starts_with("layers")) { - if (style == "fade" || style == "" || style == "slide") + if (style.empty() || style == "fade" || style == "slide") return ""; else if (style.starts_with("popin")) { // try parsing diff --git a/src/managers/CursorManager.cpp b/src/managers/CursorManager.cpp index 9211fc20..cb46dd65 100644 --- a/src/managers/CursorManager.cpp +++ b/src/managers/CursorManager.cpp @@ -183,7 +183,7 @@ void CCursorManager::setCursorFromName(const std::string& name) { auto setHyprCursor = [this](auto const& name) { m_currentCursorShapeData = m_hyprcursor->getShape(name.c_str(), m_currentStyleInfo); - if (m_currentCursorShapeData.images.size() < 1) { + if (m_currentCursorShapeData.images.empty()) { // try with '_' first (old hc, etc) std::string newName = name; std::ranges::replace(newName, '-', '_'); @@ -191,18 +191,18 @@ void CCursorManager::setCursorFromName(const std::string& name) { m_currentCursorShapeData = m_hyprcursor->getShape(newName.c_str(), m_currentStyleInfo); } - if (m_currentCursorShapeData.images.size() < 1) { + if (m_currentCursorShapeData.images.empty()) { // fallback to a default if available constexpr const std::array fallbackShapes = {"default", "left_ptr", "left-ptr"}; for (auto const& s : fallbackShapes) { m_currentCursorShapeData = m_hyprcursor->getShape(s, m_currentStyleInfo); - if (m_currentCursorShapeData.images.size() > 0) + if (!m_currentCursorShapeData.images.empty()) break; } - if (m_currentCursorShapeData.images.size() < 1) { + if (m_currentCursorShapeData.images.empty()) { Debug::log(ERR, "BUG THIS: No fallback found for a cursor in setCursorFromName"); return false; } diff --git a/src/managers/KeybindManager.cpp b/src/managers/KeybindManager.cpp index 58951281..976e292d 100644 --- a/src/managers/KeybindManager.cpp +++ b/src/managers/KeybindManager.cpp @@ -164,7 +164,7 @@ CKeybindManager::CKeybindManager() { m_repeatKeyTimer = makeShared( std::nullopt, [this](SP self, void* data) { - if (m_activeKeybinds.size() == 0 || g_pSeatManager->m_keyboard.expired()) + if (m_activeKeybinds.empty() || g_pSeatManager->m_keyboard.expired()) return; const auto PACTIVEKEEB = g_pSeatManager->m_keyboard.lock(); @@ -288,7 +288,7 @@ void CKeybindManager::updateXKBTranslationState() { xkb_rule_names rules = {.rules = RULES.c_str(), .model = MODEL.c_str(), .layout = LAYOUT.c_str(), .variant = VARIANT.c_str(), .options = OPTIONS.c_str()}; const auto PCONTEXT = xkb_context_new(XKB_CONTEXT_NO_FLAGS); - FILE* const KEYMAPFILE = FILEPATH == "" ? nullptr : fopen(absolutePath(FILEPATH, g_pConfigManager->m_configCurrentPath).c_str(), "r"); + FILE* const KEYMAPFILE = FILEPATH.empty() ? nullptr : fopen(absolutePath(FILEPATH, g_pConfigManager->m_configCurrentPath).c_str(), "r"); auto PKEYMAP = KEYMAPFILE ? xkb_keymap_new_from_file(PCONTEXT, KEYMAPFILE, XKB_KEYMAP_FORMAT_TEXT_V1, XKB_KEYMAP_COMPILE_NO_FLAGS) : xkb_keymap_new_from_names(PCONTEXT, &rules, XKB_KEYMAP_COMPILE_NO_FLAGS); @@ -630,7 +630,7 @@ eMultiKeyCase CKeybindManager::mkKeysymSetMatches(const std::set k if (boundKeysNotPressed.empty() && pressedKeysNotBound.empty()) return MK_FULL_MATCH; - if (boundKeysNotPressed.size() && pressedKeysNotBound.empty()) + if (!boundKeysNotPressed.empty() && pressedKeysNotBound.empty()) return MK_PARTIAL_MATCH; return MK_NO_MATCH; @@ -2398,7 +2398,7 @@ SDispatchResult CKeybindManager::toggleSwallow(std::string args) { } SDispatchResult CKeybindManager::setSubmap(std::string submap) { - if (submap == "reset" || submap == "") { + if (submap == "reset" || submap.empty()) { m_currentSelectedSubmap = ""; Debug::log(LOG, "Reset active submap to the default one."); g_pEventManager->postEvent(SHyprIPCEvent{"submap", ""}); @@ -2576,7 +2576,7 @@ SDispatchResult CKeybindManager::sendshortcut(std::string args) { //if regexp is not empty, send shortcut to current window //else, dont change focus - if (regexp != "") { + if (!regexp.empty()) { PWINDOW = g_pCompositor->getWindowByRegex(regexp); if (!PWINDOW) { diff --git a/src/managers/ProtocolManager.cpp b/src/managers/ProtocolManager.cpp index ab542fc2..942e7954 100644 --- a/src/managers/ProtocolManager.cpp +++ b/src/managers/ProtocolManager.cpp @@ -209,7 +209,7 @@ CProtocolManager::CProtocolManager() { break; } - if (g_pHyprOpenGL->getDRMFormats().size() > 0) { + if (!g_pHyprOpenGL->getDRMFormats().empty()) { PROTO::mesaDRM = makeUnique(&wl_drm_interface, 2, "MesaDRM"); PROTO::linuxDma = makeUnique(&zwp_linux_dmabuf_v1_interface, 5, "LinuxDMABUF"); } else diff --git a/src/managers/SeatManager.cpp b/src/managers/SeatManager.cpp index a7660854..9fe2b26b 100644 --- a/src/managers/SeatManager.cpp +++ b/src/managers/SeatManager.cpp @@ -493,7 +493,7 @@ void CSeatManager::refocusGrab() { if (!m_seatGrab) return; - if (m_seatGrab->m_surfs.size() > 0) { + if (!m_seatGrab->m_surfs.empty()) { // try to find a surf in focus first const auto MOUSE = g_pInputManager->getMouseCoordsInternal(); for (auto const& s : m_seatGrab->m_surfs) { diff --git a/src/managers/input/InputManager.cpp b/src/managers/input/InputManager.cpp index cc0485d8..70f92023 100644 --- a/src/managers/input/InputManager.cpp +++ b/src/managers/input/InputManager.cpp @@ -1082,7 +1082,7 @@ void CInputManager::applyConfigToKeyboard(SP pKeyboard) { pKeyboard->m_allowed = PERM == PERMISSION_RULE_ALLOW_MODE_ALLOW; try { - if (NUMLOCKON == pKeyboard->m_numlockOn && REPEATDELAY == pKeyboard->m_repeatDelay && REPEATRATE == pKeyboard->m_repeatRate && RULES != "" && + if (NUMLOCKON == pKeyboard->m_numlockOn && REPEATDELAY == pKeyboard->m_repeatDelay && REPEATRATE == pKeyboard->m_repeatRate && !RULES.empty() && RULES == pKeyboard->m_currentRules.rules && MODEL == pKeyboard->m_currentRules.model && LAYOUT == pKeyboard->m_currentRules.layout && VARIANT == pKeyboard->m_currentRules.variant && OPTIONS == pKeyboard->m_currentRules.options && FILEPATH == pKeyboard->m_xkbFilePath) { Debug::log(LOG, "Not applying config to keyboard, it did not change."); @@ -1205,7 +1205,7 @@ void CInputManager::setPointerConfigs() { libinput_device_config_middle_emulation_set_enabled(LIBINPUTDEV, LIBINPUT_CONFIG_MIDDLE_EMULATION_DISABLED); const auto TAP_MAP = g_pConfigManager->getDeviceString(devname, "tap_button_map", "input:touchpad:tap_button_map"); - if (TAP_MAP == "" || TAP_MAP == "lrm") + if (TAP_MAP.empty() || TAP_MAP == "lrm") libinput_device_config_tap_set_button_map(LIBINPUTDEV, LIBINPUT_CONFIG_TAP_MAP_LRM); else if (TAP_MAP == "lmr") libinput_device_config_tap_set_button_map(LIBINPUTDEV, LIBINPUT_CONFIG_TAP_MAP_LMR); @@ -1214,7 +1214,7 @@ void CInputManager::setPointerConfigs() { } const auto SCROLLMETHOD = g_pConfigManager->getDeviceString(devname, "scroll_method", "input:scroll_method"); - if (SCROLLMETHOD == "") { + if (SCROLLMETHOD.empty()) { libinput_device_config_scroll_set_method(LIBINPUTDEV, libinput_device_config_scroll_get_default_method(LIBINPUTDEV)); } else if (SCROLLMETHOD == "no_scroll") { libinput_device_config_scroll_set_method(LIBINPUTDEV, LIBINPUT_CONFIG_SCROLL_NO_SCROLL); @@ -1330,7 +1330,7 @@ void CInputManager::destroyKeyboard(SP pKeyboard) { std::erase_if(m_keyboards, [pKeyboard](const auto& other) { return other == pKeyboard; }); - if (m_keyboards.size() > 0) { + if (!m_keyboards.empty()) { bool found = false; for (auto const& k : m_keyboards | std::views::reverse) { if (!k) @@ -1354,7 +1354,7 @@ void CInputManager::destroyPointer(SP mouse) { std::erase_if(m_pointers, [mouse](const auto& other) { return other == mouse; }); - g_pSeatManager->setMouse(m_pointers.size() > 0 ? m_pointers.front() : nullptr); + g_pSeatManager->setMouse(!m_pointers.empty() ? m_pointers.front() : nullptr); if (!g_pSeatManager->m_mouse.expired()) unconstrainMouse(); diff --git a/src/plugins/HookSystem.cpp b/src/plugins/HookSystem.cpp index 8bb660e6..f39eb145 100644 --- a/src/plugins/HookSystem.cpp +++ b/src/plugins/HookSystem.cpp @@ -167,7 +167,7 @@ bool CFunctionHook::hook() { const auto PROBEFIXEDASM = fixInstructionProbeRIPCalls(probe); - if (PROBEFIXEDASM.bytes.size() == 0) { + if (PROBEFIXEDASM.bytes.empty()) { Debug::log(ERR, "[functionhook] failed, unsupported asm / failed assembling:\n{}", probe.assembly); return false; } diff --git a/src/render/OpenGL.cpp b/src/render/OpenGL.cpp index 89d769b3..d589e3cf 100644 --- a/src/render/OpenGL.cpp +++ b/src/render/OpenGL.cpp @@ -415,7 +415,7 @@ std::optional> CHyprOpenGLImpl::getModsForFormat(EGLint fo } // if the driver doesn't mark linear as external, add it. It's allowed unless the driver says otherwise. (e.g. nvidia) - if (!linearIsExternal && std::ranges::find(mods, DRM_FORMAT_MOD_LINEAR) == mods.end() && mods.size() == 0) + if (!linearIsExternal && std::ranges::find(mods, DRM_FORMAT_MOD_LINEAR) == mods.end() && mods.empty()) mods.push_back(DRM_FORMAT_MOD_LINEAR); return result; @@ -444,7 +444,7 @@ void CHyprOpenGLImpl::initDRMFormats() { m_proc.eglQueryDmaBufFormatsEXT(m_eglDisplay, len, formats.data(), &len); } - if (formats.size() == 0) { + if (formats.empty()) { Debug::log(ERR, "EGL: Failed to get formats, DMABufs will not work."); return; } @@ -466,7 +466,7 @@ void CHyprOpenGLImpl::initDRMFormats() { } else mods = {DRM_FORMAT_MOD_LINEAR}; - m_hasModifiers = m_hasModifiers || mods.size() > 0; + m_hasModifiers = m_hasModifiers || !mods.empty(); // EGL can always do implicit modifiers. mods.push_back(DRM_FORMAT_MOD_INVALID); @@ -506,7 +506,7 @@ void CHyprOpenGLImpl::initDRMFormats() { Debug::log(LOG, "EGL: {} formats found in total. Some modifiers may be omitted as they are external-only.", dmaFormats.size()); - if (dmaFormats.size() == 0) + if (dmaFormats.empty()) Debug::log(WARN, "EGL: WARNING: No dmabuf formats were found, dmabuf will be disabled. This will degrade performance, but is most likely a driver issue or a very old GPU."); @@ -1193,7 +1193,7 @@ void CHyprOpenGLImpl::applyScreenShader(const std::string& path) { m_finalScreenShader.destroy(); - if (path == "" || path == STRVAL_EMPTY) + if (path.empty() || path == STRVAL_EMPTY) return; std::ifstream infile(absolutePath(path, g_pConfigManager->getMainConfigPath())); @@ -2362,7 +2362,7 @@ void CHyprOpenGLImpl::renderBorder(const CBox& box, const CGradientValueData& gr glUniform4fv(m_shaders->m_shBORDER1.gradient, grad1.m_colorsOkLabA.size() / 4, (float*)grad1.m_colorsOkLabA.data()); glUniform1i(m_shaders->m_shBORDER1.gradientLength, grad1.m_colorsOkLabA.size() / 4); glUniform1f(m_shaders->m_shBORDER1.angle, (int)(grad1.m_angle / (PI / 180.0)) % 360 * (PI / 180.0)); - if (grad2.m_colorsOkLabA.size() > 0) + if (!grad2.m_colorsOkLabA.empty()) glUniform4fv(m_shaders->m_shBORDER1.gradient2, grad2.m_colorsOkLabA.size() / 4, (float*)grad2.m_colorsOkLabA.data()); glUniform1i(m_shaders->m_shBORDER1.gradient2Length, grad2.m_colorsOkLabA.size() / 4); glUniform1f(m_shaders->m_shBORDER1.angle2, (int)(grad2.m_angle / (PI / 180.0)) % 360 * (PI / 180.0)); diff --git a/src/render/Renderer.cpp b/src/render/Renderer.cpp index 28f078aa..71d22d3c 100644 --- a/src/render/Renderer.cpp +++ b/src/render/Renderer.cpp @@ -2077,7 +2077,7 @@ std::tuple CHyprRenderer::getRenderTimes(PHLMONITOR pMonito minRenderTime = rt; avgRenderTime += rt; } - avgRenderTime /= POVERLAY->m_lastRenderTimes.size() == 0 ? 1 : POVERLAY->m_lastRenderTimes.size(); + avgRenderTime /= POVERLAY->m_lastRenderTimes.empty() ? 1 : POVERLAY->m_lastRenderTimes.size(); return std::make_tuple<>(avgRenderTime, maxRenderTime, minRenderTime); } diff --git a/src/render/decorations/CHyprGroupBarDecoration.cpp b/src/render/decorations/CHyprGroupBarDecoration.cpp index 65d7d7ff..7a6eebba 100644 --- a/src/render/decorations/CHyprGroupBarDecoration.cpp +++ b/src/render/decorations/CHyprGroupBarDecoration.cpp @@ -81,7 +81,7 @@ void CHyprGroupBarDecoration::updateWindow(PHLWINDOW pWindow) { damageEntire(); - if (m_dwGroupMembers.size() == 0) { + if (m_dwGroupMembers.empty()) { m_window->removeWindowDeco(this); return; } From 82b854954230a45d590c1287a8c2c1f0076f3392 Mon Sep 17 00:00:00 2001 From: vaxerski Date: Sun, 1 Jun 2025 21:53:20 +0200 Subject: [PATCH 1335/2181] hyprpm: refuse adding a new repo without update --- hyprpm/src/core/PluginManager.cpp | 5 +++++ src/xwayland/Dnd.cpp | 2 +- 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/hyprpm/src/core/PluginManager.cpp b/hyprpm/src/core/PluginManager.cpp index 90eba579..b7316fdb 100644 --- a/hyprpm/src/core/PluginManager.cpp +++ b/hyprpm/src/core/PluginManager.cpp @@ -159,6 +159,11 @@ bool CPluginManager::addNewPluginRepo(const std::string& url, const std::string& DataState::updateGlobalState(GLOBALSTATE); } + if (GLOBALSTATE.headersHashCompiled.empty()) { + std::println("\n{}", failureString("Cannot find headers in the global state. Try running hyprpm update first.")); + return false; + } + std::cout << Colors::GREEN << "✔" << Colors::RESET << Colors::RED << " adding a new plugin repository " << Colors::RESET << "from " << url << "\n " << Colors::RED << "MAKE SURE" << Colors::RESET << " that you trust the authors. " << Colors::RED << "DO NOT" << Colors::RESET << " install random plugins without verifying the code and author.\n " diff --git a/src/xwayland/Dnd.cpp b/src/xwayland/Dnd.cpp index e4c60920..9d2012fb 100644 --- a/src/xwayland/Dnd.cpp +++ b/src/xwayland/Dnd.cpp @@ -286,8 +286,8 @@ void CX11DataDevice::forceCleanupDnd() { if (m_lastOffer) { auto source = m_lastOffer->getSource(); if (source) { - source->cancelled(); source->sendDndFinished(); + source->cancelled(); } } From 2d1c6f88d2202ae40671277759b1edc3ecc51c45 Mon Sep 17 00:00:00 2001 From: Jasson Date: Sun, 1 Jun 2025 16:02:17 -0400 Subject: [PATCH 1336/2181] xwm: Refactored functions in XWM.cpp (#10569) * Refactored SXSelection::onSelection in XWM.cpp - Made the function more readable and less redundant - Extracted repeated conditions into booleans. - Reduced nested conditionals - Reused (conn) pointer * Refectd readProp * Refactor initSelection --- src/xwayland/XWM.cpp | 261 ++++++++++++++++++++++++------------------- 1 file changed, 147 insertions(+), 114 deletions(-) diff --git a/src/xwayland/XWM.cpp b/src/xwayland/XWM.cpp index 76ae1d88..5b423dca 100644 --- a/src/xwayland/XWM.cpp +++ b/src/xwayland/XWM.cpp @@ -1,5 +1,6 @@ #include "helpers/math/Math.hpp" #include +#include #ifndef NO_XWAYLAND #include @@ -198,104 +199,125 @@ void CXWM::readProp(SP XSURF, uint32_t atom, xcb_get_property_ if (Debug::m_trace) propName = getAtomName(atom); - if (atom == XCB_ATOM_WM_CLASS) { - size_t len = xcb_get_property_value_length(reply); - char* string = (char*)xcb_get_property_value(reply); - XSURF->m_state.appid = std::string{string, len}; - if (std::ranges::count(XSURF->m_state.appid, '\000') == 2) - XSURF->m_state.appid = XSURF->m_state.appid.substr(XSURF->m_state.appid.find_first_of('\000') + 1); // fuck you X + const auto valueLen = xcb_get_property_value_length(reply); + const auto* value = (const char*)xcb_get_property_value(reply); + + auto handleWMClass = [&]() { + XSURF->m_state.appid = std::string{value, valueLen}; + if (std::count(XSURF->m_state.appid.begin(), XSURF->m_state.appid.end(), '\000') == 2) + XSURF->m_state.appid = XSURF->m_state.appid.substr(XSURF->m_state.appid.find_first_of('\000') + 1); + if (!XSURF->m_state.appid.empty()) XSURF->m_state.appid.pop_back(); XSURF->m_events.metadataChanged.emit(); - } else if (atom == XCB_ATOM_WM_NAME || atom == HYPRATOMS["_NET_WM_NAME"]) { - size_t len = xcb_get_property_value_length(reply); - char* string = (char*)xcb_get_property_value(reply); + }; + + auto handleWMName = [&]() { if (reply->type != HYPRATOMS["UTF8_STRING"] && reply->type != HYPRATOMS["TEXT"] && reply->type != XCB_ATOM_STRING) return; - XSURF->m_state.title = std::string{string, len}; + XSURF->m_state.title = std::string{value, valueLen}; XSURF->m_events.metadataChanged.emit(); - } else if (atom == HYPRATOMS["_NET_WM_WINDOW_TYPE"]) { - xcb_atom_t* atomsArr = (xcb_atom_t*)xcb_get_property_value(reply); - size_t atomsNo = reply->value_len; - XSURF->m_atoms.clear(); - for (size_t i = 0; i < atomsNo; ++i) { - XSURF->m_atoms.push_back(atomsArr[i]); - } - } else if (atom == HYPRATOMS["_NET_WM_STATE"]) { - xcb_atom_t* atoms = (xcb_atom_t*)xcb_get_property_value(reply); + }; + + auto handleWindowType = [&]() { + auto* atomsArr = (xcb_atom_t*)value; + XSURF->m_atoms.assign(atomsArr, atomsArr + reply->value_len); + }; + + auto handleWMState = [&]() { + auto* atoms = (xcb_atom_t*)value; for (uint32_t i = 0; i < reply->value_len; i++) { if (atoms[i] == HYPRATOMS["_NET_WM_STATE_MODAL"]) XSURF->m_modal = true; } - } else if (atom == HYPRATOMS["WM_HINTS"]) { - if (reply->value_len != 0) { - XSURF->m_hints = makeUnique(); - xcb_icccm_get_wm_hints_from_reply(XSURF->m_hints.get(), reply); + }; - if (!(XSURF->m_hints->flags & XCB_ICCCM_WM_HINT_INPUT)) - XSURF->m_hints->input = true; - } - } else if (atom == HYPRATOMS["WM_WINDOW_ROLE"]) { - size_t len = xcb_get_property_value_length(reply); + auto handleWMHints = [&]() { + if (reply->value_len == 0) + return; + XSURF->m_hints = makeUnique(); + xcb_icccm_get_wm_hints_from_reply(XSURF->m_hints.get(), reply); + if (!(XSURF->m_hints->flags & XCB_ICCCM_WM_HINT_INPUT)) + XSURF->m_hints->input = true; + }; - if (len <= 0) + auto handleWMRole = [&]() { + if (valueLen <= 0) XSURF->m_role = ""; else { - XSURF->m_role = std::string{(char*)xcb_get_property_value(reply), len}; + XSURF->m_role = std::string{value, valueLen}; XSURF->m_role = XSURF->m_role.substr(0, XSURF->m_role.find_first_of('\000')); } - } else if (atom == XCB_ATOM_WM_TRANSIENT_FOR) { - if (reply->type == XCB_ATOM_WINDOW) { - const auto XID = (xcb_window_t*)xcb_get_property_value(reply); - XSURF->m_transient = XID; - if (XID) { - if (const auto NEWXSURF = windowForXID(*XID); NEWXSURF && !lookupParentExists(XSURF, NEWXSURF)) { - XSURF->m_parent = NEWXSURF; - NEWXSURF->m_children.emplace_back(XSURF); - } else - Debug::log(LOG, "[xwm] Denying transient because it would create a loop"); - } + }; + + auto handleTransientFor = [&]() { + if (reply->type != XCB_ATOM_WINDOW) + return; + const auto XID = (xcb_window_t*)value; + XSURF->m_transient = XID; + if (!XID) + return; + + if (const auto NEWXSURF = windowForXID(*XID); NEWXSURF && !lookupParentExists(XSURF, NEWXSURF)) { + XSURF->m_parent = NEWXSURF; + NEWXSURF->m_children.emplace_back(XSURF); + } else + Debug::log(LOG, "[xwm] Denying transient because it would create a loop"); + }; + + auto handleSizeHints = [&]() { + if (reply->type != HYPRATOMS["WM_SIZE_HINTS"] || reply->value_len == 0) + return; + + XSURF->m_sizeHints = makeUnique(); + std::memset(XSURF->m_sizeHints.get(), 0, sizeof(xcb_size_hints_t)); + xcb_icccm_get_wm_size_hints_from_reply(XSURF->m_sizeHints.get(), reply); + + const int32_t FLAGS = XSURF->m_sizeHints->flags; + const bool HASMIN = FLAGS & XCB_ICCCM_SIZE_HINT_P_MIN_SIZE; + const bool HASBASE = FLAGS & XCB_ICCCM_SIZE_HINT_BASE_SIZE; + + if (!HASMIN && !HASBASE) { + XSURF->m_sizeHints->min_width = XSURF->m_sizeHints->min_height = -1; + XSURF->m_sizeHints->base_width = XSURF->m_sizeHints->base_height = -1; + } else if (!HASBASE) { + XSURF->m_sizeHints->base_width = XSURF->m_sizeHints->min_width; + XSURF->m_sizeHints->base_height = XSURF->m_sizeHints->min_height; + } else if (!HASMIN) { + XSURF->m_sizeHints->min_width = XSURF->m_sizeHints->base_width; + XSURF->m_sizeHints->min_height = XSURF->m_sizeHints->base_height; } - } else if (atom == HYPRATOMS["WM_NORMAL_HINTS"]) { - if (reply->type == HYPRATOMS["WM_SIZE_HINTS"] && reply->value_len > 0) { - XSURF->m_sizeHints = makeUnique(); - std::memset(XSURF->m_sizeHints.get(), 0, sizeof(xcb_size_hints_t)); - xcb_icccm_get_wm_size_hints_from_reply(XSURF->m_sizeHints.get(), reply); + if (!(FLAGS & XCB_ICCCM_SIZE_HINT_P_MAX_SIZE)) + XSURF->m_sizeHints->max_width = XSURF->m_sizeHints->max_height = -1; + }; - const int32_t FLAGS = XSURF->m_sizeHints->flags; - const bool HASMIN = (FLAGS & XCB_ICCCM_SIZE_HINT_P_MIN_SIZE); - const bool HASBASE = (FLAGS & XCB_ICCCM_SIZE_HINT_BASE_SIZE); + auto handleWMProtocols = [&]() { + if (reply->type != XCB_ATOM_ATOM) + return; + auto* atoms = (xcb_atom_t*)value; + XSURF->m_protocols.assign(atoms, atoms + reply->value_len); + }; - if (!HASMIN && !HASBASE) { - XSURF->m_sizeHints->min_width = -1; - XSURF->m_sizeHints->min_height = -1; - XSURF->m_sizeHints->base_width = -1; - XSURF->m_sizeHints->base_height = -1; - } else if (!HASBASE) { - XSURF->m_sizeHints->base_width = XSURF->m_sizeHints->min_width; - XSURF->m_sizeHints->base_height = XSURF->m_sizeHints->min_height; - } else if (!HASMIN) { - XSURF->m_sizeHints->min_width = XSURF->m_sizeHints->base_width; - XSURF->m_sizeHints->min_height = XSURF->m_sizeHints->base_height; - } - - if (!(FLAGS & XCB_ICCCM_SIZE_HINT_P_MAX_SIZE)) { - XSURF->m_sizeHints->max_width = -1; - XSURF->m_sizeHints->max_height = -1; - } - } - } else if (atom == HYPRATOMS["WM_PROTOCOLS"]) { - if (reply->type == XCB_ATOM_ATOM) { - auto atoms = (xcb_atom_t*)xcb_get_property_value(reply); - std::vector vec; - vec.reserve(reply->value_len); - for (size_t i = 0; i < reply->value_len; ++i) { - vec.emplace_back(atoms[i]); - } - XSURF->m_protocols = vec; - } - } else { + if (atom == XCB_ATOM_WM_CLASS) + handleWMClass(); + else if (atom == XCB_ATOM_WM_NAME || atom == HYPRATOMS["_NET_WM_NAME"]) + handleWMName(); + else if (atom == HYPRATOMS["_NET_WM_WINDOW_TYPE"]) + handleWindowType(); + else if (atom == HYPRATOMS["_NET_WM_STATE"]) + handleWMState(); + else if (atom == HYPRATOMS["WM_HINTS"]) + handleWMHints(); + else if (atom == HYPRATOMS["WM_WINDOW_ROLE"]) + handleWMRole(); + else if (atom == XCB_ATOM_WM_TRANSIENT_FOR) + handleTransientFor(); + else if (atom == HYPRATOMS["WM_NORMAL_HINTS"]) + handleSizeHints(); + else if (atom == HYPRATOMS["WM_PROTOCOLS"]) + handleWMProtocols(); + else { Debug::log(TRACE, "[xwm] Unhandled prop {} -> {}", atom, propName); return; } @@ -757,7 +779,7 @@ bool CXWM::handleSelectionEvent(xcb_generic_event_t* e) { if (e->response_type - m_xfixes->first_event == XCB_XFIXES_SELECTION_NOTIFY) return handleSelectionXFixesNotify((xcb_xfixes_selection_notify_event_t*)e); - return 0; + return false; } int CXWM::onEvent(int fd, uint32_t mask) { @@ -772,14 +794,14 @@ int CXWM::onEvent(int fd, uint32_t mask) { return 0; } - int count = 0; + int processedEventCount = 0; while (42069) { xcb_generic_event_t* event = xcb_poll_for_event(m_connection); if (!event) break; - count++; + processedEventCount++; if (handleSelectionEvent(event)) { free(event); @@ -806,10 +828,10 @@ int CXWM::onEvent(int fd, uint32_t mask) { free(event); } - if (count) + if (processedEventCount) xcb_flush(m_connection); - return count; + return processedEventCount; } void CXWM::gatherResources() { @@ -1171,35 +1193,37 @@ void CXWM::updateOverrideRedirect(SP surf, bool overrideRedire } void CXWM::initSelection() { - m_clipboard.window = xcb_generate_id(m_connection); - uint32_t mask[1] = {XCB_EVENT_MASK_SUBSTRUCTURE_NOTIFY | XCB_EVENT_MASK_PROPERTY_CHANGE}; - xcb_create_window(m_connection, XCB_COPY_FROM_PARENT, m_clipboard.window, m_screen->root, 0, 0, 10, 10, 0, XCB_WINDOW_CLASS_INPUT_OUTPUT, m_screen->root_visual, - XCB_CW_EVENT_MASK, mask); - xcb_set_selection_owner(m_connection, m_clipboard.window, HYPRATOMS["CLIPBOARD_MANAGER"], XCB_TIME_CURRENT_TIME); - - uint32_t mask2 = + const uint32_t windowMask = XCB_EVENT_MASK_SUBSTRUCTURE_NOTIFY | XCB_EVENT_MASK_PROPERTY_CHANGE; + const uint32_t xfixesMask = XCB_XFIXES_SELECTION_EVENT_MASK_SET_SELECTION_OWNER | XCB_XFIXES_SELECTION_EVENT_MASK_SELECTION_WINDOW_DESTROY | XCB_XFIXES_SELECTION_EVENT_MASK_SELECTION_CLIENT_CLOSE; - xcb_xfixes_select_selection_input(m_connection, m_clipboard.window, HYPRATOMS["CLIPBOARD"], mask2); - m_clipboard.listeners.setSelection = g_pSeatManager->m_events.setSelection.registerListener([this](std::any d) { m_clipboard.onSelection(); }); - m_clipboard.listeners.keyboardFocusChange = g_pSeatManager->m_events.keyboardFocusChange.registerListener([this](std::any d) { m_clipboard.onKeyboardFocus(); }); + auto createSelectionWindow = [&](xcb_window_t& window, const std::string& atomName, bool inputOnly = false) { + window = xcb_generate_id(m_connection); + const uint16_t width = inputOnly ? 8192 : 10; + const uint16_t height = inputOnly ? 8192 : 10; - m_primarySelection.window = xcb_generate_id(m_connection); - xcb_create_window(m_connection, XCB_COPY_FROM_PARENT, m_primarySelection.window, m_screen->root, 0, 0, 10, 10, 0, XCB_WINDOW_CLASS_INPUT_OUTPUT, m_screen->root_visual, - XCB_CW_EVENT_MASK, mask); - xcb_set_selection_owner(m_connection, m_primarySelection.window, HYPRATOMS["PRIMARY"], XCB_TIME_CURRENT_TIME); + xcb_create_window(m_connection, XCB_COPY_FROM_PARENT, window, m_screen->root, 0, 0, width, height, 0, + inputOnly ? XCB_WINDOW_CLASS_INPUT_ONLY : XCB_WINDOW_CLASS_INPUT_OUTPUT, m_screen->root_visual, XCB_CW_EVENT_MASK, &windowMask); - xcb_xfixes_select_selection_input(m_connection, m_primarySelection.window, HYPRATOMS["PRIMARY"], mask2); + if (!inputOnly) { + xcb_set_selection_owner(m_connection, window, HYPRATOMS[atomName], XCB_TIME_CURRENT_TIME); + xcb_xfixes_select_selection_input(m_connection, window, HYPRATOMS[atomName], xfixesMask); + } - m_primarySelection.listeners.setSelection = g_pSeatManager->m_events.setPrimarySelection.registerListener([this](std::any d) { m_primarySelection.onSelection(); }); - m_primarySelection.listeners.keyboardFocusChange = g_pSeatManager->m_events.keyboardFocusChange.registerListener([this](std::any d) { m_primarySelection.onKeyboardFocus(); }); + return window; + }; - m_dndSelection.window = xcb_generate_id(m_connection); - xcb_create_window(m_connection, XCB_COPY_FROM_PARENT, m_dndSelection.window, m_screen->root, 0, 0, 8192, 8192, 0, XCB_WINDOW_CLASS_INPUT_ONLY, m_screen->root_visual, - XCB_CW_EVENT_MASK, mask); + createSelectionWindow(m_clipboard.window, "CLIPBOARD_MANAGER"); + m_clipboard.listeners.setSelection = g_pSeatManager->m_events.setSelection.registerListener([this](std::any) { m_clipboard.onSelection(); }); + m_clipboard.listeners.keyboardFocusChange = g_pSeatManager->m_events.keyboardFocusChange.registerListener([this](std::any) { m_clipboard.onKeyboardFocus(); }); - uint32_t val1 = XDND_VERSION; - xcb_change_property(m_connection, XCB_PROP_MODE_REPLACE, m_dndSelection.window, HYPRATOMS["XdndAware"], XCB_ATOM_ATOM, 32, 1, &val1); + createSelectionWindow(m_primarySelection.window, "PRIMARY"); + m_primarySelection.listeners.setSelection = g_pSeatManager->m_events.setPrimarySelection.registerListener([this](std::any) { m_primarySelection.onSelection(); }); + m_primarySelection.listeners.keyboardFocusChange = g_pSeatManager->m_events.keyboardFocusChange.registerListener([this](std::any) { m_primarySelection.onKeyboardFocus(); }); + + createSelectionWindow(m_dndSelection.window, "XdndAware", true); + const uint32_t xdndVersion = XDND_VERSION; + xcb_change_property(m_connection, XCB_PROP_MODE_REPLACE, m_dndSelection.window, HYPRATOMS["XdndAware"], XCB_ATOM_ATOM, 32, 1, &xdndVersion); } void CXWM::setClipboardToWayland(SXSelection& sel) { @@ -1332,18 +1356,27 @@ SP CXWM::createX11DataOffer(SP surf, SPm_wm->m_clipboard && g_pSeatManager->m_selection.currentSelection && g_pSeatManager->m_selection.currentSelection->type() == DATA_SOURCE_TYPE_X11) || - (this == &g_pXWayland->m_wm->m_primarySelection && g_pSeatManager->m_selection.currentPrimarySelection && - g_pSeatManager->m_selection.currentPrimarySelection->type() == DATA_SOURCE_TYPE_X11)) + const bool isClipboard = this == &g_pXWayland->m_wm->m_clipboard; + const bool isPrimary = this == &g_pXWayland->m_wm->m_primarySelection; + + auto currentSel = g_pSeatManager->m_selection.currentSelection; + auto currentPrimSel = g_pSeatManager->m_selection.currentPrimarySelection; + + const bool isX11Clipboard = isClipboard && currentSel && currentSel->type() == DATA_SOURCE_TYPE_X11; + const bool isX11Primary = isPrimary && currentPrimSel && currentPrimSel->type() == DATA_SOURCE_TYPE_X11; + + if (isX11Clipboard || isX11Primary) return; - if (this == &g_pXWayland->m_wm->m_clipboard && g_pSeatManager->m_selection.currentSelection) { - xcb_set_selection_owner(g_pXWayland->m_wm->m_connection, g_pXWayland->m_wm->m_clipboard.window, HYPRATOMS["CLIPBOARD"], XCB_TIME_CURRENT_TIME); - xcb_flush(g_pXWayland->m_wm->m_connection); + xcb_connection_t* conn = g_pXWayland->m_wm->m_connection; + + if (isClipboard && currentSel) { + xcb_set_selection_owner(conn, g_pXWayland->m_wm->m_clipboard.window, HYPRATOMS["CLIPBOARD"], XCB_TIME_CURRENT_TIME); + xcb_flush(conn); g_pXWayland->m_wm->m_clipboard.notifyOnFocus = true; - } else if (this == &g_pXWayland->m_wm->m_primarySelection && g_pSeatManager->m_selection.currentPrimarySelection) { - xcb_set_selection_owner(g_pXWayland->m_wm->m_connection, g_pXWayland->m_wm->m_primarySelection.window, HYPRATOMS["PRIMARY"], XCB_TIME_CURRENT_TIME); - xcb_flush(g_pXWayland->m_wm->m_connection); + } else if (isPrimary && currentPrimSel) { + xcb_set_selection_owner(conn, g_pXWayland->m_wm->m_primarySelection.window, HYPRATOMS["PRIMARY"], XCB_TIME_CURRENT_TIME); + xcb_flush(conn); g_pXWayland->m_wm->m_primarySelection.notifyOnFocus = true; } } From 16c62a6dbb5f8eee4dcfe903e743f6f144971c06 Mon Sep 17 00:00:00 2001 From: Kamikadze <40305144+Kam1k4dze@users.noreply.github.com> Date: Mon, 2 Jun 2025 01:03:53 +0500 Subject: [PATCH 1337/2181] internal: Fix HyprError not displaying at startup (#10606) --- src/render/OpenGL.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/src/render/OpenGL.cpp b/src/render/OpenGL.cpp index d589e3cf..817944ef 100644 --- a/src/render/OpenGL.cpp +++ b/src/render/OpenGL.cpp @@ -1183,7 +1183,6 @@ bool CHyprOpenGLImpl::initShaders() { m_shadersInitialized = true; Debug::log(LOG, "Shaders initialized successfully."); - g_pHyprError->destroy(); return true; } From ef2c73af80d37265babc3287b3e5502a40c39374 Mon Sep 17 00:00:00 2001 From: Kamikadze <40305144+Kam1k4dze@users.noreply.github.com> Date: Mon, 2 Jun 2025 22:36:44 +0500 Subject: [PATCH 1338/2181] internal: embed example config (#10608) --- src/config/ConfigManager.cpp | 2 +- src/config/defaultConfig.hpp | 313 +---------------------------------- 2 files changed, 8 insertions(+), 307 deletions(-) diff --git a/src/config/ConfigManager.cpp b/src/config/ConfigManager.cpp index f7fed52f..8dce9f30 100644 --- a/src/config/ConfigManager.cpp +++ b/src/config/ConfigManager.cpp @@ -849,7 +849,7 @@ std::optional CConfigManager::generateConfig(std::string configPath Debug::log(WARN, "No config file found; attempting to generate."); std::ofstream ofs; ofs.open(configPath, std::ios::trunc); - ofs << AUTOCONFIG; + ofs << AUTOGENERATED_PREFIX << EXAMPLE_CONFIG; ofs.close(); if (!std::filesystem::exists(configPath)) diff --git a/src/config/defaultConfig.hpp b/src/config/defaultConfig.hpp index a9ea6694..8bdfea39 100644 --- a/src/config/defaultConfig.hpp +++ b/src/config/defaultConfig.hpp @@ -2,316 +2,17 @@ #include -inline const std::string AUTOCONFIG = R"#( +inline constexpr std::string_view AUTOGENERATED_PREFIX = R"#( # ####################################################################################### # AUTOGENERATED HYPRLAND CONFIG. -# PLEASE USE THE CONFIG PROVIDED IN THE GIT REPO /examples/hyprland.conf AND EDIT IT, -# OR EDIT THIS ONE ACCORDING TO THE WIKI INSTRUCTIONS. +# EDIT THIS CONFIG ACCORDING TO THE WIKI INSTRUCTIONS. # ####################################################################################### autogenerated = 1 # remove this line to remove the warning -# This is an example Hyprland config file. -# Refer to the wiki for more information. -# https://wiki.hyprland.org/Configuring/ - -# Please note not all available settings / options are set here. -# For a full list, see the wiki - -# You can split this configuration into multiple files -# Create your files separately and then link them to this file like this: -# source = ~/.config/hypr/myColors.conf - - -################ -### MONITORS ### -################ - -# See https://wiki.hyprland.org/Configuring/Monitors/ -monitor=,preferred,auto,auto - - -################### -### MY PROGRAMS ### -################### - -# See https://wiki.hyprland.org/Configuring/Keywords/ - -# Set programs that you use -$terminal = kitty -$fileManager = dolphin -$menu = wofi --show drun - - -################# -### AUTOSTART ### -################# - -# Autostart necessary processes (like notifications daemons, status bars, etc.) -# Or execute your favorite apps at launch like this: - -# exec-once = $terminal -# exec-once = nm-applet & -# exec-once = waybar & hyprpaper & firefox - - -############################# -### ENVIRONMENT VARIABLES ### -############################# - -# See https://wiki.hyprland.org/Configuring/Environment-variables/ - -env = XCURSOR_SIZE,24 -env = HYPRCURSOR_SIZE,24 - - -################### -### PERMISSIONS ### -################### - -# See https://wiki.hyprland.org/Configuring/Permissions/ -# Please note permission changes here require a Hyprland restart and are not applied on-the-fly -# for security reasons - -# ecosystem { -# enforce_permissions = 1 -# } - -# permission = /usr/(bin|local/bin)/grim, screencopy, allow -# permission = /usr/(lib|libexec|lib64)/xdg-desktop-portal-hyprland, screencopy, allow -# permission = /usr/(bin|local/bin)/hyprpm, plugin, allow - - -##################### -### LOOK AND FEEL ### -##################### - -# Refer to https://wiki.hyprland.org/Configuring/Variables/ - -# https://wiki.hyprland.org/Configuring/Variables/#general -general { - gaps_in = 5 - gaps_out = 20 - - border_size = 2 - - # https://wiki.hyprland.org/Configuring/Variables/#variable-types for info about colors - col.active_border = rgba(33ccffee) rgba(00ff99ee) 45deg - col.inactive_border = rgba(595959aa) - - # Set to true enable resizing windows by clicking and dragging on borders and gaps - resize_on_border = false - - # Please see https://wiki.hyprland.org/Configuring/Tearing/ before you turn this on - allow_tearing = false - - layout = dwindle -} - -# https://wiki.hyprland.org/Configuring/Variables/#decoration -decoration { - rounding = 10 - rounding_power = 2 - - # Change transparency of focused and unfocused windows - active_opacity = 1.0 - inactive_opacity = 1.0 - - shadow { - enabled = true - range = 4 - render_power = 3 - color = rgba(1a1a1aee) - } - - # https://wiki.hyprland.org/Configuring/Variables/#blur - blur { - enabled = true - size = 3 - passes = 1 - - vibrancy = 0.1696 - } -} - -# https://wiki.hyprland.org/Configuring/Variables/#animations -animations { - enabled = yes, please :) - - # Default animations, see https://wiki.hyprland.org/Configuring/Animations/ for more - - bezier = easeOutQuint,0.23,1,0.32,1 - bezier = easeInOutCubic,0.65,0.05,0.36,1 - bezier = linear,0,0,1,1 - bezier = almostLinear,0.5,0.5,0.75,1.0 - bezier = quick,0.15,0,0.1,1 - - animation = global, 1, 10, default - animation = border, 1, 5.39, easeOutQuint - animation = windows, 1, 4.79, easeOutQuint - animation = windowsIn, 1, 4.1, easeOutQuint, popin 87% - animation = windowsOut, 1, 1.49, linear, popin 87% - animation = fadeIn, 1, 1.73, almostLinear - animation = fadeOut, 1, 1.46, almostLinear - animation = fade, 1, 3.03, quick - animation = layers, 1, 3.81, easeOutQuint - animation = layersIn, 1, 4, easeOutQuint, fade - animation = layersOut, 1, 1.5, linear, fade - animation = fadeLayersIn, 1, 1.79, almostLinear - animation = fadeLayersOut, 1, 1.39, almostLinear - animation = workspaces, 1, 1.94, almostLinear, fade - animation = workspacesIn, 1, 1.21, almostLinear, fade - animation = workspacesOut, 1, 1.94, almostLinear, fade -} - -# Ref https://wiki.hyprland.org/Configuring/Workspace-Rules/ -# "Smart gaps" / "No gaps when only" -# uncomment all if you wish to use that. -# workspace = w[tv1], gapsout:0, gapsin:0 -# workspace = f[1], gapsout:0, gapsin:0 -# windowrule = bordersize 0, floating:0, onworkspace:w[tv1] -# windowrule = rounding 0, floating:0, onworkspace:w[tv1] -# windowrule = bordersize 0, floating:0, onworkspace:f[1] -# windowrule = rounding 0, floating:0, onworkspace:f[1] - -# See https://wiki.hyprland.org/Configuring/Dwindle-Layout/ for more -dwindle { - pseudotile = true # Master switch for pseudotiling. Enabling is bound to mainMod + P in the keybinds section below - preserve_split = true # You probably want this -} - -# See https://wiki.hyprland.org/Configuring/Master-Layout/ for more -master { - new_status = master -} - -# https://wiki.hyprland.org/Configuring/Variables/#misc -misc { - force_default_wallpaper = -1 # Set to 0 or 1 to disable the anime mascot wallpapers - disable_hyprland_logo = false # If true disables the random hyprland logo / anime girl background. :( -} - - -############# -### INPUT ### -############# - -# https://wiki.hyprland.org/Configuring/Variables/#input -input { - kb_layout = us - kb_variant = - kb_model = - kb_options = - kb_rules = - - follow_mouse = 1 - - sensitivity = 0 # -1.0 - 1.0, 0 means no modification. - - touchpad { - natural_scroll = false - } -} - -# https://wiki.hyprland.org/Configuring/Variables/#gestures -gestures { - workspace_swipe = false -} - -# Example per-device config -# See https://wiki.hyprland.org/Configuring/Keywords/#per-device-input-configs for more -device { - name = epic-mouse-v1 - sensitivity = -0.5 -} - - -################### -### KEYBINDINGS ### -################### - -# See https://wiki.hyprland.org/Configuring/Keywords/ -$mainMod = SUPER # Sets "Windows" key as main modifier - -# Example binds, see https://wiki.hyprland.org/Configuring/Binds/ for more -bind = $mainMod, Q, exec, $terminal -bind = $mainMod, C, killactive, -bind = $mainMod, M, exit, -bind = $mainMod, E, exec, $fileManager -bind = $mainMod, V, togglefloating, -bind = $mainMod, R, exec, $menu -bind = $mainMod, P, pseudo, # dwindle -bind = $mainMod, J, togglesplit, # dwindle - -# Move focus with mainMod + arrow keys -bind = $mainMod, left, movefocus, l -bind = $mainMod, right, movefocus, r -bind = $mainMod, up, movefocus, u -bind = $mainMod, down, movefocus, d - -# Switch workspaces with mainMod + [0-9] -bind = $mainMod, 1, workspace, 1 -bind = $mainMod, 2, workspace, 2 -bind = $mainMod, 3, workspace, 3 -bind = $mainMod, 4, workspace, 4 -bind = $mainMod, 5, workspace, 5 -bind = $mainMod, 6, workspace, 6 -bind = $mainMod, 7, workspace, 7 -bind = $mainMod, 8, workspace, 8 -bind = $mainMod, 9, workspace, 9 -bind = $mainMod, 0, workspace, 10 - -# Move active window to a workspace with mainMod + SHIFT + [0-9] -bind = $mainMod SHIFT, 1, movetoworkspace, 1 -bind = $mainMod SHIFT, 2, movetoworkspace, 2 -bind = $mainMod SHIFT, 3, movetoworkspace, 3 -bind = $mainMod SHIFT, 4, movetoworkspace, 4 -bind = $mainMod SHIFT, 5, movetoworkspace, 5 -bind = $mainMod SHIFT, 6, movetoworkspace, 6 -bind = $mainMod SHIFT, 7, movetoworkspace, 7 -bind = $mainMod SHIFT, 8, movetoworkspace, 8 -bind = $mainMod SHIFT, 9, movetoworkspace, 9 -bind = $mainMod SHIFT, 0, movetoworkspace, 10 - -# Example special workspace (scratchpad) -bind = $mainMod, S, togglespecialworkspace, magic -bind = $mainMod SHIFT, S, movetoworkspace, special:magic - -# Scroll through existing workspaces with mainMod + scroll -bind = $mainMod, mouse_down, workspace, e+1 -bind = $mainMod, mouse_up, workspace, e-1 - -# Move/resize windows with mainMod + LMB/RMB and dragging -bindm = $mainMod, mouse:272, movewindow -bindm = $mainMod, mouse:273, resizewindow - -# Laptop multimedia keys for volume and LCD brightness -bindel = ,XF86AudioRaiseVolume, exec, wpctl set-volume -l 1 @DEFAULT_AUDIO_SINK@ 5%+ -bindel = ,XF86AudioLowerVolume, exec, wpctl set-volume @DEFAULT_AUDIO_SINK@ 5%- -bindel = ,XF86AudioMute, exec, wpctl set-mute @DEFAULT_AUDIO_SINK@ toggle -bindel = ,XF86AudioMicMute, exec, wpctl set-mute @DEFAULT_AUDIO_SOURCE@ toggle -bindel = ,XF86MonBrightnessUp, exec, brightnessctl -e4 -n2 set 5%+ -bindel = ,XF86MonBrightnessDown, exec, brightnessctl -e4 -n2 set 5%- - -# Requires playerctl -bindl = , XF86AudioNext, exec, playerctl next -bindl = , XF86AudioPause, exec, playerctl play-pause -bindl = , XF86AudioPlay, exec, playerctl play-pause -bindl = , XF86AudioPrev, exec, playerctl previous - -############################## -### WINDOWS AND WORKSPACES ### -############################## - -# See https://wiki.hyprland.org/Configuring/Window-Rules/ for more -# See https://wiki.hyprland.org/Configuring/Workspace-Rules/ for workspace rules - -# Example windowrule -# windowrule = float,class:^(kitty)$,title:^(kitty)$ - -# Ignore maximize requests from apps. You'll probably like this. -windowrule = suppressevent maximize, class:.* - -# Fix some dragging issues with XWayland -windowrule = nofocus,class:^$,title:^$,xwayland:1,floating:1,fullscreen:0,pinned:0 )#"; +inline constexpr char EXAMPLE_CONFIG_BYTES[] = { +#embed "../../example/hyprland.conf" +}; + +inline constexpr std::string_view EXAMPLE_CONFIG = {EXAMPLE_CONFIG_BYTES, sizeof(EXAMPLE_CONFIG_BYTES)}; From b1d0a727cc594e5329c5971d73391c7529e1c80e Mon Sep 17 00:00:00 2001 From: sam Date: Tue, 3 Jun 2025 02:22:51 +0800 Subject: [PATCH 1339/2181] internal: Center window on parent if available (#10582) Fixes #10537 --- src/layout/IHyprLayout.cpp | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/layout/IHyprLayout.cpp b/src/layout/IHyprLayout.cpp index fbde7344..40794b3e 100644 --- a/src/layout/IHyprLayout.cpp +++ b/src/layout/IHyprLayout.cpp @@ -158,6 +158,7 @@ void IHyprLayout::onWindowCreatedFloating(PHLWINDOW pWindow) { } // TODO: detect a popup in a more consistent way. + bool centeredOnParent = false; if ((desiredGeometry.x == 0 && desiredGeometry.y == 0) || !visible || !pWindow->m_isX11) { // if the pos isn't set, fall back to the center placement if it's not a child auto pos = PMONITOR->m_position + PMONITOR->m_size / 2.F - desiredGeometry.size() / 2.F; @@ -168,10 +169,11 @@ void IHyprLayout::onWindowCreatedFloating(PHLWINDOW pWindow) { *pWindow->m_realPosition = PARENT->m_realPosition->goal() + PARENT->m_realSize->goal() / 2.F - desiredGeometry.size() / 2.F; pWindow->m_workspace = PARENT->m_workspace; pWindow->m_monitor = PARENT->m_monitor; + centeredOnParent = true; } } - - *pWindow->m_realPosition = pos; + if (!centeredOnParent) + *pWindow->m_realPosition = pos; } else { // if it is, we respect where it wants to put itself, but apply monitor offset if outside // most of these are popups From b5c0d0b8aa8bb095ac447bf6c73486cb1c172b6e Mon Sep 17 00:00:00 2001 From: littleblack111 Date: Wed, 4 Jun 2025 02:48:56 +0800 Subject: [PATCH 1340/2181] keybinds: add an option to respect gaps out for floating to movewindow (#9360) --- src/config/ConfigDescriptions.hpp | 7 +++++++ src/config/ConfigManager.cpp | 3 +++ src/config/ConfigManager.hpp | 1 + src/managers/KeybindManager.cpp | 21 +++++++++++++++------ 4 files changed, 26 insertions(+), 6 deletions(-) diff --git a/src/config/ConfigDescriptions.hpp b/src/config/ConfigDescriptions.hpp index a77cf757..98214284 100644 --- a/src/config/ConfigDescriptions.hpp +++ b/src/config/ConfigDescriptions.hpp @@ -32,6 +32,13 @@ inline static const std::vector CONFIG_OPTIONS = { .type = CONFIG_OPTION_STRING_SHORT, .data = SConfigOptionDescription::SStringData{"20"}, }, + SConfigOptionDescription{ + .value = "general:float_gaps", + .description = "gaps between windows and monitor edges for floating windows\n\nsupports css style gaps (top, right, bottom, left -> 5 10 15 20). \n-1 means default " + "gaps_in/gaps_out\n0 means no gaps", + .type = CONFIG_OPTION_STRING_SHORT, + .data = SConfigOptionDescription::SStringData{"0"}, + }, SConfigOptionDescription{ .value = "general:gaps_workspaces", .description = "gaps between workspaces. Stacks with gaps_out.", diff --git a/src/config/ConfigManager.cpp b/src/config/ConfigManager.cpp index 8dce9f30..e2fb26ab 100644 --- a/src/config/ConfigManager.cpp +++ b/src/config/ConfigManager.cpp @@ -444,6 +444,7 @@ CConfigManager::CConfigManager() { registerConfigVar("general:no_border_on_floating", Hyprlang::INT{0}); registerConfigVar("general:gaps_in", Hyprlang::CConfigCustomValueType{configHandleGapSet, configHandleGapDestroy, "5"}); registerConfigVar("general:gaps_out", Hyprlang::CConfigCustomValueType{configHandleGapSet, configHandleGapDestroy, "20"}); + registerConfigVar("general:float_gaps", Hyprlang::CConfigCustomValueType{configHandleGapSet, configHandleGapDestroy, "0"}); registerConfigVar("general:gaps_workspaces", Hyprlang::INT{0}); registerConfigVar("general:no_focus_fallback", Hyprlang::INT{0}); registerConfigVar("general:resize_on_border", Hyprlang::INT{0}); @@ -1318,6 +1319,8 @@ SWorkspaceRule CConfigManager::mergeWorkspaceRules(const SWorkspaceRule& rule1, mergedRule.gapsIn = rule2.gapsIn; if (rule2.gapsOut.has_value()) mergedRule.gapsOut = rule2.gapsOut; + if (rule2.floatGaps) + mergedRule.floatGaps = rule2.floatGaps; if (rule2.borderSize.has_value()) mergedRule.borderSize = rule2.borderSize; if (rule2.noBorder.has_value()) diff --git a/src/config/ConfigManager.hpp b/src/config/ConfigManager.hpp index 5cb95bac..134292e5 100644 --- a/src/config/ConfigManager.hpp +++ b/src/config/ConfigManager.hpp @@ -36,6 +36,7 @@ struct SWorkspaceRule { bool isPersistent = false; std::optional gapsIn; std::optional gapsOut; + std::optional floatGaps = gapsOut; std::optional borderSize; std::optional decorate; std::optional noRounding; diff --git a/src/managers/KeybindManager.cpp b/src/managers/KeybindManager.cpp index 976e292d..43558d9d 100644 --- a/src/managers/KeybindManager.cpp +++ b/src/managers/KeybindManager.cpp @@ -1682,16 +1682,25 @@ SDispatchResult CKeybindManager::moveActiveTo(std::string args) { if (PLASTWINDOW->m_isFloating) { std::optional vPosx, vPosy; - const auto PMONITOR = PLASTWINDOW->m_monitor.lock(); - const auto BORDERSIZE = PLASTWINDOW->getRealBorderSize(); + const auto PMONITOR = PLASTWINDOW->m_monitor.lock(); + const auto BORDERSIZE = PLASTWINDOW->getRealBorderSize(); + static auto PGAPSCUSTOMDATA = CConfigValue("general:float_gaps"); + static auto PGAPSOUTDATA = CConfigValue("general:gaps_out"); + auto* PGAPSOUT = (CCssGapData*)PGAPSCUSTOMDATA.ptr()->getData(); + if (PGAPSOUT->m_left < 0 || PGAPSOUT->m_right < 0 || PGAPSOUT->m_top < 0 || PGAPSOUT->m_bottom < 0) + PGAPSOUT = (CCssGapData*)PGAPSOUTDATA.ptr()->getData(); switch (arg) { - case 'l': vPosx = PMONITOR->m_reservedTopLeft.x + BORDERSIZE + PMONITOR->m_position.x; break; - case 'r': vPosx = PMONITOR->m_size.x - PMONITOR->m_reservedBottomRight.x - PLASTWINDOW->m_realSize->goal().x - BORDERSIZE + PMONITOR->m_position.x; break; + case 'l': vPosx = PMONITOR->m_reservedTopLeft.x + BORDERSIZE + PMONITOR->m_position.x + PGAPSOUT->m_left; break; + case 'r': + vPosx = PMONITOR->m_size.x - PMONITOR->m_reservedBottomRight.x - PLASTWINDOW->m_realSize->goal().x - BORDERSIZE + PMONITOR->m_position.x - PGAPSOUT->m_right; + break; case 't': - case 'u': vPosy = PMONITOR->m_reservedTopLeft.y + BORDERSIZE + PMONITOR->m_position.y; break; + case 'u': vPosy = PMONITOR->m_reservedTopLeft.y + BORDERSIZE + PMONITOR->m_position.y + PGAPSOUT->m_top; break; case 'b': - case 'd': vPosy = PMONITOR->m_size.y - PMONITOR->m_reservedBottomRight.y - PLASTWINDOW->m_realSize->goal().y - BORDERSIZE + PMONITOR->m_position.y; break; + case 'd': + vPosy = PMONITOR->m_size.y - PMONITOR->m_reservedBottomRight.y - PLASTWINDOW->m_realSize->goal().y - BORDERSIZE + PMONITOR->m_position.y - PGAPSOUT->m_bottom; + break; } *PLASTWINDOW->m_realPosition = Vector2D(vPosx.value_or(PLASTWINDOW->m_realPosition->goal().x), vPosy.value_or(PLASTWINDOW->m_realPosition->goal().y)); From d9f7448d82132f4c1c07105f4bc3a4f717915d30 Mon Sep 17 00:00:00 2001 From: vaxerski Date: Wed, 4 Jun 2025 16:54:12 +0200 Subject: [PATCH 1341/2181] xwayland: pad pid with leading zeroes in lockfile fixes #10652 --- src/xwayland/Server.cpp | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/xwayland/Server.cpp b/src/xwayland/Server.cpp index 814bd20c..0cc16fef 100644 --- a/src/xwayland/Server.cpp +++ b/src/xwayland/Server.cpp @@ -199,8 +199,9 @@ bool CXWaylandServer::tryOpenSockets() { continue; } - const std::string pidStr = std::to_string(getpid()); - if (write(fd.get(), pidStr.c_str(), pidStr.length()) != (long)pidStr.length()) { + const std::string pidStr = std::format("{:010d}\n", getpid()); + ASSERT(pidStr.length() == 11); + if (write(fd.get(), pidStr.c_str(), 11) != 11L) { safeRemove(lockPath); continue; } From d7a87ce6e2535f1029fc93b062d2828e8549c525 Mon Sep 17 00:00:00 2001 From: Jasson Date: Wed, 4 Jun 2025 11:00:55 -0400 Subject: [PATCH 1342/2181] xwayland: fix xwayland -> wayland clipboard (#10646) --- src/xwayland/XWM.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/src/xwayland/XWM.cpp b/src/xwayland/XWM.cpp index 5b423dca..1da8c71e 100644 --- a/src/xwayland/XWM.cpp +++ b/src/xwayland/XWM.cpp @@ -1214,6 +1214,7 @@ void CXWM::initSelection() { }; createSelectionWindow(m_clipboard.window, "CLIPBOARD_MANAGER"); + createSelectionWindow(m_clipboard.window, "CLIPBOARD"); m_clipboard.listeners.setSelection = g_pSeatManager->m_events.setSelection.registerListener([this](std::any) { m_clipboard.onSelection(); }); m_clipboard.listeners.keyboardFocusChange = g_pSeatManager->m_events.keyboardFocusChange.registerListener([this](std::any) { m_clipboard.onKeyboardFocus(); }); From 59c886d85500cf4c8ae11eaf2ebe50ec25b596f6 Mon Sep 17 00:00:00 2001 From: sam Date: Thu, 5 Jun 2025 22:19:54 +0800 Subject: [PATCH 1343/2181] internal: Catch filesystem exceptions while iterating RunTimeDir (#10648) --- hyprctl/main.cpp | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/hyprctl/main.cpp b/hyprctl/main.cpp index 25a4eef3..4a8b9819 100644 --- a/hyprctl/main.cpp +++ b/hyprctl/main.cpp @@ -72,10 +72,13 @@ std::vector instances() { return {}; } catch (std::exception& e) { return {}; } - for (const auto& el : std::filesystem::directory_iterator(getRuntimeDir())) { + std::error_code ec; + std::filesystem::directory_iterator it = std::filesystem::directory_iterator(getRuntimeDir(), std::filesystem::directory_options::skip_permission_denied, ec); + if (ec) + return {}; + for (const auto& el : it) { if (!el.is_directory() || !std::filesystem::exists(el.path().string() + "/hyprland.lock")) continue; - // read lock SInstanceData* data = &result.emplace_back(); data->id = el.path().filename().string(); From abdfc5ea40c0793117f34bf6c465840500cf7cb0 Mon Sep 17 00:00:00 2001 From: UjinT34 <41110182+UjinT34@users.noreply.github.com> Date: Thu, 5 Jun 2025 17:56:46 +0300 Subject: [PATCH 1344/2181] config: add a new monitor v2 config syntax (#9761) --- src/config/ConfigManager.cpp | 443 ++++++++++++++++++++++------------- src/config/ConfigManager.hpp | 33 +++ src/debug/HyprCtl.cpp | 3 + 3 files changed, 322 insertions(+), 157 deletions(-) diff --git a/src/config/ConfigManager.cpp b/src/config/ConfigManager.cpp index e2fb26ab..735d9703 100644 --- a/src/config/ConfigManager.cpp +++ b/src/config/ConfigManager.cpp @@ -791,6 +791,20 @@ CConfigManager::CConfigManager() { m_config->addSpecialConfigValue("device", "flip_y", Hyprlang::INT{0}); // only for touchpads m_config->addSpecialConfigValue("device", "keybinds", Hyprlang::INT{1}); // enable/disable keybinds + m_config->addSpecialCategory("monitorv2", {.key = "output"}); + m_config->addSpecialConfigValue("monitorv2", "disabled", Hyprlang::INT{0}); + m_config->addSpecialConfigValue("monitorv2", "mode", {"preferred"}); + m_config->addSpecialConfigValue("monitorv2", "position", {"auto"}); + m_config->addSpecialConfigValue("monitorv2", "scale", Hyprlang::FLOAT{1.0}); + m_config->addSpecialConfigValue("monitorv2", "addreserved", {STRVAL_EMPTY}); + m_config->addSpecialConfigValue("monitorv2", "mirror", {STRVAL_EMPTY}); + m_config->addSpecialConfigValue("monitorv2", "bitdepth", {STRVAL_EMPTY}); // TODO use correct type + m_config->addSpecialConfigValue("monitorv2", "cm", {"auto"}); + m_config->addSpecialConfigValue("monitorv2", "sdrbrightness", Hyprlang::FLOAT{1.0}); + m_config->addSpecialConfigValue("monitorv2", "sdrsaturation", Hyprlang::FLOAT{1.0}); + m_config->addSpecialConfigValue("monitorv2", "vrr", Hyprlang::INT{0}); + m_config->addSpecialConfigValue("monitorv2", "transform", {STRVAL_EMPTY}); // TODO use correct type + // keywords m_config->registerHandler(&::handleExec, "exec", {false}); m_config->registerHandler(&::handleRawExec, "execr", {false}); @@ -918,8 +932,9 @@ void CConfigManager::reload() { resetHLConfig(); m_configCurrentPath = getMainConfigPath(); const auto ERR = m_config->parse(); - m_lastConfigVerificationWasSuccessful = !ERR.error; - postConfigReload(ERR); + const auto monitorError = handleMonitorv2(); + m_lastConfigVerificationWasSuccessful = !ERR.error && !monitorError.error; + postConfigReload(ERR.error || !monitorError.error ? ERR : monitorError); } std::string CConfigManager::verify() { @@ -1009,6 +1024,68 @@ void CConfigManager::updateWatcher() { g_pConfigWatcher->setWatchList(*PDISABLEAUTORELOAD ? std::vector{} : m_configPaths); } +std::optional CConfigManager::handleMonitorv2(const std::string& output) { + auto parser = CMonitorRuleParser(output); + auto VAL = m_config->getSpecialConfigValuePtr("monitorv2", "disabled", output.c_str()); + if (VAL && VAL->m_bSetByUser && std::any_cast(VAL->getValue())) + parser.setDisabled(); + VAL = m_config->getSpecialConfigValuePtr("monitorv2", "mode", output.c_str()); + if (VAL && VAL->m_bSetByUser) + parser.parseMode(std::any_cast(VAL->getValue())); + VAL = m_config->getSpecialConfigValuePtr("monitorv2", "position", output.c_str()); + if (VAL && VAL->m_bSetByUser) + parser.parsePosition(std::any_cast(VAL->getValue())); + VAL = m_config->getSpecialConfigValuePtr("monitorv2", "scale", output.c_str()); + if (VAL && VAL->m_bSetByUser) + parser.rule().scale = std::any_cast(VAL->getValue()); + VAL = m_config->getSpecialConfigValuePtr("monitorv2", "addreserved", output.c_str()); + if (VAL && VAL->m_bSetByUser) { + const auto ARGS = CVarList(std::any_cast(VAL->getValue())); + parser.setReserved({.top = std::stoi(ARGS[0]), .bottom = std::stoi(ARGS[1]), .left = std::stoi(ARGS[2]), .right = std::stoi(ARGS[3])}); + } + VAL = m_config->getSpecialConfigValuePtr("monitorv2", "mirror", output.c_str()); + if (VAL && VAL->m_bSetByUser) + parser.setMirror(std::any_cast(VAL->getValue())); + VAL = m_config->getSpecialConfigValuePtr("monitorv2", "bitdepth", output.c_str()); + if (VAL && VAL->m_bSetByUser) + parser.parseBitdepth(std::any_cast(VAL->getValue())); + VAL = m_config->getSpecialConfigValuePtr("monitorv2", "cm", output.c_str()); + if (VAL && VAL->m_bSetByUser) + parser.parseCM(std::any_cast(VAL->getValue())); + VAL = m_config->getSpecialConfigValuePtr("monitorv2", "sdrbrightness", output.c_str()); + if (VAL && VAL->m_bSetByUser) + parser.rule().sdrBrightness = std::any_cast(VAL->getValue()); + VAL = m_config->getSpecialConfigValuePtr("monitorv2", "sdrsaturation", output.c_str()); + if (VAL && VAL->m_bSetByUser) + parser.rule().sdrSaturation = std::any_cast(VAL->getValue()); + VAL = m_config->getSpecialConfigValuePtr("monitorv2", "vrr", output.c_str()); + if (VAL && VAL->m_bSetByUser) + parser.rule().vrr = std::any_cast(VAL->getValue()); + VAL = m_config->getSpecialConfigValuePtr("monitorv2", "transform", output.c_str()); + if (VAL && VAL->m_bSetByUser) + parser.parseTransform(std::any_cast(VAL->getValue())); + + auto newrule = parser.rule(); + + std::erase_if(m_monitorRules, [&](const auto& other) { return other.name == newrule.name; }); + + m_monitorRules.push_back(newrule); + + return parser.getError(); +} + +Hyprlang::CParseResult CConfigManager::handleMonitorv2() { + Hyprlang::CParseResult result; + for (const auto& output : m_config->listKeysForSpecialCategory("monitorv2")) { + const auto error = handleMonitorv2(output); + if (error.has_value()) { + result.setError(error.value().c_str()); + return result; + } + } + return result; +} + void CConfigManager::postConfigReload(const Hyprlang::CParseResult& result) { static const auto PENABLEEXPLICIT = CConfigValue("render:explicit_sync"); static int prevEnabledExplicit = *PENABLEEXPLICIT; @@ -1607,6 +1684,7 @@ void CConfigManager::dispatchExecShutdown() { } void CConfigManager::performMonitorReload() { + handleMonitorv2(); bool overAgain = false; @@ -1956,30 +2034,207 @@ static bool parseModeLine(const std::string& modeline, drmModeModeInfo& mode) { return true; } +CMonitorRuleParser::CMonitorRuleParser(const std::string& name) { + m_rule.name = name; +} + +const std::string& CMonitorRuleParser::name() { + return m_rule.name; +} + +SMonitorRule& CMonitorRuleParser::rule() { + return m_rule; +} + +std::optional CMonitorRuleParser::getError() { + if (m_error.empty()) + return {}; + return m_error; +} + +bool CMonitorRuleParser::parseMode(const std::string& value) { + if (value.starts_with("pref")) + m_rule.resolution = Vector2D(); + else if (value.starts_with("highrr")) + m_rule.resolution = Vector2D(-1, -1); + else if (value.starts_with("highres")) + m_rule.resolution = Vector2D(-1, -2); + else if (parseModeLine(value, m_rule.drmMode)) { + m_rule.resolution = Vector2D(m_rule.drmMode.hdisplay, m_rule.drmMode.vdisplay); + m_rule.refreshRate = float(m_rule.drmMode.vrefresh) / 1000; + } else { + + if (!value.contains("x")) { + m_error += "invalid resolution "; + m_rule.resolution = Vector2D(); + return false; + } else { + try { + m_rule.resolution.x = stoi(value.substr(0, value.find_first_of('x'))); + m_rule.resolution.y = stoi(value.substr(value.find_first_of('x') + 1, value.find_first_of('@'))); + + if (value.contains("@")) + m_rule.refreshRate = stof(value.substr(value.find_first_of('@') + 1)); + } catch (...) { + m_error += "invalid resolution "; + m_rule.resolution = Vector2D(); + return false; + } + } + } + return true; +} + +bool CMonitorRuleParser::parsePosition(const std::string& value, bool isFirst) { + if (value.starts_with("auto")) { + m_rule.offset = Vector2D(-INT32_MAX, -INT32_MAX); + // If this is the first monitor rule needs to be on the right. + if (value == "auto-right" || value == "auto" || isFirst) + m_rule.autoDir = eAutoDirs::DIR_AUTO_RIGHT; + else if (value == "auto-left") + m_rule.autoDir = eAutoDirs::DIR_AUTO_LEFT; + else if (value == "auto-up") + m_rule.autoDir = eAutoDirs::DIR_AUTO_UP; + else if (value == "auto-down") + m_rule.autoDir = eAutoDirs::DIR_AUTO_DOWN; + else { + Debug::log(WARN, + "Invalid auto direction. Valid options are 'auto'," + "'auto-up', 'auto-down', 'auto-left', and 'auto-right'."); + m_error += "invalid auto direction "; + return false; + } + } else { + if (!value.contains("x")) { + m_error += "invalid offset "; + m_rule.offset = Vector2D(-INT32_MAX, -INT32_MAX); + return false; + } else { + m_rule.offset.x = stoi(value.substr(0, value.find_first_of('x'))); + m_rule.offset.y = stoi(value.substr(value.find_first_of('x') + 1)); + } + } + return true; +} + +bool CMonitorRuleParser::parseScale(const std::string& value) { + if (value.starts_with("auto")) + m_rule.scale = -1; + else { + if (!isNumber(value, true)) { + m_error += "invalid scale "; + return false; + } else { + m_rule.scale = stof(value); + + if (m_rule.scale < 0.25f) { + m_error += "invalid scale "; + m_rule.scale = 1; + return false; + } + } + } + return true; +} + +bool CMonitorRuleParser::parseTransform(const std::string& value) { + const auto TSF = std::stoi(value); + if (std::clamp(TSF, 0, 7) != TSF) { + Debug::log(ERR, "Invalid transform {} in monitor", TSF); + m_error += "invalid transform "; + return false; + } + m_rule.transform = (wl_output_transform)TSF; + return true; +} + +bool CMonitorRuleParser::parseBitdepth(const std::string& value) { + m_rule.enable10bit = value == "10"; + return true; +} + +bool CMonitorRuleParser::parseCM(const std::string& value) { + if (value == "auto") + m_rule.cmType = CM_AUTO; + else if (value == "srgb") + m_rule.cmType = CM_SRGB; + else if (value == "wide") + m_rule.cmType = CM_WIDE; + else if (value == "edid") + m_rule.cmType = CM_EDID; + else if (value == "hdr") + m_rule.cmType = CM_HDR; + else if (value == "hdredid") + m_rule.cmType = CM_HDR_EDID; + else { + m_error += "invalid cm "; + return false; + } + return true; +} + +bool CMonitorRuleParser::parseSDRBrightness(const std::string& value) { + try { + m_rule.sdrBrightness = stof(value); + } catch (...) { + m_error += "invalid sdrbrightness "; + return false; + } + return true; +} + +bool CMonitorRuleParser::parseSDRSaturation(const std::string& value) { + try { + m_rule.sdrSaturation = stof(value); + } catch (...) { + m_error += "invalid sdrsaturation "; + return false; + } + return true; +} + +bool CMonitorRuleParser::parseVRR(const std::string& value) { + if (!isNumber(value)) { + m_error += "invalid vrr "; + return false; + } + + m_rule.vrr = std::stoi(value); + return true; +} + +void CMonitorRuleParser::setDisabled() { + m_rule.disabled = true; +} + +void CMonitorRuleParser::setMirror(const std::string& value) { + m_rule.mirrorOf = value; +} + +bool CMonitorRuleParser::setReserved(const SMonitorAdditionalReservedArea& value) { + g_pConfigManager->m_mAdditionalReservedAreas[name()] = value; + return true; +} + std::optional CConfigManager::handleMonitor(const std::string& command, const std::string& args) { // get the monitor config - SMonitorRule newrule; + const auto ARGS = CVarList(args); - const auto ARGS = CVarList(args); - - newrule.name = ARGS[0]; + auto parser = CMonitorRuleParser(ARGS[0]); if (ARGS[1] == "disable" || ARGS[1] == "disabled" || ARGS[1] == "addreserved" || ARGS[1] == "transform") { if (ARGS[1] == "disable" || ARGS[1] == "disabled") - newrule.disabled = true; + parser.setDisabled(); else if (ARGS[1] == "transform") { - const auto TSF = std::stoi(ARGS[2]); - if (std::clamp(TSF, 0, 7) != TSF) { - Debug::log(ERR, "Invalid transform {} in monitor", TSF); - return "invalid transform"; - } + if (!parser.parseTransform(ARGS[2])) + return parser.getError(); - const auto TRANSFORM = (wl_output_transform)TSF; + const auto TRANSFORM = parser.rule().transform; // overwrite if exists for (auto& r : m_monitorRules) { - if (r.name == newrule.name) { + if (r.name == parser.name()) { r.transform = TRANSFORM; return {}; } @@ -1987,179 +2242,53 @@ std::optional CConfigManager::handleMonitor(const std::string& comm return {}; } else if (ARGS[1] == "addreserved") { - int top = std::stoi(ARGS[2]); - - int bottom = std::stoi(ARGS[3]); - - int left = std::stoi(ARGS[4]); - - int right = std::stoi(ARGS[5]); - - m_mAdditionalReservedAreas[newrule.name] = {top, bottom, left, right}; - + parser.setReserved({.top = std::stoi(ARGS[2]), .bottom = std::stoi(ARGS[3]), .left = std::stoi(ARGS[4]), .right = std::stoi(ARGS[5])}); return {}; } else { Debug::log(ERR, "ConfigManager parseMonitor, curitem bogus???"); return "parse error: curitem bogus"; } - std::erase_if(m_monitorRules, [&](const auto& other) { return other.name == newrule.name; }); + std::erase_if(m_monitorRules, [&](const auto& other) { return other.name == parser.name(); }); - m_monitorRules.push_back(newrule); + m_monitorRules.push_back(parser.rule()); return {}; } - std::string error = ""; - - if (ARGS[1].starts_with("pref")) { - newrule.resolution = Vector2D(); - } else if (ARGS[1].starts_with("highrr")) { - newrule.resolution = Vector2D(-1, -1); - } else if (ARGS[1].starts_with("highres")) { - newrule.resolution = Vector2D(-1, -2); - } else if (ARGS[1].starts_with("maxwidth")) { - newrule.resolution = Vector2D(-1, -3); - } else if (parseModeLine(ARGS[1], newrule.drmMode)) { - newrule.resolution = Vector2D(newrule.drmMode.hdisplay, newrule.drmMode.vdisplay); - newrule.refreshRate = float(newrule.drmMode.vrefresh) / 1000; - } else { - - if (!ARGS[1].contains("x")) { - error += "invalid resolution "; - newrule.resolution = Vector2D(); - } else { - try { - newrule.resolution.x = stoi(ARGS[1].substr(0, ARGS[1].find_first_of('x'))); - newrule.resolution.y = stoi(ARGS[1].substr(ARGS[1].find_first_of('x') + 1, ARGS[1].find_first_of('@'))); - - if (ARGS[1].contains("@")) - newrule.refreshRate = stof(ARGS[1].substr(ARGS[1].find_first_of('@') + 1)); - } catch (...) { - error += "invalid resolution "; - newrule.resolution = Vector2D(); - } - } - } - - if (ARGS[2].starts_with("auto")) { - newrule.offset = Vector2D(-INT32_MAX, -INT32_MAX); - // If this is the first monitor rule needs to be on the right. - if (ARGS[2] == "auto-right" || ARGS[2] == "auto" || m_monitorRules.empty()) - newrule.autoDir = eAutoDirs::DIR_AUTO_RIGHT; - else if (ARGS[2] == "auto-left") - newrule.autoDir = eAutoDirs::DIR_AUTO_LEFT; - else if (ARGS[2] == "auto-up") - newrule.autoDir = eAutoDirs::DIR_AUTO_UP; - else if (ARGS[2] == "auto-down") - newrule.autoDir = eAutoDirs::DIR_AUTO_DOWN; - else if (ARGS[2] == "auto-center-right") - newrule.autoDir = eAutoDirs::DIR_AUTO_CENTER_RIGHT; - else if (ARGS[2] == "auto-center-left") - newrule.autoDir = eAutoDirs::DIR_AUTO_CENTER_LEFT; - else if (ARGS[2] == "auto-center-up") - newrule.autoDir = eAutoDirs::DIR_AUTO_CENTER_UP; - else if (ARGS[2] == "auto-center-down") - newrule.autoDir = eAutoDirs::DIR_AUTO_CENTER_DOWN; - else { - Debug::log(WARN, - "Invalid auto direction. Valid options are 'auto'," - "'auto-up', 'auto-down', 'auto-left', 'auto-right'," - "'auto-center-up', 'auto-center-down'," - "'auto-center-left', and 'auto-center-right'."); - error += "invalid auto direction "; - } - } else { - if (!ARGS[2].contains("x")) { - error += "invalid offset "; - newrule.offset = Vector2D(-INT32_MAX, -INT32_MAX); - } else { - newrule.offset.x = stoi(ARGS[2].substr(0, ARGS[2].find_first_of('x'))); - newrule.offset.y = stoi(ARGS[2].substr(ARGS[2].find_first_of('x') + 1)); - } - } - - if (ARGS[3].starts_with("auto")) { - newrule.scale = -1; - } else { - if (!isNumber(ARGS[3], true)) - error += "invalid scale "; - else { - newrule.scale = stof(ARGS[3]); - - if (newrule.scale < 0.25f) { - error += "invalid scale "; - newrule.scale = 1; - } - } - } + parser.parseMode(ARGS[1]); + parser.parsePosition(ARGS[2]); + parser.parseScale(ARGS[3]); int argno = 4; while (!ARGS[argno].empty()) { if (ARGS[argno] == "mirror") { - newrule.mirrorOf = ARGS[argno + 1]; + parser.setMirror(ARGS[argno + 1]); argno++; } else if (ARGS[argno] == "bitdepth") { - newrule.enable10bit = ARGS[argno + 1] == "10"; + parser.parseBitdepth(ARGS[argno + 1]); argno++; } else if (ARGS[argno] == "cm") { - if (ARGS[argno + 1] == "auto") - newrule.cmType = CM_AUTO; - else if (ARGS[argno + 1] == "srgb") - newrule.cmType = CM_SRGB; - else if (ARGS[argno + 1] == "wide") - newrule.cmType = CM_WIDE; - else if (ARGS[argno + 1] == "edid") - newrule.cmType = CM_EDID; - else if (ARGS[argno + 1] == "hdr") - newrule.cmType = CM_HDR; - else if (ARGS[argno + 1] == "hdredid") - newrule.cmType = CM_HDR_EDID; - else - error = "invalid cm "; + parser.parseCM(ARGS[argno + 1]); argno++; } else if (ARGS[argno] == "sdrsaturation") { - try { - newrule.sdrSaturation = stof(ARGS[argno + 1]); - } catch (...) { error = "invalid sdrsaturation "; } + parser.parseSDRSaturation(ARGS[argno + 1]); argno++; } else if (ARGS[argno] == "sdrbrightness") { - try { - newrule.sdrBrightness = stof(ARGS[argno + 1]); - } catch (...) { error = "invalid sdrbrightness "; } + parser.parseSDRBrightness(ARGS[argno + 1]); argno++; } else if (ARGS[argno] == "transform") { - if (!isNumber(ARGS[argno + 1])) { - error = "invalid transform "; - argno++; - continue; - } - - const auto NUM = std::stoi(ARGS[argno + 1]); - - if (NUM < 0 || NUM > 7) { - error = "invalid transform "; - argno++; - continue; - } - - newrule.transform = (wl_output_transform)std::stoi(ARGS[argno + 1]); + parser.parseTransform(ARGS[argno + 1]); argno++; } else if (ARGS[argno] == "vrr") { - if (!isNumber(ARGS[argno + 1])) { - error = "invalid vrr "; - argno++; - continue; - } - - newrule.vrr = std::stoi(ARGS[argno + 1]); + parser.parseVRR(ARGS[argno + 1]); argno++; } else if (ARGS[argno] == "workspace") { const auto& [id, name] = getWorkspaceIDNameFromString(ARGS[argno + 1]); SWorkspaceRule wsRule; - wsRule.monitor = newrule.name; + wsRule.monitor = parser.name(); wsRule.workspaceString = ARGS[argno + 1]; wsRule.workspaceId = id; wsRule.workspaceName = name; @@ -2174,13 +2303,13 @@ std::optional CConfigManager::handleMonitor(const std::string& comm argno++; } + auto newrule = parser.rule(); + std::erase_if(m_monitorRules, [&](const auto& other) { return other.name == newrule.name; }); m_monitorRules.push_back(newrule); - if (error.empty()) - return {}; - return error; + return parser.getError(); } std::optional CConfigManager::handleBezier(const std::string& command, const std::string& args) { diff --git a/src/config/ConfigManager.hpp b/src/config/ConfigManager.hpp index 134292e5..2d8446b5 100644 --- a/src/config/ConfigManager.hpp +++ b/src/config/ConfigManager.hpp @@ -27,6 +27,8 @@ #define HANDLE void* +class CConfigManager; + struct SWorkspaceRule { std::string monitor = ""; std::string workspaceString = ""; @@ -170,6 +172,32 @@ namespace std { }; } +class CMonitorRuleParser { + public: + CMonitorRuleParser(const std::string& name); + + const std::string& name(); + SMonitorRule& rule(); + std::optional getError(); + bool parseMode(const std::string& value); + bool parsePosition(const std::string& value, bool isFirst = false); + bool parseScale(const std::string& value); + bool parseTransform(const std::string& value); + bool parseBitdepth(const std::string& value); + bool parseCM(const std::string& value); + bool parseSDRBrightness(const std::string& value); + bool parseSDRSaturation(const std::string& value); + bool parseVRR(const std::string& value); + + void setDisabled(); + void setMirror(const std::string& value); + bool setReserved(const SMonitorAdditionalReservedArea& value); + + private: + SMonitorRule m_rule; + std::string m_error = ""; +}; + class CConfigManager { public: CConfigManager(); @@ -257,6 +285,9 @@ class CConfigManager { std::optional handlePlugin(const std::string&, const std::string&); std::optional handlePermission(const std::string&, const std::string&); + std::optional handleMonitorv2(const std::string& output); + Hyprlang::CParseResult handleMonitorv2(); + std::string m_configCurrentPath; bool m_wantsMonitorReload = false; @@ -307,6 +338,7 @@ class CConfigManager { std::optional resetHLConfig(); std::optional generateConfig(std::string configPath); std::optional verifyConfigExists(); + void postConfigReload(const Hyprlang::CParseResult& result); SWorkspaceRule mergeWorkspaceRules(const SWorkspaceRule&, const SWorkspaceRule&); @@ -319,6 +351,7 @@ class CConfigManager { std::unordered_map m_mStoredFloatingSizes; friend struct SConfigOptionDescription; + friend class CMonitorRuleParser; }; inline UP g_pConfigManager; diff --git a/src/debug/HyprCtl.cpp b/src/debug/HyprCtl.cpp index 77f54c2b..11f8b39a 100644 --- a/src/debug/HyprCtl.cpp +++ b/src/debug/HyprCtl.cpp @@ -1109,6 +1109,9 @@ static std::string dispatchKeyword(eHyprCtlOutputFormat format, std::string in) if (COMMAND == "monitor" || COMMAND == "source") g_pConfigManager->m_wantsMonitorReload = true; // for monitor keywords + if (COMMAND.contains("monitorv2")) + g_pEventLoopManager->doLater([] { g_pConfigManager->m_wantsMonitorReload = true; }); + if (COMMAND.contains("input") || COMMAND.contains("device") || COMMAND == "source") { g_pInputManager->setKeyboardLayout(); // update kb layout g_pInputManager->setPointerConfigs(); // update mouse cfgs From 423b69f5d3c76762e05c1511a10942714dea4e8e Mon Sep 17 00:00:00 2001 From: Eric Li Date: Thu, 5 Jun 2025 16:17:04 -0400 Subject: [PATCH 1345/2181] config: add group: selector (#10588) --- src/config/ConfigManager.cpp | 19 +++++++++++++++++-- src/desktop/WindowRule.hpp | 3 ++- 2 files changed, 19 insertions(+), 3 deletions(-) diff --git a/src/config/ConfigManager.cpp b/src/config/ConfigManager.cpp index 735d9703..025be9f7 100644 --- a/src/config/ConfigManager.cpp +++ b/src/config/ConfigManager.cpp @@ -1434,6 +1434,7 @@ std::vector> CConfigManager::getMatchingRules(PHLWINDOW pWindow, // since some rules will be applied later, we need to store some flags bool hasFloating = pWindow->m_isFloating; bool hasFullscreen = pWindow->isFullscreen(); + bool isGrouped = pWindow->m_groupData.pNextWindow; // local tags for dynamic tag rule match auto tags = pWindow->m_tags; @@ -1482,6 +1483,11 @@ std::vector> CConfigManager::getMatchingRules(PHLWINDOW pWindow, continue; } + if (rule->m_group != -1) { + if (rule->m_group != isGrouped) + continue; + } + if (!rule->m_fullscreenState.empty()) { const auto ARGS = CVarList(rule->m_fullscreenState, 2, ' '); // @@ -2576,6 +2582,7 @@ std::optional CConfigManager::handleWindowRule(const std::string& c const auto ONWORKSPACEPOS = VALUE.find("onworkspace:"); const auto CONTENTTYPEPOS = VALUE.find("content:"); const auto XDGTAGPOS = VALUE.find("xdgTag:"); + const auto GROUPPOS = VALUE.find("group:"); // find workspacepos that isn't onworkspacepos size_t WORKSPACEPOS = std::string::npos; @@ -2588,8 +2595,8 @@ std::optional CConfigManager::handleWindowRule(const std::string& c currentPos = VALUE.find("workspace:", currentPos + 1); } - const auto checkPos = std::unordered_set{TAGPOS, TITLEPOS, CLASSPOS, INITIALTITLEPOS, INITIALCLASSPOS, X11POS, FLOATPOS, FULLSCREENPOS, - PINNEDPOS, FULLSCREENSTATEPOS, WORKSPACEPOS, FOCUSPOS, ONWORKSPACEPOS, CONTENTTYPEPOS, XDGTAGPOS}; + const auto checkPos = std::unordered_set{TAGPOS, TITLEPOS, CLASSPOS, INITIALTITLEPOS, INITIALCLASSPOS, X11POS, FLOATPOS, FULLSCREENPOS, + PINNEDPOS, FULLSCREENSTATEPOS, WORKSPACEPOS, FOCUSPOS, ONWORKSPACEPOS, CONTENTTYPEPOS, XDGTAGPOS, GROUPPOS}; if (checkPos.size() == 1 && checkPos.contains(std::string::npos)) { Debug::log(ERR, "Invalid rulev2 syntax: {}", VALUE); return "Invalid rulev2 syntax: " + VALUE; @@ -2630,6 +2637,8 @@ std::optional CConfigManager::handleWindowRule(const std::string& c min = CONTENTTYPEPOS; if (XDGTAGPOS > pos && XDGTAGPOS < min) min = XDGTAGPOS; + if (GROUPPOS > pos && GROUPPOS < min) + min = GROUPPOS; result = result.substr(0, min - pos); @@ -2694,6 +2703,9 @@ std::optional CConfigManager::handleWindowRule(const std::string& c if (XDGTAGPOS != std::string::npos) rule->m_xdgTag = extract(XDGTAGPOS + 8); + if (GROUPPOS != std::string::npos) + rule->m_group = extract(GROUPPOS + 6) == "1" ? 1 : 0; + if (RULE == "unset") { std::erase_if(m_windowRules, [&](const auto& other) { if (!other->m_v2) @@ -2741,6 +2753,9 @@ std::optional CConfigManager::handleWindowRule(const std::string& c if (!rule->m_contentType.empty() && rule->m_contentType != other->m_contentType) return false; + if (rule->m_group != -1 && rule->m_group != other->m_group) + return false; + return true; } }); diff --git a/src/desktop/WindowRule.hpp b/src/desktop/WindowRule.hpp index 9af3909a..b828c8ee 100644 --- a/src/desktop/WindowRule.hpp +++ b/src/desktop/WindowRule.hpp @@ -58,6 +58,7 @@ class CWindowRule { int m_fullscreen = -1; int m_pinned = -1; int m_focus = -1; + int m_group = -1; std::string m_fullscreenState = ""; // empty means any std::string m_onWorkspace = ""; // empty means any std::string m_workspace = ""; // empty means any @@ -70,4 +71,4 @@ class CWindowRule { CRuleRegexContainer m_initialTitleRegex; CRuleRegexContainer m_initialClassRegex; CRuleRegexContainer m_v1Regex; -}; \ No newline at end of file +}; From fb7548cb41d82f12db2d51b50af29abe4704a1a4 Mon Sep 17 00:00:00 2001 From: XPhyro Date: Thu, 5 Jun 2025 23:29:01 +0300 Subject: [PATCH 1346/2181] screencopy: fix applying `noscreenshare` to invisible special workspaces (#10628) --- src/protocols/Screencopy.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/protocols/Screencopy.cpp b/src/protocols/Screencopy.cpp index 8002776a..3ad57ed7 100644 --- a/src/protocols/Screencopy.cpp +++ b/src/protocols/Screencopy.cpp @@ -206,7 +206,7 @@ void CScreencopyFrame::renderMon() { if (!w->m_windowData.noScreenShare.valueOrDefault()) continue; - if (!g_pHyprRenderer->shouldRenderWindow(w)) + if (!g_pHyprRenderer->shouldRenderWindow(w, m_monitor.lock())) continue; const auto PWORKSPACE = w->m_workspace; From d6fbd89336f2f0b631856e6a68a9d62c772ef50f Mon Sep 17 00:00:00 2001 From: Friday Date: Thu, 5 Jun 2025 22:02:58 +0100 Subject: [PATCH 1347/2181] nix: use gcc15-built dependencies --- flake.lock | 66 +++++++++++++++++++++++++++--------------------------- 1 file changed, 33 insertions(+), 33 deletions(-) diff --git a/flake.lock b/flake.lock index 01b437e6..ba7d34bf 100644 --- a/flake.lock +++ b/flake.lock @@ -16,11 +16,11 @@ ] }, "locked": { - "lastModified": 1747864449, - "narHash": "sha256-PIjVAWghZhr3L0EFM2UObhX84UQxIACbON0IC0zzSKA=", + "lastModified": 1749155310, + "narHash": "sha256-t0HfHg/1+TbSra5s6nNM0o4tnb3uqWedShSpZXsUMYY=", "owner": "hyprwm", "repo": "aquamarine", - "rev": "389372c5f4dc1ac0e7645ed29a35fd6d71672ef5", + "rev": "94981cf75a9f11da0b6dd6a1abbd7c50a36ab2d3", "type": "github" }, "original": { @@ -79,11 +79,11 @@ ] }, "locked": { - "lastModified": 1745948457, - "narHash": "sha256-lzTV10FJTCGNtMdgW5YAhCAqezeAzKOd/97HbQK8GTU=", + "lastModified": 1749155331, + "narHash": "sha256-XR9fsI0zwLiFWfqi/pdS/VD+YNorKb3XIykgTg4l1nA=", "owner": "hyprwm", "repo": "hyprcursor", - "rev": "ac903e80b33ba6a88df83d02232483d99f327573", + "rev": "45fcc10b4c282746d93ec406a740c43b48b4ef80", "type": "github" }, "original": { @@ -105,11 +105,11 @@ ] }, "locked": { - "lastModified": 1745015490, - "narHash": "sha256-apEJ9zoSzmslhJ2vOKFcXTMZLUFYzh1ghfB6Rbw3Low=", + "lastModified": 1749145600, + "narHash": "sha256-v2kY5RDk9oyo1x9m8u83GdklC96xlJ7ka1rrvZoYL78=", "owner": "hyprwm", "repo": "hyprgraphics", - "rev": "60754910946b4e2dc1377b967b7156cb989c5873", + "rev": "80b754e38e836777ad3a9d5d1ffc3491b0332471", "type": "github" }, "original": { @@ -128,11 +128,11 @@ ] }, "locked": { - "lastModified": 1743714874, - "narHash": "sha256-yt8F7NhMFCFHUHy/lNjH/pjZyIDFNk52Q4tivQ31WFo=", + "lastModified": 1749046714, + "narHash": "sha256-kymV5FMnddYGI+UjwIw8ceDjdeg7ToDVjbHCvUlhn14=", "owner": "hyprwm", "repo": "hyprland-protocols", - "rev": "3a5c2bda1c1a4e55cc1330c782547695a93f05b2", + "rev": "613878cb6f459c5e323aaafe1e6f388ac8a36330", "type": "github" }, "original": { @@ -157,11 +157,11 @@ ] }, "locked": { - "lastModified": 1737634706, - "narHash": "sha256-nGCibkfsXz7ARx5R+SnisRtMq21IQIhazp6viBU8I/A=", + "lastModified": 1749154592, + "narHash": "sha256-DO7z5CeT/ddSGDEnK9mAXm1qlGL47L3VAHLlLXoCjhE=", "owner": "hyprwm", "repo": "hyprland-qt-support", - "rev": "8810df502cdee755993cb803eba7b23f189db795", + "rev": "4c8053c3c888138a30c3a6c45c2e45f5484f2074", "type": "github" }, "original": { @@ -189,11 +189,11 @@ ] }, "locked": { - "lastModified": 1745951494, - "narHash": "sha256-2dModE32doiyQMmd6EDAQeZnz+5LOs6KXyE0qX76WIg=", + "lastModified": 1749155776, + "narHash": "sha256-t1PM0wxQLQwv2F2AW23uA7pm5giwmcgYEWbNIRct9r4=", "owner": "hyprwm", "repo": "hyprland-qtutils", - "rev": "4be1d324faf8d6e82c2be9f8510d299984dfdd2e", + "rev": "396e8aa1c06274835b69da7f9a015fff9a9b7522", "type": "github" }, "original": { @@ -215,11 +215,11 @@ ] }, "locked": { - "lastModified": 1747484975, - "narHash": "sha256-+LAQ81HBwG0lwshHlWe0kfWg4KcChIPpnwtnwqmnoEU=", + "lastModified": 1749145882, + "narHash": "sha256-qr0KXeczF8Sma3Ae7+dR2NHhvG7YeLBJv19W4oMu6ZE=", "owner": "hyprwm", "repo": "hyprlang", - "rev": "163c83b3db48a17c113729c220a60b94596c9291", + "rev": "1bfb84f54d50c7ae6558c794d3cfd5f6a7e6e676", "type": "github" }, "original": { @@ -238,11 +238,11 @@ ] }, "locked": { - "lastModified": 1746635225, - "narHash": "sha256-W9G9bb0zRYDBRseHbVez0J8qVpD5QbizX67H/vsudhM=", + "lastModified": 1749135356, + "narHash": "sha256-Q8mAKMDsFbCEuq7zoSlcTuxgbIBVhfIYpX0RjE32PS0=", "owner": "hyprwm", "repo": "hyprutils", - "rev": "674ea57373f08b7609ce93baff131117a0dfe70d", + "rev": "e36db00dfb3a3d3fdcc4069cb292ff60d2699ccb", "type": "github" }, "original": { @@ -261,11 +261,11 @@ ] }, "locked": { - "lastModified": 1747584298, - "narHash": "sha256-PH9qZqWLHvSBQiUnA0NzAyQA3tu2no2z8kz0ZeHWj4w=", + "lastModified": 1749145760, + "narHash": "sha256-IHaGWpGrv7seFWdw/1A+wHtTsPlOGIKMrk1TUIYJEFI=", "owner": "hyprwm", "repo": "hyprwayland-scanner", - "rev": "e511882b9c2e1d7a75d45d8fddd2160daeafcbc3", + "rev": "817918315ea016cc2d94004bfb3223b5fd9dfcc6", "type": "github" }, "original": { @@ -276,11 +276,11 @@ }, "nixpkgs": { "locked": { - "lastModified": 1748460289, - "narHash": "sha256-7doLyJBzCllvqX4gszYtmZUToxKvMUrg45EUWaUYmBg=", + "lastModified": 1748929857, + "narHash": "sha256-lcZQ8RhsmhsK8u7LIFsJhsLh/pzR9yZ8yqpTzyGdj+Q=", "owner": "NixOS", "repo": "nixpkgs", - "rev": "96ec055edbe5ee227f28cdbc3f1ddf1df5965102", + "rev": "c2a03962b8e24e669fb37b7df10e7c79531ff1a4", "type": "github" }, "original": { @@ -365,11 +365,11 @@ ] }, "locked": { - "lastModified": 1745871725, - "narHash": "sha256-M24SNc2flblWGXFkGQfqSlEOzAGZnMc9QG3GH4K/KbE=", + "lastModified": 1749155346, + "narHash": "sha256-KIkJu3zF8MF3DuGwzAmo3Ww9wsWXolwV30SjJRTAxYE=", "owner": "hyprwm", "repo": "xdg-desktop-portal-hyprland", - "rev": "76bbf1a6b1378e4ab5230bad00ad04bc287c969e", + "rev": "44bf29f1df45786098920c655af523535a9191ae", "type": "github" }, "original": { From c35c2fea409a845b1023151a2b642f4aa077dacc Mon Sep 17 00:00:00 2001 From: UjinT34 <41110182+UjinT34@users.noreply.github.com> Date: Fri, 6 Jun 2025 10:01:19 +0300 Subject: [PATCH 1348/2181] config: Restore auto-center-* for monitors (#10660) --- src/config/ConfigManager.cpp | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/src/config/ConfigManager.cpp b/src/config/ConfigManager.cpp index 025be9f7..0632018c 100644 --- a/src/config/ConfigManager.cpp +++ b/src/config/ConfigManager.cpp @@ -2103,10 +2103,20 @@ bool CMonitorRuleParser::parsePosition(const std::string& value, bool isFirst) { m_rule.autoDir = eAutoDirs::DIR_AUTO_UP; else if (value == "auto-down") m_rule.autoDir = eAutoDirs::DIR_AUTO_DOWN; + else if (value == "auto-center-right") + m_rule.autoDir = eAutoDirs::DIR_AUTO_CENTER_RIGHT; + else if (value == "auto-center-left") + m_rule.autoDir = eAutoDirs::DIR_AUTO_CENTER_LEFT; + else if (value == "auto-center-up") + m_rule.autoDir = eAutoDirs::DIR_AUTO_CENTER_UP; + else if (value == "auto-center-down") + m_rule.autoDir = eAutoDirs::DIR_AUTO_CENTER_DOWN; else { Debug::log(WARN, "Invalid auto direction. Valid options are 'auto'," - "'auto-up', 'auto-down', 'auto-left', and 'auto-right'."); + "'auto-up', 'auto-down', 'auto-left', 'auto-right'," + "'auto-center-up', 'auto-center-down'," + "'auto-center-left', and 'auto-center-right'."); m_error += "invalid auto direction "; return false; } From 456c820d52263579e4afdc3429fdaecab12f37a5 Mon Sep 17 00:00:00 2001 From: vaxerski Date: Fri, 6 Jun 2025 15:11:12 +0200 Subject: [PATCH 1349/2181] assets: update header --- assets/header.svg | 128 ++++++++++++++++++++++------------------------ 1 file changed, 60 insertions(+), 68 deletions(-) diff --git a/assets/header.svg b/assets/header.svg index c8cf8222..a2b32551 100644 --- a/assets/header.svg +++ b/assets/header.svg @@ -1,72 +1,64 @@ - - -
- - - -

Hyprland

-
-
-
-
+ .st4 { + fill: url(#e); + } + + .st5 { + fill: url(#f); + } + + .st6 { + fill: url(#g); + } + + .st7 { + fill: url(#h); + } + + .st8 { + fill: url(#i); + } +