Merge branch 'vaxerski:main' into main

This commit is contained in:
Narice 2022-05-16 11:53:28 +01:00 committed by GitHub
commit 23c3534197
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
19 changed files with 437 additions and 78 deletions

View File

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

View File

@ -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) {
@ -863,4 +883,4 @@ SMonitor* CCompositor::getMonitorInDirection(const char& dir) {
return longestIntersectMonitor;
return nullptr;
}
}

View File

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

View File

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

View File

@ -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()) {
parseError = "Error setting value <" + VALUE + "> for field <" + COMMAND + ">: No such field.";
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,18 +703,26 @@ void CConfigManager::tick() {
return;
}
struct stat fileStat;
int err = stat(CONFIGPATH.c_str(), &fileStat);
if (err != 0) {
Debug::log(WARN, "Error at ticking config at %s, error %i: %s", CONFIGPATH.c_str(), err, strerror(err));
return;
bool parse = false;
for (auto& cf : configPaths) {
struct stat fileStat;
int err = stat(cf.c_str(), &fileStat);
if (err != 0) {
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 != configModifyTimes[cf] || m_bForceReload) {
parse = true;
configModifyTimes[cf] = fileStat.st_mtime;
}
}
// check if we need to reload cfg
if (fileStat.st_mtime != lastModifyTime || m_bForceReload) {
lastModifyTime = fileStat.st_mtime;
if (parse) {
m_bForceReload = false;
loadConfigLoadVars();
}
}

View File

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

View File

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

View File

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

View File

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

View File

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

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

View File

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

View File

@ -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,8 +203,64 @@ 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
//
//
void CAnimationManager::animationPopin(CWindow* pWindow) {
const auto GOALPOS = pWindow->m_vRealPosition.goalv();
const auto GOALSIZE = pWindow->m_vRealSize.goalv();
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();
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 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);
const bool DISPLAYBOTTOM = STICKS(pWindow->m_vPosition.y + pWindow->m_vSize.y, PMONITOR->vecPosition.y + PMONITOR->vecSize.y - PMONITOR->vecReservedBottomRight.y);
if (DISPLAYBOTTOM && DISPLAYTOP) {
if (DISPLAYLEFT && DISPLAYRIGHT) {
pWindow->m_vRealPosition.setValue(GOALPOS + Vector2D(0, GOALSIZE.y));
} else if (DISPLAYLEFT) {
pWindow->m_vRealPosition.setValue(GOALPOS - Vector2D(GOALSIZE.x, 0));
} else {
pWindow->m_vRealPosition.setValue(GOALPOS + Vector2D(GOALSIZE.x, 0));
}
} else if (DISPLAYTOP) {
pWindow->m_vRealPosition.setValue(GOALPOS - Vector2D(0, GOALSIZE.y));
} else if (DISPLAYBOTTOM) {
pWindow->m_vRealPosition.setValue(GOALPOS + Vector2D(0, GOALSIZE.y));
} else {
if (MIDPOINT.y > PMONITOR->vecPosition.y + PMONITOR->vecSize.y / 2.f)
pWindow->m_vRealPosition.setValue(Vector2D(GOALPOS.x, PMONITOR->vecPosition.y + PMONITOR->vecSize.y));
else
pWindow->m_vRealPosition.setValue(Vector2D(GOALPOS.x, PMONITOR->vecPosition.y - GOALSIZE.y));
}
}
// animation on events
void CAnimationManager::onWindowPostCreate(CWindow* pWindow) {
auto ANIMSTYLE = g_pConfigManager->getString("animations:windows_style");
transform(ANIMSTYLE.begin(), ANIMSTYLE.end(), ANIMSTYLE.begin(), ::tolower);
@ -209,42 +269,25 @@ void CAnimationManager::onWindowPostCreate(CWindow* pWindow) {
if (!pWindow->m_vRealPosition.isBeingAnimated() && !pWindow->m_vRealSize.isBeingAnimated())
return;
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 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);
const bool DISPLAYBOTTOM = STICKS(pWindow->m_vPosition.y + pWindow->m_vSize.y, PMONITOR->vecPosition.y + PMONITOR->vecSize.y - PMONITOR->vecReservedBottomRight.y);
if (DISPLAYBOTTOM && DISPLAYTOP) {
if (DISPLAYLEFT && DISPLAYRIGHT) {
pWindow->m_vRealPosition.setValue(GOALPOS + Vector2D(0, GOALSIZE.y));
} else if (DISPLAYLEFT) {
pWindow->m_vRealPosition.setValue(GOALPOS - Vector2D(GOALSIZE.x, 0));
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 {
pWindow->m_vRealPosition.setValue(GOALPOS + Vector2D(GOALSIZE.x, 0));
animationSlide(pWindow);
}
} else if (DISPLAYTOP) {
pWindow->m_vRealPosition.setValue(GOALPOS - Vector2D(0, GOALSIZE.y));
} else if (DISPLAYBOTTOM) {
pWindow->m_vRealPosition.setValue(GOALPOS + Vector2D(0, GOALSIZE.y));
} else {
if (MIDPOINT.y > PMONITOR->vecPosition.y + PMONITOR->vecSize.y / 2.f)
pWindow->m_vRealPosition.setValue(Vector2D(GOALPOS.x, PMONITOR->vecPosition.y + PMONITOR->vecSize.y));
else
pWindow->m_vRealPosition.setValue(Vector2D(GOALPOS.x, PMONITOR->vecPosition.y - GOALSIZE.y));
// anim popin, fallback
animationPopin(pWindow);
}
} else {
// anim popin, fallback
pWindow->m_vRealPosition.setValue(GOALPOS + GOALSIZE / 2.f);
pWindow->m_vRealSize.setValue(Vector2D(5, 5));
if (ANIMSTYLE == "slide") {
animationSlide(pWindow);
} else {
// anim popin, fallback
animationPopin(pWindow);
}
}
}

View File

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

View File

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

View File

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

View File

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

View File

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