Hyprland/src/events/Monitors.cpp

248 lines
8.5 KiB
C++
Raw Normal View History

2022-03-21 15:17:04 +01:00
#include "../Compositor.hpp"
#include "../helpers/WLClasses.hpp"
2022-06-09 12:46:55 +02:00
#include "../managers/input/InputManager.hpp"
2022-03-21 15:17:04 +01:00
#include "../render/Renderer.hpp"
#include "Events.hpp"
2022-04-21 22:00:03 +02:00
#include "../debug/HyprCtl.hpp"
#include "../config/ConfigValue.hpp"
2022-03-21 15:17:04 +01:00
// --------------------------------------------------------- //
// __ __ ____ _ _ _____ _______ ____ _____ _____ //
// | \/ |/ __ \| \ | |_ _|__ __/ __ \| __ \ / ____| //
// | \ / | | | | \| | | | | | | | | | |__) | (___ //
// | |\/| | | | | . ` | | | | | | | | | _ / \___ \ //
// | | | | |__| | |\ |_| |_ | | | |__| | | \ \ ____) | //
// |_| |_|\____/|_| \_|_____| |_| \____/|_| \_\_____/ //
// //
// --------------------------------------------------------- //
static void checkDefaultCursorWarp(SP<CMonitor> PNEWMONITOR, std::string monitorName) {
static auto PCURSORMONITOR = CConfigValue<std::string>("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::seconds>(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();
}
}
2022-06-17 20:31:15 +02:00
void Events::listener_newOutput(wl_listener* listener, void* data) {
// new monitor added, let's accommodate for that.
2022-06-17 20:31:15 +02:00
const auto OUTPUT = (wlr_output*)data;
2022-03-21 15:17:04 +01:00
2022-06-17 20:31:15 +02:00
if (!OUTPUT->name) {
Debug::log(ERR, "New monitor has no name?? Ignoring");
return;
}
2022-07-27 12:32:00 +02:00
// add it to real
auto PNEWMONITOR = g_pCompositor->m_vRealMonitors.emplace_back(makeShared<CMonitor>());
if (std::string("HEADLESS-1") == OUTPUT->name)
g_pCompositor->m_pUnsafeOutput = PNEWMONITOR.get();
2022-08-10 21:54:09 +02:00
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;
2022-08-10 21:54:09 +02:00
EMIT_HOOK_EVENT("newMonitor", PNEWMONITOR);
if (!FALLBACK)
PNEWMONITOR->onConnect(false);
2022-08-03 16:19:00 +02:00
if (!PNEWMONITOR->m_bEnabled || FALLBACK)
return;
2022-06-21 22:13:13 +02:00
// 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();
2022-07-12 10:02:12 +02:00
g_pCompositor->m_bReadyToProcess = true;
g_pConfigManager->m_bWantsMonitorReload = true;
g_pCompositor->scheduleFrameForMonitor(PNEWMONITOR.get());
2023-01-28 13:26:33 +01:00
checkDefaultCursorWarp(PNEWMONITOR, OUTPUT->name);
for (auto& w : g_pCompositor->m_vWindows) {
if (w->m_iMonitorID == PNEWMONITOR->ID) {
w->m_iLastSurfaceMonitorID = -1;
w->updateSurfaceScaleTransformDetails();
}
2023-01-28 13:26:33 +01:00
}
2022-03-21 15:17:04 +01:00
}
2022-06-17 20:31:15 +02:00
void Events::listener_monitorFrame(void* owner, void* data) {
if (g_pCompositor->m_bExitTriggered) {
// Only signal cleanup once
g_pCompositor->m_bExitTriggered = false;
g_pCompositor->cleanup();
return;
}
2022-07-27 12:32:00 +02:00
CMonitor* const PMONITOR = (CMonitor*)owner;
2022-03-21 15:17:04 +01:00
2022-08-10 21:54:09 +02:00
if ((g_pCompositor->m_sWLRSession && !g_pCompositor->m_sWLRSession->active) || !g_pCompositor->m_bSessionActive || g_pCompositor->m_bUnsafeState) {
2022-07-13 18:18:23 +02:00
Debug::log(WARN, "Attempted to render frame on inactive session!");
2023-03-15 16:11:41 +01:00
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();
}
2023-03-15 16:11:41 +01:00
2022-07-13 18:18:23 +02:00
return; // cannot draw on session inactive (different tty)
}
2022-09-25 20:07:48 +02:00
2022-07-27 12:32:00 +02:00
if (!PMONITOR->m_bEnabled)
return;
2022-07-13 18:18:23 +02:00
g_pHyprRenderer->recheckSolitaryForMonitor(PMONITOR);
PMONITOR->tearingState.busy = false;
if (PMONITOR->tearingState.activelyTearing && PMONITOR->solitaryClient.lock() /* can be invalidated by a recheck */) {
if (!PMONITOR->tearingState.frameScheduledWhileBusy)
return; // we did not schedule a frame yet to be displayed, but we are tearing. Why render?
PMONITOR->tearingState.nextRenderTorn = true;
PMONITOR->tearingState.frameScheduledWhileBusy = false;
}
static auto PENABLERAT = CConfigValue<Hyprlang::INT>("misc:render_ahead_of_time");
static auto PRATSAFE = CConfigValue<Hyprlang::INT>("misc:render_ahead_safezone");
2022-05-28 17:32:19 +02:00
PMONITOR->lastPresentationTimer.reset();
2022-06-29 11:44:00 +02:00
if (*PENABLERAT && !PMONITOR->tearingState.nextRenderTorn) {
if (!PMONITOR->RATScheduled) {
// render
g_pHyprRenderer->renderMonitor(PMONITOR);
2022-07-13 18:18:23 +02:00
}
2022-07-31 16:54:36 +02:00
PMONITOR->RATScheduled = false;
2022-07-13 18:18:23 +02:00
const auto& [avg, max, min] = g_pHyprRenderer->getRenderTimes(PMONITOR);
2022-04-12 20:02:57 +02:00
if (max + *PRATSAFE > 1000.0 / PMONITOR->refreshRate)
2022-11-05 13:50:47 +01:00
return;
const auto MSLEFT = 1000.0 / PMONITOR->refreshRate - PMONITOR->lastPresentationTimer.getMillis();
2022-09-25 20:07:48 +02:00
PMONITOR->RATScheduled = true;
2022-04-14 16:43:29 +02:00
const auto ESTRENDERTIME = std::ceil(avg + *PRATSAFE);
const auto TIMETOSLEEP = std::floor(MSLEFT - ESTRENDERTIME);
2022-03-21 15:17:04 +01:00
if (MSLEFT < 1 || MSLEFT < ESTRENDERTIME || TIMETOSLEEP < 1)
g_pHyprRenderer->renderMonitor(PMONITOR);
else
wl_event_source_timer_update(PMONITOR->renderTimer, TIMETOSLEEP);
2022-09-13 15:25:42 +02:00
} else {
g_pHyprRenderer->renderMonitor(PMONITOR);
2022-05-28 17:40:57 +02:00
}
2022-03-21 15:17:04 +01:00
}
2022-06-17 20:31:15 +02:00
void Events::listener_monitorDestroy(void* owner, void* data) {
const auto OUTPUT = (wlr_output*)data;
2022-03-21 15:17:04 +01:00
CMonitor* pMonitor = nullptr;
2022-03-21 15:17:04 +01:00
2022-11-19 14:14:55 +01:00
for (auto& m : g_pCompositor->m_vRealMonitors) {
if (m->output == OUTPUT) {
2022-06-30 15:44:26 +02:00
pMonitor = m.get();
2022-03-21 15:17:04 +01:00
break;
}
}
if (!pMonitor)
return;
2023-09-06 12:51:36 +02:00
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);
2023-03-15 16:11:41 +01:00
pMonitor->output = nullptr;
pMonitor->m_bRenderingInitPassed = false;
Debug::log(LOG, "Removing monitor {} from realMonitors", pMonitor->szName);
std::erase_if(g_pCompositor->m_vRealMonitors, [&](SP<CMonitor>& el) { return el.get() == pMonitor; });
2022-03-21 15:17:04 +01:00
}
2022-11-19 17:28:04 +01:00
void Events::listener_monitorStateRequest(void* owner, void* data) {
const auto PMONITOR = (CMonitor*)owner;
const auto E = (wlr_output_event_request_state*)data;
if (!PMONITOR->createdByUser)
return;
const auto SIZE = E->state->mode ? Vector2D{E->state->mode->width, E->state->mode->height} : Vector2D{E->state->custom_mode.width, E->state->custom_mode.height};
PMONITOR->forceSize = SIZE;
SMonitorRule rule = PMONITOR->activeMonitorRule;
rule.resolution = SIZE;
2022-11-19 17:28:04 +01:00
g_pHyprRenderer->applyMonitorRule(PMONITOR, &rule);
2022-11-19 17:28:04 +01:00
}
void Events::listener_monitorDamage(void* owner, void* data) {
const auto PMONITOR = (CMonitor*)owner;
const auto E = (wlr_output_event_damage*)data;
PMONITOR->addDamage(E->damage);
}
2023-04-07 18:25:56 +02:00
void Events::listener_monitorNeedsFrame(void* owner, void* data) {
const auto PMONITOR = (CMonitor*)owner;
g_pCompositor->scheduleFrameForMonitor(PMONITOR);
}
2023-04-12 22:40:51 +02:00
void Events::listener_monitorCommit(void* owner, void* data) {
const auto PMONITOR = (CMonitor*)owner;
const auto E = (wlr_output_event_commit*)data;
2023-10-25 01:27:16 +02:00
if (E->state->committed & WLR_OUTPUT_STATE_BUFFER) {
g_pProtocolManager->m_pScreencopyProtocolManager->onOutputCommit(PMONITOR, E);
g_pProtocolManager->m_pToplevelExportProtocolManager->onOutputCommit(PMONITOR, E);
}
}
void Events::listener_monitorBind(void* owner, void* data) {
;
2023-04-12 22:40:51 +02:00
}