mirror of
https://github.com/hyprwm/Hyprland
synced 2024-12-23 09: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,12 +493,17 @@ void CConfigManager::handleMonitor(const std::string& command, const std::string
|
||||||
|
|
||||||
nextItem();
|
nextItem();
|
||||||
|
|
||||||
if (curitem != "") {
|
while (curitem != "") {
|
||||||
// warning for old cfg
|
if (curitem == "mirror") {
|
||||||
Debug::log(ERR, "Error in parsing rule for %s, possibly old config!", newrule.name.c_str());
|
nextItem();
|
||||||
parseError = "Error in setting monitor rule. Are you using the old syntax? Confront the wiki.";
|
newrule.mirrorOf = curitem;
|
||||||
|
nextItem();
|
||||||
|
} else {
|
||||||
|
Debug::log(ERR, "Config error: invalid monitor syntax");
|
||||||
|
parseError = "invalid syntax at \"" + curitem + "\"";
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (std::find_if(m_dMonitorRules.begin(), m_dMonitorRules.end(), [&](const auto& other) { return other.name == newrule.name; }) != m_dMonitorRules.end())
|
if (std::find_if(m_dMonitorRules.begin(), m_dMonitorRules.end(), [&](const auto& other) { return other.name == newrule.name; }) != m_dMonitorRules.end())
|
||||||
m_dMonitorRules.erase(std::remove_if(m_dMonitorRules.begin(), m_dMonitorRules.end(), [&](const auto& other) { return other.name == newrule.name; }));
|
m_dMonitorRules.erase(std::remove_if(m_dMonitorRules.begin(), m_dMonitorRules.end(), [&](const auto& other) { return other.name == newrule.name; }));
|
||||||
|
@ -1444,6 +1449,10 @@ void CConfigManager::performMonitorReload() {
|
||||||
|
|
||||||
for (auto& m : g_pCompositor->m_vRealMonitors) {
|
for (auto& m : g_pCompositor->m_vRealMonitors) {
|
||||||
auto rule = getMonitorRuleFor(m->szName);
|
auto rule = getMonitorRuleFor(m->szName);
|
||||||
|
|
||||||
|
// ensure mirror
|
||||||
|
m->setMirror(rule.mirrorOf);
|
||||||
|
|
||||||
if (!g_pHyprRenderer->applyMonitorRule(m.get(), &rule)) {
|
if (!g_pHyprRenderer->applyMonitorRule(m.get(), &rule)) {
|
||||||
overAgain = true;
|
overAgain = true;
|
||||||
break;
|
break;
|
||||||
|
|
|
@ -36,6 +36,7 @@ struct SMonitorRule {
|
||||||
std::string defaultWorkspace = "";
|
std::string defaultWorkspace = "";
|
||||||
bool disabled = false;
|
bool disabled = false;
|
||||||
wl_output_transform transform = WL_OUTPUT_TRANSFORM_NORMAL;
|
wl_output_transform transform = WL_OUTPUT_TRANSFORM_NORMAL;
|
||||||
|
std::string mirrorOf = "";
|
||||||
};
|
};
|
||||||
|
|
||||||
struct SMonitorAdditionalReservedArea {
|
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 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_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);
|
pixman_region32_copy(&g_pHyprOpenGL->m_rOriginalDamageRegion, &damage);
|
||||||
|
@ -224,6 +224,12 @@ void Events::listener_monitorFrame(void* owner, void* data) {
|
||||||
// potentially can save on resources.
|
// potentially can save on resources.
|
||||||
|
|
||||||
g_pHyprOpenGL->begin(PMONITOR, &damage);
|
g_pHyprOpenGL->begin(PMONITOR, &damage);
|
||||||
|
|
||||||
|
if (PMONITOR->isMirror()) {
|
||||||
|
g_pHyprOpenGL->renderMirrored();
|
||||||
|
|
||||||
|
Debug::log(LOG, "Mirror frame");
|
||||||
|
} else {
|
||||||
g_pHyprOpenGL->clear(CColor(17, 17, 17, 255));
|
g_pHyprOpenGL->clear(CColor(17, 17, 17, 255));
|
||||||
g_pHyprOpenGL->clearWithTex(); // will apply the hypr "wallpaper"
|
g_pHyprOpenGL->clearWithTex(); // will apply the hypr "wallpaper"
|
||||||
|
|
||||||
|
@ -255,6 +261,7 @@ void Events::listener_monitorFrame(void* owner, void* data) {
|
||||||
wlr_output_render_software_cursors(PMONITOR->output, NULL);
|
wlr_output_render_software_cursors(PMONITOR->output, NULL);
|
||||||
|
|
||||||
wlr_renderer_end(g_pCompositor->m_sWLRRenderer);
|
wlr_renderer_end(g_pCompositor->m_sWLRRenderer);
|
||||||
|
}
|
||||||
|
|
||||||
g_pHyprOpenGL->end();
|
g_pHyprOpenGL->end();
|
||||||
|
|
||||||
|
@ -272,6 +279,10 @@ void Events::listener_monitorFrame(void* owner, void* data) {
|
||||||
pixman_region32_union(&frameDamage, &frameDamage, &damage);
|
pixman_region32_union(&frameDamage, &frameDamage, &damage);
|
||||||
|
|
||||||
wlr_output_set_damage(PMONITOR->output, &frameDamage);
|
wlr_output_set_damage(PMONITOR->output, &frameDamage);
|
||||||
|
|
||||||
|
if (!PMONITOR->mirrors.empty())
|
||||||
|
g_pHyprRenderer->damageMirrorsWith(PMONITOR, &frameDamage);
|
||||||
|
|
||||||
pixman_region32_fini(&frameDamage);
|
pixman_region32_fini(&frameDamage);
|
||||||
pixman_region32_fini(&damage);
|
pixman_region32_fini(&damage);
|
||||||
|
|
||||||
|
|
|
@ -116,49 +116,13 @@ void CMonitor::onConnect(bool noRule) {
|
||||||
|
|
||||||
wlr_ext_workspace_group_handle_v1_output_enter(pWLRWorkspaceGroupHandle, output);
|
wlr_ext_workspace_group_handle_v1_output_enter(pWLRWorkspaceGroupHandle, output);
|
||||||
|
|
||||||
// Workspace
|
setupDefaultWS(monitorRule);
|
||||||
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;
|
scale = monitorRule.scale;
|
||||||
|
|
||||||
m_pThisWrap = nullptr;
|
m_pThisWrap = nullptr;
|
||||||
|
|
||||||
forceFullFrames = 3; // force 3 full frames to make sure there is no blinking due to double-buffering.
|
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
|
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_bEnabled = false;
|
||||||
m_bRenderingInitPassed = false;
|
m_bRenderingInitPassed = false;
|
||||||
|
|
||||||
|
@ -246,3 +224,136 @@ void CMonitor::addDamage(pixman_region32_t* rg) {
|
||||||
void CMonitor::addDamage(wlr_box* box) {
|
void CMonitor::addDamage(wlr_box* box) {
|
||||||
wlr_output_damage_add_box(damage, 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 <array>
|
||||||
#include <memory>
|
#include <memory>
|
||||||
|
|
||||||
|
struct SMonitorRule;
|
||||||
|
|
||||||
class CMonitor {
|
class CMonitor {
|
||||||
public:
|
public:
|
||||||
Vector2D vecPosition = Vector2D(0,0);
|
Vector2D vecPosition = Vector2D(0,0);
|
||||||
|
@ -35,6 +37,10 @@ public:
|
||||||
bool scheduledRecalc = false;
|
bool scheduledRecalc = false;
|
||||||
wl_output_transform transform = WL_OUTPUT_TRANSFORM_NORMAL;
|
wl_output_transform transform = WL_OUTPUT_TRANSFORM_NORMAL;
|
||||||
|
|
||||||
|
// mirroring
|
||||||
|
CMonitor* pMirrorOf = nullptr;
|
||||||
|
std::vector<CMonitor*> mirrors;
|
||||||
|
|
||||||
// for the special workspace
|
// for the special workspace
|
||||||
bool specialWorkspaceOpen = false;
|
bool specialWorkspaceOpen = false;
|
||||||
|
|
||||||
|
@ -57,6 +63,8 @@ public:
|
||||||
void onDisconnect();
|
void onDisconnect();
|
||||||
void addDamage(pixman_region32_t* rg);
|
void addDamage(pixman_region32_t* rg);
|
||||||
void addDamage(wlr_box* box);
|
void addDamage(wlr_box* box);
|
||||||
|
void setMirror(const std::string&);
|
||||||
|
bool isMirror();
|
||||||
|
|
||||||
std::shared_ptr<CMonitor>* m_pThisWrap = nullptr;
|
std::shared_ptr<CMonitor>* m_pThisWrap = nullptr;
|
||||||
bool m_bEnabled = false;
|
bool m_bEnabled = false;
|
||||||
|
@ -67,4 +75,7 @@ public:
|
||||||
bool operator==(const CMonitor& rhs) {
|
bool operator==(const CMonitor& rhs) {
|
||||||
return vecPosition == rhs.vecPosition && vecSize == rhs.vecSize && szName == rhs.szName;
|
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->primaryFB.alloc(pMonitor->vecPixelSize.x, pMonitor->vecPixelSize.y);
|
||||||
m_RenderData.pCurrentMonData->mirrorFB.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->mirrorSwapFB.alloc(pMonitor->vecPixelSize.x, pMonitor->vecPixelSize.y);
|
||||||
|
m_RenderData.pCurrentMonData->monitorMirrorFB.alloc(pMonitor->vecPixelSize.x, pMonitor->vecPixelSize.y);
|
||||||
|
|
||||||
createBGTextureForMonitor(pMonitor);
|
createBGTextureForMonitor(pMonitor);
|
||||||
}
|
}
|
||||||
|
@ -120,11 +121,14 @@ void CHyprOpenGLImpl::begin(CMonitor* pMonitor, pixman_region32_t* pDamage, bool
|
||||||
void CHyprOpenGLImpl::end() {
|
void CHyprOpenGLImpl::end() {
|
||||||
// end the render, copy the data to the WLR framebuffer
|
// end the render, copy the data to the WLR framebuffer
|
||||||
if (!m_bFakeFrame) {
|
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);
|
glBindFramebuffer(GL_FRAMEBUFFER, m_iWLROutputFb);
|
||||||
wlr_box monbox = {0, 0, m_RenderData.pMonitor->vecTransformedSize.x, m_RenderData.pMonitor->vecTransformedSize.y};
|
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));
|
clear(CColor(11, 11, 11, 255));
|
||||||
|
|
||||||
m_bEndFrame = true;
|
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);
|
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) {
|
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);
|
cairo_select_font_face(CAIRO, "Sans", CAIRO_FONT_SLANT_NORMAL, CAIRO_FONT_WEIGHT_NORMAL);
|
||||||
|
|
||||||
|
|
|
@ -33,8 +33,10 @@ inline const float fanVertsFull[] = {
|
||||||
|
|
||||||
struct SMonitorRenderData {
|
struct SMonitorRenderData {
|
||||||
CFramebuffer primaryFB;
|
CFramebuffer primaryFB;
|
||||||
CFramebuffer mirrorFB;
|
CFramebuffer mirrorFB; // these are used for some effects,
|
||||||
CFramebuffer mirrorSwapFB;
|
CFramebuffer mirrorSwapFB; // etc
|
||||||
|
|
||||||
|
CFramebuffer monitorMirrorFB; // used for mirroring outputs
|
||||||
|
|
||||||
CTexture stencilTex;
|
CTexture stencilTex;
|
||||||
|
|
||||||
|
@ -102,6 +104,9 @@ public:
|
||||||
void preWindowPass();
|
void preWindowPass();
|
||||||
void preRender(CMonitor*);
|
void preRender(CMonitor*);
|
||||||
|
|
||||||
|
void saveBufferForMirror();
|
||||||
|
void renderMirrored();
|
||||||
|
|
||||||
SCurrentRenderData m_RenderData;
|
SCurrentRenderData m_RenderData;
|
||||||
|
|
||||||
GLint m_iCurrentOutputFb = 0;
|
GLint m_iCurrentOutputFb = 0;
|
||||||
|
|
|
@ -778,7 +778,7 @@ void CHyprRenderer::damageWindow(CWindow* pWindow) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void CHyprRenderer::damageMonitor(CMonitor* pMonitor) {
|
void CHyprRenderer::damageMonitor(CMonitor* pMonitor) {
|
||||||
if (g_pCompositor->m_bUnsafeState)
|
if (g_pCompositor->m_bUnsafeState || pMonitor->isMirror())
|
||||||
return;
|
return;
|
||||||
|
|
||||||
wlr_box damageBox = {0, 0, pMonitor->vecPixelSize.x, pMonitor->vecPixelSize.y};
|
wlr_box damageBox = {0, 0, pMonitor->vecPixelSize.x, pMonitor->vecPixelSize.y};
|
||||||
|
@ -795,6 +795,9 @@ void CHyprRenderer::damageBox(wlr_box* pBox) {
|
||||||
return;
|
return;
|
||||||
|
|
||||||
for (auto& m : g_pCompositor->m_vMonitors) {
|
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};
|
wlr_box damageBox = {pBox->x - m->vecPosition.x, pBox->y - m->vecPosition.y, pBox->width, pBox->height};
|
||||||
scaleBox(&damageBox, m->scale);
|
scaleBox(&damageBox, m->scale);
|
||||||
m->addDamage(&damageBox);
|
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) {
|
void CHyprRenderer::renderDragIcon(CMonitor* pMonitor, timespec* time) {
|
||||||
if (!(g_pInputManager->m_sDrag.dragIcon && g_pInputManager->m_sDrag.iconMapped && g_pInputManager->m_sDrag.dragIcon->surface))
|
if (!(g_pInputManager->m_sDrag.dragIcon && g_pInputManager->m_sDrag.iconMapped && g_pInputManager->m_sDrag.dragIcon->surface))
|
||||||
return;
|
return;
|
||||||
|
@ -1029,6 +1045,7 @@ bool CHyprRenderer::applyMonitorRule(CMonitor* pMonitor, SMonitorRule* pMonitorR
|
||||||
pMonitor->vecPosition = finalPos;
|
pMonitor->vecPosition = finalPos;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!pMonitor->isMirror())
|
||||||
wlr_output_layout_add(g_pCompositor->m_sWLROutputLayout, pMonitor->output, (int)pMonitor->vecPosition.x, (int)pMonitor->vecPosition.y);
|
wlr_output_layout_add(g_pCompositor->m_sWLROutputLayout, pMonitor->output, (int)pMonitor->vecPosition.x, (int)pMonitor->vecPosition.y);
|
||||||
|
|
||||||
wlr_output_enable(pMonitor->output, true);
|
wlr_output_enable(pMonitor->output, true);
|
||||||
|
@ -1042,6 +1059,9 @@ bool CHyprRenderer::applyMonitorRule(CMonitor* pMonitor, SMonitorRule* pMonitorR
|
||||||
// frame skip
|
// frame skip
|
||||||
pMonitor->framesToSkip = 1;
|
pMonitor->framesToSkip = 1;
|
||||||
|
|
||||||
|
// reload to fix mirrors
|
||||||
|
g_pConfigManager->m_bWantsMonitorReload = true;
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -35,6 +35,7 @@ public:
|
||||||
void damageBox(const int& x, const int& y, const int& w, const int& h);
|
void damageBox(const int& x, const int& y, const int& w, const int& h);
|
||||||
void damageRegion(pixman_region32_t*);
|
void damageRegion(pixman_region32_t*);
|
||||||
void damageMonitor(CMonitor*);
|
void damageMonitor(CMonitor*);
|
||||||
|
void damageMirrorsWith(CMonitor*, pixman_region32_t*);
|
||||||
bool applyMonitorRule(CMonitor*, SMonitorRule*, bool force = false);
|
bool applyMonitorRule(CMonitor*, SMonitorRule*, bool force = false);
|
||||||
bool shouldRenderWindow(CWindow*, CMonitor*);
|
bool shouldRenderWindow(CWindow*, CMonitor*);
|
||||||
bool shouldRenderWindow(CWindow*);
|
bool shouldRenderWindow(CWindow*);
|
||||||
|
|
Loading…
Reference in a new issue