mirror of
https://github.com/hyprwm/Hyprland.git
synced 2025-08-05 06:31:57 -07:00
Compare commits
40 Commits
0.1.0-beta
...
v0.1.4beta
Author | SHA1 | Date | |
---|---|---|---|
|
e81790f357 | ||
|
edf57c50ff | ||
|
e2be91582a | ||
|
7522ade58d | ||
|
3d7abfea92 | ||
|
2de65771ea | ||
|
6b60595822 | ||
|
b76b32b458 | ||
|
f5645805d8 | ||
|
15338fcf63 | ||
|
227cbb0464 | ||
|
9842730f57 | ||
|
d0ff0c0990 | ||
|
fdb3f610e5 | ||
|
d2e1899f26 | ||
|
9d3099b21f | ||
|
4cc085ac75 | ||
|
af55d5aa96 | ||
|
632d00c51c | ||
|
f06d4fca27 | ||
|
2cd5059cf1 | ||
|
65610555c4 | ||
|
3f8845a6a7 | ||
|
894ae2d742 | ||
|
08e0567d3a | ||
|
685cf1e00d | ||
|
bdf1c16195 | ||
|
b1b24cb21a | ||
|
9ede0f1c7d | ||
|
10a9325a6a | ||
|
e4d494aed4 | ||
|
5c911df351 | ||
|
15553804d6 | ||
|
7f1f14fe85 | ||
|
7d442d4851 | ||
|
8c10857f14 | ||
|
9b6960eb55 | ||
|
4cda50399c | ||
|
daff7d8ca2 | ||
|
1bef63a1e6 |
4
.gitignore
vendored
4
.gitignore
vendored
@@ -19,3 +19,7 @@ result
|
||||
.ccls-cache
|
||||
|
||||
hyprctl/hyprctl
|
||||
|
||||
gmon.out
|
||||
*.out
|
||||
*.tar.gz
|
32
aur/PKGBUILD
Normal file
32
aur/PKGBUILD
Normal file
@@ -0,0 +1,32 @@
|
||||
# Maintainer: ThatOneCalculator <kainoa@t1c.dev>
|
||||
|
||||
_pkgname="hyprland"
|
||||
pkgname="${_pkgname}"
|
||||
pkgver="0.1.1beta"
|
||||
pkgrel=2
|
||||
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}-${pkgver}.tar.gz::https://github.com/vaxerski/hyprland/archive/v${pkgver}.tar.gz")
|
||||
sha256sums=('SKIP')
|
||||
options=(!makeflags !buildflags)
|
||||
|
||||
build() {
|
||||
cd "$srcdir/Hyprland-$pkgver"
|
||||
make all
|
||||
}
|
||||
|
||||
package() {
|
||||
cd "$srcdir/Hyprland-$pkgver"
|
||||
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}"
|
||||
}
|
@@ -1,9 +1,9 @@
|
||||
# Maintainer: Sander van Kasteel <info@sandervankasteel.nl>, ThatOneCalculator <kainoa@t1c.dev>
|
||||
# Maintainer: ThatOneCalculator <kainoa@t1c.dev>, Sander van Kasteel <info@sandervankasteel.nl>
|
||||
|
||||
_pkgname="hyprland"
|
||||
pkgname="${_pkgname}-git"
|
||||
pkgver=r461.96cdf8f
|
||||
pkgrel=5
|
||||
pkgver=r568.g632d00c
|
||||
pkgrel=1
|
||||
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"
|
||||
|
@@ -64,7 +64,7 @@ dwindle {
|
||||
# example binds
|
||||
bind=SUPER,Q,exec,kitty
|
||||
bind=SUPER,C,killactive,
|
||||
bind=SUPER,M,exec,pkill Hyprland
|
||||
bind=SUPER,M,exit,
|
||||
bind=SUPER,E,exec,dolphin
|
||||
bind=SUPER,V,togglefloating,
|
||||
bind=SUPER,R,exec,wofi --show drun -o DP-3
|
||||
|
12
flake.lock
generated
12
flake.lock
generated
@@ -2,11 +2,11 @@
|
||||
"nodes": {
|
||||
"nixpkgs": {
|
||||
"locked": {
|
||||
"lastModified": 1653407748,
|
||||
"narHash": "sha256-g9puJaILRTb9ttlLQ7IehpV7Wcy0n+vs8LOFu6ylQcM=",
|
||||
"lastModified": 1653581809,
|
||||
"narHash": "sha256-Uvka0V5MTGbeOfWte25+tfRL3moECDh1VwokWSZUdoY=",
|
||||
"owner": "NixOS",
|
||||
"repo": "nixpkgs",
|
||||
"rev": "5ce6597eca7d7b518c03ecda57d45f9404b5e060",
|
||||
"rev": "83658b28fe638a170a19b8933aa008b30640fbd1",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
@@ -26,11 +26,11 @@
|
||||
"flake": false,
|
||||
"locked": {
|
||||
"host": "gitlab.freedesktop.org",
|
||||
"lastModified": 1653502661,
|
||||
"narHash": "sha256-unQ1j3jleghIMi340dJTJZZ1ffwm1cI7gaQbdKd7laE=",
|
||||
"lastModified": 1653733431,
|
||||
"narHash": "sha256-0JwNH2E9XlMVa7ZCsqxazpKwpZ2rW5QQjbk0DdZxa48=",
|
||||
"owner": "wlroots",
|
||||
"repo": "wlroots",
|
||||
"rev": "1cb6b2cf673a5b580d7ad79ce2b37c14b14b0268",
|
||||
"rev": "93ee4c7684050807e959bb3b6d57826a72fba8c2",
|
||||
"type": "gitlab"
|
||||
},
|
||||
"original": {
|
||||
|
@@ -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, 2);
|
||||
m_sWLRXDGShell = wlr_xdg_shell_create(m_sWLDisplay, 3);
|
||||
|
||||
m_sWLRCursor = wlr_cursor_create();
|
||||
wlr_cursor_attach_output_layout(m_sWLRCursor, m_sWLROutputLayout);
|
||||
@@ -102,6 +102,8 @@ CCompositor::CCompositor() {
|
||||
m_sWLRVKeyboardMgr = wlr_virtual_keyboard_manager_v1_create(m_sWLDisplay);
|
||||
|
||||
m_sWLRVirtPtrMgr = wlr_virtual_pointer_manager_v1_create(m_sWLDisplay);
|
||||
|
||||
m_sWLRToplevelMgr = wlr_foreign_toplevel_manager_v1_create(m_sWLDisplay);
|
||||
}
|
||||
|
||||
CCompositor::~CCompositor() {
|
||||
@@ -144,6 +146,12 @@ void CCompositor::cleanupExit() {
|
||||
if (!m_sWLDisplay)
|
||||
return;
|
||||
|
||||
m_pLastFocus = nullptr;
|
||||
m_pLastWindow = nullptr;
|
||||
|
||||
m_lWorkspaces.clear();
|
||||
m_lWindows.clear();
|
||||
|
||||
if (g_pXWaylandManager->m_sWLRXWayland) {
|
||||
wlr_xwayland_destroy(g_pXWaylandManager->m_sWLRXWayland);
|
||||
g_pXWaylandManager->m_sWLRXWayland = nullptr;
|
||||
@@ -192,6 +200,9 @@ void CCompositor::startCompositor() {
|
||||
Debug::log(LOG, "Creating the EventManager!");
|
||||
g_pEventManager = std::make_unique<CEventManager>();
|
||||
g_pEventManager->startThread();
|
||||
|
||||
Debug::log(LOG, "Creating the HyprDebugOverlay!");
|
||||
g_pDebugOverlay = std::make_unique<CHyprDebugOverlay>();
|
||||
//
|
||||
//
|
||||
|
||||
@@ -244,6 +255,16 @@ SMonitor* CCompositor::getMonitorFromID(const int& id) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
SMonitor* CCompositor::getMonitorFromName(const std::string& name) {
|
||||
for (auto& m : m_lMonitors) {
|
||||
if (m.szName == name) {
|
||||
return &m;
|
||||
}
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
SMonitor* CCompositor::getMonitorFromCursor() {
|
||||
const auto COORDS = Vector2D(m_sWLRCursor->x, m_sWLRCursor->y);
|
||||
|
||||
@@ -433,6 +454,9 @@ void CCompositor::focusWindow(CWindow* pWindow, wlr_surface* pSurface) {
|
||||
wlr_seat_keyboard_notify_clear_focus(m_sSeat.seat);
|
||||
wlr_seat_pointer_clear_focus(m_sSeat.seat);
|
||||
}
|
||||
|
||||
if (PLASTWINDOW->m_phForeignToplevel)
|
||||
wlr_foreign_toplevel_handle_v1_set_activated(PLASTWINDOW->m_phForeignToplevel, false);
|
||||
}
|
||||
|
||||
m_pLastWindow = PLASTWINDOW;
|
||||
@@ -451,6 +475,9 @@ void CCompositor::focusWindow(CWindow* pWindow, wlr_surface* pSurface) {
|
||||
|
||||
// Send an event
|
||||
g_pEventManager->postEvent(SHyprIPCEvent("activewindow", g_pXWaylandManager->getAppIDClass(pWindow) + "," + pWindow->m_szTitle));
|
||||
|
||||
if (pWindow->m_phForeignToplevel)
|
||||
wlr_foreign_toplevel_handle_v1_set_activated(pWindow->m_phForeignToplevel, true);
|
||||
}
|
||||
|
||||
void CCompositor::focusSurface(wlr_surface* pSurface, CWindow* pWindowOwner) {
|
||||
@@ -614,6 +641,9 @@ bool CCompositor::doesSeatAcceptInput(wlr_surface* surface) {
|
||||
}
|
||||
|
||||
bool CCompositor::isWindowActive(CWindow* pWindow) {
|
||||
if (!m_pLastWindow && !m_pLastFocus)
|
||||
return false;
|
||||
|
||||
if (!windowValidMapped(pWindow))
|
||||
return false;
|
||||
|
||||
|
@@ -15,6 +15,7 @@
|
||||
#include "managers/KeybindManager.hpp"
|
||||
#include "managers/AnimationManager.hpp"
|
||||
#include "managers/EventManager.hpp"
|
||||
#include "debug/HyprDebugOverlay.hpp"
|
||||
#include "helpers/Monitor.hpp"
|
||||
#include "helpers/Workspace.hpp"
|
||||
#include "Window.hpp"
|
||||
@@ -57,6 +58,7 @@ public:
|
||||
wlr_server_decoration_manager* m_sWLRServerDecoMgr;
|
||||
wlr_xdg_decoration_manager_v1* m_sWLRXDGDecoMgr;
|
||||
wlr_virtual_pointer_manager_v1* m_sWLRVirtPtrMgr;
|
||||
wlr_foreign_toplevel_manager_v1* m_sWLRToplevelMgr;
|
||||
// ------------------------------------------------- //
|
||||
|
||||
|
||||
@@ -84,6 +86,7 @@ public:
|
||||
// ------------------------------------------------- //
|
||||
|
||||
SMonitor* getMonitorFromID(const int&);
|
||||
SMonitor* getMonitorFromName(const std::string&);
|
||||
SMonitor* getMonitorFromCursor();
|
||||
SMonitor* getMonitorFromVector(const Vector2D&);
|
||||
void removeWindowFromVectorSafe(CWindow*);
|
||||
|
@@ -4,6 +4,8 @@
|
||||
#include "events/Events.hpp"
|
||||
#include "helpers/SubsurfaceTree.hpp"
|
||||
#include "helpers/AnimatedVariable.hpp"
|
||||
#include "render/decorations/IHyprWindowDecoration.hpp"
|
||||
#include <deque>
|
||||
|
||||
struct SWindowSpecialRenderData {
|
||||
float alpha = 1.f;
|
||||
@@ -11,6 +13,7 @@ struct SWindowSpecialRenderData {
|
||||
|
||||
struct SWindowAdditionalConfigData {
|
||||
std::string animationStyle = "";
|
||||
int rounding = -1; // -1 means no
|
||||
};
|
||||
|
||||
class CWindow {
|
||||
@@ -81,10 +84,18 @@ public:
|
||||
CAnimatedVariable m_fAlpha;
|
||||
bool m_bFadingOut = false;
|
||||
bool m_bReadyToDelete = false;
|
||||
Vector2D m_vOriginalClosedPos; // these will be used for calculations later on in
|
||||
Vector2D m_vOriginalClosedSize; // drawing the closing animations
|
||||
|
||||
// For hidden windows and stuff
|
||||
bool m_bHidden = false;
|
||||
|
||||
// Foreign Toplevel proto
|
||||
wlr_foreign_toplevel_handle_v1* m_phForeignToplevel = nullptr;
|
||||
|
||||
// Window decorations
|
||||
std::deque<std::unique_ptr<IHyprWindowDecoration>> m_dWindowDecorations;
|
||||
|
||||
// Special render data, rules, etc
|
||||
SWindowSpecialRenderData m_sSpecialRenderData;
|
||||
SWindowAdditionalConfigData m_sAdditionalConfigData;
|
||||
|
@@ -35,11 +35,13 @@ void CConfigManager::setDefaultVars() {
|
||||
|
||||
configValues["debug:int"].intValue = 0;
|
||||
configValues["debug:log_damage"].intValue = 0;
|
||||
configValues["debug:overlay"].intValue = 0;
|
||||
|
||||
configValues["decoration:rounding"].intValue = 1;
|
||||
configValues["decoration:blur"].intValue = 1;
|
||||
configValues["decoration:blur_size"].intValue = 8;
|
||||
configValues["decoration:blur_passes"].intValue = 1;
|
||||
configValues["decoration:blur_ignore_opacity"].intValue = 0;
|
||||
configValues["decoration:active_opacity"].floatValue = 1;
|
||||
configValues["decoration:inactive_opacity"].floatValue = 1;
|
||||
configValues["decoration:fullscreen_opacity"].floatValue = 1;
|
||||
@@ -184,10 +186,24 @@ void CConfigManager::handleMonitor(const std::string& command, const std::string
|
||||
|
||||
nextItem();
|
||||
|
||||
if (curitem == "disable" || curitem == "disabled" || curitem == "addreserved") {
|
||||
if (curitem == "disable" || curitem == "disabled" || curitem == "addreserved" || curitem == "transform") {
|
||||
if (curitem == "disable" || curitem == "disabled")
|
||||
newrule.disabled = true;
|
||||
else if (curitem == "addreserved") {
|
||||
else if (curitem == "transform") {
|
||||
nextItem();
|
||||
|
||||
wl_output_transform transform = (wl_output_transform)std::stoi(curitem);
|
||||
|
||||
// overwrite if exists
|
||||
for (auto& r : m_dMonitorRules) {
|
||||
if (r.name == newrule.name) {
|
||||
r.transform = transform;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
return;
|
||||
} else if (curitem == "addreserved") {
|
||||
nextItem();
|
||||
|
||||
int top = std::stoi(curitem);
|
||||
@@ -411,6 +427,7 @@ void CConfigManager::handleWindowRule(const std::string& command, const std::str
|
||||
&& RULE.find("monitor") != 0
|
||||
&& RULE.find("nofocus") != 0
|
||||
&& RULE.find("animation") != 0
|
||||
&& RULE.find("rounding") != 0
|
||||
&& RULE.find("workspace") != 0) {
|
||||
Debug::log(ERR, "Invalid rule found: %s", RULE.c_str());
|
||||
parseError = "Invalid rule found: " + RULE;
|
||||
|
@@ -30,6 +30,7 @@ struct SMonitorRule {
|
||||
float refreshRate = 60;
|
||||
int defaultWorkspaceID = -1;
|
||||
bool disabled = false;
|
||||
wl_output_transform transform = WL_OUTPUT_TRANSFORM_NORMAL;
|
||||
};
|
||||
|
||||
struct SMonitorAdditionalReservedArea {
|
||||
|
@@ -71,7 +71,7 @@ dwindle {
|
||||
# example binds
|
||||
bind=SUPER,Q,exec,kitty
|
||||
bind=SUPER,C,killactive,
|
||||
bind=SUPER,M,exec,pkill Hyprland
|
||||
bind=SUPER,M,exit,
|
||||
bind=SUPER,E,exec,dolphin
|
||||
bind=SUPER,V,togglefloating,
|
||||
bind=SUPER,R,exec,wofi --show drun -o DP-3
|
||||
|
181
src/debug/HyprDebugOverlay.cpp
Normal file
181
src/debug/HyprDebugOverlay.cpp
Normal file
@@ -0,0 +1,181 @@
|
||||
#include "HyprDebugOverlay.hpp"
|
||||
#include "../Compositor.hpp"
|
||||
|
||||
void CHyprMonitorDebugOverlay::renderData(SMonitor* pMonitor, float µs) {
|
||||
m_dLastRenderTimes.push_back(µs / 1000.f);
|
||||
|
||||
if (m_dLastRenderTimes.size() > (long unsigned int)pMonitor->refreshRate)
|
||||
m_dLastRenderTimes.pop_front();
|
||||
|
||||
if (!m_pMonitor)
|
||||
m_pMonitor = pMonitor;
|
||||
}
|
||||
|
||||
void CHyprMonitorDebugOverlay::renderDataNoOverlay(SMonitor* pMonitor, float µs) {
|
||||
m_dLastRenderTimesNoOverlay.push_back(µs / 1000.f);
|
||||
|
||||
if (m_dLastRenderTimesNoOverlay.size() > (long unsigned int)pMonitor->refreshRate)
|
||||
m_dLastRenderTimesNoOverlay.pop_front();
|
||||
|
||||
if (!m_pMonitor)
|
||||
m_pMonitor = pMonitor;
|
||||
}
|
||||
|
||||
void CHyprMonitorDebugOverlay::frameData(SMonitor* pMonitor) {
|
||||
m_dLastFrametimes.push_back(std::chrono::duration_cast<std::chrono::microseconds>(std::chrono::high_resolution_clock::now() - m_tpLastFrame).count() / 1000.f);
|
||||
|
||||
if (m_dLastFrametimes.size() > (long unsigned int)pMonitor->refreshRate)
|
||||
m_dLastFrametimes.pop_front();
|
||||
|
||||
m_tpLastFrame = std::chrono::high_resolution_clock::now();
|
||||
|
||||
if (!m_pMonitor)
|
||||
m_pMonitor = pMonitor;
|
||||
}
|
||||
|
||||
int CHyprMonitorDebugOverlay::draw(int offset) {
|
||||
|
||||
if (!m_pMonitor)
|
||||
return 0;
|
||||
|
||||
int yOffset = offset;
|
||||
cairo_text_extents_t cairoExtents;
|
||||
float maxX = 0;
|
||||
std::string text = "";
|
||||
|
||||
// get avg fps
|
||||
float avgFrametime = 0;
|
||||
for (auto& ft : m_dLastFrametimes) {
|
||||
avgFrametime += ft;
|
||||
}
|
||||
avgFrametime /= m_dLastFrametimes.size() == 0 ? 1 : m_dLastFrametimes.size();
|
||||
|
||||
float avgRenderTime = 0;
|
||||
for (auto& rt : m_dLastRenderTimes) {
|
||||
avgRenderTime += rt;
|
||||
}
|
||||
avgRenderTime /= m_dLastRenderTimes.size() == 0 ? 1 : m_dLastRenderTimes.size();
|
||||
|
||||
float avgRenderTimeNoOverlay = 0;
|
||||
for (auto& rt : m_dLastRenderTimesNoOverlay) {
|
||||
avgRenderTimeNoOverlay += rt;
|
||||
}
|
||||
avgRenderTimeNoOverlay /= m_dLastRenderTimes.size() == 0 ? 1 : m_dLastRenderTimes.size();
|
||||
|
||||
const float FPS = 1.f / (avgFrametime / 1000.f); // frametimes are in ms
|
||||
const float idealFPS = m_dLastFrametimes.size();
|
||||
|
||||
cairo_select_font_face(g_pDebugOverlay->m_pCairo, "Noto Sans", CAIRO_FONT_SLANT_NORMAL, CAIRO_FONT_WEIGHT_NORMAL);
|
||||
|
||||
cairo_set_font_size(g_pDebugOverlay->m_pCairo, 10);
|
||||
cairo_set_source_rgba(g_pDebugOverlay->m_pCairo, 1.f, 1.f, 1.f, 1.f);
|
||||
|
||||
yOffset += 10;
|
||||
cairo_move_to(g_pDebugOverlay->m_pCairo, 0, yOffset);
|
||||
text = m_pMonitor->szName;
|
||||
cairo_show_text(g_pDebugOverlay->m_pCairo, text.c_str());
|
||||
cairo_text_extents(g_pDebugOverlay->m_pCairo, text.c_str(), &cairoExtents);
|
||||
if (cairoExtents.width > maxX) maxX = cairoExtents.width;
|
||||
|
||||
cairo_set_font_size(g_pDebugOverlay->m_pCairo, 16);
|
||||
|
||||
if (FPS > idealFPS * 0.95f)
|
||||
cairo_set_source_rgba(g_pDebugOverlay->m_pCairo, 0.2f, 1.f, 0.2f, 1.f);
|
||||
else if (FPS > idealFPS * 0.8f)
|
||||
cairo_set_source_rgba(g_pDebugOverlay->m_pCairo, 1.f, 1.f, 0.2f, 1.f);
|
||||
else
|
||||
cairo_set_source_rgba(g_pDebugOverlay->m_pCairo, 1.f, 0.2f, 0.2f, 1.f);
|
||||
|
||||
yOffset += 17;
|
||||
cairo_move_to(g_pDebugOverlay->m_pCairo, 0, yOffset);
|
||||
text = std::string(std::to_string((int)FPS) + " FPS");
|
||||
cairo_show_text(g_pDebugOverlay->m_pCairo, text.c_str());
|
||||
cairo_text_extents(g_pDebugOverlay->m_pCairo, text.c_str(), &cairoExtents);
|
||||
if (cairoExtents.width > maxX) maxX = cairoExtents.width;
|
||||
|
||||
cairo_set_font_size(g_pDebugOverlay->m_pCairo, 10);
|
||||
cairo_set_source_rgba(g_pDebugOverlay->m_pCairo, 1.f, 1.f, 1.f, 1.f);
|
||||
|
||||
yOffset += 11;
|
||||
cairo_move_to(g_pDebugOverlay->m_pCairo, 0, yOffset);
|
||||
text = std::string("Avg Frametime: " + std::to_string((int)avgFrametime) + "." + std::to_string((int)(avgFrametime * 10.f) % 10) + "ms");
|
||||
cairo_show_text(g_pDebugOverlay->m_pCairo, text.c_str());
|
||||
cairo_text_extents(g_pDebugOverlay->m_pCairo, text.c_str(), &cairoExtents);
|
||||
if (cairoExtents.width > maxX) maxX = cairoExtents.width;
|
||||
|
||||
yOffset += 11;
|
||||
cairo_move_to(g_pDebugOverlay->m_pCairo, 0, yOffset);
|
||||
text = std::string("Avg Rendertime: " + std::to_string((int)avgRenderTime) + "." + std::to_string((int)(avgRenderTime * 10.f) % 10) + "ms");
|
||||
cairo_show_text(g_pDebugOverlay->m_pCairo, text.c_str());
|
||||
cairo_text_extents(g_pDebugOverlay->m_pCairo, text.c_str(), &cairoExtents);
|
||||
if (cairoExtents.width > maxX) maxX = cairoExtents.width;
|
||||
|
||||
yOffset += 11;
|
||||
cairo_move_to(g_pDebugOverlay->m_pCairo, 0, yOffset);
|
||||
text = std::string("Avg Rendertime (no overlay): " + std::to_string((int)avgRenderTimeNoOverlay) + "." + std::to_string((int)(avgRenderTimeNoOverlay * 10.f) % 10) + "ms");
|
||||
cairo_show_text(g_pDebugOverlay->m_pCairo, text.c_str());
|
||||
cairo_text_extents(g_pDebugOverlay->m_pCairo, text.c_str(), &cairoExtents);
|
||||
if (cairoExtents.width > maxX) maxX = cairoExtents.width;
|
||||
|
||||
yOffset += 11;
|
||||
|
||||
g_pHyprRenderer->damageBox(&m_wbLastDrawnBox);
|
||||
m_wbLastDrawnBox = {(int)g_pCompositor->m_lMonitors.front().vecPosition.x, (int)g_pCompositor->m_lMonitors.front().vecPosition.y + offset - 1, (int)maxX + 2, yOffset - offset + 2};
|
||||
g_pHyprRenderer->damageBox(&m_wbLastDrawnBox);
|
||||
|
||||
return yOffset - offset;
|
||||
}
|
||||
|
||||
void CHyprDebugOverlay::renderData(SMonitor* pMonitor, float µs) {
|
||||
m_mMonitorOverlays[pMonitor].renderData(pMonitor, µs);
|
||||
}
|
||||
|
||||
void CHyprDebugOverlay::renderDataNoOverlay(SMonitor* pMonitor, float µs) {
|
||||
m_mMonitorOverlays[pMonitor].renderDataNoOverlay(pMonitor, µs);
|
||||
}
|
||||
|
||||
void CHyprDebugOverlay::frameData(SMonitor* pMonitor) {
|
||||
m_mMonitorOverlays[pMonitor].frameData(pMonitor);
|
||||
}
|
||||
|
||||
void CHyprDebugOverlay::draw() {
|
||||
|
||||
const auto PMONITOR = &g_pCompositor->m_lMonitors.front();
|
||||
|
||||
if (!m_pCairoSurface || !m_pCairo) {
|
||||
m_pCairoSurface = cairo_image_surface_create(CAIRO_FORMAT_ARGB32, PMONITOR->vecSize.x, PMONITOR->vecSize.y);
|
||||
m_pCairo = cairo_create(m_pCairoSurface);
|
||||
}
|
||||
|
||||
// clear the pixmap
|
||||
cairo_save(m_pCairo);
|
||||
cairo_set_operator(m_pCairo, CAIRO_OPERATOR_CLEAR);
|
||||
cairo_paint(m_pCairo);
|
||||
cairo_restore(m_pCairo);
|
||||
|
||||
// draw the things
|
||||
int offsetY = 0;
|
||||
for (auto& m : g_pCompositor->m_lMonitors) {
|
||||
offsetY += m_mMonitorOverlays[&m].draw(offsetY);
|
||||
offsetY += 5; // for padding between mons
|
||||
}
|
||||
|
||||
cairo_surface_flush(m_pCairoSurface);
|
||||
|
||||
// copy the data to an OpenGL texture we have
|
||||
const auto DATA = cairo_image_surface_get_data(m_pCairoSurface);
|
||||
m_tTexture.allocate();
|
||||
glBindTexture(GL_TEXTURE_2D, m_tTexture.m_iTexID);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
|
||||
|
||||
#ifndef GLES2
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_R, GL_BLUE);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_B, GL_RED);
|
||||
#endif
|
||||
|
||||
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, PMONITOR->vecSize.x, PMONITOR->vecSize.y, 0, GL_RGBA, GL_UNSIGNED_BYTE, DATA);
|
||||
|
||||
wlr_box pMonBox = {0,0,PMONITOR->vecPixelSize.x, PMONITOR->vecPixelSize.y};
|
||||
g_pHyprOpenGL->renderTexture(m_tTexture, &pMonBox, 255.f);
|
||||
}
|
47
src/debug/HyprDebugOverlay.hpp
Normal file
47
src/debug/HyprDebugOverlay.hpp
Normal file
@@ -0,0 +1,47 @@
|
||||
#pragma once
|
||||
|
||||
#include "../defines.hpp"
|
||||
#include "../helpers/Monitor.hpp"
|
||||
#include "../render/Texture.hpp"
|
||||
#include <deque>
|
||||
#include <cairo/cairo.h>
|
||||
#include <unordered_map>
|
||||
|
||||
class CHyprMonitorDebugOverlay {
|
||||
public:
|
||||
int draw(int offset);
|
||||
|
||||
void renderData(SMonitor* pMonitor, float µs);
|
||||
void renderDataNoOverlay(SMonitor* pMonitor, float µs);
|
||||
void frameData(SMonitor* pMonitor);
|
||||
|
||||
private:
|
||||
std::deque<float> m_dLastFrametimes;
|
||||
std::deque<float> m_dLastRenderTimes;
|
||||
std::deque<float> m_dLastRenderTimesNoOverlay;
|
||||
std::chrono::high_resolution_clock::time_point m_tpLastFrame;
|
||||
SMonitor* m_pMonitor = nullptr;
|
||||
wlr_box m_wbLastDrawnBox;
|
||||
};
|
||||
|
||||
class CHyprDebugOverlay {
|
||||
public:
|
||||
|
||||
void draw();
|
||||
void renderData(SMonitor*, float µs);
|
||||
void renderDataNoOverlay(SMonitor*, float µs);
|
||||
void frameData(SMonitor*);
|
||||
|
||||
private:
|
||||
|
||||
std::unordered_map<SMonitor*, CHyprMonitorDebugOverlay> m_mMonitorOverlays;
|
||||
|
||||
cairo_surface_t* m_pCairoSurface = nullptr;
|
||||
cairo_t* m_pCairo = nullptr;
|
||||
|
||||
CTexture m_tTexture;
|
||||
|
||||
friend class CHyprMonitorDebugOverlay;
|
||||
};
|
||||
|
||||
inline std::unique_ptr<CHyprDebugOverlay> g_pDebugOverlay;
|
@@ -64,4 +64,4 @@
|
||||
#endif
|
||||
#ifndef GIT_DIRTY
|
||||
#define GIT_DIRTY "?"
|
||||
#endif
|
||||
#endif
|
@@ -48,6 +48,16 @@ void Events::listener_newOutput(wl_listener* listener, void* data) {
|
||||
// new monitor added, let's accomodate for that.
|
||||
const auto OUTPUT = (wlr_output*)data;
|
||||
|
||||
if (!OUTPUT->name) {
|
||||
Debug::log(ERR, "New monitor has no name?? Ignoring");
|
||||
return;
|
||||
}
|
||||
|
||||
if (g_pCompositor->getMonitorFromName(std::string(OUTPUT->name))) {
|
||||
Debug::log(WARN, "Monitor with name %s already exists, not adding as new!", OUTPUT->name);
|
||||
return;
|
||||
}
|
||||
|
||||
// get monitor rule that matches
|
||||
SMonitorRule monitorRule = g_pConfigManager->getMonitorRuleFor(OUTPUT->name);
|
||||
|
||||
@@ -131,6 +141,15 @@ void Events::listener_newOutput(wl_listener* listener, void* data) {
|
||||
void Events::listener_monitorFrame(void* owner, void* data) {
|
||||
SMonitor* const PMONITOR = (SMonitor*)owner;
|
||||
|
||||
static std::chrono::high_resolution_clock::time_point startRender = std::chrono::high_resolution_clock::now();
|
||||
static std::chrono::high_resolution_clock::time_point startRenderOverlay = std::chrono::high_resolution_clock::now();
|
||||
static std::chrono::high_resolution_clock::time_point endRenderOverlay = std::chrono::high_resolution_clock::now();
|
||||
|
||||
if (g_pConfigManager->getInt("debug:overlay") == 1) {
|
||||
startRender = std::chrono::high_resolution_clock::now();
|
||||
g_pDebugOverlay->frameData(PMONITOR);
|
||||
}
|
||||
|
||||
// Hack: only check when monitor with top hz refreshes, saves a bit of resources.
|
||||
// This is for stuff that should be run every frame
|
||||
if (PMONITOR->ID == pMostHzMonitor->ID) {
|
||||
@@ -182,7 +201,7 @@ void Events::listener_monitorFrame(void* owner, void* data) {
|
||||
|
||||
// if we have no tracking or full tracking, invalidate the entire monitor
|
||||
if (DTMODE == DAMAGE_TRACKING_NONE || DTMODE == DAMAGE_TRACKING_MONITOR) {
|
||||
pixman_region32_union_rect(&damage, &damage, 0, 0, (int)PMONITOR->vecPixelSize.x, (int)PMONITOR->vecPixelSize.y);
|
||||
pixman_region32_union_rect(&damage, &damage, 0, 0, (int)PMONITOR->vecTransformedSize.x, (int)PMONITOR->vecTransformedSize.y);
|
||||
|
||||
pixman_region32_copy(&g_pHyprOpenGL->m_rOriginalDamageRegion, &damage);
|
||||
} else {
|
||||
@@ -213,6 +232,17 @@ void Events::listener_monitorFrame(void* owner, void* data) {
|
||||
|
||||
g_pHyprRenderer->renderAllClientsForMonitor(PMONITOR->ID, &now);
|
||||
|
||||
// if correct monitor draw hyprerror
|
||||
if (PMONITOR->ID == 0)
|
||||
g_pHyprError->draw();
|
||||
|
||||
// for drawing the debug overlay
|
||||
if (PMONITOR->ID == 0 && g_pConfigManager->getInt("debug:overlay") == 1) {
|
||||
startRenderOverlay = std::chrono::high_resolution_clock::now();
|
||||
g_pDebugOverlay->draw();
|
||||
endRenderOverlay = std::chrono::high_resolution_clock::now();
|
||||
}
|
||||
|
||||
wlr_renderer_begin(g_pCompositor->m_sWLRRenderer, PMONITOR->vecPixelSize.x, PMONITOR->vecPixelSize.y);
|
||||
|
||||
wlr_output_render_software_cursors(PMONITOR->output, NULL);
|
||||
@@ -226,10 +256,10 @@ void Events::listener_monitorFrame(void* owner, void* data) {
|
||||
pixman_region32_init(&frameDamage);
|
||||
|
||||
const auto TRANSFORM = wlr_output_transform_invert(PMONITOR->output->transform);
|
||||
wlr_region_transform(&frameDamage, &PMONITOR->damage->current, TRANSFORM, (int)PMONITOR->vecPixelSize.x, (int)PMONITOR->vecPixelSize.y);
|
||||
wlr_region_transform(&frameDamage, &PMONITOR->damage->current, TRANSFORM, (int)PMONITOR->vecTransformedSize.x, (int)PMONITOR->vecTransformedSize.y);
|
||||
|
||||
if (DTMODE == DAMAGE_TRACKING_NONE || DTMODE == DAMAGE_TRACKING_MONITOR)
|
||||
pixman_region32_union_rect(&frameDamage, &frameDamage, 0, 0, (int)PMONITOR->vecPixelSize.x, (int)PMONITOR->vecPixelSize.y);
|
||||
pixman_region32_union_rect(&frameDamage, &frameDamage, 0, 0, (int)PMONITOR->vecTransformedSize.x, (int)PMONITOR->vecTransformedSize.y);
|
||||
|
||||
wlr_output_set_damage(PMONITOR->output, &frameDamage);
|
||||
pixman_region32_fini(&frameDamage);
|
||||
@@ -238,6 +268,17 @@ void Events::listener_monitorFrame(void* owner, void* data) {
|
||||
wlr_output_commit(PMONITOR->output);
|
||||
|
||||
wlr_output_schedule_frame(PMONITOR->output);
|
||||
|
||||
if (g_pConfigManager->getInt("debug:overlay") == 1) {
|
||||
const float µs = std::chrono::duration_cast<std::chrono::nanoseconds>(std::chrono::high_resolution_clock::now() - startRender).count() / 1000.f;
|
||||
g_pDebugOverlay->renderData(PMONITOR, µs);
|
||||
if (PMONITOR->ID == 0) {
|
||||
const float µsNoOverlay = µs - std::chrono::duration_cast<std::chrono::nanoseconds>(endRenderOverlay - startRenderOverlay).count() / 1000.f;
|
||||
g_pDebugOverlay->renderDataNoOverlay(PMONITOR, µsNoOverlay);
|
||||
} else {
|
||||
g_pDebugOverlay->renderDataNoOverlay(PMONITOR, µs);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Events::listener_monitorDestroy(void* owner, void* data) {
|
||||
|
@@ -23,8 +23,8 @@ void addPopupGlobalCoords(void* pPopup, int* x, int* y) {
|
||||
|
||||
auto curPopup = PPOPUP;
|
||||
while (true) {
|
||||
px += curPopup->popup->geometry.x;
|
||||
py += curPopup->popup->geometry.y;
|
||||
px += curPopup->popup->current.geometry.x;
|
||||
py += curPopup->popup->current.geometry.y;
|
||||
|
||||
if (curPopup->parentPopup) {
|
||||
curPopup = curPopup->parentPopup;
|
||||
|
@@ -35,6 +35,11 @@ void Events::listener_mapWindow(void* owner, void* data) {
|
||||
PWINDOW->m_szTitle = g_pXWaylandManager->getTitle(PWINDOW);
|
||||
PWINDOW->m_fAlpha = 255.f;
|
||||
|
||||
// Foreign Toplevel
|
||||
PWINDOW->m_phForeignToplevel = wlr_foreign_toplevel_handle_v1_create(g_pCompositor->m_sWLRToplevelMgr);
|
||||
// TODO: handle foreign events (requests)
|
||||
wlr_foreign_toplevel_handle_v1_set_app_id(PWINDOW->m_phForeignToplevel, g_pXWaylandManager->getAppIDClass(PWINDOW).c_str());
|
||||
|
||||
// checks if the window wants borders and sets the appriopriate flag
|
||||
g_pXWaylandManager->checkBorders(PWINDOW);
|
||||
|
||||
@@ -62,7 +67,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);
|
||||
g_pLayoutManager->getCurrentLayout()->fullscreenRequestForWindow(PFULLWINDOW, FULLSCREEN_FULL);
|
||||
g_pXWaylandManager->setWindowFullscreen(PFULLWINDOW, PFULLWINDOW->m_bIsFullscreen);
|
||||
}
|
||||
|
||||
@@ -101,6 +106,12 @@ 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.find("rounding") == 0) {
|
||||
try {
|
||||
PWINDOW->m_sAdditionalConfigData.rounding = std::stoi(r.szRule.substr(r.szRule.find_first_of(' ') + 1));
|
||||
} catch (std::exception& e) {
|
||||
Debug::log(ERR, "Rounding rule \"%s\" failed with: %s", r.szRule.c_str(), e.what());
|
||||
}
|
||||
} else if (r.szRule.find("opacity") == 0) {
|
||||
try {
|
||||
PWINDOW->m_sSpecialRenderData.alpha = std::stof(r.szRule.substr(r.szRule.find_first_of(' ') + 1));
|
||||
@@ -184,7 +195,7 @@ void Events::listener_mapWindow(void* owner, void* data) {
|
||||
}
|
||||
|
||||
// do the animation thing
|
||||
g_pAnimationManager->onWindowPostCreate(PWINDOW);
|
||||
g_pAnimationManager->onWindowPostCreateClose(PWINDOW, false);
|
||||
|
||||
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);
|
||||
}
|
||||
@@ -244,6 +255,18 @@ void Events::listener_unmapWindow(void* owner, void* data) {
|
||||
g_pCompositor->m_lWindowsFadingOut.push_back(PWINDOW);
|
||||
|
||||
g_pHyprRenderer->damageMonitor(g_pCompositor->getMonitorFromID(PWINDOW->m_iMonitorID));
|
||||
|
||||
// do the animation thing
|
||||
PWINDOW->m_vOriginalClosedPos = PWINDOW->m_vRealPosition.vec();
|
||||
PWINDOW->m_vOriginalClosedSize = PWINDOW->m_vRealSize.vec();
|
||||
|
||||
if (!PWINDOW->m_bX11DoesntWantBorders) // don't animate out if they weren't animated in.
|
||||
PWINDOW->m_vRealPosition = PWINDOW->m_vRealPosition.vec() + Vector2D(0.01f, 0.01f); // it has to be animated, otherwise onWindowPostCreateClose will ignore it
|
||||
g_pAnimationManager->onWindowPostCreateClose(PWINDOW, true);
|
||||
|
||||
// Destroy Foreign Toplevel
|
||||
wlr_foreign_toplevel_handle_v1_destroy(PWINDOW->m_phForeignToplevel);
|
||||
PWINDOW->m_phForeignToplevel = nullptr;
|
||||
}
|
||||
|
||||
void Events::listener_commitWindow(void* owner, void* data) {
|
||||
@@ -291,6 +314,9 @@ void Events::listener_setTitleWindow(void* owner, void* data) {
|
||||
if (PWINDOW == g_pCompositor->m_pLastWindow) // if it's the active, let's post an event to update others
|
||||
g_pEventManager->postEvent(SHyprIPCEvent("activewindow", g_pXWaylandManager->getAppIDClass(PWINDOW) + "," + PWINDOW->m_szTitle));
|
||||
|
||||
if (PWINDOW->m_phForeignToplevel)
|
||||
wlr_foreign_toplevel_handle_v1_set_title(PWINDOW->m_phForeignToplevel, PWINDOW->m_szTitle.c_str());
|
||||
|
||||
Debug::log(LOG, "Window %x set title to %s", PWINDOW, PWINDOW->m_szTitle.c_str());
|
||||
}
|
||||
|
||||
@@ -301,9 +327,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);
|
||||
g_pLayoutManager->getCurrentLayout()->fullscreenRequestForWindow(PWINDOW, FULLSCREEN_FULL);
|
||||
} else {
|
||||
g_pLayoutManager->getCurrentLayout()->fullscreenRequestForWindow(PWINDOW);
|
||||
g_pLayoutManager->getCurrentLayout()->fullscreenRequestForWindow(PWINDOW, FULLSCREEN_FULL);
|
||||
}
|
||||
|
||||
Debug::log(LOG, "Window %x fullscreen to %i", PWINDOW, PWINDOW->m_bIsFullscreen);
|
||||
|
@@ -7,9 +7,10 @@
|
||||
#include <array>
|
||||
|
||||
struct SMonitor {
|
||||
Vector2D vecPosition = Vector2D(0,0);
|
||||
Vector2D vecSize = Vector2D(0,0);
|
||||
Vector2D vecPixelSize = Vector2D(0,0);
|
||||
Vector2D vecPosition = Vector2D(0,0);
|
||||
Vector2D vecSize = Vector2D(0,0);
|
||||
Vector2D vecPixelSize = Vector2D(0,0);
|
||||
Vector2D vecTransformedSize = Vector2D(0,0);
|
||||
|
||||
bool primary = false;
|
||||
|
||||
@@ -27,6 +28,7 @@ struct SMonitor {
|
||||
float refreshRate = 60;
|
||||
wlr_output_damage* damage = nullptr;
|
||||
bool needsFrameSkip = false;
|
||||
wl_output_transform transform = WL_OUTPUT_TRANSFORM_NORMAL;
|
||||
|
||||
// Double-linked list because we need to have constant mem addresses for signals
|
||||
// We have to store pointers and use raw new/delete because they might be moved between them
|
||||
|
@@ -57,6 +57,9 @@ struct SRenderData {
|
||||
|
||||
// for decorations (border)
|
||||
bool decorate = false;
|
||||
|
||||
// for custom round values
|
||||
int rounding = -1; // -1 means not set
|
||||
};
|
||||
|
||||
struct SKeyboard {
|
||||
|
@@ -3,6 +3,11 @@
|
||||
#include "../defines.hpp"
|
||||
#include "AnimatedVariable.hpp"
|
||||
|
||||
enum eFullscreenMode : uint8_t {
|
||||
FULLSCREEN_FULL = 0,
|
||||
FULLSCREEN_MAXIMIZED
|
||||
};
|
||||
|
||||
class CWorkspace {
|
||||
public:
|
||||
CWorkspace(int monitorID);
|
||||
@@ -14,6 +19,7 @@ public:
|
||||
std::string m_szName = "";
|
||||
uint64_t m_iMonitorID = -1;
|
||||
bool m_bHasFullscreenWindow = false;
|
||||
eFullscreenMode m_efFullscreenMode = FULLSCREEN_FULL;
|
||||
|
||||
wlr_ext_workspace_handle_v1* m_pWlrHandle = nullptr;
|
||||
|
||||
|
@@ -73,6 +73,7 @@ extern "C" {
|
||||
#include <wlr/types/wlr_input_inhibitor.h>
|
||||
#include <wlr/types/wlr_keyboard_shortcuts_inhibit_v1.h>
|
||||
#include <wlr/types/wlr_virtual_pointer_v1.h>
|
||||
#include <wlr/types/wlr_foreign_toplevel_management_v1.h>
|
||||
#include <wlr/util/log.h>
|
||||
#include <wlr/xwayland.h>
|
||||
#include <wlr/util/region.h>
|
||||
|
@@ -275,6 +275,10 @@ void CHyprDwindleLayout::onWindowCreated(CWindow* pWindow) {
|
||||
|
||||
if (OPENINGON->pGroupParent) {
|
||||
// means we opened on a group
|
||||
|
||||
// add the group deco
|
||||
pWindow->m_dWindowDecorations.emplace_back(std::make_unique<CHyprGroupBarDecoration>(pWindow));
|
||||
|
||||
PNODE->pGroupParent = OPENINGON->pGroupParent;
|
||||
PNODE->pGroupParent->groupMembers.push_back(PNODE);
|
||||
PNODE->pGroupParent->groupMemberActive = PNODE->pGroupParent->groupMembers.size() - 1;
|
||||
@@ -616,7 +620,7 @@ void CHyprDwindleLayout::onWindowCreatedFloating(CWindow* pWindow) {
|
||||
g_pCompositor->moveWindowToTop(pWindow);
|
||||
}
|
||||
|
||||
void CHyprDwindleLayout::fullscreenRequestForWindow(CWindow* pWindow) {
|
||||
void CHyprDwindleLayout::fullscreenRequestForWindow(CWindow* pWindow, eFullscreenMode fullscreenMode) {
|
||||
if (!g_pCompositor->windowValidMapped(pWindow))
|
||||
return;
|
||||
|
||||
@@ -646,6 +650,8 @@ void CHyprDwindleLayout::fullscreenRequestForWindow(CWindow* pWindow) {
|
||||
} else {
|
||||
// if it now got fullscreen, make it fullscreen
|
||||
|
||||
PWORKSPACE->m_efFullscreenMode = fullscreenMode;
|
||||
|
||||
// save position and size if floating
|
||||
if (pWindow->m_bIsFloating) {
|
||||
pWindow->m_vPosition = pWindow->m_vRealPosition.vec();
|
||||
@@ -653,8 +659,22 @@ void CHyprDwindleLayout::fullscreenRequestForWindow(CWindow* pWindow) {
|
||||
}
|
||||
|
||||
// apply new pos and size being monitors' box
|
||||
pWindow->m_vRealPosition = PMONITOR->vecPosition;
|
||||
pWindow->m_vRealSize = PMONITOR->vecSize;
|
||||
if (fullscreenMode == FULLSCREEN_FULL) {
|
||||
pWindow->m_vRealPosition = PMONITOR->vecPosition;
|
||||
pWindow->m_vRealSize = PMONITOR->vecSize;
|
||||
} else {
|
||||
// This is a massive hack.
|
||||
// We make a fake "only" node and apply
|
||||
// To keep consistent with the settings without C+P code
|
||||
|
||||
SDwindleNodeData fakeNode;
|
||||
fakeNode.pWindow = pWindow;
|
||||
fakeNode.position = PMONITOR->vecPosition + PMONITOR->vecReservedTopLeft;
|
||||
fakeNode.size = PMONITOR->vecSize - PMONITOR->vecReservedTopLeft - PMONITOR->vecReservedBottomRight;
|
||||
fakeNode.workspaceID = pWindow->m_iWorkspaceID;
|
||||
|
||||
applyNodeDataToWindow(&fakeNode);
|
||||
}
|
||||
}
|
||||
|
||||
g_pXWaylandManager->setWindowSize(pWindow, pWindow->m_vRealSize.goalv());
|
||||
@@ -693,6 +713,10 @@ void CHyprDwindleLayout::toggleWindowGroup(CWindow* pWindow) {
|
||||
for (auto& node : PGROUPPARENT->groupMembers) {
|
||||
node->pGroupParent = nullptr;
|
||||
node->pWindow->m_cRealBorderColor.setValueAndWarp(INACTIVEBORDERCOL); // no anim here because they pop in
|
||||
|
||||
for (auto& wd : node->pWindow->m_dWindowDecorations) {
|
||||
wd->updateWindow(node->pWindow);
|
||||
}
|
||||
}
|
||||
|
||||
PGROUPPARENT->groupMembers.clear();
|
||||
@@ -725,6 +749,8 @@ void CHyprDwindleLayout::toggleWindowGroup(CWindow* pWindow) {
|
||||
c->pGroupParent = PPARENT;
|
||||
c->pWindow->m_cRealBorderColor = GROUPINACTIVEBORDERCOL;
|
||||
|
||||
c->pWindow->m_dWindowDecorations.push_back(std::make_unique<CHyprGroupBarDecoration>(c->pWindow));
|
||||
|
||||
if (c->pWindow == g_pCompositor->m_pLastWindow)
|
||||
c->pWindow->m_cRealBorderColor = CColor(g_pConfigManager->getInt("dwindle:col.group_border_active"));
|
||||
}
|
||||
@@ -735,7 +761,32 @@ void CHyprDwindleLayout::toggleWindowGroup(CWindow* pWindow) {
|
||||
}
|
||||
}
|
||||
|
||||
void CHyprDwindleLayout::switchGroupWindow(CWindow* pWindow) {
|
||||
std::deque<CWindow*> CHyprDwindleLayout::getGroupMembers(CWindow* pWindow) {
|
||||
|
||||
std::deque<CWindow*> result;
|
||||
|
||||
if (!g_pCompositor->windowExists(pWindow))
|
||||
return result; // reject with empty
|
||||
|
||||
// get the node
|
||||
const auto PNODE = getNodeFromWindow(pWindow);
|
||||
|
||||
if (!PNODE)
|
||||
return result; // reject with empty
|
||||
|
||||
const auto PGROUPPARENT = PNODE->pGroupParent;
|
||||
|
||||
if (!PGROUPPARENT)
|
||||
return result; // reject with empty
|
||||
|
||||
for (auto& node : PGROUPPARENT->groupMembers) {
|
||||
result.push_back(node->pWindow);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
void CHyprDwindleLayout::switchGroupWindow(CWindow* pWindow, bool forward) {
|
||||
if (!g_pCompositor->windowValidMapped(pWindow))
|
||||
return; // reject
|
||||
|
||||
@@ -747,13 +798,25 @@ void CHyprDwindleLayout::switchGroupWindow(CWindow* pWindow) {
|
||||
if (!PNODE->pGroupParent)
|
||||
return; // reject
|
||||
|
||||
PNODE->pGroupParent->groupMemberActive++;
|
||||
if (forward)
|
||||
PNODE->pGroupParent->groupMemberActive++;
|
||||
else
|
||||
PNODE->pGroupParent->groupMemberActive--;
|
||||
|
||||
if (PNODE->pGroupParent->groupMemberActive < 0)
|
||||
PNODE->pGroupParent->groupMemberActive = PNODE->pGroupParent->groupMembers.size() - 1;
|
||||
|
||||
if ((long unsigned int)PNODE->pGroupParent->groupMemberActive >= PNODE->pGroupParent->groupMembers.size())
|
||||
PNODE->pGroupParent->groupMemberActive = 0;
|
||||
|
||||
PNODE->pGroupParent->recalcSizePosRecursive();
|
||||
|
||||
for (auto& gm : PNODE->pGroupParent->groupMembers) {
|
||||
for (auto& deco : gm->pWindow->m_dWindowDecorations) {
|
||||
deco->updateWindow(gm->pWindow);
|
||||
}
|
||||
}
|
||||
|
||||
// focus
|
||||
g_pCompositor->focusWindow(PNODE->pGroupParent->groupMembers[PNODE->pGroupParent->groupMemberActive]->pWindow);
|
||||
}
|
||||
@@ -844,13 +907,21 @@ void CHyprDwindleLayout::alterSplitRatioBy(CWindow* pWindow, float ratio) {
|
||||
PNODE->pParent->recalcSizePosRecursive();
|
||||
}
|
||||
|
||||
void CHyprDwindleLayout::layoutMessage(SLayoutMessageHeader header, std::string message) {
|
||||
std::any CHyprDwindleLayout::layoutMessage(SLayoutMessageHeader header, std::string message) {
|
||||
if (message == "togglegroup")
|
||||
toggleWindowGroup(header.pWindow);
|
||||
else if (message == "changegroupactive")
|
||||
switchGroupWindow(header.pWindow);
|
||||
else if (message == "changegroupactivef")
|
||||
switchGroupWindow(header.pWindow, true);
|
||||
else if (message == "changegroupactiveb")
|
||||
switchGroupWindow(header.pWindow, false);
|
||||
else if (message == "togglesplit")
|
||||
toggleSplit(header.pWindow);
|
||||
else if (message == "groupinfo") {
|
||||
auto res = getGroupMembers(g_pCompositor->m_pLastWindow);
|
||||
return res;
|
||||
}
|
||||
|
||||
return "";
|
||||
}
|
||||
|
||||
void CHyprDwindleLayout::toggleSplit(CWindow* pWindow) {
|
||||
@@ -862,4 +933,8 @@ void CHyprDwindleLayout::toggleSplit(CWindow* pWindow) {
|
||||
PNODE->pParent->splitTop = !PNODE->pParent->splitTop;
|
||||
|
||||
PNODE->pParent->recalcSizePosRecursive();
|
||||
}
|
||||
|
||||
std::string CHyprDwindleLayout::getLayoutName() {
|
||||
return "dwindle";
|
||||
}
|
@@ -3,8 +3,10 @@
|
||||
#include "IHyprLayout.hpp"
|
||||
#include <list>
|
||||
#include <deque>
|
||||
#include "../render/decorations/CHyprGroupBarDecoration.hpp"
|
||||
|
||||
class CHyprDwindleLayout;
|
||||
enum eFullscreenMode : uint8_t;
|
||||
|
||||
struct SDwindleNodeData {
|
||||
SDwindleNodeData* pParent = nullptr;
|
||||
@@ -49,11 +51,12 @@ public:
|
||||
virtual void onEndDragWindow();
|
||||
virtual void onMouseMove(const Vector2D&);
|
||||
virtual void onWindowCreatedFloating(CWindow*);
|
||||
virtual void fullscreenRequestForWindow(CWindow*);
|
||||
virtual void layoutMessage(SLayoutMessageHeader, std::string);
|
||||
virtual void fullscreenRequestForWindow(CWindow*, eFullscreenMode);
|
||||
virtual std::any layoutMessage(SLayoutMessageHeader, std::string);
|
||||
virtual SWindowRenderLayoutHints requestRenderHints(CWindow*);
|
||||
virtual void switchWindows(CWindow*, CWindow*);
|
||||
virtual void alterSplitRatioBy(CWindow*, float);
|
||||
virtual std::string getLayoutName();
|
||||
|
||||
private:
|
||||
|
||||
@@ -71,8 +74,9 @@ public:
|
||||
SDwindleNodeData* getMasterNodeOnWorkspace(const int&);
|
||||
|
||||
void toggleWindowGroup(CWindow*);
|
||||
void switchGroupWindow(CWindow*);
|
||||
void switchGroupWindow(CWindow*, bool forward);
|
||||
void toggleSplit(CWindow*);
|
||||
std::deque<CWindow*> getGroupMembers(CWindow*);
|
||||
|
||||
friend struct SDwindleNodeData;
|
||||
};
|
@@ -12,6 +12,8 @@ struct SLayoutMessageHeader {
|
||||
CWindow* pWindow = nullptr;
|
||||
};
|
||||
|
||||
enum eFullscreenMode : uint8_t;
|
||||
|
||||
interface IHyprLayout {
|
||||
public:
|
||||
|
||||
@@ -66,17 +68,18 @@ public:
|
||||
virtual void onWindowCreatedFloating(CWindow*) = 0;
|
||||
|
||||
/*
|
||||
Called when a window requests to toggle its' fullscreen state.
|
||||
Called when a window / the user requests to toggle the fullscreen state of a window
|
||||
The layout sets all the fullscreen flags.
|
||||
It can either accept or ignore.
|
||||
*/
|
||||
virtual void fullscreenRequestForWindow(CWindow*) = 0;
|
||||
virtual void fullscreenRequestForWindow(CWindow*, eFullscreenMode) = 0;
|
||||
|
||||
/*
|
||||
Called when a dispatcher requests a custom message
|
||||
The layout is free to ignore.
|
||||
The layout is free to ignore.
|
||||
std::any is the reply. Can be empty.
|
||||
*/
|
||||
virtual void layoutMessage(SLayoutMessageHeader, std::string) = 0;
|
||||
virtual std::any layoutMessage(SLayoutMessageHeader, std::string) = 0;
|
||||
|
||||
/*
|
||||
Required to be handled, but may return just SWindowRenderLayoutHints()
|
||||
@@ -96,4 +99,9 @@ public:
|
||||
on a window
|
||||
*/
|
||||
virtual void alterSplitRatioBy(CWindow*, float) = 0;
|
||||
|
||||
/*
|
||||
Called when something wants the current layout's name
|
||||
*/
|
||||
virtual std::string getLayoutName() = 0;
|
||||
};
|
@@ -140,8 +140,12 @@ void CAnimationManager::tick() {
|
||||
case AVARDAMAGE_ENTIRE: {
|
||||
g_pHyprRenderer->damageBox(&WLRBOXPREV);
|
||||
|
||||
if (PWINDOW)
|
||||
if (PWINDOW) {
|
||||
g_pHyprRenderer->damageWindow(PWINDOW);
|
||||
for (auto& wd : PWINDOW->m_dWindowDecorations) {
|
||||
wd->updateWindow(PWINDOW);
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
case AVARDAMAGE_BORDER: {
|
||||
@@ -208,15 +212,20 @@ bool CAnimationManager::deltazero(const CColor& a, const CColor& b) {
|
||||
//
|
||||
//
|
||||
|
||||
void CAnimationManager::animationPopin(CWindow* pWindow) {
|
||||
void CAnimationManager::animationPopin(CWindow* pWindow, bool close) {
|
||||
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));
|
||||
if (!close) {
|
||||
pWindow->m_vRealPosition.setValue(GOALPOS + GOALSIZE / 2.f);
|
||||
pWindow->m_vRealSize.setValue(Vector2D(5, 5));
|
||||
} else {
|
||||
pWindow->m_vRealPosition = GOALPOS + GOALSIZE / 2.f;
|
||||
pWindow->m_vRealSize = Vector2D(5, 5);
|
||||
}
|
||||
}
|
||||
|
||||
void CAnimationManager::animationSlide(CWindow* pWindow, std::string force) {
|
||||
void CAnimationManager::animationSlide(CWindow* pWindow, std::string force, bool close) {
|
||||
pWindow->m_vRealSize.warp(); // size we preserve in slide
|
||||
|
||||
const auto GOALPOS = pWindow->m_vRealPosition.goalv();
|
||||
@@ -224,11 +233,18 @@ void CAnimationManager::animationSlide(CWindow* pWindow, std::string force) {
|
||||
|
||||
const auto PMONITOR = g_pCompositor->getMonitorFromID(pWindow->m_iMonitorID);
|
||||
|
||||
Vector2D posOffset;
|
||||
|
||||
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));
|
||||
if (force == "bottom") posOffset = Vector2D(GOALPOS.x, PMONITOR->vecPosition.y + PMONITOR->vecSize.y);
|
||||
else if (force == "left") posOffset = GOALPOS - Vector2D(GOALSIZE.x, 0);
|
||||
else if (force == "right") posOffset = GOALPOS + Vector2D(GOALSIZE.x, 0);
|
||||
else posOffset = Vector2D(GOALPOS.x, PMONITOR->vecPosition.y - GOALSIZE.y);
|
||||
|
||||
if (!close)
|
||||
pWindow->m_vRealPosition.setValue(posOffset);
|
||||
else
|
||||
pWindow->m_vRealPosition = posOffset;
|
||||
|
||||
return;
|
||||
}
|
||||
@@ -243,25 +259,30 @@ void CAnimationManager::animationSlide(CWindow* pWindow, std::string force) {
|
||||
|
||||
if (DISPLAYBOTTOM && DISPLAYTOP) {
|
||||
if (DISPLAYLEFT && DISPLAYRIGHT) {
|
||||
pWindow->m_vRealPosition.setValue(GOALPOS + Vector2D(0, GOALSIZE.y));
|
||||
posOffset = GOALPOS + Vector2D(0, GOALSIZE.y);
|
||||
} else if (DISPLAYLEFT) {
|
||||
pWindow->m_vRealPosition.setValue(GOALPOS - Vector2D(GOALSIZE.x, 0));
|
||||
posOffset = GOALPOS - Vector2D(GOALSIZE.x, 0);
|
||||
} else {
|
||||
pWindow->m_vRealPosition.setValue(GOALPOS + Vector2D(GOALSIZE.x, 0));
|
||||
posOffset = GOALPOS + Vector2D(GOALSIZE.x, 0);
|
||||
}
|
||||
} else if (DISPLAYTOP) {
|
||||
pWindow->m_vRealPosition.setValue(GOALPOS - Vector2D(0, GOALSIZE.y));
|
||||
posOffset = GOALPOS - Vector2D(0, GOALSIZE.y);
|
||||
} else if (DISPLAYBOTTOM) {
|
||||
pWindow->m_vRealPosition.setValue(GOALPOS + Vector2D(0, GOALSIZE.y));
|
||||
posOffset = 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));
|
||||
posOffset = Vector2D(GOALPOS.x, PMONITOR->vecPosition.y + PMONITOR->vecSize.y);
|
||||
else
|
||||
pWindow->m_vRealPosition.setValue(Vector2D(GOALPOS.x, PMONITOR->vecPosition.y - GOALSIZE.y));
|
||||
posOffset = Vector2D(GOALPOS.x, PMONITOR->vecPosition.y - GOALSIZE.y);
|
||||
}
|
||||
|
||||
if (!close)
|
||||
pWindow->m_vRealPosition.setValue(posOffset);
|
||||
else
|
||||
pWindow->m_vRealPosition = posOffset;
|
||||
}
|
||||
|
||||
void CAnimationManager::onWindowPostCreate(CWindow* pWindow) {
|
||||
void CAnimationManager::onWindowPostCreateClose(CWindow* pWindow, bool close) {
|
||||
auto ANIMSTYLE = g_pConfigManager->getString("animations:windows_style");
|
||||
transform(ANIMSTYLE.begin(), ANIMSTYLE.end(), ANIMSTYLE.begin(), ::tolower);
|
||||
|
||||
@@ -274,20 +295,20 @@ void CAnimationManager::onWindowPostCreate(CWindow* pWindow) {
|
||||
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));
|
||||
animationSlide(pWindow, pWindow->m_sAdditionalConfigData.animationStyle.substr(pWindow->m_sAdditionalConfigData.animationStyle.find(' ') + 1), close);
|
||||
} else {
|
||||
animationSlide(pWindow);
|
||||
animationSlide(pWindow, "", close);
|
||||
}
|
||||
} else {
|
||||
// anim popin, fallback
|
||||
animationPopin(pWindow);
|
||||
animationPopin(pWindow, close);
|
||||
}
|
||||
} else {
|
||||
if (ANIMSTYLE == "slide") {
|
||||
animationSlide(pWindow);
|
||||
animationSlide(pWindow, "", close);
|
||||
} else {
|
||||
// anim popin, fallback
|
||||
animationPopin(pWindow);
|
||||
animationPopin(pWindow, close);
|
||||
}
|
||||
}
|
||||
}
|
@@ -16,7 +16,7 @@ public:
|
||||
void addBezierWithName(std::string, const Vector2D&, const Vector2D&);
|
||||
void removeAllBeziers();
|
||||
|
||||
void onWindowPostCreate(CWindow*);
|
||||
void onWindowPostCreateClose(CWindow*, bool close = false);
|
||||
|
||||
std::list<CAnimatedVariable*> m_lAnimatedVariables;
|
||||
|
||||
@@ -31,8 +31,8 @@ private:
|
||||
std::unordered_map<std::string, CBezierCurve> m_mBezierCurves;
|
||||
|
||||
// Anim stuff
|
||||
void animationPopin(CWindow*);
|
||||
void animationSlide(CWindow*, std::string force = "");
|
||||
void animationPopin(CWindow*, bool close = false);
|
||||
void animationSlide(CWindow*, std::string force = "", bool close = false);
|
||||
};
|
||||
|
||||
inline std::unique_ptr<CAnimationManager> g_pAnimationManager;
|
@@ -221,7 +221,6 @@ void CInputManager::onMouseButton(wlr_pointer_button_event* e) {
|
||||
// notify app if we didnt handle it
|
||||
if (g_pCompositor->doesSeatAcceptInput(g_pCompositor->m_pLastFocus)) {
|
||||
wlr_seat_pointer_notify_button(g_pCompositor->m_sSeat.seat, e->time_msec, e->button, e->state);
|
||||
Debug::log(LOG, "Seat notified of button %i (state %i) on surface %x", e->button, e->state, g_pCompositor->m_pLastFocus);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -360,8 +359,6 @@ void CInputManager::onKeyboardKey(wlr_keyboard_key_event* e, SKeyboard* pKeyboar
|
||||
|
||||
bool found = false;
|
||||
if (e->state == WL_KEYBOARD_KEY_STATE_PRESSED) {
|
||||
Debug::log(LOG, "Pressed key %i, with the MODMASK being %i", e->keycode, MODS);
|
||||
|
||||
for (int i = 0; i < syms; ++i)
|
||||
found = g_pKeybindManager->handleKeybinds(MODS, keysyms[i]) || found;
|
||||
} else if (e->state == WL_KEYBOARD_KEY_STATE_RELEASED) {
|
||||
|
@@ -20,6 +20,7 @@ CKeybindManager::CKeybindManager() {
|
||||
m_mDispatchers["focusmonitor"] = focusMonitor;
|
||||
m_mDispatchers["movecursortocorner"] = moveCursorToCorner;
|
||||
m_mDispatchers["workspaceopt"] = workspaceOpt;
|
||||
m_mDispatchers["exit"] = exitHyprland;
|
||||
}
|
||||
|
||||
void CKeybindManager::addKeybind(SKeybind kb) {
|
||||
@@ -88,6 +89,7 @@ bool CKeybindManager::handleKeybinds(const uint32_t& modmask, const xkb_keysym_t
|
||||
Debug::log(ERR, "Inavlid handler in a keybind! (handler %s does not exist)", k.handler.c_str());
|
||||
} else {
|
||||
// call the dispatcher
|
||||
Debug::log(LOG, "Keybind triggered, calling dispatcher (%d, %d)", modmask, KBKEYUPPER);
|
||||
DISPATCHER->second(k.arg);
|
||||
}
|
||||
|
||||
@@ -294,9 +296,9 @@ void CKeybindManager::fullscreenActive(std::string args) {
|
||||
if (!g_pCompositor->windowValidMapped(PWINDOW))
|
||||
return;
|
||||
|
||||
g_pLayoutManager->getCurrentLayout()->fullscreenRequestForWindow(PWINDOW);
|
||||
g_pLayoutManager->getCurrentLayout()->fullscreenRequestForWindow(PWINDOW, args == "1" ? eFullscreenMode::FULLSCREEN_MAXIMIZED : eFullscreenMode::FULLSCREEN_FULL);
|
||||
|
||||
g_pXWaylandManager->setWindowFullscreen(PWINDOW, PWINDOW->m_bIsFullscreen);
|
||||
g_pXWaylandManager->setWindowFullscreen(PWINDOW, PWINDOW->m_bIsFullscreen && args == "0");
|
||||
|
||||
// make all windows on the same workspace under the fullscreen window
|
||||
for (auto& w : g_pCompositor->m_lWindows) {
|
||||
@@ -503,7 +505,10 @@ void CKeybindManager::toggleGroup(std::string args) {
|
||||
void CKeybindManager::changeGroupActive(std::string args) {
|
||||
SLayoutMessageHeader header;
|
||||
header.pWindow = g_pCompositor->m_pLastWindow;
|
||||
g_pLayoutManager->getCurrentLayout()->layoutMessage(header, "changegroupactive");
|
||||
if (args == "b")
|
||||
g_pLayoutManager->getCurrentLayout()->layoutMessage(header, "changegroupactiveb");
|
||||
else
|
||||
g_pLayoutManager->getCurrentLayout()->layoutMessage(header, "changegroupactivef");
|
||||
}
|
||||
|
||||
void CKeybindManager::toggleSplit(std::string args) {
|
||||
@@ -558,7 +563,12 @@ void CKeybindManager::focusMonitor(std::string arg) {
|
||||
if (isDirection(arg)) {
|
||||
const auto PMONITOR = g_pCompositor->getMonitorInDirection(arg[0]);
|
||||
if (PMONITOR) {
|
||||
changeworkspace(std::to_string(PMONITOR->activeWorkspace));
|
||||
if (PMONITOR->activeWorkspace < 0) {
|
||||
const auto PWORKSPACE = g_pCompositor->getWorkspaceByID(PMONITOR->activeWorkspace);
|
||||
changeworkspace("name:" + PWORKSPACE->m_szName);
|
||||
}
|
||||
else
|
||||
changeworkspace(std::to_string(PMONITOR->activeWorkspace));
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
@@ -666,4 +676,9 @@ void CKeybindManager::workspaceOpt(std::string args) {
|
||||
|
||||
// recalc mon
|
||||
g_pLayoutManager->getCurrentLayout()->recalculateMonitor(g_pCompositor->m_pLastMonitor->ID);
|
||||
}
|
||||
|
||||
void CKeybindManager::exitHyprland(std::string argz) {
|
||||
g_pCompositor->cleanupExit();
|
||||
exit(0);
|
||||
}
|
@@ -50,6 +50,7 @@ private:
|
||||
static void toggleSplit(std::string);
|
||||
static void moveCursorToCorner(std::string);
|
||||
static void workspaceOpt(std::string);
|
||||
static void exitHyprland(std::string);
|
||||
};
|
||||
|
||||
inline std::unique_ptr<CKeybindManager> g_pKeybindManager;
|
@@ -121,8 +121,13 @@ void CHyprXWaylandManager::sendCloseWindow(CWindow* pWindow) {
|
||||
void CHyprXWaylandManager::setWindowSize(CWindow* pWindow, const Vector2D& size) {
|
||||
if (pWindow->m_bIsX11)
|
||||
wlr_xwayland_surface_configure(pWindow->m_uSurface.xwayland, pWindow->m_vRealPosition.vec().x, pWindow->m_vRealPosition.vec().y, size.x, size.y);
|
||||
else // vvvvv I don't know if this is fucking correct, but the fucking idea of putting shadows into a window's surface is borderline criminal.
|
||||
wlr_xdg_toplevel_set_size(pWindow->m_uSurface.xdg->toplevel, size.x - pWindow->m_uSurface.xdg->current.geometry.x * 2, size.y - pWindow->m_uSurface.xdg->current.geometry.y * 2);
|
||||
else {
|
||||
// I don't know if this is fucking correct, but the fucking idea of putting shadows into a window's surface is borderline criminal.
|
||||
const auto XDELTA = pWindow->m_uSurface.xdg->surface->current.width - pWindow->m_uSurface.xdg->current.geometry.width;
|
||||
const auto YDELTA = pWindow->m_uSurface.xdg->surface->current.height - pWindow->m_uSurface.xdg->current.geometry.height;
|
||||
|
||||
wlr_xdg_toplevel_set_size(pWindow->m_uSurface.xdg->toplevel, size.x - XDELTA, size.y - YDELTA);
|
||||
}
|
||||
}
|
||||
|
||||
void CHyprXWaylandManager::setWindowStyleTiled(CWindow* pWindow, uint32_t edgez) {
|
||||
@@ -217,5 +222,8 @@ void CHyprXWaylandManager::setWindowFullscreen(CWindow* pWindow, bool fullscreen
|
||||
wlr_xdg_toplevel_set_fullscreen(pWindow->m_uSurface.xdg->toplevel, fullscreen);
|
||||
}
|
||||
|
||||
if (pWindow->m_phForeignToplevel)
|
||||
wlr_foreign_toplevel_handle_v1_set_fullscreen(pWindow->m_phForeignToplevel, fullscreen);
|
||||
|
||||
g_pEventManager->postEvent(SHyprIPCEvent("fullscreen", std::to_string((int)fullscreen)));
|
||||
}
|
@@ -166,13 +166,17 @@ void CHyprOpenGLImpl::end() {
|
||||
// end the render, copy the data to the WLR framebuffer
|
||||
if (!m_bFakeFrame) {
|
||||
glBindFramebuffer(GL_FRAMEBUFFER, m_iWLROutputFb);
|
||||
wlr_box monbox = {0, 0, m_RenderData.pMonitor->vecPixelSize.x, m_RenderData.pMonitor->vecPixelSize.y};
|
||||
wlr_box monbox = {0, 0, m_RenderData.pMonitor->vecTransformedSize.x, m_RenderData.pMonitor->vecTransformedSize.y};
|
||||
|
||||
pixman_region32_copy(m_RenderData.pDamage, &m_rOriginalDamageRegion);
|
||||
|
||||
clear(CColor(11, 11, 11, 255));
|
||||
|
||||
m_bEndFrame = true;
|
||||
|
||||
renderTexture(m_mMonitorRenderResources[m_RenderData.pMonitor].primaryFB.m_cTex, &monbox, 255.f, 0);
|
||||
|
||||
m_bEndFrame = false;
|
||||
}
|
||||
|
||||
// reset our data
|
||||
@@ -205,7 +209,15 @@ void CHyprOpenGLImpl::scissor(const wlr_box* pBox) {
|
||||
return;
|
||||
}
|
||||
|
||||
glScissor(pBox->x, pBox->y, pBox->width, pBox->height);
|
||||
wlr_box newBox = *pBox;
|
||||
|
||||
int w, h;
|
||||
wlr_output_transformed_resolution(m_RenderData.pMonitor->output, &w, &h);
|
||||
|
||||
const auto TR = wlr_output_transform_invert(m_RenderData.pMonitor->transform);
|
||||
wlr_box_transform(&newBox, &newBox, TR, w, h);
|
||||
|
||||
glScissor(newBox.x, newBox.y, newBox.width, newBox.height);
|
||||
glEnable(GL_SCISSOR_TEST);
|
||||
}
|
||||
|
||||
@@ -217,8 +229,9 @@ void CHyprOpenGLImpl::scissor(const pixman_box32* pBox) {
|
||||
return;
|
||||
}
|
||||
|
||||
glScissor(pBox->x1, pBox->y1, pBox->x2 - pBox->x1, pBox->y2 - pBox->y1);
|
||||
glEnable(GL_SCISSOR_TEST);
|
||||
wlr_box newBox = {pBox->x1, pBox->y1, pBox->x2 - pBox->x1, pBox->y2 - pBox->y1};
|
||||
|
||||
scissor(&newBox);
|
||||
}
|
||||
|
||||
void CHyprOpenGLImpl::scissor(const int x, const int y, const int w, const int h) {
|
||||
@@ -231,7 +244,7 @@ void CHyprOpenGLImpl::renderRect(wlr_box* box, const CColor& col, int round) {
|
||||
RASSERT(m_RenderData.pMonitor, "Tried to render rect without begin()!");
|
||||
|
||||
float matrix[9];
|
||||
wlr_matrix_project_box(matrix, box, WL_OUTPUT_TRANSFORM_NORMAL, 0, m_RenderData.pMonitor->output->transform_matrix); // TODO: write own, don't use WLR here
|
||||
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);
|
||||
@@ -296,7 +309,7 @@ void CHyprOpenGLImpl::renderTextureInternalWithDamage(const CTexture& tex, wlr_b
|
||||
RASSERT((tex.m_iTexID > 0), "Attempted to draw NULL texture!");
|
||||
|
||||
// get transform
|
||||
const auto TRANSFORM = wlr_output_transform_invert(WL_OUTPUT_TRANSFORM_NORMAL);
|
||||
const auto TRANSFORM = wlr_output_transform_invert(!m_bEndFrame ? WL_OUTPUT_TRANSFORM_NORMAL : m_RenderData.pMonitor->transform);
|
||||
float matrix[9];
|
||||
wlr_matrix_project_box(matrix, pBox, TRANSFORM, 0, m_RenderData.pMonitor->output->transform_matrix);
|
||||
|
||||
@@ -534,7 +547,7 @@ void CHyprOpenGLImpl::renderTextureWithBlur(const CTexture& tex, wlr_box* pBox,
|
||||
pixman_region32_t inverseOpaque;
|
||||
pixman_region32_init(&inverseOpaque);
|
||||
if (a == 255.f) {
|
||||
pixman_box32_t monbox = {0, 0, m_RenderData.pMonitor->vecPixelSize.x, m_RenderData.pMonitor->vecPixelSize.y};
|
||||
pixman_box32_t monbox = {0, 0, m_RenderData.pMonitor->vecTransformedSize.x, m_RenderData.pMonitor->vecTransformedSize.y};
|
||||
pixman_region32_copy(&inverseOpaque, &pSurface->current.opaque);
|
||||
pixman_region32_translate(&inverseOpaque, pBox->x, pBox->y);
|
||||
pixman_region32_inverse(&inverseOpaque, &inverseOpaque, &monbox);
|
||||
@@ -572,11 +585,11 @@ void CHyprOpenGLImpl::renderTextureWithBlur(const CTexture& tex, wlr_box* pBox,
|
||||
glStencilOp(GL_KEEP, GL_KEEP, GL_REPLACE);
|
||||
|
||||
// stencil done. Render everything.
|
||||
wlr_box MONITORBOX = {0, 0, m_RenderData.pMonitor->vecPixelSize.x, m_RenderData.pMonitor->vecPixelSize.y};
|
||||
wlr_box MONITORBOX = {0, 0, m_RenderData.pMonitor->vecTransformedSize.x, m_RenderData.pMonitor->vecTransformedSize.y};
|
||||
if (pixman_region32_not_empty(&damage)) {
|
||||
// render our great blurred FB
|
||||
renderTextureInternalWithDamage(POUTFB->m_cTex, &MONITORBOX, a, &damage);
|
||||
|
||||
renderTextureInternalWithDamage(POUTFB->m_cTex, &MONITORBOX, g_pConfigManager->getInt("decoration:blur_ignore_opacity") ? 255.f : a, &damage);
|
||||
|
||||
// render the window, but clear stencil
|
||||
glClearStencil(0);
|
||||
glClear(GL_STENCIL_BUFFER_BIT);
|
||||
@@ -756,7 +769,14 @@ void CHyprOpenGLImpl::renderSnapshot(CWindow** pWindow) {
|
||||
|
||||
const auto PMONITOR = g_pCompositor->getMonitorFromID(PWINDOW->m_iMonitorID);
|
||||
|
||||
wlr_box windowBox = {0, 0, PMONITOR->vecPixelSize.x, PMONITOR->vecPixelSize.y};
|
||||
wlr_box windowBox;
|
||||
// some mafs to figure out the correct box
|
||||
Vector2D scaleXY = Vector2D((PWINDOW->m_vRealSize.vec().x / PWINDOW->m_vOriginalClosedSize.x), (PWINDOW->m_vRealSize.vec().y / PWINDOW->m_vOriginalClosedSize.y));
|
||||
|
||||
windowBox.width = PMONITOR->vecPixelSize.x * scaleXY.x;
|
||||
windowBox.height = PMONITOR->vecPixelSize.y * scaleXY.y;
|
||||
windowBox.x = (PWINDOW->m_vRealPosition.vec().x - PMONITOR->vecPosition.x) - ((PWINDOW->m_vOriginalClosedPos.x - PMONITOR->vecPosition.x) * scaleXY.x);
|
||||
windowBox.y = (PWINDOW->m_vRealPosition.vec().y - PMONITOR->vecPosition.y) - ((PWINDOW->m_vOriginalClosedPos.y - PMONITOR->vecPosition.y) * scaleXY.y);
|
||||
|
||||
pixman_region32_t fakeDamage;
|
||||
pixman_region32_init_rect(&fakeDamage, 0, 0, PMONITOR->vecPixelSize.x, PMONITOR->vecPixelSize.y);
|
||||
@@ -810,10 +830,10 @@ void CHyprOpenGLImpl::createBGTextureForMonitor(SMonitor* pMonitor) {
|
||||
// get the adequate tex
|
||||
std::string texPath = "/usr/share/hyprland/wall_";
|
||||
Vector2D textureSize;
|
||||
if (pMonitor->vecSize.x > 7000) {
|
||||
if (pMonitor->vecTransformedSize.x > 7000) {
|
||||
textureSize = Vector2D(7680, 4320);
|
||||
texPath += "8K.png";
|
||||
} else if (pMonitor->vecSize.x > 3000) {
|
||||
} else if (pMonitor->vecTransformedSize.x > 3000) {
|
||||
textureSize = Vector2D(3840, 2160);
|
||||
texPath += "4K.png";
|
||||
} else {
|
||||
@@ -846,7 +866,7 @@ void CHyprOpenGLImpl::createBGTextureForMonitor(SMonitor* pMonitor) {
|
||||
void CHyprOpenGLImpl::clearWithTex() {
|
||||
RASSERT(m_RenderData.pMonitor, "Tried to render BGtex without begin()!");
|
||||
|
||||
wlr_box box = {0, 0, m_RenderData.pMonitor->vecPixelSize.x, m_RenderData.pMonitor->vecPixelSize.y};
|
||||
wlr_box box = {0, 0, m_RenderData.pMonitor->vecTransformedSize.x, m_RenderData.pMonitor->vecTransformedSize.y};
|
||||
|
||||
renderTexture(m_mMonitorBGTextures[m_RenderData.pMonitor], &box, 255, 0);
|
||||
}
|
||||
|
@@ -92,6 +92,7 @@ private:
|
||||
std::string m_szExtensions;
|
||||
|
||||
bool m_bFakeFrame = false;
|
||||
bool m_bEndFrame = false;
|
||||
|
||||
// Shaders
|
||||
SQuad m_shQUAD;
|
||||
|
@@ -19,10 +19,12 @@ void renderSurface(struct wlr_surface* surface, int x, int y, void* data) {
|
||||
}
|
||||
scaleBox(&windowBox, RDATA->output->scale);
|
||||
|
||||
float rounding = RDATA->dontRound ? 0 : RDATA->rounding == -1 ? g_pConfigManager->getInt("decoration:rounding") : RDATA->rounding;
|
||||
|
||||
if (RDATA->surface && surface == RDATA->surface)
|
||||
g_pHyprOpenGL->renderTextureWithBlur(TEXTURE, &windowBox, RDATA->fadeAlpha * RDATA->alpha, surface, RDATA->dontRound ? 0 : g_pConfigManager->getInt("decoration:rounding"), RDATA->decorate);
|
||||
g_pHyprOpenGL->renderTextureWithBlur(TEXTURE, &windowBox, RDATA->fadeAlpha * RDATA->alpha, surface, rounding, RDATA->decorate);
|
||||
else
|
||||
g_pHyprOpenGL->renderTexture(TEXTURE, &windowBox, RDATA->fadeAlpha * RDATA->alpha, RDATA->dontRound ? 0 : g_pConfigManager->getInt("decoration:rounding"), false, false);
|
||||
g_pHyprOpenGL->renderTexture(TEXTURE, &windowBox, RDATA->fadeAlpha * RDATA->alpha, rounding, false, false);
|
||||
|
||||
wlr_surface_send_frame_done(surface, RDATA->when);
|
||||
|
||||
@@ -55,7 +57,7 @@ void CHyprRenderer::renderWorkspaceWithFullscreenWindow(SMonitor* pMonitor, CWor
|
||||
continue;
|
||||
|
||||
// found it!
|
||||
renderWindow(&w, pMonitor, time, false);
|
||||
renderWindow(&w, pMonitor, time, pWorkspace->m_efFullscreenMode != FULLSCREEN_FULL);
|
||||
|
||||
pWorkspaceWindow = &w;
|
||||
}
|
||||
@@ -69,6 +71,13 @@ void CHyprRenderer::renderWorkspaceWithFullscreenWindow(SMonitor* pMonitor, CWor
|
||||
}
|
||||
|
||||
// and the overlay layers
|
||||
if (pWorkspace->m_efFullscreenMode != FULLSCREEN_FULL) {
|
||||
// on non-full we draw the bar and shit
|
||||
for (auto& ls : pMonitor->m_aLayerSurfaceLists[ZWLR_LAYER_SHELL_V1_LAYER_TOP]) {
|
||||
renderLayer(ls, pMonitor, time);
|
||||
}
|
||||
}
|
||||
|
||||
for (auto& ls : pMonitor->m_aLayerSurfaceLists[ZWLR_LAYER_SHELL_V1_LAYER_OVERLAY]) {
|
||||
renderLayer(ls, pMonitor, time);
|
||||
}
|
||||
@@ -85,7 +94,8 @@ void CHyprRenderer::renderWindow(CWindow* pWindow, SMonitor* pMonitor, timespec*
|
||||
return;
|
||||
|
||||
if (pWindow->m_bFadingOut) {
|
||||
g_pHyprOpenGL->renderSnapshot(&pWindow);
|
||||
if (pMonitor->ID == pWindow->m_iMonitorID) // TODO: fix this
|
||||
g_pHyprOpenGL->renderSnapshot(&pWindow);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -95,16 +105,21 @@ void CHyprRenderer::renderWindow(CWindow* pWindow, SMonitor* pMonitor, timespec*
|
||||
renderdata.surface = g_pXWaylandManager->getWindowSurface(pWindow);
|
||||
renderdata.w = std::clamp(pWindow->m_vRealSize.vec().x, (double)5, (double)1337420); // clamp the size to min 5,
|
||||
renderdata.h = std::clamp(pWindow->m_vRealSize.vec().y, (double)5, (double)1337420); // otherwise we'll have issues later with invalid boxes
|
||||
renderdata.dontRound = pWindow->m_bIsFullscreen;
|
||||
renderdata.dontRound = pWindow->m_bIsFullscreen && PWORKSPACE->m_efFullscreenMode == FULLSCREEN_FULL;
|
||||
renderdata.fadeAlpha = pWindow->m_fAlpha.fl() * (PWORKSPACE->m_fAlpha.fl() / 255.f);
|
||||
renderdata.alpha = pWindow->m_bIsFullscreen ? g_pConfigManager->getFloat("decoration:fullscreen_opacity") : pWindow == g_pCompositor->m_pLastWindow ? g_pConfigManager->getFloat("decoration:active_opacity") : g_pConfigManager->getFloat("decoration:inactive_opacity");
|
||||
renderdata.decorate = decorate && !pWindow->m_bX11DoesntWantBorders;
|
||||
renderdata.rounding = pWindow->m_sAdditionalConfigData.rounding;
|
||||
|
||||
// apply window special data
|
||||
renderdata.alpha *= pWindow->m_sSpecialRenderData.alpha;
|
||||
|
||||
g_pHyprOpenGL->m_pCurrentWindow = pWindow;
|
||||
|
||||
// render window decorations first
|
||||
for (auto& wd : pWindow->m_dWindowDecorations)
|
||||
wd->draw(pMonitor);
|
||||
|
||||
wlr_surface_for_each_surface(g_pXWaylandManager->getWindowSurface(pWindow), renderSurface, &renderdata);
|
||||
|
||||
if (pWindow->m_bIsX11) {
|
||||
@@ -194,10 +209,6 @@ void CHyprRenderer::renderAllClientsForMonitor(const int& ID, timespec* time) {
|
||||
}
|
||||
|
||||
renderDragIcon(PMONITOR, time);
|
||||
|
||||
// if correct monitor draw hyprerror
|
||||
if (PMONITOR == &g_pCompositor->m_lMonitors.front())
|
||||
g_pHyprError->draw();
|
||||
}
|
||||
|
||||
void CHyprRenderer::outputMgrApplyTest(wlr_output_configuration_v1* config, bool test) {
|
||||
@@ -548,7 +559,7 @@ void CHyprRenderer::applyMonitorRule(SMonitor* pMonitor, SMonitorRule* pMonitorR
|
||||
Debug::log(LOG, "Applying monitor rule for %s", pMonitor->szName.c_str());
|
||||
|
||||
// Check if the rule isn't already applied
|
||||
if (!force && DELTALESSTHAN(pMonitor->vecPixelSize.x, pMonitorRule->resolution.x, 1) && DELTALESSTHAN(pMonitor->vecPixelSize.y, pMonitorRule->resolution.y, 1) && DELTALESSTHAN(pMonitor->refreshRate, pMonitorRule->refreshRate, 1) && pMonitor->scale == pMonitorRule->scale && DELTALESSTHAN(pMonitor->vecPosition.x, pMonitorRule->offset.x, 1) && DELTALESSTHAN(pMonitor->vecPosition.y, pMonitorRule->offset.y, 1)) {
|
||||
if (!force && DELTALESSTHAN(pMonitor->vecPixelSize.x, pMonitorRule->resolution.x, 1) && DELTALESSTHAN(pMonitor->vecPixelSize.y, pMonitorRule->resolution.y, 1) && DELTALESSTHAN(pMonitor->refreshRate, pMonitorRule->refreshRate, 1) && pMonitor->scale == pMonitorRule->scale && DELTALESSTHAN(pMonitor->vecPosition.x, pMonitorRule->offset.x, 1) && DELTALESSTHAN(pMonitor->vecPosition.y, pMonitorRule->offset.y, 1) && pMonitor->transform == pMonitorRule->transform) {
|
||||
Debug::log(LOG, "Not applying a new rule to %s because it's already applied!", pMonitor->szName.c_str());
|
||||
return;
|
||||
}
|
||||
@@ -612,8 +623,10 @@ void CHyprRenderer::applyMonitorRule(SMonitor* pMonitor, SMonitorRule* pMonitorR
|
||||
pMonitor->vecSize = pMonitorRule->resolution;
|
||||
}
|
||||
|
||||
wlr_output_set_transform(pMonitor->output, pMonitorRule->transform);
|
||||
pMonitor->transform = pMonitorRule->transform;
|
||||
|
||||
pMonitor->vecPixelSize = pMonitor->vecSize;
|
||||
pMonitor->vecSize = (pMonitor->vecSize / pMonitor->scale).floor();
|
||||
|
||||
// update renderer
|
||||
g_pHyprOpenGL->destroyMonitorResources(pMonitor);
|
||||
@@ -623,6 +636,11 @@ void CHyprRenderer::applyMonitorRule(SMonitor* pMonitor, SMonitorRule* pMonitorR
|
||||
return;
|
||||
}
|
||||
|
||||
int x, y;
|
||||
wlr_output_transformed_resolution(pMonitor->output, &x, &y);
|
||||
pMonitor->vecSize = (Vector2D(x, y) / pMonitor->scale).floor();
|
||||
pMonitor->vecTransformedSize = Vector2D(x,y);
|
||||
|
||||
wlr_output_layout_add(g_pCompositor->m_sWLROutputLayout, pMonitor->output, (int)pMonitorRule->offset.x, (int)pMonitorRule->offset.y);
|
||||
|
||||
//wlr_output_damage_add_whole(pMonitor->damage);
|
||||
|
95
src/render/decorations/CHyprGroupBarDecoration.cpp
Normal file
95
src/render/decorations/CHyprGroupBarDecoration.cpp
Normal file
@@ -0,0 +1,95 @@
|
||||
#include "CHyprGroupBarDecoration.hpp"
|
||||
#include "../../Compositor.hpp"
|
||||
|
||||
CHyprGroupBarDecoration::CHyprGroupBarDecoration(CWindow* pWindow) {
|
||||
m_pWindow = pWindow;
|
||||
updateWindow(pWindow);
|
||||
}
|
||||
|
||||
CHyprGroupBarDecoration::~CHyprGroupBarDecoration() {
|
||||
|
||||
}
|
||||
|
||||
SWindowDecorationExtents CHyprGroupBarDecoration::getWindowDecorationExtents() {
|
||||
return m_seExtents;
|
||||
}
|
||||
|
||||
eDecorationType CHyprGroupBarDecoration::getDecorationType() {
|
||||
return DECORATION_GROUPBAR;
|
||||
}
|
||||
|
||||
void CHyprGroupBarDecoration::updateWindow(CWindow* pWindow) {
|
||||
damageEntire();
|
||||
|
||||
if (pWindow->m_vRealPosition.vec() != m_vLastWindowPos || pWindow->m_vRealSize.vec() != m_vLastWindowSize) {
|
||||
// we draw 3px above the window's border with 3px
|
||||
const auto BORDERSIZE = g_pConfigManager->getInt("general:border_size");
|
||||
|
||||
m_seExtents.topLeft = Vector2D(0, BORDERSIZE + 3 + 3);
|
||||
m_seExtents.bottomRight = Vector2D();
|
||||
|
||||
m_vLastWindowPos = pWindow->m_vRealPosition.vec();
|
||||
m_vLastWindowSize = pWindow->m_vRealSize.vec();
|
||||
}
|
||||
|
||||
// let's check if the window group is different.
|
||||
|
||||
if (g_pLayoutManager->getCurrentLayout()->getLayoutName() != "dwindle") {
|
||||
// ????
|
||||
for (auto it = pWindow->m_dWindowDecorations.begin(); it != pWindow->m_dWindowDecorations.end(); it++) {
|
||||
if (it->get() == this) {
|
||||
pWindow->m_dWindowDecorations.erase(it);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// get the group info
|
||||
SLayoutMessageHeader header;
|
||||
header.pWindow = g_pCompositor->m_pLastWindow;
|
||||
|
||||
m_dwGroupMembers = std::any_cast<std::deque<CWindow*>>(g_pLayoutManager->getCurrentLayout()->layoutMessage(header, "groupinfo"));
|
||||
|
||||
damageEntire();
|
||||
|
||||
if (m_dwGroupMembers.size() == 0) {
|
||||
// remove
|
||||
for (auto it = pWindow->m_dWindowDecorations.begin(); it != pWindow->m_dWindowDecorations.end(); it++) {
|
||||
if (it->get() == this) {
|
||||
pWindow->m_dWindowDecorations.erase(it);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void CHyprGroupBarDecoration::damageEntire() {
|
||||
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_seExtents.topLeft.y};
|
||||
g_pHyprRenderer->damageBox(&dm);
|
||||
}
|
||||
|
||||
void CHyprGroupBarDecoration::draw(SMonitor* pMonitor) {
|
||||
// get how many bars we will draw
|
||||
int barsToDraw = m_dwGroupMembers.size();
|
||||
|
||||
if (barsToDraw < 1 || m_pWindow->m_bHidden || !g_pCompositor->windowValidMapped(m_pWindow))
|
||||
return;
|
||||
|
||||
const int PAD = 2; //2px
|
||||
|
||||
const int BARW = (m_vLastWindowSize.x - PAD * (barsToDraw - 1)) / barsToDraw;
|
||||
|
||||
int xoff = 0;
|
||||
|
||||
for (int i = 0; i < barsToDraw; ++i) {
|
||||
wlr_box rect = {m_vLastWindowPos.x + xoff - pMonitor->vecPosition.x, m_vLastWindowPos.y - m_seExtents.topLeft.y - pMonitor->vecPosition.y, BARW, 3};
|
||||
|
||||
if (rect.width <= 0 || rect.height <= 0)
|
||||
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"));
|
||||
g_pHyprOpenGL->renderRect(&rect, color);
|
||||
|
||||
xoff += PAD + BARW;
|
||||
}
|
||||
}
|
30
src/render/decorations/CHyprGroupBarDecoration.hpp
Normal file
30
src/render/decorations/CHyprGroupBarDecoration.hpp
Normal file
@@ -0,0 +1,30 @@
|
||||
#pragma once
|
||||
|
||||
#include "IHyprWindowDecoration.hpp"
|
||||
#include <deque>
|
||||
|
||||
class CHyprGroupBarDecoration : public IHyprWindowDecoration {
|
||||
public:
|
||||
CHyprGroupBarDecoration(CWindow*);
|
||||
virtual ~CHyprGroupBarDecoration();
|
||||
|
||||
virtual SWindowDecorationExtents getWindowDecorationExtents();
|
||||
|
||||
virtual void draw(SMonitor*);
|
||||
|
||||
virtual eDecorationType getDecorationType();
|
||||
|
||||
virtual void updateWindow(CWindow*);
|
||||
|
||||
virtual void damageEntire();
|
||||
|
||||
private:
|
||||
SWindowDecorationExtents m_seExtents;
|
||||
|
||||
CWindow* m_pWindow = nullptr;
|
||||
|
||||
Vector2D m_vLastWindowPos;
|
||||
Vector2D m_vLastWindowSize;
|
||||
|
||||
std::deque<CWindow*> m_dwGroupMembers;
|
||||
};
|
7
src/render/decorations/IHyprWindowDecoration.cpp
Normal file
7
src/render/decorations/IHyprWindowDecoration.cpp
Normal file
@@ -0,0 +1,7 @@
|
||||
#include "IHyprWindowDecoration.hpp"
|
||||
|
||||
#include "../../Window.hpp"
|
||||
|
||||
IHyprWindowDecoration::~IHyprWindowDecoration() {
|
||||
|
||||
}
|
31
src/render/decorations/IHyprWindowDecoration.hpp
Normal file
31
src/render/decorations/IHyprWindowDecoration.hpp
Normal file
@@ -0,0 +1,31 @@
|
||||
#pragma once
|
||||
|
||||
#include "../../defines.hpp"
|
||||
|
||||
enum eDecorationType {
|
||||
DECORATION_NONE = -1,
|
||||
DECORATION_GROUPBAR
|
||||
};
|
||||
|
||||
struct SWindowDecorationExtents {
|
||||
Vector2D topLeft;
|
||||
Vector2D bottomRight;
|
||||
};
|
||||
|
||||
class CWindow;
|
||||
struct SMonitor;
|
||||
|
||||
class IHyprWindowDecoration {
|
||||
public:
|
||||
virtual ~IHyprWindowDecoration() = 0;
|
||||
|
||||
virtual SWindowDecorationExtents getWindowDecorationExtents() = 0;
|
||||
|
||||
virtual void draw(SMonitor*) = 0;
|
||||
|
||||
virtual eDecorationType getDecorationType() = 0;
|
||||
|
||||
virtual void updateWindow(CWindow*) = 0;
|
||||
|
||||
virtual void damageEntire() = 0;
|
||||
};
|
Reference in New Issue
Block a user