Merge branch 'hyprwm:main' into main

This commit is contained in:
xDarksome 2022-06-26 19:20:20 +03:00 committed by GitHub
commit 504f76112a
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
41 changed files with 841 additions and 397 deletions

1
.github/FUNDING.yml vendored Normal file
View file

@ -0,0 +1 @@
ko_fi: vaxry

View file

@ -1,6 +1,6 @@
name: "Nix & Meson: update version" name: "Nix & Meson: update version"
on: [push, workflow_dispatch] on: [workflow_dispatch]
jobs: jobs:
update: update:

View file

@ -54,6 +54,7 @@ Try it out and report bugs / suggestions!
- Custom bezier curve based animations - Custom bezier curve based animations
- `wlr_ext` workspaces protocol support - `wlr_ext` workspaces protocol support
- Dual Kawase blur - Dual Kawase blur
- Drop shadows
- Fully dynamic workspaces - Fully dynamic workspaces
- Closely follows `wlroots-git` - Closely follows `wlroots-git`
- Bundled wlroots - Bundled wlroots

View file

@ -17,8 +17,7 @@ input {
} }
general { general {
max_fps=60 # deprecated, unused sensitivity=1.0 # for mouse cursor
sensitivity=0.25
main_mod=SUPER main_mod=SUPER
gaps_in=5 gaps_in=5
@ -27,7 +26,7 @@ general {
col.active_border=0x66ee1111 col.active_border=0x66ee1111
col.inactive_border=0x66333333 col.inactive_border=0x66333333
apply_sens_to_raw=0 # do not apply the sensitivity to raw input (e.g. used by games where you aim) apply_sens_to_raw=0 # whether to apply the sensitivity to raw input (e.g. used by games where you aim using your mouse)
damage_tracking=full # leave it on full unless you hate your GPU and want to make it suffer damage_tracking=full # leave it on full unless you hate your GPU and want to make it suffer
} }

View file

@ -32,7 +32,7 @@
src = inputs.wlroots; src = inputs.wlroots;
}); });
hyprland = prev.callPackage ./nix/default.nix { hyprland = prev.callPackage ./nix/default.nix {
version = "0.5.0beta" + "+date=" + (mkDate (self.lastModifiedDate or "19700101")); version = "0.6.0beta" + "+date=" + (mkDate (self.lastModifiedDate or "19700101"));
wlroots = wlroots-hyprland; wlroots = wlroots-hyprland;
}; };
}; };

View file

@ -1,5 +1,5 @@
project('Hyprland', 'cpp', 'c', project('Hyprland', 'cpp', 'c',
version : '0.5.0beta', version : '0.6.0beta',
default_options : ['warning_level=3', 'cpp_std=c++20', 'default_library=static']) default_options : ['warning_level=3', 'cpp_std=c++20', 'default_library=static'])
wlroots = subproject('wlroots', default_options: ['examples=false']) wlroots = subproject('wlroots', default_options: ['examples=false'])

View file

@ -7,6 +7,16 @@ CCompositor::CCompositor() {
Debug::log(LOG, "Instance Signature: %s", m_szInstanceSignature.c_str()); Debug::log(LOG, "Instance Signature: %s", m_szInstanceSignature.c_str());
Debug::log(LOG, "===== SYSTEM INFO: =====");
logSystemInfo();
Debug::log(LOG, "========================");
Debug::log(NONE, "\n\n"); // pad
Debug::log(INFO, "If you are crashing, or encounter any bugs, please consult https://github.com/hyprwm/Hyprland/wiki/Crashing-and-bugs\n\n");
setenv("HYPRLAND_INSTANCE_SIGNATURE", m_szInstanceSignature.c_str(), true); setenv("HYPRLAND_INSTANCE_SIGNATURE", m_szInstanceSignature.c_str(), true);
const auto INSTANCEPATH = "/tmp/hypr/" + m_szInstanceSignature; const auto INSTANCEPATH = "/tmp/hypr/" + m_szInstanceSignature;
@ -1106,3 +1116,17 @@ bool CCompositor::workspaceIDOutOfBounds(const int& id) {
return std::clamp(id, lowestID, highestID) != id; return std::clamp(id, lowestID, highestID) != id;
} }
void CCompositor::setWindowFullscreen(CWindow* pWindow, bool on, eFullscreenMode mode) {
if (!windowValidMapped(pWindow))
return;
g_pLayoutManager->getCurrentLayout()->fullscreenRequestForWindow(pWindow, mode, on);
g_pXWaylandManager->setWindowFullscreen(pWindow, pWindow->m_bIsFullscreen && mode == FULLSCREEN_FULL);
// make all windows on the same workspace under the fullscreen window
for (auto& w : g_pCompositor->m_lWindows) {
if (w.m_iWorkspaceID == pWindow->m_iWorkspaceID)
w.m_bCreatedOverFullscreen = false;
}
}

View file

@ -132,6 +132,7 @@ public:
int getNextAvailableMonitorID(); int getNextAvailableMonitorID();
void moveWorkspaceToMonitor(CWorkspace*, SMonitor*); void moveWorkspaceToMonitor(CWorkspace*, SMonitor*);
bool workspaceIDOutOfBounds(const int&); bool workspaceIDOutOfBounds(const int&);
void setWindowFullscreen(CWindow*, bool, eFullscreenMode);
private: private:
void initAllSignals(); void initAllSignals();

View file

@ -1,11 +1,14 @@
#include "Window.hpp" #include "Window.hpp"
#include "Compositor.hpp" #include "Compositor.hpp"
#include "render/decorations/CHyprDropShadowDecoration.hpp"
CWindow::CWindow() { CWindow::CWindow() {
m_vRealPosition.create(AVARTYPE_VECTOR, &g_pConfigManager->getConfigValuePtr("animations:windows_speed")->floatValue, &g_pConfigManager->getConfigValuePtr("animations:windows")->intValue, &g_pConfigManager->getConfigValuePtr("animations:windows_curve")->strValue, (void*) this, AVARDAMAGE_ENTIRE); m_vRealPosition.create(AVARTYPE_VECTOR, &g_pConfigManager->getConfigValuePtr("animations:windows_speed")->floatValue, &g_pConfigManager->getConfigValuePtr("animations:windows")->intValue, &g_pConfigManager->getConfigValuePtr("animations:windows_curve")->strValue, (void*) this, AVARDAMAGE_ENTIRE);
m_vRealSize.create(AVARTYPE_VECTOR, &g_pConfigManager->getConfigValuePtr("animations:windows_speed")->floatValue, &g_pConfigManager->getConfigValuePtr("animations:windows")->intValue, &g_pConfigManager->getConfigValuePtr("animations:windows_curve")->strValue, (void*)this, AVARDAMAGE_ENTIRE); m_vRealSize.create(AVARTYPE_VECTOR, &g_pConfigManager->getConfigValuePtr("animations:windows_speed")->floatValue, &g_pConfigManager->getConfigValuePtr("animations:windows")->intValue, &g_pConfigManager->getConfigValuePtr("animations:windows_curve")->strValue, (void*)this, AVARDAMAGE_ENTIRE);
m_cRealBorderColor.create(AVARTYPE_COLOR, &g_pConfigManager->getConfigValuePtr("animations:borders_speed")->floatValue, &g_pConfigManager->getConfigValuePtr("animations:borders")->intValue, &g_pConfigManager->getConfigValuePtr("animations:borders_curve")->strValue, (void*)this, AVARDAMAGE_BORDER); m_cRealBorderColor.create(AVARTYPE_COLOR, &g_pConfigManager->getConfigValuePtr("animations:borders_speed")->floatValue, &g_pConfigManager->getConfigValuePtr("animations:borders")->intValue, &g_pConfigManager->getConfigValuePtr("animations:borders_curve")->strValue, (void*)this, AVARDAMAGE_BORDER);
m_fAlpha.create(AVARTYPE_FLOAT, &g_pConfigManager->getConfigValuePtr("animations:fadein_speed")->floatValue, &g_pConfigManager->getConfigValuePtr("animations:fadein")->intValue, &g_pConfigManager->getConfigValuePtr("animations:fadein_curve")->strValue, (void*)this, AVARDAMAGE_ENTIRE); m_fAlpha.create(AVARTYPE_FLOAT, &g_pConfigManager->getConfigValuePtr("animations:fadein_speed")->floatValue, &g_pConfigManager->getConfigValuePtr("animations:fadein")->intValue, &g_pConfigManager->getConfigValuePtr("animations:fadein_curve")->strValue, (void*)this, AVARDAMAGE_ENTIRE);
m_dWindowDecorations.emplace_back(std::make_unique<CHyprDropShadowDecoration>(this)); // put the shadow so it's the first deco (has to be rendered first)
} }
CWindow::~CWindow() { CWindow::~CWindow() {
@ -16,8 +19,9 @@ CWindow::~CWindow() {
} }
wlr_box CWindow::getFullWindowBoundingBox() { wlr_box CWindow::getFullWindowBoundingBox() {
static auto* const PBORDERSIZE = &g_pConfigManager->getConfigValuePtr("general:border_size")->intValue;
SWindowDecorationExtents maxExtents; SWindowDecorationExtents maxExtents = {{*PBORDERSIZE + 1, *PBORDERSIZE + 1}, {*PBORDERSIZE + 1, *PBORDERSIZE + 1}};
for (auto& wd : m_dWindowDecorations) { for (auto& wd : m_dWindowDecorations) {

View file

@ -15,6 +15,7 @@ struct SWindowSpecialRenderData {
struct SWindowAdditionalConfigData { struct SWindowAdditionalConfigData {
std::string animationStyle = ""; std::string animationStyle = "";
int rounding = -1; // -1 means no int rounding = -1; // -1 means no
bool forceNoBlur = false;
}; };
class CWindow { class CWindow {

View file

@ -18,14 +18,14 @@ CConfigManager::CConfigManager() {
} }
void CConfigManager::setDefaultVars() { void CConfigManager::setDefaultVars() {
configValues["general:max_fps"].intValue = 240; configValues["general:max_fps"].intValue = 60;
configValues["general:sensitivity"].floatValue = 0.25f; configValues["general:sensitivity"].floatValue = 1.0f;
configValues["general:apply_sens_to_raw"].intValue = 0; configValues["general:apply_sens_to_raw"].intValue = 0;
configValues["general:main_mod"].strValue = "SUPER"; // exposed to the user for easier configuring configValues["general:main_mod"].strValue = "SUPER"; // exposed to the user for easier configuring
configValues["general:main_mod_internal"].intValue = g_pKeybindManager->stringToModMask("SUPER"); // actually used and automatically calculated configValues["general:main_mod_internal"].intValue = g_pKeybindManager->stringToModMask("SUPER"); // actually used and automatically calculated
configValues["general:damage_tracking"].strValue = "none"; configValues["general:damage_tracking"].strValue = "full";
configValues["general:damage_tracking_internal"].intValue = DAMAGE_TRACKING_NONE; configValues["general:damage_tracking_internal"].intValue = DAMAGE_TRACKING_FULL;
configValues["general:border_size"].intValue = 1; configValues["general:border_size"].intValue = 1;
configValues["general:no_border_on_floating"].intValue = 0; configValues["general:no_border_on_floating"].intValue = 0;
@ -33,6 +33,7 @@ void CConfigManager::setDefaultVars() {
configValues["general:gaps_out"].intValue = 20; configValues["general:gaps_out"].intValue = 20;
configValues["general:col.active_border"].intValue = 0xffffffff; configValues["general:col.active_border"].intValue = 0xffffffff;
configValues["general:col.inactive_border"].intValue = 0xff444444; configValues["general:col.inactive_border"].intValue = 0xff444444;
configValues["general:cursor_inactive_timeout"].intValue = 0;
configValues["debug:int"].intValue = 0; configValues["debug:int"].intValue = 0;
configValues["debug:log_damage"].intValue = 0; configValues["debug:log_damage"].intValue = 0;
@ -48,6 +49,11 @@ void CConfigManager::setDefaultVars() {
configValues["decoration:fullscreen_opacity"].floatValue = 1; configValues["decoration:fullscreen_opacity"].floatValue = 1;
configValues["decoration:multisample_edges"].intValue = 0; configValues["decoration:multisample_edges"].intValue = 0;
configValues["decoration:no_blur_on_oversized"].intValue = 1; configValues["decoration:no_blur_on_oversized"].intValue = 1;
configValues["decoration:drop_shadow"].intValue = 1;
configValues["decoration:shadow_range"].intValue = 4;
configValues["decoration:shadow_render_power"].intValue = 3;
configValues["decoration:shadow_ignore_window"].intValue = 1;
configValues["decoration:col.shadow"].intValue = 0xee1a1a1a;
configValues["dwindle:pseudotile"].intValue = 0; configValues["dwindle:pseudotile"].intValue = 0;
configValues["dwindle:col.group_border"].intValue = 0x66777700; configValues["dwindle:col.group_border"].intValue = 0x66777700;
@ -76,7 +82,7 @@ void CConfigManager::setDefaultVars() {
configValues["animations:workspaces_speed"].floatValue = 0.f; configValues["animations:workspaces_speed"].floatValue = 0.f;
configValues["animations:workspaces"].intValue = 1; configValues["animations:workspaces"].intValue = 1;
configValues["input:kb_layout"].strValue = "en"; configValues["input:kb_layout"].strValue = "us";
configValues["input:kb_variant"].strValue = STRVAL_EMPTY; configValues["input:kb_variant"].strValue = STRVAL_EMPTY;
configValues["input:kb_options"].strValue = STRVAL_EMPTY; configValues["input:kb_options"].strValue = STRVAL_EMPTY;
configValues["input:kb_rules"].strValue = STRVAL_EMPTY; configValues["input:kb_rules"].strValue = STRVAL_EMPTY;
@ -481,7 +487,9 @@ void CConfigManager::handleWindowRule(const std::string& command, const std::str
&& RULE.find("size") != 0 && RULE.find("size") != 0
&& RULE.find("pseudo") != 0 && RULE.find("pseudo") != 0
&& RULE.find("monitor") != 0 && RULE.find("monitor") != 0
&& RULE.find("nofocus") != 0 && RULE != "nofocus"
&& RULE != "noblur"
&& RULE != "fullscreen"
&& RULE.find("animation") != 0 && RULE.find("animation") != 0
&& RULE.find("rounding") != 0 && RULE.find("rounding") != 0
&& RULE.find("workspace") != 0) { && RULE.find("workspace") != 0) {

View file

@ -24,8 +24,7 @@ input {
} }
general { general {
max_fps=60 # deprecated, unused sensitivity=1.0 # for mouse cursor
sensitivity=0.25
main_mod=SUPER main_mod=SUPER
gaps_in=5 gaps_in=5
@ -34,7 +33,7 @@ general {
col.active_border=0x66ee1111 col.active_border=0x66ee1111
col.inactive_border=0x66333333 col.inactive_border=0x66333333
apply_sens_to_raw=0 # do not apply the sensitivity to raw input (e.g. used by games where you aim) apply_sens_to_raw=0 # whether to apply the sensitivity to raw input (e.g. used by games where you aim using your mouse)
damage_tracking=full # leave it on full unless you hate your GPU and want to make it suffer damage_tracking=full # leave it on full unless you hate your GPU and want to make it suffer
} }

View file

@ -31,6 +31,9 @@ void Debug::log(LogLevel level, const char* fmt, ...) {
case CRIT: case CRIT:
ofs << "[CRITICAL] "; ofs << "[CRITICAL] ";
break; break;
case INFO:
ofs << "[INFO] ";
break;
default: default:
break; break;
} }

View file

@ -8,7 +8,8 @@ enum LogLevel {
LOG = 0, LOG = 0,
WARN, WARN,
ERR, ERR,
CRIT CRIT,
INFO
}; };
namespace Debug { namespace Debug {

View file

@ -56,6 +56,15 @@ void Events::listener_mouseAxis(wl_listener* listener, void* data) {
void Events::listener_requestMouse(wl_listener* listener, void* data) { void Events::listener_requestMouse(wl_listener* listener, void* data) {
const auto EVENT = (wlr_seat_pointer_request_set_cursor_event*)data; const auto EVENT = (wlr_seat_pointer_request_set_cursor_event*)data;
if (!g_pHyprRenderer->shouldRenderCursor())
return;
if (!EVENT->surface) {
g_pHyprRenderer->m_bWindowRequestedCursorHide = true;
} else {
g_pHyprRenderer->m_bWindowRequestedCursorHide = false;
}
if (EVENT->seat_client == g_pCompositor->m_sSeat.seat->pointer_state.focused_client) if (EVENT->seat_client == g_pCompositor->m_sSeat.seat->pointer_state.focused_client)
wlr_cursor_set_surface(g_pCompositor->m_sWLRCursor, EVENT->surface, EVENT->hotspot_x, EVENT->hotspot_y); wlr_cursor_set_surface(g_pCompositor->m_sWLRCursor, EVENT->surface, EVENT->hotspot_x, EVENT->hotspot_y);
} }

View file

@ -193,6 +193,8 @@ void Events::listener_monitorFrame(void* owner, void* data) {
if (g_pConfigManager->m_bWantsMonitorReload) if (g_pConfigManager->m_bWantsMonitorReload)
g_pConfigManager->performMonitorReload(); g_pConfigManager->performMonitorReload();
g_pHyprRenderer->ensureCursorRenderingMode(); // so that the cursor gets hidden/shown if the user requested timeouts
} }
if (PMONITOR->framesToSkip > 0) { if (PMONITOR->framesToSkip > 0) {

View file

@ -78,7 +78,7 @@ void Events::listener_mapWindow(void* owner, void* data) {
if (PWORKSPACE->m_bHasFullscreenWindow && !PWINDOW->m_bIsFloating) { if (PWORKSPACE->m_bHasFullscreenWindow && !PWINDOW->m_bIsFloating) {
const auto PFULLWINDOW = g_pCompositor->getFullscreenWindowOnWorkspace(PWORKSPACE->m_iID); const auto PFULLWINDOW = g_pCompositor->getFullscreenWindowOnWorkspace(PWORKSPACE->m_iID);
g_pLayoutManager->getCurrentLayout()->fullscreenRequestForWindow(PFULLWINDOW, FULLSCREEN_FULL); g_pLayoutManager->getCurrentLayout()->fullscreenRequestForWindow(PFULLWINDOW, FULLSCREEN_FULL, false);
g_pXWaylandManager->setWindowFullscreen(PFULLWINDOW, PFULLWINDOW->m_bIsFullscreen); g_pXWaylandManager->setWindowFullscreen(PFULLWINDOW, PFULLWINDOW->m_bIsFullscreen);
} }
@ -86,6 +86,7 @@ void Events::listener_mapWindow(void* owner, void* data) {
const auto WINDOWRULES = g_pConfigManager->getMatchingRules(PWINDOW); const auto WINDOWRULES = g_pConfigManager->getMatchingRules(PWINDOW);
std::string requestedWorkspace = ""; std::string requestedWorkspace = "";
bool workspaceSilent = false; bool workspaceSilent = false;
bool requestsFullscreen = false;
for (auto& r : WINDOWRULES) { for (auto& r : WINDOWRULES) {
if (r.szRule.find("monitor") == 0) { if (r.szRule.find("monitor") == 0) {
@ -127,6 +128,10 @@ void Events::listener_mapWindow(void* owner, void* data) {
PWINDOW->m_bIsPseudotiled = true; PWINDOW->m_bIsPseudotiled = true;
} else if (r.szRule.find("nofocus") == 0) { } else if (r.szRule.find("nofocus") == 0) {
PWINDOW->m_bNoFocus = true; PWINDOW->m_bNoFocus = true;
} else if (r.szRule == "noblur") {
PWINDOW->m_sAdditionalConfigData.forceNoBlur = true;
} else if (r.szRule == "fullscreen") {
requestsFullscreen = true;
} else if (r.szRule.find("rounding") == 0) { } else if (r.szRule.find("rounding") == 0) {
try { try {
PWINDOW->m_sAdditionalConfigData.rounding = std::stoi(r.szRule.substr(r.szRule.find_first_of(' ') + 1)); PWINDOW->m_sAdditionalConfigData.rounding = std::stoi(r.szRule.substr(r.szRule.find_first_of(' ') + 1));
@ -254,6 +259,10 @@ void Events::listener_mapWindow(void* owner, void* data) {
} }
} }
if (requestsFullscreen) {
g_pCompositor->setWindowFullscreen(PWINDOW, true, FULLSCREEN_FULL);
}
Debug::log(LOG, "Map request dispatched, monitor %s, xywh: %f %f %f %f", PMONITOR->szName.c_str(), PWINDOW->m_vRealPosition.goalv().x, PWINDOW->m_vRealPosition.goalv().y, PWINDOW->m_vRealSize.goalv().x, PWINDOW->m_vRealSize.goalv().y); Debug::log(LOG, "Map request dispatched, monitor %s, xywh: %f %f %f %f", PMONITOR->szName.c_str(), PWINDOW->m_vRealPosition.goalv().x, PWINDOW->m_vRealPosition.goalv().y, PWINDOW->m_vRealSize.goalv().x, PWINDOW->m_vRealSize.goalv().y);
} }
@ -384,9 +393,9 @@ void Events::listener_fullscreenWindow(void* owner, void* data) {
const auto REQUESTED = &PWINDOW->m_uSurface.xdg->toplevel->requested; const auto REQUESTED = &PWINDOW->m_uSurface.xdg->toplevel->requested;
if (REQUESTED->fullscreen != PWINDOW->m_bIsFullscreen) if (REQUESTED->fullscreen != PWINDOW->m_bIsFullscreen)
g_pLayoutManager->getCurrentLayout()->fullscreenRequestForWindow(PWINDOW, FULLSCREEN_FULL); g_pLayoutManager->getCurrentLayout()->fullscreenRequestForWindow(PWINDOW, FULLSCREEN_FULL, true);
} else { } else {
g_pLayoutManager->getCurrentLayout()->fullscreenRequestForWindow(PWINDOW, FULLSCREEN_FULL); g_pLayoutManager->getCurrentLayout()->fullscreenRequestForWindow(PWINDOW, FULLSCREEN_FULL, true);
} }
Debug::log(LOG, "Window %x fullscreen to %i", PWINDOW, PWINDOW->m_bIsFullscreen); Debug::log(LOG, "Window %x fullscreen to %i", PWINDOW, PWINDOW->m_bIsFullscreen);

View file

@ -2,6 +2,7 @@
#include "../defines.hpp" #include "../defines.hpp"
#include <algorithm> #include <algorithm>
#include "../Compositor.hpp" #include "../Compositor.hpp"
#include <sys/utsname.h>
void addWLSignal(wl_signal* pSignal, wl_listener* pListener, void* pOwner, std::string ownerString) { void addWLSignal(wl_signal* pSignal, wl_listener* pListener, void* pOwner, std::string ownerString) {
ASSERT(pSignal); ASSERT(pSignal);
@ -233,3 +234,34 @@ float vecToRectDistanceSquared(const Vector2D& vec, const Vector2D& p1, const Ve
const float DY = std::max((double)0, std::max(p1.y - vec.y, vec.y - p2.y)); const float DY = std::max((double)0, std::max(p1.y - vec.y, vec.y - p2.y));
return DX * DX + DY * DY; return DX * DX + DY * DY;
} }
// Execute a shell command and get the output
std::string execAndGet(const char* cmd) {
std::array<char, 128> buffer;
std::string result;
const std::unique_ptr<FILE, decltype(&pclose)> pipe(popen(cmd, "r"), pclose);
if (!pipe) {
Debug::log(ERR, "execAndGet: failed in pipe");
return "";
}
while (fgets(buffer.data(), buffer.size(), pipe.get()) != nullptr) {
result += buffer.data();
}
return result;
}
void logSystemInfo() {
struct utsname unameInfo;
uname(&unameInfo);
Debug::log(LOG, "System name: %s", unameInfo.sysname);
Debug::log(LOG, "Node name: %s", unameInfo.nodename);
Debug::log(LOG, "Release: %s", unameInfo.release);
Debug::log(LOG, "Version: %s", unameInfo.version);
// log etc
Debug::log(LOG, "os-release:");
Debug::log(NONE, "%s", execAndGet("cat /etc/os-release").c_str());
}

View file

@ -11,5 +11,7 @@ bool isNumber(const std::string&);
bool isDirection(const std::string&); bool isDirection(const std::string&);
int getWorkspaceIDFromString(const std::string&, std::string&); int getWorkspaceIDFromString(const std::string&, std::string&);
float vecToRectDistanceSquared(const Vector2D& vec, const Vector2D& p1, const Vector2D& p2); float vecToRectDistanceSquared(const Vector2D& vec, const Vector2D& p1, const Vector2D& p2);
void logSystemInfo();
std::string execAndGet(const char*);
float getPlusMinusKeywordResult(std::string in, float relative); float getPlusMinusKeywordResult(std::string in, float relative);

17
src/helpers/Timer.cpp Normal file
View file

@ -0,0 +1,17 @@
#include "Timer.hpp"
void CTimer::reset() {
m_tpLastReset = std::chrono::system_clock::now();
}
std::chrono::system_clock::duration CTimer::getDuration() {
return std::chrono::system_clock::now() - m_tpLastReset;
}
int CTimer::getMillis() {
return std::chrono::duration_cast<std::chrono::milliseconds>(getDuration()).count();
}
float CTimer::getSeconds() {
return std::chrono::duration_cast<std::chrono::milliseconds>(getDuration()).count() / 1000.f;
}

15
src/helpers/Timer.hpp Normal file
View file

@ -0,0 +1,15 @@
#pragma once
#include "../defines.hpp"
class CTimer {
public:
void reset();
float getSeconds();
int getMillis();
private:
std::chrono::system_clock::time_point m_tpLastReset;
std::chrono::system_clock::duration getDuration();
};

View file

@ -71,6 +71,8 @@ struct SKeyboard {
bool active = false; bool active = false;
xkb_rule_names currentRules;
// For the list lookup // For the list lookup
bool operator==(const SKeyboard& rhs) { bool operator==(const SKeyboard& rhs) {
return keyboard == rhs.keyboard; return keyboard == rhs.keyboard;

View file

@ -482,6 +482,9 @@ void CHyprDwindleLayout::onBeginDragWindow() {
void CHyprDwindleLayout::onEndDragWindow() { void CHyprDwindleLayout::onEndDragWindow() {
const auto DRAGGINGWINDOW = g_pInputManager->currentlyDraggedWindow; const auto DRAGGINGWINDOW = g_pInputManager->currentlyDraggedWindow;
if (!g_pCompositor->windowValidMapped(DRAGGINGWINDOW))
return;
if (DRAGGINGWINDOW->m_bDraggingTiled) { if (DRAGGINGWINDOW->m_bDraggingTiled) {
DRAGGINGWINDOW->m_bIsFloating = false; DRAGGINGWINDOW->m_bIsFloating = false;
changeWindowFloatingMode(DRAGGINGWINDOW); changeWindowFloatingMode(DRAGGINGWINDOW);
@ -494,8 +497,10 @@ void CHyprDwindleLayout::onMouseMove(const Vector2D& mousePos) {
const auto DRAGGINGWINDOW = g_pInputManager->currentlyDraggedWindow; const auto DRAGGINGWINDOW = g_pInputManager->currentlyDraggedWindow;
// Window invalid or drag begin size 0,0 meaning we rejected it. // Window invalid or drag begin size 0,0 meaning we rejected it.
if (!g_pCompositor->windowValidMapped(DRAGGINGWINDOW) || m_vBeginDragSizeXY == Vector2D()) if (!g_pCompositor->windowValidMapped(DRAGGINGWINDOW) || m_vBeginDragSizeXY == Vector2D()) {
g_pInputManager->currentlyDraggedWindow = nullptr;
return; return;
}
const auto DELTA = Vector2D(mousePos.x - m_vBeginDragXY.x, mousePos.y - m_vBeginDragXY.y); const auto DELTA = Vector2D(mousePos.x - m_vBeginDragXY.x, mousePos.y - m_vBeginDragXY.y);
const auto TICKDELTA = Vector2D(mousePos.x - m_vLastDragXY.x, mousePos.y - m_vLastDragXY.y); const auto TICKDELTA = Vector2D(mousePos.x - m_vLastDragXY.x, mousePos.y - m_vLastDragXY.y);
@ -671,21 +676,24 @@ void CHyprDwindleLayout::onWindowCreatedFloating(CWindow* pWindow) {
g_pCompositor->moveWindowToTop(pWindow); g_pCompositor->moveWindowToTop(pWindow);
} }
void CHyprDwindleLayout::fullscreenRequestForWindow(CWindow* pWindow, eFullscreenMode fullscreenMode) { void CHyprDwindleLayout::fullscreenRequestForWindow(CWindow* pWindow, eFullscreenMode fullscreenMode, bool on) {
if (!g_pCompositor->windowValidMapped(pWindow)) if (!g_pCompositor->windowValidMapped(pWindow))
return; return;
if (on == pWindow->m_bIsFullscreen)
return; // ignore
const auto PMONITOR = g_pCompositor->getMonitorFromID(pWindow->m_iMonitorID); const auto PMONITOR = g_pCompositor->getMonitorFromID(pWindow->m_iMonitorID);
const auto PWORKSPACE = g_pCompositor->getWorkspaceByID(pWindow->m_iWorkspaceID); const auto PWORKSPACE = g_pCompositor->getWorkspaceByID(pWindow->m_iWorkspaceID);
if (PWORKSPACE->m_bHasFullscreenWindow && !pWindow->m_bIsFullscreen) { if (PWORKSPACE->m_bHasFullscreenWindow && on) {
// if the window wants to be fullscreen but there already is one, // if the window wants to be fullscreen but there already is one,
// ignore the request. // ignore the request.
return; return;
} }
// otherwise, accept it. // otherwise, accept it.
pWindow->m_bIsFullscreen = !pWindow->m_bIsFullscreen; pWindow->m_bIsFullscreen = on;
PWORKSPACE->m_bHasFullscreenWindow = !PWORKSPACE->m_bHasFullscreenWindow; PWORKSPACE->m_bHasFullscreenWindow = !PWORKSPACE->m_bHasFullscreenWindow;
if (!pWindow->m_bIsFullscreen) { if (!pWindow->m_bIsFullscreen) {

View file

@ -53,7 +53,7 @@ public:
virtual void onEndDragWindow(); virtual void onEndDragWindow();
virtual void onMouseMove(const Vector2D&); virtual void onMouseMove(const Vector2D&);
virtual void onWindowCreatedFloating(CWindow*); virtual void onWindowCreatedFloating(CWindow*);
virtual void fullscreenRequestForWindow(CWindow*, eFullscreenMode); virtual void fullscreenRequestForWindow(CWindow*, eFullscreenMode, bool);
virtual std::any layoutMessage(SLayoutMessageHeader, std::string); virtual std::any layoutMessage(SLayoutMessageHeader, std::string);
virtual SWindowRenderLayoutHints requestRenderHints(CWindow*); virtual SWindowRenderLayoutHints requestRenderHints(CWindow*);
virtual void switchWindows(CWindow*, CWindow*); virtual void switchWindows(CWindow*, CWindow*);

View file

@ -84,7 +84,7 @@ public:
The layout sets all the fullscreen flags. The layout sets all the fullscreen flags.
It can either accept or ignore. It can either accept or ignore.
*/ */
virtual void fullscreenRequestForWindow(CWindow*, eFullscreenMode) = 0; virtual void fullscreenRequestForWindow(CWindow*, eFullscreenMode, bool) = 0;
/* /*
Called when a dispatcher requests a custom message Called when a dispatcher requests a custom message

View file

@ -366,14 +366,7 @@ void CKeybindManager::fullscreenActive(std::string args) {
if (!g_pCompositor->windowValidMapped(PWINDOW)) if (!g_pCompositor->windowValidMapped(PWINDOW))
return; return;
g_pLayoutManager->getCurrentLayout()->fullscreenRequestForWindow(PWINDOW, args == "1" ? eFullscreenMode::FULLSCREEN_MAXIMIZED : eFullscreenMode::FULLSCREEN_FULL); g_pCompositor->setWindowFullscreen(PWINDOW, !PWINDOW->m_bIsFullscreen, args == "1" ? FULLSCREEN_MAXIMIZED : FULLSCREEN_FULL);
g_pXWaylandManager->setWindowFullscreen(PWINDOW, PWINDOW->m_bIsFullscreen && (args == "0" || args == ""));
// make all windows on the same workspace under the fullscreen window
for (auto& w : g_pCompositor->m_lWindows) {
if (w.m_iWorkspaceID == PWINDOW->m_iWorkspaceID)
w.m_bCreatedOverFullscreen = false;
}
} }
void CKeybindManager::moveActiveToWorkspace(std::string args) { void CKeybindManager::moveActiveToWorkspace(std::string args) {
@ -954,8 +947,8 @@ void CKeybindManager::moveActive(std::string args) {
const int X = std::stoi(newX); const int X = std::stoi(newX);
const int Y = std::stoi(newY); const int Y = std::stoi(newY);
if (X < 10 || Y < 10) { if (X < 0 || Y < 0) {
Debug::log(ERR, "moveActive: exact args cannot be < 10"); Debug::log(ERR, "moveActive: exact args cannot be < 0");
return; return;
} }
@ -999,6 +992,9 @@ void CKeybindManager::focusWindowByClass(std::string clazz) {
std::regex classCheck(clazz); std::regex classCheck(clazz);
for (auto& w : g_pCompositor->m_lWindows) { for (auto& w : g_pCompositor->m_lWindows) {
if (!w.m_bIsMapped || w.m_bHidden)
continue;
const auto windowClass = g_pXWaylandManager->getAppIDClass(&w); const auto windowClass = g_pXWaylandManager->getAppIDClass(&w);
if (!std::regex_search(windowClass, classCheck)) if (!std::regex_search(windowClass, classCheck))

View file

@ -14,12 +14,16 @@ void CInputManager::onMouseMoved(wlr_pointer_motion_event* e) {
wlr_cursor_move(g_pCompositor->m_sWLRCursor, &e->pointer->base, DELTA.x * sensitivity, DELTA.y * sensitivity); wlr_cursor_move(g_pCompositor->m_sWLRCursor, &e->pointer->base, DELTA.x * sensitivity, DELTA.y * sensitivity);
mouseMoveUnified(e->time_msec); mouseMoveUnified(e->time_msec);
m_tmrLastCursorMovement.reset();
} }
void CInputManager::onMouseWarp(wlr_pointer_motion_absolute_event* e) { void CInputManager::onMouseWarp(wlr_pointer_motion_absolute_event* e) {
wlr_cursor_warp_absolute(g_pCompositor->m_sWLRCursor, &e->pointer->base, e->x, e->y); wlr_cursor_warp_absolute(g_pCompositor->m_sWLRCursor, &e->pointer->base, e->x, e->y);
mouseMoveUnified(e->time_msec); mouseMoveUnified(e->time_msec);
m_tmrLastCursorMovement.reset();
} }
void CInputManager::mouseMoveUnified(uint32_t time, bool refocus) { void CInputManager::mouseMoveUnified(uint32_t time, bool refocus) {
@ -205,6 +209,8 @@ void CInputManager::mouseMoveUnified(uint32_t time, bool refocus) {
void CInputManager::onMouseButton(wlr_pointer_button_event* e) { void CInputManager::onMouseButton(wlr_pointer_button_event* e) {
wlr_idle_notify_activity(g_pCompositor->m_sWLRIdle, g_pCompositor->m_sSeat.seat); wlr_idle_notify_activity(g_pCompositor->m_sWLRIdle, g_pCompositor->m_sSeat.seat);
m_tmrLastCursorMovement.reset();
const auto PKEYBOARD = wlr_seat_get_keyboard(g_pCompositor->m_sSeat.seat); const auto PKEYBOARD = wlr_seat_get_keyboard(g_pCompositor->m_sSeat.seat);
if (!PKEYBOARD) { // ??? if (!PKEYBOARD) { // ???
@ -289,7 +295,7 @@ void CInputManager::newKeyboard(wlr_input_device* keyboard) {
m_pActiveKeyboard->active = false; m_pActiveKeyboard->active = false;
m_pActiveKeyboard = PNEWKEYBOARD; m_pActiveKeyboard = PNEWKEYBOARD;
setKeyboardLayout(); applyConfigToKeyboard(PNEWKEYBOARD);
wlr_seat_set_keyboard(g_pCompositor->m_sSeat.seat, keyboard->keyboard); wlr_seat_set_keyboard(g_pCompositor->m_sSeat.seat, keyboard->keyboard);
@ -311,6 +317,11 @@ void CInputManager::applyConfigToKeyboard(SKeyboard* pKeyboard) {
const auto VARIANT = g_pConfigManager->getString("input:kb_variant"); const auto VARIANT = g_pConfigManager->getString("input:kb_variant");
const auto OPTIONS = g_pConfigManager->getString("input:kb_options"); const auto OPTIONS = g_pConfigManager->getString("input:kb_options");
if (RULES != "" && RULES == pKeyboard->currentRules.rules && MODEL == pKeyboard->currentRules.model && LAYOUT == pKeyboard->currentRules.layout && VARIANT == pKeyboard->currentRules.variant && OPTIONS == pKeyboard->currentRules.options) {
Debug::log(LOG, "Not applying config to keyboard, it did not change.");
return;
}
xkb_rule_names rules = { xkb_rule_names rules = {
.rules = RULES.c_str(), .rules = RULES.c_str(),
.model = MODEL.c_str(), .model = MODEL.c_str(),
@ -318,6 +329,8 @@ void CInputManager::applyConfigToKeyboard(SKeyboard* pKeyboard) {
.variant = VARIANT.c_str(), .variant = VARIANT.c_str(),
.options = OPTIONS.c_str()}; .options = OPTIONS.c_str()};
pKeyboard->currentRules = rules;
const auto CONTEXT = xkb_context_new(XKB_CONTEXT_NO_FLAGS); const auto CONTEXT = xkb_context_new(XKB_CONTEXT_NO_FLAGS);
if (!CONTEXT) { if (!CONTEXT) {
@ -325,12 +338,17 @@ void CInputManager::applyConfigToKeyboard(SKeyboard* pKeyboard) {
return; return;
} }
const auto KEYMAP = xkb_keymap_new_from_names(CONTEXT, &rules, XKB_KEYMAP_COMPILE_NO_FLAGS); Debug::log(LOG, "Attempting to create a keymap for layout %s with variant %s (rules: %s, model: %s, options: %s)", rules.layout, rules.variant, rules.rules, rules.model, rules.options);
auto KEYMAP = xkb_keymap_new_from_names(CONTEXT, &rules, XKB_KEYMAP_COMPILE_NO_FLAGS);
if (!KEYMAP) { if (!KEYMAP) {
Debug::log(ERR, "Keyboard layout %s with variant %s (rules: %s, model: %s, options: %s) couldn't have been loaded.", rules.layout, rules.variant, rules.rules, rules.model, rules.options); Debug::log(ERR, "Keyboard layout %s with variant %s (rules: %s, model: %s, options: %s) couldn't have been loaded.", rules.layout, rules.variant, rules.rules, rules.model, rules.options);
xkb_context_unref(CONTEXT); memset(&rules, 0, sizeof(rules));
return;
pKeyboard->currentRules = rules;
KEYMAP = xkb_keymap_new_from_names(CONTEXT, &rules, XKB_KEYMAP_COMPILE_NO_FLAGS);
} }
wlr_keyboard_set_keymap(pKeyboard->keyboard->keyboard, KEYMAP); wlr_keyboard_set_keymap(pKeyboard->keyboard->keyboard, KEYMAP);
@ -401,6 +419,8 @@ void CInputManager::newMouse(wlr_input_device* mouse) {
g_pCompositor->m_sSeat.mouse = PMOUSE; g_pCompositor->m_sSeat.mouse = PMOUSE;
m_tmrLastCursorMovement.reset();
Debug::log(LOG, "New mouse created, pointer WLR: %x", mouse); Debug::log(LOG, "New mouse created, pointer WLR: %x", mouse);
} }

View file

@ -4,6 +4,7 @@
#include <list> #include <list>
#include "../../helpers/WLClasses.hpp" #include "../../helpers/WLClasses.hpp"
#include "../../Window.hpp" #include "../../Window.hpp"
#include "../../helpers/Timer.hpp"
class CInputManager { class CInputManager {
public: public:
@ -53,6 +54,8 @@ public:
SKeyboard* m_pActiveKeyboard = nullptr; SKeyboard* m_pActiveKeyboard = nullptr;
CTimer m_tmrLastCursorMovement;
private: private:
uint32_t m_uiCapabilities = 0; uint32_t m_uiCapabilities = 0;

View file

@ -75,6 +75,12 @@ CHyprOpenGLImpl::CHyprOpenGLImpl() {
m_shBLUR2.posAttrib = glGetAttribLocation(prog, "pos"); m_shBLUR2.posAttrib = glGetAttribLocation(prog, "pos");
m_shBLUR2.texAttrib = glGetAttribLocation(prog, "texcoord"); m_shBLUR2.texAttrib = glGetAttribLocation(prog, "texcoord");
prog = createProgram(QUADVERTSRC, FRAGSHADOW);
m_shSHADOW.program = prog;
m_shSHADOW.proj = glGetUniformLocation(prog, "proj");
m_shSHADOW.posAttrib = glGetAttribLocation(prog, "pos");
m_shSHADOW.texAttrib = glGetAttribLocation(prog, "texcoord");
Debug::log(LOG, "Shaders initialized successfully."); Debug::log(LOG, "Shaders initialized successfully.");
// End shaders // End shaders
@ -566,7 +572,7 @@ void CHyprOpenGLImpl::renderTextureWithBlur(const CTexture& tex, wlr_box* pBox,
static auto *const PBLURENABLED = &g_pConfigManager->getConfigValuePtr("decoration:blur")->intValue; static auto *const PBLURENABLED = &g_pConfigManager->getConfigValuePtr("decoration:blur")->intValue;
static auto* const PNOBLUROVERSIZED = &g_pConfigManager->getConfigValuePtr("decoration:no_blur_on_oversized")->intValue; static auto* const PNOBLUROVERSIZED = &g_pConfigManager->getConfigValuePtr("decoration:no_blur_on_oversized")->intValue;
if (*PBLURENABLED == 0 || (*PNOBLUROVERSIZED && m_RenderData.primarySurfaceUVTopLeft != Vector2D(-1, -1))) { if (*PBLURENABLED == 0 || (*PNOBLUROVERSIZED && m_RenderData.primarySurfaceUVTopLeft != Vector2D(-1, -1)) || (m_pCurrentWindow && m_pCurrentWindow->m_sAdditionalConfigData.forceNoBlur)) {
renderTexture(tex, pBox, a, round, false, border, true); renderTexture(tex, pBox, a, round, false, border, true);
return; return;
} }
@ -858,6 +864,68 @@ void CHyprOpenGLImpl::renderSnapshot(SLayerSurface** pLayer) {
pixman_region32_fini(&fakeDamage); pixman_region32_fini(&fakeDamage);
} }
void CHyprOpenGLImpl::renderRoundedShadow(wlr_box* box, int round, int range, 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!");
static auto *const PSHADOWCOL = &g_pConfigManager->getConfigValuePtr("decoration:col.shadow")->intValue;
static auto *const PSHADOWPOWER = &g_pConfigManager->getConfigValuePtr("decoration:shadow_render_power")->intValue;
static auto *const PSHADOWIGNOREWINDOW = &g_pConfigManager->getConfigValuePtr("decoration:shadow_ignore_window")->intValue;
const auto SHADOWPOWER = std::clamp((int)*PSHADOWPOWER, 1, 4);
const auto col = CColor(*PSHADOWCOL);
float matrix[9];
wlr_matrix_project_box(matrix, box, wlr_output_transform_invert(!m_bEndFrame ? WL_OUTPUT_TRANSFORM_NORMAL : m_RenderData.pMonitor->transform), 0, m_RenderData.pMonitor->output->transform_matrix); // TODO: write own, don't use WLR here
float glMatrix[9];
wlr_matrix_multiply(glMatrix, m_RenderData.projection, matrix);
wlr_matrix_multiply(glMatrix, matrixFlip180, glMatrix);
wlr_matrix_transpose(glMatrix, glMatrix);
glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
glUseProgram(m_shSHADOW.program);
glUniformMatrix3fv(m_shSHADOW.proj, 1, GL_FALSE, glMatrix);
glUniform4f(glGetUniformLocation(m_shSHADOW.program, "color"), col.r / 255.f, col.g / 255.f, col.b / 255.f, col.a / 255.f * a);
const auto TOPLEFT = Vector2D(range + round, range + round);
const auto BOTTOMRIGHT = Vector2D(box->width - (range + round), box->height - (range + round));
const auto FULLSIZE = Vector2D(box->width, box->height);
// Rounded corners
glUniform2f(glGetUniformLocation(m_shSHADOW.program, "topLeft"), (float)TOPLEFT.x, (float)TOPLEFT.y);
glUniform2f(glGetUniformLocation(m_shSHADOW.program, "bottomRight"), (float)BOTTOMRIGHT.x, (float)BOTTOMRIGHT.y);
glUniform2f(glGetUniformLocation(m_shSHADOW.program, "fullSize"), (float)FULLSIZE.x, (float)FULLSIZE.y);
glUniform1f(glGetUniformLocation(m_shSHADOW.program, "radius"), range + round);
glUniform1f(glGetUniformLocation(m_shSHADOW.program, "range"), range);
glUniform1f(glGetUniformLocation(m_shSHADOW.program, "shadowPower"), SHADOWPOWER);
glUniform1i(glGetUniformLocation(m_shSHADOW.program, "ignoreWindow"), *PSHADOWIGNOREWINDOW);
glVertexAttribPointer(m_shSHADOW.posAttrib, 2, GL_FLOAT, GL_FALSE, 0, fullVerts);
glVertexAttribPointer(m_shSHADOW.texAttrib, 2, GL_FLOAT, GL_FALSE, 0, fullVerts);
glEnableVertexAttribArray(m_shSHADOW.posAttrib);
glEnableVertexAttribArray(m_shSHADOW.texAttrib);
if (pixman_region32_not_empty(m_RenderData.pDamage)) {
PIXMAN_DAMAGE_FOREACH(m_RenderData.pDamage) {
const auto RECT = RECTSARR[i];
scissor(&RECT);
glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
}
}
glDisableVertexAttribArray(m_shSHADOW.posAttrib);
glDisableVertexAttribArray(m_shSHADOW.texAttrib);
glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
}
void CHyprOpenGLImpl::createBGTextureForMonitor(SMonitor* pMonitor) { void CHyprOpenGLImpl::createBGTextureForMonitor(SMonitor* pMonitor) {
RASSERT(m_RenderData.pMonitor, "Tried to createBGTex without begin()!"); RASSERT(m_RenderData.pMonitor, "Tried to createBGTex without begin()!");

View file

@ -61,6 +61,7 @@ public:
void renderTexture(wlr_texture*, wlr_box*, float a, int round = 0); void renderTexture(wlr_texture*, wlr_box*, float a, int round = 0);
void renderTexture(const CTexture&, wlr_box*, float a, int round = 0, bool discardOpaque = false, bool border = false, bool allowPrimary = false); void renderTexture(const CTexture&, wlr_box*, float a, int round = 0, bool discardOpaque = false, bool border = false, bool allowPrimary = false);
void renderTextureWithBlur(const CTexture&, wlr_box*, float a, wlr_surface* pSurface, int round = 0, bool border = false); void renderTextureWithBlur(const CTexture&, wlr_box*, float a, wlr_surface* pSurface, int round = 0, bool border = false);
void renderRoundedShadow(wlr_box*, int round, int range, float a = 1.0);
void makeWindowSnapshot(CWindow*); void makeWindowSnapshot(CWindow*);
void makeLayerSnapshot(SLayerSurface*); void makeLayerSnapshot(SLayerSurface*);
@ -106,6 +107,7 @@ private:
CShader m_shEXT; CShader m_shEXT;
CShader m_shBLUR1; CShader m_shBLUR1;
CShader m_shBLUR2; CShader m_shBLUR2;
CShader m_shSHADOW;
// //
GLuint createProgram(const std::string&, const std::string&); GLuint createProgram(const std::string&, const std::string&);

View file

@ -168,7 +168,7 @@ void CHyprRenderer::renderWindow(CWindow* pWindow, SMonitor* pMonitor, timespec*
// render window decorations first // render window decorations first
for (auto& wd : pWindow->m_dWindowDecorations) for (auto& wd : pWindow->m_dWindowDecorations)
wd->draw(pMonitor); wd->draw(pMonitor, renderdata.alpha * renderdata.fadeAlpha / 255.f);
if (!pWindow->m_bIsX11) { if (!pWindow->m_bIsX11) {
@ -194,12 +194,7 @@ void CHyprRenderer::renderWindow(CWindow* pWindow, SMonitor* pMonitor, timespec*
g_pHyprOpenGL->m_RenderData.primarySurfaceUVTopLeft = Vector2D(-1, -1); g_pHyprOpenGL->m_RenderData.primarySurfaceUVTopLeft = Vector2D(-1, -1);
g_pHyprOpenGL->m_RenderData.primarySurfaceUVBottomRight = Vector2D(-1, -1); g_pHyprOpenGL->m_RenderData.primarySurfaceUVBottomRight = Vector2D(-1, -1);
if (pWindow->m_bIsX11) { if (!pWindow->m_bIsX11) {
if (pWindow->m_uSurface.xwayland->surface) {
wlr_surface_for_each_surface(pWindow->m_uSurface.xwayland->surface, renderSurface, &renderdata);
}
}
else {
renderdata.dontRound = false; // restore dontround renderdata.dontRound = false; // restore dontround
renderdata.pMonitor = pMonitor; renderdata.pMonitor = pMonitor;
wlr_xdg_surface_for_each_popup_surface(pWindow->m_uSurface.xdg, renderSurface, &renderdata); wlr_xdg_surface_for_each_popup_surface(pWindow->m_uSurface.xdg, renderSurface, &renderdata);
@ -574,7 +569,7 @@ void CHyprRenderer::damageWindow(CWindow* pWindow) {
// damage by size & pos // damage by size & pos
// TODO TEMP: revise when added shadows/etc // TODO TEMP: revise when added shadows/etc
wlr_box damageBox = {pWindow->m_vRealPosition.vec().x, pWindow->m_vRealPosition.vec().y, pWindow->m_vRealSize.vec().x, pWindow->m_vRealSize.vec().y}; wlr_box damageBox = pWindow->getFullWindowBoundingBox();
for (auto& m : g_pCompositor->m_lMonitors) { for (auto& m : g_pCompositor->m_lMonitors) {
wlr_box fixedDamageBox = damageBox; wlr_box fixedDamageBox = damageBox;
fixedDamageBox.x -= m.vecPosition.x; fixedDamageBox.x -= m.vecPosition.x;
@ -589,8 +584,7 @@ void CHyprRenderer::damageWindow(CWindow* pWindow) {
Debug::log(LOG, "Damage: Window floated (%s): xy: %d, %d wh: %d, %d", pWindow->m_szTitle.c_str(), damageBox.x, damageBox.y, damageBox.width, damageBox.height); Debug::log(LOG, "Damage: Window floated (%s): xy: %d, %d wh: %d, %d", pWindow->m_szTitle.c_str(), damageBox.x, damageBox.y, damageBox.width, damageBox.height);
} else { } else {
// damage by real size & pos + border size * 2 (JIC) // damage by real size & pos + border size * 2 (JIC)
static auto *const PBORDERSIZE = &g_pConfigManager->getConfigValuePtr("general:border_size")->intValue; wlr_box damageBox = pWindow->getFullWindowBoundingBox();
wlr_box damageBox = { pWindow->m_vRealPosition.vec().x - *PBORDERSIZE - 1, pWindow->m_vRealPosition.vec().y - *PBORDERSIZE - 1, pWindow->m_vRealSize.vec().x + 2 * *PBORDERSIZE + 2, pWindow->m_vRealSize.vec().y + 2 * *PBORDERSIZE + 2};
for (auto& m : g_pCompositor->m_lMonitors) { for (auto& m : g_pCompositor->m_lMonitors) {
wlr_box fixedDamageBox = damageBox; wlr_box fixedDamageBox = damageBox;
fixedDamageBox.x -= m.vecPosition.x; fixedDamageBox.x -= m.vecPosition.x;
@ -759,3 +753,38 @@ void CHyprRenderer::applyMonitorRule(SMonitor* pMonitor, SMonitorRule* pMonitorR
// frame skip // frame skip
pMonitor->framesToSkip = 1; pMonitor->framesToSkip = 1;
} }
void CHyprRenderer::ensureCursorRenderingMode() {
static auto *const PCURSORTIMEOUT = &g_pConfigManager->getConfigValuePtr("general:cursor_inactive_timeout")->intValue;
const auto PASSEDCURSORSECONDS = g_pInputManager->m_tmrLastCursorMovement.getSeconds();
if (*PCURSORTIMEOUT > 0) {
if (*PCURSORTIMEOUT < PASSEDCURSORSECONDS && m_bHasARenderedCursor) {
m_bHasARenderedCursor = false;
wlr_cursor_set_surface(g_pCompositor->m_sWLRCursor, nullptr, 0, 0); // hide
Debug::log(LOG, "Hiding the cursor (timeout)");
for (auto& m : g_pCompositor->m_lMonitors)
g_pHyprRenderer->damageMonitor(&m); // TODO: maybe just damage the cursor area?
} else if (*PCURSORTIMEOUT > PASSEDCURSORSECONDS && !m_bHasARenderedCursor) {
m_bHasARenderedCursor = true;
if (!m_bWindowRequestedCursorHide)
wlr_xcursor_manager_set_cursor_image(g_pCompositor->m_sWLRXCursorMgr, "left_ptr", g_pCompositor->m_sWLRCursor);
Debug::log(LOG, "Showing the cursor (timeout)");
for (auto& m : g_pCompositor->m_lMonitors)
g_pHyprRenderer->damageMonitor(&m); // TODO: maybe just damage the cursor area?
}
} else {
m_bHasARenderedCursor = true;
}
}
bool CHyprRenderer::shouldRenderCursor() {
return m_bHasARenderedCursor;
}

View file

@ -31,6 +31,10 @@ public:
void applyMonitorRule(SMonitor*, SMonitorRule*, bool force = false); void applyMonitorRule(SMonitor*, SMonitorRule*, bool force = false);
bool shouldRenderWindow(CWindow*, SMonitor*); bool shouldRenderWindow(CWindow*, SMonitor*);
bool shouldRenderWindow(CWindow*); bool shouldRenderWindow(CWindow*);
void ensureCursorRenderingMode();
bool shouldRenderCursor();
bool m_bWindowRequestedCursorHide = false;
DAMAGETRACKINGMODES damageTrackingModeFromStr(const std::string&); DAMAGETRACKINGMODES damageTrackingModeFromStr(const std::string&);
@ -41,6 +45,8 @@ private:
void renderLayer(SLayerSurface*, SMonitor*, timespec*); void renderLayer(SLayerSurface*, SMonitor*, timespec*);
void renderDragIcon(SMonitor*, timespec*); void renderDragIcon(SMonitor*, timespec*);
bool m_bHasARenderedCursor = true;
friend class CHyprOpenGLImpl; friend class CHyprOpenGLImpl;
}; };

View file

@ -1,341 +1,4 @@
#pragma once #pragma once
#include <string> #include "shaders/Textures.hpp"
#include "shaders/Shadow.hpp"
inline static constexpr auto ROUNDED_SHADER_FUNC = [](const std::string colorVarName) -> std::string {
return R"#(
if (pixCoord[0] < topLeft[0]) {
// we're close left
if (pixCoord[1] < topLeft[1]) {
// top
if (ignoreCorners == 1) {
discard;
return;
}
float topLeftDistance = distance(topLeft, pixCoord);
if (topLeftDistance > radius - 1.0) {
if (primitiveMultisample == 0 && topLeftDistance > radius) {
discard;
return;
} else if (primitiveMultisample == 1) {
float distances = 0.0;
if (distance(topLeft, pixCoord + vec2(0.25, 0.25)) < radius) { distances = distances + 1.0; }
if (distance(topLeft, pixCoord + vec2(0.75, 0.25)) < radius) { distances = distances + 1.0; }
if (distance(topLeft, pixCoord + vec2(0.25, 0.75)) < radius) { distances = distances + 1.0; }
if (distance(topLeft, pixCoord + vec2(0.75, 0.75)) < radius) { distances = distances + 1.0; }
if (distances == 0.0) {
discard;
return;
}
distances = distances / 4.0;
gl_FragColor = )#" + colorVarName + R"#( * distances;
return;
}
}
} else if (pixCoord[1] > bottomRight[1]) {
// bottom
if (ignoreCorners == 1) {
discard;
return;
}
float topLeftDistance = distance(vec2(topLeft[0], bottomRight[1]), pixCoord);
if (topLeftDistance > radius - 1.0) {
if (primitiveMultisample == 0 && topLeftDistance > radius) {
discard;
return;
} else if (primitiveMultisample == 1) {
float distances = 0.0;
if (distance(vec2(topLeft[0], bottomRight[1]), pixCoord + vec2(0.25, 0.25)) < radius) { distances = distances + 1.0; }
if (distance(vec2(topLeft[0], bottomRight[1]), pixCoord + vec2(0.75, 0.25)) < radius) { distances = distances + 1.0; }
if (distance(vec2(topLeft[0], bottomRight[1]), pixCoord + vec2(0.25, 0.75)) < radius) { distances = distances + 1.0; }
if (distance(vec2(topLeft[0], bottomRight[1]), pixCoord + vec2(0.75, 0.75)) < radius) { distances = distances + 1.0; }
if (distances == 0.0) {
discard;
return;
}
distances = distances / 4.0;
gl_FragColor = )#" + colorVarName + R"#( * distances;
return;
}
}
}
}
else if (pixCoord[0] > bottomRight[0]) {
// we're close right
if (pixCoord[1] < topLeft[1]) {
// top
if (ignoreCorners == 1) {
discard;
return;
}
float topLeftDistance = distance(vec2(bottomRight[0], topLeft[1]), pixCoord);
if (topLeftDistance > radius - 1.0) {
if (primitiveMultisample == 0 && topLeftDistance > radius) {
discard;
return;
} else if (primitiveMultisample == 1) {
float distances = 0.0;
if (distance(vec2(bottomRight[0], topLeft[1]), pixCoord + vec2(0.25, 0.25)) < radius) { distances = distances + 1.0; }
if (distance(vec2(bottomRight[0], topLeft[1]), pixCoord + vec2(0.75, 0.25)) < radius) { distances = distances + 1.0; }
if (distance(vec2(bottomRight[0], topLeft[1]), pixCoord + vec2(0.25, 0.75)) < radius) { distances = distances + 1.0; }
if (distance(vec2(bottomRight[0], topLeft[1]), pixCoord + vec2(0.75, 0.75)) < radius) { distances = distances + 1.0; }
if (distances == 0.0) {
discard;
return;
}
distances = distances / 4.0;
gl_FragColor = )#" + colorVarName + R"#( * distances;
return;
}
}
} else if (pixCoord[1] > bottomRight[1]) {
// bottom
if (ignoreCorners == 1) {
discard;
return;
}
float topLeftDistance = distance(bottomRight, pixCoord);
if (topLeftDistance > radius - 1.0) {
if (primitiveMultisample == 0 && topLeftDistance > radius) {
discard;
return;
} else if (primitiveMultisample == 1) {
float distances = 0.0;
if (distance(bottomRight, pixCoord + vec2(0.25, 0.25)) < radius) { distances = distances + 1.0; }
if (distance(bottomRight, pixCoord + vec2(0.75, 0.25)) < radius) { distances = distances + 1.0; }
if (distance(bottomRight, pixCoord + vec2(0.25, 0.75)) < radius) { distances = distances + 1.0; }
if (distance(bottomRight, pixCoord + vec2(0.75, 0.75)) < radius) { distances = distances + 1.0; }
if (distances == 0.0) {
discard;
return;
}
distances = distances / 4.0;
gl_FragColor = )#" + colorVarName + R"#( * distances;
return;
}
}
}
}
)#";
};
inline const std::string QUADVERTSRC = R"#(
uniform mat3 proj;
uniform vec4 color;
attribute vec2 pos;
attribute vec2 texcoord;
varying vec4 v_color;
varying vec2 v_texcoord;
void main() {
gl_Position = vec4(proj * vec3(pos, 1.0), 1.0);
v_color = color;
v_texcoord = texcoord;
})#";
inline const std::string QUADFRAGSRC = R"#(
precision mediump float;
varying vec4 v_color;
varying vec2 v_texcoord;
uniform vec2 topLeft;
uniform vec2 bottomRight;
uniform vec2 fullSize;
uniform float radius;
uniform int primitiveMultisample;
uniform int ignoreCorners;
void main() {
if (radius == 0.0) {
gl_FragColor = v_color;
return;
}
vec2 pixCoord = fullSize * v_texcoord;
)#" + ROUNDED_SHADER_FUNC("v_color") + R"#(
gl_FragColor = v_color;
})#";
inline const std::string TEXVERTSRC = R"#(
uniform mat3 proj;
attribute vec2 pos;
attribute vec2 texcoord;
varying vec2 v_texcoord;
void main() {
gl_Position = vec4(proj * vec3(pos, 1.0), 1.0);
v_texcoord = texcoord;
})#";
inline const std::string TEXFRAGSRCRGBA = R"#(
precision mediump float;
varying vec2 v_texcoord; // is in 0-1
uniform sampler2D tex;
uniform float alpha;
uniform vec2 topLeft;
uniform vec2 bottomRight;
uniform vec2 fullSize;
uniform float radius;
uniform int discardOpaque;
uniform int primitiveMultisample;
uniform int ignoreCorners;
void main() {
vec4 pixColor = texture2D(tex, v_texcoord);
if (discardOpaque == 1 && pixColor[3] * alpha == 1.0) {
discard;
return;
}
vec2 pixCoord = fullSize * v_texcoord;
)#" + ROUNDED_SHADER_FUNC("pixColor") +
R"#(
gl_FragColor = pixColor * alpha;
})#";
inline const std::string TEXFRAGSRCRGBX = R"#(
precision mediump float;
varying vec2 v_texcoord;
uniform sampler2D tex;
uniform float alpha;
uniform vec2 topLeft;
uniform vec2 bottomRight;
uniform vec2 fullSize;
uniform float radius;
uniform int discardOpaque;
uniform int primitiveMultisample;
uniform int ignoreCorners;
void main() {
if (discardOpaque == 1 && alpha == 1.0) {
discard;
return;
}
vec4 pixColor = vec4(texture2D(tex, v_texcoord).rgb, 1.0);
vec2 pixCoord = fullSize * v_texcoord;
)#" + ROUNDED_SHADER_FUNC("pixColor") + R"#(
gl_FragColor = pixColor * alpha;
})#";
inline const std::string FRAGBLUR1 = R"#(
#version 100
precision mediump float;
varying mediump vec2 v_texcoord; // is in 0-1
uniform sampler2D tex;
uniform float radius;
uniform vec2 halfpixel;
void main() {
vec2 uv = v_texcoord * 2.0;
vec4 sum = texture2D(tex, uv) * 4.0;
sum += texture2D(tex, uv - halfpixel.xy * radius);
sum += texture2D(tex, uv + halfpixel.xy * radius);
sum += texture2D(tex, uv + vec2(halfpixel.x, -halfpixel.y) * radius);
sum += texture2D(tex, uv - vec2(halfpixel.x, -halfpixel.y) * radius);
gl_FragColor = sum / 8.0;
}
)#";
inline const std::string FRAGBLUR2 = R"#(
#version 100
precision mediump float;
varying mediump vec2 v_texcoord; // is in 0-1
uniform sampler2D tex;
uniform float radius;
uniform vec2 halfpixel;
void main() {
vec2 uv = v_texcoord / 2.0;
vec4 sum = texture2D(tex, uv + vec2(-halfpixel.x * 2.0, 0.0) * radius);
sum += texture2D(tex, uv + vec2(-halfpixel.x, halfpixel.y) * radius) * 2.0;
sum += texture2D(tex, uv + vec2(0.0, halfpixel.y * 2.0) * radius);
sum += texture2D(tex, uv + vec2(halfpixel.x, halfpixel.y) * radius) * 2.0;
sum += texture2D(tex, uv + vec2(halfpixel.x * 2.0, 0.0) * radius);
sum += texture2D(tex, uv + vec2(halfpixel.x, -halfpixel.y) * radius) * 2.0;
sum += texture2D(tex, uv + vec2(0.0, -halfpixel.y * 2.0) * radius);
sum += texture2D(tex, uv + vec2(-halfpixel.x, -halfpixel.y) * radius) * 2.0;
gl_FragColor = sum / 12.0;
}
)#";
inline const std::string TEXFRAGSRCEXT = R"#(
#extension GL_OES_EGL_image_external : require
precision mediump float;
varying vec2 v_texcoord;
uniform samplerExternalOES texture0;
uniform float alpha;
uniform vec2 topLeft;
uniform vec2 bottomRight;
uniform vec2 fullSize;
uniform float radius;
uniform int discardOpaque;
uniform int primitiveMultisample;
uniform int ignoreCorners;
void main() {
vec4 pixColor = texture2D(texture0, v_texcoord);
if (discardOpaque == 1 && pixColor[3] * alpha == 1.0) {
discard;
return;
}
vec2 pixCoord = fullSize * v_texcoord;
)#" + ROUNDED_SHADER_FUNC("pixColor") + R"#(
gl_FragColor = pixColor * alpha;
})#";

View file

@ -0,0 +1,66 @@
#include "CHyprDropShadowDecoration.hpp"
#include "../../Compositor.hpp"
CHyprDropShadowDecoration::CHyprDropShadowDecoration(CWindow* pWindow) {
m_pWindow = pWindow;
}
CHyprDropShadowDecoration::~CHyprDropShadowDecoration() {
updateWindow(m_pWindow);
}
SWindowDecorationExtents CHyprDropShadowDecoration::getWindowDecorationExtents() {
static auto *const PSHADOWS = &g_pConfigManager->getConfigValuePtr("decoration:drop_shadow")->intValue;
if (*PSHADOWS != 1)
return {{}, {}};
return m_seExtents;
}
eDecorationType CHyprDropShadowDecoration::getDecorationType() {
return DECORATION_SHADOW;
}
void CHyprDropShadowDecoration::damageEntire() {
static auto *const PSHADOWS = &g_pConfigManager->getConfigValuePtr("decoration:drop_shadow")->intValue;
if (*PSHADOWS != 1)
return; // disabled
wlr_box dm = {m_vLastWindowPos.x - m_seExtents.topLeft.x, m_vLastWindowPos.y - m_seExtents.topLeft.y, m_vLastWindowSize.x + m_seExtents.topLeft.x + m_seExtents.bottomRight.x, m_vLastWindowSize.y + m_seExtents.topLeft.y + m_seExtents.bottomRight.y};
g_pHyprRenderer->damageBox(&dm);
}
void CHyprDropShadowDecoration::updateWindow(CWindow* pWindow) {
damageEntire();
}
void CHyprDropShadowDecoration::draw(SMonitor* pMonitor, float a) {
if (!g_pCompositor->windowValidMapped(m_pWindow))
return;
static auto *const PSHADOWS = &g_pConfigManager->getConfigValuePtr("decoration:drop_shadow")->intValue;
static auto *const PSHADOWSIZE = &g_pConfigManager->getConfigValuePtr("decoration:shadow_range")->intValue;
static auto *const PROUNDING = &g_pConfigManager->getConfigValuePtr("decoration:rounding")->intValue;
if (*PSHADOWS != 1)
return; // disabled
// update the extents if needed
if (*PSHADOWSIZE != m_seExtents.topLeft.x)
m_seExtents = {{*PSHADOWSIZE + 2, *PSHADOWSIZE + 2}, {*PSHADOWSIZE + 2, *PSHADOWSIZE + 2}};
m_vLastWindowPos = m_pWindow->m_vRealPosition.vec();
m_vLastWindowSize = m_pWindow->m_vRealSize.vec();
// draw the shadow
wlr_box fullBox = {m_vLastWindowPos.x - m_seExtents.topLeft.x + 2, m_vLastWindowPos.y - m_seExtents.topLeft.y + 2, m_vLastWindowSize.x + m_seExtents.topLeft.x + m_seExtents.bottomRight.x - 4, m_vLastWindowSize.y + m_seExtents.topLeft.y + m_seExtents.bottomRight.y - 4};
fullBox.x -= pMonitor->vecPosition.x;
fullBox.y -= pMonitor->vecPosition.y;
g_pHyprOpenGL->renderRoundedShadow(&fullBox, *PROUNDING, *PSHADOWSIZE, a);
}

View file

@ -0,0 +1,27 @@
#pragma once
#include "IHyprWindowDecoration.hpp"
class CHyprDropShadowDecoration : public IHyprWindowDecoration {
public:
CHyprDropShadowDecoration(CWindow*);
virtual ~CHyprDropShadowDecoration();
virtual SWindowDecorationExtents getWindowDecorationExtents();
virtual void draw(SMonitor*, float a);
virtual eDecorationType getDecorationType();
virtual void updateWindow(CWindow*);
virtual void damageEntire();
private:
SWindowDecorationExtents m_seExtents;
CWindow* m_pWindow = nullptr;
Vector2D m_vLastWindowPos;
Vector2D m_vLastWindowSize;
};

View file

@ -68,7 +68,7 @@ void CHyprGroupBarDecoration::damageEntire() {
g_pHyprRenderer->damageBox(&dm); g_pHyprRenderer->damageBox(&dm);
} }
void CHyprGroupBarDecoration::draw(SMonitor* pMonitor) { void CHyprGroupBarDecoration::draw(SMonitor* pMonitor, float a) {
// get how many bars we will draw // get how many bars we will draw
int barsToDraw = m_dwGroupMembers.size(); int barsToDraw = m_dwGroupMembers.size();
@ -88,6 +88,7 @@ void CHyprGroupBarDecoration::draw(SMonitor* pMonitor) {
break; break;
CColor color = m_dwGroupMembers[i] == g_pCompositor->m_pLastWindow ? CColor(g_pConfigManager->getInt("dwindle:col.group_border_active")) : CColor(g_pConfigManager->getInt("dwindle:col.group_border")); CColor color = m_dwGroupMembers[i] == g_pCompositor->m_pLastWindow ? CColor(g_pConfigManager->getInt("dwindle:col.group_border_active")) : CColor(g_pConfigManager->getInt("dwindle:col.group_border"));
color.a *= a;
g_pHyprOpenGL->renderRect(&rect, color); g_pHyprOpenGL->renderRect(&rect, color);
xoff += PAD + BARW; xoff += PAD + BARW;

View file

@ -10,7 +10,7 @@ public:
virtual SWindowDecorationExtents getWindowDecorationExtents(); virtual SWindowDecorationExtents getWindowDecorationExtents();
virtual void draw(SMonitor*); virtual void draw(SMonitor*, float a);
virtual eDecorationType getDecorationType(); virtual eDecorationType getDecorationType();

View file

@ -4,7 +4,8 @@
enum eDecorationType { enum eDecorationType {
DECORATION_NONE = -1, DECORATION_NONE = -1,
DECORATION_GROUPBAR DECORATION_GROUPBAR,
DECORATION_SHADOW
}; };
struct SWindowDecorationExtents { struct SWindowDecorationExtents {
@ -21,7 +22,7 @@ public:
virtual SWindowDecorationExtents getWindowDecorationExtents() = 0; virtual SWindowDecorationExtents getWindowDecorationExtents() = 0;
virtual void draw(SMonitor*) = 0; virtual void draw(SMonitor*, float a) = 0;
virtual eDecorationType getDecorationType() = 0; virtual eDecorationType getDecorationType() = 0;

View file

@ -0,0 +1,83 @@
#pragma once
#include <string>
inline const std::string FRAGSHADOW = R"#(
precision mediump float;
varying vec4 v_color;
varying vec2 v_texcoord;
uniform vec2 topLeft;
uniform vec2 bottomRight;
uniform vec2 fullSize;
uniform float radius;
uniform float range;
uniform float shadowPower;
uniform int ignoreWindow;
float pixAlphaRoundedDistance(float distanceToCorner) {
if (distanceToCorner > radius) {
return 0.0;
}
if (distanceToCorner > radius - range) {
return pow((range - (distanceToCorner - radius + range)) / range, shadowPower); // i think?
}
return 1.0;
}
void main() {
vec4 pixColor = v_color;
float originalAlpha = pixColor[3];
bool done = false;
vec2 pixCoord = fullSize * v_texcoord;
// ok, now we check the distance to a border.
if (pixCoord[0] < topLeft[0]) {
if (pixCoord[1] < topLeft[1]) {
// top left
pixColor[3] = pixColor[3] * pixAlphaRoundedDistance(distance(pixCoord, topLeft));
done = true;
} else if (pixCoord[1] > bottomRight[1]) {
// bottom left
pixColor[3] = pixColor[3] * pixAlphaRoundedDistance(distance(pixCoord, vec2(topLeft[0], bottomRight[1])));
done = true;
}
} else if (pixCoord[0] > bottomRight[0]) {
if (pixCoord[1] < topLeft[1]) {
// top right
pixColor[3] = pixColor[3] * pixAlphaRoundedDistance(distance(pixCoord, vec2(bottomRight[0], topLeft[1])));
done = true;
} else if (pixCoord[1] > bottomRight[1]) {
// bottom right
pixColor[3] = pixColor[3] * pixAlphaRoundedDistance(distance(pixCoord, bottomRight));
done = true;
}
}
if (!done) {
// distance to all straight bb borders
float distanceT = pixCoord[1];
float distanceB = fullSize[1] - pixCoord[1];
float distanceL = pixCoord[0];
float distanceR = fullSize[0] - pixCoord[0];
// get the smallest
float smallest = min(min(distanceT, distanceB), min(distanceL, distanceR));
if (smallest < range) {
pixColor[3] = pixColor[3] * pow((smallest / range), shadowPower);
}
}
if (pixColor[3] == 0.0 || (ignoreWindow == 1 && pixColor[3] == originalAlpha)) {
discard; return;
}
gl_FragColor = pixColor;
})#";

View file

@ -0,0 +1,341 @@
#pragma once
#include <string>
inline static constexpr auto ROUNDED_SHADER_FUNC = [](const std::string colorVarName) -> std::string {
return R"#(
if (pixCoord[0] < topLeft[0]) {
// we're close left
if (pixCoord[1] < topLeft[1]) {
// top
if (ignoreCorners == 1) {
discard;
return;
}
float topLeftDistance = distance(topLeft, pixCoord);
if (topLeftDistance > radius - 1.0) {
if (primitiveMultisample == 0 && topLeftDistance > radius) {
discard;
return;
} else if (primitiveMultisample == 1) {
float distances = 0.0;
if (distance(topLeft, pixCoord + vec2(0.25, 0.25)) < radius) { distances = distances + 1.0; }
if (distance(topLeft, pixCoord + vec2(0.75, 0.25)) < radius) { distances = distances + 1.0; }
if (distance(topLeft, pixCoord + vec2(0.25, 0.75)) < radius) { distances = distances + 1.0; }
if (distance(topLeft, pixCoord + vec2(0.75, 0.75)) < radius) { distances = distances + 1.0; }
if (distances == 0.0) {
discard;
return;
}
distances = distances / 4.0;
gl_FragColor = )#" + colorVarName + R"#( * distances;
return;
}
}
} else if (pixCoord[1] > bottomRight[1]) {
// bottom
if (ignoreCorners == 1) {
discard;
return;
}
float topLeftDistance = distance(vec2(topLeft[0], bottomRight[1]), pixCoord);
if (topLeftDistance > radius - 1.0) {
if (primitiveMultisample == 0 && topLeftDistance > radius) {
discard;
return;
} else if (primitiveMultisample == 1) {
float distances = 0.0;
if (distance(vec2(topLeft[0], bottomRight[1]), pixCoord + vec2(0.25, 0.25)) < radius) { distances = distances + 1.0; }
if (distance(vec2(topLeft[0], bottomRight[1]), pixCoord + vec2(0.75, 0.25)) < radius) { distances = distances + 1.0; }
if (distance(vec2(topLeft[0], bottomRight[1]), pixCoord + vec2(0.25, 0.75)) < radius) { distances = distances + 1.0; }
if (distance(vec2(topLeft[0], bottomRight[1]), pixCoord + vec2(0.75, 0.75)) < radius) { distances = distances + 1.0; }
if (distances == 0.0) {
discard;
return;
}
distances = distances / 4.0;
gl_FragColor = )#" + colorVarName + R"#( * distances;
return;
}
}
}
}
else if (pixCoord[0] > bottomRight[0]) {
// we're close right
if (pixCoord[1] < topLeft[1]) {
// top
if (ignoreCorners == 1) {
discard;
return;
}
float topLeftDistance = distance(vec2(bottomRight[0], topLeft[1]), pixCoord);
if (topLeftDistance > radius - 1.0) {
if (primitiveMultisample == 0 && topLeftDistance > radius) {
discard;
return;
} else if (primitiveMultisample == 1) {
float distances = 0.0;
if (distance(vec2(bottomRight[0], topLeft[1]), pixCoord + vec2(0.25, 0.25)) < radius) { distances = distances + 1.0; }
if (distance(vec2(bottomRight[0], topLeft[1]), pixCoord + vec2(0.75, 0.25)) < radius) { distances = distances + 1.0; }
if (distance(vec2(bottomRight[0], topLeft[1]), pixCoord + vec2(0.25, 0.75)) < radius) { distances = distances + 1.0; }
if (distance(vec2(bottomRight[0], topLeft[1]), pixCoord + vec2(0.75, 0.75)) < radius) { distances = distances + 1.0; }
if (distances == 0.0) {
discard;
return;
}
distances = distances / 4.0;
gl_FragColor = )#" + colorVarName + R"#( * distances;
return;
}
}
} else if (pixCoord[1] > bottomRight[1]) {
// bottom
if (ignoreCorners == 1) {
discard;
return;
}
float topLeftDistance = distance(bottomRight, pixCoord);
if (topLeftDistance > radius - 1.0) {
if (primitiveMultisample == 0 && topLeftDistance > radius) {
discard;
return;
} else if (primitiveMultisample == 1) {
float distances = 0.0;
if (distance(bottomRight, pixCoord + vec2(0.25, 0.25)) < radius) { distances = distances + 1.0; }
if (distance(bottomRight, pixCoord + vec2(0.75, 0.25)) < radius) { distances = distances + 1.0; }
if (distance(bottomRight, pixCoord + vec2(0.25, 0.75)) < radius) { distances = distances + 1.0; }
if (distance(bottomRight, pixCoord + vec2(0.75, 0.75)) < radius) { distances = distances + 1.0; }
if (distances == 0.0) {
discard;
return;
}
distances = distances / 4.0;
gl_FragColor = )#" + colorVarName + R"#( * distances;
return;
}
}
}
}
)#";
};
inline const std::string QUADVERTSRC = R"#(
uniform mat3 proj;
uniform vec4 color;
attribute vec2 pos;
attribute vec2 texcoord;
varying vec4 v_color;
varying vec2 v_texcoord;
void main() {
gl_Position = vec4(proj * vec3(pos, 1.0), 1.0);
v_color = color;
v_texcoord = texcoord;
})#";
inline const std::string QUADFRAGSRC = R"#(
precision mediump float;
varying vec4 v_color;
varying vec2 v_texcoord;
uniform vec2 topLeft;
uniform vec2 bottomRight;
uniform vec2 fullSize;
uniform float radius;
uniform int primitiveMultisample;
uniform int ignoreCorners;
void main() {
if (radius == 0.0) {
gl_FragColor = v_color;
return;
}
vec2 pixCoord = fullSize * v_texcoord;
)#" + ROUNDED_SHADER_FUNC("v_color") + R"#(
gl_FragColor = v_color;
})#";
inline const std::string TEXVERTSRC = R"#(
uniform mat3 proj;
attribute vec2 pos;
attribute vec2 texcoord;
varying vec2 v_texcoord;
void main() {
gl_Position = vec4(proj * vec3(pos, 1.0), 1.0);
v_texcoord = texcoord;
})#";
inline const std::string TEXFRAGSRCRGBA = R"#(
precision mediump float;
varying vec2 v_texcoord; // is in 0-1
uniform sampler2D tex;
uniform float alpha;
uniform vec2 topLeft;
uniform vec2 bottomRight;
uniform vec2 fullSize;
uniform float radius;
uniform int discardOpaque;
uniform int primitiveMultisample;
uniform int ignoreCorners;
void main() {
vec4 pixColor = texture2D(tex, v_texcoord);
if (discardOpaque == 1 && pixColor[3] * alpha == 1.0) {
discard;
return;
}
vec2 pixCoord = fullSize * v_texcoord;
)#" + ROUNDED_SHADER_FUNC("pixColor") +
R"#(
gl_FragColor = pixColor * alpha;
})#";
inline const std::string TEXFRAGSRCRGBX = R"#(
precision mediump float;
varying vec2 v_texcoord;
uniform sampler2D tex;
uniform float alpha;
uniform vec2 topLeft;
uniform vec2 bottomRight;
uniform vec2 fullSize;
uniform float radius;
uniform int discardOpaque;
uniform int primitiveMultisample;
uniform int ignoreCorners;
void main() {
if (discardOpaque == 1 && alpha == 1.0) {
discard;
return;
}
vec4 pixColor = vec4(texture2D(tex, v_texcoord).rgb, 1.0);
vec2 pixCoord = fullSize * v_texcoord;
)#" + ROUNDED_SHADER_FUNC("pixColor") + R"#(
gl_FragColor = pixColor * alpha;
})#";
inline const std::string FRAGBLUR1 = R"#(
#version 100
precision mediump float;
varying mediump vec2 v_texcoord; // is in 0-1
uniform sampler2D tex;
uniform float radius;
uniform vec2 halfpixel;
void main() {
vec2 uv = v_texcoord * 2.0;
vec4 sum = texture2D(tex, uv) * 4.0;
sum += texture2D(tex, uv - halfpixel.xy * radius);
sum += texture2D(tex, uv + halfpixel.xy * radius);
sum += texture2D(tex, uv + vec2(halfpixel.x, -halfpixel.y) * radius);
sum += texture2D(tex, uv - vec2(halfpixel.x, -halfpixel.y) * radius);
gl_FragColor = sum / 8.0;
}
)#";
inline const std::string FRAGBLUR2 = R"#(
#version 100
precision mediump float;
varying mediump vec2 v_texcoord; // is in 0-1
uniform sampler2D tex;
uniform float radius;
uniform vec2 halfpixel;
void main() {
vec2 uv = v_texcoord / 2.0;
vec4 sum = texture2D(tex, uv + vec2(-halfpixel.x * 2.0, 0.0) * radius);
sum += texture2D(tex, uv + vec2(-halfpixel.x, halfpixel.y) * radius) * 2.0;
sum += texture2D(tex, uv + vec2(0.0, halfpixel.y * 2.0) * radius);
sum += texture2D(tex, uv + vec2(halfpixel.x, halfpixel.y) * radius) * 2.0;
sum += texture2D(tex, uv + vec2(halfpixel.x * 2.0, 0.0) * radius);
sum += texture2D(tex, uv + vec2(halfpixel.x, -halfpixel.y) * radius) * 2.0;
sum += texture2D(tex, uv + vec2(0.0, -halfpixel.y * 2.0) * radius);
sum += texture2D(tex, uv + vec2(-halfpixel.x, -halfpixel.y) * radius) * 2.0;
gl_FragColor = sum / 12.0;
}
)#";
inline const std::string TEXFRAGSRCEXT = R"#(
#extension GL_OES_EGL_image_external : require
precision mediump float;
varying vec2 v_texcoord;
uniform samplerExternalOES texture0;
uniform float alpha;
uniform vec2 topLeft;
uniform vec2 bottomRight;
uniform vec2 fullSize;
uniform float radius;
uniform int discardOpaque;
uniform int primitiveMultisample;
uniform int ignoreCorners;
void main() {
vec4 pixColor = texture2D(texture0, v_texcoord);
if (discardOpaque == 1 && pixColor[3] * alpha == 1.0) {
discard;
return;
}
vec2 pixCoord = fullSize * v_texcoord;
)#" + ROUNDED_SHADER_FUNC("pixColor") + R"#(
gl_FragColor = pixColor * alpha;
})#";