diff --git a/src/Compositor.cpp b/src/Compositor.cpp index cdcf880c..b0949d89 100644 --- a/src/Compositor.cpp +++ b/src/Compositor.cpp @@ -2,6 +2,16 @@ #include "helpers/Splashes.hpp" #include +int handleCritSignal(int signo, void* data) { + Debug::log(LOG, "Hyprland received signal %d", signo); + + if (signo == SIGTERM || signo == SIGINT || signo == SIGKILL) { + g_pCompositor->cleanup(); + } + + return 0; // everything went fine +} + CCompositor::CCompositor() { m_szInstanceSignature = GIT_COMMIT_HASH + std::string("_") + std::to_string(time(NULL)); @@ -30,6 +40,12 @@ CCompositor::CCompositor() { m_sWLDisplay = wl_display_create(); + m_sWLEventLoop = wl_display_get_event_loop(m_sWLDisplay); + + // register crit signal handler + wl_event_loop_add_signal(m_sWLEventLoop, SIGTERM, handleCritSignal, nullptr); + //wl_event_loop_add_signal(m_sWLEventLoop, SIGINT, handleCritSignal, nullptr); + m_sWLRBackend = wlr_backend_autocreate(m_sWLDisplay); if (!m_sWLRBackend) { @@ -131,15 +147,12 @@ CCompositor::CCompositor() { wlr_xdg_foreign_v2_create(m_sWLDisplay, m_sWLRForeignRegistry); m_sWLRPointerGestures = wlr_pointer_gestures_v1_create(m_sWLDisplay); + + m_sWLRSession = wlr_backend_get_session(m_sWLRBackend); } CCompositor::~CCompositor() { - cleanupExit(); -} - -void handleCritSignal(int signo) { - g_pCompositor->cleanupExit(); - exit(signo); + cleanup(); } void CCompositor::setRandomSplash() { @@ -177,12 +190,10 @@ void CCompositor::initAllSignals() { addWLSignal(&m_sWLRVirtPtrMgr->events.new_virtual_pointer, &Events::listen_newVirtPtr, m_sWLRVirtPtrMgr, "VirtPtrMgr"); addWLSignal(&m_sWLRRenderer->events.destroy, &Events::listen_RendererDestroy, m_sWLRRenderer, "WLRRenderer"); addWLSignal(&m_sWLRIdleInhibitMgr->events.new_inhibitor, &Events::listen_newIdleInhibitor, m_sWLRIdleInhibitMgr, "WLRIdleInhibitMgr"); - - signal(SIGINT, handleCritSignal); - signal(SIGTERM, handleCritSignal); + addWLSignal(&m_sWLRSession->events.active, &Events::listen_sessionActive, m_sWLRSession, "Session"); } -void CCompositor::cleanupExit() { +void CCompositor::cleanup() { if (!m_sWLDisplay) return; @@ -197,8 +208,7 @@ void CCompositor::cleanupExit() { g_pXWaylandManager->m_sWLRXWayland = nullptr; } - wl_display_destroy_clients(m_sWLDisplay); - wl_display_destroy(m_sWLDisplay); + wl_display_terminate(m_sWLDisplay); m_sWLDisplay = nullptr; } @@ -1334,3 +1344,10 @@ void CCompositor::updateWorkspaceWindowDecos(const int& id) { w->updateWindowDecos(); } } + +void CCompositor::scheduleFrameForMonitor(SMonitor* pMonitor) { + if (!m_sWLRSession->active || !m_bSessionActive) + return; + + wlr_output_schedule_frame(pMonitor->output); +} \ No newline at end of file diff --git a/src/Compositor.hpp b/src/Compositor.hpp index bc967621..3ea1711a 100644 --- a/src/Compositor.hpp +++ b/src/Compositor.hpp @@ -30,7 +30,9 @@ public: // ------------------ 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; @@ -80,7 +82,7 @@ public: std::vector m_vSurfacesFadingOut; void startCompositor(); - void cleanupExit(); + void cleanup(); wlr_surface* m_pLastFocus = nullptr; CWindow* m_pLastWindow = nullptr; @@ -89,6 +91,7 @@ public: SSeat m_sSeat; bool m_bReadyToProcess = false; + bool m_bSessionActive = true; // ------------------------------------------------- // @@ -142,6 +145,7 @@ public: void setWindowFullscreen(CWindow*, bool, eFullscreenMode); void moveUnmanagedX11ToWindows(CWindow*); CWindow* getX11Parent(CWindow*); + void scheduleFrameForMonitor(SMonitor*); private: void initAllSignals(); diff --git a/src/debug/HyprCtl.cpp b/src/debug/HyprCtl.cpp index cdc04ff4..6b94ce1d 100644 --- a/src/debug/HyprCtl.cpp +++ b/src/debug/HyprCtl.cpp @@ -593,7 +593,7 @@ std::string getRequestFromThread(std::string rq) { // this might be a race condition // tested with 2 instances of `watch -n 0.1 hyprctl splash` and seems to not crash so I'll take that as a yes if (!*PNOVFR) - wlr_output_schedule_frame(g_pCompositor->m_vMonitors.front()->output); + g_pCompositor->scheduleFrameForMonitor(g_pCompositor->m_vMonitors.front().get()); while (HyprCtl::request != "" || HyprCtl::requestMade || HyprCtl::requestReady) { std::this_thread::sleep_for(std::chrono::milliseconds(5)); diff --git a/src/events/Events.hpp b/src/events/Events.hpp index eefc55c7..63e65fdc 100644 --- a/src/events/Events.hpp +++ b/src/events/Events.hpp @@ -119,4 +119,7 @@ namespace Events { LISTENER(swipeBegin); LISTENER(swipeEnd); LISTENER(swipeUpdate); + + // session + LISTENER(sessionActive); }; \ No newline at end of file diff --git a/src/events/Misc.cpp b/src/events/Misc.cpp index c25b1c6a..503d2111 100644 --- a/src/events/Misc.cpp +++ b/src/events/Misc.cpp @@ -157,4 +157,10 @@ void Events::listener_InhibitDeactivate(wl_listener* listener, void* data) { void Events::listener_RendererDestroy(wl_listener* listener, void* data) { Debug::log(LOG, "!!Renderer destroyed!!"); +} + +void Events::listener_sessionActive(wl_listener* listener, void* data) { + Debug::log(LOG, "Session got activated!"); + + g_pCompositor->m_bSessionActive = true; } \ No newline at end of file diff --git a/src/events/Monitors.cpp b/src/events/Monitors.cpp index cf7e4b49..949d4585 100644 --- a/src/events/Monitors.cpp +++ b/src/events/Monitors.cpp @@ -166,6 +166,11 @@ void Events::listener_newOutput(wl_listener* listener, void* data) { void Events::listener_monitorFrame(void* owner, void* data) { SMonitor* const PMONITOR = (SMonitor*)owner; + if (!g_pCompositor->m_sWLRSession->active || !g_pCompositor->m_bSessionActive) { + Debug::log(WARN, "Attempted to render frame on inactive session!"); + return; // cannot draw on session inactive (different tty) + } + static std::chrono::high_resolution_clock::time_point startRender = std::chrono::high_resolution_clock::now(); static std::chrono::high_resolution_clock::time_point startRenderOverlay = std::chrono::high_resolution_clock::now(); static std::chrono::high_resolution_clock::time_point endRenderOverlay = std::chrono::high_resolution_clock::now(); @@ -182,6 +187,18 @@ void Events::listener_monitorFrame(void* owner, void* data) { g_pDebugOverlay->frameData(PMONITOR); } + if (PMONITOR->framesToSkip > 0) { + PMONITOR->framesToSkip -= 1; + + if (!PMONITOR->noFrameSchedule) + g_pCompositor->scheduleFrameForMonitor(PMONITOR); + else { + Debug::log(LOG, "NoFrameSchedule hit for %s.", PMONITOR->szName.c_str()); + } + g_pLayoutManager->getCurrentLayout()->recalculateMonitor(PMONITOR->ID); + return; + } + // checks // if (PMONITOR->ID == pMostHzMonitor->ID || !*PNOVFR) { // unfortunately with VFR we don't have the guarantee mostHz is going to be updated all the time, so we have to ignore that g_pCompositor->sanityCheckWorkspaces(); @@ -198,18 +215,6 @@ void Events::listener_monitorFrame(void* owner, void* data) { } // // - if (PMONITOR->framesToSkip > 0) { - PMONITOR->framesToSkip -= 1; - - if (!PMONITOR->noFrameSchedule) - wlr_output_schedule_frame(PMONITOR->output); - else { - Debug::log(LOG, "NoFrameSchedule hit for %s.", PMONITOR->szName.c_str()); - } - g_pLayoutManager->getCurrentLayout()->recalculateMonitor(PMONITOR->ID); - return; - } - timespec now; clock_gettime(CLOCK_MONOTONIC, &now); @@ -236,7 +241,7 @@ void Events::listener_monitorFrame(void* owner, void* data) { wlr_output_rollback(PMONITOR->output); if (*PDAMAGEBLINK || *PNOVFR) - wlr_output_schedule_frame(PMONITOR->output); + g_pCompositor->scheduleFrameForMonitor(PMONITOR); return; } @@ -326,7 +331,7 @@ void Events::listener_monitorFrame(void* owner, void* data) { wlr_output_commit(PMONITOR->output); if (*PDAMAGEBLINK || *PNOVFR) - wlr_output_schedule_frame(PMONITOR->output); + g_pCompositor->scheduleFrameForMonitor(PMONITOR); if (*PDEBUGOVERLAY == 1) { const float µs = std::chrono::duration_cast(std::chrono::high_resolution_clock::now() - startRender).count() / 1000.f; @@ -360,8 +365,7 @@ void Events::listener_monitorDestroy(void* owner, void* data) { if (!BACKUPMON) { Debug::log(CRIT, "No monitors! Unplugged last! Exiting."); - g_pCompositor->cleanupExit(); - exit(1); + g_pCompositor->cleanup(); return; } diff --git a/src/main.cpp b/src/main.cpp index 0947f375..3f68fa8f 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -46,7 +46,7 @@ int main(int argc, char** argv) { // If we are here it means we got yote. Debug::log(LOG, "Hyprland reached the end."); - g_pCompositor->cleanupExit(); + g_pCompositor->cleanup(); return EXIT_SUCCESS; } diff --git a/src/managers/AnimationManager.cpp b/src/managers/AnimationManager.cpp index 82fb8392..053267e3 100644 --- a/src/managers/AnimationManager.cpp +++ b/src/managers/AnimationManager.cpp @@ -195,7 +195,7 @@ void CAnimationManager::tick() { g_pXWaylandManager->setWindowSize(PWINDOW, PWINDOW->m_vRealSize.goalv()); // manually schedule a frame - wlr_output_schedule_frame(PMONITOR->output); + g_pCompositor->scheduleFrameForMonitor(PMONITOR); } } diff --git a/src/managers/KeybindManager.cpp b/src/managers/KeybindManager.cpp index 348f0655..60e4cdd6 100644 --- a/src/managers/KeybindManager.cpp +++ b/src/managers/KeybindManager.cpp @@ -140,11 +140,11 @@ bool CKeybindManager::handleVT(xkb_keysym_t keysym) { if (PSESSION) { const int TTY = keysym - XKB_KEY_XF86Switch_VT_1 + 1; wlr_session_change_vt(PSESSION, TTY); + g_pCompositor->m_bSessionActive = false; for (auto& m : g_pCompositor->m_vMonitors) { - g_pHyprOpenGL->destroyMonitorResources(m.get()); // mark resources as unusable anymore m->noFrameSchedule = true; - m->framesToSkip = 2; + m->framesToSkip = 1; } Debug::log(LOG, "Switched to VT %i, destroyed all render data, frames to skip for each: 2", TTY); @@ -812,8 +812,7 @@ void CKeybindManager::workspaceOpt(std::string args) { } void CKeybindManager::exitHyprland(std::string argz) { - g_pCompositor->cleanupExit(); - exit(0); + g_pCompositor->cleanup(); } void CKeybindManager::moveCurrentWorkspaceToMonitor(std::string args) { diff --git a/src/render/Renderer.cpp b/src/render/Renderer.cpp index e3a0f227..d2b5efa9 100644 --- a/src/render/Renderer.cpp +++ b/src/render/Renderer.cpp @@ -599,7 +599,7 @@ void CHyprRenderer::damageSurface(wlr_surface* pSurface, double x, double y) { // schedule frame events if (!wl_list_empty(&pSurface->current.frame_callback_list)) { - wlr_output_schedule_frame(g_pCompositor->getMonitorFromVector(Vector2D(x, y))->output); + g_pCompositor->scheduleFrameForMonitor(g_pCompositor->getMonitorFromVector(Vector2D(x, y))); } if (!pixman_region32_not_empty(&damageBox)) {