mirror of
https://github.com/hyprwm/Hyprland
synced 2024-12-23 00:29:49 +01:00
Added monitor mirroring
This commit is contained in:
parent
7d4f0a3199
commit
e9f226797e
9 changed files with 271 additions and 77 deletions
|
@ -493,11 +493,16 @@ void CConfigManager::handleMonitor(const std::string& command, const std::string
|
|||
|
||||
nextItem();
|
||||
|
||||
if (curitem != "") {
|
||||
// warning for old cfg
|
||||
Debug::log(ERR, "Error in parsing rule for %s, possibly old config!", newrule.name.c_str());
|
||||
parseError = "Error in setting monitor rule. Are you using the old syntax? Confront the wiki.";
|
||||
return;
|
||||
while (curitem != "") {
|
||||
if (curitem == "mirror") {
|
||||
nextItem();
|
||||
newrule.mirrorOf = curitem;
|
||||
nextItem();
|
||||
} else {
|
||||
Debug::log(ERR, "Config error: invalid monitor syntax");
|
||||
parseError = "invalid syntax at \"" + curitem + "\"";
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if (std::find_if(m_dMonitorRules.begin(), m_dMonitorRules.end(), [&](const auto& other) { return other.name == newrule.name; }) != m_dMonitorRules.end())
|
||||
|
@ -1444,6 +1449,10 @@ void CConfigManager::performMonitorReload() {
|
|||
|
||||
for (auto& m : g_pCompositor->m_vRealMonitors) {
|
||||
auto rule = getMonitorRuleFor(m->szName);
|
||||
|
||||
// ensure mirror
|
||||
m->setMirror(rule.mirrorOf);
|
||||
|
||||
if (!g_pHyprRenderer->applyMonitorRule(m.get(), &rule)) {
|
||||
overAgain = true;
|
||||
break;
|
||||
|
|
|
@ -36,6 +36,7 @@ struct SMonitorRule {
|
|||
std::string defaultWorkspace = "";
|
||||
bool disabled = false;
|
||||
wl_output_transform transform = WL_OUTPUT_TRANSFORM_NORMAL;
|
||||
std::string mirrorOf = "";
|
||||
};
|
||||
|
||||
struct SMonitorAdditionalReservedArea {
|
||||
|
|
|
@ -190,7 +190,7 @@ void Events::listener_monitorFrame(void* owner, void* data) {
|
|||
}
|
||||
|
||||
// if we have no tracking or full tracking, invalidate the entire monitor
|
||||
if (*PDAMAGETRACKINGMODE == DAMAGE_TRACKING_NONE || *PDAMAGETRACKINGMODE == DAMAGE_TRACKING_MONITOR || PMONITOR->forceFullFrames > 0 || damageBlinkCleanup > 0) {
|
||||
if (*PDAMAGETRACKINGMODE == DAMAGE_TRACKING_NONE || *PDAMAGETRACKINGMODE == DAMAGE_TRACKING_MONITOR || PMONITOR->forceFullFrames > 0 || damageBlinkCleanup > 0 || PMONITOR->isMirror() /* why??? */) {
|
||||
pixman_region32_union_rect(&damage, &damage, 0, 0, (int)PMONITOR->vecTransformedSize.x * 10, (int)PMONITOR->vecTransformedSize.y * 10); // wot?
|
||||
|
||||
pixman_region32_copy(&g_pHyprOpenGL->m_rOriginalDamageRegion, &damage);
|
||||
|
@ -224,38 +224,45 @@ void Events::listener_monitorFrame(void* owner, void* data) {
|
|||
// potentially can save on resources.
|
||||
|
||||
g_pHyprOpenGL->begin(PMONITOR, &damage);
|
||||
g_pHyprOpenGL->clear(CColor(17, 17, 17, 255));
|
||||
g_pHyprOpenGL->clearWithTex(); // will apply the hypr "wallpaper"
|
||||
|
||||
g_pHyprRenderer->renderAllClientsForMonitor(PMONITOR->ID, &now);
|
||||
if (PMONITOR->isMirror()) {
|
||||
g_pHyprOpenGL->renderMirrored();
|
||||
|
||||
// if correct monitor draw hyprerror
|
||||
if (PMONITOR->ID == 0)
|
||||
g_pHyprError->draw();
|
||||
Debug::log(LOG, "Mirror frame");
|
||||
} else {
|
||||
g_pHyprOpenGL->clear(CColor(17, 17, 17, 255));
|
||||
g_pHyprOpenGL->clearWithTex(); // will apply the hypr "wallpaper"
|
||||
|
||||
// for drawing the debug overlay
|
||||
if (PMONITOR->ID == 0 && *PDEBUGOVERLAY == 1) {
|
||||
startRenderOverlay = std::chrono::high_resolution_clock::now();
|
||||
g_pDebugOverlay->draw();
|
||||
endRenderOverlay = std::chrono::high_resolution_clock::now();
|
||||
g_pHyprRenderer->renderAllClientsForMonitor(PMONITOR->ID, &now);
|
||||
|
||||
// if correct monitor draw hyprerror
|
||||
if (PMONITOR->ID == 0)
|
||||
g_pHyprError->draw();
|
||||
|
||||
// for drawing the debug overlay
|
||||
if (PMONITOR->ID == 0 && *PDEBUGOVERLAY == 1) {
|
||||
startRenderOverlay = std::chrono::high_resolution_clock::now();
|
||||
g_pDebugOverlay->draw();
|
||||
endRenderOverlay = std::chrono::high_resolution_clock::now();
|
||||
}
|
||||
|
||||
if (*PDAMAGEBLINK && damageBlinkCleanup == 0) {
|
||||
wlr_box monrect = {0, 0, PMONITOR->vecTransformedSize.x, PMONITOR->vecTransformedSize.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);
|
||||
|
||||
wlr_output_render_software_cursors(PMONITOR->output, NULL);
|
||||
|
||||
wlr_renderer_end(g_pCompositor->m_sWLRRenderer);
|
||||
}
|
||||
|
||||
if (*PDAMAGEBLINK && damageBlinkCleanup == 0) {
|
||||
wlr_box monrect = {0, 0, PMONITOR->vecTransformedSize.x, PMONITOR->vecTransformedSize.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);
|
||||
|
||||
wlr_output_render_software_cursors(PMONITOR->output, NULL);
|
||||
|
||||
wlr_renderer_end(g_pCompositor->m_sWLRRenderer);
|
||||
|
||||
g_pHyprOpenGL->end();
|
||||
|
||||
// calc frame damage
|
||||
|
@ -272,6 +279,10 @@ void Events::listener_monitorFrame(void* owner, void* data) {
|
|||
pixman_region32_union(&frameDamage, &frameDamage, &damage);
|
||||
|
||||
wlr_output_set_damage(PMONITOR->output, &frameDamage);
|
||||
|
||||
if (!PMONITOR->mirrors.empty())
|
||||
g_pHyprRenderer->damageMirrorsWith(PMONITOR, &frameDamage);
|
||||
|
||||
pixman_region32_fini(&frameDamage);
|
||||
pixman_region32_fini(&damage);
|
||||
|
||||
|
|
|
@ -115,50 +115,14 @@ void CMonitor::onConnect(bool noRule) {
|
|||
}
|
||||
|
||||
wlr_ext_workspace_group_handle_v1_output_enter(pWLRWorkspaceGroupHandle, output);
|
||||
|
||||
setupDefaultWS(monitorRule);
|
||||
|
||||
// Workspace
|
||||
std::string newDefaultWorkspaceName = "";
|
||||
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) {
|
||||
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.c_str());
|
||||
}
|
||||
|
||||
auto PNEWWORKSPACE = g_pCompositor->getWorkspaceByID(WORKSPACEID);
|
||||
|
||||
Debug::log(LOG, "New monitor: WORKSPACEID %d, exists: %d", WORKSPACEID, (int)(PNEWWORKSPACE != nullptr));
|
||||
|
||||
if (PNEWWORKSPACE) {
|
||||
// workspace exists, move it to the newly connected monitor
|
||||
g_pCompositor->moveWorkspaceToMonitor(PNEWWORKSPACE, this);
|
||||
activeWorkspace = PNEWWORKSPACE->m_iID;
|
||||
g_pLayoutManager->getCurrentLayout()->recalculateMonitor(ID);
|
||||
PNEWWORKSPACE->startAnim(true, true, true);
|
||||
} else {
|
||||
|
||||
if (newDefaultWorkspaceName == "")
|
||||
newDefaultWorkspaceName = std::to_string(WORKSPACEID);
|
||||
|
||||
PNEWWORKSPACE = g_pCompositor->m_vWorkspaces.emplace_back(std::make_unique<CWorkspace>(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;
|
||||
}
|
||||
|
||||
activeWorkspace = PNEWWORKSPACE->m_iID;
|
||||
scale = monitorRule.scale;
|
||||
|
||||
m_pThisWrap = nullptr;
|
||||
|
||||
forceFullFrames = 3; // force 3 full frames to make sure there is no blinking due to double-buffering.
|
||||
|
||||
g_pCompositor->deactivateAllWLRWorkspaces(PNEWWORKSPACE->m_pWlrHandle);
|
||||
PNEWWORKSPACE->setActive(true);
|
||||
//
|
||||
|
||||
if (!g_pCompositor->m_pLastMonitor) // set the last monitor if it isnt set yet
|
||||
|
@ -186,6 +150,20 @@ void CMonitor::onDisconnect() {
|
|||
}
|
||||
}
|
||||
|
||||
// remove mirror
|
||||
if (pMirrorOf) {
|
||||
pMirrorOf->mirrors.erase(std::find_if(pMirrorOf->mirrors.begin(), pMirrorOf->mirrors.end(), [&](const auto& other) { return other == this; }));
|
||||
pMirrorOf = nullptr;
|
||||
}
|
||||
|
||||
if (!mirrors.empty()) {
|
||||
for (auto& m : mirrors) {
|
||||
m->setMirror("");
|
||||
}
|
||||
|
||||
g_pConfigManager->m_bWantsMonitorReload = true;
|
||||
}
|
||||
|
||||
m_bEnabled = false;
|
||||
m_bRenderingInitPassed = false;
|
||||
|
||||
|
@ -246,3 +224,136 @@ void CMonitor::addDamage(pixman_region32_t* rg) {
|
|||
void CMonitor::addDamage(wlr_box* box) {
|
||||
wlr_output_damage_add_box(damage, box);
|
||||
}
|
||||
|
||||
bool CMonitor::isMirror() {
|
||||
return pMirrorOf != nullptr;
|
||||
}
|
||||
|
||||
void CMonitor::setupDefaultWS(const SMonitorRule& monitorRule) {
|
||||
// Workspace
|
||||
std::string newDefaultWorkspaceName = "";
|
||||
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) {
|
||||
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.c_str());
|
||||
}
|
||||
|
||||
auto PNEWWORKSPACE = g_pCompositor->getWorkspaceByID(WORKSPACEID);
|
||||
|
||||
Debug::log(LOG, "New monitor: WORKSPACEID %d, exists: %d", WORKSPACEID, (int)(PNEWWORKSPACE != nullptr));
|
||||
|
||||
if (PNEWWORKSPACE) {
|
||||
// workspace exists, move it to the newly connected monitor
|
||||
g_pCompositor->moveWorkspaceToMonitor(PNEWWORKSPACE, this);
|
||||
activeWorkspace = PNEWWORKSPACE->m_iID;
|
||||
g_pLayoutManager->getCurrentLayout()->recalculateMonitor(ID);
|
||||
PNEWWORKSPACE->startAnim(true, true, true);
|
||||
} else {
|
||||
if (newDefaultWorkspaceName == "")
|
||||
newDefaultWorkspaceName = std::to_string(WORKSPACEID);
|
||||
|
||||
PNEWWORKSPACE = g_pCompositor->m_vWorkspaces.emplace_back(std::make_unique<CWorkspace>(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;
|
||||
}
|
||||
|
||||
activeWorkspace = PNEWWORKSPACE->m_iID;
|
||||
|
||||
g_pCompositor->deactivateAllWLRWorkspaces(PNEWWORKSPACE->m_pWlrHandle);
|
||||
PNEWWORKSPACE->setActive(true);
|
||||
}
|
||||
|
||||
void CMonitor::setMirror(const std::string& mirrorOf) {
|
||||
const auto PMIRRORMON = g_pCompositor->getMonitorFromString(mirrorOf);
|
||||
|
||||
if (PMIRRORMON == pMirrorOf)
|
||||
return;
|
||||
|
||||
if (PMIRRORMON && PMIRRORMON->isMirror()) {
|
||||
Debug::log(ERR, "Cannot mirror a mirror!");
|
||||
return;
|
||||
}
|
||||
|
||||
if (PMIRRORMON == this) {
|
||||
Debug::log(ERR, "Cannot mirror self!");
|
||||
return;
|
||||
}
|
||||
|
||||
if (!PMIRRORMON) {
|
||||
// disable mirroring
|
||||
|
||||
if (pMirrorOf) {
|
||||
pMirrorOf->mirrors.erase(std::find_if(pMirrorOf->mirrors.begin(), pMirrorOf->mirrors.end(), [&](const auto& other) { return other == this; }));
|
||||
}
|
||||
|
||||
pMirrorOf = nullptr;
|
||||
|
||||
// set rule
|
||||
const auto RULE = g_pConfigManager->getMonitorRuleFor(this->szName);
|
||||
|
||||
vecPosition = RULE.offset;
|
||||
|
||||
// push to mvmonitors
|
||||
if (!m_pThisWrap) {
|
||||
// find the wrap
|
||||
for (auto& m : g_pCompositor->m_vRealMonitors) {
|
||||
if (m->ID == ID) {
|
||||
m_pThisWrap = &m;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (std::find_if(g_pCompositor->m_vMonitors.begin(), g_pCompositor->m_vMonitors.end(), [&](auto& other) { return other.get() == this; }) == g_pCompositor->m_vMonitors.end()) {
|
||||
g_pCompositor->m_vMonitors.push_back(*m_pThisWrap);
|
||||
}
|
||||
|
||||
setupDefaultWS(RULE);
|
||||
|
||||
wlr_output_layout_add(g_pCompositor->m_sWLROutputLayout, output, (int)vecPosition.x, (int)vecPosition.y);
|
||||
} else {
|
||||
CMonitor* BACKUPMON = nullptr;
|
||||
for (auto& m : g_pCompositor->m_vMonitors) {
|
||||
if (m.get() != this) {
|
||||
BACKUPMON = m.get();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// move all the WS
|
||||
std::deque<CWorkspace*> wspToMove;
|
||||
for (auto& w : g_pCompositor->m_vWorkspaces) {
|
||||
if (w->m_iMonitorID == ID) {
|
||||
wspToMove.push_back(w.get());
|
||||
}
|
||||
}
|
||||
|
||||
for (auto& w : wspToMove) {
|
||||
g_pCompositor->moveWorkspaceToMonitor(w, BACKUPMON);
|
||||
w->startAnim(true, true, true);
|
||||
}
|
||||
|
||||
activeWorkspace = -1;
|
||||
|
||||
wlr_output_layout_remove(g_pCompositor->m_sWLROutputLayout, output);
|
||||
|
||||
vecPosition = Vector2D(-1337420, -1337420);
|
||||
|
||||
pMirrorOf = PMIRRORMON;
|
||||
|
||||
pMirrorOf->mirrors.push_back(this);
|
||||
|
||||
// remove from mvmonitors
|
||||
if (std::find_if(g_pCompositor->m_vMonitors.begin(), g_pCompositor->m_vMonitors.end(), [&](auto& other) { return other.get() == this; }) != g_pCompositor->m_vMonitors.end()) {
|
||||
g_pCompositor->m_vMonitors.erase(std::remove_if(g_pCompositor->m_vMonitors.begin(), g_pCompositor->m_vMonitors.end(), [&](const auto& other) { return other.get() == this; }));
|
||||
}
|
||||
|
||||
g_pCompositor->m_pLastMonitor = g_pCompositor->m_vMonitors.front().get();
|
||||
}
|
||||
}
|
|
@ -7,6 +7,8 @@
|
|||
#include <array>
|
||||
#include <memory>
|
||||
|
||||
struct SMonitorRule;
|
||||
|
||||
class CMonitor {
|
||||
public:
|
||||
Vector2D vecPosition = Vector2D(0,0);
|
||||
|
@ -35,6 +37,10 @@ public:
|
|||
bool scheduledRecalc = false;
|
||||
wl_output_transform transform = WL_OUTPUT_TRANSFORM_NORMAL;
|
||||
|
||||
// mirroring
|
||||
CMonitor* pMirrorOf = nullptr;
|
||||
std::vector<CMonitor*> mirrors;
|
||||
|
||||
// for the special workspace
|
||||
bool specialWorkspaceOpen = false;
|
||||
|
||||
|
@ -57,6 +63,8 @@ public:
|
|||
void onDisconnect();
|
||||
void addDamage(pixman_region32_t* rg);
|
||||
void addDamage(wlr_box* box);
|
||||
void setMirror(const std::string&);
|
||||
bool isMirror();
|
||||
|
||||
std::shared_ptr<CMonitor>* m_pThisWrap = nullptr;
|
||||
bool m_bEnabled = false;
|
||||
|
@ -67,4 +75,7 @@ public:
|
|||
bool operator==(const CMonitor& rhs) {
|
||||
return vecPosition == rhs.vecPosition && vecSize == rhs.vecSize && szName == rhs.szName;
|
||||
}
|
||||
|
||||
private:
|
||||
void setupDefaultWS(const SMonitorRule&);
|
||||
};
|
|
@ -102,6 +102,7 @@ void CHyprOpenGLImpl::begin(CMonitor* pMonitor, pixman_region32_t* pDamage, bool
|
|||
m_RenderData.pCurrentMonData->primaryFB.alloc(pMonitor->vecPixelSize.x, pMonitor->vecPixelSize.y);
|
||||
m_RenderData.pCurrentMonData->mirrorFB.alloc(pMonitor->vecPixelSize.x, pMonitor->vecPixelSize.y);
|
||||
m_RenderData.pCurrentMonData->mirrorSwapFB.alloc(pMonitor->vecPixelSize.x, pMonitor->vecPixelSize.y);
|
||||
m_RenderData.pCurrentMonData->monitorMirrorFB.alloc(pMonitor->vecPixelSize.x, pMonitor->vecPixelSize.y);
|
||||
|
||||
createBGTextureForMonitor(pMonitor);
|
||||
}
|
||||
|
@ -120,11 +121,14 @@ void CHyprOpenGLImpl::begin(CMonitor* pMonitor, pixman_region32_t* pDamage, bool
|
|||
void CHyprOpenGLImpl::end() {
|
||||
// end the render, copy the data to the WLR framebuffer
|
||||
if (!m_bFakeFrame) {
|
||||
pixman_region32_copy(m_RenderData.pDamage, &m_rOriginalDamageRegion);
|
||||
|
||||
if (!m_RenderData.pMonitor->mirrors.empty())
|
||||
g_pHyprOpenGL->saveBufferForMirror(); // save with original damage region
|
||||
|
||||
glBindFramebuffer(GL_FRAMEBUFFER, m_iWLROutputFb);
|
||||
wlr_box monbox = {0, 0, m_RenderData.pMonitor->vecTransformedSize.x, m_RenderData.pMonitor->vecTransformedSize.y};
|
||||
|
||||
pixman_region32_copy(m_RenderData.pDamage, &m_rOriginalDamageRegion);
|
||||
|
||||
clear(CColor(11, 11, 11, 255));
|
||||
|
||||
m_bEndFrame = true;
|
||||
|
@ -1088,6 +1092,27 @@ void CHyprOpenGLImpl::renderRoundedShadow(wlr_box* box, int round, int range, fl
|
|||
glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
|
||||
}
|
||||
|
||||
void CHyprOpenGLImpl::saveBufferForMirror() {
|
||||
m_RenderData.pCurrentMonData->monitorMirrorFB.bind();
|
||||
|
||||
wlr_box monbox = {0, 0, m_RenderData.pMonitor->vecPixelSize.x, m_RenderData.pMonitor->vecPixelSize.y};
|
||||
|
||||
renderTexture(m_RenderData.pCurrentMonData->primaryFB.m_cTex, &monbox, 255.f, 0, false, false);
|
||||
|
||||
m_RenderData.pCurrentMonData->primaryFB.bind();
|
||||
}
|
||||
|
||||
void CHyprOpenGLImpl::renderMirrored() {
|
||||
wlr_box monbox = {0, 0, m_RenderData.pMonitor->vecPixelSize.x, m_RenderData.pMonitor->vecPixelSize.y};
|
||||
|
||||
const auto PFB = &m_mMonitorRenderResources[m_RenderData.pMonitor->pMirrorOf].monitorMirrorFB;
|
||||
|
||||
if (PFB->m_cTex.m_iTexID <= 0)
|
||||
return;
|
||||
|
||||
renderTexture(PFB->m_cTex, &monbox, 255.f, 0, false, false);
|
||||
}
|
||||
|
||||
void CHyprOpenGLImpl::renderSplash(cairo_t *const CAIRO, cairo_surface_t *const CAIROSURFACE) {
|
||||
cairo_select_font_face(CAIRO, "Sans", CAIRO_FONT_SLANT_NORMAL, CAIRO_FONT_WEIGHT_NORMAL);
|
||||
|
||||
|
|
|
@ -33,8 +33,10 @@ inline const float fanVertsFull[] = {
|
|||
|
||||
struct SMonitorRenderData {
|
||||
CFramebuffer primaryFB;
|
||||
CFramebuffer mirrorFB;
|
||||
CFramebuffer mirrorSwapFB;
|
||||
CFramebuffer mirrorFB; // these are used for some effects,
|
||||
CFramebuffer mirrorSwapFB; // etc
|
||||
|
||||
CFramebuffer monitorMirrorFB; // used for mirroring outputs
|
||||
|
||||
CTexture stencilTex;
|
||||
|
||||
|
@ -102,6 +104,9 @@ public:
|
|||
void preWindowPass();
|
||||
void preRender(CMonitor*);
|
||||
|
||||
void saveBufferForMirror();
|
||||
void renderMirrored();
|
||||
|
||||
SCurrentRenderData m_RenderData;
|
||||
|
||||
GLint m_iCurrentOutputFb = 0;
|
||||
|
|
|
@ -778,7 +778,7 @@ void CHyprRenderer::damageWindow(CWindow* pWindow) {
|
|||
}
|
||||
|
||||
void CHyprRenderer::damageMonitor(CMonitor* pMonitor) {
|
||||
if (g_pCompositor->m_bUnsafeState)
|
||||
if (g_pCompositor->m_bUnsafeState || pMonitor->isMirror())
|
||||
return;
|
||||
|
||||
wlr_box damageBox = {0, 0, pMonitor->vecPixelSize.x, pMonitor->vecPixelSize.y};
|
||||
|
@ -795,6 +795,9 @@ void CHyprRenderer::damageBox(wlr_box* pBox) {
|
|||
return;
|
||||
|
||||
for (auto& m : g_pCompositor->m_vMonitors) {
|
||||
if (m->isMirror())
|
||||
continue; // don't damage mirrors traditionally
|
||||
|
||||
wlr_box damageBox = {pBox->x - m->vecPosition.x, pBox->y - m->vecPosition.y, pBox->width, pBox->height};
|
||||
scaleBox(&damageBox, m->scale);
|
||||
m->addDamage(&damageBox);
|
||||
|
@ -818,6 +821,19 @@ void CHyprRenderer::damageRegion(pixman_region32_t* rg) {
|
|||
}
|
||||
}
|
||||
|
||||
void CHyprRenderer::damageMirrorsWith(CMonitor* pMonitor, pixman_region32_t* pRegion) {
|
||||
for (auto& mirror : pMonitor->mirrors) {
|
||||
Vector2D scale = {mirror->vecSize.x / pMonitor->vecSize.x, mirror->vecSize.y / pMonitor->vecSize.y};
|
||||
|
||||
pixman_region32_t rg;
|
||||
pixman_region32_init(&rg);
|
||||
pixman_region32_copy(&rg, pRegion);
|
||||
wlr_region_scale_xy(&rg, &rg, scale.x, scale.y);
|
||||
pMonitor->addDamage(&rg);
|
||||
pixman_region32_fini(&rg);
|
||||
}
|
||||
}
|
||||
|
||||
void CHyprRenderer::renderDragIcon(CMonitor* pMonitor, timespec* time) {
|
||||
if (!(g_pInputManager->m_sDrag.dragIcon && g_pInputManager->m_sDrag.iconMapped && g_pInputManager->m_sDrag.dragIcon->surface))
|
||||
return;
|
||||
|
@ -1029,7 +1045,8 @@ bool CHyprRenderer::applyMonitorRule(CMonitor* pMonitor, SMonitorRule* pMonitorR
|
|||
pMonitor->vecPosition = finalPos;
|
||||
}
|
||||
|
||||
wlr_output_layout_add(g_pCompositor->m_sWLROutputLayout, pMonitor->output, (int)pMonitor->vecPosition.x, (int)pMonitor->vecPosition.y);
|
||||
if (!pMonitor->isMirror())
|
||||
wlr_output_layout_add(g_pCompositor->m_sWLROutputLayout, pMonitor->output, (int)pMonitor->vecPosition.x, (int)pMonitor->vecPosition.y);
|
||||
|
||||
wlr_output_enable(pMonitor->output, true);
|
||||
|
||||
|
@ -1042,6 +1059,9 @@ bool CHyprRenderer::applyMonitorRule(CMonitor* pMonitor, SMonitorRule* pMonitorR
|
|||
// frame skip
|
||||
pMonitor->framesToSkip = 1;
|
||||
|
||||
// reload to fix mirrors
|
||||
g_pConfigManager->m_bWantsMonitorReload = true;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
|
|
@ -35,6 +35,7 @@ public:
|
|||
void damageBox(const int& x, const int& y, const int& w, const int& h);
|
||||
void damageRegion(pixman_region32_t*);
|
||||
void damageMonitor(CMonitor*);
|
||||
void damageMirrorsWith(CMonitor*, pixman_region32_t*);
|
||||
bool applyMonitorRule(CMonitor*, SMonitorRule*, bool force = false);
|
||||
bool shouldRenderWindow(CWindow*, CMonitor*);
|
||||
bool shouldRenderWindow(CWindow*);
|
||||
|
|
Loading…
Reference in a new issue