diff --git a/CMakeLists.txt b/CMakeLists.txt index 07fa8cf6..f7adcb5d 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -109,6 +109,7 @@ 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 diff --git a/Makefile b/Makefile index 493a6784..aff2a25a 100644 --- a/Makefile +++ b/Makefile @@ -88,7 +88,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/src/Compositor.cpp b/src/Compositor.cpp index 7ffccf36..07843d92 100644 --- a/src/Compositor.cpp +++ b/src/Compositor.cpp @@ -25,13 +25,16 @@ #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 +75,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 +200,9 @@ void CCompositor::setRandomSplash() { m_szCurrentSplash = SPLASHES[distribution(engine)]; } +static std::vector> pendingOutputs; + +// void CCompositor::initServer() { m_sWLDisplay = wl_display_create(); @@ -200,102 +223,91 @@ 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 waylandOptions; + waylandOptions.backendType = Aquamarine::eBackendType::AQ_BACKEND_WAYLAND; + waylandOptions.backendRequestMode = Aquamarine::eBackendRequestMode::AQ_BACKEND_REQUEST_IF_AVAILABLE; + implementations.emplace_back(waylandOptions); - 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(); - m_sWLRRenderer = wlr_gles2_renderer_create_with_drm_fd(m_iDRMFD); + 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!"); } - 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!"); - } + m_bInitialized = true; - m_sWLRAllocator = wlr_allocator_autocreate(m_sWLRBackend, m_sWLRRenderer); - - if (!m_sWLRAllocator) { - Debug::log(CRIT, "m_sWLRAllocator was NULL!"); - throwError("wlr_allocator_autocreate() 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!"); - } + m_iDRMFD = m_pAqBackend->drmFD(); 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); } 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 +321,7 @@ void CCompositor::cleanEnvironment() { unsetenv("XDG_BACKEND"); unsetenv("XDG_CURRENT_DESKTOP"); - if (m_sWLRSession) { + if (false /* TODO: */) { 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 +364,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 +401,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 +448,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 +481,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(); @@ -516,22 +522,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); + // TODO: + // // 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); - if (!headless) { - Debug::log(WARN, "Unsafe state will be ineffective, no fallback output"); - return; - } + // if (!headless) { + // Debug::log(WARN, "Unsafe state will be ineffective, no fallback output"); + // return; + // } - wlr_headless_add_output(headless, 1920, 1080); + // wlr_headless_add_output(headless, 1920, 1080); } void CCompositor::startCompositor(std::string socketName, int socketFd) { @@ -568,7 +575,6 @@ 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)"); } @@ -576,7 +582,8 @@ void CCompositor::startCompositor(std::string socketName, int socketFd) { signal(SIGPIPE, SIG_IGN); - if (m_sWLRSession /* Session-less Hyprland usually means a nest, don't update the env in that case */) { + // TODO: + if (false /* 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 +595,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 +882,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 +892,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(); @@ -2283,8 +2283,9 @@ void CCompositor::updateWorkspaceWindowData(const int& id) { } void CCompositor::scheduleFrameForMonitor(CMonitor* pMonitor) { - if ((m_sWLRSession && !m_sWLRSession->active) || !m_bSessionActive) - return; + // FIXME: + // if ((m_sWLRSession && !m_sWLRSession->active) || !m_bSessionActive) + // return; if (!pMonitor->m_bEnabled) return; @@ -2292,7 +2293,7 @@ void CCompositor::scheduleFrameForMonitor(CMonitor* pMonitor) { if (pMonitor->renderingActive) pMonitor->pendingFrame = true; - wlr_output_schedule_frame(pMonitor->output); + pMonitor->output->scheduleFrame(); } PHLWINDOW CCompositor::getWindowByRegex(const std::string& regexp) { @@ -2808,3 +2809,80 @@ 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(); + + 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()); + + 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..3f85229c 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 = ""; @@ -116,8 +108,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); @@ -182,6 +174,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..af1608f9 100644 --- a/src/config/ConfigManager.cpp +++ b/src/config/ConfigManager.cpp @@ -1285,7 +1285,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 +1410,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 +1420,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 +1443,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/HyprCtl.cpp b/src/debug/HyprCtl.cpp index 08d2bb57..45986037 100644 --- a/src/debug/HyprCtl.cpp +++ b/src/debug/HyprCtl.cpp @@ -20,6 +20,7 @@ #include using namespace Hyprutils::String; +#include #include "../config/ConfigDataValues.hpp" #include "../config/ConfigValue.hpp" @@ -53,18 +54,11 @@ 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); } return result; @@ -75,8 +69,11 @@ std::string CHyprCtl::getMonitorData(Hyprutils::Memory::CSharedPointer if (!m->output || m->ID == -1ull) return ""; - result += std::format( - R"#({{ + if (format == eHyprCtlOutputFormat::FORMAT_JSON) { + result += "["; + + result += std::format( + R"#({{ "id": {}, "name": "{}", "description": "{}", @@ -107,54 +104,28 @@ 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)); - 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); - } + 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->drmFormat), availableModesForOutput(m.get(), format)); trimTrailingComma(result); result += "]"; } else { - for (auto& m : allMonitors ? g_pCompositor->m_vRealMonitors : g_pCompositor->m_vMonitors) { - 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, m->output->state->state().adaptiveSync, m->tearingState.activelyTearing, + !m->m_bEnabled, formatToString(m->drmFormat), availableModesForOutput(m.get(), format)); } return result; @@ -552,8 +523,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); @@ -654,9 +624,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"; @@ -1125,24 +1093,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->xkbTranslationState, 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 +1118,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,26 +1334,26 @@ 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; +// 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 (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; +// if (output && !name.empty()) +// g_pCompositor->getMonitorFromOutput(output)->szName = name; - return output != nullptr; -} +// return output != nullptr; +// } struct outputData { std::string type; @@ -1401,8 +1367,8 @@ void createOutputIter(wlr_backend* backend, void* data) { if (DATA->added) return; - if (addOutput(backend, DATA->type, DATA->name)) - DATA->added = true; + // if (addOutput(backend, DATA->type, DATA->name)) + // DATA->added = true; } std::string dispatchOutput(eHyprCtlOutputFormat format, std::string request) { @@ -1413,13 +1379,15 @@ std::string dispatchOutput(eHyprCtlOutputFormat format, std::string request) { const auto MODE = vars[1]; + // FIXME: + 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}; - wlr_multi_for_each_backend(g_pCompositor->m_sWLRBackend, createOutputIter, &result); + // wlr_multi_for_each_backend(g_pCompositor->m_sWLRBackend, createOutputIter, &result); if (!result.added) return "no backend replied to the request"; @@ -1433,7 +1401,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); + //wlr_output_destroy(PMONITOR->output); } return "ok"; diff --git a/src/devices/IKeyboard.cpp b/src/devices/IKeyboard.cpp index cb294d1a..5ecba556 100644 --- a/src/devices/IKeyboard.cpp +++ b/src/devices/IKeyboard.cpp @@ -2,7 +2,16 @@ #include "../defines.hpp" #include "../helpers/varlist/VarList.hpp" #include "../managers/input/InputManager.hpp" +#include +#include +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,11 +23,130 @@ eHIDType IKeyboard::getType() { IKeyboard::~IKeyboard() { events.destroy.emit(); - if (!xkbTranslationState) - return; + clearManuallyAllocd(); +} - xkb_state_unref(xkbTranslationState); +void IKeyboard::clearManuallyAllocd() { + if (xkbTranslationState) + xkb_state_unref(xkbTranslationState); + + if (xkbInternalTranslationState) + xkb_state_unref(xkbInternalTranslationState); + + if (xkbKeymap) + xkb_keymap_unref(xkbKeymap); + + if (xkbKeymapFD >= 0) + close(xkbKeymapFD); + + xkbKeymap = nullptr; xkbTranslationState = 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 + xkbInternalTranslationState = xkb_state_new(xkbKeymap); + + updateXKBTranslationState(); + + 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; + } + + if (modifiersState.locked != 0) + keyboardEvents.modifiers.emit(SModifiersEvent{.locked = modifiersState.locked}); + + 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), modIndexes.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); } void IKeyboard::updateXKBTranslationState(xkb_keymap* const keymap) { @@ -32,9 +160,8 @@ void IKeyboard::updateXKBTranslationState(xkb_keymap* const keymap) { return; } - const auto WLRKB = wlr(); - const auto KEYMAP = WLRKB->keymap; - const auto STATE = WLRKB->xkb_state; + const auto KEYMAP = xkbKeymap; + const auto STATE = xkbInternalTranslationState; const auto LAYOUTSNUM = xkb_keymap_num_layouts(KEYMAP); const auto PCONTEXT = xkb_context_new(XKB_CONTEXT_NO_FLAGS); @@ -101,9 +228,8 @@ void IKeyboard::updateXKBTranslationState(xkb_keymap* const keymap) { } 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 = xkbTranslationState; const auto LAYOUTSNUM = xkb_keymap_num_layouts(KEYMAP); for (uint32_t i = 0; i < LAYOUTSNUM; ++i) { @@ -120,14 +246,12 @@ std::string IKeyboard::getActiveLayout() { } void IKeyboard::updateLEDs() { - auto keyboard = wlr(); - - if (!keyboard || keyboard->xkb_state == nullptr) + if (xkbTranslationState == 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])) + if (xkb_state_led_index_is_active(xkbTranslationState, ledIndexes.at(i))) leds |= (1 << i); } @@ -135,13 +259,62 @@ void IKeyboard::updateLEDs() { } void IKeyboard::updateLEDs(uint32_t leds) { - auto keyboard = wlr(); - - if (!keyboard || keyboard->xkb_state == nullptr) + if (!xkbTranslationState) 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 (!xkbTranslationState) + return; + + xkb_state_update_mask(xkbTranslationState, depressed, latched, locked, 0, 0, group); + + if (!updateModifiersState()) + return; + + updateLEDs(); +} + +bool IKeyboard::updateModifiersState() { + if (!xkbTranslationState) + return false; + + auto depressed = xkb_state_serialize_mods(xkbTranslationState, XKB_STATE_MODS_DEPRESSED); + auto latched = xkb_state_serialize_mods(xkbTranslationState, XKB_STATE_MODS_LATCHED); + auto locked = xkb_state_serialize_mods(xkbTranslationState, XKB_STATE_MODS_LOCKED); + auto group = xkb_state_serialize_layout(xkbTranslationState, 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; } diff --git a/src/devices/IKeyboard.hpp b/src/devices/IKeyboard.hpp index b1757a18..fec85606 100644 --- a/src/devices/IKeyboard.hpp +++ b/src/devices/IKeyboard.hpp @@ -7,15 +7,15 @@ #include -struct wlr_keyboard; +AQUAMARINE_FORWARD(IKeyboard); 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 +24,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 +50,43 @@ 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 active = false; bool enabled = true; xkb_layout_index_t activeLayout = 0; - xkb_state* xkbTranslationState = nullptr; + xkb_state * xkbTranslationState = nullptr, *xkbInternalTranslationState = 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; + std::array modIndexes; + 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(); + bool updateModifiersState(); // rets whether changed }; 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..514bef2b 100644 --- a/src/devices/Keyboard.cpp +++ b/src/devices/Keyboard.cpp @@ -1,7 +1,9 @@ #include "Keyboard.hpp" #include "../defines.hpp" -SP CKeyboard::create(wlr_keyboard* keeb) { +#include + +SP CKeyboard::create(SP keeb) { SP pKeeb = SP(new CKeyboard(keeb)); pKeeb->self = pKeeb; @@ -13,52 +15,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); 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) { + auto E = std::any_cast(d); - hyprListener_modifiers.initCallback(&keeb->events.modifiers, [this] (void* owner, void* data) { - keyboardEvents.modifiers.emit(); - }, this, "CKeyboard"); + updateModifiers(E.depressed, E.latched, E.locked, E.group); - hyprListener_repeatInfo.initCallback(&keeb->events.repeat_info, [this] (void* owner, void* data) { - keyboardEvents.repeatInfo.emit(); - }, this, "CKeyboard"); - // clang-format on + keyboardEvents.modifiers.emit(SModifiersEvent{ + .depressed = modifiersState.depressed, + .latched = modifiersState.latched, + .locked = modifiersState.locked, + .group = modifiersState.group, + }); + }); - 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/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 index fedc844e..752e51f7 100644 --- a/src/events/Devices.cpp +++ b/src/events/Devices.cpp @@ -21,15 +21,15 @@ void Events::listener_newInput(wl_listener* listener, void* data) { switch (DEVICE->type) { case WLR_INPUT_DEVICE_KEYBOARD: Debug::log(LOG, "Attached a keyboard with name {}", DEVICE->name); - g_pInputManager->newKeyboard(DEVICE); + //g_pInputManager->newKeyboard(DEVICE); break; case WLR_INPUT_DEVICE_POINTER: Debug::log(LOG, "Attached a mouse with name {}", DEVICE->name); - g_pInputManager->newMouse(DEVICE); + //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); + // g_pInputManager->newTouchDevice(DEVICE); break; case WLR_INPUT_DEVICE_TABLET: Debug::log(LOG, "Attached a tablet with name {}", DEVICE->name); diff --git a/src/events/Monitors.cpp b/src/events/Monitors.cpp index 2536e1f7..4217e279 100644 --- a/src/events/Monitors.cpp +++ b/src/events/Monitors.cpp @@ -16,88 +16,6 @@ // // // --------------------------------------------------------- // -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 @@ -108,18 +26,19 @@ void Events::listener_monitorFrame(void* owner, void* data) { CMonitor* const PMONITOR = (CMonitor*)owner; - if ((g_pCompositor->m_sWLRSession && !g_pCompositor->m_sWLRSession->active) || !g_pCompositor->m_bSessionActive || g_pCompositor->m_bUnsafeState) { - Debug::log(WARN, "Attempted to render frame on inactive session!"); + // FIXME: + // if ((g_pCompositor->m_sWLRSession && !g_pCompositor->m_sWLRSession->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(); - } + // 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) - } + // return; // cannot draw on session inactive (different tty) + // } if (!PMONITOR->m_bEnabled) return; @@ -172,12 +91,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 = nullptr; for (auto& m : g_pCompositor->m_vRealMonitors) { - if (m->output == OUTPUT) { + if (m->output == pMonitor->output) { pMonitor = m.get(); break; } @@ -188,9 +105,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; @@ -202,20 +116,20 @@ void Events::listener_monitorDestroy(void* owner, void* data) { } void Events::listener_monitorStateRequest(void* owner, void* data) { - const auto PMONITOR = (CMonitor*)owner; - const auto E = (wlr_output_event_request_state*)data; + // const auto PMONITOR = (CMonitor*)owner; + // const auto E = (wlr_output_event_request_state*)data; - if (!PMONITOR->createdByUser) - return; + // 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}; + // 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; + // PMONITOR->forceSize = SIZE; - SMonitorRule rule = PMONITOR->activeMonitorRule; - rule.resolution = SIZE; + // SMonitorRule rule = PMONITOR->activeMonitorRule; + // rule.resolution = SIZE; - g_pHyprRenderer->applyMonitorRule(PMONITOR, &rule); + // g_pHyprRenderer->applyMonitorRule(PMONITOR, &rule); } void Events::listener_monitorDamage(void* owner, void* data) { @@ -234,11 +148,9 @@ void Events::listener_monitorNeedsFrame(void* owner, void* data) { 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/Format.hpp b/src/helpers/Format.hpp index a1ef53f5..c0dabdd5 100644 --- a/src/helpers/Format.hpp +++ b/src/helpers/Format.hpp @@ -19,7 +19,7 @@ struct SPixelFormat { }; struct SDRMFormat { - uint32_t format = 0; + DRMFormat format = 0; /* DRM_FORMAT_INVALID */ std::vector mods; }; diff --git a/src/helpers/Monitor.cpp b/src/helpers/Monitor.cpp index 20c2e81e..2912d734 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 "../protocols/core/Output.hpp" #include "../managers/PointerManager.hpp" #include using namespace Hyprutils::String; @@ -21,14 +22,6 @@ 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(); } @@ -40,43 +33,48 @@ static void onPresented(void* owner, void* data) { } 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 + 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); }); + + listeners.state = output->events.state.registerListener([this](std::any d) { + if (!createdByUser) + return; + + auto E = std::any_cast(d); + + 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,56 +82,26 @@ 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); - } + // TODO: + // if (g_pCompositor->m_sWRLDRMLeaseMgr) { + // wlr_drm_lease_v1_manager_offer_output(g_pCompositor->m_sWRLDRMLeaseMgr, output); + // } return; } - 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; - } - SP* thisWrapper = nullptr; // find the wrap @@ -151,7 +119,7 @@ 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) @@ -261,12 +229,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 +282,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); @@ -369,8 +335,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 +529,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; @@ -787,31 +753,35 @@ 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); +} + 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::clear() { - wlr_output_state_finish(&m_state); - m_state = {0}; - wlr_output_state_init(&m_state); + ; } bool CMonitorState::commit() { - bool ret = wlr_output_commit_state(m_pOwner->output, &m_state); - clear(); + bool ret = m_pOwner->output->commit(); return ret; } bool CMonitorState::test() { - return wlr_output_test_state(m_pOwner->output, &m_state); + return m_pOwner->output->test(); } diff --git a/src/helpers/Monitor.hpp b/src/helpers/Monitor.hpp index 8a2acdaf..87c73a14 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 { @@ -45,15 +47,11 @@ class CMonitorState { CMonitorState(CMonitor* owner); ~CMonitorState(); - wlr_output_state* wlr(); - void clear(); - // commit() will also clear() bool commit(); bool test(); private: - wlr_output_state m_state = {0}; - CMonitor* m_pOwner; + CMonitor* m_pOwner; }; class CMonitor { @@ -61,61 +59,62 @@ 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; + uint32_t drmFormat = DRM_FORMAT_INVALID; + 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; + SMonitorRule activeMonitorRule; - WP self; + WP self; // mirroring CMonitor* pMirrorOf = nullptr; @@ -143,15 +142,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 +163,7 @@ class CMonitor { int64_t activeWorkspaceID(); int64_t activeSpecialWorkspaceID(); CBox logicalBox(); + void scheduleDone(); bool m_bEnabled = false; bool m_bRenderingInitPassed = false; @@ -184,6 +175,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/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/CursorManager.cpp b/src/managers/CursorManager.cpp index daa4f4be..5a14ec3a 100644 --- a/src/managers/CursorManager.cpp +++ b/src/managers/CursorManager.cpp @@ -67,54 +67,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) { @@ -150,11 +157,11 @@ void CCursorManager::setXCursor(const std::string& name) { auto image = xcursor->images[0]; 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})); + makeShared(image->buffer, Vector2D{(int)image->width, (int)image->height}, Vector2D{(double)image->hotspot_x, (double)image->hotspot_y})); 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); + dropBufferRef(m_vCursorBuffers.at(0).get()); m_bOurBufferConnected = true; } @@ -196,14 +203,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 +232,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})); diff --git a/src/managers/CursorManager.hpp b/src/managers/CursorManager.hpp index 3ee98ca6..6a042743 100644 --- a/src/managers/CursorManager.hpp +++ b/src/managers/CursorManager.hpp @@ -7,46 +7,49 @@ #include "../helpers/math/Math.hpp" #include "../helpers/memory/Memory.hpp" -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 +59,7 @@ class CCursorManager { bool m_bOurBufferConnected = false; private: - std::vector> m_vCursorBuffers; + std::vector> m_vCursorBuffers; std::unique_ptr m_pHyprcursor; diff --git a/src/managers/KeybindManager.cpp b/src/managers/KeybindManager.cpp index eb8a3232..54c13f87 100644 --- a/src/managers/KeybindManager.cpp +++ b/src/managers/KeybindManager.cpp @@ -367,7 +367,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->xkbTranslationState : m_pXKBTranslationState, KEYCODE); - const xkb_keysym_t internalKeysym = xkb_state_key_get_one_sym(pKeyboard->wlr()->xkb_state, KEYCODE); + const xkb_keysym_t internalKeysym = xkb_state_key_get_one_sym(pKeyboard->xkbInternalTranslationState, KEYCODE); if (handleInternalKeybinds(internalKeysym)) return true; @@ -554,7 +554,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 +786,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,7 +810,8 @@ 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); + // FIXME: + //wlr_session_change_vt(g_pCompositor->m_sWLRSession, TTY); return true; } @@ -2121,7 +2122,7 @@ 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_keymap* km = KB->xkbKeymap; xkb_state* ks = KB->xkbTranslationState; xkb_keycode_t keycode_min, keycode_max; @@ -2259,7 +2260,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/PointerManager.cpp b/src/managers/PointerManager.cpp index 7090645f..0b52d132 100644 --- a/src/managers/PointerManager.cpp +++ b/src/managers/PointerManager.cpp @@ -10,128 +10,26 @@ #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); +static Aquamarine::SDRMFormat pickCursorFormat(SP output) { - size_t capacity = a->len < b->len ? a->len : b->len; - uint64_t* modifiers = (uint64_t*)malloc(sizeof(*modifiers) * capacity); - if (!modifiers) - return false; + const auto fmts = output->getBackend()->getCursorFormats(); - struct wlr_drm_format fmt = { - .format = a->format, - .len = 0, - .capacity = capacity, - .modifiers = modifiers, - }; + if (fmts.empty()) + return {}; - 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; - } + // try to use common formats in their order + std::vector PREFERRED_FORMATS = {DRM_FORMAT_ARGB8888, DRM_FORMAT_XRGB8888}; + + for (auto& pf : PREFERRED_FORMATS) { + for (auto& fmt : fmts) { + if (pf != fmt.drmFormat) + continue; + + return fmt; } } - 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; + return fmts.at(0); } CPointerManager::CPointerManager() { @@ -201,6 +99,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 +119,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 +135,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 +218,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 +240,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 +266,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 +313,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 +354,68 @@ 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); - 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->maxCursorSize(); - if (w < currentCursorImage.size.x || h < currentCursorImage.size.y) { - Debug::log(TRACE, "hardware cursor too big! {} > {}x{}", currentCursorImage.size, w, h); - return nullptr; - } - } + auto cursorSize = currentCursorImage.size; - 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 (cursorSize == 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"); - return nullptr; - } + // error + if (maxSize == Vector2D{}) + return nullptr; - wlr_swapchain_destroy(output->cursor_swapchain); - output->cursor_swapchain = wlr_swapchain_create(output->allocator, w, h, &fmt); - wlr_drm_format_finish(&fmt); - - if (!output->cursor_swapchain) { - Debug::log(TRACE, "Failed to create cursor swapchain"); + 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; } } - wlr_buffer* buf = wlr_swapchain_acquire(output->cursor_swapchain, nullptr); + if (!state->monitor->cursorSwapchain || cursorSize != state->monitor->cursorSwapchain->currentOptions().size) { + auto format = pickCursorFormat(output); + + if (format.drmFormat == DRM_FORMAT_INVALID) { + Debug::log(TRACE, "Failed to pick an output format for hw cursor"); + return nullptr; + } + + if (!state->monitor->cursorSwapchain) + state->monitor->cursorSwapchain = makeShared(g_pCompositor->m_pAqBackend->allocator); + + auto options = state->monitor->cursorSwapchain->currentOptions(); + options.size = cursorSize; + options.length = 2; + options.format = format.drmFormat; + + if (!state->monitor->cursorSwapchain->reconfigure(options)) { + Debug::log(TRACE, "Failed to reconfigure cursor swapchain"); + return 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 +424,16 @@ 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(); - const auto RBO = g_pHyprRenderer->getOrCreateRenderbuffer(buf, DRM_FORMAT_ARGB8888); + const auto RBO = g_pHyprRenderer->getOrCreateRenderbuffer(buf, state->monitor->cursorSwapchain->currentOptions().format); 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); @@ -545,8 +444,6 @@ wlr_buffer* CPointerManager::renderHWCursorBuffer(SPonRenderbufferDestroy(RBO); - wlr_buffer_unlock(buf); - return buf; } @@ -593,11 +490,12 @@ Vector2D CPointerManager::getCursorPosForMonitor(SP pMonitor) { } 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(wlr_output_transform_invert(pMonitor->transform)), pMonitor->cursorSwapchain->currentOptions().size.x, + pMonitor->cursorSwapchain->currentOptions().size.y) .pos(); } @@ -799,10 +697,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..68596ab7 100644 --- a/src/managers/PointerManager.hpp +++ b/src/managers/PointerManager.hpp @@ -9,10 +9,11 @@ #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 +38,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 +48,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 +137,40 @@ 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; } 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/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..dd52b968 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 @@ -25,9 +26,19 @@ static int timerWrite(int fd, uint32_t mask, void* data) { return 1; } +static int aquamarineFDWrite(int fd, uint32_t mask, void* data) { + g_pCompositor->m_pAqBackend->dispatchEventsAsync(); + return 1; +} + void CEventLoopManager::enterLoop() { m_sWayland.eventSource = wl_event_loop_add_fd(m_sWayland.loop, m_sTimers.timerfd, WL_EVENT_READABLE, timerWrite, nullptr); + auto aqFDs = g_pCompositor->m_pAqBackend->getPollFDs(); + for (auto& fd : aqFDs) { + m_sWayland.aqEventSources.emplace_back(wl_event_loop_add_fd(m_sWayland.loop, fd, WL_EVENT_READABLE, aquamarineFDWrite, nullptr)); + } + 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..7758bdf6 100644 --- a/src/managers/eventLoop/EventLoopManager.hpp +++ b/src/managers/eventLoop/EventLoopManager.hpp @@ -33,9 +33,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 { diff --git a/src/managers/input/InputManager.cpp b/src/managers/input/InputManager.cpp index 23e183d0..6388327c 100644 --- a/src/managers/input/InputManager.cpp +++ b/src/managers/input/InputManager.cpp @@ -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,7 +191,7 @@ 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) + if (!PMONITOR->solitaryClient.lock() && g_pHyprRenderer->shouldRenderCursor() && g_pPointerManager->softwareLockedFor(PMONITOR->self.lock()) && !skipFrameSchedule) g_pCompositor->scheduleFrameForMonitor(PMONITOR); PHLWINDOW forcedFocus = m_pForcedFocus.lock(); @@ -372,7 +374,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 && !skipFrameSchedule) + if (g_pPointerManager->softwareLockedFor(PMONITOR->self.lock()) > 0 && !skipFrameSchedule) g_pCompositor->scheduleFrameForMonitor(g_pCompositor->m_pLastMonitor.get()); // grabs @@ -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) && @@ -1270,7 +1201,7 @@ void CInputManager::destroyKeyboard(SP 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); @@ -1330,23 +1261,19 @@ void CInputManager::destroyTabletPad(SP pad) { } void CInputManager::updateKeyboardsLeds(SP pKeyboard) { - if (!pKeyboard) + if (!pKeyboard || !pKeyboard->xkbTranslationState) return; - auto keyboard = pKeyboard->wlr(); + // FIXME: + // uint32_t leds = 0; + // for (uint32_t i = 0; i < WLR_LED_COUNT; ++i) { + // if (xkb_state_led_index_is_active(pKeyboard->xkbTranslationState, keyboard->led_indexes[i])) + // leds |= (1 << i); + // } - 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); - } + // for (auto& k : m_vKeyboards) { + // k->updateLEDs(leds); + // } } void CInputManager::onKeyboardKey(std::any event, SP pKeyboard) { @@ -1374,7 +1301,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 +1319,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,8 +1335,8 @@ 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(); @@ -1524,10 +1450,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 +1469,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 +1498,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 +1515,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; diff --git a/src/managers/input/InputManager.hpp b/src/managers/input/InputManager.hpp index 85ae6197..692b5c27 100644 --- a/src/managers/input/InputManager.hpp +++ b/src/managers/input/InputManager.hpp @@ -18,6 +18,10 @@ class CVirtualKeyboardV1Resource; class CVirtualPointerV1Resource; class IKeyboard; +AQUAMARINE_FORWARD(IPointer); +AQUAMARINE_FORWARD(IKeyboard); +AQUAMARINE_FORWARD(ITouch); + enum eClickBehaviorMode { CLICKMODE_DEFAULT = 0, CLICKMODE_KILL @@ -82,11 +86,11 @@ 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 newTouchDevice(SP); void newSwitch(wlr_input_device*); void newTabletTool(wlr_tablet_tool*); void newTabletPad(wlr_input_device*); diff --git a/src/protocols/GammaControl.cpp b/src/protocols/GammaControl.cpp index 7c3b39ce..c8f423ce 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); @@ -95,7 +95,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 +109,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/InputMethodV2.cpp b/src/protocols/InputMethodV2.cpp index 24f7ad54..f70cc4fc 100644 --- a/src/protocols/InputMethodV2.cpp +++ b/src/protocols/InputMethodV2.cpp @@ -19,7 +19,7 @@ CInputMethodKeyboardGrabV2::CInputMethodKeyboardGrabV2(SPkeyboard->wlr()); + sendKeyboardData(g_pSeatManager->keyboard.lock()); } CInputMethodKeyboardGrabV2::~CInputMethodKeyboardGrabV2() { @@ -27,37 +27,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 +315,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..6167ec3f 100644 --- a/src/protocols/LinuxDMABUF.cpp +++ b/src/protocols/LinuxDMABUF.cpp @@ -73,7 +73,7 @@ CCompiledDMABUFFeedback::~CCompiledDMABUFFeedback() { 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 +103,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; @@ -376,7 +376,7 @@ void CLinuxDMABUFResource::sendMods() { 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()) { diff --git a/src/protocols/LinuxDMABUF.hpp b/src/protocols/LinuxDMABUF.hpp index 2b8ce736..e845352c 100644 --- a/src/protocols/LinuxDMABUF.hpp +++ b/src/protocols/LinuxDMABUF.hpp @@ -7,15 +7,15 @@ #include "wayland.hpp" #include "linux-dmabuf-v1.hpp" #include "../helpers/signal/Signal.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(); @@ -66,12 +66,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; diff --git a/src/protocols/MesaDRM.cpp b/src/protocols/MesaDRM.cpp index 0bcf4a9c..ab77cb4d 100644 --- a/src/protocols/MesaDRM.cpp +++ b/src/protocols/MesaDRM.cpp @@ -7,7 +7,7 @@ #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,7 +60,7 @@ CMesaDRMResource::CMesaDRMResource(SP resource_) : resource(resource_) { return; } - SDMABUFAttrs attrs; + Aquamarine::SDMABUFAttrs attrs; attrs.success = true; attrs.size = {w, h}; attrs.modifier = DRM_FORMAT_MOD_INVALID; @@ -97,7 +97,7 @@ 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(); 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..1c92513c 100644 --- a/src/protocols/PresentationTime.cpp +++ b/src/protocols/PresentationTime.cpp @@ -3,6 +3,7 @@ #include "../helpers/Monitor.hpp" #include "../managers/HookSystemManager.hpp" #include "core/Compositor.hpp" +#include "core/Output.hpp" #define LOGM PROTO::presentation->protoLog @@ -41,13 +42,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; diff --git a/src/protocols/Screencopy.cpp b/src/protocols/Screencopy.cpp index 8a6285a1..fd7bd65c 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 @@ -489,10 +482,8 @@ bool CScreencopyProtocolManager::copyFrameShm(SScreencopyFrame* frame, timespec* CFramebuffer fb; fb.alloc(frame->box.w, frame->box.h, g_pHyprRenderer->isNvidia() ? DRM_FORMAT_XBGR8888 : frame->pMonitor->drmFormat); - if (!g_pHyprRenderer->beginRender(frame->pMonitor, fakeDamage, RENDER_MODE_FULL_FAKE, nullptr, &fb, true)) { - wlr_texture_destroy(sourceTex); + if (!g_pHyprRenderer->beginRender(frame->pMonitor, fakeDamage, RENDER_MODE_FULL_FAKE, nullptr, &fb, true)) return false; - } CBox monbox = CBox{0, 0, frame->pMonitor->vecTransformedSize.x, frame->pMonitor->vecTransformedSize.y}.translate({-frame->box.x, -frame->box.y}); g_pHyprOpenGL->setMonitorTransformEnabled(true); @@ -510,7 +501,6 @@ bool CScreencopyProtocolManager::copyFrameShm(SScreencopyFrame* frame, timespec* const auto PFORMAT = FormatUtils::getPixelFormatFromDRM(shm.format); if (!PFORMAT) { g_pHyprRenderer->endRender(); - wlr_texture_destroy(sourceTex); return false; } @@ -539,27 +529,20 @@ bool CScreencopyProtocolManager::copyFrameShm(SScreencopyFrame* frame, timespec* g_pHyprOpenGL->m_RenderData.pMonitor = nullptr; - wlr_texture_destroy(sourceTex); - 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)) 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(wlr_output_transform_invert(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 +552,5 @@ bool CScreencopyProtocolManager::copyFrameDmabuf(SScreencopyFrame* frame) { g_pHyprOpenGL->m_RenderData.blockScreenShader = true; g_pHyprRenderer->endRender(); - wlr_texture_destroy(sourceTex); - return true; } diff --git a/src/protocols/Screencopy.hpp b/src/protocols/Screencopy.hpp index be434285..063068b5 100644 --- a/src/protocols/Screencopy.hpp +++ b/src/protocols/Screencopy.hpp @@ -10,7 +10,7 @@ #include "../managers/eventLoop/EventLoopTimer.hpp" class CMonitor; -class IWLBuffer; +class IHLBuffer; enum eClientOwners { CLIENT_SCREENCOPY = 0, @@ -56,7 +56,7 @@ struct SScreencopyFrame { bool bufferDMA = false; - WP buffer; + WP buffer; CMonitor* pMonitor = nullptr; PHLWINDOWREF pWindow; @@ -79,7 +79,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 +93,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/ToplevelExport.cpp b/src/protocols/ToplevelExport.cpp index d4c66c3b..ce74a823 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}; 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/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/core/Compositor.hpp b/src/protocols/core/Compositor.hpp index 2f276719..a232ac30 100644 --- a/src/protocols/core/Compositor.hpp +++ b/src/protocols/core/Compositor.hpp @@ -85,7 +85,7 @@ class CWLSurfaceResource { 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; 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..109a7d04 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,12 +188,11 @@ 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); + size_t len = 0; + // TODO: support 10 bit shm - for (size_t i = 0; i < len; ++i) { - shmFormats.push_back(FormatUtils::drmToShm(formats[i])); - } + shmFormats.push_back(WL_SHM_FORMAT_ARGB8888); + shmFormats.push_back(WL_SHM_FORMAT_XRGB8888); } const auto RESOURCE = m_vManagers.emplace_back(makeShared(makeShared(client, ver, id))); 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..23679ce7 100644 --- a/src/protocols/types/Buffer.cpp +++ b/src/protocols/types/Buffer.cpp @@ -1,41 +1,5 @@ #include "Buffer.hpp" -#include "WLBuffer.hpp" -SDMABUFAttrs IWLBuffer::dmabuf() { - return SDMABUFAttrs{}; -} - -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::sendRelease() { + resource->sendRelease(); } diff --git a/src/protocols/types/Buffer.hpp b/src/protocols/types/Buffer.hpp index 9999a4e9..0b377bb3 100644 --- a/src/protocols/types/Buffer.hpp +++ b/src/protocols/types/Buffer.hpp @@ -1,75 +1,24 @@ #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 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; - - struct { - CSignal destroy; - } events; - - private: - int locks = 0; + SP texture; + bool opaque = false; + SP resource; }; 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.hpp b/src/protocols/types/WLBuffer.hpp index ac177965..83d042cd 100644 --- a/src/protocols/types/WLBuffer.hpp +++ b/src/protocols/types/WLBuffer.hpp @@ -7,7 +7,7 @@ #include "wayland.hpp" #include "../../helpers/signal/Signal.hpp" -class IWLBuffer; +class IHLBuffer; class CWLBufferResource { public: @@ -18,7 +18,7 @@ class CWLBufferResource { void sendRelease(); wl_resource* getResource(); - WP buffer; + WP buffer; WP self; @@ -27,5 +27,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..8faf693c 100644 --- a/src/render/OpenGL.cpp +++ b/src/render/OpenGL.cpp @@ -9,6 +9,8 @@ #include "../protocols/LayerShell.hpp" #include "../protocols/core/Compositor.hpp" #include +#include +#include inline void loadGLProc(void* pProc, const char* name) { void* proc = (void*)eglGetProcAddress(name); @@ -19,17 +21,198 @@ 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) { + char* renderName = drmGetRenderDeviceNameFromFd(drmFd); + if (renderName == NULL) { + // This can happen on split render/display platforms, fallback to + // primary node + renderName = drmGetPrimaryDeviceNameFromFd(drmFd); + if (renderName == NULL) { + wlr_log_errno(WLR_ERROR, "drmGetPrimaryDeviceNameFromFd failed"); + return -1; + } + wlr_log(WLR_DEBUG, + "DRM device '%s' has no render node, " + "falling back to primary node", + renderName); + + drmVersion* render_version = drmGetVersion(drmFd); + if (render_version != NULL && render_version->name != NULL) { + wlr_log(WLR_DEBUG, "DRM device version.name '%s'", 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); + } + } + + wlr_log(WLR_DEBUG, "open_render_node() DRM device '%s'", renderName); + + int render_fd = open(renderName, O_RDWR | O_CLOEXEC); + if (render_fd < 0) { + wlr_log_errno(WLR_ERROR, "Failed to open DRM node '%s'", renderName); + } + free(renderName); + return render_fd; +} + +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"); + + 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 +221,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 +248,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 +260,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 +274,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 +313,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) { @@ -209,7 +383,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 +425,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; @@ -915,11 +1089,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); + newBox.transform(TR, m_RenderData.pMonitor->vecTransformedSize.x, m_RenderData.pMonitor->vecTransformedSize.y); } glScissor(newBox.x, newBox.y, newBox.width, newBox.height); @@ -2474,6 +2645,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(); diff --git a/src/render/OpenGL.hpp b/src/render/OpenGL.hpp index 814b80fe..ed11e3cb 100644 --- a/src/render/OpenGL.hpp +++ b/src/render/OpenGL.hpp @@ -19,9 +19,11 @@ #include "Renderbuffer.hpp" #include +#include #include "../debug/TracyDefines.hpp" +struct gbm_device; class CHyprRenderer; inline const float fullVerts[] = { @@ -182,12 +184,17 @@ class CHyprOpenGLImpl { uint32_t getPreferredReadFormat(CMonitor* pMonitor); std::vector getDRMFormats(); - EGLImageKHR createEGLImage(const SDMABUFAttrs& attrs); + EGLImageKHR createEGLImage(const Aquamarine::SDMABUFAttrs& attrs); 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 +212,20 @@ 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; } 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 +235,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 +253,7 @@ class CHyprOpenGLImpl { void createBGTextureForMonitor(CMonitor*); void initShaders(); void initDRMFormats(); + void initEGL(bool gbm); // std::optional> getModsForFormat(EGLint format); diff --git a/src/render/Renderbuffer.cpp b/src/render/Renderbuffer.cpp index 3f591d13..65c64eb9 100644 --- a/src/render/Renderbuffer.cpp +++ b/src/render/Renderbuffer.cpp @@ -15,53 +15,10 @@ 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); @@ -82,6 +39,8 @@ CRenderbuffer::CRenderbuffer(SP buffer, uint32_t format) : m_pHLBuffe throw std::runtime_error("rbo: glCheckFramebufferStatus failed"); glBindFramebuffer(GL_FRAMEBUFFER, 0); + + listeners.destroyBuffer = buffer->events.destroy.registerListener([this](std::any d) { g_pHyprRenderer->onRenderbufferDestroy(this); }); } void CRenderbuffer::bind() { diff --git a/src/render/Renderbuffer.hpp b/src/render/Renderbuffer.hpp index ed7050c5..94814e23 100644 --- a/src/render/Renderbuffer.hpp +++ b/src/render/Renderbuffer.hpp @@ -1,30 +1,30 @@ #pragma once #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(); + 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; GLuint m_iRBO = 0; CFramebuffer m_sFramebuffer; uint32_t m_uDrmFormat = 0; + + struct { + CHyprSignalListener destroyBuffer; + } listeners; }; \ No newline at end of file diff --git a/src/render/Renderer.cpp b/src/render/Renderer.cpp index a7f3c941..9b165df1 100644 --- a/src/render/Renderer.cpp +++ b/src/render/Renderer.cpp @@ -25,22 +25,23 @@ 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()) { + // wlr_device* dev; + // FIXME: + // wl_list_for_each(dev, &g_pCompositor->m_sWLRSession->devices, link) { + // const auto DRMV = drmGetVersion(dev->fd); - std::string name = std::string{DRMV->name, DRMV->name_len}; - std::transform(name.begin(), name.end(), name.begin(), tolower); + // std::string name = std::string{DRMV->name, DRMV->name_len}; + // std::transform(name.begin(), name.end(), name.begin(), tolower); - if (name.contains("nvidia")) - m_bNvidia = true; + // if (name.contains("nvidia")) + // m_bNvidia = true; - Debug::log(LOG, "DRM driver information: {} v{}.{}.{} from {} description {}", name, DRMV->version_major, DRMV->version_minor, DRMV->version_patchlevel, - std::string{DRMV->date, DRMV->date_len}, std::string{DRMV->desc, DRMV->desc_len}); + // Debug::log(LOG, "DRM driver information: {} v{}.{}.{} from {} description {}", name, DRMV->version_major, DRMV->version_minor, DRMV->version_patchlevel, + // std::string{DRMV->date, DRMV->date_len}, std::string{DRMV->desc, DRMV->desc_len}); - drmFreeVersion(DRMV); - } + // drmFreeVersion(DRMV); + // } } else { Debug::log(LOG, "m_sWLRSession is null, omitting full DRM node checks"); @@ -1249,7 +1250,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->needs_frame ||*/ pMonitor->damage.hasChanged(); if (!hasChanged && *PDAMAGETRACKINGMODE != DAMAGE_TRACKING_NONE && pMonitor->forceFullFrames == 0 && damageBlinkCleanup == 0) return; @@ -1295,7 +1296,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; } @@ -1398,7 +1398,7 @@ void CHyprRenderer::renderMonitor(CMonitor* pMonitor) { if (!pMonitor->mirrors.empty()) { CRegion frameDamage{}; - const auto TRANSFORM = wlr_output_transform_invert(pMonitor->output->transform); + const auto TRANSFORM = wlr_output_transform_invert(pMonitor->transform); wlr_region_transform(frameDamage.pixman(), finalDamage.pixman(), TRANSFORM, (int)pMonitor->vecTransformedSize.x, (int)pMonitor->vecTransformedSize.y); if (*PDAMAGETRACKINGMODE == DAMAGE_TRACKING_NONE || *PDAMAGETRACKINGMODE == DAMAGE_TRACKING_MONITOR) @@ -1414,7 +1414,8 @@ 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(); @@ -1869,7 +1870,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) { @@ -1910,38 +1911,36 @@ 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; + pMonitor->output->state->setFormat(DRM_FORMAT_XBGR8888); - 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 +1948,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 +1964,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 +1981,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 +2013,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 +2061,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 +2074,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 +2091,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,18 +2118,18 @@ 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; @@ -2145,10 +2144,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,12 +2183,6 @@ 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); } } @@ -2209,9 +2201,9 @@ bool CHyprRenderer::applyMonitorRule(CMonitor* pMonitor, SMonitorRule* pMonitorR pMonitor->drmFormat = DRM_FORMAT_INVALID; for (auto& fmt : formats[(int)!RULE->enable10bit]) { - wlr_output_state_set_render_format(pMonitor->state.wlr(), fmt.second); + pMonitor->output->state->setFormat(fmt.second); - if (!wlr_output_test_state(pMonitor->output, pMonitor->state.wlr())) { + 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); @@ -2225,17 +2217,18 @@ bool CHyprRenderer::applyMonitorRule(CMonitor* pMonitor, SMonitorRule* pMonitorR 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(wlr_output_transform_invert(pMonitor->transform)), pMonitor->vecTransformedSize.x, pMonitor->vecTransformedSize.y); pMonitor->vecPixelSize = Vector2D(transformedBox.width, transformedBox.height); } @@ -2260,9 +2253,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 +2319,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 +2331,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,16 +2560,7 @@ 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) { +CRenderbuffer* 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()) @@ -2589,18 +2570,21 @@ CRenderbuffer* CHyprRenderer::getOrCreateRenderbuffer(SP buffer, uint } 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(); @@ -2621,27 +2605,18 @@ bool CHyprRenderer::beginRender(CMonitor* pMonitor, CRegion& damage, eRenderMode 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, &bufferAge); - if (!m_pCurrentWlrBuffer) { + m_pCurrentBuffer = pMonitor->output->swapchain->next(&bufferAge); + 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->drmFormat); } catch (std::exception& e) { Debug::log(ERR, "getOrCreateRenderbuffer failed for {}", pMonitor->szName); - wlr_buffer_unlock(m_pCurrentWlrBuffer); return false; } @@ -2679,17 +2654,13 @@ void CHyprRenderer::endRender() { else glFlush(); - if (m_eRenderMode == RENDER_MODE_NORMAL) { - wlr_output_state_set_buffer(PMONITOR->state.wlr(), m_pCurrentWlrBuffer); - unsetEGL(); // flush the context - } - - wlr_buffer_unlock(m_pCurrentWlrBuffer); + if (m_eRenderMode == RENDER_MODE_NORMAL) + PMONITOR->output->state->setBuffer(m_pCurrentBuffer); m_pCurrentRenderbuffer->unbind(); m_pCurrentRenderbuffer = nullptr; - m_pCurrentWlrBuffer = nullptr; + m_pCurrentBuffer = nullptr; } void CHyprRenderer::onRenderbufferDestroy(CRenderbuffer* rb) { diff --git a/src/render/Renderer.hpp b/src/render/Renderer.hpp index 8f404c88..81b9e55b 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 { @@ -76,7 +76,7 @@ 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); + 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; @@ -122,11 +122,10 @@ class CHyprRenderer { 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; + SP m_pCurrentBuffer; + eRenderMode m_eRenderMode = RENDER_MODE_NORMAL; - bool m_bNvidia = false; + bool m_bNvidia = false; struct { bool hiddenOnTouch = false; @@ -134,8 +133,7 @@ class CHyprRenderer { bool hiddenOnKeyboard = false; } m_sCursorHiddenConditions; - CRenderbuffer* getOrCreateRenderbuffer(wlr_buffer* buffer, uint32_t fmt); - CRenderbuffer* getOrCreateRenderbuffer(SP buffer, uint32_t fmt); + CRenderbuffer* getOrCreateRenderbuffer(SP buffer, uint32_t fmt); std::vector> m_vRenderbuffers; friend class CHyprOpenGLImpl; diff --git a/src/render/Texture.cpp b/src/render/Texture.cpp index 46c501a0..f72fa3a4 100644 --- a/src/render/Texture.cpp +++ b/src/render/Texture.cpp @@ -17,6 +17,62 @@ CTexture::~CTexture() { } CTexture::CTexture(uint32_t drmFormat, uint8_t* pixels, uint32_t stride, const Vector2D& size_) { + createFromShm(drmFormat, pixels, stride, size_); +} + +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 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 +97,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 +158,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..4c5c2c76 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 { @@ -25,8 +25,9 @@ class CTexture { 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(); @@ -39,4 +40,8 @@ class CTexture { Vector2D m_vSize; void* m_pEglImage = nullptr; bool m_bNonOwning = false; // wlr + + 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