Hyprland/src/events/Monitors.cpp

404 lines
17 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"
2022-03-21 15:17:04 +01:00
// --------------------------------------------------------- //
// __ __ ____ _ _ _____ _______ ____ _____ _____ //
// | \/ |/ __ \| \ | |_ _|__ __/ __ \| __ \ / ____| //
// | \ / | | | | \| | | | | | | | | | |__) | (___ //
// | |\/| | | | | . ` | | | | | | | | | _ / \___ \ //
// | | | | |__| | |\ |_| |_ | | | |__| | | \ \ ____) | //
// |_| |_|\____/|_| \_|_____| |_| \____/|_| \_\_____/ //
// //
// --------------------------------------------------------- //
2022-06-17 20:31:15 +02:00
SMonitor* pMostHzMonitor = nullptr;
2022-04-19 18:00:54 +02:00
2022-06-17 20:31:15 +02:00
void Events::listener_change(wl_listener* listener, void* data) {
2022-03-21 15:17:04 +01:00
// layout got changed, let's update monitors.
const auto CONFIG = wlr_output_configuration_v1_create();
2022-06-30 15:44:26 +02:00
for (auto& m : g_pCompositor->m_vMonitors) {
const auto CONFIGHEAD = wlr_output_configuration_head_v1_create(CONFIG, m->output);
2022-03-21 15:17:04 +01:00
// TODO: clients off of disabled
wlr_box BOX;
2022-06-30 15:44:26 +02:00
wlr_output_layout_get_box(g_pCompositor->m_sWLROutputLayout, m->output, &BOX);
2022-03-21 15:17:04 +01:00
2022-06-30 15:44:26 +02:00
//m->vecSize.x = BOX.width;
// m->vecSize.y = BOX.height;
m->vecPosition.x = BOX.x;
m->vecPosition.y = BOX.y;
2022-03-21 15:17:04 +01:00
2022-06-30 15:44:26 +02:00
CONFIGHEAD->state.enabled = m->output->enabled;
CONFIGHEAD->state.mode = m->output->current_mode;
CONFIGHEAD->state.x = m->vecPosition.x;
CONFIGHEAD->state.y = m->vecPosition.y;
2022-03-21 15:17:04 +01:00
2022-06-30 15:44:26 +02:00
wlr_output_set_custom_mode(m->output, m->vecPixelSize.x, m->vecPixelSize.y, (int)(round(m->refreshRate * 1000)));
2022-03-21 15:17:04 +01:00
}
wlr_output_manager_v1_set_configuration(g_pCompositor->m_sWLROutputMgr, CONFIG);
}
2022-06-17 20:31:15 +02:00
void Events::listener_newOutput(wl_listener* listener, void* data) {
2022-03-21 15:17:04 +01:00
// new monitor added, let's accomodate 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-06-17 20:31:15 +02:00
if (g_pCompositor->getMonitorFromName(std::string(OUTPUT->name))) {
Debug::log(WARN, "Monitor with name %s already exists, not adding as new!", OUTPUT->name);
return;
}
2022-04-17 10:19:46 +02:00
// get monitor rule that matches
SMonitorRule monitorRule = g_pConfigManager->getMonitorRuleFor(OUTPUT->name);
// if it's disabled, disable and ignore
2022-06-17 20:31:15 +02:00
if (monitorRule.disabled) {
2022-04-17 10:19:46 +02:00
wlr_output_enable(OUTPUT, 0);
wlr_output_commit(OUTPUT);
2022-06-01 21:10:12 +02:00
2022-06-17 20:31:15 +02:00
if (const auto PMONITOR = g_pCompositor->getMonitorFromName(std::string(OUTPUT->name)); PMONITOR) {
2022-06-01 21:10:12 +02:00
listener_monitorDestroy(nullptr, PMONITOR->output);
}
2022-04-17 10:19:46 +02:00
return;
}
2022-03-21 15:17:04 +01:00
SMonitor newMonitor;
newMonitor.output = OUTPUT;
2022-05-30 17:11:35 +02:00
newMonitor.ID = g_pCompositor->getNextAvailableMonitorID();
2022-03-21 15:17:04 +01:00
newMonitor.szName = OUTPUT->name;
wlr_output_init_render(OUTPUT, g_pCompositor->m_sWLRAllocator, g_pCompositor->m_sWLRRenderer);
wlr_output_set_scale(OUTPUT, monitorRule.scale);
wlr_xcursor_manager_load(g_pCompositor->m_sWLRXCursorMgr, monitorRule.scale);
2022-06-17 20:31:15 +02:00
wlr_output_set_transform(OUTPUT, WL_OUTPUT_TRANSFORM_NORMAL); // TODO: support other transforms
2022-03-21 15:17:04 +01:00
wlr_output_enable_adaptive_sync(OUTPUT, 1);
// create it in the arr
newMonitor.vecPosition = monitorRule.offset;
newMonitor.vecSize = monitorRule.resolution;
newMonitor.refreshRate = monitorRule.refreshRate;
2022-06-30 15:44:26 +02:00
const auto PNEWMONITOR = g_pCompositor->m_vMonitors.emplace_back(std::make_unique<SMonitor>(newMonitor)).get();
2022-03-21 15:17:04 +01:00
PNEWMONITOR->hyprListener_monitorFrame.initCallback(&OUTPUT->events.frame, &Events::listener_monitorFrame, PNEWMONITOR);
PNEWMONITOR->hyprListener_monitorDestroy.initCallback(&OUTPUT->events.destroy, &Events::listener_monitorDestroy, PNEWMONITOR);
2022-03-21 15:17:04 +01:00
wlr_output_enable(OUTPUT, 1);
// TODO: this doesn't seem to set the X and Y correctly,
// wlr_output_layout_output_coords returns invalid values, I think...
2022-03-21 15:17:04 +01:00
wlr_output_layout_add(g_pCompositor->m_sWLROutputLayout, OUTPUT, monitorRule.offset.x, monitorRule.offset.y);
2022-04-19 19:01:23 +02:00
// set mode, also applies
g_pHyprRenderer->applyMonitorRule(PNEWMONITOR, &monitorRule, true);
2022-03-21 15:17:04 +01:00
2022-04-19 18:00:54 +02:00
Debug::log(LOG, "Added new monitor with name %s at %i,%i with size %ix%i, pointer %x", OUTPUT->name, (int)monitorRule.offset.x, (int)monitorRule.offset.y, (int)monitorRule.resolution.x, (int)monitorRule.resolution.y, OUTPUT);
2022-04-19 19:01:23 +02:00
PNEWMONITOR->damage = wlr_output_damage_create(PNEWMONITOR->output);
// add a WLR workspace group
PNEWMONITOR->pWLRWorkspaceGroupHandle = wlr_ext_workspace_group_handle_v1_create(g_pCompositor->m_sWLREXTWorkspaceMgr);
2022-04-28 18:06:25 +02:00
wlr_ext_workspace_group_handle_v1_output_enter(PNEWMONITOR->pWLRWorkspaceGroupHandle, PNEWMONITOR->output);
// Workspace
std::string newDefaultWorkspaceName = "";
2022-06-30 15:44:26 +02:00
auto WORKSPACEID = monitorRule.defaultWorkspace == "" ? g_pCompositor->m_vWorkspaces.size() + 1 : getWorkspaceIDFromString(monitorRule.defaultWorkspace, newDefaultWorkspaceName);
if (WORKSPACEID == INT_MAX || WORKSPACEID == (long unsigned int)SPECIAL_WORKSPACE_ID) {
2022-06-30 15:44:26 +02:00
WORKSPACEID = g_pCompositor->m_vWorkspaces.size() + 1;
newDefaultWorkspaceName = std::to_string(WORKSPACEID);
Debug::log(LOG, "Invalid workspace= directive name in monitor parsing, workspace name \"%s\" is invalid.", monitorRule.defaultWorkspace);
}
auto PNEWWORKSPACE = g_pCompositor->getWorkspaceByID(WORKSPACEID);
Debug::log(LOG, "New monitor: WORKSPACEID %d, exists: %d", WORKSPACEID, (int)(PNEWWORKSPACE != nullptr));
2022-06-17 20:31:15 +02:00
if (PNEWWORKSPACE) {
// workspace exists, move it to the newly connected monitor
g_pCompositor->moveWorkspaceToMonitor(PNEWWORKSPACE, PNEWMONITOR);
PNEWMONITOR->activeWorkspace = PNEWWORKSPACE->m_iID;
g_pLayoutManager->getCurrentLayout()->recalculateMonitor(PNEWMONITOR->ID);
PNEWWORKSPACE->startAnim(true,true,true);
2022-06-17 20:31:15 +02:00
} else {
2022-06-30 15:44:26 +02:00
PNEWWORKSPACE = g_pCompositor->m_vWorkspaces.emplace_back(std::make_unique<CWorkspace>(newMonitor.ID, newDefaultWorkspaceName)).get();
// We are required to set the name here immediately
wlr_ext_workspace_handle_v1_set_name(PNEWWORKSPACE->m_pWlrHandle, newDefaultWorkspaceName.c_str());
PNEWWORKSPACE->m_iID = WORKSPACEID;
}
PNEWMONITOR->activeWorkspace = PNEWWORKSPACE->m_iID;
PNEWMONITOR->scale = monitorRule.scale;
2022-06-21 22:13:13 +02:00
PNEWMONITOR->forceFullFrames = 3; // force 3 full frames to make sure there is no blinking due to double-buffering.
2022-04-28 17:55:25 +02:00
g_pCompositor->deactivateAllWLRWorkspaces(PNEWWORKSPACE->m_pWlrHandle);
2022-05-25 10:25:36 +02:00
PNEWWORKSPACE->setActive(true);
2022-04-19 18:00:54 +02:00
if (!pMostHzMonitor || monitorRule.refreshRate > pMostHzMonitor->refreshRate)
pMostHzMonitor = PNEWMONITOR;
//
if (!g_pCompositor->m_pLastMonitor) // set the last monitor if it isnt set yet
g_pCompositor->m_pLastMonitor = PNEWMONITOR;
g_pEventManager->postEvent(SHyprIPCEvent("monitoradded", PNEWMONITOR->szName));
// ready to process cuz we have a monitor
g_pCompositor->m_bReadyToProcess = true;
2022-03-21 15:17:04 +01:00
}
2022-06-17 20:31:15 +02:00
void Events::listener_monitorFrame(void* owner, void* data) {
SMonitor* const PMONITOR = (SMonitor*)owner;
2022-03-21 15:17:04 +01:00
2022-05-28 17:32:19 +02:00
static std::chrono::high_resolution_clock::time_point startRender = std::chrono::high_resolution_clock::now();
2022-05-28 17:40:57 +02:00
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();
2022-05-28 17:32:19 +02:00
static auto *const PDEBUGOVERLAY = &g_pConfigManager->getConfigValuePtr("debug:overlay")->intValue;
static auto *const PDAMAGETRACKINGMODE = &g_pConfigManager->getConfigValuePtr("general:damage_tracking_internal")->intValue;
2022-06-29 11:44:00 +02:00
static auto *const PDAMAGEBLINK = &g_pConfigManager->getConfigValuePtr("debug:damage_blink")->intValue;
static int damageBlinkCleanup = 0; // because double-buffered
2022-06-17 20:31:15 +02:00
if (*PDEBUGOVERLAY == 1) {
2022-05-28 17:32:19 +02:00
startRender = std::chrono::high_resolution_clock::now();
g_pDebugOverlay->frameData(PMONITOR);
}
2022-04-19 18:00:54 +02:00
// Hack: only check when monitor with top hz refreshes, saves a bit of resources.
2022-03-23 22:01:59 +01:00
// This is for stuff that should be run every frame
2022-06-17 20:31:15 +02:00
if (PMONITOR->ID == pMostHzMonitor->ID) {
2022-03-23 22:01:59 +01:00
g_pCompositor->sanityCheckWorkspaces();
g_pAnimationManager->tick();
g_pCompositor->cleanupFadingOut();
2022-04-12 20:02:57 +02:00
2022-04-21 22:00:03 +02:00
HyprCtl::tickHyprCtl(); // so that we dont get that race condition multithread bullshit
2022-04-12 20:02:57 +02:00
g_pConfigManager->dispatchExecOnce(); // We exec-once when at least one monitor starts refreshing, meaning stuff has init'd
2022-04-19 19:01:23 +02:00
if (g_pConfigManager->m_bWantsMonitorReload)
g_pConfigManager->performMonitorReload();
2022-06-24 23:27:02 +02:00
g_pHyprRenderer->ensureCursorRenderingMode(); // so that the cursor gets hidden/shown if the user requested timeouts
2022-03-23 22:01:59 +01:00
}
2022-06-17 20:31:15 +02:00
if (PMONITOR->framesToSkip > 0) {
PMONITOR->framesToSkip -= 1;
if (!PMONITOR->noFrameSchedule)
wlr_output_schedule_frame(PMONITOR->output);
2022-06-17 20:31:15 +02:00
else {
Debug::log(LOG, "NoFrameSchedule hit for %s.", PMONITOR->szName.c_str());
}
2022-04-21 18:11:28 +02:00
g_pLayoutManager->getCurrentLayout()->recalculateMonitor(PMONITOR->ID);
return;
}
2022-03-21 15:17:04 +01:00
timespec now;
clock_gettime(CLOCK_MONOTONIC, &now);
2022-04-14 16:43:29 +02:00
// check the damage
pixman_region32_t damage;
bool hasChanged;
pixman_region32_init(&damage);
2022-06-17 20:31:15 +02:00
if (*PDAMAGETRACKINGMODE == -1) {
2022-04-14 16:43:29 +02:00
Debug::log(CRIT, "Damage tracking mode -1 ????");
2022-03-21 15:17:04 +01:00
return;
2022-04-14 16:43:29 +02:00
}
2022-03-21 15:17:04 +01:00
2022-06-17 20:31:15 +02:00
if (!wlr_output_damage_attach_render(PMONITOR->damage, &hasChanged, &damage)){
2022-04-14 16:43:29 +02:00
Debug::log(ERR, "Couldn't attach render to display %s ???", PMONITOR->szName.c_str());
return;
}
2022-06-29 11:44:00 +02:00
if (!hasChanged && *PDAMAGETRACKINGMODE != DAMAGE_TRACKING_NONE && PMONITOR->forceFullFrames == 0 && damageBlinkCleanup == 0) {
2022-04-14 16:43:29 +02:00
pixman_region32_fini(&damage);
wlr_output_rollback(PMONITOR->output);
wlr_output_schedule_frame(PMONITOR->output); // we update shit at the monitor's Hz so we need to schedule frames because rollback wont
return;
}
// if we have no tracking or full tracking, invalidate the entire monitor
2022-06-29 11:44:00 +02:00
if (*PDAMAGETRACKINGMODE == DAMAGE_TRACKING_NONE || *PDAMAGETRACKINGMODE == DAMAGE_TRACKING_MONITOR || PMONITOR->forceFullFrames > 0 || damageBlinkCleanup > 0) {
pixman_region32_union_rect(&damage, &damage, 0, 0, (int)PMONITOR->vecTransformedSize.x, (int)PMONITOR->vecTransformedSize.y);
pixman_region32_copy(&g_pHyprOpenGL->m_rOriginalDamageRegion, &damage);
2022-06-17 20:31:15 +02:00
} else {
static auto* const PBLURENABLED = &g_pConfigManager->getConfigValuePtr("decoration:blur")->intValue;
// if we use blur we need to expand the damage for proper blurring
2022-06-17 20:31:15 +02:00
if (*PBLURENABLED == 1) {
// TODO: can this be optimized?
2022-06-17 20:31:15 +02:00
static auto* const PBLURSIZE = &g_pConfigManager->getConfigValuePtr("decoration:blur_size")->intValue;
static auto* const PBLURPASSES = &g_pConfigManager->getConfigValuePtr("decoration:blur_passes")->intValue;
const auto BLURRADIUS = *PBLURSIZE * pow(2, *PBLURPASSES); // is this 2^pass? I don't know but it works... I think.
pixman_region32_copy(&g_pHyprOpenGL->m_rOriginalDamageRegion, &damage);
// now, prep the damage, get the extended damage region
2022-06-17 20:31:15 +02:00
wlr_region_expand(&damage, &damage, BLURRADIUS); // expand for proper blurring
} else {
2022-05-25 19:19:54 +02:00
pixman_region32_copy(&g_pHyprOpenGL->m_rOriginalDamageRegion, &damage);
}
2022-04-14 16:43:29 +02:00
}
2022-06-21 22:13:13 +02:00
if (PMONITOR->forceFullFrames > 0)
PMONITOR->forceFullFrames -= 1;
2022-04-14 16:43:29 +02:00
// TODO: this is getting called with extents being 0,0,0,0 should it be?
// potentially can save on resources.
g_pHyprOpenGL->begin(PMONITOR, &damage);
g_pHyprOpenGL->clear(CColor(100, 11, 11, 255));
2022-04-10 14:32:18 +02:00
g_pHyprOpenGL->clearWithTex(); // will apply the hypr "wallpaper"
2022-03-21 15:17:04 +01:00
2022-04-05 14:33:54 +02:00
g_pHyprRenderer->renderAllClientsForMonitor(PMONITOR->ID, &now);
2022-03-21 15:17:04 +01:00
2022-05-28 17:32:19 +02:00
// if correct monitor draw hyprerror
if (PMONITOR->ID == 0)
g_pHyprError->draw();
// for drawing the debug overlay
2022-06-17 20:31:15 +02:00
if (PMONITOR->ID == 0 && *PDEBUGOVERLAY == 1) {
2022-05-28 17:40:57 +02:00
startRenderOverlay = std::chrono::high_resolution_clock::now();
2022-05-28 17:32:19 +02:00
g_pDebugOverlay->draw();
2022-05-28 17:40:57 +02:00
endRenderOverlay = std::chrono::high_resolution_clock::now();
}
2022-05-28 17:32:19 +02:00
2022-06-29 11:44:00 +02:00
if (*PDAMAGEBLINK && damageBlinkCleanup == 0) {
wlr_box monrect = {0, 0, PMONITOR->vecPixelSize.x, PMONITOR->vecPixelSize.y};
g_pHyprOpenGL->renderRect(&monrect, CColor(255,0,255,100), 0);
damageBlinkCleanup = 1;
} else if (*PDAMAGEBLINK) {
damageBlinkCleanup++;
if (damageBlinkCleanup > 3)
damageBlinkCleanup = 0;
}
wlr_renderer_begin(g_pCompositor->m_sWLRRenderer, PMONITOR->vecPixelSize.x, PMONITOR->vecPixelSize.y);
2022-05-16 21:30:11 +02:00
2022-04-05 14:33:54 +02:00
wlr_output_render_software_cursors(PMONITOR->output, NULL);
2022-04-04 19:44:25 +02:00
2022-04-05 14:33:54 +02:00
wlr_renderer_end(g_pCompositor->m_sWLRRenderer);
2022-04-04 19:44:25 +02:00
2022-04-05 14:33:54 +02:00
g_pHyprOpenGL->end();
2022-03-21 15:17:04 +01:00
2022-04-14 16:43:29 +02:00
// calc frame damage
pixman_region32_t frameDamage;
pixman_region32_init(&frameDamage);
const auto TRANSFORM = wlr_output_transform_invert(PMONITOR->output->transform);
wlr_region_transform(&frameDamage, &PMONITOR->damage->current, TRANSFORM, (int)PMONITOR->vecTransformedSize.x, (int)PMONITOR->vecTransformedSize.y);
if (*PDAMAGETRACKINGMODE == DAMAGE_TRACKING_NONE || *PDAMAGETRACKINGMODE == DAMAGE_TRACKING_MONITOR)
pixman_region32_union_rect(&frameDamage, &frameDamage, 0, 0, (int)PMONITOR->vecTransformedSize.x, (int)PMONITOR->vecTransformedSize.y);
2022-04-14 16:43:29 +02:00
2022-06-29 11:44:00 +02:00
if (*PDAMAGEBLINK)
pixman_region32_union(&frameDamage, &frameDamage, &damage);
2022-04-14 16:43:29 +02:00
wlr_output_set_damage(PMONITOR->output, &frameDamage);
pixman_region32_fini(&frameDamage);
pixman_region32_fini(&damage);
2022-03-21 15:17:04 +01:00
wlr_output_commit(PMONITOR->output);
2022-04-14 16:43:29 +02:00
wlr_output_schedule_frame(PMONITOR->output);
2022-05-28 17:32:19 +02:00
2022-06-17 20:31:15 +02:00
if (*PDEBUGOVERLAY == 1) {
2022-05-28 17:40:57 +02:00
const float µs = std::chrono::duration_cast<std::chrono::nanoseconds>(std::chrono::high_resolution_clock::now() - startRender).count() / 1000.f;
g_pDebugOverlay->renderData(PMONITOR, µs);
2022-06-17 20:31:15 +02:00
if (PMONITOR->ID == 0) {
2022-05-28 17:40:57 +02:00
const float µsNoOverlay = µs - std::chrono::duration_cast<std::chrono::nanoseconds>(endRenderOverlay - startRenderOverlay).count() / 1000.f;
g_pDebugOverlay->renderDataNoOverlay(PMONITOR, µsNoOverlay);
2022-06-17 20:31:15 +02:00
} else {
2022-05-28 17:40:57 +02:00
g_pDebugOverlay->renderDataNoOverlay(PMONITOR, µs);
}
}
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
2022-06-17 20:31:15 +02:00
SMonitor* pMonitor = nullptr;
2022-03-21 15:17:04 +01:00
2022-06-30 15:44:26 +02:00
for (auto& m : g_pCompositor->m_vMonitors) {
if (m->szName == OUTPUT->name) {
pMonitor = m.get();
2022-03-21 15:17:04 +01:00
break;
}
}
if (!pMonitor)
return;
2022-05-30 17:11:35 +02:00
// Cleanup everything. Move windows back, snap cursor, shit.
2022-06-30 15:44:26 +02:00
const auto BACKUPMON = g_pCompositor->m_vMonitors.front().get();
2022-06-17 20:31:15 +02:00
if (!BACKUPMON) {
2022-05-30 17:11:35 +02:00
Debug::log(CRIT, "No monitors! Unplugged last! Exiting.");
g_pCompositor->cleanupExit();
2022-06-08 15:13:47 +02:00
exit(1);
2022-05-30 17:11:35 +02:00
return;
}
2022-06-08 15:13:47 +02:00
const auto BACKUPWORKSPACE = BACKUPMON->activeWorkspace > 0 ? std::to_string(BACKUPMON->activeWorkspace) : "name:" + g_pCompositor->getWorkspaceByID(BACKUPMON->activeWorkspace)->m_szName;
2022-05-30 17:11:35 +02:00
// snap cursor
wlr_cursor_warp(g_pCompositor->m_sWLRCursor, g_pCompositor->m_sSeat.mouse->mouse, BACKUPMON->vecPosition.x + BACKUPMON->vecTransformedSize.x / 2.f, BACKUPMON->vecPosition.y + BACKUPMON->vecTransformedSize.y / 2.f);
// move workspaces
2022-06-17 20:31:15 +02:00
std::deque<CWorkspace*> wspToMove;
2022-06-30 15:44:26 +02:00
for (auto& w : g_pCompositor->m_vWorkspaces) {
if (w->m_iMonitorID == pMonitor->ID) {
wspToMove.push_back(w.get());
2022-05-30 17:11:35 +02:00
}
}
2022-06-17 20:31:15 +02:00
for (auto& w : wspToMove) {
g_pCompositor->moveWorkspaceToMonitor(w, BACKUPMON);
w->startAnim(true, true, true);
}
pMonitor->activeWorkspace = -1;
2022-06-30 15:44:26 +02:00
g_pCompositor->m_vWorkspaces.erase(std::remove_if(g_pCompositor->m_vWorkspaces.begin(), g_pCompositor->m_vWorkspaces.end(), [&](std::unique_ptr<CWorkspace>& el) { return el->m_iMonitorID == pMonitor->ID; }));
2022-05-30 17:11:35 +02:00
Debug::log(LOG, "Removed monitor %s!", pMonitor->szName.c_str());
g_pEventManager->postEvent(SHyprIPCEvent("monitorremoved", pMonitor->szName));
2022-06-30 15:44:26 +02:00
g_pCompositor->m_vMonitors.erase(std::remove_if(g_pCompositor->m_vMonitors.begin(), g_pCompositor->m_vMonitors.end(), [&](std::unique_ptr<SMonitor>& el) { return el.get() == pMonitor; }));
2022-03-21 15:17:04 +01:00
2022-05-30 17:11:35 +02:00
// update the pMostHzMonitor
2022-06-17 20:31:15 +02:00
if (pMostHzMonitor == pMonitor) {
2022-05-30 17:11:35 +02:00
int mostHz = 0;
2022-06-17 20:31:15 +02:00
SMonitor* pMonitorMostHz = nullptr;
2022-05-30 17:11:35 +02:00
2022-06-30 15:44:26 +02:00
for (auto& m : g_pCompositor->m_vMonitors) {
if (m->refreshRate > mostHz) {
pMonitorMostHz = m.get();
mostHz = m->refreshRate;
2022-05-30 17:11:35 +02:00
}
}
pMostHzMonitor = pMonitorMostHz;
}
2022-03-21 15:17:04 +01:00
}