mirror of
https://github.com/hyprwm/Hyprland.git
synced 2025-08-02 05:01:56 -07:00
Compare commits
41 Commits
v0.6.0beta
...
v0.6.1beta
Author | SHA1 | Date | |
---|---|---|---|
|
0b525cdc63 | ||
|
6a47a305f8 | ||
|
1a0b2c4ade | ||
|
f1a5cb4979 | ||
|
f5c2dfc706 | ||
|
4d09101e23 | ||
|
314e1f8fbe | ||
|
78bf88ba60 | ||
|
29aab21033 | ||
|
adead82778 | ||
|
45898a57c8 | ||
|
2c8cf6afc4 | ||
|
316b49eee2 | ||
|
8de8f6667e | ||
|
648b2c892c | ||
|
2955698f28 | ||
|
747ff3369d | ||
|
b46f45befa | ||
|
3842b1641f | ||
|
72c86b99eb | ||
|
eb13be1240 | ||
|
45a44f9690 | ||
|
e95e01416e | ||
|
94e8234ac9 | ||
|
c78b811b49 | ||
|
3053f99db6 | ||
|
e7467c60f9 | ||
|
3e8842e1f8 | ||
|
81e36298bf | ||
|
218675246f | ||
|
e4e323a0df | ||
|
f76b9c4852 | ||
|
ae60075226 | ||
|
b25bafda08 | ||
|
a8e2595534 | ||
|
3c6526dbbe | ||
|
4945c5887d | ||
|
ccdb03391e | ||
|
6ba5edd13e | ||
|
31dc70a41a | ||
|
f9745b0d3b |
1
.github/FUNDING.yml
vendored
Normal file
1
.github/FUNDING.yml
vendored
Normal file
@@ -0,0 +1 @@
|
||||
ko_fi: vaxry
|
@@ -1,6 +1,6 @@
|
||||
name: "Nix & Meson: update version"
|
||||
|
||||
on: [push, workflow_dispatch]
|
||||
on: [workflow_dispatch]
|
||||
|
||||
jobs:
|
||||
update:
|
@@ -54,6 +54,7 @@ Try it out and report bugs / suggestions!
|
||||
- Custom bezier curve based animations
|
||||
- `wlr_ext` workspaces protocol support
|
||||
- Dual Kawase blur
|
||||
- Drop shadows
|
||||
- Fully dynamic workspaces
|
||||
- Closely follows `wlroots-git`
|
||||
- Bundled wlroots
|
||||
|
@@ -17,8 +17,7 @@ input {
|
||||
}
|
||||
|
||||
general {
|
||||
max_fps=60 # deprecated, unused
|
||||
sensitivity=0.25
|
||||
sensitivity=1.0 # for mouse cursor
|
||||
main_mod=SUPER
|
||||
|
||||
gaps_in=5
|
||||
@@ -27,7 +26,7 @@ general {
|
||||
col.active_border=0x66ee1111
|
||||
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
|
||||
}
|
||||
|
@@ -32,7 +32,7 @@
|
||||
src = inputs.wlroots;
|
||||
});
|
||||
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;
|
||||
};
|
||||
};
|
||||
|
@@ -1,5 +1,5 @@
|
||||
project('Hyprland', 'cpp', 'c',
|
||||
version : '0.5.0beta',
|
||||
version : '0.6.0beta',
|
||||
default_options : ['warning_level=3', 'cpp_std=c++20', 'default_library=static'])
|
||||
|
||||
wlroots = subproject('wlroots', default_options: ['examples=false'])
|
||||
|
@@ -7,6 +7,16 @@ CCompositor::CCompositor() {
|
||||
|
||||
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);
|
||||
|
||||
const auto INSTANCEPATH = "/tmp/hypr/" + m_szInstanceSignature;
|
||||
@@ -770,18 +780,24 @@ void CCompositor::cleanupFadingOut() {
|
||||
}
|
||||
|
||||
CWindow* CCompositor::getWindowInDirection(CWindow* pWindow, char dir) {
|
||||
const auto POSA = pWindow->m_vPosition;
|
||||
const auto SIZEA = pWindow->m_vSize;
|
||||
|
||||
const auto WINDOWIDEALBB = pWindow->getWindowIdealBoundingBoxIgnoreReserved();
|
||||
|
||||
const auto POSA = Vector2D(WINDOWIDEALBB.x, WINDOWIDEALBB.y);
|
||||
const auto SIZEA = Vector2D(WINDOWIDEALBB.width, WINDOWIDEALBB.height);
|
||||
|
||||
auto longestIntersect = -1;
|
||||
CWindow* longestIntersectWindow = nullptr;
|
||||
|
||||
for (auto& w : m_lWindows) {
|
||||
if (&w == pWindow || !windowValidMapped(&w) || w.m_bIsFloating || w.m_iWorkspaceID != pWindow->m_iWorkspaceID)
|
||||
if (&w == pWindow || !windowValidMapped(&w) || w.m_bIsFloating || !isWorkspaceVisible(w.m_iWorkspaceID))
|
||||
continue;
|
||||
|
||||
const auto POSB = w.m_vPosition;
|
||||
const auto SIZEB = w.m_vSize;
|
||||
const auto BWINDOWIDEALBB = w.getWindowIdealBoundingBoxIgnoreReserved();
|
||||
|
||||
const auto POSB = Vector2D(BWINDOWIDEALBB.x, BWINDOWIDEALBB.y);
|
||||
const auto SIZEB = Vector2D(BWINDOWIDEALBB.width, BWINDOWIDEALBB.height);
|
||||
|
||||
switch (dir) {
|
||||
case 'l':
|
||||
if (STICKS(POSA.x, POSB.x + SIZEB.x)) {
|
||||
@@ -1100,3 +1116,17 @@ bool CCompositor::workspaceIDOutOfBounds(const int& 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;
|
||||
}
|
||||
}
|
@@ -132,6 +132,7 @@ public:
|
||||
int getNextAvailableMonitorID();
|
||||
void moveWorkspaceToMonitor(CWorkspace*, SMonitor*);
|
||||
bool workspaceIDOutOfBounds(const int&);
|
||||
void setWindowFullscreen(CWindow*, bool, eFullscreenMode);
|
||||
|
||||
private:
|
||||
void initAllSignals();
|
||||
|
@@ -1,11 +1,14 @@
|
||||
#include "Window.hpp"
|
||||
#include "Compositor.hpp"
|
||||
#include "render/decorations/CHyprDropShadowDecoration.hpp"
|
||||
|
||||
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_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_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() {
|
||||
@@ -16,8 +19,9 @@ CWindow::~CWindow() {
|
||||
}
|
||||
|
||||
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) {
|
||||
|
||||
@@ -44,3 +48,28 @@ wlr_box CWindow::getFullWindowBoundingBox() {
|
||||
|
||||
return finalBox;
|
||||
}
|
||||
|
||||
wlr_box CWindow::getWindowIdealBoundingBoxIgnoreReserved() {
|
||||
|
||||
const auto PMONITOR = g_pCompositor->getMonitorFromID(m_iMonitorID);
|
||||
|
||||
auto POS = m_vPosition;
|
||||
auto SIZE = m_vSize;
|
||||
|
||||
if (DELTALESSTHAN(POS.y - PMONITOR->vecPosition.y, PMONITOR->vecReservedTopLeft.y, 1)) {
|
||||
POS.y = PMONITOR->vecPosition.y;
|
||||
SIZE.y += PMONITOR->vecReservedTopLeft.y;
|
||||
}
|
||||
if (DELTALESSTHAN(POS.x - PMONITOR->vecPosition.x, PMONITOR->vecReservedTopLeft.x, 1)) {
|
||||
POS.x = PMONITOR->vecPosition.x;
|
||||
SIZE.x += PMONITOR->vecReservedTopLeft.x;
|
||||
}
|
||||
if (DELTALESSTHAN(POS.x + SIZE.x - PMONITOR->vecPosition.x, PMONITOR->vecSize.x - PMONITOR->vecReservedBottomRight.x, 1)) {
|
||||
SIZE.x += PMONITOR->vecReservedBottomRight.x;
|
||||
}
|
||||
if (DELTALESSTHAN(POS.y + SIZE.y - PMONITOR->vecPosition.y, PMONITOR->vecSize.y - PMONITOR->vecReservedBottomRight.y, 1)) {
|
||||
SIZE.y += PMONITOR->vecReservedBottomRight.y;
|
||||
}
|
||||
|
||||
return wlr_box{(int)POS.x, (int)POS.y, (int)SIZE.x, (int)SIZE.y};
|
||||
}
|
@@ -15,6 +15,7 @@ struct SWindowSpecialRenderData {
|
||||
struct SWindowAdditionalConfigData {
|
||||
std::string animationStyle = "";
|
||||
int rounding = -1; // -1 means no
|
||||
bool forceNoBlur = false;
|
||||
};
|
||||
|
||||
class CWindow {
|
||||
@@ -75,6 +76,7 @@ public:
|
||||
|
||||
// For nofocus
|
||||
bool m_bNoFocus = false;
|
||||
bool m_bNoInitialFocus = false;
|
||||
|
||||
SSurfaceTreeNode* m_pSurfaceTree = nullptr;
|
||||
|
||||
@@ -108,5 +110,6 @@ public:
|
||||
|
||||
// methods
|
||||
wlr_box getFullWindowBoundingBox();
|
||||
wlr_box getWindowIdealBoundingBoxIgnoreReserved();
|
||||
|
||||
};
|
@@ -18,14 +18,14 @@ CConfigManager::CConfigManager() {
|
||||
}
|
||||
|
||||
void CConfigManager::setDefaultVars() {
|
||||
configValues["general:max_fps"].intValue = 240;
|
||||
configValues["general:sensitivity"].floatValue = 0.25f;
|
||||
configValues["general:max_fps"].intValue = 60;
|
||||
configValues["general:sensitivity"].floatValue = 1.0f;
|
||||
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_internal"].intValue = g_pKeybindManager->stringToModMask("SUPER"); // actually used and automatically calculated
|
||||
|
||||
configValues["general:damage_tracking"].strValue = "none";
|
||||
configValues["general:damage_tracking_internal"].intValue = DAMAGE_TRACKING_NONE;
|
||||
configValues["general:damage_tracking"].strValue = "full";
|
||||
configValues["general:damage_tracking_internal"].intValue = DAMAGE_TRACKING_FULL;
|
||||
|
||||
configValues["general:border_size"].intValue = 1;
|
||||
configValues["general:no_border_on_floating"].intValue = 0;
|
||||
@@ -33,6 +33,7 @@ void CConfigManager::setDefaultVars() {
|
||||
configValues["general:gaps_out"].intValue = 20;
|
||||
configValues["general:col.active_border"].intValue = 0xffffffff;
|
||||
configValues["general:col.inactive_border"].intValue = 0xff444444;
|
||||
configValues["general:cursor_inactive_timeout"].intValue = 0;
|
||||
|
||||
configValues["debug:int"].intValue = 0;
|
||||
configValues["debug:log_damage"].intValue = 0;
|
||||
@@ -46,8 +47,13 @@ void CConfigManager::setDefaultVars() {
|
||||
configValues["decoration:active_opacity"].floatValue = 1;
|
||||
configValues["decoration:inactive_opacity"].floatValue = 1;
|
||||
configValues["decoration:fullscreen_opacity"].floatValue = 1;
|
||||
configValues["decoration:multisample_edges"].intValue = 0;
|
||||
configValues["decoration:multisample_edges"].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:col.group_border"].intValue = 0x66777700;
|
||||
@@ -76,7 +82,7 @@ void CConfigManager::setDefaultVars() {
|
||||
configValues["animations:workspaces_speed"].floatValue = 0.f;
|
||||
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_options"].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("pseudo") != 0
|
||||
&& RULE.find("monitor") != 0
|
||||
&& RULE.find("nofocus") != 0
|
||||
&& RULE != "nofocus"
|
||||
&& RULE != "noblur"
|
||||
&& RULE != "fullscreen"
|
||||
&& RULE.find("animation") != 0
|
||||
&& RULE.find("rounding") != 0
|
||||
&& RULE.find("workspace") != 0) {
|
||||
@@ -911,15 +919,26 @@ std::vector<SWindowRule> CConfigManager::getMatchingRules(CWindow* pWindow) {
|
||||
std::string title = g_pXWaylandManager->getTitle(pWindow);
|
||||
std::string appidclass = g_pXWaylandManager->getAppIDClass(pWindow);
|
||||
|
||||
Debug::log(LOG, "Searching for matching rules for %s (title: %s)", appidclass.c_str(), title.c_str());
|
||||
|
||||
for (auto& rule : m_dWindowRules) {
|
||||
// check if we have a matching rule
|
||||
try {
|
||||
std::regex classCheck(rule.szValue);
|
||||
if (rule.szValue.find("title:") == 0) {
|
||||
// we have a title rule.
|
||||
std::regex RULECHECK(rule.szValue.substr(6));
|
||||
|
||||
if (!std::regex_search(title, classCheck) && !std::regex_search(appidclass, classCheck))
|
||||
continue;
|
||||
if (!std::regex_search(title, RULECHECK))
|
||||
continue;
|
||||
} else {
|
||||
std::regex classCheck(rule.szValue);
|
||||
|
||||
if (!std::regex_search(appidclass, classCheck))
|
||||
continue;
|
||||
}
|
||||
} catch (...) {
|
||||
Debug::log(ERR, "Regex error at %s", rule.szValue.c_str());
|
||||
continue;
|
||||
}
|
||||
|
||||
// applies. Read the rule and behave accordingly
|
||||
|
@@ -24,8 +24,7 @@ input {
|
||||
}
|
||||
|
||||
general {
|
||||
max_fps=60 # deprecated, unused
|
||||
sensitivity=0.25
|
||||
sensitivity=1.0 # for mouse cursor
|
||||
main_mod=SUPER
|
||||
|
||||
gaps_in=5
|
||||
@@ -34,7 +33,7 @@ general {
|
||||
col.active_border=0x66ee1111
|
||||
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
|
||||
}
|
||||
|
@@ -31,6 +31,9 @@ void Debug::log(LogLevel level, const char* fmt, ...) {
|
||||
case CRIT:
|
||||
ofs << "[CRITICAL] ";
|
||||
break;
|
||||
case INFO:
|
||||
ofs << "[INFO] ";
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
@@ -8,7 +8,8 @@ enum LogLevel {
|
||||
LOG = 0,
|
||||
WARN,
|
||||
ERR,
|
||||
CRIT
|
||||
CRIT,
|
||||
INFO
|
||||
};
|
||||
|
||||
namespace Debug {
|
||||
|
@@ -57,6 +57,15 @@ void Events::listener_mouseAxis(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;
|
||||
|
||||
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)
|
||||
wlr_cursor_set_surface(g_pCompositor->m_sWLRCursor, EVENT->surface, EVENT->hotspot_x, EVENT->hotspot_y);
|
||||
}
|
||||
|
@@ -193,6 +193,8 @@ void Events::listener_monitorFrame(void* owner, void* data) {
|
||||
|
||||
if (g_pConfigManager->m_bWantsMonitorReload)
|
||||
g_pConfigManager->performMonitorReload();
|
||||
|
||||
g_pHyprRenderer->ensureCursorRenderingMode(); // so that the cursor gets hidden/shown if the user requested timeouts
|
||||
}
|
||||
|
||||
if (PMONITOR->framesToSkip > 0) {
|
||||
|
@@ -26,6 +26,14 @@ void addPopupGlobalCoords(void* pPopup, int* x, int* y) {
|
||||
px += curPopup->popup->current.geometry.x;
|
||||
py += curPopup->popup->current.geometry.y;
|
||||
|
||||
// fix oversized fucking popups
|
||||
// kill me
|
||||
if (curPopup->pSurfaceTree && curPopup->pSurfaceTree->pSurface && !curPopup->parentPopup) {
|
||||
const auto EXTENTSSURFACE = pixman_region32_extents(&curPopup->pSurfaceTree->pSurface->input_region);
|
||||
px -= EXTENTSSURFACE->x1;
|
||||
py -= EXTENTSSURFACE->y1;
|
||||
}
|
||||
|
||||
if (curPopup->parentPopup) {
|
||||
curPopup = curPopup->parentPopup;
|
||||
} else {
|
||||
|
@@ -78,7 +78,7 @@ void Events::listener_mapWindow(void* owner, void* data) {
|
||||
|
||||
if (PWORKSPACE->m_bHasFullscreenWindow && !PWINDOW->m_bIsFloating) {
|
||||
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);
|
||||
}
|
||||
|
||||
@@ -86,6 +86,7 @@ void Events::listener_mapWindow(void* owner, void* data) {
|
||||
const auto WINDOWRULES = g_pConfigManager->getMatchingRules(PWINDOW);
|
||||
std::string requestedWorkspace = "";
|
||||
bool workspaceSilent = false;
|
||||
bool requestsFullscreen = false;
|
||||
|
||||
for (auto& r : WINDOWRULES) {
|
||||
if (r.szRule.find("monitor") == 0) {
|
||||
@@ -127,6 +128,10 @@ void Events::listener_mapWindow(void* owner, void* data) {
|
||||
PWINDOW->m_bIsPseudotiled = true;
|
||||
} else if (r.szRule.find("nofocus") == 0) {
|
||||
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) {
|
||||
try {
|
||||
PWINDOW->m_sAdditionalConfigData.rounding = std::stoi(r.szRule.substr(r.szRule.find_first_of(' ') + 1));
|
||||
@@ -223,7 +228,7 @@ void Events::listener_mapWindow(void* owner, void* data) {
|
||||
PWINDOW->m_vPseudoSize = PWINDOW->m_vRealSize.goalv() - Vector2D(10,10);
|
||||
}
|
||||
|
||||
if (!PWINDOW->m_bNoFocus)
|
||||
if (!PWINDOW->m_bNoFocus && !PWINDOW->m_bNoInitialFocus)
|
||||
g_pCompositor->focusWindow(PWINDOW);
|
||||
|
||||
PWINDOW->m_pSurfaceTree = SubsurfaceTree::createTreeRoot(g_pXWaylandManager->getWindowSurface(PWINDOW), addViewCoords, PWINDOW, PWINDOW);
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -384,9 +393,9 @@ void Events::listener_fullscreenWindow(void* owner, void* data) {
|
||||
const auto REQUESTED = &PWINDOW->m_uSurface.xdg->toplevel->requested;
|
||||
|
||||
if (REQUESTED->fullscreen != PWINDOW->m_bIsFullscreen)
|
||||
g_pLayoutManager->getCurrentLayout()->fullscreenRequestForWindow(PWINDOW, FULLSCREEN_FULL);
|
||||
g_pLayoutManager->getCurrentLayout()->fullscreenRequestForWindow(PWINDOW, FULLSCREEN_FULL, true);
|
||||
} 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);
|
||||
|
@@ -2,6 +2,7 @@
|
||||
#include "../defines.hpp"
|
||||
#include <algorithm>
|
||||
#include "../Compositor.hpp"
|
||||
#include <sys/utsname.h>
|
||||
|
||||
void addWLSignal(wl_signal* pSignal, wl_listener* pListener, void* pOwner, std::string ownerString) {
|
||||
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));
|
||||
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());
|
||||
}
|
@@ -11,5 +11,7 @@ bool isNumber(const std::string&);
|
||||
bool isDirection(const std::string&);
|
||||
int getWorkspaceIDFromString(const std::string&, std::string&);
|
||||
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);
|
17
src/helpers/Timer.cpp
Normal file
17
src/helpers/Timer.cpp
Normal 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
15
src/helpers/Timer.hpp
Normal 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();
|
||||
};
|
@@ -71,6 +71,8 @@ struct SKeyboard {
|
||||
|
||||
bool active = false;
|
||||
|
||||
xkb_rule_names currentRules;
|
||||
|
||||
// For the list lookup
|
||||
bool operator==(const SKeyboard& rhs) {
|
||||
return keyboard == rhs.keyboard;
|
||||
|
@@ -482,6 +482,9 @@ void CHyprDwindleLayout::onBeginDragWindow() {
|
||||
void CHyprDwindleLayout::onEndDragWindow() {
|
||||
const auto DRAGGINGWINDOW = g_pInputManager->currentlyDraggedWindow;
|
||||
|
||||
if (!g_pCompositor->windowValidMapped(DRAGGINGWINDOW))
|
||||
return;
|
||||
|
||||
if (DRAGGINGWINDOW->m_bDraggingTiled) {
|
||||
DRAGGINGWINDOW->m_bIsFloating = false;
|
||||
changeWindowFloatingMode(DRAGGINGWINDOW);
|
||||
@@ -494,8 +497,10 @@ void CHyprDwindleLayout::onMouseMove(const Vector2D& mousePos) {
|
||||
const auto DRAGGINGWINDOW = g_pInputManager->currentlyDraggedWindow;
|
||||
|
||||
// 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;
|
||||
}
|
||||
|
||||
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);
|
||||
@@ -545,11 +550,7 @@ void CHyprDwindleLayout::resizeActiveWindow(const Vector2D& pixResize, CWindow*
|
||||
const auto PNODE = getNodeFromWindow(PWINDOW);
|
||||
|
||||
if (!PNODE) {
|
||||
PWINDOW->m_vRealSize.setValueAndWarp(PWINDOW->m_vRealSize.goalv() + pixResize);
|
||||
PWINDOW->m_vRealSize.setValueAndWarp(Vector2D(std::clamp(PWINDOW->m_vRealSize.vec().x, (double)20, (double)999999), std::clamp(PWINDOW->m_vRealSize.vec().y, (double)20, (double)999999)));
|
||||
|
||||
g_pXWaylandManager->setWindowSize(PWINDOW, PWINDOW->m_vRealSize.goalv());
|
||||
|
||||
PWINDOW->m_vRealSize = Vector2D(std::clamp((PWINDOW->m_vRealSize.goalv() + pixResize).x, (double)20, (double)999999), std::clamp((PWINDOW->m_vRealSize.goalv() + pixResize).y, (double)20, (double)999999));
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -675,21 +676,24 @@ void CHyprDwindleLayout::onWindowCreatedFloating(CWindow* 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))
|
||||
return;
|
||||
|
||||
if (on == pWindow->m_bIsFullscreen)
|
||||
return; // ignore
|
||||
|
||||
const auto PMONITOR = g_pCompositor->getMonitorFromID(pWindow->m_iMonitorID);
|
||||
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,
|
||||
// ignore the request.
|
||||
return;
|
||||
}
|
||||
|
||||
// otherwise, accept it.
|
||||
pWindow->m_bIsFullscreen = !pWindow->m_bIsFullscreen;
|
||||
pWindow->m_bIsFullscreen = on;
|
||||
PWORKSPACE->m_bHasFullscreenWindow = !PWORKSPACE->m_bHasFullscreenWindow;
|
||||
|
||||
if (!pWindow->m_bIsFullscreen) {
|
||||
@@ -906,6 +910,11 @@ void CHyprDwindleLayout::switchWindows(CWindow* pWindow, CWindow* pWindow2) {
|
||||
if (!PNODE2 || !PNODE)
|
||||
return;
|
||||
|
||||
if (PNODE->workspaceID != PNODE2->workspaceID) {
|
||||
Debug::log(ERR, "Dwindle: Rejecting a swap between workspaces");
|
||||
return;
|
||||
}
|
||||
|
||||
// we will not delete the nodes, just fix the tree
|
||||
if (PNODE2->pParent == PNODE->pParent) {
|
||||
const auto PPARENT = PNODE->pParent;
|
||||
@@ -993,3 +1002,19 @@ void CHyprDwindleLayout::toggleSplit(CWindow* pWindow) {
|
||||
std::string CHyprDwindleLayout::getLayoutName() {
|
||||
return "dwindle";
|
||||
}
|
||||
|
||||
void CHyprDwindleLayout::moveActiveWindow(const Vector2D& delta, CWindow* pWindow) {
|
||||
const auto PWINDOW = pWindow ? pWindow : g_pCompositor->m_pLastWindow;
|
||||
|
||||
if (!g_pCompositor->windowValidMapped(PWINDOW))
|
||||
return;
|
||||
|
||||
if (!PWINDOW->m_bIsFloating) {
|
||||
Debug::log(LOG, "Dwindle cannot move a tiled window in moveActiveWindow!");
|
||||
return;
|
||||
}
|
||||
|
||||
PWINDOW->m_vRealPosition = PWINDOW->m_vRealPosition.goalv() + delta;
|
||||
|
||||
g_pHyprRenderer->damageWindow(PWINDOW);
|
||||
}
|
@@ -49,10 +49,11 @@ public:
|
||||
virtual void changeWindowFloatingMode(CWindow*);
|
||||
virtual void onBeginDragWindow();
|
||||
virtual void resizeActiveWindow(const Vector2D&, CWindow* pWindow = nullptr);
|
||||
virtual void moveActiveWindow(const Vector2D&, CWindow* pWindow = nullptr);
|
||||
virtual void onEndDragWindow();
|
||||
virtual void onMouseMove(const Vector2D&);
|
||||
virtual void onWindowCreatedFloating(CWindow*);
|
||||
virtual void fullscreenRequestForWindow(CWindow*, eFullscreenMode);
|
||||
virtual void fullscreenRequestForWindow(CWindow*, eFullscreenMode, bool);
|
||||
virtual std::any layoutMessage(SLayoutMessageHeader, std::string);
|
||||
virtual SWindowRenderLayoutHints requestRenderHints(CWindow*);
|
||||
virtual void switchWindows(CWindow*, CWindow*);
|
||||
|
@@ -55,6 +55,12 @@ public:
|
||||
Optional pWindow for a specific window
|
||||
*/
|
||||
virtual void resizeActiveWindow(const Vector2D&, CWindow* pWindow = nullptr) = 0;
|
||||
/*
|
||||
Called when a user requests a move of the current window by a vec
|
||||
Vector2D holds pixel values
|
||||
Optional pWindow for a specific window
|
||||
*/
|
||||
virtual void moveActiveWindow(const Vector2D&, CWindow* pWindow = nullptr) = 0;
|
||||
/*
|
||||
Called when a window is ended being dragged
|
||||
(mouse up)
|
||||
@@ -78,7 +84,7 @@ public:
|
||||
The layout sets all the fullscreen flags.
|
||||
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
|
||||
|
@@ -28,6 +28,7 @@ CKeybindManager::CKeybindManager() {
|
||||
m_mDispatchers["togglespecialworkspace"] = toggleSpecialWorkspace;
|
||||
m_mDispatchers["forcerendererreload"] = forceRendererReload;
|
||||
m_mDispatchers["resizeactive"] = resizeActive;
|
||||
m_mDispatchers["moveactive"] = moveActive;
|
||||
m_mDispatchers["cyclenext"] = circleNext;
|
||||
m_mDispatchers["focuswindowbyclass"] = focusWindowByClass;
|
||||
m_mDispatchers["submap"] = setSubmap;
|
||||
@@ -365,14 +366,7 @@ void CKeybindManager::fullscreenActive(std::string args) {
|
||||
if (!g_pCompositor->windowValidMapped(PWINDOW))
|
||||
return;
|
||||
|
||||
g_pLayoutManager->getCurrentLayout()->fullscreenRequestForWindow(PWINDOW, args == "1" ? eFullscreenMode::FULLSCREEN_MAXIMIZED : eFullscreenMode::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;
|
||||
}
|
||||
g_pCompositor->setWindowFullscreen(PWINDOW, !PWINDOW->m_bIsFullscreen, args == "1" ? FULLSCREEN_MAXIMIZED : FULLSCREEN_FULL);
|
||||
}
|
||||
|
||||
void CKeybindManager::moveActiveToWorkspace(std::string args) {
|
||||
@@ -892,6 +886,37 @@ void CKeybindManager::resizeActive(std::string args) {
|
||||
std::string x = args.substr(0, args.find_first_of(' '));
|
||||
std::string y = args.substr(args.find_first_of(' ') + 1);
|
||||
|
||||
if (x == "exact") {
|
||||
std::string newX = y.substr(0, y.find_first_of(' '));
|
||||
std::string newY = y.substr(y.find_first_of(' ') + 1);
|
||||
|
||||
if (!isNumber(newX) || !isNumber(newY)) {
|
||||
Debug::log(ERR, "resizeTiledWindow: exact args not numbers");
|
||||
return;
|
||||
}
|
||||
|
||||
const int X = std::stoi(newX);
|
||||
const int Y = std::stoi(newY);
|
||||
|
||||
if (X < 10 || Y < 10) {
|
||||
Debug::log(ERR, "resizeTiledWindow: exact args cannot be < 10");
|
||||
return;
|
||||
}
|
||||
|
||||
// calc the delta
|
||||
if (!g_pCompositor->windowValidMapped(g_pCompositor->m_pLastWindow))
|
||||
return; // ignore
|
||||
|
||||
const auto PWINDOW = g_pCompositor->m_pLastWindow;
|
||||
|
||||
const int DX = X - PWINDOW->m_vRealSize.goalv().x;
|
||||
const int DY = Y - PWINDOW->m_vRealSize.goalv().y;
|
||||
|
||||
g_pLayoutManager->getCurrentLayout()->resizeActiveWindow(Vector2D(DX, DY));
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
if (!isNumber(x) || !isNumber(y)) {
|
||||
Debug::log(ERR, "resizeTiledWindow: args not numbers");
|
||||
return;
|
||||
@@ -903,6 +928,55 @@ void CKeybindManager::resizeActive(std::string args) {
|
||||
g_pLayoutManager->getCurrentLayout()->resizeActiveWindow(Vector2D(X, Y));
|
||||
}
|
||||
|
||||
void CKeybindManager::moveActive(std::string args) {
|
||||
if (args.find_first_of(' ') == std::string::npos)
|
||||
return;
|
||||
|
||||
std::string x = args.substr(0, args.find_first_of(' '));
|
||||
std::string y = args.substr(args.find_first_of(' ') + 1);
|
||||
|
||||
if (x == "exact") {
|
||||
std::string newX = y.substr(0, y.find_first_of(' '));
|
||||
std::string newY = y.substr(y.find_first_of(' ') + 1);
|
||||
|
||||
if (!isNumber(newX) || !isNumber(newY)) {
|
||||
Debug::log(ERR, "moveActive: exact args not numbers");
|
||||
return;
|
||||
}
|
||||
|
||||
const int X = std::stoi(newX);
|
||||
const int Y = std::stoi(newY);
|
||||
|
||||
if (X < 0 || Y < 0) {
|
||||
Debug::log(ERR, "moveActive: exact args cannot be < 0");
|
||||
return;
|
||||
}
|
||||
|
||||
// calc the delta
|
||||
if (!g_pCompositor->windowValidMapped(g_pCompositor->m_pLastWindow))
|
||||
return; // ignore
|
||||
|
||||
const auto PWINDOW = g_pCompositor->m_pLastWindow;
|
||||
|
||||
const int DX = X - PWINDOW->m_vRealPosition.goalv().x;
|
||||
const int DY = Y - PWINDOW->m_vRealPosition.goalv().y;
|
||||
|
||||
g_pLayoutManager->getCurrentLayout()->moveActiveWindow(Vector2D(DX, DY));
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
if (!isNumber(x) || !isNumber(y)) {
|
||||
Debug::log(ERR, "moveActive: args not numbers");
|
||||
return;
|
||||
}
|
||||
|
||||
const int X = std::stoi(x);
|
||||
const int Y = std::stoi(y);
|
||||
|
||||
g_pLayoutManager->getCurrentLayout()->moveActiveWindow(Vector2D(X, Y));
|
||||
}
|
||||
|
||||
void CKeybindManager::circleNext(std::string) {
|
||||
if (!g_pCompositor->windowValidMapped(g_pCompositor->m_pLastWindow))
|
||||
return;
|
||||
@@ -918,6 +992,9 @@ void CKeybindManager::focusWindowByClass(std::string clazz) {
|
||||
std::regex classCheck(clazz);
|
||||
|
||||
for (auto& w : g_pCompositor->m_lWindows) {
|
||||
if (!w.m_bIsMapped || w.m_bHidden)
|
||||
continue;
|
||||
|
||||
const auto windowClass = g_pXWaylandManager->getAppIDClass(&w);
|
||||
|
||||
if (!std::regex_search(windowClass, classCheck))
|
||||
|
@@ -58,6 +58,7 @@ private:
|
||||
static void toggleSpecialWorkspace(std::string);
|
||||
static void forceRendererReload(std::string);
|
||||
static void resizeActive(std::string);
|
||||
static void moveActive(std::string);
|
||||
static void circleNext(std::string);
|
||||
static void focusWindowByClass(std::string);
|
||||
static void setSubmap(std::string);
|
||||
|
@@ -146,8 +146,10 @@ bool CHyprXWaylandManager::shouldBeFloated(CWindow* pWindow) {
|
||||
if (pWindow->m_uSurface.xwayland->window_type[i] == HYPRATOMS["_NET_WM_WINDOW_TYPE_DIALOG"] || pWindow->m_uSurface.xwayland->window_type[i] == HYPRATOMS["_NET_WM_WINDOW_TYPE_SPLASH"] ||
|
||||
pWindow->m_uSurface.xwayland->window_type[i] == HYPRATOMS["_NET_WM_WINDOW_TYPE_TOOLBAR"] || pWindow->m_uSurface.xwayland->window_type[i] == HYPRATOMS["_NET_WM_WINDOW_TYPE_UTILITY"] ||
|
||||
pWindow->m_uSurface.xwayland->window_type[i] == HYPRATOMS["_NET_WM_WINDOW_TYPE_TOOLTIP"] || pWindow->m_uSurface.xwayland->window_type[i] == HYPRATOMS["_NET_WM_WINDOW_TYPE_POPUP_MENU"] ||
|
||||
pWindow->m_uSurface.xwayland->window_type[i] == HYPRATOMS["_NET_WM_WINDOW_TYPE_DOCK"] || pWindow->m_uSurface.xwayland->window_type[i] == HYPRATOMS["_NET_WM_WINDOW_TYPE_DROPDOWN_MENU"])
|
||||
pWindow->m_uSurface.xwayland->window_type[i] == HYPRATOMS["_NET_WM_WINDOW_TYPE_DOCK"] || pWindow->m_uSurface.xwayland->window_type[i] == HYPRATOMS["_NET_WM_WINDOW_TYPE_DROPDOWN_MENU"] ||
|
||||
pWindow->m_uSurface.xwayland->window_type[i] == HYPRATOMS["_NET_WM_WINDOW_TYPE_MENU"])
|
||||
{
|
||||
pWindow->m_bNoInitialFocus = true;
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@@ -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);
|
||||
|
||||
mouseMoveUnified(e->time_msec);
|
||||
|
||||
m_tmrLastCursorMovement.reset();
|
||||
}
|
||||
|
||||
void CInputManager::onMouseWarp(wlr_pointer_motion_absolute_event* e) {
|
||||
wlr_cursor_warp_absolute(g_pCompositor->m_sWLRCursor, &e->pointer->base, e->x, e->y);
|
||||
|
||||
mouseMoveUnified(e->time_msec);
|
||||
|
||||
m_tmrLastCursorMovement.reset();
|
||||
}
|
||||
|
||||
void CInputManager::mouseMoveUnified(uint32_t time, bool refocus) {
|
||||
@@ -205,8 +209,15 @@ void CInputManager::mouseMoveUnified(uint32_t time, bool refocus) {
|
||||
void CInputManager::onMouseButton(wlr_pointer_button_event* e) {
|
||||
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);
|
||||
|
||||
if (!PKEYBOARD) { // ???
|
||||
Debug::log(ERR, "No active keyboard in onMouseButton??");
|
||||
return;
|
||||
}
|
||||
|
||||
switch (e->state) {
|
||||
case WLR_BUTTON_PRESSED:
|
||||
if (!g_pCompositor->m_sSeat.mouse->currentConstraint)
|
||||
@@ -266,7 +277,7 @@ void CInputManager::newKeyboard(wlr_input_device* keyboard) {
|
||||
m_pActiveKeyboard->active = false;
|
||||
m_pActiveKeyboard = PNEWKEYBOARD;
|
||||
|
||||
setKeyboardLayout();
|
||||
applyConfigToKeyboard(PNEWKEYBOARD);
|
||||
|
||||
wlr_seat_set_keyboard(g_pCompositor->m_sSeat.seat, keyboard->keyboard);
|
||||
|
||||
@@ -274,41 +285,55 @@ void CInputManager::newKeyboard(wlr_input_device* keyboard) {
|
||||
}
|
||||
|
||||
void CInputManager::setKeyboardLayout() {
|
||||
for (auto& k : m_lKeyboards)
|
||||
applyConfigToKeyboard(&k);
|
||||
}
|
||||
|
||||
const auto RULES = g_pConfigManager->getString("input:kb_rules");
|
||||
const auto MODEL = g_pConfigManager->getString("input:kb_model");
|
||||
const auto LAYOUT = g_pConfigManager->getString("input:kb_layout");
|
||||
const auto VARIANT = g_pConfigManager->getString("input:kb_variant");
|
||||
const auto OPTIONS = g_pConfigManager->getString("input:kb_options");
|
||||
void CInputManager::applyConfigToKeyboard(SKeyboard* pKeyboard) {
|
||||
|
||||
ASSERT(pKeyboard);
|
||||
|
||||
const auto RULES = g_pConfigManager->getString("input:kb_rules");
|
||||
const auto MODEL = g_pConfigManager->getString("input:kb_model");
|
||||
const auto LAYOUT = g_pConfigManager->getString("input:kb_layout");
|
||||
const auto VARIANT = g_pConfigManager->getString("input:kb_variant");
|
||||
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 = {
|
||||
.rules = RULES.c_str(),
|
||||
.model = MODEL.c_str(),
|
||||
.layout = LAYOUT.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 KEYMAP = xkb_keymap_new_from_names(CONTEXT, &rules, XKB_KEYMAP_COMPILE_NO_FLAGS);
|
||||
|
||||
if (!CONTEXT) {
|
||||
Debug::log(ERR, "applyConfigToKeyboard: CONTEXT null??");
|
||||
return;
|
||||
}
|
||||
|
||||
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) {
|
||||
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);
|
||||
return;
|
||||
memset(&rules, 0, sizeof(rules));
|
||||
|
||||
pKeyboard->currentRules = rules;
|
||||
|
||||
KEYMAP = xkb_keymap_new_from_names(CONTEXT, &rules, XKB_KEYMAP_COMPILE_NO_FLAGS);
|
||||
}
|
||||
|
||||
const auto PLASTKEEB = m_pActiveKeyboard->keyboard->keyboard;
|
||||
|
||||
if (!PLASTKEEB) {
|
||||
xkb_keymap_unref(KEYMAP);
|
||||
xkb_context_unref(CONTEXT);
|
||||
|
||||
Debug::log(ERR, "No Seat Keyboard???");
|
||||
return;
|
||||
}
|
||||
|
||||
wlr_keyboard_set_keymap(PLASTKEEB, KEYMAP);
|
||||
wlr_keyboard_set_keymap(pKeyboard->keyboard->keyboard, KEYMAP);
|
||||
|
||||
wlr_keyboard_modifiers wlrMods = {0};
|
||||
|
||||
@@ -321,13 +346,13 @@ void CInputManager::setKeyboardLayout() {
|
||||
}
|
||||
|
||||
if (wlrMods.locked != 0) {
|
||||
wlr_keyboard_notify_modifiers(g_pInputManager->m_pActiveKeyboard->keyboard->keyboard, 0, 0, wlrMods.locked, 0);
|
||||
wlr_keyboard_notify_modifiers(pKeyboard->keyboard->keyboard, 0, 0, wlrMods.locked, 0);
|
||||
}
|
||||
|
||||
xkb_keymap_unref(KEYMAP);
|
||||
xkb_context_unref(CONTEXT);
|
||||
|
||||
Debug::log(LOG, "Set the keyboard layout to %s and variant to %s", rules.layout, rules.variant);
|
||||
Debug::log(LOG, "Set the keyboard layout to %s and variant to %s for keyboard \"%s\"", rules.layout, rules.variant, pKeyboard->keyboard->name);
|
||||
}
|
||||
|
||||
void CInputManager::newMouse(wlr_input_device* mouse) {
|
||||
@@ -376,6 +401,8 @@ void CInputManager::newMouse(wlr_input_device* mouse) {
|
||||
|
||||
g_pCompositor->m_sSeat.mouse = PMOUSE;
|
||||
|
||||
m_tmrLastCursorMovement.reset();
|
||||
|
||||
Debug::log(LOG, "New mouse created, pointer WLR: %x", mouse);
|
||||
}
|
||||
|
||||
|
@@ -4,6 +4,7 @@
|
||||
#include <list>
|
||||
#include "../../helpers/WLClasses.hpp"
|
||||
#include "../../Window.hpp"
|
||||
#include "../../helpers/Timer.hpp"
|
||||
|
||||
class CInputManager {
|
||||
public:
|
||||
@@ -52,13 +53,17 @@ public:
|
||||
|
||||
SKeyboard* m_pActiveKeyboard = nullptr;
|
||||
|
||||
private:
|
||||
CTimer m_tmrLastCursorMovement;
|
||||
|
||||
private:
|
||||
|
||||
uint32_t m_uiCapabilities = 0;
|
||||
|
||||
void mouseMoveUnified(uint32_t, bool refocus = false);
|
||||
|
||||
STabletTool* ensureTabletToolPresent(wlr_tablet_tool*);
|
||||
|
||||
void applyConfigToKeyboard(SKeyboard*);
|
||||
};
|
||||
|
||||
inline std::unique_ptr<CInputManager> g_pInputManager;
|
@@ -75,6 +75,18 @@ CHyprOpenGLImpl::CHyprOpenGLImpl() {
|
||||
m_shBLUR2.posAttrib = glGetAttribLocation(prog, "pos");
|
||||
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");
|
||||
|
||||
prog = createProgram(QUADVERTSRC, FRAGBORDER1);
|
||||
m_shBORDER1.program = prog;
|
||||
m_shBORDER1.proj = glGetUniformLocation(prog, "proj");
|
||||
m_shBORDER1.posAttrib = glGetAttribLocation(prog, "pos");
|
||||
m_shBORDER1.texAttrib = glGetAttribLocation(prog, "texcoord");
|
||||
|
||||
Debug::log(LOG, "Shaders initialized successfully.");
|
||||
|
||||
// End shaders
|
||||
@@ -303,15 +315,15 @@ void CHyprOpenGLImpl::renderTexture(wlr_texture* tex, wlr_box* pBox, float alpha
|
||||
renderTexture(CTexture(tex), pBox, alpha, round);
|
||||
}
|
||||
|
||||
void CHyprOpenGLImpl::renderTexture(const CTexture& tex, wlr_box* pBox, float alpha, int round, bool discardopaque, bool border, bool allowPrimary) {
|
||||
void CHyprOpenGLImpl::renderTexture(const CTexture& tex, wlr_box* pBox, float alpha, int round, bool discardopaque, bool allowPrimary) {
|
||||
RASSERT(m_RenderData.pMonitor, "Tried to render texture without begin()!");
|
||||
|
||||
renderTextureInternalWithDamage(tex, pBox, alpha, m_RenderData.pDamage, round, discardopaque, border, false, allowPrimary);
|
||||
renderTextureInternalWithDamage(tex, pBox, alpha, m_RenderData.pDamage, round, discardopaque, false, allowPrimary);
|
||||
|
||||
scissor((wlr_box*)nullptr);
|
||||
}
|
||||
|
||||
void CHyprOpenGLImpl::renderTextureInternalWithDamage(const CTexture& tex, wlr_box* pBox, float alpha, pixman_region32_t* damage, int round, bool discardOpaque, bool border, bool noAA, bool allowPrimary) {
|
||||
void CHyprOpenGLImpl::renderTextureInternalWithDamage(const CTexture& tex, wlr_box* pBox, float alpha, pixman_region32_t* damage, int round, bool discardOpaque, bool noAA, bool allowPrimary) {
|
||||
RASSERT(m_RenderData.pMonitor, "Tried to render texture without begin()!");
|
||||
RASSERT((tex.m_iTexID > 0), "Attempted to draw NULL texture!");
|
||||
|
||||
@@ -345,23 +357,6 @@ void CHyprOpenGLImpl::renderTextureInternalWithDamage(const CTexture& tex, wlr_b
|
||||
RASSERT(false, "tex.m_iTarget unsupported!");
|
||||
}
|
||||
|
||||
// stencil for when we want a border
|
||||
if (border) {
|
||||
glClearStencil(0);
|
||||
glClear(GL_STENCIL_BUFFER_BIT);
|
||||
|
||||
glEnable(GL_STENCIL_TEST);
|
||||
|
||||
glStencilFunc(GL_ALWAYS, 1, -1);
|
||||
glStencilOp(GL_REPLACE, GL_REPLACE, GL_REPLACE);
|
||||
|
||||
// hacky fix to fix broken borders.
|
||||
// TODO: this is kinda slow... question mark?
|
||||
renderRect(pBox, CColor(0, 0, 0, 0), round);
|
||||
|
||||
glDisable(GL_STENCIL_TEST);
|
||||
}
|
||||
|
||||
glActiveTexture(GL_TEXTURE0);
|
||||
glBindTexture(tex.m_iTarget, tex.m_iTexID);
|
||||
|
||||
@@ -378,8 +373,8 @@ void CHyprOpenGLImpl::renderTextureInternalWithDamage(const CTexture& tex, wlr_b
|
||||
// so we need to do some maf
|
||||
|
||||
const auto TOPLEFT = Vector2D(round, round);
|
||||
const auto BOTTOMRIGHT = Vector2D(tex.m_vSize.x - round, tex.m_vSize.y - round);
|
||||
const auto FULLSIZE = tex.m_vSize;
|
||||
const auto BOTTOMRIGHT = Vector2D(pBox->width - round, pBox->height - round);
|
||||
const auto FULLSIZE = Vector2D(pBox->width, pBox->height);
|
||||
static auto *const PMULTISAMPLEEDGES = &g_pConfigManager->getConfigValuePtr("decoration:multisample_edges")->intValue;
|
||||
|
||||
// Rounded corners
|
||||
@@ -387,7 +382,7 @@ void CHyprOpenGLImpl::renderTextureInternalWithDamage(const CTexture& tex, wlr_b
|
||||
glUniform2f(glGetUniformLocation(shader->program, "bottomRight"), (float)BOTTOMRIGHT.x, (float)BOTTOMRIGHT.y);
|
||||
glUniform2f(glGetUniformLocation(shader->program, "fullSize"), (float)FULLSIZE.x, (float)FULLSIZE.y);
|
||||
glUniform1f(glGetUniformLocation(shader->program, "radius"), round);
|
||||
glUniform1i(glGetUniformLocation(shader->program, "primitiveMultisample"), (int)(*PMULTISAMPLEEDGES == 1 && round != 0 && !border && !noAA));
|
||||
glUniform1i(glGetUniformLocation(shader->program, "primitiveMultisample"), (int)(*PMULTISAMPLEEDGES == 1 && round != 0 && !noAA));
|
||||
|
||||
glVertexAttribPointer(shader->posAttrib, 2, GL_FLOAT, GL_FALSE, 0, fullVerts);
|
||||
|
||||
@@ -415,30 +410,10 @@ void CHyprOpenGLImpl::renderTextureInternalWithDamage(const CTexture& tex, wlr_b
|
||||
}
|
||||
}
|
||||
|
||||
if (border) {
|
||||
glEnable(GL_STENCIL_TEST);
|
||||
|
||||
glStencilFunc(GL_EQUAL, 1, -1);
|
||||
glStencilOp(GL_KEEP, GL_KEEP, GL_REPLACE);
|
||||
}
|
||||
|
||||
glDisableVertexAttribArray(shader->posAttrib);
|
||||
glDisableVertexAttribArray(shader->texAttrib);
|
||||
|
||||
glBindTexture(tex.m_iTarget, 0);
|
||||
|
||||
// if border draw
|
||||
// we dont disable stencil here if we havent touched it.
|
||||
// some other func might be using it.
|
||||
if (border) {
|
||||
auto BORDERCOL = m_pCurrentWindow->m_cRealBorderColor.col();
|
||||
static auto *const PBORDERSIZE = &g_pConfigManager->getConfigValuePtr("general:border_size")->intValue;
|
||||
BORDERCOL.a *= alpha / 255.f;
|
||||
renderBorder(pBox, BORDERCOL, *PBORDERSIZE, round);
|
||||
glStencilMask(-1);
|
||||
glStencilFunc(GL_ALWAYS, 1, 0xFF);
|
||||
glDisable(GL_STENCIL_TEST);
|
||||
}
|
||||
}
|
||||
|
||||
// This probably isn't the fastest
|
||||
@@ -560,14 +535,14 @@ CFramebuffer* CHyprOpenGLImpl::blurMainFramebufferWithDamage(float a, wlr_box* p
|
||||
return currentRenderToFB;
|
||||
}
|
||||
|
||||
void CHyprOpenGLImpl::renderTextureWithBlur(const CTexture& tex, wlr_box* pBox, float a, wlr_surface* pSurface, int round, bool border) {
|
||||
void CHyprOpenGLImpl::renderTextureWithBlur(const CTexture& tex, wlr_box* pBox, float a, wlr_surface* pSurface, int round) {
|
||||
RASSERT(m_RenderData.pMonitor, "Tried to render texture with blur without begin()!");
|
||||
|
||||
static auto *const PBLURENABLED = &g_pConfigManager->getConfigValuePtr("decoration:blur")->intValue;
|
||||
static auto* const PNOBLUROVERSIZED = &g_pConfigManager->getConfigValuePtr("decoration:no_blur_on_oversized")->intValue;
|
||||
|
||||
if (*PBLURENABLED == 0 || (*PNOBLUROVERSIZED && m_RenderData.primarySurfaceUVTopLeft != Vector2D(-1, -1))) {
|
||||
renderTexture(tex, pBox, a, round, false, border, true);
|
||||
if (*PBLURENABLED == 0 || (*PNOBLUROVERSIZED && m_RenderData.primarySurfaceUVTopLeft != Vector2D(-1, -1)) || (m_pCurrentWindow && m_pCurrentWindow->m_sAdditionalConfigData.forceNoBlur)) {
|
||||
renderTexture(tex, pBox, a, round, false, true);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -590,7 +565,7 @@ void CHyprOpenGLImpl::renderTextureWithBlur(const CTexture& tex, wlr_box* pBox,
|
||||
}
|
||||
|
||||
if (!pixman_region32_not_empty(&inverseOpaque)) {
|
||||
renderTexture(tex, pBox, a, round, false, border); // reject blurring a fully opaque window
|
||||
renderTexture(tex, pBox, a, round, false); // reject blurring a fully opaque window
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -624,7 +599,7 @@ void CHyprOpenGLImpl::renderTextureWithBlur(const CTexture& tex, wlr_box* pBox,
|
||||
if (pixman_region32_not_empty(&damage)) {
|
||||
// render our great blurred FB
|
||||
static auto *const PBLURIGNOREOPACITY = &g_pConfigManager->getConfigValuePtr("decoration:blur_ignore_opacity")->intValue;
|
||||
renderTextureInternalWithDamage(POUTFB->m_cTex, &MONITORBOX, *PBLURIGNOREOPACITY ? 255.f : a, &damage, 0, false, false, false, true);
|
||||
renderTextureInternalWithDamage(POUTFB->m_cTex, &MONITORBOX, *PBLURIGNOREOPACITY ? 255.f : a, &damage, 0, false, false, true);
|
||||
|
||||
// render the window, but clear stencil
|
||||
glClearStencil(0);
|
||||
@@ -632,36 +607,11 @@ void CHyprOpenGLImpl::renderTextureWithBlur(const CTexture& tex, wlr_box* pBox,
|
||||
|
||||
// draw window
|
||||
glDisable(GL_STENCIL_TEST);
|
||||
renderTextureInternalWithDamage(tex, pBox, a, &damage, round, false, false, true, true);
|
||||
glEnable(GL_STENCIL_TEST);
|
||||
|
||||
// prep stencil for border
|
||||
glStencilFunc(GL_ALWAYS, 1, -1);
|
||||
glStencilOp(GL_KEEP, GL_KEEP, GL_REPLACE);
|
||||
|
||||
if (border) {
|
||||
// hacky fix to fix broken borders.
|
||||
// TODO: this is kinda slow... question mark?
|
||||
renderRectWithDamage(pBox, CColor(0,0,0,0), &damage, round);
|
||||
}
|
||||
|
||||
// then stop
|
||||
glStencilFunc(GL_EQUAL, 1, -1);
|
||||
glStencilOp(GL_KEEP, GL_KEEP, GL_REPLACE);
|
||||
renderTextureInternalWithDamage(tex, pBox, a, &damage, round, false, false, true);
|
||||
}
|
||||
|
||||
// disable the stencil (if no border), finalize everything
|
||||
if (!border) {
|
||||
glStencilMask(-1);
|
||||
glStencilFunc(GL_ALWAYS, 1, 0xFF);
|
||||
} else {
|
||||
auto BORDERCOL = m_pCurrentWindow->m_cRealBorderColor.col();
|
||||
BORDERCOL.a *= a / 255.f;
|
||||
static auto *const PBORDERSIZE = &g_pConfigManager->getConfigValuePtr("general:border_size")->intValue;
|
||||
renderBorder(pBox, BORDERCOL, *PBORDERSIZE, round);
|
||||
}
|
||||
|
||||
glDisable(GL_STENCIL_TEST);
|
||||
glStencilMask(-1);
|
||||
glStencilFunc(GL_ALWAYS, 1, 0xFF);
|
||||
pixman_region32_fini(&damage);
|
||||
scissor((wlr_box*)nullptr);
|
||||
}
|
||||
@@ -673,23 +623,67 @@ void pushVert2D(float x, float y, float* arr, int& counter, wlr_box* box) {
|
||||
counter++;
|
||||
}
|
||||
|
||||
void CHyprOpenGLImpl::renderBorder(wlr_box* box, const CColor& col, int thick, int round) {
|
||||
void CHyprOpenGLImpl::renderBorder(wlr_box* box, const CColor& col, 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()!");
|
||||
|
||||
// this method assumes a set stencil and scaled box
|
||||
box->x -= thick;
|
||||
box->y -= thick;
|
||||
box->width += 2 * thick;
|
||||
box->height += 2 * thick;
|
||||
static auto *const PBORDERSIZE = &g_pConfigManager->getConfigValuePtr("general:border_size")->intValue;
|
||||
static auto *const PMULTISAMPLE = &g_pConfigManager->getConfigValuePtr("decoration:multisample_edges")->intValue;
|
||||
|
||||
round += thick * m_RenderData.pMonitor->scale; // cuz yeah
|
||||
// adjust box
|
||||
box->x -= *PBORDERSIZE;
|
||||
box->y -= *PBORDERSIZE;
|
||||
box->width += 2 * *PBORDERSIZE;
|
||||
box->height += 2 * *PBORDERSIZE;
|
||||
|
||||
// only draw on non-stencild.
|
||||
glStencilFunc(GL_NOTEQUAL, 1, -1);
|
||||
round += *PBORDERSIZE;
|
||||
|
||||
// draw a rounded rect
|
||||
renderRect(box, col, round);
|
||||
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_shBORDER1.program);
|
||||
|
||||
glUniformMatrix3fv(m_shBORDER1.proj, 1, GL_FALSE, glMatrix);
|
||||
glUniform4f(glGetUniformLocation(m_shBORDER1.program, "color"), col.r / 255.f, col.g / 255.f, col.b / 255.f, col.a / 255.f);
|
||||
|
||||
const auto TOPLEFT = Vector2D(round, round);
|
||||
const auto BOTTOMRIGHT = Vector2D(box->width - round, box->height - round);
|
||||
const auto FULLSIZE = Vector2D(box->width, box->height);
|
||||
|
||||
glUniform2f(glGetUniformLocation(m_shBORDER1.program, "topLeft"), (float)TOPLEFT.x, (float)TOPLEFT.y);
|
||||
glUniform2f(glGetUniformLocation(m_shBORDER1.program, "bottomRight"), (float)BOTTOMRIGHT.x, (float)BOTTOMRIGHT.y);
|
||||
glUniform2f(glGetUniformLocation(m_shBORDER1.program, "fullSize"), (float)FULLSIZE.x, (float)FULLSIZE.y);
|
||||
glUniform1f(glGetUniformLocation(m_shBORDER1.program, "radius"), round);
|
||||
glUniform1f(glGetUniformLocation(m_shBORDER1.program, "thick"), *PBORDERSIZE);
|
||||
glUniform1i(glGetUniformLocation(m_shBORDER1.program, "primitiveMultisample"), *PMULTISAMPLE);
|
||||
|
||||
glVertexAttribPointer(m_shBORDER1.posAttrib, 2, GL_FLOAT, GL_FALSE, 0, fullVerts);
|
||||
glVertexAttribPointer(m_shBORDER1.texAttrib, 2, GL_FLOAT, GL_FALSE, 0, fullVerts);
|
||||
|
||||
glEnableVertexAttribArray(m_shBORDER1.posAttrib);
|
||||
glEnableVertexAttribArray(m_shBORDER1.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_shBORDER1.posAttrib);
|
||||
glDisableVertexAttribArray(m_shBORDER1.texAttrib);
|
||||
|
||||
glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
|
||||
}
|
||||
|
||||
void CHyprOpenGLImpl::makeWindowSnapshot(CWindow* pWindow) {
|
||||
@@ -858,6 +852,68 @@ void CHyprOpenGLImpl::renderSnapshot(SLayerSurface** pLayer) {
|
||||
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) {
|
||||
RASSERT(m_RenderData.pMonitor, "Tried to createBGTex without begin()!");
|
||||
|
||||
|
@@ -59,8 +59,10 @@ public:
|
||||
void renderRect(wlr_box*, const CColor&, int round = 0);
|
||||
void renderRectWithDamage(wlr_box*, const CColor&, pixman_region32_t* damage, 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 renderTextureWithBlur(const CTexture&, wlr_box*, float a, wlr_surface* pSurface, int round = 0, bool border = false);
|
||||
void renderTexture(const CTexture&, wlr_box*, float a, int round = 0, bool discardOpaque = false, bool allowPrimary = false);
|
||||
void renderTextureWithBlur(const CTexture&, wlr_box*, float a, wlr_surface* pSurface, int round = 0);
|
||||
void renderRoundedShadow(wlr_box*, int round, int range, float a = 1.0);
|
||||
void renderBorder(wlr_box*, const CColor&, int round);
|
||||
|
||||
void makeWindowSnapshot(CWindow*);
|
||||
void makeLayerSnapshot(SLayerSurface*);
|
||||
@@ -106,6 +108,8 @@ private:
|
||||
CShader m_shEXT;
|
||||
CShader m_shBLUR1;
|
||||
CShader m_shBLUR2;
|
||||
CShader m_shSHADOW;
|
||||
CShader m_shBORDER1;
|
||||
//
|
||||
|
||||
GLuint createProgram(const std::string&, const std::string&);
|
||||
@@ -115,8 +119,7 @@ private:
|
||||
// returns the out FB, can be either Mirror or MirrorSwap
|
||||
CFramebuffer* blurMainFramebufferWithDamage(float a, wlr_box* pBox, pixman_region32_t* damage);
|
||||
|
||||
void renderTextureInternalWithDamage(const CTexture&, wlr_box* pBox, float a, pixman_region32_t* damage, int round = 0, bool discardOpaque = false, bool border = false, bool noAA = false, bool allowPrimary = false);
|
||||
void renderBorder(wlr_box*, const CColor&, int thick = 1, int round = 0);
|
||||
void renderTextureInternalWithDamage(const CTexture&, wlr_box* pBox, float a, pixman_region32_t* damage, int round = 0, bool discardOpaque = false, bool noAA = false, bool allowPrimary = false);
|
||||
};
|
||||
|
||||
inline std::unique_ptr<CHyprOpenGLImpl> g_pHyprOpenGL;
|
@@ -27,7 +27,13 @@ void renderSurface(struct wlr_surface* surface, int x, int y, void* data) {
|
||||
|
||||
if (RDATA->surface && surface == RDATA->surface) {
|
||||
g_pHyprOpenGL->m_RenderData.renderingPrimarySurface = true;
|
||||
g_pHyprOpenGL->renderTextureWithBlur(TEXTURE, &windowBox, RDATA->fadeAlpha * RDATA->alpha, surface, rounding, RDATA->decorate);
|
||||
g_pHyprOpenGL->renderTextureWithBlur(TEXTURE, &windowBox, RDATA->fadeAlpha * RDATA->alpha, surface, rounding);
|
||||
|
||||
if (RDATA->decorate) {
|
||||
auto col = g_pHyprOpenGL->m_pCurrentWindow->m_cRealBorderColor.col();
|
||||
col.a *= RDATA->fadeAlpha * RDATA->alpha / 255.f;
|
||||
g_pHyprOpenGL->renderBorder(&windowBox, col, rounding);
|
||||
}
|
||||
}
|
||||
else
|
||||
g_pHyprOpenGL->renderTexture(TEXTURE, &windowBox, RDATA->fadeAlpha * RDATA->alpha, rounding, false, false);
|
||||
@@ -168,7 +174,7 @@ void CHyprRenderer::renderWindow(CWindow* pWindow, SMonitor* pMonitor, timespec*
|
||||
|
||||
// render window decorations first
|
||||
for (auto& wd : pWindow->m_dWindowDecorations)
|
||||
wd->draw(pMonitor);
|
||||
wd->draw(pMonitor, renderdata.alpha * renderdata.fadeAlpha / 255.f);
|
||||
|
||||
if (!pWindow->m_bIsX11) {
|
||||
|
||||
@@ -194,12 +200,7 @@ void CHyprRenderer::renderWindow(CWindow* pWindow, SMonitor* pMonitor, timespec*
|
||||
g_pHyprOpenGL->m_RenderData.primarySurfaceUVTopLeft = Vector2D(-1, -1);
|
||||
g_pHyprOpenGL->m_RenderData.primarySurfaceUVBottomRight = Vector2D(-1, -1);
|
||||
|
||||
if (pWindow->m_bIsX11) {
|
||||
if (pWindow->m_uSurface.xwayland->surface) {
|
||||
wlr_surface_for_each_surface(pWindow->m_uSurface.xwayland->surface, renderSurface, &renderdata);
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (!pWindow->m_bIsX11) {
|
||||
renderdata.dontRound = false; // restore dontround
|
||||
renderdata.pMonitor = pMonitor;
|
||||
wlr_xdg_surface_for_each_popup_surface(pWindow->m_uSurface.xdg, renderSurface, &renderdata);
|
||||
@@ -574,7 +575,7 @@ void CHyprRenderer::damageWindow(CWindow* pWindow) {
|
||||
// damage by size & pos
|
||||
// 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) {
|
||||
wlr_box fixedDamageBox = damageBox;
|
||||
fixedDamageBox.x -= m.vecPosition.x;
|
||||
@@ -589,8 +590,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);
|
||||
} else {
|
||||
// damage by real size & pos + border size * 2 (JIC)
|
||||
static auto *const PBORDERSIZE = &g_pConfigManager->getConfigValuePtr("general:border_size")->intValue;
|
||||
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};
|
||||
wlr_box damageBox = pWindow->getFullWindowBoundingBox();
|
||||
for (auto& m : g_pCompositor->m_lMonitors) {
|
||||
wlr_box fixedDamageBox = damageBox;
|
||||
fixedDamageBox.x -= m.vecPosition.x;
|
||||
@@ -759,3 +759,38 @@ void CHyprRenderer::applyMonitorRule(SMonitor* pMonitor, SMonitorRule* pMonitorR
|
||||
// frame skip
|
||||
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;
|
||||
}
|
@@ -31,6 +31,10 @@ public:
|
||||
void applyMonitorRule(SMonitor*, SMonitorRule*, bool force = false);
|
||||
bool shouldRenderWindow(CWindow*, SMonitor*);
|
||||
bool shouldRenderWindow(CWindow*);
|
||||
void ensureCursorRenderingMode();
|
||||
bool shouldRenderCursor();
|
||||
|
||||
bool m_bWindowRequestedCursorHide = false;
|
||||
|
||||
DAMAGETRACKINGMODES damageTrackingModeFromStr(const std::string&);
|
||||
|
||||
@@ -41,6 +45,8 @@ private:
|
||||
void renderLayer(SLayerSurface*, SMonitor*, timespec*);
|
||||
void renderDragIcon(SMonitor*, timespec*);
|
||||
|
||||
bool m_bHasARenderedCursor = true;
|
||||
|
||||
|
||||
friend class CHyprOpenGLImpl;
|
||||
};
|
||||
|
@@ -1,341 +1,5 @@
|
||||
#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;
|
||||
})#";
|
||||
#include "shaders/Textures.hpp"
|
||||
#include "shaders/Shadow.hpp"
|
||||
#include "shaders/Border.hpp"
|
66
src/render/decorations/CHyprDropShadowDecoration.cpp
Normal file
66
src/render/decorations/CHyprDropShadowDecoration.cpp
Normal 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);
|
||||
}
|
27
src/render/decorations/CHyprDropShadowDecoration.hpp
Normal file
27
src/render/decorations/CHyprDropShadowDecoration.hpp
Normal 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;
|
||||
};
|
@@ -68,7 +68,7 @@ void CHyprGroupBarDecoration::damageEntire() {
|
||||
g_pHyprRenderer->damageBox(&dm);
|
||||
}
|
||||
|
||||
void CHyprGroupBarDecoration::draw(SMonitor* pMonitor) {
|
||||
void CHyprGroupBarDecoration::draw(SMonitor* pMonitor, float a) {
|
||||
// get how many bars we will draw
|
||||
int barsToDraw = m_dwGroupMembers.size();
|
||||
|
||||
@@ -88,6 +88,7 @@ void CHyprGroupBarDecoration::draw(SMonitor* pMonitor) {
|
||||
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"));
|
||||
color.a *= a;
|
||||
g_pHyprOpenGL->renderRect(&rect, color);
|
||||
|
||||
xoff += PAD + BARW;
|
||||
|
@@ -10,7 +10,7 @@ public:
|
||||
|
||||
virtual SWindowDecorationExtents getWindowDecorationExtents();
|
||||
|
||||
virtual void draw(SMonitor*);
|
||||
virtual void draw(SMonitor*, float a);
|
||||
|
||||
virtual eDecorationType getDecorationType();
|
||||
|
||||
|
@@ -4,7 +4,8 @@
|
||||
|
||||
enum eDecorationType {
|
||||
DECORATION_NONE = -1,
|
||||
DECORATION_GROUPBAR
|
||||
DECORATION_GROUPBAR,
|
||||
DECORATION_SHADOW
|
||||
};
|
||||
|
||||
struct SWindowDecorationExtents {
|
||||
@@ -21,7 +22,7 @@ public:
|
||||
|
||||
virtual SWindowDecorationExtents getWindowDecorationExtents() = 0;
|
||||
|
||||
virtual void draw(SMonitor*) = 0;
|
||||
virtual void draw(SMonitor*, float a) = 0;
|
||||
|
||||
virtual eDecorationType getDecorationType() = 0;
|
||||
|
||||
|
91
src/render/shaders/Border.hpp
Normal file
91
src/render/shaders/Border.hpp
Normal file
@@ -0,0 +1,91 @@
|
||||
#pragma once
|
||||
|
||||
#include <string>
|
||||
|
||||
// makes a stencil without corners
|
||||
inline const std::string FRAGBORDER1 = 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 thick;
|
||||
uniform int primitiveMultisample;
|
||||
|
||||
float getOpacityForPixAndCorner(vec2 pix, vec2 corner) {
|
||||
|
||||
if (primitiveMultisample == 0) {
|
||||
float dis = distance(pix + vec2(0.5, 0.5), corner);
|
||||
return dis < radius && dis > radius - thick ? 1.0 : 0.0;
|
||||
}
|
||||
|
||||
float distance1 = distance(pix + vec2(0.25, 0.25), corner);
|
||||
float distance2 = distance(pix + vec2(0.75, 0.25), corner);
|
||||
float distance3 = distance(pix + vec2(0.25, 0.75), corner);
|
||||
float distance4 = distance(pix + vec2(0.75, 0.75), corner);
|
||||
|
||||
float v1 = distance1 < radius && distance1 > radius - thick ? 1.0 : 0.0;
|
||||
float v2 = distance2 < radius && distance2 > radius - thick ? 1.0 : 0.0;
|
||||
float v3 = distance3 < radius && distance3 > radius - thick ? 1.0 : 0.0;
|
||||
float v4 = distance4 < radius && distance4 > radius - thick ? 1.0 : 0.0;
|
||||
|
||||
return (v1 + v2 + v3 + v4) / 4.0;
|
||||
}
|
||||
|
||||
void main() {
|
||||
|
||||
vec2 pixCoord = fullSize * v_texcoord;
|
||||
|
||||
vec4 pixColor = v_color;
|
||||
|
||||
bool done = false;
|
||||
|
||||
// check for edges
|
||||
if (pixCoord[0] < topLeft[0]) {
|
||||
if (pixCoord[1] < topLeft[1]) {
|
||||
// top left
|
||||
pixColor[3] = pixColor[3] * getOpacityForPixAndCorner(pixCoord, topLeft + vec2(1,1));
|
||||
done = true;
|
||||
} else if (pixCoord[1] > bottomRight[1]) {
|
||||
// bottom left
|
||||
pixColor[3] = pixColor[3] * getOpacityForPixAndCorner(pixCoord, vec2(topLeft[0] + 1.0, bottomRight[1]));
|
||||
done = true;
|
||||
}
|
||||
} else if (pixCoord[0] > bottomRight[0]) {
|
||||
if (pixCoord[1] < topLeft[1]) {
|
||||
// top right
|
||||
pixColor[3] = pixColor[3] * getOpacityForPixAndCorner(pixCoord, vec2(bottomRight[0], topLeft[1] + 1.0));
|
||||
done = true;
|
||||
} else if (pixCoord[1] > bottomRight[1]) {
|
||||
// bottom right
|
||||
pixColor[3] = pixColor[3] * getOpacityForPixAndCorner(pixCoord, bottomRight);
|
||||
done = true;
|
||||
}
|
||||
}
|
||||
|
||||
// now check for other shit
|
||||
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 > thick) {
|
||||
discard; return;
|
||||
}
|
||||
}
|
||||
|
||||
if (pixColor[3] == 0.0) {
|
||||
discard; return;
|
||||
}
|
||||
|
||||
gl_FragColor = pixColor;
|
||||
}
|
||||
)#";
|
83
src/render/shaders/Shadow.hpp
Normal file
83
src/render/shaders/Shadow.hpp
Normal 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;
|
||||
})#";
|
341
src/render/shaders/Textures.hpp
Normal file
341
src/render/shaders/Textures.hpp
Normal 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;
|
||||
})#";
|
Reference in New Issue
Block a user