mirror of
https://github.com/hyprwm/Hyprland
synced 2025-12-20 05:10:20 +01:00
Merge 6a11bc3545 into 315806f598
This commit is contained in:
commit
42fed34743
8 changed files with 103 additions and 9 deletions
|
|
@ -15,6 +15,18 @@ inline static const std::vector<SConfigOptionDescription> CONFIG_OPTIONS = {
|
|||
.type = CONFIG_OPTION_INT,
|
||||
.data = SConfigOptionDescription::SRangeData{1, 0, 20},
|
||||
},
|
||||
SConfigOptionDescription{
|
||||
.value = "general:screencast_border.enabled",
|
||||
.description = "enable red border indicator when screen sharing",
|
||||
.type = CONFIG_OPTION_BOOL,
|
||||
.data = SConfigOptionDescription::SBoolData{true},
|
||||
},
|
||||
SConfigOptionDescription{
|
||||
.value = "general:screencast_border.color",
|
||||
.description = "border color when screen sharing",
|
||||
.type = CONFIG_OPTION_GRADIENT,
|
||||
.data = SConfigOptionDescription::SGradientData{"0xffff0000"},
|
||||
},
|
||||
SConfigOptionDescription{
|
||||
.value = "general:gaps_in",
|
||||
.description = "gaps between windows\n\nsupports css style gaps (top, right, bottom, left -> 5 10 15 20)",
|
||||
|
|
|
|||
|
|
@ -443,6 +443,8 @@ CConfigManager::CConfigManager() {
|
|||
m_config = makeUnique<Hyprlang::CConfig>(m_configPaths.begin()->c_str(), Hyprlang::SConfigOptions{.throwAllErrors = true, .allowMissingConfig = true});
|
||||
|
||||
registerConfigVar("general:border_size", Hyprlang::INT{1});
|
||||
registerConfigVar("general:screencast_border.enabled", Hyprlang::INT{1});
|
||||
registerConfigVar("general:screencast_border.color", Hyprlang::CConfigCustomValueType{&configHandleGradientSet, configHandleGradientDestroy, "0xffff0000"});
|
||||
registerConfigVar("general:gaps_in", Hyprlang::CConfigCustomValueType{configHandleGapSet, configHandleGapDestroy, "5"});
|
||||
registerConfigVar("general:gaps_out", Hyprlang::CConfigCustomValueType{configHandleGapSet, configHandleGapDestroy, "20"});
|
||||
registerConfigVar("general:float_gaps", Hyprlang::CConfigCustomValueType{configHandleGapSet, configHandleGapDestroy, "0"});
|
||||
|
|
|
|||
|
|
@ -514,6 +514,11 @@ void CScreencopyProtocol::destroyResource(CScreencopyClient* client) {
|
|||
}
|
||||
|
||||
void CScreencopyProtocol::destroyResource(CScreencopyFrame* frame) {
|
||||
// Damage the monitor before destroying the frame so the border updates
|
||||
if (frame && frame->m_monitor) {
|
||||
if (auto monitor = frame->m_monitor.lock())
|
||||
g_pHyprRenderer->damageMonitor(monitor);
|
||||
}
|
||||
std::erase_if(m_frames, [&](const auto& other) { return other.get() == frame; });
|
||||
std::erase_if(m_framesAwaitingWrite, [&](const auto& other) { return !other || other.get() == frame; });
|
||||
}
|
||||
|
|
|
|||
|
|
@ -36,12 +36,13 @@ class CScreencopyClient {
|
|||
CTimer m_lastFrame;
|
||||
int m_frameCounter = 0;
|
||||
|
||||
bool m_sentScreencast = false;
|
||||
|
||||
private:
|
||||
SP<CZwlrScreencopyManagerV1> m_resource;
|
||||
|
||||
int m_framesInLastHalfSecond = 0;
|
||||
CTimer m_lastMeasure;
|
||||
bool m_sentScreencast = false;
|
||||
|
||||
SP<HOOK_CALLBACK_FN> m_tickCallback;
|
||||
void onTick();
|
||||
|
|
@ -59,11 +60,10 @@ class CScreencopyFrame {
|
|||
|
||||
WP<CScreencopyFrame> m_self;
|
||||
WP<CScreencopyClient> m_client;
|
||||
PHLMONITORREF m_monitor;
|
||||
|
||||
private:
|
||||
SP<CZwlrScreencopyFrameV1> m_resource;
|
||||
|
||||
PHLMONITORREF m_monitor;
|
||||
bool m_overlayCursor = false;
|
||||
bool m_withDamage = false;
|
||||
|
||||
|
|
@ -97,8 +97,9 @@ class CScreencopyProtocol : public IWaylandProtocol {
|
|||
|
||||
void onOutputCommit(PHLMONITOR pMonitor);
|
||||
|
||||
private:
|
||||
std::vector<SP<CScreencopyFrame>> m_frames;
|
||||
|
||||
private:
|
||||
std::vector<WP<CScreencopyFrame>> m_framesAwaitingWrite;
|
||||
std::vector<SP<CScreencopyClient>> m_clients;
|
||||
|
||||
|
|
|
|||
|
|
@ -74,7 +74,7 @@ bool CToplevelExportClient::good() {
|
|||
return m_resource->resource();
|
||||
}
|
||||
|
||||
CToplevelExportFrame::CToplevelExportFrame(SP<CHyprlandToplevelExportFrameV1> resource_, int32_t overlayCursor_, PHLWINDOW pWindow_) : m_resource(resource_), m_window(pWindow_) {
|
||||
CToplevelExportFrame::CToplevelExportFrame(SP<CHyprlandToplevelExportFrameV1> resource_, int32_t overlayCursor_, PHLWINDOW pWindow_) : m_window(pWindow_), m_resource(resource_) {
|
||||
if UNLIKELY (!good())
|
||||
return;
|
||||
|
||||
|
|
@ -411,6 +411,10 @@ void CToplevelExportProtocol::destroyResource(CToplevelExportClient* client) {
|
|||
}
|
||||
|
||||
void CToplevelExportProtocol::destroyResource(CToplevelExportFrame* frame) {
|
||||
// Damage the window before destroying the frame so the border updates
|
||||
if (frame && frame->m_window) {
|
||||
g_pHyprRenderer->damageWindow(frame->m_window);
|
||||
}
|
||||
std::erase_if(m_frames, [&](const auto& other) { return other.get() == frame; });
|
||||
std::erase_if(m_framesAwaitingWrite, [&](const auto& other) { return !other || other.get() == frame; });
|
||||
}
|
||||
|
|
|
|||
|
|
@ -22,12 +22,13 @@ class CToplevelExportClient {
|
|||
CTimer m_lastFrame;
|
||||
int m_frameCounter = 0;
|
||||
|
||||
bool m_sentScreencast = false;
|
||||
|
||||
private:
|
||||
SP<CHyprlandToplevelExportManagerV1> m_resource;
|
||||
|
||||
int m_framesInLastHalfSecond = 0;
|
||||
CTimer m_lastMeasure;
|
||||
bool m_sentScreencast = false;
|
||||
|
||||
SP<HOOK_CALLBACK_FN> m_tickCallback;
|
||||
void onTick();
|
||||
|
|
@ -45,11 +46,10 @@ class CToplevelExportFrame {
|
|||
|
||||
WP<CToplevelExportFrame> m_self;
|
||||
WP<CToplevelExportClient> m_client;
|
||||
PHLWINDOW m_window;
|
||||
|
||||
private:
|
||||
SP<CHyprlandToplevelExportFrameV1> m_resource;
|
||||
|
||||
PHLWINDOW m_window;
|
||||
bool m_cursorOverlayRequested = false;
|
||||
bool m_ignoreDamage = false;
|
||||
|
||||
|
|
@ -79,9 +79,10 @@ class CToplevelExportProtocol : IWaylandProtocol {
|
|||
|
||||
void onOutputCommit(PHLMONITOR pMonitor);
|
||||
|
||||
std::vector<SP<CToplevelExportFrame>> m_frames;
|
||||
|
||||
private:
|
||||
std::vector<SP<CToplevelExportClient>> m_clients;
|
||||
std::vector<SP<CToplevelExportFrame>> m_frames;
|
||||
std::vector<WP<CToplevelExportFrame>> m_framesAwaitingWrite;
|
||||
|
||||
void onWindowUnmap(PHLWINDOW pWindow);
|
||||
|
|
|
|||
|
|
@ -41,6 +41,10 @@
|
|||
#include "../protocols/types/ContentType.hpp"
|
||||
#include "../helpers/MiscFunctions.hpp"
|
||||
#include "render/OpenGL.hpp"
|
||||
#include "../protocols/Screencopy.hpp"
|
||||
#include "../config/ConfigDataValues.hpp"
|
||||
#include "../helpers/Color.hpp"
|
||||
#include "pass/BorderPassElement.hpp"
|
||||
|
||||
#include <hyprutils/utils/ScopeGuard.hpp>
|
||||
using namespace Hyprutils::Utils;
|
||||
|
|
@ -1459,6 +1463,46 @@ void CHyprRenderer::renderMonitor(PHLMONITOR pMonitor, bool commit) {
|
|||
m_renderPass.add(makeUnique<CRectPassElement>(data));
|
||||
}
|
||||
|
||||
// Render border around monitor if it's being shared
|
||||
static auto PENABLED = CConfigValue<Hyprlang::INT>("general:screencast_border.enabled");
|
||||
if (*PENABLED) {
|
||||
// Check if monitor is being shared through screencopy
|
||||
bool isMonitorShared = false;
|
||||
if (PROTO::screencopy) {
|
||||
for (const auto& frame : PROTO::screencopy->m_frames) {
|
||||
if (frame && frame->m_monitor && frame->m_monitor.lock() == pMonitor) {
|
||||
isMonitorShared = frame->m_client->m_sentScreencast;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (isMonitorShared) {
|
||||
static auto PBORDERSIZE = CConfigValue<Hyprlang::INT>("general:border_size");
|
||||
static auto PCOLOR = CConfigValue<Hyprlang::CUSTOMTYPE>("general:screencast_border.color");
|
||||
const int borderSize = *PBORDERSIZE > 0 ? *PBORDERSIZE : 1;
|
||||
|
||||
const int scaledBorderSize = std::round(borderSize * pMonitor->m_scale);
|
||||
CBox monitorBox = {scaledBorderSize, scaledBorderSize, std::max(1, sc<int>(pMonitor->m_transformedSize.x) - (2 * scaledBorderSize)),
|
||||
std::max(1, sc<int>(pMonitor->m_transformedSize.y) - (2 * scaledBorderSize))};
|
||||
|
||||
const auto* const PGRAD = sc<CGradientValueData*>((PCOLOR.ptr())->getData());
|
||||
CGradientValueData borderGrad = PGRAD ? *PGRAD : CGradientValueData(Colors::RED); // fallback to red if config not loaded
|
||||
|
||||
CBorderPassElement::SBorderData borderData;
|
||||
borderData.box = monitorBox;
|
||||
borderData.grad1 = borderGrad;
|
||||
borderData.round = 0;
|
||||
borderData.outerRound = -1;
|
||||
borderData.roundingPower = 2.0f;
|
||||
borderData.a = 1.0f;
|
||||
borderData.borderSize = borderSize;
|
||||
borderData.hasGrad2 = false;
|
||||
|
||||
m_renderPass.add(makeUnique<CBorderPassElement>(borderData));
|
||||
}
|
||||
}
|
||||
|
||||
EMIT_HOOK_EVENT("render", RENDER_LAST_MOMENT);
|
||||
|
||||
endRender();
|
||||
|
|
|
|||
|
|
@ -5,6 +5,10 @@
|
|||
#include "../pass/BorderPassElement.hpp"
|
||||
#include "../Renderer.hpp"
|
||||
#include "../../managers/HookSystemManager.hpp"
|
||||
#include "../../protocols/Screencopy.hpp"
|
||||
#include "../../protocols/ToplevelExport.hpp"
|
||||
#include "../../helpers/Color.hpp"
|
||||
#include "../../config/ConfigDataValues.hpp"
|
||||
|
||||
CHyprBorderDecoration::CHyprBorderDecoration(PHLWINDOW pWindow) : IHyprWindowDecoration(pWindow), m_window(pWindow) {
|
||||
;
|
||||
|
|
@ -60,6 +64,27 @@ void CHyprBorderDecoration::draw(PHLMONITOR pMonitor, float const& a) {
|
|||
auto grad = m_window->m_realBorderColor;
|
||||
const bool ANIMATED = m_window->m_borderFadeAnimationProgress->isBeingAnimated();
|
||||
|
||||
static auto PENABLED = CConfigValue<Hyprlang::INT>("general:screencast_border.enabled");
|
||||
static auto PCOLOR = CConfigValue<Hyprlang::CUSTOMTYPE>("general:screencast_border.color");
|
||||
|
||||
if (*PENABLED) {
|
||||
// Check if window is being shared through toplevel export
|
||||
bool isWindowShared = false;
|
||||
if (PROTO::toplevelExport) {
|
||||
for (const auto& frame : PROTO::toplevelExport->m_frames) {
|
||||
if (frame && frame->m_window && frame->m_window == m_window) {
|
||||
isWindowShared = frame->m_client->m_sentScreencast;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (isWindowShared) {
|
||||
const auto* const PGRAD = sc<CGradientValueData*>((PCOLOR.ptr())->getData());
|
||||
grad = PGRAD ? *PGRAD : CGradientValueData(Colors::RED); // fallback to red if config not loaded
|
||||
}
|
||||
}
|
||||
|
||||
if (m_window->m_borderAngleAnimationProgress->enabled()) {
|
||||
grad.m_angle += m_window->m_borderAngleAnimationProgress->value() * M_PI * 2;
|
||||
grad.m_angle = normalizeAngleRad(grad.m_angle);
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue