mirror of
https://github.com/hyprwm/Hyprland.git
synced 2025-08-01 12:41:55 -07:00
Compare commits
28 Commits
v0.1.1beta
...
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 |
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": 1653658290,
|
||||
"narHash": "sha256-zZaona39DOZNL93A1KG3zAi8vDttJBirxacq24hWCn4=",
|
||||
"lastModified": 1653733431,
|
||||
"narHash": "sha256-0JwNH2E9XlMVa7ZCsqxazpKwpZ2rW5QQjbk0DdZxa48=",
|
||||
"owner": "wlroots",
|
||||
"repo": "wlroots",
|
||||
"rev": "75d31509db8c28e8379fe9570118ef8c82284581",
|
||||
"rev": "93ee4c7684050807e959bb3b6d57826a72fba8c2",
|
||||
"type": "gitlab"
|
||||
},
|
||||
"original": {
|
||||
|
@@ -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;
|
||||
@@ -247,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);
|
||||
|
||||
@@ -436,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;
|
||||
@@ -454,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) {
|
||||
@@ -617,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;
|
||||
|
||||
|
@@ -58,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;
|
||||
// ------------------------------------------------- //
|
||||
|
||||
|
||||
@@ -85,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;
|
||||
@@ -88,6 +90,12 @@ public:
|
||||
// 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;
|
||||
|
@@ -186,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);
|
||||
|
@@ -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
|
||||
|
@@ -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);
|
||||
|
||||
@@ -191,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 {
|
||||
@@ -246,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);
|
||||
|
@@ -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);
|
||||
}
|
||||
|
||||
@@ -254,8 +259,14 @@ void Events::listener_unmapWindow(void* owner, void* data) {
|
||||
// do the animation thing
|
||||
PWINDOW->m_vOriginalClosedPos = PWINDOW->m_vRealPosition.vec();
|
||||
PWINDOW->m_vOriginalClosedSize = PWINDOW->m_vRealSize.vec();
|
||||
PWINDOW->m_vRealPosition = PWINDOW->m_vRealPosition.vec() + Vector2D(0.01f, 0.01f); // it has to be animated, otherwise onWindowPostCreateClose will ignore it
|
||||
|
||||
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) {
|
||||
@@ -303,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());
|
||||
}
|
||||
|
||||
@@ -313,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
|
||||
|
@@ -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: {
|
||||
|
@@ -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) {
|
||||
@@ -671,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;
|
@@ -126,7 +126,7 @@ void CHyprXWaylandManager::setWindowSize(CWindow* pWindow, const Vector2D& size)
|
||||
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 * 2);
|
||||
wlr_xdg_toplevel_set_size(pWindow->m_uSurface.xdg->toplevel, size.x - XDELTA, size.y - YDELTA);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -222,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,7 +585,7 @@ 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, g_pConfigManager->getInt("decoration:blur_ignore_opacity") ? 255.f : a, &damage);
|
||||
@@ -817,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 {
|
||||
@@ -853,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;
|
||||
|
@@ -57,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;
|
||||
}
|
||||
@@ -71,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);
|
||||
}
|
||||
@@ -98,7 +105,7 @@ 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;
|
||||
@@ -109,6 +116,10 @@ void CHyprRenderer::renderWindow(CWindow* pWindow, SMonitor* pMonitor, timespec*
|
||||
|
||||
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) {
|
||||
@@ -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