Compare commits

...

41 Commits

Author SHA1 Message Date
vaxerski
0b525cdc63 default to multisample on 2022-06-26 20:09:42 +02:00
vaxerski
6a47a305f8 fix some xwayland popups 2022-06-26 20:08:19 +02:00
vaxerski
1a0b2c4ade rewritten borders, fixed msaa 2022-06-26 19:39:56 +02:00
Vaxry
f1a5cb4979 Merge pull request #252 from squidgyberries/ex-conf-improvements
Made some settings' comments clearer
2022-06-26 14:53:46 +01:00
vaxerski
f5c2dfc706 a bit of fixes to cursor hiding 2022-06-26 13:43:32 +02:00
Vaxry
4d09101e23 oops 2022-06-26 12:53:56 +02:00
Vaxry
314e1f8fbe added funding 2022-06-26 12:53:22 +02:00
vaxerski
78bf88ba60 Added fullscreen rule 2022-06-26 12:12:29 +02:00
vaxerski
29aab21033 fix up some stupid default settings (internal) 2022-06-25 23:57:23 +02:00
vaxerski
adead82778 some changes to the sens and use in autogen 2022-06-25 23:40:52 +02:00
vaxerski
45898a57c8 guard windows' validity in focuswindowbyclass 2022-06-25 21:18:33 +02:00
vaxerski
2c8cf6afc4 notify of wiki in case of crashes 2022-06-25 21:16:52 +02:00
vaxerski
316b49eee2 added log level info 2022-06-25 20:50:29 +02:00
vaxerski
8de8f6667e add system info logging 2022-06-25 20:49:06 +02:00
Vaxry
648b2c892c mention shadows in readme 2022-06-25 20:36:48 +02:00
vaxerski
2955698f28 fix fade with deco 2022-06-25 20:31:54 +02:00
vaxerski
747ff3369d added drop shadows 2022-06-25 20:28:40 +02:00
vaxerski
b46f45befa additional keymap reload safety 2022-06-25 11:50:09 +02:00
vaxerski
3842b1641f allow move to 0 0 2022-06-25 11:20:03 +02:00
vaxerski
72c86b99eb added general:cursor_inactive_timeout 2022-06-24 23:27:02 +02:00
vaxerski
eb13be1240 fix one of the stupidest things i've ever written I am embarrassed. 2022-06-24 22:45:30 +02:00
vaxerski
45a44f9690 added noblur 2022-06-24 22:28:54 +02:00
Mihai Fufezan
e95e01416e flake, meson: manually update version
version update workflow: temporarily disable running on push
2022-06-24 19:48:11 +03:00
fufexan
94e8234ac9 [gha] bump flake and meson version 2022-06-24 16:45:11 +00:00
Mihai Fufezan
c78b811b49 Nix & Meson: fix update workflow 2022-06-24 19:44:53 +03:00
vaxerski
3053f99db6 guard dragging windows in dwindle 2022-06-24 18:37:04 +02:00
vaxerski
e7467c60f9 fix windowrule regex logic and add title: 2022-06-24 16:25:57 +02:00
vaxerski
3e8842e1f8 fix janky pixel maths with scaled textures 2022-06-24 15:59:59 +02:00
vaxerski
81e36298bf dont scale thick in border 2022-06-24 15:52:42 +02:00
vaxerski
218675246f guard pkeyboard in onMouseButton 2022-06-23 21:46:36 +02:00
vaxerski
e4e323a0df dwindle: disallow swaps between workspaces 2022-06-23 20:51:01 +02:00
vaxerski
f76b9c4852 fix: ignore reserved in getWindowInDirection 2022-06-23 20:39:48 +02:00
vaxerski
ae60075226 fix calculating damage offset for oversized popups 2022-06-23 19:32:00 +02:00
vaxerski
b25bafda08 guard null context in applyConfigToKeyboard 2022-06-23 18:52:05 +02:00
thinkingwithberries
a8e2595534 Update hyprland.conf 2022-06-23 21:52:17 +08:00
thinkingwithberries
3c6526dbbe Merge branch 'hyprwm:main' into ex-conf-improvements 2022-06-23 21:51:40 +08:00
vaxerski
4945c5887d reload all keyboards and not only the active 2022-06-23 15:48:31 +02:00
thinkingwithberries
ccdb03391e removed unused max fps option 2022-06-23 20:30:28 +08:00
thinkingwithberries
6ba5edd13e Made some settings' comments clearer 2022-06-23 18:26:48 +08:00
vaxerski
31dc70a41a Added exact to resizeActive and added moveactive 2022-06-23 10:14:59 +02:00
vaxerski
f9745b0d3b allow getWindowInDirection to scan other mons 2022-06-23 09:56:16 +02:00
45 changed files with 1224 additions and 524 deletions

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

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

View File

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

View File

@@ -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

View File

@@ -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
}
@@ -97,4 +96,4 @@ bind=ALT,6,movetoworkspace,6
bind=ALT,7,movetoworkspace,7
bind=ALT,8,movetoworkspace,8
bind=ALT,9,movetoworkspace,9
bind=ALT,0,movetoworkspace,10
bind=ALT,0,movetoworkspace,10

View File

@@ -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;
};
};

View File

@@ -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'])

View File

@@ -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)) {
@@ -1099,4 +1115,18 @@ 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;
}
}

View File

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

View File

@@ -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) {
@@ -43,4 +47,29 @@ wlr_box CWindow::getFullWindowBoundingBox() {
m_vRealSize.vec().y + maxExtents.topLeft.y + maxExtents.bottomRight.y};
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};
}

View File

@@ -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();
};
};

View File

@@ -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

View File

@@ -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
}

View File

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

View File

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

View File

@@ -56,7 +56,16 @@ 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);
}

View File

@@ -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) {

View File

@@ -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 {

View File

@@ -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);

View File

@@ -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);
@@ -232,4 +233,35 @@ float vecToRectDistanceSquared(const Vector2D& vec, const Vector2D& p1, const Ve
const float DX = std::max((double)0, std::max(p1.x - vec.x, vec.x - p2.x));
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());
}

View File

@@ -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
View File

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

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

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

View File

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

View File

@@ -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;
@@ -992,4 +1001,20 @@ 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);
}

View File

@@ -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*);

View File

@@ -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

View File

@@ -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))

View File

@@ -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);

View File

@@ -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;
}

View File

@@ -14,12 +14,16 @@ void CInputManager::onMouseMoved(wlr_pointer_motion_event* e) {
wlr_cursor_move(g_pCompositor->m_sWLRCursor, &e->pointer->base, DELTA.x * sensitivity, DELTA.y * sensitivity);
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,14 +346,14 @@ 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) {
m_lMice.emplace_back();
@@ -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);
}

View File

@@ -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;

View File

@@ -226,4 +226,4 @@ void CInputManager::focusTablet(STablet* pTab, wlr_tablet_tool* pTool, bool moti
if (PTOOL->pSurface)
wlr_tablet_v2_tablet_tool_notify_proximity_out(PTOOL->wlrTabletToolV2);
}
}
}

View File

@@ -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()!");

View File

@@ -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;

View File

@@ -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;
}

View File

@@ -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;
};

View File

@@ -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"

View File

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

View File

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

View File

@@ -68,7 +68,7 @@ void CHyprGroupBarDecoration::damageEntire() {
g_pHyprRenderer->damageBox(&dm);
}
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;

View File

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

View File

@@ -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;

View 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;
}
)#";

View File

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

View File

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