mirror of
https://github.com/hyprwm/Hyprland
synced 2024-11-02 14:45:59 +01:00
Merge branch 'vaxerski:main' into main
This commit is contained in:
commit
23c3534197
19 changed files with 437 additions and 78 deletions
|
@ -79,6 +79,10 @@ Try it out and report bugs / suggestions!
|
|||
|
||||
![Preview B]
|
||||
|
||||
<br>
|
||||
|
||||
![Preview C]
|
||||
|
||||
<br>
|
||||
<br>
|
||||
|
||||
|
@ -139,8 +143,9 @@ Try it out and report bugs / suggestions!
|
|||
<!----------------------------------{ Images }--------------------------------->
|
||||
|
||||
[Stars Preview]: https://starchart.cc/vaxerski/Hyprland.svg
|
||||
[Preview A]: https://i.imgur.com/ZA4Fa8R.png
|
||||
[Preview B]: https://i.imgur.com/BpXxM8H.png
|
||||
[Preview A]: https://i.imgur.com/NbrTnZH.png
|
||||
[Preview B]: https://i.imgur.com/ZA4Fa8R.png
|
||||
[Preview C]: https://i.imgur.com/BpXxM8H.png
|
||||
[Banner]: https://raw.githubusercontent.com/vaxerski/Hyprland/main/assets/hyprland.png
|
||||
|
||||
|
||||
|
|
40
aur/PKGBUILD-git
Normal file
40
aur/PKGBUILD-git
Normal file
|
@ -0,0 +1,40 @@
|
|||
# Maintainer: Sander van Kasteel <info@sandervankasteel.nl>, ThatOneCalculator <kainoa@t1c.dev>
|
||||
|
||||
_pkgname="hyprland"
|
||||
pkgname="${_pkgname}-git"
|
||||
pkgver=r461.96cdf8f
|
||||
pkgrel=5
|
||||
pkgdesc="Hyprland is a dynamic tiling Wayland compositor based on wlroots that doesn't sacrifice on its looks."
|
||||
arch=(any)
|
||||
url="https://github.com/vaxerski/Hyprland"
|
||||
license=('BSD')
|
||||
depends=(libxcb xcb-proto xcb-util xcb-util-keysyms libxfixes libx11 libxcomposite xorg-xinput libxrender pixman wayland-protocols wlroots-git cairo pango)
|
||||
makedepends=(git cmake ninja gcc gdb)
|
||||
source=("${_pkgname}::git+https://github.com/vaxerski/Hyprland.git")
|
||||
sha256sums=('SKIP')
|
||||
options=(!makeflags !buildflags)
|
||||
|
||||
pkgver() {
|
||||
cd "$_pkgname"
|
||||
( set -o pipefail
|
||||
git describe --long 2>/dev/null | sed 's/\([^-]*-g\)/r\1/;s/-/./g' ||
|
||||
printf "r%s.%s" "$(git rev-list --count HEAD)" "$(git rev-parse --short HEAD)"
|
||||
)
|
||||
}
|
||||
|
||||
build() {
|
||||
cd "${srcdir}/${_pkgname}"
|
||||
make all
|
||||
}
|
||||
|
||||
package() {
|
||||
cd "${srcdir}/${_pkgname}"
|
||||
mkdir -p "${pkgdir}/usr/share/wayland-sessions"
|
||||
mkdir -p "${pkgdir}/usr/share/hyprland"
|
||||
install -Dm755 build/Hyprland -t "${pkgdir}/usr/bin"
|
||||
install -Dm755 hyprctl/hyprctl -t "${pkgdir}/usr/bin"
|
||||
install -Dm644 assets/*.png -t "${pkgdir}/usr/share/hyprland"
|
||||
install -Dm644 example/hyprland.desktop -t "${pkgdir}/usr/share/wayland-sessions"
|
||||
install -Dm644 example/hyprland.conf -t "${pkgdir}/usr/share/hyprland"
|
||||
install -Dm644 LICENSE -t "${pkgdir}/usr/share/licenses/${_pkgname}"
|
||||
}
|
|
@ -67,7 +67,7 @@ CCompositor::CCompositor() {
|
|||
m_sWLRScene = wlr_scene_create();
|
||||
wlr_scene_attach_output_layout(m_sWLRScene, m_sWLROutputLayout);
|
||||
|
||||
m_sWLRXDGShell = wlr_xdg_shell_create(m_sWLDisplay);
|
||||
m_sWLRXDGShell = wlr_xdg_shell_create(m_sWLDisplay, 2);
|
||||
|
||||
m_sWLRCursor = wlr_cursor_create();
|
||||
wlr_cursor_attach_output_layout(m_sWLRCursor, m_sWLROutputLayout);
|
||||
|
@ -402,13 +402,13 @@ void CCompositor::focusWindow(CWindow* pWindow, wlr_surface* pSurface) {
|
|||
return;
|
||||
}
|
||||
|
||||
if (pWindow->m_bNoFocus) {
|
||||
Debug::log(LOG, "Ignoring focus to nofocus window!");
|
||||
if (!pWindow || !windowValidMapped(pWindow)) {
|
||||
wlr_seat_keyboard_notify_clear_focus(m_sSeat.seat);
|
||||
return;
|
||||
}
|
||||
|
||||
if (!pWindow || !windowValidMapped(pWindow)) {
|
||||
wlr_seat_keyboard_notify_clear_focus(m_sSeat.seat);
|
||||
if (pWindow->m_bNoFocus) {
|
||||
Debug::log(LOG, "Ignoring focus to nofocus window!");
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -513,7 +513,7 @@ CWindow* CCompositor::getWindowForPopup(wlr_xdg_popup* popup) {
|
|||
|
||||
wlr_surface* CCompositor::vectorToLayerSurface(const Vector2D& pos, std::list<SLayerSurface*>* layerSurfaces, Vector2D* sCoords) {
|
||||
for (auto& l : *layerSurfaces) {
|
||||
if (!l->layerSurface->mapped)
|
||||
if (l->fadingOut || (l->layerSurface && !l->layerSurface->mapped))
|
||||
continue;
|
||||
|
||||
const auto SURFACEAT = wlr_layer_surface_v1_surface_at(l->layerSurface, pos.x - l->geometry.x, pos.y - l->geometry.y, &sCoords->x, &sCoords->y);
|
||||
|
@ -632,7 +632,7 @@ void CCompositor::moveWindowToTop(CWindow* pWindow) {
|
|||
}
|
||||
}
|
||||
|
||||
void CCompositor::cleanupWindows() {
|
||||
void CCompositor::cleanupFadingOut() {
|
||||
for (auto& w : m_lWindowsFadingOut) {
|
||||
|
||||
bool valid = windowExists(w);
|
||||
|
@ -650,6 +650,26 @@ void CCompositor::cleanupWindows() {
|
|||
return;
|
||||
}
|
||||
}
|
||||
|
||||
for (auto& ls : m_lSurfacesFadingOut) {
|
||||
if (ls->fadingOut && ls->readyToDelete && !ls->alpha.isBeingAnimated()) {
|
||||
for (auto& m : m_lMonitors) {
|
||||
for (auto& lsl : m.m_aLayerSurfaceLists) {
|
||||
lsl.remove(ls);
|
||||
}
|
||||
}
|
||||
|
||||
g_pHyprOpenGL->m_mLayerFramebuffers[ls].release();
|
||||
g_pHyprOpenGL->m_mLayerFramebuffers.erase(ls);
|
||||
|
||||
m_lSurfacesFadingOut.remove(ls);
|
||||
delete ls;
|
||||
|
||||
Debug::log(LOG, "Cleanup: destroyed a layersurface");
|
||||
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
CWindow* CCompositor::getWindowInDirection(CWindow* pWindow, char dir) {
|
||||
|
|
|
@ -67,6 +67,7 @@ public:
|
|||
std::list<CWorkspace> m_lWorkspaces;
|
||||
std::list<SSubsurface> m_lSubsurfaces;
|
||||
std::list<CWindow*> m_lWindowsFadingOut;
|
||||
std::list<SLayerSurface*> m_lSurfacesFadingOut;
|
||||
|
||||
void startCompositor();
|
||||
void cleanupExit();
|
||||
|
@ -111,7 +112,7 @@ public:
|
|||
bool doesSeatAcceptInput(wlr_surface*);
|
||||
bool isWindowActive(CWindow*);
|
||||
void moveWindowToTop(CWindow*);
|
||||
void cleanupWindows();
|
||||
void cleanupFadingOut();
|
||||
CWindow* getWindowInDirection(CWindow*, char);
|
||||
void deactivateAllWLRWorkspaces(wlr_ext_workspace_handle_v1* exclude = nullptr);
|
||||
CWindow* getNextWindowOnWorkspace(CWindow*);
|
||||
|
|
|
@ -9,6 +9,10 @@ struct SWindowSpecialRenderData {
|
|||
float alpha = 1.f;
|
||||
};
|
||||
|
||||
struct SWindowAdditionalConfigData {
|
||||
std::string animationStyle = "";
|
||||
};
|
||||
|
||||
class CWindow {
|
||||
public:
|
||||
CWindow();
|
||||
|
@ -81,6 +85,7 @@ public:
|
|||
|
||||
// Special render data, rules, etc
|
||||
SWindowSpecialRenderData m_sSpecialRenderData;
|
||||
SWindowAdditionalConfigData m_sAdditionalConfigData;
|
||||
|
||||
// For the list lookup
|
||||
bool operator==(const CWindow& rhs) {
|
||||
|
|
|
@ -12,6 +12,9 @@
|
|||
|
||||
CConfigManager::CConfigManager() {
|
||||
setDefaultVars();
|
||||
static const char* const ENVHOME = getenv("HOME");
|
||||
const std::string CONFIGPATH = ENVHOME + (ISDEBUG ? (std::string) "/.config/hypr/hyprlandd.conf" : (std::string) "/.config/hypr/hyprland.conf");
|
||||
configPaths.emplace_back(CONFIGPATH);
|
||||
}
|
||||
|
||||
void CConfigManager::setDefaultVars() {
|
||||
|
@ -94,14 +97,21 @@ void CConfigManager::init() {
|
|||
Debug::log(WARN, "Error at statting config, error %i", errno);
|
||||
}
|
||||
|
||||
lastModifyTime = fileStat.st_mtime;
|
||||
configModifyTimes[CONFIGPATH] = fileStat.st_mtime;
|
||||
|
||||
isFirstLaunch = false;
|
||||
}
|
||||
|
||||
void CConfigManager::configSetValueSafe(const std::string& COMMAND, const std::string& VALUE) {
|
||||
if (configValues.find(COMMAND) == configValues.end()) {
|
||||
if (COMMAND[0] == '$') {
|
||||
// register a dynamic var
|
||||
Debug::log(LOG, "Registered dynamic var \"%s\" -> %s", COMMAND.c_str(), VALUE.c_str());
|
||||
configDynamicVars[COMMAND.substr(1)] = VALUE;
|
||||
} else {
|
||||
parseError = "Error setting value <" + VALUE + "> for field <" + COMMAND + ">: No such field.";
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -398,6 +408,7 @@ void CConfigManager::handleWindowRule(const std::string& command, const std::str
|
|||
&& RULE.find("pseudo") != 0
|
||||
&& RULE.find("monitor") != 0
|
||||
&& RULE.find("nofocus") != 0
|
||||
&& RULE.find("animation") != 0
|
||||
&& RULE.find("workspace") != 0) {
|
||||
Debug::log(ERR, "Invalid rule found: %s", RULE.c_str());
|
||||
parseError = "Invalid rule found: " + RULE;
|
||||
|
@ -421,6 +432,60 @@ void CConfigManager::handleDefaultWorkspace(const std::string& command, const st
|
|||
}
|
||||
}
|
||||
|
||||
void CConfigManager::handleSource(const std::string& command, const std::string& rawpath) {
|
||||
static const char* const ENVHOME = getenv("HOME");
|
||||
|
||||
auto value = rawpath;
|
||||
|
||||
if (value[0] == '~') {
|
||||
value.replace(0, 1, std::string(ENVHOME));
|
||||
}
|
||||
|
||||
if (!std::filesystem::exists(value)) {
|
||||
Debug::log(ERR, "source= file doesnt exist");
|
||||
parseError = "source file " + value + " doesn't exist!";
|
||||
return;
|
||||
}
|
||||
|
||||
configPaths.push_back(value);
|
||||
|
||||
struct stat fileStat;
|
||||
int err = stat(value.c_str(), &fileStat);
|
||||
if (err != 0) {
|
||||
Debug::log(WARN, "Error at ticking config at %s, error %i: %s", value.c_str(), err, strerror(err));
|
||||
return;
|
||||
}
|
||||
|
||||
configModifyTimes[value] = fileStat.st_mtime;
|
||||
|
||||
std::ifstream ifs;
|
||||
ifs.open(value);
|
||||
std::string line = "";
|
||||
int linenum = 1;
|
||||
if (ifs.is_open()) {
|
||||
while (std::getline(ifs, line)) {
|
||||
// Read line by line.
|
||||
try {
|
||||
configCurrentPath = value;
|
||||
parseLine(line);
|
||||
} catch (...) {
|
||||
Debug::log(ERR, "Error reading line from config. Line:");
|
||||
Debug::log(NONE, "%s", line.c_str());
|
||||
|
||||
parseError += "Config error at line " + std::to_string(linenum) + " (" + configCurrentPath + "): Line parsing error.";
|
||||
}
|
||||
|
||||
if (parseError != "" && parseError.find("Config error at line") != 0) {
|
||||
parseError = "Config error at line " + std::to_string(linenum) + " (" + configCurrentPath + "): " + parseError;
|
||||
}
|
||||
|
||||
++linenum;
|
||||
}
|
||||
|
||||
ifs.close();
|
||||
}
|
||||
}
|
||||
|
||||
std::string CConfigManager::parseKeyword(const std::string& COMMAND, const std::string& VALUE, bool dynamic) {
|
||||
if (dynamic)
|
||||
parseError = "";
|
||||
|
@ -443,6 +508,7 @@ std::string CConfigManager::parseKeyword(const std::string& COMMAND, const std::
|
|||
else if (COMMAND == "windowrule") handleWindowRule(COMMAND, VALUE);
|
||||
else if (COMMAND == "bezier") handleBezier(COMMAND, VALUE);
|
||||
else if (COMMAND == "animation") handleAnimation(COMMAND, VALUE);
|
||||
else if (COMMAND == "source") handleSource(COMMAND, VALUE);
|
||||
else
|
||||
configSetValueSafe(currentCategory + (currentCategory == "" ? "" : ":") + COMMAND, VALUE);
|
||||
|
||||
|
@ -455,6 +521,23 @@ std::string CConfigManager::parseKeyword(const std::string& COMMAND, const std::
|
|||
return parseError;
|
||||
}
|
||||
|
||||
void CConfigManager::applyUserDefinedVars(std::string& line, const size_t equalsPlace) {
|
||||
auto dollarPlace = line.find_first_of('$', equalsPlace);
|
||||
|
||||
while (dollarPlace != std::string::npos) {
|
||||
|
||||
const auto STRAFTERDOLLAR = line.substr(dollarPlace + 1);
|
||||
for (auto&[var, value] : configDynamicVars) {
|
||||
if (STRAFTERDOLLAR.find(var) == 0) {
|
||||
line.replace(dollarPlace, var.length() + 1, value);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
dollarPlace = line.find_first_of('$', dollarPlace + 1);
|
||||
}
|
||||
}
|
||||
|
||||
void CConfigManager::parseLine(std::string& line) {
|
||||
// first check if its not a comment
|
||||
const auto COMMENTSTART = line.find_first_of('#');
|
||||
|
@ -493,6 +576,9 @@ void CConfigManager::parseLine(std::string& line) {
|
|||
// check if command
|
||||
const auto EQUALSPLACE = line.find_first_of('=');
|
||||
|
||||
// apply vars
|
||||
applyUserDefinedVars(line, EQUALSPLACE);
|
||||
|
||||
if (EQUALSPLACE == std::string::npos)
|
||||
return;
|
||||
|
||||
|
@ -515,10 +601,16 @@ void CConfigManager::loadConfigLoadVars() {
|
|||
g_pKeybindManager->clearKeybinds();
|
||||
g_pAnimationManager->removeAllBeziers();
|
||||
m_mAdditionalReservedAreas.clear();
|
||||
configDynamicVars.clear();
|
||||
|
||||
const char* const ENVHOME = getenv("HOME");
|
||||
// paths
|
||||
configPaths.clear();
|
||||
|
||||
static const char* const ENVHOME = getenv("HOME");
|
||||
const std::string CONFIGPATH = ENVHOME + (ISDEBUG ? (std::string) "/.config/hypr/hyprlandd.conf" : (std::string) "/.config/hypr/hyprland.conf");
|
||||
|
||||
configPaths.push_back(CONFIGPATH);
|
||||
|
||||
std::ifstream ifs;
|
||||
ifs.open(CONFIGPATH);
|
||||
|
||||
|
@ -549,16 +641,17 @@ void CConfigManager::loadConfigLoadVars() {
|
|||
while (std::getline(ifs, line)) {
|
||||
// Read line by line.
|
||||
try {
|
||||
configCurrentPath = "~/.config/hypr/hyprland.conf";
|
||||
parseLine(line);
|
||||
} catch (...) {
|
||||
Debug::log(ERR, "Error reading line from config. Line:");
|
||||
Debug::log(NONE, "%s", line.c_str());
|
||||
|
||||
parseError += "Config error at line " + std::to_string(linenum) + ": Line parsing error.";
|
||||
parseError += "Config error at line " + std::to_string(linenum) + " (" + configCurrentPath + "): Line parsing error.";
|
||||
}
|
||||
|
||||
if (parseError != "" && parseError.find("Config error at line") != 0) {
|
||||
parseError = "Config error at line " + std::to_string(linenum) + ": " + parseError;
|
||||
parseError = "Config error at line " + std::to_string(linenum) + " (" + configCurrentPath + "): " + parseError;
|
||||
}
|
||||
|
||||
++linenum;
|
||||
|
@ -601,7 +694,7 @@ void CConfigManager::loadConfigLoadVars() {
|
|||
}
|
||||
|
||||
void CConfigManager::tick() {
|
||||
const char* const ENVHOME = getenv("HOME");
|
||||
static const char* const ENVHOME = getenv("HOME");
|
||||
|
||||
const std::string CONFIGPATH = ENVHOME + (ISDEBUG ? (std::string) "/.config/hypr/hyprlandd.conf" : (std::string) "/.config/hypr/hyprland.conf");
|
||||
|
||||
|
@ -610,16 +703,24 @@ void CConfigManager::tick() {
|
|||
return;
|
||||
}
|
||||
|
||||
bool parse = false;
|
||||
|
||||
for (auto& cf : configPaths) {
|
||||
struct stat fileStat;
|
||||
int err = stat(CONFIGPATH.c_str(), &fileStat);
|
||||
int err = stat(cf.c_str(), &fileStat);
|
||||
if (err != 0) {
|
||||
Debug::log(WARN, "Error at ticking config at %s, error %i: %s", CONFIGPATH.c_str(), err, strerror(err));
|
||||
Debug::log(WARN, "Error at ticking config at %s, error %i: %s", cf.c_str(), err, strerror(err));
|
||||
return;
|
||||
}
|
||||
|
||||
// check if we need to reload cfg
|
||||
if (fileStat.st_mtime != lastModifyTime || m_bForceReload) {
|
||||
lastModifyTime = fileStat.st_mtime;
|
||||
if (fileStat.st_mtime != configModifyTimes[cf] || m_bForceReload) {
|
||||
parse = true;
|
||||
configModifyTimes[cf] = fileStat.st_mtime;
|
||||
}
|
||||
}
|
||||
|
||||
if (parse) {
|
||||
m_bForceReload = false;
|
||||
|
||||
loadConfigLoadVars();
|
||||
|
|
|
@ -76,8 +76,12 @@ public:
|
|||
std::string parseKeyword(const std::string&, const std::string&, bool dynamic = false);
|
||||
|
||||
private:
|
||||
std::deque<std::string> configPaths; // stores all the config paths
|
||||
std::unordered_map<std::string, time_t> configModifyTimes; // stores modify times
|
||||
std::unordered_map<std::string, std::string> configDynamicVars; // stores dynamic vars declared by the user
|
||||
std::unordered_map<std::string, SConfigValue> configValues;
|
||||
time_t lastModifyTime = 0; // for reloading the config if changed
|
||||
|
||||
std::string configCurrentPath;
|
||||
|
||||
std::string currentCategory = ""; // For storing the category of the current item
|
||||
|
||||
|
@ -94,6 +98,7 @@ private:
|
|||
// internal methods
|
||||
void setDefaultVars();
|
||||
|
||||
void applyUserDefinedVars(std::string&, const size_t);
|
||||
void loadConfigLoadVars();
|
||||
SConfigValue getConfigValueSafe(std::string);
|
||||
void parseLine(std::string&);
|
||||
|
@ -106,6 +111,7 @@ private:
|
|||
void handleDefaultWorkspace(const std::string&, const std::string&);
|
||||
void handleBezier(const std::string&, const std::string&);
|
||||
void handleAnimation(const std::string&, const std::string&);
|
||||
void handleSource(const std::string&, const std::string&);
|
||||
};
|
||||
|
||||
inline std::unique_ptr<CConfigManager> g_pConfigManager;
|
|
@ -58,6 +58,23 @@ void Events::listener_destroyLayerSurface(void* owner, void* data) {
|
|||
|
||||
Debug::log(LOG, "LayerSurface %x destroyed", layersurface->layerSurface);
|
||||
|
||||
if (!layersurface->fadingOut) {
|
||||
if (layersurface->layerSurface->mapped) {
|
||||
Debug::log(LOG, "LayerSurface wasn't unmapped, making a snapshot now!");
|
||||
|
||||
// make a snapshot and start fade
|
||||
// layersurfaces aren't required to unmap before destroy
|
||||
g_pHyprOpenGL->makeLayerSnapshot(layersurface);
|
||||
layersurface->alpha = 0.f;
|
||||
|
||||
layersurface->fadingOut = true;
|
||||
} else {
|
||||
Debug::log(LOG, "Removing LayerSurface that wasn't mapped.");
|
||||
layersurface->alpha.setValueAndWarp(0.f);
|
||||
layersurface->fadingOut = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (layersurface->layerSurface->mapped)
|
||||
layersurface->layerSurface->mapped = false;
|
||||
|
||||
|
@ -72,9 +89,6 @@ void Events::listener_destroyLayerSurface(void* owner, void* data) {
|
|||
|
||||
const auto PMONITOR = g_pCompositor->getMonitorFromID(layersurface->monitorID);
|
||||
|
||||
// remove the layersurface as it's not used anymore
|
||||
PMONITOR->m_aLayerSurfaceLists[layersurface->layer].remove(layersurface);
|
||||
|
||||
// rearrange to fix the reserved areas
|
||||
if (PMONITOR) {
|
||||
g_pHyprRenderer->arrangeLayersForMonitor(PMONITOR->ID);
|
||||
|
@ -85,7 +99,8 @@ void Events::listener_destroyLayerSurface(void* owner, void* data) {
|
|||
g_pHyprRenderer->damageBox(&geomFixed);
|
||||
}
|
||||
|
||||
delete layersurface;
|
||||
layersurface->readyToDelete = true;
|
||||
layersurface->layerSurface = nullptr;
|
||||
}
|
||||
|
||||
void Events::listener_mapLayerSurface(void* owner, void* data) {
|
||||
|
@ -121,6 +136,11 @@ void Events::listener_mapLayerSurface(void* owner, void* data) {
|
|||
|
||||
wlr_box geomFixed = {layersurface->geometry.x + PMONITOR->vecPosition.x, layersurface->geometry.y + PMONITOR->vecPosition.y, layersurface->geometry.width, layersurface->geometry.height};
|
||||
g_pHyprRenderer->damageBox(&geomFixed);
|
||||
|
||||
layersurface->alpha.setValue(0);
|
||||
layersurface->alpha = 255.f;
|
||||
layersurface->readyToDelete = false;
|
||||
layersurface->fadingOut = false;
|
||||
}
|
||||
|
||||
void Events::listener_unmapLayerSurface(void* owner, void* data) {
|
||||
|
@ -128,6 +148,14 @@ void Events::listener_unmapLayerSurface(void* owner, void* data) {
|
|||
|
||||
Debug::log(LOG, "LayerSurface %x unmapped", layersurface->layerSurface);
|
||||
|
||||
// make a snapshot and start fade
|
||||
g_pHyprOpenGL->makeLayerSnapshot(layersurface);
|
||||
layersurface->alpha = 0.f;
|
||||
|
||||
layersurface->fadingOut = true;
|
||||
|
||||
g_pCompositor->m_lSurfacesFadingOut.push_back(layersurface);
|
||||
|
||||
if (layersurface->layerSurface->mapped)
|
||||
layersurface->layerSurface->mapped = false;
|
||||
|
||||
|
|
|
@ -135,7 +135,7 @@ void Events::listener_monitorFrame(void* owner, void* data) {
|
|||
if (PMONITOR->ID == pMostHzMonitor->ID) {
|
||||
g_pCompositor->sanityCheckWorkspaces();
|
||||
g_pAnimationManager->tick();
|
||||
g_pCompositor->cleanupWindows();
|
||||
g_pCompositor->cleanupFadingOut();
|
||||
|
||||
HyprCtl::tickHyprCtl(); // so that we dont get that race condition multithread bullshit
|
||||
|
||||
|
@ -191,7 +191,7 @@ void Events::listener_monitorFrame(void* owner, void* data) {
|
|||
const auto BLURSIZE = g_pConfigManager->getInt("decoration:blur_size");
|
||||
const auto BLURPASSES = g_pConfigManager->getInt("decoration:blur_passes");
|
||||
|
||||
const auto BLURRADIUS = BLURSIZE * BLURPASSES * 2; // is this 2? I don't know but 2 works.
|
||||
const auto BLURRADIUS = BLURSIZE * pow(2, BLURPASSES); // is this 2^pass? I don't know but it works... I think.
|
||||
|
||||
pixman_region32_copy(&g_pHyprOpenGL->m_rOriginalDamageRegion, &damage);
|
||||
|
||||
|
|
|
@ -95,6 +95,9 @@ void Events::listener_mapWindow(void* owner, void* data) {
|
|||
} catch(std::exception& e) {
|
||||
Debug::log(ERR, "Opacity rule \"%s\" failed with: %s", r.szRule.c_str(), e.what());
|
||||
}
|
||||
} else if (r.szRule.find("animation") == 0) {
|
||||
auto STYLE = r.szRule.substr(r.szRule.find_first_of(' ') + 1);
|
||||
PWINDOW->m_sAdditionalConfigData.animationStyle = STYLE;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -18,6 +18,7 @@ enum AVARDAMAGEPOLICY {
|
|||
|
||||
class CAnimationManager;
|
||||
class CWorkspace;
|
||||
struct SLayerSurface;
|
||||
|
||||
class CAnimatedVariable {
|
||||
public:
|
||||
|
@ -183,8 +184,12 @@ private:
|
|||
|
||||
float* m_pSpeed = nullptr;
|
||||
int64_t* m_pEnabled = nullptr;
|
||||
|
||||
// owners
|
||||
void* m_pWindow = nullptr;
|
||||
void* m_pWorkspace = nullptr;
|
||||
void* m_pLayer = nullptr;
|
||||
|
||||
std::string* m_pBezier = nullptr;
|
||||
|
||||
bool m_bDummy = true;
|
||||
|
@ -196,4 +201,5 @@ private:
|
|||
|
||||
friend class CAnimationManager;
|
||||
friend class CWorkspace;
|
||||
friend struct SLayerSurface;
|
||||
};
|
7
src/helpers/WLClasses.cpp
Normal file
7
src/helpers/WLClasses.cpp
Normal file
|
@ -0,0 +1,7 @@
|
|||
#include "WLClasses.hpp"
|
||||
#include "../config/ConfigManager.hpp"
|
||||
|
||||
SLayerSurface::SLayerSurface() {
|
||||
alpha.create(AVARTYPE_FLOAT, &g_pConfigManager->getConfigValuePtr("animations:fadein_speed")->floatValue, &g_pConfigManager->getConfigValuePtr("animations:fadein")->intValue, &g_pConfigManager->getConfigValuePtr("animations:fadein_curve")->strValue, nullptr, AVARDAMAGE_ENTIRE);
|
||||
alpha.m_pLayer = this;
|
||||
}
|
|
@ -5,8 +5,11 @@
|
|||
#include "../../wlr-layer-shell-unstable-v1-protocol.h"
|
||||
#include "../Window.hpp"
|
||||
#include "SubsurfaceTree.hpp"
|
||||
#include "AnimatedVariable.hpp"
|
||||
|
||||
struct SLayerSurface {
|
||||
SLayerSurface();
|
||||
|
||||
wlr_layer_surface_v1* layerSurface;
|
||||
wl_list link;
|
||||
|
||||
|
@ -22,6 +25,9 @@ struct SLayerSurface {
|
|||
|
||||
int monitorID = -1;
|
||||
|
||||
CAnimatedVariable alpha;
|
||||
bool fadingOut = false;
|
||||
bool readyToDelete = false;
|
||||
|
||||
// For the list lookup
|
||||
bool operator==(const SLayerSurface& rhs) {
|
||||
|
|
|
@ -41,12 +41,16 @@ void CAnimationManager::tick() {
|
|||
// window stuff
|
||||
const auto PWINDOW = (CWindow*)av->m_pWindow;
|
||||
const auto PWORKSPACE = (CWorkspace*)av->m_pWorkspace;
|
||||
const auto PLAYER = (SLayerSurface*)av->m_pLayer;
|
||||
|
||||
wlr_box WLRBOXPREV = {0,0,0,0};
|
||||
if (PWINDOW) {
|
||||
WLRBOXPREV = {(int)PWINDOW->m_vRealPosition.vec().x - BORDERSIZE - 1, (int)PWINDOW->m_vRealPosition.vec().y - BORDERSIZE - 1, (int)PWINDOW->m_vRealSize.vec().x + 2 * BORDERSIZE + 2, (int)PWINDOW->m_vRealSize.vec().y + 2 * BORDERSIZE + 2};
|
||||
} else if (PWORKSPACE) {
|
||||
const auto PMONITOR = g_pCompositor->getMonitorFromID(PWORKSPACE->m_iMonitorID);
|
||||
WLRBOXPREV = {(int)PMONITOR->vecPosition.x, (int)PMONITOR->vecPosition.y, (int)PMONITOR->vecSize.x, (int)PMONITOR->vecSize.y};
|
||||
} else if (PLAYER) {
|
||||
WLRBOXPREV = PLAYER->geometry;
|
||||
}
|
||||
|
||||
// check if it's disabled, if so, warp
|
||||
|
@ -199,26 +203,39 @@ bool CAnimationManager::deltazero(const CColor& a, const CColor& b) {
|
|||
return a.r == b.r && a.g == b.g && a.b == b.b && a.a == b.a;
|
||||
}
|
||||
|
||||
//
|
||||
// Anims
|
||||
//
|
||||
//
|
||||
|
||||
// animation on events
|
||||
void CAnimationManager::onWindowPostCreate(CWindow* pWindow) {
|
||||
auto ANIMSTYLE = g_pConfigManager->getString("animations:windows_style");
|
||||
transform(ANIMSTYLE.begin(), ANIMSTYLE.end(), ANIMSTYLE.begin(), ::tolower);
|
||||
void CAnimationManager::animationPopin(CWindow* pWindow) {
|
||||
const auto GOALPOS = pWindow->m_vRealPosition.goalv();
|
||||
const auto GOALSIZE = pWindow->m_vRealSize.goalv();
|
||||
|
||||
// if the window is not being animated, that means the layout set a fixed size for it, don't animate.
|
||||
if (!pWindow->m_vRealPosition.isBeingAnimated() && !pWindow->m_vRealSize.isBeingAnimated())
|
||||
return;
|
||||
pWindow->m_vRealPosition.setValue(GOALPOS + GOALSIZE / 2.f);
|
||||
pWindow->m_vRealSize.setValue(Vector2D(5, 5));
|
||||
}
|
||||
|
||||
void CAnimationManager::animationSlide(CWindow* pWindow, std::string force) {
|
||||
pWindow->m_vRealSize.warp(); // size we preserve in slide
|
||||
|
||||
const auto GOALPOS = pWindow->m_vRealPosition.goalv();
|
||||
const auto GOALSIZE = pWindow->m_vRealSize.goalv();
|
||||
|
||||
if (ANIMSTYLE == "slide") {
|
||||
pWindow->m_vRealSize.warp(); // size we preserve in slide
|
||||
const auto PMONITOR = g_pCompositor->getMonitorFromID(pWindow->m_iMonitorID);
|
||||
|
||||
if (force != "") {
|
||||
if (force == "bottom") pWindow->m_vRealPosition.setValue(Vector2D(GOALPOS.x, PMONITOR->vecPosition.y + PMONITOR->vecSize.y));
|
||||
else if (force == "left") pWindow->m_vRealPosition.setValue(GOALPOS - Vector2D(GOALSIZE.x, 0));
|
||||
else if (force == "right") pWindow->m_vRealPosition.setValue(GOALPOS + Vector2D(GOALSIZE.x, 0));
|
||||
else pWindow->m_vRealPosition.setValue(Vector2D(GOALPOS.x, PMONITOR->vecPosition.y - GOALSIZE.y));
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
const auto MIDPOINT = GOALPOS + GOALSIZE / 2.f;
|
||||
|
||||
// check sides it touches
|
||||
const auto PMONITOR = g_pCompositor->getMonitorFromID(pWindow->m_iMonitorID);
|
||||
const bool DISPLAYLEFT = STICKS(pWindow->m_vPosition.x, PMONITOR->vecPosition.x + PMONITOR->vecReservedTopLeft.x);
|
||||
const bool DISPLAYRIGHT = STICKS(pWindow->m_vPosition.x + pWindow->m_vSize.x, PMONITOR->vecPosition.x + PMONITOR->vecSize.x - PMONITOR->vecReservedBottomRight.x);
|
||||
const bool DISPLAYTOP = STICKS(pWindow->m_vPosition.y, PMONITOR->vecPosition.y + PMONITOR->vecReservedTopLeft.y);
|
||||
|
@ -242,9 +259,35 @@ void CAnimationManager::onWindowPostCreate(CWindow* pWindow) {
|
|||
else
|
||||
pWindow->m_vRealPosition.setValue(Vector2D(GOALPOS.x, PMONITOR->vecPosition.y - GOALSIZE.y));
|
||||
}
|
||||
}
|
||||
|
||||
void CAnimationManager::onWindowPostCreate(CWindow* pWindow) {
|
||||
auto ANIMSTYLE = g_pConfigManager->getString("animations:windows_style");
|
||||
transform(ANIMSTYLE.begin(), ANIMSTYLE.end(), ANIMSTYLE.begin(), ::tolower);
|
||||
|
||||
// if the window is not being animated, that means the layout set a fixed size for it, don't animate.
|
||||
if (!pWindow->m_vRealPosition.isBeingAnimated() && !pWindow->m_vRealSize.isBeingAnimated())
|
||||
return;
|
||||
|
||||
if (pWindow->m_sAdditionalConfigData.animationStyle != "") {
|
||||
// the window has config'd special anim
|
||||
if (pWindow->m_sAdditionalConfigData.animationStyle.find("slide") == 0) {
|
||||
if (pWindow->m_sAdditionalConfigData.animationStyle.find(' ') != std::string::npos) {
|
||||
// has a direction
|
||||
animationSlide(pWindow, pWindow->m_sAdditionalConfigData.animationStyle.substr(pWindow->m_sAdditionalConfigData.animationStyle.find(' ') + 1));
|
||||
} else {
|
||||
animationSlide(pWindow);
|
||||
}
|
||||
} else {
|
||||
// anim popin, fallback
|
||||
pWindow->m_vRealPosition.setValue(GOALPOS + GOALSIZE / 2.f);
|
||||
pWindow->m_vRealSize.setValue(Vector2D(5, 5));
|
||||
animationPopin(pWindow);
|
||||
}
|
||||
} else {
|
||||
if (ANIMSTYLE == "slide") {
|
||||
animationSlide(pWindow);
|
||||
} else {
|
||||
// anim popin, fallback
|
||||
animationPopin(pWindow);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -29,6 +29,10 @@ private:
|
|||
bool deltazero(const float& a, const float& b);
|
||||
|
||||
std::unordered_map<std::string, CBezierCurve> m_mBezierCurves;
|
||||
|
||||
// Anim stuff
|
||||
void animationPopin(CWindow*);
|
||||
void animationSlide(CWindow*, std::string force = "");
|
||||
};
|
||||
|
||||
inline std::unique_ptr<CAnimationManager> g_pAnimationManager;
|
|
@ -377,7 +377,7 @@ CFramebuffer* CHyprOpenGLImpl::blurMainFramebufferWithDamage(float a, wlr_box* p
|
|||
pixman_region32_t damage;
|
||||
pixman_region32_init(&damage);
|
||||
pixman_region32_copy(&damage, originalDamage);
|
||||
wlr_region_expand(&damage, &damage, BLURPASSES * BLURSIZE * 2);
|
||||
wlr_region_expand(&damage, &damage, pow(2, BLURPASSES) * BLURSIZE);
|
||||
|
||||
// helper
|
||||
const auto PMIRRORFB = &m_mMonitorRenderResources[m_RenderData.pMonitor].mirrorFB;
|
||||
|
@ -698,12 +698,57 @@ void CHyprOpenGLImpl::makeWindowSnapshot(CWindow* pWindow) {
|
|||
wlr_output_rollback(PMONITOR->output);
|
||||
}
|
||||
|
||||
void CHyprOpenGLImpl::makeLayerSnapshot(SLayerSurface* pLayer) {
|
||||
// we trust the window is valid.
|
||||
const auto PMONITOR = g_pCompositor->getMonitorFromID(pLayer->monitorID);
|
||||
wlr_output_attach_render(PMONITOR->output, nullptr);
|
||||
|
||||
// we need to "damage" the entire monitor
|
||||
// so that we render the entire window
|
||||
// this is temporary, doesnt mess with the actual wlr damage
|
||||
pixman_region32_t fakeDamage;
|
||||
pixman_region32_init(&fakeDamage);
|
||||
pixman_region32_union_rect(&fakeDamage, &fakeDamage, 0, 0, (int)PMONITOR->vecSize.x, (int)PMONITOR->vecSize.y);
|
||||
|
||||
begin(PMONITOR, &fakeDamage);
|
||||
|
||||
pixman_region32_fini(&fakeDamage);
|
||||
|
||||
const auto PFRAMEBUFFER = &m_mLayerFramebuffers[pLayer];
|
||||
|
||||
PFRAMEBUFFER->m_tTransform = pLayer->layerSurface->surface->current.transform;
|
||||
|
||||
PFRAMEBUFFER->alloc(PMONITOR->vecSize.x, PMONITOR->vecSize.y);
|
||||
|
||||
PFRAMEBUFFER->bind();
|
||||
|
||||
clear(CColor(0, 0, 0, 0)); // JIC
|
||||
|
||||
timespec now;
|
||||
clock_gettime(CLOCK_MONOTONIC, &now);
|
||||
|
||||
// draw the layer
|
||||
g_pHyprRenderer->renderLayer(pLayer, PMONITOR, &now);
|
||||
|
||||
// restore original fb
|
||||
#ifndef GLES2
|
||||
glBindFramebuffer(GL_DRAW_FRAMEBUFFER, m_iCurrentOutputFb);
|
||||
#else
|
||||
glBindFramebuffer(GL_FRAMEBUFFER, m_iCurrentOutputFb);
|
||||
#endif
|
||||
glViewport(0, 0, g_pHyprOpenGL->m_RenderData.pMonitor->vecSize.x, g_pHyprOpenGL->m_RenderData.pMonitor->vecSize.y);
|
||||
|
||||
end();
|
||||
|
||||
wlr_output_rollback(PMONITOR->output);
|
||||
}
|
||||
|
||||
void CHyprOpenGLImpl::renderSnapshot(CWindow** pWindow) {
|
||||
RASSERT(m_RenderData.pMonitor, "Tried to render snapshot rect without begin()!");
|
||||
const auto PWINDOW = *pWindow;
|
||||
|
||||
auto it = m_mWindowFramebuffers.begin();
|
||||
for (;it != m_mWindowFramebuffers.end(); it++) {
|
||||
for (; it != m_mWindowFramebuffers.end(); it++) {
|
||||
if (it->first == PWINDOW) {
|
||||
break;
|
||||
}
|
||||
|
@ -724,6 +769,32 @@ void CHyprOpenGLImpl::renderSnapshot(CWindow** pWindow) {
|
|||
pixman_region32_fini(&fakeDamage);
|
||||
}
|
||||
|
||||
void CHyprOpenGLImpl::renderSnapshot(SLayerSurface** pLayer) {
|
||||
RASSERT(m_RenderData.pMonitor, "Tried to render snapshot rect without begin()!");
|
||||
const auto PLAYER = *pLayer;
|
||||
|
||||
auto it = m_mLayerFramebuffers.begin();
|
||||
for (; it != m_mLayerFramebuffers.end(); it++) {
|
||||
if (it->first == PLAYER) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (it == m_mLayerFramebuffers.end() || !it->second.m_cTex.m_iTexID)
|
||||
return;
|
||||
|
||||
const auto PMONITOR = g_pCompositor->getMonitorFromID(PLAYER->monitorID);
|
||||
|
||||
wlr_box windowBox = {0, 0, PMONITOR->vecSize.x, PMONITOR->vecSize.y};
|
||||
|
||||
pixman_region32_t fakeDamage;
|
||||
pixman_region32_init_rect(&fakeDamage, 0, 0, PMONITOR->vecSize.x, PMONITOR->vecSize.y);
|
||||
|
||||
renderTextureInternalWithDamage(it->second.m_cTex, &windowBox, PLAYER->alpha.fl(), &fakeDamage, 0);
|
||||
|
||||
pixman_region32_fini(&fakeDamage);
|
||||
}
|
||||
|
||||
void CHyprOpenGLImpl::createBGTextureForMonitor(SMonitor* pMonitor) {
|
||||
RASSERT(m_RenderData.pMonitor, "Tried to createBGTex without begin()!");
|
||||
|
||||
|
|
|
@ -60,7 +60,9 @@ public:
|
|||
void renderBorder(wlr_box*, const CColor&, int thick = 1, int round = 0);
|
||||
|
||||
void makeWindowSnapshot(CWindow*);
|
||||
void makeLayerSnapshot(SLayerSurface*);
|
||||
void renderSnapshot(CWindow**);
|
||||
void renderSnapshot(SLayerSurface**);
|
||||
|
||||
void clear(const CColor&);
|
||||
void clearWithTex();
|
||||
|
@ -78,6 +80,7 @@ public:
|
|||
pixman_region32_t m_rOriginalDamageRegion; // used for storing the pre-expanded region
|
||||
|
||||
std::unordered_map<CWindow*, CFramebuffer> m_mWindowFramebuffers;
|
||||
std::unordered_map<SLayerSurface*, CFramebuffer> m_mLayerFramebuffers;
|
||||
std::unordered_map<SMonitor*, SMonitorRenderData> m_mMonitorRenderResources;
|
||||
std::unordered_map<SMonitor*, CTexture> m_mMonitorBGTextures;
|
||||
|
||||
|
|
|
@ -70,8 +70,7 @@ void CHyprRenderer::renderWorkspaceWithFullscreenWindow(SMonitor* pMonitor, CWor
|
|||
|
||||
// and the overlay layers
|
||||
for (auto& ls : pMonitor->m_aLayerSurfaceLists[ZWLR_LAYER_SHELL_V1_LAYER_OVERLAY]) {
|
||||
SRenderData renderdata = {pMonitor->output, time, ls->geometry.x, ls->geometry.y};
|
||||
wlr_surface_for_each_surface(ls->layerSurface->surface, renderSurface, &renderdata);
|
||||
renderLayer(ls, pMonitor, time);
|
||||
}
|
||||
|
||||
renderDragIcon(pMonitor, time);
|
||||
|
@ -121,6 +120,17 @@ void CHyprRenderer::renderWindow(CWindow* pWindow, SMonitor* pMonitor, timespec*
|
|||
}
|
||||
}
|
||||
|
||||
void CHyprRenderer::renderLayer(SLayerSurface* pLayer, SMonitor* pMonitor, timespec* time) {
|
||||
if (pLayer->fadingOut) {
|
||||
g_pHyprOpenGL->renderSnapshot(&pLayer);
|
||||
return;
|
||||
}
|
||||
|
||||
SRenderData renderdata = {pMonitor->output, time, pLayer->geometry.x, pLayer->geometry.y};
|
||||
renderdata.fadeAlpha = pLayer->alpha.fl();
|
||||
wlr_surface_for_each_surface(pLayer->layerSurface->surface, renderSurface, &renderdata);
|
||||
}
|
||||
|
||||
void CHyprRenderer::renderAllClientsForMonitor(const int& ID, timespec* time) {
|
||||
const auto PMONITOR = g_pCompositor->getMonitorFromID(ID);
|
||||
|
||||
|
@ -129,12 +139,10 @@ void CHyprRenderer::renderAllClientsForMonitor(const int& ID, timespec* time) {
|
|||
|
||||
// Render layer surfaces below windows for monitor
|
||||
for (auto& ls : PMONITOR->m_aLayerSurfaceLists[ZWLR_LAYER_SHELL_V1_LAYER_BACKGROUND]) {
|
||||
SRenderData renderdata = {PMONITOR->output, time, ls->geometry.x, ls->geometry.y};
|
||||
wlr_surface_for_each_surface(ls->layerSurface->surface, renderSurface, &renderdata);
|
||||
renderLayer(ls, PMONITOR, time);
|
||||
}
|
||||
for (auto& ls : PMONITOR->m_aLayerSurfaceLists[ZWLR_LAYER_SHELL_V1_LAYER_BOTTOM]) {
|
||||
SRenderData renderdata = {PMONITOR->output, time, ls->geometry.x, ls->geometry.y};
|
||||
wlr_surface_for_each_surface(ls->layerSurface->surface, renderSurface, &renderdata);
|
||||
renderLayer(ls, PMONITOR, time);
|
||||
}
|
||||
|
||||
// if there is a fullscreen window, render it and then do not render anymore.
|
||||
|
@ -178,12 +186,10 @@ void CHyprRenderer::renderAllClientsForMonitor(const int& ID, timespec* time) {
|
|||
|
||||
// Render surfaces above windows for monitor
|
||||
for (auto& ls : PMONITOR->m_aLayerSurfaceLists[ZWLR_LAYER_SHELL_V1_LAYER_TOP]) {
|
||||
SRenderData renderdata = {PMONITOR->output, time, ls->geometry.x, ls->geometry.y};
|
||||
wlr_surface_for_each_surface(ls->layerSurface->surface, renderSurface, &renderdata);
|
||||
renderLayer(ls, PMONITOR, time);
|
||||
}
|
||||
for (auto& ls : PMONITOR->m_aLayerSurfaceLists[ZWLR_LAYER_SHELL_V1_LAYER_OVERLAY]) {
|
||||
SRenderData renderdata = {PMONITOR->output, time, ls->geometry.x, ls->geometry.y};
|
||||
wlr_surface_for_each_surface(ls->layerSurface->surface, renderSurface, &renderdata);
|
||||
renderLayer(ls, PMONITOR, time);
|
||||
}
|
||||
|
||||
renderDragIcon(PMONITOR, time);
|
||||
|
@ -316,6 +322,9 @@ void CHyprRenderer::arrangeLayerArray(SMonitor* pMonitor, const std::list<SLayer
|
|||
wlr_box full_area = {pMonitor->vecPosition.x, pMonitor->vecPosition.y, pMonitor->vecSize.x, pMonitor->vecSize.y};
|
||||
|
||||
for (auto& ls : layerSurfaces) {
|
||||
if (ls->fadingOut || ls->readyToDelete)
|
||||
continue;
|
||||
|
||||
const auto PLAYER = ls->layerSurface;
|
||||
const auto PSTATE = &PLAYER->current;
|
||||
if (exclusiveZone != (PSTATE->exclusive_zone > 0)) {
|
||||
|
|
|
@ -37,6 +37,7 @@ private:
|
|||
void drawBorderForWindow(CWindow*, SMonitor*, float a = 255.f, const Vector2D& offset = Vector2D(0,0));
|
||||
void renderWorkspaceWithFullscreenWindow(SMonitor*, CWorkspace*, timespec*);
|
||||
void renderWindow(CWindow*, SMonitor*, timespec*, bool);
|
||||
void renderLayer(SLayerSurface*, SMonitor*, timespec*);
|
||||
void renderDragIcon(SMonitor*, timespec*);
|
||||
|
||||
|
||||
|
|
Loading…
Reference in a new issue