core: move colorspace handling to oklab (#8635)

* Meson: add hyprgraphics

* Nix: add hyprgraphics

* CI/setup_base: get hyprgraphics-git

---------

Co-authored-by: Mihai Fufezan <mihai@fufexan.net>
This commit is contained in:
Vaxry 2024-12-03 18:58:24 +00:00 committed by GitHub
parent 92186898c0
commit 320144ae72
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
40 changed files with 492 additions and 173 deletions

View file

@ -33,7 +33,9 @@ runs:
libfontenc \
libglvnd \
libinput \
libjxl \
libliftoff \
libwebp \
libxcursor \
libxcvt \
libxfont2 \
@ -69,6 +71,11 @@ runs:
cmake --build ./build --config Release --target all -j`nproc 2>/dev/null || getconf NPROCESSORS_CONF`
cmake --install build
- name: Get hyprgraphics-git
shell: bash
run: |
git clone https://github.com/hyprwm/hyprgraphics && cd hyprgraphics && cmake -DCMAKE_BUILD_TYPE:STRING=Release -DCMAKE_INSTALL_PREFIX:PATH=/usr -B build && cmake --build build --target hyprgraphics && cmake --install build
- name: Get hyprutils-git
shell: bash
run: |

View file

@ -107,11 +107,13 @@ pkg_check_modules(aquamarine_dep REQUIRED IMPORTED_TARGET aquamarine>=0.4.5)
pkg_check_modules(hyprlang_dep REQUIRED IMPORTED_TARGET hyprlang>=0.3.2)
pkg_check_modules(hyprcursor_dep REQUIRED IMPORTED_TARGET hyprcursor>=0.1.7)
pkg_check_modules(hyprutils_dep REQUIRED IMPORTED_TARGET hyprutils>=0.2.3)
pkg_check_modules(hyprgraphics_dep REQUIRED IMPORTED_TARGET hyprgraphics>=0.1.1)
add_compile_definitions(AQUAMARINE_VERSION="${aquamarine_dep_VERSION}")
add_compile_definitions(HYPRLANG_VERSION="${hyprlang_dep_VERSION}")
add_compile_definitions(HYPRUTILS_VERSION="${hyprutils_dep_VERSION}")
add_compile_definitions(HYPRCURSOR_VERSION="${hyprcursor_dep_VERSION}")
add_compile_definitions(HYPRGRAPHICS_VERSION="${hyprgraphics_dep_VERSION}")
pkg_check_modules(
deps
@ -247,7 +249,7 @@ target_precompile_headers(Hyprland PRIVATE
message(STATUS "Setting link libraries")
target_link_libraries(Hyprland rt PkgConfig::aquamarine_dep PkgConfig::hyprlang_dep PkgConfig::hyprutils_dep PkgConfig::hyprcursor_dep PkgConfig::deps)
target_link_libraries(Hyprland rt PkgConfig::aquamarine_dep PkgConfig::hyprlang_dep PkgConfig::hyprutils_dep PkgConfig::hyprcursor_dep PkgConfig::hyprgraphics_dep PkgConfig::deps)
if(udis_dep_FOUND)
target_link_libraries(Hyprland PkgConfig::udis_dep)
else()

View file

@ -92,6 +92,32 @@
"type": "github"
}
},
"hyprgraphics": {
"inputs": {
"hyprutils": [
"hyprutils"
],
"nixpkgs": [
"nixpkgs"
],
"systems": [
"systems"
]
},
"locked": {
"lastModified": 1733248371,
"narHash": "sha256-FFLJzFTyNhS7tBEEECx0B8Ye/bpmxhFVEKlECgMLc6c=",
"owner": "hyprwm",
"repo": "hyprgraphics",
"rev": "cc95e5babc6065bc3ab4cd195429a9900836ef13",
"type": "github"
},
"original": {
"owner": "hyprwm",
"repo": "hyprgraphics",
"type": "github"
}
},
"hyprland-protocols": {
"inputs": {
"nixpkgs": [
@ -246,6 +272,7 @@
"inputs": {
"aquamarine": "aquamarine",
"hyprcursor": "hyprcursor",
"hyprgraphics": "hyprgraphics",
"hyprland-protocols": "hyprland-protocols",
"hyprlang": "hyprlang",
"hyprutils": "hyprutils",

View file

@ -22,6 +22,13 @@
inputs.hyprlang.follows = "hyprlang";
};
hyprgraphics = {
url = "github:hyprwm/hyprgraphics";
inputs.nixpkgs.follows = "nixpkgs";
inputs.systems.follows = "systems";
inputs.hyprutils.follows = "hyprutils";
};
hyprland-protocols = {
url = "github:hyprwm/hyprland-protocols";
inputs.nixpkgs.follows = "nixpkgs";

View file

@ -33,10 +33,12 @@ endif
aquamarine = dependency('aquamarine', version: '>=0.4.5')
hyprcursor = dependency('hyprcursor', version: '>=0.1.7')
hyprgraphics = dependency('hyprgraphics', version: '>= 0.1.1')
hyprlang = dependency('hyprlang', version: '>= 0.3.2')
hyprutils = dependency('hyprutils', version: '>= 0.2.3')
add_project_arguments(['-DAQUAMARINE_VERSION="@0@"'.format(aquamarine.version())], language: 'cpp')
add_project_arguments(['-DHYPRCURSOR_VERSION="@0@"'.format(hyprcursor.version())], language: 'cpp')
add_project_arguments(['-DHYPRGRAPHICS_VERSION="@0@"'.format(hyprgraphics.version())], language: 'cpp')
add_project_arguments(['-DHYPRLANG_VERSION="@0@"'.format(hyprlang.version())], language: 'cpp')
add_project_arguments(['-DHYPRUTILS_VERSION="@0@"'.format(hyprutils.version())], language: 'cpp')

View file

@ -12,6 +12,7 @@
cairo,
git,
hyprcursor,
hyprgraphics,
hyprland-protocols,
hyprlang,
hyprutils,
@ -113,6 +114,7 @@ in
cairo
git
hyprcursor
hyprgraphics
hyprland-protocols
hyprlang
hyprutils

View file

@ -22,6 +22,7 @@ in {
# Dependencies
inputs.aquamarine.overlays.default
inputs.hyprcursor.overlays.default
inputs.hyprgraphics.overlays.default
inputs.hyprland-protocols.overlays.default
inputs.hyprlang.overlays.default
inputs.hyprutils.overlays.default

View file

@ -1873,11 +1873,11 @@ void CCompositor::updateWindowAnimatedDecorationValues(PHLWINDOW pWindow) {
// shadow
if (!pWindow->isX11OverrideRedirect() && !pWindow->m_bX11DoesntWantBorders) {
if (pWindow == m_pLastWindow)
pWindow->m_cRealShadowColor = CColor(*PSHADOWCOL);
pWindow->m_cRealShadowColor = CHyprColor(*PSHADOWCOL);
else
pWindow->m_cRealShadowColor = CColor(*PSHADOWCOLINACTIVE != INT64_MAX ? *PSHADOWCOLINACTIVE : *PSHADOWCOL);
pWindow->m_cRealShadowColor = CHyprColor(*PSHADOWCOLINACTIVE != INT64_MAX ? *PSHADOWCOLINACTIVE : *PSHADOWCOL);
} else {
pWindow->m_cRealShadowColor.setValueAndWarp(CColor(0, 0, 0, 0)); // no shadow
pWindow->m_cRealShadowColor.setValueAndWarp(CHyprColor(0, 0, 0, 0)); // no shadow
}
pWindow->updateWindowDecos();
@ -2608,14 +2608,14 @@ void CCompositor::performUserChecks() {
g_pHyprNotificationOverlay->addNotification(
std::format("Your XDG_CURRENT_DESKTOP environment seems to be managed externally, and the current value is {}.\nThis might cause issues unless it's intentional.",
CURRENT_DESKTOP_ENV ? CURRENT_DESKTOP_ENV : "unset"),
CColor{}, 15000, ICON_WARNING);
CHyprColor{}, 15000, ICON_WARNING);
}
}
if (g_pHyprOpenGL->failedAssetsNo > 0) {
g_pHyprNotificationOverlay->addNotification(std::format("Hyprland failed to load {} essential asset{}, blame your distro's packager for doing a bad job at packaging!",
g_pHyprOpenGL->failedAssetsNo, g_pHyprOpenGL->failedAssetsNo > 1 ? "s" : ""),
CColor{1.0, 0.1, 0.1, 1.0}, 15000, ICON_ERROR);
CHyprColor{1.0, 0.1, 0.1, 1.0}, 15000, ICON_ERROR);
}
}

View file

@ -21,8 +21,9 @@ class ICustomConfigValueData {
class CGradientValueData : public ICustomConfigValueData {
public:
CGradientValueData() {};
CGradientValueData(CColor col) {
CGradientValueData(CHyprColor col) {
m_vColors.push_back(col);
updateColorsOk();
};
virtual ~CGradientValueData() {};
@ -30,14 +31,29 @@ class CGradientValueData : public ICustomConfigValueData {
return CVD_TYPE_GRADIENT;
}
void reset(CColor col) {
void reset(CHyprColor col) {
m_vColors.clear();
m_vColors.emplace_back(col);
m_fAngle = 0;
updateColorsOk();
}
void updateColorsOk() {
m_vColorsOkLabA.clear();
for (auto& c : m_vColors) {
const auto OKLAB = c.asOkLab();
m_vColorsOkLabA.emplace_back(OKLAB.l);
m_vColorsOkLabA.emplace_back(OKLAB.a);
m_vColorsOkLabA.emplace_back(OKLAB.b);
m_vColorsOkLabA.emplace_back(c.a);
}
}
/* Vector containing the colors */
std::vector<CColor> m_vColors;
std::vector<CHyprColor> m_vColors;
/* Vector containing pure colors for shoving into opengl */
std::vector<float> m_vColorsOkLabA;
/* Float corresponding to the angle (rad) */
float m_fAngle = 0;

View file

@ -70,7 +70,7 @@ static Hyprlang::CParseResult configHandleGradientSet(const char* VALUE, void**
const auto COL = configStringToInt(var);
if (!COL)
throw std::runtime_error(std::format("failed to parse {} as a color", var));
DATA->m_vColors.push_back(CColor(COL.value()));
DATA->m_vColors.push_back(CHyprColor(COL.value()));
} catch (std::exception& e) {
Debug::log(WARN, "Error parsing gradient {}", V);
parseError = "Error parsing gradient " + V + ": " + e.what();
@ -85,6 +85,8 @@ static Hyprlang::CParseResult configHandleGradientSet(const char* VALUE, void**
DATA->m_vColors.push_back(0); // transparent
}
DATA->updateColorsOk();
Hyprlang::CParseResult result;
if (!parseError.empty())
result.setError(parseError.c_str());
@ -676,7 +678,7 @@ CConfigManager::CConfigManager() {
Debug::disableTime = reinterpret_cast<int64_t* const*>(m_pConfig->getConfigValuePtr("debug:disable_time")->getDataStaticPtr());
if (ERR.has_value())
g_pHyprError->queueCreate(ERR.value(), CColor{1.0, 0.1, 0.1, 1.0});
g_pHyprError->queueCreate(ERR.value(), CHyprColor{1.0, 0.1, 0.1, 1.0});
}
std::optional<std::string> CConfigManager::generateConfig(std::string configPath) {
@ -883,14 +885,14 @@ void CConfigManager::postConfigReload(const Hyprlang::CParseResult& result) {
m_szConfigErrors = "";
if (result.error && !std::any_cast<Hyprlang::INT>(m_pConfig->getConfigValue("debug:suppress_errors")))
g_pHyprError->queueCreate(result.getError(), CColor(1.0, 50.0 / 255.0, 50.0 / 255.0, 1.0));
g_pHyprError->queueCreate(result.getError(), CHyprColor(1.0, 50.0 / 255.0, 50.0 / 255.0, 1.0));
else if (std::any_cast<Hyprlang::INT>(m_pConfig->getConfigValue("autogenerated")) == 1)
g_pHyprError->queueCreate(
"Warning: You're using an autogenerated config! (config file: " + getMainConfigPath() +
" )\nSUPER+Q -> kitty (if it doesn't launch, make sure it's installed or choose a different terminal in the config)\nSUPER+M -> exit Hyprland",
CColor(1.0, 1.0, 70.0 / 255.0, 1.0));
CHyprColor(1.0, 1.0, 70.0 / 255.0, 1.0));
else if (*PENABLEEXPLICIT != prevEnabledExplicit)
g_pHyprError->queueCreate("Warning: You changed the render:explicit_sync option, this requires you to restart Hyprland.", CColor(0.9, 0.76, 0.221, 1.0));
g_pHyprError->queueCreate("Warning: You changed the render:explicit_sync option, this requires you to restart Hyprland.", CHyprColor(0.9, 0.76, 0.221, 1.0));
else
g_pHyprError->destroy();
@ -948,7 +950,8 @@ void CConfigManager::postConfigReload(const Hyprlang::CParseResult& result) {
// manual crash
if (std::any_cast<Hyprlang::INT>(m_pConfig->getConfigValue("debug:manual_crash")) && !m_bManualCrashInitiated) {
m_bManualCrashInitiated = true;
g_pHyprNotificationOverlay->addNotification("Manual crash has been set up. Set debug:manual_crash back to 0 in order to crash the compositor.", CColor(0), 5000, ICON_INFO);
g_pHyprNotificationOverlay->addNotification("Manual crash has been set up. Set debug:manual_crash back to 0 in order to crash the compositor.", CHyprColor(0), 5000,
ICON_INFO);
} else if (m_bManualCrashInitiated && !std::any_cast<Hyprlang::INT>(m_pConfig->getConfigValue("debug:manual_crash"))) {
// cowabunga it is
g_pHyprRenderer->initiateManualCrash();
@ -1015,7 +1018,7 @@ std::string CConfigManager::parseKeyword(const std::string& COMMAND, const std::
if (COMMAND.contains("explicit")) {
if (*PENABLEEXPLICIT != prevEnabledExplicit)
g_pHyprError->queueCreate("Warning: You changed the render:explicit_sync option, this requires you to restart Hyprland.", CColor(0.9, 0.76, 0.221, 1.0));
g_pHyprError->queueCreate("Warning: You changed the render:explicit_sync option, this requires you to restart Hyprland.", CHyprColor(0.9, 0.76, 0.221, 1.0));
else
g_pHyprError->destroy();
}
@ -1027,7 +1030,7 @@ std::string CConfigManager::parseKeyword(const std::string& COMMAND, const std::
if (std::any_cast<Hyprlang::INT>(m_pConfig->getConfigValue("debug:manual_crash")) && !m_bManualCrashInitiated) {
m_bManualCrashInitiated = true;
if (g_pHyprNotificationOverlay) {
g_pHyprNotificationOverlay->addNotification("Manual crash has been set up. Set debug:manual_crash back to 0 in order to crash the compositor.", CColor(0), 5000,
g_pHyprNotificationOverlay->addNotification("Manual crash has been set up. Set debug:manual_crash back to 0 in order to crash the compositor.", CHyprColor(0), 5000,
ICON_INFO);
}
} else if (m_bManualCrashInitiated && !std::any_cast<Hyprlang::INT>(m_pConfig->getConfigValue("debug:manual_crash"))) {
@ -1671,7 +1674,7 @@ SAnimationPropertyConfig* CConfigManager::getAnimationPropertyConfig(const std::
}
void CConfigManager::addParseError(const std::string& err) {
g_pHyprError->queueCreate(err + "\nHyprland may not work correctly.", CColor(1.0, 50.0 / 255.0, 50.0 / 255.0, 1.0));
g_pHyprError->queueCreate(err + "\nHyprland may not work correctly.", CHyprColor(1.0, 50.0 / 255.0, 50.0 / 255.0, 1.0));
}
PHLMONITOR CConfigManager::getBoundMonitorForWS(const std::string& wsname) {
@ -1716,7 +1719,7 @@ void CConfigManager::handlePluginLoads() {
error << "\n" << path;
}
g_pHyprError->queueCreate(error.str(), CColor(1.0, 50.0 / 255.0, 50.0 / 255.0, 1.0));
g_pHyprError->queueCreate(error.str(), CHyprColor(1.0, 50.0 / 255.0, 50.0 / 255.0, 1.0));
}
if (pluginsChanged) {

View file

@ -119,7 +119,7 @@ struct SConfigOptionDescription {
};
struct SColorData {
CColor color;
CHyprColor color;
};
struct SChoiceData {

View file

@ -875,9 +875,9 @@ std::string versionRequest(eHyprCtlOutputFormat format, std::string request) {
std::string result = std::format("Hyprland {} built from branch {} at commit {} {} ({}).\n"
"Date: {}\n"
"Tag: {}, commits: {}\n"
"built against:\n aquamarine {}\n hyprlang {}\n hyprutils {}\n hyprcursor {}\n\n\n",
"built against:\n aquamarine {}\n hyprlang {}\n hyprutils {}\n hyprcursor {}\n hyprgraphics {}\n\n\n",
HYPRLAND_VERSION, GIT_BRANCH, GIT_COMMIT_HASH, GIT_DIRTY, commitMsg, GIT_COMMIT_DATE, GIT_TAG, GIT_COMMITS, AQUAMARINE_VERSION,
HYPRLANG_VERSION, HYPRUTILS_VERSION, HYPRCURSOR_VERSION);
HYPRLANG_VERSION, HYPRUTILS_VERSION, HYPRCURSOR_VERSION, HYPRGRAPHICS_VERSION);
#if (!defined(LEGACY_RENDERER) && !defined(ISDEBUG) && !defined(NO_XWAYLAND))
result += "no flags were set\n";
@ -909,9 +909,10 @@ std::string versionRequest(eHyprCtlOutputFormat format, std::string request) {
"buildHyprlang": "{}",
"buildHyprutils": "{}",
"buildHyprcursor": "{}",
"buildHyprgraphics": "{}",
"flags": [)#",
GIT_BRANCH, GIT_COMMIT_HASH, HYPRLAND_VERSION, (strcmp(GIT_DIRTY, "dirty") == 0 ? "true" : "false"), escapeJSONStrings(commitMsg), GIT_COMMIT_DATE, GIT_TAG,
GIT_COMMITS, AQUAMARINE_VERSION, HYPRLANG_VERSION, HYPRUTILS_VERSION, HYPRCURSOR_VERSION);
GIT_COMMITS, AQUAMARINE_VERSION, HYPRLANG_VERSION, HYPRUTILS_VERSION, HYPRCURSOR_VERSION, HYPRGRAPHICS_VERSION);
#ifdef LEGACY_RENDERER
result += "\"legacyrenderer\",";
@ -1290,7 +1291,7 @@ std::string dispatchSeterror(eHyprCtlOutputFormat format, std::string request) {
return "ok";
}
const CColor COLOR = configStringToInt(vars[1]).value_or(0);
const CHyprColor COLOR = configStringToInt(vars[1]).value_or(0);
for (size_t i = 2; i < vars.size(); ++i)
errorMessage += vars[i] + ' ';
@ -1545,10 +1546,10 @@ std::string dispatchNotify(eHyprCtlOutputFormat format, std::string request) {
const auto COLOR_RESULT = configStringToInt(vars[3]);
if (!COLOR_RESULT)
return "invalid arg 3";
CColor color = *COLOR_RESULT;
CHyprColor color = *COLOR_RESULT;
size_t msgidx = 4;
float fontsize = 13.f;
size_t msgidx = 4;
float fontsize = 13.f;
if (vars[msgidx].length() > 9 && vars[msgidx].compare(0, 9, "fontsize:") == 0) {
const auto FONTSIZE = vars[msgidx].substr(9);

View file

@ -34,11 +34,11 @@ CHyprNotificationOverlay::~CHyprNotificationOverlay() {
cairo_surface_destroy(m_pCairoSurface);
}
void CHyprNotificationOverlay::addNotification(const std::string& text, const CColor& color, const float timeMs, const eIcons icon, const float fontSize) {
void CHyprNotificationOverlay::addNotification(const std::string& text, const CHyprColor& color, const float timeMs, const eIcons icon, const float fontSize) {
const auto PNOTIF = m_dNotifications.emplace_back(std::make_unique<SNotification>()).get();
PNOTIF->text = icon != eIcons::ICON_NONE ? " " + text /* tiny bit of padding otherwise icon touches text */ : text;
PNOTIF->color = color == CColor(0) ? ICONS_COLORS[icon] : color;
PNOTIF->color = color == CHyprColor(0) ? ICONS_COLORS[icon] : color;
PNOTIF->started.reset();
PNOTIF->timeMs = timeMs;
PNOTIF->icon = icon;

View file

@ -19,17 +19,17 @@ enum eIconBackend {
static const std::array<std::array<std::string, ICON_NONE + 1>, 3 /* backends */> ICONS_ARRAY = {
std::array<std::string, ICON_NONE + 1>{"[!]", "[i]", "[Hint]", "[Err]", "[?]", "[ok]", ""},
std::array<std::string, ICON_NONE + 1>{"", "", "", "", "", "󰸞", ""}, std::array<std::string, ICON_NONE + 1>{"", "", "", "", "", ""}};
static const std::array<CColor, ICON_NONE + 1> ICONS_COLORS = {CColor{255.0 / 255.0, 204 / 255.0, 102 / 255.0, 1.0},
CColor{128 / 255.0, 255 / 255.0, 255 / 255.0, 1.0},
CColor{179 / 255.0, 255 / 255.0, 204 / 255.0, 1.0},
CColor{255 / 255.0, 77 / 255.0, 77 / 255.0, 1.0},
CColor{255 / 255.0, 204 / 255.0, 153 / 255.0, 1.0},
CColor{128 / 255.0, 255 / 255.0, 128 / 255.0, 1.0},
CColor{0, 0, 0, 1.0}};
static const std::array<CHyprColor, ICON_NONE + 1> ICONS_COLORS = {CHyprColor{255.0 / 255.0, 204 / 255.0, 102 / 255.0, 1.0},
CHyprColor{128 / 255.0, 255 / 255.0, 255 / 255.0, 1.0},
CHyprColor{179 / 255.0, 255 / 255.0, 204 / 255.0, 1.0},
CHyprColor{255 / 255.0, 77 / 255.0, 77 / 255.0, 1.0},
CHyprColor{255 / 255.0, 204 / 255.0, 153 / 255.0, 1.0},
CHyprColor{128 / 255.0, 255 / 255.0, 128 / 255.0, 1.0},
CHyprColor{0, 0, 0, 1.0}};
struct SNotification {
std::string text = "";
CColor color;
CHyprColor color;
CTimer started;
float timeMs = 0;
eIcons icon = ICON_NONE;
@ -42,7 +42,7 @@ class CHyprNotificationOverlay {
~CHyprNotificationOverlay();
void draw(PHLMONITOR pMonitor);
void addNotification(const std::string& text, const CColor& color, const float timeMs, const eIcons icon = ICON_NONE, const float fontSize = 13.f);
void addNotification(const std::string& text, const CHyprColor& color, const float timeMs, const eIcons icon = ICON_NONE, const float fontSize = 13.f);
void dismissNotifications(const int amount);
bool hasAny();

View file

@ -674,8 +674,8 @@ void CWindow::applyDynamicRule(const SWindowRule& r) {
// Basic form has only two colors, everything else can be parsed as a gradient
if (colorsAndAngles.size() == 2 && !colorsAndAngles[1].contains("deg")) {
m_sWindowData.activeBorderColor = CWindowOverridableVar(CGradientValueData(CColor(configStringToInt(colorsAndAngles[0]).value_or(0))), priority);
m_sWindowData.inactiveBorderColor = CWindowOverridableVar(CGradientValueData(CColor(configStringToInt(colorsAndAngles[1]).value_or(0))), priority);
m_sWindowData.activeBorderColor = CWindowOverridableVar(CGradientValueData(CHyprColor(configStringToInt(colorsAndAngles[0]).value_or(0))), priority);
m_sWindowData.inactiveBorderColor = CWindowOverridableVar(CGradientValueData(CHyprColor(configStringToInt(colorsAndAngles[1]).value_or(0))), priority);
return;
}

View file

@ -356,7 +356,7 @@ class CWindow {
CAnimatedVariable<float> m_fActiveInactiveAlpha;
// animated shadow color
CAnimatedVariable<CColor> m_cRealShadowColor;
CAnimatedVariable<CHyprColor> m_cRealShadowColor;
// animated tint
CAnimatedVariable<float> m_fDimPercent;

View file

@ -34,7 +34,7 @@ struct typeToANIMATEDVARTYPE_t<Vector2D> {
};
template <>
struct typeToANIMATEDVARTYPE_t<CColor> {
struct typeToANIMATEDVARTYPE_t<CHyprColor> {
static constexpr ANIMATEDVARTYPE value = AVARTYPE_COLOR;
};
@ -63,7 +63,7 @@ concept OneOf = (... or std::same_as<T, U>);
// This is mainly to get better errors if we put a type that's not supported
// Otherwise template errors are ugly
template <class T>
concept Animable = OneOf<T, Vector2D, float, CColor>;
concept Animable = OneOf<T, Vector2D, float, CHyprColor>;
class CBaseAnimatedVariable {
public:

View file

@ -5,22 +5,52 @@
#define GREEN(c) ((double)(((c) >> 8) & 0xff) / 255.0)
#define BLUE(c) ((double)(((c)) & 0xff) / 255.0)
CColor::CColor() {}
CHyprColor::CHyprColor() {}
CColor::CColor(float r, float g, float b, float a) {
this->r = r;
this->g = g;
this->b = b;
this->a = a;
CHyprColor::CHyprColor(float r_, float g_, float b_, float a_) {
r = r_;
g = g_;
b = b_;
a = a_;
okLab = Hyprgraphics::CColor(Hyprgraphics::CColor::SSRGB{r, g, b}).asOkLab();
}
CColor::CColor(uint64_t hex) {
this->r = RED(hex);
this->g = GREEN(hex);
this->b = BLUE(hex);
this->a = ALPHA(hex);
CHyprColor::CHyprColor(uint64_t hex) {
r = RED(hex);
g = GREEN(hex);
b = BLUE(hex);
a = ALPHA(hex);
okLab = Hyprgraphics::CColor(Hyprgraphics::CColor::SSRGB{r, g, b}).asOkLab();
}
uint32_t CColor::getAsHex() const {
CHyprColor::CHyprColor(const Hyprgraphics::CColor& color, float a_) {
const auto SRGB = color.asRgb();
r = SRGB.r;
g = SRGB.g;
b = SRGB.b;
a = a_;
okLab = color.asOkLab();
}
uint32_t CHyprColor::getAsHex() const {
return (uint32_t)(a * 255.f) * 0x1000000 + (uint32_t)(r * 255.f) * 0x10000 + (uint32_t)(g * 255.f) * 0x100 + (uint32_t)(b * 255.f) * 0x1;
}
}
Hyprgraphics::CColor::SSRGB CHyprColor::asRGB() const {
return {r, g, b};
}
Hyprgraphics::CColor::SOkLab CHyprColor::asOkLab() const {
return okLab;
}
Hyprgraphics::CColor::SHSL CHyprColor::asHSL() const {
return Hyprgraphics::CColor(okLab).asHSL();
}
CHyprColor CHyprColor::stripA() const {
return {r, g, b, 1.F};
}

View file

@ -1,35 +1,47 @@
#pragma once
#include <cstdint>
#include <hyprgraphics/color/Color.hpp>
#include "../debug/Log.hpp"
#include "../macros.hpp"
class CColor {
class CHyprColor {
public:
CColor();
CColor(float r, float g, float b, float a);
CColor(uint64_t);
float r = 0, g = 0, b = 0, a = 1.f;
CHyprColor();
CHyprColor(float r, float g, float b, float a);
CHyprColor(const Hyprgraphics::CColor& col, float a);
CHyprColor(uint64_t);
// AR32
uint32_t getAsHex() const;
uint32_t getAsHex() const;
Hyprgraphics::CColor::SSRGB asRGB() const;
Hyprgraphics::CColor::SOkLab asOkLab() const;
Hyprgraphics::CColor::SHSL asHSL() const;
CHyprColor stripA() const;
CColor operator-(const CColor& c2) const {
return CColor(r - c2.r, g - c2.g, b - c2.b, a - c2.a);
//
bool operator==(const CHyprColor& c2) const {
return c2.r == r && c2.g == g && c2.b == b && c2.a == a;
}
CColor operator+(const CColor& c2) const {
return CColor(r + c2.r, g + c2.g, b + c2.b, a + c2.a);
// stubs for the AnimationMgr
CHyprColor operator-(const CHyprColor& c2) const {
RASSERT(false, "CHyprColor: - is a STUB");
return {};
}
CColor operator*(const float& v) const {
return CColor(r * v, g * v, b * v, a * v);
CHyprColor operator+(const CHyprColor& c2) const {
RASSERT(false, "CHyprColor: + is a STUB");
return {};
}
bool operator==(const CColor& c2) const {
return r == c2.r && g == c2.g && b == c2.b && a == c2.a;
CHyprColor operator*(const float& c2) const {
RASSERT(false, "CHyprColor: * is a STUB");
return {};
}
CColor stripA() const {
return {r, g, b, 1};
}
double r = 0, g = 0, b = 0, a = 0;
private:
Hyprgraphics::CColor::SOkLab okLab; // cache for the OkLab representation
};

View file

@ -33,7 +33,7 @@ CHyprError::~CHyprError() {
m_fFadeOpacity.unregister();
}
void CHyprError::queueCreate(std::string message, const CColor& color) {
void CHyprError::queueCreate(std::string message, const CHyprColor& color) {
m_szQueued = message;
m_cQueued = color;
}
@ -98,7 +98,7 @@ void CHyprError::createQueued() {
cairo_stroke(CAIRO);
// draw the text with a common font
const CColor textColor = CColor(0.9, 0.9, 0.9, 1.0);
const CHyprColor textColor = CHyprColor(0.9, 0.9, 0.9, 1.0);
cairo_set_source_rgba(CAIRO, textColor.r, textColor.g, textColor.b, textColor.a);
static auto fontFamily = CConfigValue<std::string>("misc:font_family");
@ -160,7 +160,7 @@ void CHyprError::createQueued() {
m_bIsCreated = true;
m_szQueued = "";
m_cQueued = CColor();
m_cQueued = CHyprColor();
g_pHyprRenderer->damageMonitor(PMONITOR);

View file

@ -11,7 +11,7 @@ class CHyprError {
CHyprError();
~CHyprError();
void queueCreate(std::string message, const CColor& color);
void queueCreate(std::string message, const CHyprColor& color);
void draw();
void destroy();
@ -21,7 +21,7 @@ class CHyprError {
private:
void createQueued();
std::string m_szQueued = "";
CColor m_cQueued;
CHyprColor m_cQueued;
bool m_bQueuedDestroy = false;
bool m_bIsCreated = false;
SP<CTexture> m_pTexture;

View file

@ -8,6 +8,8 @@
#include "eventLoop/EventLoopManager.hpp"
#include "../helpers/varlist/VarList.hpp"
#include <hyprgraphics/color/Color.hpp>
int wlTick(SP<CEventLoopTimer> self, void* data) {
if (g_pAnimationManager)
g_pAnimationManager->onTicked();
@ -154,7 +156,7 @@ void CAnimationManager::tick() {
// beziers are with a switch unforto
// TODO: maybe do something cleaner
auto updateVariable = [&]<Animable T>(CAnimatedVariable<T>& av) {
static const auto updateVariable = [&]<Animable T>(CAnimatedVariable<T>& av) {
// for disabled anims just warp
if (av.m_pConfig->pValues->internalEnabled == 0 || animationsDisabled) {
av.warp(false);
@ -166,13 +168,50 @@ void CAnimationManager::tick() {
return;
}
const auto DELTA = av.m_Goal - av.m_Begun;
const auto BEZIER = m_mBezierCurves.find(av.m_pConfig->pValues->internalBezier);
const auto POINTY = BEZIER != m_mBezierCurves.end() ? BEZIER->second.getYForPoint(SPENT) : DEFAULTBEZIER->second.getYForPoint(SPENT);
const auto DELTA = av.m_Goal - av.m_Begun;
if (BEZIER != m_mBezierCurves.end())
av.m_Value = av.m_Begun + DELTA * BEZIER->second.getYForPoint(SPENT);
av.m_Value = av.m_Begun + DELTA * POINTY;
else
av.m_Value = av.m_Begun + DELTA * DEFAULTBEZIER->second.getYForPoint(SPENT);
av.m_Value = av.m_Begun + DELTA * POINTY;
};
static const auto updateColorVariable = [&](CAnimatedVariable<CHyprColor>& av) {
// for disabled anims just warp
if (av.m_pConfig->pValues->internalEnabled == 0 || animationsDisabled) {
av.warp(false);
return;
}
if (SPENT >= 1.f || av.m_Begun == av.m_Goal) {
av.warp(false);
return;
}
const auto BEZIER = m_mBezierCurves.find(av.m_pConfig->pValues->internalBezier);
const auto POINTY = BEZIER != m_mBezierCurves.end() ? BEZIER->second.getYForPoint(SPENT) : DEFAULTBEZIER->second.getYForPoint(SPENT);
// convert both to OkLab, then lerp that, and convert back.
// This is not as fast as just lerping rgb, but it's WAY more precise...
// Use the CHyprColor cache for OkLab
const auto& L1 = av.m_Begun.asOkLab();
const auto& L2 = av.m_Goal.asOkLab();
static const auto lerp = [](const float one, const float two, const float progress) -> float { return one + (two - one) * progress; };
const Hyprgraphics::CColor lerped = Hyprgraphics::CColor::SOkLab{
.l = lerp(L1.l, L2.l, POINTY),
.a = lerp(L1.a, L2.a, POINTY),
.b = lerp(L1.b, L2.b, POINTY),
};
av.m_Value = {lerped, lerp(av.m_Begun.a, av.m_Goal.a, POINTY)};
return;
};
switch (av->m_Type) {
@ -187,8 +226,8 @@ void CAnimationManager::tick() {
break;
}
case AVARTYPE_COLOR: {
auto typedAv = static_cast<CAnimatedVariable<CColor>*>(av);
updateVariable(*typedAv);
auto typedAv = static_cast<CAnimatedVariable<CHyprColor>*>(av);
updateColorVariable(*typedAv);
break;
}
default: UNREACHABLE();
@ -272,7 +311,7 @@ bool CAnimationManager::deltaSmallToFlip(const Vector2D& a, const Vector2D& b) {
return std::abs(a.x - b.x) < 0.5f && std::abs(a.y - b.y) < 0.5f;
}
bool CAnimationManager::deltaSmallToFlip(const CColor& a, const CColor& b) {
bool CAnimationManager::deltaSmallToFlip(const CHyprColor& a, const CHyprColor& b) {
return std::abs(a.r - b.r) < 0.5f && std::abs(a.g - b.g) < 0.5f && std::abs(a.b - b.b) < 0.5f && std::abs(a.a - b.a) < 0.5f;
}
@ -288,7 +327,7 @@ bool CAnimationManager::deltazero(const float& a, const float& b) {
return a == b;
}
bool CAnimationManager::deltazero(const CColor& a, const CColor& b) {
bool CAnimationManager::deltazero(const CHyprColor& a, const CHyprColor& b) {
return a.r == b.r && a.g == b.g && a.b == b.b && a.a == b.a;
}

View file

@ -39,10 +39,10 @@ class CAnimationManager {
private:
bool deltaSmallToFlip(const Vector2D& a, const Vector2D& b);
bool deltaSmallToFlip(const CColor& a, const CColor& b);
bool deltaSmallToFlip(const CHyprColor& a, const CHyprColor& b);
bool deltaSmallToFlip(const float& a, const float& b);
bool deltazero(const Vector2D& a, const Vector2D& b);
bool deltazero(const CColor& a, const CColor& b);
bool deltazero(const CHyprColor& a, const CHyprColor& b);
bool deltazero(const float& a, const float& b);
std::unordered_map<std::string, CBezierCurve> m_mBezierCurves;

View file

@ -275,7 +275,7 @@ void CKeybindManager::updateXKBTranslationState() {
if (!PKEYMAP) {
g_pHyprError->queueCreate("[Runtime Error] Invalid keyboard layout passed. ( rules: " + RULES + ", model: " + MODEL + ", variant: " + VARIANT + ", options: " + OPTIONS +
", layout: " + LAYOUT + " )",
CColor(1.0, 50.0 / 255.0, 50.0 / 255.0, 1.0));
CHyprColor(1.0, 50.0 / 255.0, 50.0 / 255.0, 1.0));
Debug::log(ERR, "[XKBTranslationState] Keyboard layout {} with variant {} (rules: {}, model: {}, options: {}) couldn't have been loaded.", rules.layout, rules.variant,
rules.rules, rules.model, rules.options);

View file

@ -505,7 +505,7 @@ SP<Aquamarine::IBuffer> CPointerManager::renderHWCursorBuffer(SP<CPointerManager
RBO->bind();
g_pHyprOpenGL->beginSimple(state->monitor.lock(), {0, 0, INT16_MAX, INT16_MAX}, RBO);
g_pHyprOpenGL->clear(CColor{0.F, 0.F, 0.F, 0.F});
g_pHyprOpenGL->clear(CHyprColor{0.F, 0.F, 0.F, 0.F});
CBox xbox = {{}, Vector2D{currentCursorImage.size / currentCursorImage.scale * state->monitor->scale}.round()};
Debug::log(TRACE, "[pointer] monitor: {}, size: {}, hw buf: {}, scale: {:.2f}, monscale: {:.2f}, xbox: {}", state->monitor->szName, currentCursorImage.size, cursorSize,

View file

@ -10,6 +10,7 @@ executable(
server_protos,
aquamarine,
hyprcursor,
hyprgraphics,
hyprlang,
hyprutils,
dependency('gbm'),

View file

@ -71,7 +71,7 @@ APICALL bool HyprlandAPI::reloadConfig() {
return true;
}
APICALL bool HyprlandAPI::addNotification(HANDLE handle, const std::string& text, const CColor& color, const float timeMs) {
APICALL bool HyprlandAPI::addNotification(HANDLE handle, const std::string& text, const CHyprColor& color, const float timeMs) {
auto* const PLUGIN = g_pPluginSystem->getPluginByHandle(handle);
if (!PLUGIN)
@ -244,7 +244,7 @@ APICALL bool addNotificationV2(HANDLE handle, const std::unordered_map<std::stri
if (iterator == data.end())
return false;
const auto COLOR = std::any_cast<CColor>(iterator->second);
const auto COLOR = std::any_cast<CHyprColor>(iterator->second);
// optional
eIcons icon = ICON_NONE;

View file

@ -187,7 +187,7 @@ namespace HyprlandAPI {
returns: true on success. False otherwise.
*/
APICALL bool addNotification(HANDLE handle, const std::string& text, const CColor& color, const float timeMs);
APICALL bool addNotification(HANDLE handle, const std::string& text, const CHyprColor& color, const float timeMs);
/*
Creates a trampoline function hook to an internal hl func.
@ -251,7 +251,7 @@ namespace HyprlandAPI {
data has to contain:
- text: std::string or const char*
- time: uint64_t
- color: CColor -> CColor(0) will apply the default color for the notification icon
- color: CHyprColor -> CHyprColor(0) will apply the default color for the notification icon
data may contain:
- icon: eIcons

View file

@ -2,7 +2,7 @@
#include <limits>
#include "render/Renderer.hpp"
CSinglePixelBuffer::CSinglePixelBuffer(uint32_t id, wl_client* client, CColor col_) {
CSinglePixelBuffer::CSinglePixelBuffer(uint32_t id, wl_client* client, CHyprColor col_) {
LOGM(LOG, "New single-pixel buffer with color 0x{:x}", col_.getAsHex());
color = col_.getAsHex();
@ -59,7 +59,7 @@ bool CSinglePixelBuffer::good() {
return resource->good();
}
CSinglePixelBufferResource::CSinglePixelBufferResource(uint32_t id, wl_client* client, CColor color) {
CSinglePixelBufferResource::CSinglePixelBufferResource(uint32_t id, wl_client* client, CHyprColor color) {
buffer = makeShared<CSinglePixelBuffer>(id, client, color);
if (!buffer->good())
@ -89,8 +89,8 @@ CSinglePixelBufferManagerResource::CSinglePixelBufferManagerResource(SP<CWpSingl
resource->setOnDestroy([this](CWpSinglePixelBufferManagerV1* r) { PROTO::singlePixel->destroyResource(this); });
resource->setCreateU32RgbaBuffer([this](CWpSinglePixelBufferManagerV1* res, uint32_t id, uint32_t r, uint32_t g, uint32_t b, uint32_t a) {
CColor color{r / (float)std::numeric_limits<uint32_t>::max(), g / (float)std::numeric_limits<uint32_t>::max(), b / (float)std::numeric_limits<uint32_t>::max(),
a / (float)std::numeric_limits<uint32_t>::max()};
CHyprColor color{r / (float)std::numeric_limits<uint32_t>::max(), g / (float)std::numeric_limits<uint32_t>::max(), b / (float)std::numeric_limits<uint32_t>::max(),
a / (float)std::numeric_limits<uint32_t>::max()};
const auto RESOURCE = PROTO::singlePixel->m_vBuffers.emplace_back(makeShared<CSinglePixelBufferResource>(id, resource->client(), color));
if (!RESOURCE->good()) {

View file

@ -9,7 +9,7 @@
class CSinglePixelBuffer : public IHLBuffer {
public:
CSinglePixelBuffer(uint32_t id, wl_client* client, CColor col);
CSinglePixelBuffer(uint32_t id, wl_client* client, CHyprColor col);
virtual ~CSinglePixelBuffer();
virtual Aquamarine::eBufferCapability caps();
@ -33,7 +33,7 @@ class CSinglePixelBuffer : public IHLBuffer {
class CSinglePixelBufferResource {
public:
CSinglePixelBufferResource(uint32_t id, wl_client* client, CColor color);
CSinglePixelBufferResource(uint32_t id, wl_client* client, CHyprColor color);
~CSinglePixelBufferResource();
bool good();

View file

@ -255,7 +255,7 @@ bool CToplevelExportFrame::copyShm(timespec* now) {
if (!g_pHyprRenderer->beginRender(PMONITOR, fakeDamage, RENDER_MODE_FULL_FAKE, nullptr, &outFB))
return false;
g_pHyprOpenGL->clear(CColor(0, 0, 0, 1.0));
g_pHyprOpenGL->clear(CHyprColor(0, 0, 0, 1.0));
// render client at 0,0
g_pHyprRenderer->m_bBlockSurfaceFeedback = g_pHyprRenderer->shouldRenderWindow(pWindow); // block the feedback to avoid spamming the surface if it's visible
@ -308,7 +308,7 @@ bool CToplevelExportFrame::copyDmabuf(timespec* now) {
if (!g_pHyprRenderer->beginRender(PMONITOR, fakeDamage, RENDER_MODE_TO_BUFFER, buffer.lock()))
return false;
g_pHyprOpenGL->clear(CColor(0, 0, 0, 1.0));
g_pHyprOpenGL->clear(CHyprColor(0, 0, 0, 1.0));
g_pHyprRenderer->m_bBlockSurfaceFeedback = g_pHyprRenderer->shouldRenderWindow(pWindow); // block the feedback to avoid spamming the surface if it's visible
g_pHyprRenderer->renderWindow(pWindow, PMONITOR, now, false, RENDER_PASS_ALL, true, true);

View file

@ -566,7 +566,11 @@ void CHyprOpenGLImpl::logShaderError(const GLuint& shader, bool program) {
glGetShaderInfoLog(shader, maxLength, &maxLength, errorLog.data());
std::string errorStr(errorLog.begin(), errorLog.end());
g_pConfigManager->addParseError((program ? "Screen shader parser: Error linking program:" : "Screen shader parser: Error compiling shader: ") + errorStr);
const auto FULLERROR = (program ? "Screen shader parser: Error linking program:" : "Screen shader parser: Error compiling shader: ") + errorStr;
Debug::log(ERR, "Failed to link shader: {}", FULLERROR);
g_pConfigManager->addParseError(FULLERROR);
}
GLuint CHyprOpenGLImpl::createProgram(const std::string& vert, const std::string& frag, bool dynamic) {
@ -604,6 +608,8 @@ GLuint CHyprOpenGLImpl::createProgram(const std::string& vert, const std::string
return 0;
}
} else {
if (ok != GL_TRUE)
logShaderError(prog, true);
RASSERT(ok != GL_FALSE, "createProgram() failed! GL_LINK_STATUS not OK!");
}
@ -627,6 +633,8 @@ GLuint CHyprOpenGLImpl::compileShader(const GLuint& type, std::string src, bool
return 0;
}
} else {
if (ok != GL_TRUE)
logShaderError(shader, false);
RASSERT(ok != GL_FALSE, "compileShader() failed! GL_COMPILE_STATUS not OK!");
}
@ -1114,8 +1122,12 @@ void CHyprOpenGLImpl::initShaders() {
m_RenderData.pCurrentMonData->m_shBORDER1.radius = glGetUniformLocation(prog, "radius");
m_RenderData.pCurrentMonData->m_shBORDER1.radiusOuter = glGetUniformLocation(prog, "radiusOuter");
m_RenderData.pCurrentMonData->m_shBORDER1.gradient = glGetUniformLocation(prog, "gradient");
m_RenderData.pCurrentMonData->m_shBORDER1.gradient2 = glGetUniformLocation(prog, "gradient2");
m_RenderData.pCurrentMonData->m_shBORDER1.gradientLength = glGetUniformLocation(prog, "gradientLength");
m_RenderData.pCurrentMonData->m_shBORDER1.gradient2Length = glGetUniformLocation(prog, "gradient2Length");
m_RenderData.pCurrentMonData->m_shBORDER1.angle = glGetUniformLocation(prog, "angle");
m_RenderData.pCurrentMonData->m_shBORDER1.angle2 = glGetUniformLocation(prog, "angle2");
m_RenderData.pCurrentMonData->m_shBORDER1.gradientLerp = glGetUniformLocation(prog, "gradientLerp");
m_RenderData.pCurrentMonData->m_shBORDER1.alpha = glGetUniformLocation(prog, "alpha");
m_RenderData.pCurrentMonData->m_bShadersInitialized = true;
@ -1167,7 +1179,7 @@ void CHyprOpenGLImpl::applyScreenShader(const std::string& path) {
m_sFinalScreenShader.posAttrib = glGetAttribLocation(m_sFinalScreenShader.program, "pos");
}
void CHyprOpenGLImpl::clear(const CColor& color) {
void CHyprOpenGLImpl::clear(const CHyprColor& color) {
RASSERT(m_RenderData.pMonitor, "Tried to render without begin()!");
TRACY_GPU_ZONE("RenderClear");
@ -1231,12 +1243,12 @@ void CHyprOpenGLImpl::scissor(const int x, const int y, const int w, const int h
scissor(&box, transform);
}
void CHyprOpenGLImpl::renderRect(CBox* box, const CColor& col, int round) {
void CHyprOpenGLImpl::renderRect(CBox* box, const CHyprColor& col, int round) {
if (!m_RenderData.damage.empty())
renderRectWithDamage(box, col, &m_RenderData.damage, round);
}
void CHyprOpenGLImpl::renderRectWithBlur(CBox* box, const CColor& col, int round, float blurA, bool xray) {
void CHyprOpenGLImpl::renderRectWithBlur(CBox* box, const CHyprColor& col, int round, float blurA, bool xray) {
if (m_RenderData.damage.empty())
return;
@ -1258,7 +1270,7 @@ void CHyprOpenGLImpl::renderRectWithBlur(CBox* box, const CColor& col, int round
glStencilOp(GL_KEEP, GL_KEEP, GL_REPLACE);
glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE);
renderRect(box, CColor(0, 0, 0, 0), round);
renderRect(box, CHyprColor(0, 0, 0, 0), round);
glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
glStencilFunc(GL_EQUAL, 1, 0xFF);
@ -1283,7 +1295,7 @@ void CHyprOpenGLImpl::renderRectWithBlur(CBox* box, const CColor& col, int round
renderRectWithDamage(box, col, &m_RenderData.damage, round);
}
void CHyprOpenGLImpl::renderRectWithDamage(CBox* box, const CColor& col, CRegion* damage, int round) {
void CHyprOpenGLImpl::renderRectWithDamage(CBox* box, const CHyprColor& col, CRegion* damage, int round) {
RASSERT((box->width > 0 && box->height > 0), "Tried to render rect with width/height < 0!");
RASSERT(m_RenderData.pMonitor, "Tried to render rect without begin()!");
@ -1981,7 +1993,7 @@ void CHyprOpenGLImpl::preBlurForCurrentMonitor() {
m_RenderData.pMonitor->output->state->state().drmFormat);
m_RenderData.pCurrentMonData->blurFB.bind();
clear(CColor(0, 0, 0, 0));
clear(CHyprColor(0, 0, 0, 0));
m_bEndFrame = true; // fix transformed
renderTextureInternalWithDamage(POUTFB->getTexture(), &wholeMonitor, 1, &fakeDamage, 0, false, true, false);
@ -2100,7 +2112,7 @@ void CHyprOpenGLImpl::renderTextureWithBlur(SP<CTexture> tex, CBox* pBox, float
glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE);
if (USENEWOPTIMIZE && !(m_RenderData.discardMode & DISCARD_ALPHA))
renderRect(pBox, CColor(0, 0, 0, 0), round);
renderRect(pBox, CHyprColor(0, 0, 0, 0), round);
else
renderTexture(tex, pBox, a, round, true, true); // discard opaque
glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
@ -2184,12 +2196,107 @@ void CHyprOpenGLImpl::renderBorder(CBox* box, const CGradientValueData& grad, in
glUniformMatrix3fv(m_RenderData.pCurrentMonData->m_shBORDER1.proj, 1, GL_FALSE, glMatrix.getMatrix().data());
#endif
static_assert(sizeof(CColor) == 4 * sizeof(float)); // otherwise the line below this will fail
glUniform4fv(m_RenderData.pCurrentMonData->m_shBORDER1.gradient, grad.m_vColors.size(), (float*)grad.m_vColors.data());
glUniform1i(m_RenderData.pCurrentMonData->m_shBORDER1.gradientLength, grad.m_vColors.size());
glUniform4fv(m_RenderData.pCurrentMonData->m_shBORDER1.gradient, grad.m_vColorsOkLabA.size(), (float*)grad.m_vColorsOkLabA.data());
glUniform1i(m_RenderData.pCurrentMonData->m_shBORDER1.gradientLength, grad.m_vColorsOkLabA.size() / 4);
glUniform1f(m_RenderData.pCurrentMonData->m_shBORDER1.angle, (int)(grad.m_fAngle / (PI / 180.0)) % 360 * (PI / 180.0));
glUniform1f(m_RenderData.pCurrentMonData->m_shBORDER1.alpha, a);
glUniform1i(m_RenderData.pCurrentMonData->m_shBORDER1.gradient2Length, 0);
CBox transformedBox = *box;
transformedBox.transform(wlTransformToHyprutils(invertTransform(m_RenderData.pMonitor->transform)), m_RenderData.pMonitor->vecTransformedSize.x,
m_RenderData.pMonitor->vecTransformedSize.y);
const auto TOPLEFT = Vector2D(transformedBox.x, transformedBox.y);
const auto FULLSIZE = Vector2D(transformedBox.width, transformedBox.height);
glUniform2f(m_RenderData.pCurrentMonData->m_shBORDER1.topLeft, (float)TOPLEFT.x, (float)TOPLEFT.y);
glUniform2f(m_RenderData.pCurrentMonData->m_shBORDER1.fullSize, (float)FULLSIZE.x, (float)FULLSIZE.y);
glUniform2f(m_RenderData.pCurrentMonData->m_shBORDER1.fullSizeUntransformed, (float)box->width, (float)box->height);
glUniform1f(m_RenderData.pCurrentMonData->m_shBORDER1.radius, round);
glUniform1f(m_RenderData.pCurrentMonData->m_shBORDER1.radiusOuter, outerRound == -1 ? round : outerRound);
glUniform1f(m_RenderData.pCurrentMonData->m_shBORDER1.thick, scaledBorderSize);
glVertexAttribPointer(m_RenderData.pCurrentMonData->m_shBORDER1.posAttrib, 2, GL_FLOAT, GL_FALSE, 0, fullVerts);
glVertexAttribPointer(m_RenderData.pCurrentMonData->m_shBORDER1.texAttrib, 2, GL_FLOAT, GL_FALSE, 0, fullVerts);
glEnableVertexAttribArray(m_RenderData.pCurrentMonData->m_shBORDER1.posAttrib);
glEnableVertexAttribArray(m_RenderData.pCurrentMonData->m_shBORDER1.texAttrib);
if (m_RenderData.clipBox.width != 0 && m_RenderData.clipBox.height != 0) {
CRegion damageClip{m_RenderData.clipBox.x, m_RenderData.clipBox.y, m_RenderData.clipBox.width, m_RenderData.clipBox.height};
damageClip.intersect(m_RenderData.damage);
if (!damageClip.empty()) {
for (auto const& RECT : damageClip.getRects()) {
scissor(&RECT);
glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
}
}
} else {
for (auto const& RECT : m_RenderData.damage.getRects()) {
scissor(&RECT);
glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
}
}
glDisableVertexAttribArray(m_RenderData.pCurrentMonData->m_shBORDER1.posAttrib);
glDisableVertexAttribArray(m_RenderData.pCurrentMonData->m_shBORDER1.texAttrib);
blend(BLEND);
}
void CHyprOpenGLImpl::renderBorder(CBox* box, const CGradientValueData& grad1, const CGradientValueData& grad2, float lerp, int round, int borderSize, float a, int outerRound) {
RASSERT((box->width > 0 && box->height > 0), "Tried to render rect with width/height < 0!");
RASSERT(m_RenderData.pMonitor, "Tried to render rect without begin()!");
TRACY_GPU_ZONE("RenderBorder2");
if (m_RenderData.damage.empty() || (m_pCurrentWindow.lock() && m_pCurrentWindow->m_sWindowData.noBorder.valueOrDefault()))
return;
CBox newBox = *box;
m_RenderData.renderModif.applyToBox(newBox);
box = &newBox;
if (borderSize < 1)
return;
int scaledBorderSize = std::round(borderSize * m_RenderData.pMonitor->scale);
scaledBorderSize = std::round(scaledBorderSize * m_RenderData.renderModif.combinedScale());
// adjust box
box->x -= scaledBorderSize;
box->y -= scaledBorderSize;
box->width += 2 * scaledBorderSize;
box->height += 2 * scaledBorderSize;
round += round == 0 ? 0 : scaledBorderSize;
Mat3x3 matrix = m_RenderData.monitorProjection.projectBox(
newBox, wlTransformToHyprutils(invertTransform(!m_bEndFrame ? WL_OUTPUT_TRANSFORM_NORMAL : m_RenderData.pMonitor->transform)), newBox.rot);
Mat3x3 glMatrix = m_RenderData.projection.copy().multiply(matrix);
const auto BLEND = m_bBlend;
blend(true);
glUseProgram(m_RenderData.pCurrentMonData->m_shBORDER1.program);
#ifndef GLES2
glUniformMatrix3fv(m_RenderData.pCurrentMonData->m_shBORDER1.proj, 1, GL_TRUE, glMatrix.getMatrix().data());
#else
glMatrix.transpose();
glUniformMatrix3fv(m_RenderData.pCurrentMonData->m_shBORDER1.proj, 1, GL_FALSE, glMatrix.getMatrix().data());
#endif
glUniform4fv(m_RenderData.pCurrentMonData->m_shBORDER1.gradient, grad1.m_vColorsOkLabA.size(), (float*)grad1.m_vColorsOkLabA.data());
glUniform1i(m_RenderData.pCurrentMonData->m_shBORDER1.gradientLength, grad1.m_vColorsOkLabA.size() / 4);
glUniform1f(m_RenderData.pCurrentMonData->m_shBORDER1.angle, (int)(grad1.m_fAngle / (PI / 180.0)) % 360 * (PI / 180.0));
glUniform4fv(m_RenderData.pCurrentMonData->m_shBORDER1.gradient2, grad2.m_vColorsOkLabA.size(), (float*)grad2.m_vColorsOkLabA.data());
glUniform1i(m_RenderData.pCurrentMonData->m_shBORDER1.gradient2Length, grad2.m_vColorsOkLabA.size() / 4);
glUniform1f(m_RenderData.pCurrentMonData->m_shBORDER1.angle2, (int)(grad2.m_fAngle / (PI / 180.0)) % 360 * (PI / 180.0));
glUniform1f(m_RenderData.pCurrentMonData->m_shBORDER1.alpha, a);
glUniform1f(m_RenderData.pCurrentMonData->m_shBORDER1.gradientLerp, lerp);
CBox transformedBox = *box;
transformedBox.transform(wlTransformToHyprutils(invertTransform(m_RenderData.pMonitor->transform)), m_RenderData.pMonitor->vecTransformedSize.x,
@ -2253,7 +2360,7 @@ void CHyprOpenGLImpl::makeRawWindowSnapshot(PHLWINDOW pWindow, CFramebuffer* pFr
g_pHyprRenderer->beginRender(PMONITOR, fakeDamage, RENDER_MODE_FULL_FAKE, nullptr, pFramebuffer);
clear(CColor(0, 0, 0, 0)); // JIC
clear(CHyprColor(0, 0, 0, 0)); // JIC
timespec now;
clock_gettime(CLOCK_MONOTONIC, &now);
@ -2272,7 +2379,7 @@ void CHyprOpenGLImpl::makeRawWindowSnapshot(PHLWINDOW pWindow, CFramebuffer* pFr
m_RenderData.currentFB = pFramebuffer;
clear(CColor(0, 0, 0, 0)); // JIC
clear(CHyprColor(0, 0, 0, 0)); // JIC
g_pHyprRenderer->renderWindow(pWindow, PMONITOR, &now, false, RENDER_PASS_ALL, true);
@ -2308,7 +2415,7 @@ void CHyprOpenGLImpl::makeWindowSnapshot(PHLWINDOW pWindow) {
g_pHyprRenderer->m_bRenderingSnapshot = true;
clear(CColor(0, 0, 0, 0)); // JIC
clear(CHyprColor(0, 0, 0, 0)); // JIC
timespec now;
clock_gettime(CLOCK_MONOTONIC, &now);
@ -2322,7 +2429,7 @@ void CHyprOpenGLImpl::makeWindowSnapshot(PHLWINDOW pWindow) {
const auto BLURVAL = **PBLUR;
**PBLUR = 0;
clear(CColor(0, 0, 0, 0)); // JIC
clear(CHyprColor(0, 0, 0, 0)); // JIC
g_pHyprRenderer->renderWindow(pWindow, PMONITOR, &now, !pWindow->m_bX11DoesntWantBorders, RENDER_PASS_ALL);
@ -2355,7 +2462,7 @@ void CHyprOpenGLImpl::makeLayerSnapshot(PHLLS pLayer) {
g_pHyprRenderer->m_bRenderingSnapshot = true;
clear(CColor(0, 0, 0, 0)); // JIC
clear(CHyprColor(0, 0, 0, 0)); // JIC
timespec now;
clock_gettime(CLOCK_MONOTONIC, &now);
@ -2405,7 +2512,7 @@ void CHyprOpenGLImpl::renderSnapshot(PHLWINDOW pWindow) {
if (*PDIMAROUND && pWindow->m_sWindowData.dimAround.valueOrDefault()) {
CBox monbox = {0, 0, g_pHyprOpenGL->m_RenderData.pMonitor->vecPixelSize.x, g_pHyprOpenGL->m_RenderData.pMonitor->vecPixelSize.y};
g_pHyprOpenGL->renderRect(&monbox, CColor(0, 0, 0, *PDIMAROUND * pWindow->m_fAlpha.value()));
g_pHyprOpenGL->renderRect(&monbox, CHyprColor(0, 0, 0, *PDIMAROUND * pWindow->m_fAlpha.value()));
g_pHyprRenderer->damageMonitor(PMONITOR);
}
@ -2449,7 +2556,7 @@ void CHyprOpenGLImpl::renderSnapshot(PHLLS pLayer) {
m_bEndFrame = false;
}
void CHyprOpenGLImpl::renderRoundedShadow(CBox* box, int round, int range, const CColor& color, float a) {
void CHyprOpenGLImpl::renderRoundedShadow(CBox* box, int round, int range, const CHyprColor& color, float a) {
RASSERT(m_RenderData.pMonitor, "Tried to render shadow without begin()!");
RASSERT((box->width > 0 && box->height > 0), "Tried to render shadow with width/height < 0!");
RASSERT(m_pCurrentWindow.lock(), "Tried to render shadow without a window!");
@ -2568,7 +2675,7 @@ void CHyprOpenGLImpl::renderMirrored() {
.translate(-monitor->vecTransformedSize / 2.0);
// clear stuff outside of mirrored area (e.g. when changing to mirrored)
clear(CColor(0, 0, 0, 0));
clear(CHyprColor(0, 0, 0, 0));
renderTexture(PFB->getTexture(), &monbox, 1.f, 0, false, false);
@ -2583,7 +2690,7 @@ void CHyprOpenGLImpl::renderSplash(cairo_t* const CAIRO, cairo_surface_t* const
const auto FONTFAMILY = *PSPLASHFONT != STRVAL_EMPTY ? *PSPLASHFONT : *FALLBACKFONT;
const auto FONTSIZE = (int)(size.y / 76);
const auto COLOR = CColor(*PSPLASHCOLOR);
const auto COLOR = CHyprColor(*PSPLASHCOLOR);
PangoLayout* layoutText = pango_cairo_create_layout(CAIRO);
PangoFontDescription* pangoFD = pango_font_description_new();
@ -2671,7 +2778,7 @@ SP<CTexture> CHyprOpenGLImpl::loadAsset(const std::string& filename) {
return tex;
}
SP<CTexture> CHyprOpenGLImpl::renderText(const std::string& text, CColor col, int pt, bool italic) {
SP<CTexture> CHyprOpenGLImpl::renderText(const std::string& text, CHyprColor col, int pt, bool italic) {
SP<CTexture> tex = makeShared<CTexture>();
static auto FONT = CConfigValue<std::string>("misc:font_family");
@ -2804,7 +2911,7 @@ void CHyprOpenGLImpl::initAssets() {
g_pCompositor->m_pAqBackend->hasSession() && g_pCompositor->m_pAqBackend->session->vt > 0 ?
std::to_string(g_pCompositor->m_pAqBackend->session->vt) :
"unknown"),
CColor{0.9F, 0.9F, 0.9F, 0.7F}, 20, true);
CHyprColor{0.9F, 0.9F, 0.9F, 0.7F}, 20, true);
// create the default background texture
{
@ -2889,7 +2996,7 @@ void CHyprOpenGLImpl::createBGTextureForMonitor(PHLMONITOR pMonitor) {
CRegion fakeDamage{0, 0, INT16_MAX, INT16_MAX};
blend(true);
clear(CColor{0, 0, 0, 1});
clear(CHyprColor{0, 0, 0, 1});
// first render the background
if (m_pBackgroundTexture) {
@ -2981,7 +3088,7 @@ void CHyprOpenGLImpl::restoreMatrix() {
void CHyprOpenGLImpl::bindOffMain() {
m_RenderData.pCurrentMonData->offMainFB.bind();
clear(CColor(0, 0, 0, 0));
clear(CHyprColor(0, 0, 0, 0));
m_RenderData.currentFB = &m_RenderData.pCurrentMonData->offMainFB;
}

View file

@ -153,15 +153,16 @@ class CHyprOpenGLImpl {
void beginSimple(PHLMONITOR, const CRegion& damage, SP<CRenderbuffer> rb = nullptr, CFramebuffer* fb = nullptr);
void end();
void renderRect(CBox*, const CColor&, int round = 0);
void renderRectWithBlur(CBox*, const CColor&, int round = 0, float blurA = 1.f, bool xray = false);
void renderRectWithDamage(CBox*, const CColor&, CRegion* damage, int round = 0);
void renderRect(CBox*, const CHyprColor&, int round = 0);
void renderRectWithBlur(CBox*, const CHyprColor&, int round = 0, float blurA = 1.f, bool xray = false);
void renderRectWithDamage(CBox*, const CHyprColor&, CRegion* damage, int round = 0);
void renderTexture(SP<CTexture>, CBox*, float a, int round = 0, bool discardActive = false, bool allowCustomUV = false);
void renderTextureWithDamage(SP<CTexture>, CBox*, CRegion* damage, float a, int round = 0, bool discardActive = false, bool allowCustomUV = false,
SP<CSyncTimeline> waitTimeline = nullptr, uint64_t waitPoint = 0);
void renderTextureWithBlur(SP<CTexture>, CBox*, float a, SP<CWLSurfaceResource> pSurface, int round = 0, bool blockBlurOptimization = false, float blurA = 1.f);
void renderRoundedShadow(CBox*, int round, int range, const CColor& color, float a = 1.0);
void renderRoundedShadow(CBox*, int round, int range, const CHyprColor& color, float a = 1.0);
void renderBorder(CBox*, const CGradientValueData&, int round, int borderSize, float a = 1.0, int outerRound = -1 /* use round */);
void renderBorder(CBox*, const CGradientValueData&, const CGradientValueData&, float lerp, int round, int borderSize, float a = 1.0, int outerRound = -1 /* use round */);
void renderTextureMatte(SP<CTexture> tex, CBox* pBox, CFramebuffer& matte);
void setMonitorTransformEnabled(bool enabled);
@ -180,7 +181,7 @@ class CHyprOpenGLImpl {
void renderSnapshot(PHLLS);
bool shouldUseNewBlurOptimizations(PHLLS pLayer, PHLWINDOW pWindow);
void clear(const CColor&);
void clear(const CHyprColor&);
void clearWithTex();
void scissor(const CBox*, bool transform = true);
void scissor(const pixman_box32*, bool transform = true);
@ -289,7 +290,7 @@ class CHyprOpenGLImpl {
void initEGL(bool gbm);
EGLDeviceEXT eglDeviceFromDRMFD(int drmFD);
SP<CTexture> loadAsset(const std::string& file);
SP<CTexture> renderText(const std::string& text, CColor col, int pt, bool italic = false);
SP<CTexture> renderText(const std::string& text, CHyprColor col, int pt, bool italic = false);
void initAssets();
void initMissingAssetTexture();

View file

@ -619,7 +619,7 @@ void CHyprRenderer::renderWindow(PHLWINDOW pWindow, PHLMONITOR pMonitor, timespe
if (*PDIMAROUND && pWindow->m_sWindowData.dimAround.valueOrDefault() && !m_bRenderingSnapshot && mode != RENDER_PASS_POPUP) {
CBox monbox = {0, 0, g_pHyprOpenGL->m_RenderData.pMonitor->vecTransformedSize.x, g_pHyprOpenGL->m_RenderData.pMonitor->vecTransformedSize.y};
g_pHyprOpenGL->renderRect(&monbox, CColor(0, 0, 0, *PDIMAROUND * renderdata.alpha * renderdata.fadeAlpha));
g_pHyprOpenGL->renderRect(&monbox, CHyprColor(0, 0, 0, *PDIMAROUND * renderdata.alpha * renderdata.fadeAlpha));
}
renderdata.x += pWindow->m_vFloatingOffset.x;
@ -668,7 +668,7 @@ void CHyprRenderer::renderWindow(PHLWINDOW pWindow, PHLMONITOR pMonitor, timespe
if (!pWindow->m_sWindowData.noBlur.valueOrDefault() && pWindow->m_pWLSurface->small() && !pWindow->m_pWLSurface->m_bFillIgnoreSmall && renderdata.blur && *PBLUR) {
CBox wb = {renderdata.x - pMonitor->vecPosition.x, renderdata.y - pMonitor->vecPosition.y, renderdata.w, renderdata.h};
wb.scale(pMonitor->scale).round();
g_pHyprOpenGL->renderRectWithBlur(&wb, CColor(0, 0, 0, 0), renderdata.dontRound ? 0 : renderdata.rounding - 1, renderdata.fadeAlpha,
g_pHyprOpenGL->renderRectWithBlur(&wb, CHyprColor(0, 0, 0, 0), renderdata.dontRound ? 0 : renderdata.rounding - 1, renderdata.fadeAlpha,
g_pHyprOpenGL->shouldUseNewBlurOptimizations(nullptr, pWindow));
renderdata.blur = false;
}
@ -780,7 +780,7 @@ void CHyprRenderer::renderLayer(PHLLS pLayer, PHLMONITOR pMonitor, timespec* tim
if (*PDIMAROUND && pLayer->dimAround && !m_bRenderingSnapshot && !popups) {
CBox monbox = {0, 0, g_pHyprOpenGL->m_RenderData.pMonitor->vecTransformedSize.x, g_pHyprOpenGL->m_RenderData.pMonitor->vecTransformedSize.y};
g_pHyprOpenGL->renderRect(&monbox, CColor(0, 0, 0, *PDIMAROUND * pLayer->alpha.value()));
g_pHyprOpenGL->renderRect(&monbox, CHyprColor(0, 0, 0, *PDIMAROUND * pLayer->alpha.value()));
}
if (pLayer->fadingOut) {
@ -919,7 +919,7 @@ void CHyprRenderer::renderAllClientsForWorkspace(PHLMONITOR pMonitor, PHLWORKSPA
g_pHyprOpenGL->blend(false);
if (!canSkipBackBufferClear(pMonitor)) {
if (*PRENDERTEX /* inverted cfg flag */)
g_pHyprOpenGL->clear(CColor(*PBACKGROUNDCOLOR));
g_pHyprOpenGL->clear(CHyprColor(*PBACKGROUNDCOLOR));
else
g_pHyprOpenGL->clearWithTex(); // will apply the hypr "wallpaper"
}
@ -959,7 +959,7 @@ void CHyprRenderer::renderAllClientsForWorkspace(PHLMONITOR pMonitor, PHLWORKSPA
g_pHyprOpenGL->blend(false);
if (!canSkipBackBufferClear(pMonitor)) {
if (*PRENDERTEX /* inverted cfg flag */)
g_pHyprOpenGL->clear(CColor(*PBACKGROUNDCOLOR));
g_pHyprOpenGL->clear(CHyprColor(*PBACKGROUNDCOLOR));
else
g_pHyprOpenGL->clearWithTex(); // will apply the hypr "wallpaper"
}
@ -995,12 +995,12 @@ void CHyprRenderer::renderAllClientsForWorkspace(PHLMONITOR pMonitor, PHLWORKSPA
if (*PDIMSPECIAL != 0.f) {
CBox monbox = {translate.x, translate.y, pMonitor->vecTransformedSize.x * scale, pMonitor->vecTransformedSize.y * scale};
g_pHyprOpenGL->renderRect(&monbox, CColor(0, 0, 0, *PDIMSPECIAL * (ANIMOUT ? (1.0 - SPECIALANIMPROGRS) : SPECIALANIMPROGRS)));
g_pHyprOpenGL->renderRect(&monbox, CHyprColor(0, 0, 0, *PDIMSPECIAL * (ANIMOUT ? (1.0 - SPECIALANIMPROGRS) : SPECIALANIMPROGRS)));
}
if (*PBLURSPECIAL && *PBLUR) {
CBox monbox = {translate.x, translate.y, pMonitor->vecTransformedSize.x * scale, pMonitor->vecTransformedSize.y * scale};
g_pHyprOpenGL->renderRectWithBlur(&monbox, CColor(0, 0, 0, 0), 0, (ANIMOUT ? (1.0 - SPECIALANIMPROGRS) : SPECIALANIMPROGRS));
g_pHyprOpenGL->renderRectWithBlur(&monbox, CHyprColor(0, 0, 0, 0), 0, (ANIMOUT ? (1.0 - SPECIALANIMPROGRS) : SPECIALANIMPROGRS));
}
break;
@ -1447,7 +1447,7 @@ void CHyprRenderer::renderMonitor(PHLMONITOR pMonitor) {
if (*PDAMAGEBLINK && damageBlinkCleanup == 0) {
CBox monrect = {0, 0, pMonitor->vecTransformedSize.x, pMonitor->vecTransformedSize.y};
g_pHyprOpenGL->renderRect(&monrect, CColor(1.0, 0.0, 1.0, 100.0 / 255.0), 0);
g_pHyprOpenGL->renderRect(&monrect, CHyprColor(1.0, 0.0, 1.0, 100.0 / 255.0), 0);
damageBlinkCleanup = 1;
} else if (*PDAMAGEBLINK) {
damageBlinkCleanup++;
@ -2526,7 +2526,7 @@ std::tuple<float, float, float> CHyprRenderer::getRenderTimes(PHLMONITOR pMonito
static int handleCrashLoop(void* data) {
g_pHyprNotificationOverlay->addNotification("Hyprland will crash in " + std::to_string(10 - (int)(g_pHyprRenderer->m_fCrashingDistort * 2.f)) + "s.", CColor(0), 5000,
g_pHyprNotificationOverlay->addNotification("Hyprland will crash in " + std::to_string(10 - (int)(g_pHyprRenderer->m_fCrashingDistort * 2.f)) + "s.", CHyprColor(0), 5000,
ICON_INFO);
g_pHyprRenderer->m_fCrashingDistort += 0.5f;
@ -2540,7 +2540,7 @@ static int handleCrashLoop(void* data) {
}
void CHyprRenderer::initiateManualCrash() {
g_pHyprNotificationOverlay->addNotification("Manual crash initiated. Farewell...", CColor(0), 5000, ICON_INFO);
g_pHyprNotificationOverlay->addNotification("Manual crash initiated. Farewell...", CHyprColor(0), 5000, ICON_INFO);
m_pCrashingLoop = wl_event_loop_add_timer(g_pCompositor->m_sWLEventLoop, handleCrashLoop, nullptr);
wl_event_source_timer_update(m_pCrashingLoop, 1000);

View file

@ -38,9 +38,13 @@ class CShader {
GLint applyTint = -1;
GLint tint = -1;
GLint gradient = -1;
GLint gradientLength = -1;
GLint angle = -1;
GLint gradient = -1;
GLint gradientLength = -1;
GLint angle = -1;
GLint gradient2 = -1;
GLint gradient2Length = -1;
GLint angle2 = -1;
GLint gradientLerp = -1;
float initialTime = 0;
GLint time = -1;

View file

@ -60,7 +60,6 @@ void CHyprBorderDecoration::draw(PHLMONITOR pMonitor, float const& a) {
auto grad = m_pWindow->m_cRealBorderColor;
const bool ANIMATED = m_pWindow->m_fBorderFadeAnimationProgress.isBeingAnimated();
float a1 = a * (ANIMATED ? m_pWindow->m_fBorderFadeAnimationProgress.value() : 1.f);
if (m_pWindow->m_fBorderAngleAnimationProgress.getConfig()->pValues->internalEnabled) {
grad.m_fAngle += m_pWindow->m_fBorderAngleAnimationProgress.value() * M_PI * 2;
@ -70,12 +69,10 @@ void CHyprBorderDecoration::draw(PHLMONITOR pMonitor, float const& a) {
int borderSize = m_pWindow->getRealBorderSize();
const auto ROUNDING = m_pWindow->rounding() * pMonitor->scale;
g_pHyprOpenGL->renderBorder(&windowBox, grad, ROUNDING, borderSize, a1);
if (ANIMATED) {
float a2 = a * (1.f - m_pWindow->m_fBorderFadeAnimationProgress.value());
g_pHyprOpenGL->renderBorder(&windowBox, m_pWindow->m_cRealBorderColorPrevious, ROUNDING, borderSize, a2);
}
if (ANIMATED)
g_pHyprOpenGL->renderBorder(&windowBox, m_pWindow->m_cRealBorderColorPrevious, grad, m_pWindow->m_fBorderFadeAnimationProgress.value(), ROUNDING, borderSize, a);
else
g_pHyprOpenGL->renderBorder(&windowBox, grad, ROUNDING, borderSize, a);
}
eDecorationType CHyprBorderDecoration::getDecorationType() {

View file

@ -93,7 +93,7 @@ void CHyprDropShadowDecoration::draw(PHLMONITOR pMonitor, float const& a) {
if (!validMapped(PWINDOW))
return;
if (PWINDOW->m_cRealShadowColor.value() == CColor(0, 0, 0, 0))
if (PWINDOW->m_cRealShadowColor.value() == CHyprColor(0, 0, 0, 0))
return; // don't draw invisible shadows
if (!PWINDOW->m_sWindowData.decorate.valueOrDefault())
@ -181,13 +181,13 @@ void CHyprDropShadowDecoration::draw(PHLMONITOR pMonitor, float const& a) {
// build the matte
// 10-bit formats have dogshit alpha channels, so we have to use the matte to its fullest.
// first, clear region of interest with black (fully transparent)
g_pHyprOpenGL->renderRect(&fullBox, CColor(0, 0, 0, 1), 0);
g_pHyprOpenGL->renderRect(&fullBox, CHyprColor(0, 0, 0, 1), 0);
// render white shadow with the alpha of the shadow color (otherwise we clear with alpha later and shit it to 2 bit)
drawShadowInternal(&fullBox, ROUNDING * pMonitor->scale, *PSHADOWSIZE * pMonitor->scale, CColor(1, 1, 1, PWINDOW->m_cRealShadowColor.value().a), a);
drawShadowInternal(&fullBox, ROUNDING * pMonitor->scale, *PSHADOWSIZE * pMonitor->scale, CHyprColor(1, 1, 1, PWINDOW->m_cRealShadowColor.value().a), a);
// render black window box ("clip")
g_pHyprOpenGL->renderRect(&windowBox, CColor(0, 0, 0, 1.0), (ROUNDING + 1 /* This fixes small pixel gaps. */) * pMonitor->scale);
g_pHyprOpenGL->renderRect(&windowBox, CHyprColor(0, 0, 0, 1.0), (ROUNDING + 1 /* This fixes small pixel gaps. */) * pMonitor->scale);
alphaSwapFB.bind();
@ -215,7 +215,7 @@ eDecorationLayer CHyprDropShadowDecoration::getDecorationLayer() {
return DECORATION_LAYER_BOTTOM;
}
void CHyprDropShadowDecoration::drawShadowInternal(CBox* box, int round, int range, CColor color, float a) {
void CHyprDropShadowDecoration::drawShadowInternal(CBox* box, int round, int range, CHyprColor color, float a) {
static auto PSHADOWSHARP = CConfigValue<Hyprlang::INT>("decoration:shadow:sharp");
g_pHyprOpenGL->blend(true);

View file

@ -34,7 +34,7 @@ class CHyprDropShadowDecoration : public IHyprWindowDecoration {
Vector2D m_vLastWindowPos;
Vector2D m_vLastWindowSize;
void drawShadowInternal(CBox* box, int round, int range, CColor color, float a);
void drawShadowInternal(CBox* box, int round, int range, CHyprColor color, float a);
CBox m_bLastWindowBox = {0};
CBox m_bLastWindowBoxWithDecos = {0};

View file

@ -147,7 +147,7 @@ void CHyprGroupBarDecoration::draw(PHLMONITOR pMonitor, float const& a) {
const auto* const PCOLACTIVE = GROUPLOCKED ? GROUPCOLACTIVELOCKED : GROUPCOLACTIVE;
const auto* const PCOLINACTIVE = GROUPLOCKED ? GROUPCOLINACTIVELOCKED : GROUPCOLINACTIVE;
CColor color = m_dwGroupMembers[WINDOWINDEX].lock() == g_pCompositor->m_pLastWindow.lock() ? PCOLACTIVE->m_vColors[0] : PCOLINACTIVE->m_vColors[0];
CHyprColor color = m_dwGroupMembers[WINDOWINDEX].lock() == g_pCompositor->m_pLastWindow.lock() ? PCOLACTIVE->m_vColors[0] : PCOLINACTIVE->m_vColors[0];
color.a *= a;
g_pHyprOpenGL->renderRect(&rect, color);
@ -205,19 +205,19 @@ void CHyprGroupBarDecoration::invalidateTextures() {
}
CTitleTex::CTitleTex(PHLWINDOW pWindow, const Vector2D& bufferSize, const float monitorScale) {
tex = makeShared<CTexture>();
szContent = pWindow->m_szTitle;
pWindowOwner = pWindow;
const auto LAYOUTSURFACE = cairo_image_surface_create(CAIRO_FORMAT_ARGB32, 0, 0);
const auto LAYOUTCAIRO = cairo_create(LAYOUTSURFACE);
tex = makeShared<CTexture>();
szContent = pWindow->m_szTitle;
pWindowOwner = pWindow;
const auto LAYOUTSURFACE = cairo_image_surface_create(CAIRO_FORMAT_ARGB32, 0, 0);
const auto LAYOUTCAIRO = cairo_create(LAYOUTSURFACE);
static auto FALLBACKFONT = CConfigValue<std::string>("misc:font_family");
static auto PTITLEFONTFAMILY = CConfigValue<std::string>("group:groupbar:font_family");
static auto PTITLEFONTSIZE = CConfigValue<Hyprlang::INT>("group:groupbar:font_size");
static auto PTEXTCOLOR = CConfigValue<Hyprlang::INT>("group:groupbar:text_color");
static auto FALLBACKFONT = CConfigValue<std::string>("misc:font_family");
static auto PTITLEFONTFAMILY = CConfigValue<std::string>("group:groupbar:font_family");
static auto PTITLEFONTSIZE = CConfigValue<Hyprlang::INT>("group:groupbar:font_size");
static auto PTEXTCOLOR = CConfigValue<Hyprlang::INT>("group:groupbar:text_color");
const CColor COLOR = CColor(*PTEXTCOLOR);
const auto FONTFAMILY = *PTITLEFONTFAMILY != STRVAL_EMPTY ? *PTITLEFONTFAMILY : *FALLBACKFONT;
const CHyprColor COLOR = CHyprColor(*PTEXTCOLOR);
const auto FONTFAMILY = *PTITLEFONTFAMILY != STRVAL_EMPTY ? *PTITLEFONTFAMILY : *FALLBACKFONT;
cairo_surface_destroy(LAYOUTSURFACE);

View file

@ -17,12 +17,32 @@ uniform float radius;
uniform float radiusOuter;
uniform float thick;
// Gradients are in OkLabA!!!! {l, a, b, alpha}
uniform vec4 gradient[10];
uniform vec4 gradient2[10];
uniform int gradientLength;
uniform int gradient2Length;
uniform float angle;
uniform float angle2;
uniform float gradientLerp;
uniform float alpha;
vec4 getColorForCoord(vec2 normalizedCoord) {
float linearToGamma(float x) {
return x >= 0.0031308 ? 1.055 * pow(x, 0.416666666) - 0.055 : 12.92 * x;
}
vec4 okLabAToSrgb(vec4 lab) {
float l = pow(lab[0] + lab[1] * 0.3963377774 + lab[2] * 0.2158037573, 3.0);
float m = pow(lab[0] + lab[1] * (-0.1055613458) + lab[2] * (-0.0638541728), 3.0);
float s = pow(lab[0] + lab[1] * (-0.0894841775) + lab[2] * (-1.2914855480), 3.0);
return vec4(linearToGamma(l * 4.0767416621 + m * -3.3077115913 + s * 0.2309699292),
linearToGamma(l * (-1.2684380046) + m * 2.6097574011 + s * (-0.3413193965)),
linearToGamma(l * (-0.0041960863) + m * (-0.7034186147) + s * 1.7076147010),
lab[3]);
}
vec4 getOkColorForCoordArray1(vec2 normalizedCoord) {
if (gradientLength < 2)
return gradient[0];
@ -51,6 +71,46 @@ vec4 getColorForCoord(vec2 normalizedCoord) {
return gradient[top] * (progress - float(bottom)) + gradient[bottom] * (float(top) - progress);
}
vec4 getOkColorForCoordArray2(vec2 normalizedCoord) {
if (gradient2Length < 2)
return gradient2[0];
float finalAng = 0.0;
if (angle2 > 4.71 /* 270 deg */) {
normalizedCoord[1] = 1.0 - normalizedCoord[1];
finalAng = 6.28 - angle;
} else if (angle2 > 3.14 /* 180 deg */) {
normalizedCoord[0] = 1.0 - normalizedCoord[0];
normalizedCoord[1] = 1.0 - normalizedCoord[1];
finalAng = angle - 3.14;
} else if (angle2 > 1.57 /* 90 deg */) {
normalizedCoord[0] = 1.0 - normalizedCoord[0];
finalAng = 3.14 - angle2;
} else {
finalAng = angle2;
}
float sine = sin(finalAng);
float progress = (normalizedCoord[1] * sine + normalizedCoord[0] * (1.0 - sine)) * float(gradient2Length - 1);
int bottom = int(floor(progress));
int top = bottom + 1;
return gradient2[top] * (progress - float(bottom)) + gradient2[bottom] * (float(top) - progress);
}
vec4 getColorForCoord(vec2 normalizedCoord) {
vec4 result1 = getOkColorForCoordArray1(normalizedCoord);
if (gradient2Length <= 0)
return okLabAToSrgb(result1);
vec4 result2 = getOkColorForCoordArray2(normalizedCoord);
return okLabAToSrgb(mix(result1, result2, gradientLerp));
}
void main() {
highp vec2 pixCoord = vec2(gl_FragCoord);