Merge branch 'hyprwm:main' into main

This commit is contained in:
xDarksome 2022-07-02 19:43:52 +03:00 committed by GitHub
commit 185c4d6ea1
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
59 changed files with 1836 additions and 1018 deletions

View file

@ -1,9 +1,9 @@
Describe your PR, what does it fix/add?
#### Describe your PR, what does it fix/add?
Is there anything you want to mention? (unchecked code, possible bugs, found problems, breaking compatibility, etc.)
#### Is there anything you want to mention? (unchecked code, possible bugs, found problems, breaking compatibility, etc.)
Is it ready for merging, or does it need work?
#### Is it ready for merging, or does it need work?

View file

@ -36,6 +36,7 @@ execute_process(
#
include_directories(. PRIVATE "subprojects/wlroots/include/")
include_directories(. PRIVATE "subprojects/wlroots/build/include/")
add_compile_options(-std=c++20 -DWLR_USE_UNSTABLE )
add_compile_options(-Wall -Wextra -Wno-unused-parameter -Wno-unused-value -Wno-missing-field-initializers -Wno-narrowing)
find_package(Threads REQUIRED)
@ -61,7 +62,7 @@ IF(CMAKE_BUILD_TYPE MATCHES Debug OR CMAKE_BUILD_TYPE MATCHES DEBUG)
message(STATUS "Configuring Hyprland in Debug with CMake!")
add_definitions( -DHYPRLAND_DEBUG )
ELSE()
# add_compile_options(-O3) # may crash for some
add_compile_options( -O3 )
message(STATUS "Configuring Hyprland in Release with CMake!")
ENDIF(CMAKE_BUILD_TYPE MATCHES Debug OR CMAKE_BUILD_TYPE MATCHES DEBUG)

View file

@ -99,7 +99,7 @@ clear:
rm -rf build
rm -f *.o *-protocol.h *-protocol.c
rm -f ./hyprctl/hyprctl
rm -rf ./wlroots/build
rm -rf ./subprojects/wlroots/build
all:
make config
@ -107,6 +107,10 @@ all:
cd ./hyprctl && make all && cd ..
install:
[ ! -d /usr/include/wlr ] || mv /usr/include/wlr /usr/include/wlrBackup
[ ! -f /usr/lib/libwlroots.so ] || mv /usr/lib/libwlroots.so /usr/lib/libwlroots.so.backup
[ ! -f /usr/lib/pkgconfig/wlroots.pc ] || mv /usr/lib/pkgconfig/wlroots.pc /usr/lib/pkgconfig/wlroots.pc.backup
make all
mkdir -p ${PREFIX}/share/wayland-sessions
cp ./example/hyprland.desktop ${PREFIX}/share/wayland-sessions/
@ -118,6 +122,13 @@ install:
cp ./assets/wall_4K.png ${PREFIX}/share/hyprland
cp ./assets/wall_8K.png ${PREFIX}/share/hyprland
rm -rf /usr/include/wlr
rm -f /usr/lib/libwlroots.so
rm -f /usr/lib/pkgconfig/wlroots.pc
[ ! -d /usr/include/wlrBackup ] || mv /usr/include/wlrBackup /usr/include/wlr
[ ! -f /usr/lib/libwlroots.so.backup ] || mv -f /usr/lib/libwlroots.so.backup /usr/lib/libwlroots.so
[ ! -f /usr/lib/pkgconfig/wlroots.pc.backup ] || mv -f /usr/lib/pkgconfig/wlroots.pc.backup /usr/lib/pkgconfig/wlroots.pc
uninstall:
rm -f ${PREFIX}/share/wayland-sessions/hyprland.desktop
rm -f ${PREFIX}/bin/Hyprland
@ -126,13 +137,16 @@ uninstall:
protocols: xdg-shell-protocol.o wlr-layer-shell-unstable-v1-protocol.o wlr-screencopy-unstable-v1-protocol.o idle-protocol.o ext-workspace-unstable-v1-protocol.o pointer-constraints-unstable-v1-protocol.o tablet-unstable-v2-protocol.o
config:
make protocols
fixwlr:
sed -i -E 's/(soversion = 11)([^032]|$$)/soversion = 11032/g' subprojects/wlroots/meson.build
rm -rf ./subprojects/wlroots/build
config:
make protocols
make fixwlr
cd subprojects/wlroots && meson ./build --prefix=/usr --buildtype=release
cd subprojects/wlroots && ninja -C build/

View file

@ -2,11 +2,11 @@
"nodes": {
"nixpkgs": {
"locked": {
"lastModified": 1655807518,
"narHash": "sha256-5YV29Ry/DpAJc/0Hc/+ISVBAjwHpJvAkeKkcUG5lWsc=",
"lastModified": 1656239181,
"narHash": "sha256-wW1xRFBn376yGloXZ4QzBE4hjipMawpV18Lshd9QSPw=",
"owner": "NixOS",
"repo": "nixpkgs",
"rev": "a72d7811be1162dd6804c4e36e5402d76fb6e921",
"rev": "f2537a505d45c31fe5d9c27ea9829b6f4c4e6ac5",
"type": "github"
},
"original": {
@ -26,11 +26,11 @@
"flake": false,
"locked": {
"host": "gitlab.freedesktop.org",
"lastModified": 1654618691,
"narHash": "sha256-8y3u8CoigjoZOVbA2wCWBHlDNEakv0AVxU46/cOC00s=",
"lastModified": 1655824477,
"narHash": "sha256-1kskHOLsnisR3kqIL5IHrQbQG/4xoXxeEf1ExMV6/RU=",
"owner": "wlroots",
"repo": "wlroots",
"rev": "b89ed9015c3fbe8d339e9d65cf70fdca6e5645bc",
"rev": "5c4384a1330faedf975c8b8644881d50390f3613",
"type": "gitlab"
},
"original": {

View file

@ -32,9 +32,13 @@
src = inputs.wlroots;
});
hyprland = prev.callPackage ./nix/default.nix {
version = "0.6.0beta" + "+date=" + (mkDate (self.lastModifiedDate or "19700101"));
version = "0.6.2beta" + "+date=" + (mkDate (self.lastModifiedDate or "19700101"));
wlroots = wlroots-hyprland;
};
hyprland-debug = hyprland.override {debug = true;};
waybar-hyprland = prev.waybar.overrideAttrs (oldAttrs: {
mesonFlags = oldAttrs.mesonFlags ++ ["-Dexperimental=true"];
});
};
packages = genSystems (system:

View file

@ -26,6 +26,8 @@ const std::string USAGE = R"#(usage: hyprctl [command] [(opt)args]
dispatch
keyword
version
kill
hyprpaper
reload)#";
void request(std::string arg) {
@ -74,7 +76,65 @@ void request(std::string arg) {
char buffer[8192] = {0};
sizeWritten = read(SERVERSOCKET,buffer, 8192);
sizeWritten = read(SERVERSOCKET, buffer, 8192);
if (sizeWritten < 0) {
std::cout << "Couldn't read (5)";
return;
}
close(SERVERSOCKET);
std::cout << std::string(buffer);
}
void requestHyprpaper(std::string arg) {
const auto SERVERSOCKET = socket(AF_UNIX, SOCK_STREAM, 0);
if (SERVERSOCKET < 0) {
std::cout << "Couldn't open a socket (1)";
return;
}
const auto SERVER = gethostbyname("localhost");
if (!SERVER) {
std::cout << "Couldn't get host (2)";
return;
}
// get the instance signature
auto instanceSig = getenv("HYPRLAND_INSTANCE_SIGNATURE");
if (!instanceSig) {
std::cout << "HYPRLAND_INSTANCE_SIGNATURE was not set! (Is Hyprland running?)";
return;
}
std::string instanceSigStr = std::string(instanceSig);
sockaddr_un serverAddress = {0};
serverAddress.sun_family = AF_UNIX;
std::string socketPath = "/tmp/hypr/" + instanceSigStr + "/.hyprpaper.sock";
strcpy(serverAddress.sun_path, socketPath.c_str());
if (connect(SERVERSOCKET, (sockaddr*)&serverAddress, SUN_LEN(&serverAddress)) < 0) {
std::cout << "Couldn't connect to " << socketPath << ". (3)";
return;
}
auto sizeWritten = write(SERVERSOCKET, arg.c_str(), arg.length());
if (sizeWritten < 0) {
std::cout << "Couldn't write (4)";
return;
}
char buffer[8192] = {0};
sizeWritten = read(SERVERSOCKET, buffer, 8192);
if (sizeWritten < 0) {
std::cout << "Couldn't read (5)";
@ -109,6 +169,17 @@ void keywordRequest(int argc, char** argv) {
request(rq);
}
void hyprpaperRequest(int argc, char** argv) {
if (argc < 4) {
std::cout << "hyprpaper requires 2 params";
return;
}
std::string rq = std::string(argv[2]) + " " + std::string(argv[3]);
requestHyprpaper(rq);
}
void batchRequest(int argc, char** argv) {
std::string rq = "[[BATCH]]" + std::string(argv[2]);
@ -129,10 +200,12 @@ int main(int argc, char** argv) {
else if (!strcmp(argv[1], "activewindow")) request("activewindow");
else if (!strcmp(argv[1], "layers")) request("layers");
else if (!strcmp(argv[1], "version")) request("version");
else if (!strcmp(argv[1], "kill")) request("kill");
else if (!strcmp(argv[1], "devices")) request("devices");
else if (!strcmp(argv[1], "reload")) request("reload");
else if (!strcmp(argv[1], "dispatch")) dispatchRequest(argc, argv);
else if (!strcmp(argv[1], "keyword")) keywordRequest(argc, argv);
else if (!strcmp(argv[1], "hyprpaper")) hyprpaperRequest(argc, argv);
else if (!strcmp(argv[1], "--batch")) batchRequest(argc, argv);
else if (!strcmp(argv[1], "--help")) printf("%s", USAGE.c_str());
else {

View file

@ -1,6 +1,15 @@
project('Hyprland', 'cpp', 'c',
version : '0.6.0beta',
default_options : ['warning_level=3', 'cpp_std=c++20', 'default_library=static'])
version : '0.6.2beta',
default_options : ['warning_level=2', 'cpp_std=c++20', 'default_library=static', 'optimization=3'])
add_project_arguments(
[
'-Wno-unused-parameter',
'-Wno-unused-value',
'-Wno-missing-field-initializers',
'-Wno-narrowing',
],
language: 'cpp')
wlroots = subproject('wlroots', default_options: ['examples=false'])
have_xwlr = wlroots.get_variable('features').get('xwayland')

View file

@ -20,9 +20,10 @@
xwayland,
enableXWayland ? true,
version ? "git",
debug ? false,
}:
stdenv.mkDerivation {
pname = "hyprland";
pname = "hyprland" + lib.optionalString debug "-debug";
inherit version;
src = ../.;
@ -48,7 +49,10 @@ stdenv.mkDerivation {
]
++ lib.optional enableXWayland xwayland;
mesonBuildType = "release";
mesonBuildType =
if debug
then "debug"
else "release";
mesonFlags = lib.optional (!enableXWayland) "-DNO_XWAYLAND=true";

View file

@ -3,6 +3,11 @@
CCompositor::CCompositor() {
m_szInstanceSignature = GIT_COMMIT_HASH + std::string("_") + std::to_string(time(NULL));
setenv("HYPRLAND_INSTANCE_SIGNATURE", m_szInstanceSignature.c_str(), true);
const auto INSTANCEPATH = "/tmp/hypr/" + m_szInstanceSignature;
mkdir(INSTANCEPATH.c_str(), S_IRWXU | S_IRWXG);
Debug::init(m_szInstanceSignature);
Debug::log(LOG, "Instance Signature: %s", m_szInstanceSignature.c_str());
@ -17,11 +22,6 @@ CCompositor::CCompositor() {
Debug::log(INFO, "If you are crashing, or encounter any bugs, please consult https://github.com/hyprwm/Hyprland/wiki/Crashing-and-bugs\n\n");
setenv("HYPRLAND_INSTANCE_SIGNATURE", m_szInstanceSignature.c_str(), true);
const auto INSTANCEPATH = "/tmp/hypr/" + m_szInstanceSignature;
mkdir(INSTANCEPATH.c_str(), S_IRWXU | S_IRWXG);
m_sWLDisplay = wl_display_create();
m_sWLRBackend = wlr_backend_autocreate(m_sWLDisplay);
@ -121,6 +121,11 @@ CCompositor::CCompositor() {
m_sWLRToplevelMgr = wlr_foreign_toplevel_manager_v1_create(m_sWLDisplay);
m_sWLRTabletManager = wlr_tablet_v2_create(m_sWLDisplay);
m_sWLRForeignRegistry = wlr_xdg_foreign_registry_create(m_sWLDisplay);
wlr_xdg_foreign_v1_create(m_sWLDisplay, m_sWLRForeignRegistry);
wlr_xdg_foreign_v2_create(m_sWLDisplay, m_sWLRForeignRegistry);
}
CCompositor::~CCompositor() {
@ -167,8 +172,8 @@ void CCompositor::cleanupExit() {
m_pLastFocus = nullptr;
m_pLastWindow = nullptr;
m_lWorkspaces.clear();
m_lWindows.clear();
m_vWorkspaces.clear();
m_vWindows.clear();
if (g_pXWaylandManager->m_sWLRXWayland) {
wlr_xwayland_destroy(g_pXWaylandManager->m_sWLRXWayland);
@ -264,9 +269,9 @@ void CCompositor::startCompositor() {
}
SMonitor* CCompositor::getMonitorFromID(const int& id) {
for (auto& m : m_lMonitors) {
if (m.ID == (uint64_t)id) {
return &m;
for (auto& m : m_vMonitors) {
if (m->ID == (uint64_t)id) {
return m.get();
}
}
@ -274,9 +279,9 @@ SMonitor* CCompositor::getMonitorFromID(const int& id) {
}
SMonitor* CCompositor::getMonitorFromName(const std::string& name) {
for (auto& m : m_lMonitors) {
if (m.szName == name) {
return &m;
for (auto& m : m_vMonitors) {
if (m->szName == name) {
return m.get();
}
}
@ -296,18 +301,18 @@ SMonitor* CCompositor::getMonitorFromVector(const Vector2D& point) {
float bestDistance = 0.f;
SMonitor* pBestMon = nullptr;
for (auto& m : m_lMonitors) {
float dist = vecToRectDistanceSquared(point, m.vecPosition, m.vecPosition + m.vecSize);
for (auto& m : m_vMonitors) {
float dist = vecToRectDistanceSquared(point, m->vecPosition, m->vecPosition + m->vecSize);
if (dist < bestDistance || !pBestMon) {
bestDistance = dist;
pBestMon = &m;
pBestMon = m.get();
}
}
if (!pBestMon) { // ?????
Debug::log(WARN, "getMonitorFromVector no close mon???");
return &m_lMonitors.front();
return m_vMonitors.front().get();
}
return pBestMon;
@ -317,13 +322,35 @@ SMonitor* CCompositor::getMonitorFromVector(const Vector2D& point) {
}
void CCompositor::removeWindowFromVectorSafe(CWindow* pWindow) {
if (windowExists(pWindow) && !pWindow->m_bFadingOut)
m_lWindows.remove(*pWindow);
if (windowExists(pWindow) && !pWindow->m_bFadingOut){
if (pWindow->m_bIsX11 && pWindow->m_iX11Type == 2) {
m_dUnmanagedX11Windows.erase(std::remove_if(m_dUnmanagedX11Windows.begin(), m_dUnmanagedX11Windows.end(), [&](std::unique_ptr<CWindow>& el) { return el.get() == pWindow; }));
}
// if X11, also check its children
// and delete any needed
if (pWindow->m_bIsX11) {
for (auto& w : m_vWindows) {
if (!w->m_bIsX11)
continue;
if (w->m_pX11Parent == pWindow)
m_vWindows.erase(std::remove_if(m_vWindows.begin(), m_vWindows.end(), [&](std::unique_ptr<CWindow>& el) { return el.get() == w.get(); }));
}
for (auto& w : m_dUnmanagedX11Windows) {
if (w->m_pX11Parent == pWindow)
m_dUnmanagedX11Windows.erase(std::remove_if(m_dUnmanagedX11Windows.begin(), m_dUnmanagedX11Windows.end(), [&](std::unique_ptr<CWindow>& el) { return el.get() == w.get(); }));
}
}
m_vWindows.erase(std::remove_if(m_vWindows.begin(), m_vWindows.end(), [&](std::unique_ptr<CWindow>& el) { return el.get() == pWindow; }));
}
}
bool CCompositor::windowExists(CWindow* pWindow) {
for (auto& w : m_lWindows) {
if (&w == pWindow)
for (auto& w : m_vWindows) {
if (w.get() == pWindow)
return true;
}
@ -334,24 +361,24 @@ CWindow* CCompositor::vectorToWindow(const Vector2D& pos) {
const auto PMONITOR = getMonitorFromVector(pos);
if (PMONITOR->specialWorkspaceOpen) {
for (auto& w : m_lWindows) {
wlr_box box = {w.m_vRealPosition.vec().x, w.m_vRealPosition.vec().y, w.m_vRealSize.vec().x, w.m_vRealSize.vec().y};
if (w.m_iWorkspaceID == SPECIAL_WORKSPACE_ID && wlr_box_contains_point(&box, pos.x, pos.y) && w.m_bIsMapped && !w.m_bIsFloating && !w.m_bHidden)
return &w;
for (auto& w : m_vWindows) {
wlr_box box = {w->m_vRealPosition.vec().x, w->m_vRealPosition.vec().y, w->m_vRealSize.vec().x, w->m_vRealSize.vec().y};
if (w->m_iWorkspaceID == SPECIAL_WORKSPACE_ID && wlr_box_contains_point(&box, pos.x, pos.y) && w->m_bIsMapped && !w->m_bIsFloating && !w->m_bHidden)
return w.get();
}
}
// first loop over floating cuz they're above, m_lWindows should be sorted bottom->top, for tiled it doesn't matter.
for (auto w = m_lWindows.rbegin(); w != m_lWindows.rend(); w++) {
wlr_box box = {w->m_vRealPosition.vec().x, w->m_vRealPosition.vec().y, w->m_vRealSize.vec().x, w->m_vRealSize.vec().y};
if (wlr_box_contains_point(&box, pos.x, pos.y) && w->m_bIsMapped && w->m_bIsFloating && isWorkspaceVisible(w->m_iWorkspaceID) && !w->m_bHidden)
return &(*w);
// first loop over floating cuz they're above, m_vWindows should be sorted bottom->top, for tiled it doesn't matter.
for (auto w = m_vWindows.rbegin(); w != m_vWindows.rend(); w++) {
wlr_box box = {(*w)->m_vRealPosition.vec().x, (*w)->m_vRealPosition.vec().y, (*w)->m_vRealSize.vec().x, (*w)->m_vRealSize.vec().y};
if (wlr_box_contains_point(&box, pos.x, pos.y) && (*w)->m_bIsMapped && (*w)->m_bIsFloating && isWorkspaceVisible((*w)->m_iWorkspaceID) && !(*w)->m_bHidden)
return w->get();
}
for (auto& w : m_lWindows) {
wlr_box box = {w.m_vRealPosition.vec().x, w.m_vRealPosition.vec().y, w.m_vRealSize.vec().x, w.m_vRealSize.vec().y};
if (wlr_box_contains_point(&box, pos.x, pos.y) && w.m_bIsMapped && !w.m_bIsFloating && PMONITOR->activeWorkspace == w.m_iWorkspaceID && !w.m_bHidden)
return &w;
for (auto& w : m_vWindows) {
wlr_box box = {w->m_vRealPosition.vec().x, w->m_vRealPosition.vec().y, w->m_vRealSize.vec().x, w->m_vRealSize.vec().y};
if (wlr_box_contains_point(&box, pos.x, pos.y) && w->m_bIsMapped && !w->m_bIsFloating && PMONITOR->activeWorkspace == w->m_iWorkspaceID && !w->m_bHidden)
return w.get();
}
return nullptr;
@ -361,17 +388,17 @@ CWindow* CCompositor::vectorToWindowTiled(const Vector2D& pos) {
const auto PMONITOR = getMonitorFromVector(pos);
if (PMONITOR->specialWorkspaceOpen) {
for (auto& w : m_lWindows) {
wlr_box box = {w.m_vPosition.x, w.m_vPosition.y, w.m_vSize.x, w.m_vSize.y};
if (w.m_iWorkspaceID == SPECIAL_WORKSPACE_ID && wlr_box_contains_point(&box, pos.x, pos.y) && !w.m_bIsFloating && !w.m_bHidden)
return &w;
for (auto& w : m_vWindows) {
wlr_box box = {w->m_vPosition.x, w->m_vPosition.y, w->m_vSize.x, w->m_vSize.y};
if (w->m_iWorkspaceID == SPECIAL_WORKSPACE_ID && wlr_box_contains_point(&box, pos.x, pos.y) && !w->m_bIsFloating && !w->m_bHidden)
return w.get();
}
}
for (auto& w : m_lWindows) {
wlr_box box = {w.m_vPosition.x, w.m_vPosition.y, w.m_vSize.x, w.m_vSize.y};
if (w.m_bIsMapped && wlr_box_contains_point(&box, pos.x, pos.y) && w.m_iWorkspaceID == PMONITOR->activeWorkspace && !w.m_bIsFloating && !w.m_bHidden)
return &w;
for (auto& w : m_vWindows) {
wlr_box box = {w->m_vPosition.x, w->m_vPosition.y, w->m_vSize.x, w->m_vSize.y};
if (w->m_bIsMapped && wlr_box_contains_point(&box, pos.x, pos.y) && w->m_iWorkspaceID == PMONITOR->activeWorkspace && !w->m_bIsFloating && !w->m_bHidden)
return w.get();
}
return nullptr;
@ -382,24 +409,24 @@ CWindow* CCompositor::vectorToWindowIdeal(const Vector2D& pos) {
// special workspace
if (PMONITOR->specialWorkspaceOpen) {
for (auto& w : m_lWindows) {
wlr_box box = {w.m_vPosition.x, w.m_vPosition.y, w.m_vSize.x, w.m_vSize.y};
if (w.m_iWorkspaceID == SPECIAL_WORKSPACE_ID && w.m_bIsMapped && wlr_box_contains_point(&box, pos.x, pos.y) && !w.m_bHidden)
return &w;
for (auto& w : m_vWindows) {
wlr_box box = {w->m_vPosition.x, w->m_vPosition.y, w->m_vSize.x, w->m_vSize.y};
if (w->m_iWorkspaceID == SPECIAL_WORKSPACE_ID && w->m_bIsMapped && wlr_box_contains_point(&box, pos.x, pos.y) && !w->m_bHidden)
return w.get();
}
}
// first loop over floating cuz they're above, m_lWindows should be sorted bottom->top, for tiled it doesn't matter.
for (auto w = m_lWindows.rbegin(); w != m_lWindows.rend(); w++) {
wlr_box box = {w->m_vRealPosition.vec().x, w->m_vRealPosition.vec().y, w->m_vRealSize.vec().x, w->m_vRealSize.vec().y};
if (w->m_bIsFloating && w->m_bIsMapped && wlr_box_contains_point(&box, m_sWLRCursor->x, m_sWLRCursor->y) && isWorkspaceVisible(w->m_iWorkspaceID) && !w->m_bHidden)
return &(*w);
for (auto w = m_vWindows.rbegin(); w != m_vWindows.rend(); w++) {
wlr_box box = {(*w)->m_vRealPosition.vec().x, (*w)->m_vRealPosition.vec().y, (*w)->m_vRealSize.vec().x, (*w)->m_vRealSize.vec().y};
if ((*w)->m_bIsFloating && (*w)->m_bIsMapped && wlr_box_contains_point(&box, m_sWLRCursor->x, m_sWLRCursor->y) && isWorkspaceVisible((*w)->m_iWorkspaceID) && !(*w)->m_bHidden)
return w->get();
}
for (auto& w : m_lWindows) {
wlr_box box = {w.m_vPosition.x, w.m_vPosition.y, w.m_vSize.x, w.m_vSize.y};
if (!w.m_bIsFloating && w.m_bIsMapped && wlr_box_contains_point(&box, pos.x, pos.y) && w.m_iWorkspaceID == PMONITOR->activeWorkspace && !w.m_bHidden)
return &w;
for (auto& w : m_vWindows) {
wlr_box box = {w->m_vPosition.x, w->m_vPosition.y, w->m_vSize.x, w->m_vSize.y};
if (!w->m_bIsFloating && w->m_bIsMapped && wlr_box_contains_point(&box, pos.x, pos.y) && w->m_iWorkspaceID == PMONITOR->activeWorkspace && !w->m_bHidden)
return w.get();
}
return nullptr;
@ -409,34 +436,34 @@ CWindow* CCompositor::windowFromCursor() {
const auto PMONITOR = getMonitorFromCursor();
if (PMONITOR->specialWorkspaceOpen) {
for (auto& w : m_lWindows) {
wlr_box box = {w.m_vPosition.x, w.m_vPosition.y, w.m_vSize.x, w.m_vSize.y};
if (w.m_iWorkspaceID == SPECIAL_WORKSPACE_ID && wlr_box_contains_point(&box, m_sWLRCursor->x, m_sWLRCursor->y) && w.m_bIsMapped)
return &w;
for (auto& w : m_vWindows) {
wlr_box box = {w->m_vPosition.x, w->m_vPosition.y, w->m_vSize.x, w->m_vSize.y};
if (w->m_iWorkspaceID == SPECIAL_WORKSPACE_ID && wlr_box_contains_point(&box, m_sWLRCursor->x, m_sWLRCursor->y) && w->m_bIsMapped)
return w.get();
}
}
// first loop over floating cuz they're above, m_lWindows should be sorted bottom->top, for tiled it doesn't matter.
for (auto w = m_lWindows.rbegin(); w != m_lWindows.rend(); w++) {
wlr_box box = {w->m_vRealPosition.vec().x, w->m_vRealPosition.vec().y, w->m_vRealSize.vec().x, w->m_vRealSize.vec().y};
if (wlr_box_contains_point(&box, m_sWLRCursor->x, m_sWLRCursor->y) && w->m_bIsMapped && w->m_bIsFloating && isWorkspaceVisible(w->m_iWorkspaceID))
return &(*w);
for (auto w = m_vWindows.rbegin(); w != m_vWindows.rend(); w++) {
wlr_box box = {(*w)->m_vRealPosition.vec().x, (*w)->m_vRealPosition.vec().y, (*w)->m_vRealSize.vec().x, (*w)->m_vRealSize.vec().y};
if (wlr_box_contains_point(&box, m_sWLRCursor->x, m_sWLRCursor->y) && (*w)->m_bIsMapped && (*w)->m_bIsFloating && isWorkspaceVisible((*w)->m_iWorkspaceID))
return w->get();
}
for (auto& w : m_lWindows) {
wlr_box box = {w.m_vPosition.x, w.m_vPosition.y, w.m_vSize.x, w.m_vSize.y};
if (wlr_box_contains_point(&box, m_sWLRCursor->x, m_sWLRCursor->y) && w.m_bIsMapped && w.m_iWorkspaceID == PMONITOR->activeWorkspace)
return &w;
for (auto& w : m_vWindows) {
wlr_box box = {w->m_vPosition.x, w->m_vPosition.y, w->m_vSize.x, w->m_vSize.y};
if (wlr_box_contains_point(&box, m_sWLRCursor->x, m_sWLRCursor->y) && w->m_bIsMapped && w->m_iWorkspaceID == PMONITOR->activeWorkspace)
return w.get();
}
return nullptr;
}
CWindow* CCompositor::windowFloatingFromCursor() {
for (auto w = m_lWindows.rbegin(); w != m_lWindows.rend(); w++) {
wlr_box box = {w->m_vRealPosition.vec().x, w->m_vRealPosition.vec().y, w->m_vRealSize.vec().x, w->m_vRealSize.vec().y};
if (wlr_box_contains_point(&box, m_sWLRCursor->x, m_sWLRCursor->y) && w->m_bIsMapped && w->m_bIsFloating && isWorkspaceVisible(w->m_iWorkspaceID) && !w->m_bHidden)
return &(*w);
for (auto w = m_vWindows.rbegin(); w != m_vWindows.rend(); w++) {
wlr_box box = {(*w)->m_vRealPosition.vec().x, (*w)->m_vRealPosition.vec().y, (*w)->m_vRealSize.vec().x, (*w)->m_vRealSize.vec().y};
if (wlr_box_contains_point(&box, m_sWLRCursor->x, m_sWLRCursor->y) && (*w)->m_bIsMapped && (*w)->m_bIsFloating && isWorkspaceVisible((*w)->m_iWorkspaceID) && !(*w)->m_bHidden)
return w->get();
}
return nullptr;
@ -475,9 +502,9 @@ wlr_surface* CCompositor::vectorWindowToSurface(const Vector2D& pos, CWindow* pW
}
SMonitor* CCompositor::getMonitorFromOutput(wlr_output* out) {
for (auto& m : m_lMonitors) {
if (m.output == out) {
return &m;
for (auto& m : m_vMonitors) {
if (m->output == out) {
return m.get();
}
}
@ -586,59 +613,58 @@ bool CCompositor::windowValidMapped(CWindow* pWindow) {
if (pWindow->m_bHidden)
return false;
if (!g_pXWaylandManager->getWindowSurface(pWindow))
return false;
return true;
}
CWindow* CCompositor::getWindowForPopup(wlr_xdg_popup* popup) {
for (auto& p : m_lXDGPopups) {
if (p.popup == popup)
return p.parentWindow;
for (auto& p : m_vXDGPopups) {
if (p->popup == popup)
return p->parentWindow;
}
return nullptr;
}
wlr_surface* CCompositor::vectorToLayerSurface(const Vector2D& pos, std::list<SLayerSurface*>* layerSurfaces, Vector2D* sCoords) {
wlr_surface* CCompositor::vectorToLayerSurface(const Vector2D& pos, std::list<SLayerSurface*>* layerSurfaces, Vector2D* sCoords, SLayerSurface** ppLayerSurfaceFound) {
for (auto it = layerSurfaces->rbegin(); it != layerSurfaces->rend(); it++) {
if ((*it)->fadingOut || !(*it)->layerSurface || ((*it)->layerSurface && !(*it)->layerSurface->mapped))
continue;
const auto SURFACEAT = wlr_layer_surface_v1_surface_at((*it)->layerSurface, pos.x - (*it)->geometry.x, pos.y - (*it)->geometry.y, &sCoords->x, &sCoords->y);
if (SURFACEAT)
if (SURFACEAT) {
*ppLayerSurfaceFound = *it;
return SURFACEAT;
}
}
return nullptr;
}
CWindow* CCompositor::getWindowFromSurface(wlr_surface* pSurface) {
for (auto& w : m_lWindows) {
if (g_pXWaylandManager->getWindowSurface(&w) == pSurface)
return &w;
for (auto& w : m_vWindows) {
if (g_pXWaylandManager->getWindowSurface(w.get()) == pSurface)
return w.get();
}
return nullptr;
}
CWindow* CCompositor::getFullscreenWindowOnWorkspace(const int& ID) {
for (auto& w : m_lWindows) {
if (w.m_iWorkspaceID == ID && w.m_bIsFullscreen)
return &w;
for (auto& w : m_vWindows) {
if (w->m_iWorkspaceID == ID && w->m_bIsFullscreen)
return w.get();
}
return nullptr;
}
bool CCompositor::isWorkspaceVisible(const int& w) {
for (auto& m : m_lMonitors) {
if (m.activeWorkspace == w)
for (auto& m : m_vMonitors) {
if (m->activeWorkspace == w)
return true;
if (m.specialWorkspaceOpen && w == SPECIAL_WORKSPACE_ID)
if (m->specialWorkspaceOpen && w == SPECIAL_WORKSPACE_ID)
return true;
}
@ -646,34 +672,42 @@ bool CCompositor::isWorkspaceVisible(const int& w) {
}
CWorkspace* CCompositor::getWorkspaceByID(const int& id) {
for (auto& w : m_lWorkspaces) {
if (w.m_iID == id)
return &w;
for (auto& w : m_vWorkspaces) {
if (w->m_iID == id)
return w.get();
}
return nullptr;
}
void CCompositor::sanityCheckWorkspaces() {
for (auto it = m_lWorkspaces.begin(); it != m_lWorkspaces.end(); ++it) {
if ((getWindowsOnWorkspace(it->m_iID) == 0 && !isWorkspaceVisible(it->m_iID))) {
it = m_lWorkspaces.erase(it);
for (auto it = m_vWorkspaces.begin(); it != m_vWorkspaces.end(); ++it) {
const auto WINDOWSONWORKSPACE = getWindowsOnWorkspace((*it)->m_iID);
if ((WINDOWSONWORKSPACE == 0 && !isWorkspaceVisible((*it)->m_iID))) {
it = m_vWorkspaces.erase(it);
if (it == m_vWorkspaces.end())
break;
}
if (it->m_iID == SPECIAL_WORKSPACE_ID && getWindowsOnWorkspace(it->m_iID) == 0) {
for (auto& m : m_lMonitors) {
m.specialWorkspaceOpen = false;
if ((*it)->m_iID == SPECIAL_WORKSPACE_ID && WINDOWSONWORKSPACE == 0) {
for (auto& m : m_vMonitors) {
m->specialWorkspaceOpen = false;
}
it = m_lWorkspaces.erase(it);
it = m_vWorkspaces.erase(it);
if (it == m_vWorkspaces.end())
break;
}
}
}
int CCompositor::getWindowsOnWorkspace(const int& id) {
int no = 0;
for (auto& w : m_lWindows) {
if (w.m_iWorkspaceID == id && w.m_bIsMapped)
for (auto& w : m_vWindows) {
if (w->m_iWorkspaceID == id && w->m_bIsMapped)
no++;
}
@ -681,9 +715,9 @@ int CCompositor::getWindowsOnWorkspace(const int& id) {
}
CWindow* CCompositor::getFirstWindowOnWorkspace(const int& id) {
for (auto& w : m_lWindows) {
if (w.m_iWorkspaceID == id)
return &w;
for (auto& w : m_vWindows) {
if (w->m_iWorkspaceID == id)
return w.get();
}
return nullptr;
@ -697,16 +731,16 @@ void CCompositor::fixXWaylandWindowsOnWorkspace(const int& id) {
if (!PWORKSPACE)
return;
for (auto& w : m_lWindows) {
if (w.m_iWorkspaceID == id) {
for (auto& w : m_vWindows) {
if (w->m_iWorkspaceID == id) {
// moveXWaylandWindow only moves XWayland windows
// so there is no need to check here
// if the window is XWayland or not.
if (ISVISIBLE && (!PWORKSPACE->m_bHasFullscreenWindow || w.m_bIsFullscreen))
g_pXWaylandManager->moveXWaylandWindow(&w, w.m_vRealPosition.vec());
if (ISVISIBLE && (!PWORKSPACE->m_bHasFullscreenWindow || w->m_bIsFullscreen))
g_pXWaylandManager->moveXWaylandWindow(w.get(), w->m_vRealPosition.vec());
else
g_pXWaylandManager->moveXWaylandWindow(&w, Vector2D(42069,42069));
g_pXWaylandManager->moveXWaylandWindow(w.get(), Vector2D(42069,42069));
}
}
}
@ -731,37 +765,37 @@ void CCompositor::moveWindowToTop(CWindow* pWindow) {
if (!windowValidMapped(pWindow))
return;
for (auto it = m_lWindows.begin(); it != m_lWindows.end(); ++it) {
if (&(*it) == pWindow) {
m_lWindows.splice(m_lWindows.end(), m_lWindows, it);
for (auto it = m_vWindows.begin(); it != m_vWindows.end(); ++it) {
if (it->get() == pWindow) {
std::rotate(it, it + 1, m_vWindows.end());
break;
}
}
}
void CCompositor::cleanupFadingOut() {
for (auto& w : m_lWindowsFadingOut) {
for (auto& w : m_vWindowsFadingOut) {
bool valid = windowExists(w);
if (!valid || !w->m_bFadingOut || w->m_fAlpha.fl() == 0.f) {
if (valid && !w->m_bReadyToDelete)
continue;
g_pHyprOpenGL->m_mWindowFramebuffers[w].release();
g_pHyprOpenGL->m_mWindowFramebuffers.erase(w);
m_lWindows.remove(*w);
m_lWindowsFadingOut.remove(w);
removeWindowFromVectorSafe(w);
m_vWindowsFadingOut.erase(std::remove(m_vWindowsFadingOut.begin(), m_vWindowsFadingOut.end(), w));
Debug::log(LOG, "Cleanup: destroyed a window");
return;
}
}
for (auto& ls : m_lSurfacesFadingOut) {
for (auto& ls : m_vSurfacesFadingOut) {
if (ls->fadingOut && ls->readyToDelete && !ls->alpha.isBeingAnimated()) {
for (auto& m : m_lMonitors) {
for (auto& lsl : m.m_aLayerSurfaceLists) {
for (auto& m : m_vMonitors) {
for (auto& lsl : m->m_aLayerSurfaceLists) {
lsl.remove(ls);
}
}
@ -770,7 +804,7 @@ void CCompositor::cleanupFadingOut() {
g_pHyprOpenGL->m_mLayerFramebuffers.erase(ls);
delete ls;
m_lSurfacesFadingOut.remove(ls);
m_vSurfacesFadingOut.erase(std::remove(m_vSurfacesFadingOut.begin(), m_vSurfacesFadingOut.end(), ls));
Debug::log(LOG, "Cleanup: destroyed a layersurface");
@ -789,11 +823,11 @@ CWindow* CCompositor::getWindowInDirection(CWindow* pWindow, char dir) {
auto longestIntersect = -1;
CWindow* longestIntersectWindow = nullptr;
for (auto& w : m_lWindows) {
if (&w == pWindow || !windowValidMapped(&w) || w.m_bIsFloating || !isWorkspaceVisible(w.m_iWorkspaceID))
for (auto& w : m_vWindows) {
if (w.get() == pWindow || !w->m_bIsMapped || w->m_bHidden || w->m_bIsFloating || !isWorkspaceVisible(w->m_iWorkspaceID))
continue;
const auto BWINDOWIDEALBB = w.getWindowIdealBoundingBoxIgnoreReserved();
const auto BWINDOWIDEALBB = w->getWindowIdealBoundingBoxIgnoreReserved();
const auto POSB = Vector2D(BWINDOWIDEALBB.x, BWINDOWIDEALBB.y);
const auto SIZEB = Vector2D(BWINDOWIDEALBB.width, BWINDOWIDEALBB.height);
@ -804,7 +838,7 @@ CWindow* CCompositor::getWindowInDirection(CWindow* pWindow, char dir) {
const auto INTERSECTLEN = std::max((double)0, std::min(POSA.y + SIZEA.y, POSB.y + SIZEB.y) - std::max(POSA.y, POSB.y));
if (INTERSECTLEN > longestIntersect) {
longestIntersect = INTERSECTLEN;
longestIntersectWindow = &w;
longestIntersectWindow = w.get();
}
}
break;
@ -813,7 +847,7 @@ CWindow* CCompositor::getWindowInDirection(CWindow* pWindow, char dir) {
const auto INTERSECTLEN = std::max((double)0, std::min(POSA.y + SIZEA.y, POSB.y + SIZEB.y) - std::max(POSA.y, POSB.y));
if (INTERSECTLEN > longestIntersect) {
longestIntersect = INTERSECTLEN;
longestIntersectWindow = &w;
longestIntersectWindow = w.get();
}
}
break;
@ -823,7 +857,7 @@ CWindow* CCompositor::getWindowInDirection(CWindow* pWindow, char dir) {
const auto INTERSECTLEN = std::max((double)0, std::min(POSA.x + SIZEA.x, POSB.x + SIZEB.x) - std::max(POSA.x, POSB.x));
if (INTERSECTLEN > longestIntersect) {
longestIntersect = INTERSECTLEN;
longestIntersectWindow = &w;
longestIntersectWindow = w.get();
}
}
break;
@ -833,7 +867,7 @@ CWindow* CCompositor::getWindowInDirection(CWindow* pWindow, char dir) {
const auto INTERSECTLEN = std::max((double)0, std::min(POSA.x + SIZEA.x, POSB.x + SIZEB.x) - std::max(POSA.x, POSB.x));
if (INTERSECTLEN > longestIntersect) {
longestIntersect = INTERSECTLEN;
longestIntersectWindow = &w;
longestIntersectWindow = w.get();
}
}
break;
@ -847,30 +881,30 @@ CWindow* CCompositor::getWindowInDirection(CWindow* pWindow, char dir) {
}
void CCompositor::deactivateAllWLRWorkspaces(wlr_ext_workspace_handle_v1* exclude) {
for (auto& w : m_lWorkspaces) {
if (w.m_pWlrHandle && w.m_pWlrHandle != exclude)
w.setActive(false);
for (auto& w : m_vWorkspaces) {
if (w->m_pWlrHandle && w->m_pWlrHandle != exclude)
w->setActive(false);
}
}
CWindow* CCompositor::getNextWindowOnWorkspace(CWindow* pWindow) {
bool gotToWindow = false;
for (auto& w : m_lWindows) {
if (&w != pWindow && !gotToWindow)
for (auto& w : m_vWindows) {
if (w.get() != pWindow && !gotToWindow)
continue;
if (&w == pWindow) {
if (w.get() == pWindow) {
gotToWindow = true;
continue;
}
if (w.m_iWorkspaceID == pWindow->m_iWorkspaceID && windowValidMapped(&w))
return &w;
if (w->m_iWorkspaceID == pWindow->m_iWorkspaceID && w->m_bIsMapped && !w->m_bHidden)
return w.get();
}
for (auto& w : m_lWindows) {
if (&w != pWindow && w.m_iWorkspaceID == pWindow->m_iWorkspaceID && windowValidMapped(&w))
return &w;
for (auto& w : m_vWindows) {
if (w.get() != pWindow && w->m_iWorkspaceID == pWindow->m_iWorkspaceID && w->m_bIsMapped && !w->m_bHidden)
return w.get();
}
return nullptr;
@ -878,18 +912,18 @@ CWindow* CCompositor::getNextWindowOnWorkspace(CWindow* pWindow) {
int CCompositor::getNextAvailableNamedWorkspace() {
int lowest = -1337 + 1;
for (auto& w : m_lWorkspaces) {
if (w.m_iID < -1 && w.m_iID < lowest)
lowest = w.m_iID;
for (auto& w : m_vWorkspaces) {
if (w->m_iID < -1 && w->m_iID < lowest)
lowest = w->m_iID;
}
return lowest - 1;
}
CWorkspace* CCompositor::getWorkspaceByName(const std::string& name) {
for (auto& w : m_lWorkspaces) {
if (w.m_szName == name)
return &w;
for (auto& w : m_vWorkspaces) {
if (w->m_szName == name)
return w.get();
}
return nullptr;
@ -911,8 +945,8 @@ CWorkspace* CCompositor::getWorkspaceByString(const std::string& str) {
}
bool CCompositor::isPointOnAnyMonitor(const Vector2D& point) {
for (auto& m : m_lMonitors) {
if (VECINRECT(point, m.vecPosition.x, m.vecPosition.y, m.vecSize.x + m.vecPosition.x, m.vecSize.y + m.vecPosition.y))
for (auto& m : m_vMonitors) {
if (VECINRECT(point, m->vecPosition.x, m->vecPosition.y, m->vecSize.x + m->vecPosition.x, m->vecSize.y + m->vecPosition.y))
return true;
}
@ -925,12 +959,12 @@ CWindow* CCompositor::getConstraintWindow(SMouse* pMouse) {
const auto PSURFACE = pMouse->currentConstraint->surface;
for (auto& w : m_lWindows) {
if (PSURFACE == g_pXWaylandManager->getWindowSurface(&w)) {
if (!w.m_bIsX11 && !windowValidMapped(&w))
for (auto& w : m_vWindows) {
if (PSURFACE == g_pXWaylandManager->getWindowSurface(w.get())) {
if (!w->m_bIsX11 && w->m_bIsMapped && !w->m_bHidden)
continue;
return &w;
return w.get();
}
}
@ -944,19 +978,19 @@ SMonitor* CCompositor::getMonitorInDirection(const char& dir) {
auto longestIntersect = -1;
SMonitor* longestIntersectMonitor = nullptr;
for (auto& m : m_lMonitors) {
if (&m == m_pLastMonitor)
for (auto& m : m_vMonitors) {
if (m.get() == m_pLastMonitor)
continue;
const auto POSB = m.vecPosition;
const auto SIZEB = m.vecSize;
const auto POSB = m->vecPosition;
const auto SIZEB = m->vecSize;
switch (dir) {
case 'l':
if (STICKS(POSA.x, POSB.x + SIZEB.x)) {
const auto INTERSECTLEN = std::max((double)0, std::min(POSA.y + SIZEA.y, POSB.y + SIZEB.y) - std::max(POSA.y, POSB.y));
if (INTERSECTLEN > longestIntersect) {
longestIntersect = INTERSECTLEN;
longestIntersectMonitor = &m;
longestIntersectMonitor = m.get();
}
}
break;
@ -965,7 +999,7 @@ SMonitor* CCompositor::getMonitorInDirection(const char& dir) {
const auto INTERSECTLEN = std::max((double)0, std::min(POSA.y + SIZEA.y, POSB.y + SIZEB.y) - std::max(POSA.y, POSB.y));
if (INTERSECTLEN > longestIntersect) {
longestIntersect = INTERSECTLEN;
longestIntersectMonitor = &m;
longestIntersectMonitor = m.get();
}
}
break;
@ -975,7 +1009,7 @@ SMonitor* CCompositor::getMonitorInDirection(const char& dir) {
const auto INTERSECTLEN = std::max((double)0, std::min(POSA.x + SIZEA.x, POSB.x + SIZEB.x) - std::max(POSA.x, POSB.x));
if (INTERSECTLEN > longestIntersect) {
longestIntersect = INTERSECTLEN;
longestIntersectMonitor = &m;
longestIntersectMonitor = m.get();
}
}
break;
@ -985,7 +1019,7 @@ SMonitor* CCompositor::getMonitorInDirection(const char& dir) {
const auto INTERSECTLEN = std::max((double)0, std::min(POSA.x + SIZEA.x, POSB.x + SIZEB.x) - std::max(POSA.x, POSB.x));
if (INTERSECTLEN > longestIntersect) {
longestIntersect = INTERSECTLEN;
longestIntersectMonitor = &m;
longestIntersectMonitor = m.get();
}
}
break;
@ -999,11 +1033,11 @@ SMonitor* CCompositor::getMonitorInDirection(const char& dir) {
}
void CCompositor::updateAllWindowsBorders() {
for (auto& w : m_lWindows) {
if (!w.m_bIsMapped)
for (auto& w : m_vWindows) {
if (!w->m_bIsMapped)
continue;
updateWindowBorderColor(&w);
updateWindowBorderColor(w.get());
}
}
@ -1028,9 +1062,9 @@ void CCompositor::moveWindowToWorkspace(CWindow* pWindow, const std::string& wor
int CCompositor::getNextAvailableMonitorID() {
int64_t topID = -1;
for (auto& m : m_lMonitors) {
if ((int64_t)m.ID > topID)
topID = m.ID;
for (auto& m : m_vMonitors) {
if ((int64_t)m->ID > topID)
topID = m->ID;
}
return topID + 1;
@ -1051,9 +1085,9 @@ void CCompositor::moveWorkspaceToMonitor(CWorkspace* pWorkspace, SMonitor* pMoni
// fix old mon
int nextWorkspaceOnMonitorID = -1;
for (auto& w : m_lWorkspaces) {
if (w.m_iMonitorID == POLDMON->ID && w.m_iID != pWorkspace->m_iID) {
nextWorkspaceOnMonitorID = w.m_iID;
for (auto& w : m_vWorkspaces) {
if (w->m_iMonitorID == POLDMON->ID && w->m_iID != pWorkspace->m_iID) {
nextWorkspaceOnMonitorID = w->m_iID;
break;
}
}
@ -1077,9 +1111,9 @@ void CCompositor::moveWorkspaceToMonitor(CWorkspace* pWorkspace, SMonitor* pMoni
pWorkspace->m_iMonitorID = pMonitor->ID;
pWorkspace->moveToMonitor(pMonitor->ID);
for (auto& w : m_lWindows) {
if (w.m_iWorkspaceID == pWorkspace->m_iID)
w.m_iMonitorID = pMonitor->ID;
for (auto& w : m_vWindows) {
if (w->m_iWorkspaceID == pWorkspace->m_iID)
w->m_iMonitorID = pMonitor->ID;
}
if (SWITCHINGISACTIVE) { // if it was active, preserve its' status. If it wasn't, don't.
@ -1106,12 +1140,12 @@ bool CCompositor::workspaceIDOutOfBounds(const int& id) {
int lowestID = 99999;
int highestID = -99999;
for (auto& w : m_lWorkspaces) {
if (w.m_iID < lowestID)
lowestID = w.m_iID;
for (auto& w : m_vWorkspaces) {
if (w->m_iID < lowestID)
lowestID = w->m_iID;
if (w.m_iID > highestID)
highestID = w.m_iID;
if (w->m_iID > highestID)
highestID = w->m_iID;
}
return std::clamp(id, lowestID, highestID) != id;
@ -1125,8 +1159,33 @@ void CCompositor::setWindowFullscreen(CWindow* pWindow, bool on, eFullscreenMode
g_pXWaylandManager->setWindowFullscreen(pWindow, pWindow->m_bIsFullscreen && mode == FULLSCREEN_FULL);
// make all windows on the same workspace under the fullscreen window
for (auto& w : g_pCompositor->m_lWindows) {
if (w.m_iWorkspaceID == pWindow->m_iWorkspaceID)
w.m_bCreatedOverFullscreen = false;
for (auto& w : g_pCompositor->m_vWindows) {
if (w->m_iWorkspaceID == pWindow->m_iWorkspaceID)
w->m_bCreatedOverFullscreen = false;
}
}
void CCompositor::moveUnmanagedX11ToWindows(CWindow* pWindow) {
for (auto it = m_dUnmanagedX11Windows.begin(); it != m_dUnmanagedX11Windows.end(); it++) {
if (it->get() == pWindow) {
m_vWindows.emplace_back(std::move(*it));
m_dUnmanagedX11Windows.erase(it);
return;
}
}
}
CWindow* CCompositor::getX11Parent(CWindow* pWindow) {
if (!pWindow->m_bIsX11)
return nullptr;
for (auto& w : m_vWindows) {
if (!w->m_bIsX11)
continue;
if (w->m_uSurface.xwayland == pWindow->m_uSurface.xwayland->parent)
return w.get();
}
return nullptr;
}

View file

@ -60,19 +60,21 @@ public:
wlr_virtual_pointer_manager_v1* m_sWLRVirtPtrMgr;
wlr_foreign_toplevel_manager_v1* m_sWLRToplevelMgr;
wlr_tablet_manager_v2* m_sWLRTabletManager;
wlr_xdg_foreign_registry* m_sWLRForeignRegistry;
// ------------------------------------------------- //
const char* m_szWLDisplaySocket;
std::string m_szInstanceSignature = "";
std::list<SMonitor> m_lMonitors;
std::list<CWindow> m_lWindows;
std::list<SXDGPopup> m_lXDGPopups;
std::list<CWorkspace> m_lWorkspaces;
std::list<SSubsurface> m_lSubsurfaces;
std::list<CWindow*> m_lWindowsFadingOut;
std::list<SLayerSurface*> m_lSurfacesFadingOut;
std::vector<std::unique_ptr<SMonitor>> m_vMonitors;
std::vector<std::unique_ptr<CWindow>> m_vWindows;
std::deque<std::unique_ptr<CWindow>> m_dUnmanagedX11Windows;
std::vector<std::unique_ptr<SXDGPopup>> m_vXDGPopups;
std::vector<std::unique_ptr<CWorkspace>> m_vWorkspaces;
std::vector<std::unique_ptr<SSubsurface>> m_vSubsurfaces;
std::vector<CWindow*> m_vWindowsFadingOut;
std::vector<SLayerSurface*> m_vSurfacesFadingOut;
void startCompositor();
void cleanupExit();
@ -99,7 +101,7 @@ public:
CWindow* vectorToWindow(const Vector2D&);
CWindow* vectorToWindowIdeal(const Vector2D&);
CWindow* vectorToWindowTiled(const Vector2D&);
wlr_surface* vectorToLayerSurface(const Vector2D&, std::list<SLayerSurface*>*, Vector2D*);
wlr_surface* vectorToLayerSurface(const Vector2D&, std::list<SLayerSurface*>*, Vector2D*, SLayerSurface**);
wlr_surface* vectorWindowToSurface(const Vector2D&, CWindow*, Vector2D& sl);
CWindow* windowFromCursor();
CWindow* windowFloatingFromCursor();
@ -133,6 +135,8 @@ public:
void moveWorkspaceToMonitor(CWorkspace*, SMonitor*);
bool workspaceIDOutOfBounds(const int&);
void setWindowFullscreen(CWindow*, bool, eFullscreenMode);
void moveUnmanagedX11ToWindows(CWindow*);
CWindow* getX11Parent(CWindow*);
private:
void initAllSignals();

View file

@ -72,4 +72,21 @@ wlr_box CWindow::getWindowIdealBoundingBoxIgnoreReserved() {
}
return wlr_box{(int)POS.x, (int)POS.y, (int)SIZE.x, (int)SIZE.y};
}
}
void CWindow::updateWindowDecos() {
for (auto& wd : m_dWindowDecorations)
wd->updateWindow(this);
}
pid_t CWindow::getPID() {
pid_t PID = -1;
if (!m_bIsX11) {
const auto CLIENT = wl_resource_get_client(m_uSurface.xdg->resource);
wl_client_get_credentials(CLIENT, &PID, nullptr, nullptr);
} else {
PID = m_uSurface.xwayland->pid;
}
return PID;
}

View file

@ -67,6 +67,7 @@ public:
// XWayland stuff
bool m_bIsX11 = false;
bool m_bMappedX11 = false;
CWindow* m_pX11Parent = nullptr;
uint64_t m_iX11Type = 0;
bool m_bIsModal = false;
bool m_bX11DoesntWantBorders = false;
@ -76,6 +77,7 @@ public:
// For nofocus
bool m_bNoFocus = false;
bool m_bNoInitialFocus = false;
SSurfaceTreeNode* m_pSurfaceTree = nullptr;
@ -110,5 +112,7 @@ public:
// methods
wlr_box getFullWindowBoundingBox();
wlr_box getWindowIdealBoundingBoxIgnoreReserved();
void updateWindowDecos();
pid_t getPID();
};

View file

@ -15,6 +15,8 @@ CConfigManager::CConfigManager() {
static const char* const ENVHOME = getenv("HOME");
const std::string CONFIGPATH = ENVHOME + (ISDEBUG ? (std::string) "/.config/hypr/hyprlandd.conf" : (std::string) "/.config/hypr/hyprland.conf");
configPaths.emplace_back(CONFIGPATH);
Debug::disableLogs = &configValues["debug:disable_logs"].intValue;
}
void CConfigManager::setDefaultVars() {
@ -38,6 +40,8 @@ void CConfigManager::setDefaultVars() {
configValues["debug:int"].intValue = 0;
configValues["debug:log_damage"].intValue = 0;
configValues["debug:overlay"].intValue = 0;
configValues["debug:damage_blink"].intValue = 0;
configValues["debug:disable_logs"].intValue = 0;
configValues["decoration:rounding"].intValue = 1;
configValues["decoration:blur"].intValue = 1;
@ -47,12 +51,13 @@ void CConfigManager::setDefaultVars() {
configValues["decoration:active_opacity"].floatValue = 1;
configValues["decoration:inactive_opacity"].floatValue = 1;
configValues["decoration:fullscreen_opacity"].floatValue = 1;
configValues["decoration:multisample_edges"].intValue = 0;
configValues["decoration:multisample_edges"].intValue = 1;
configValues["decoration:no_blur_on_oversized"].intValue = 1;
configValues["decoration:drop_shadow"].intValue = 1;
configValues["decoration:shadow_range"].intValue = 4;
configValues["decoration:shadow_render_power"].intValue = 3;
configValues["decoration:shadow_ignore_window"].intValue = 1;
configValues["decoration:shadow_offset"].strValue = "0 0";
configValues["decoration:col.shadow"].intValue = 0xee1a1a1a;
configValues["dwindle:pseudotile"].intValue = 0;
@ -103,6 +108,24 @@ void CConfigManager::setDefaultVars() {
configValues["autogenerated"].intValue = 0;
}
void CConfigManager::setDeviceDefaultVars(const std::string& dev) {
auto& cfgValues = deviceConfigs[dev];
cfgValues["kb_layout"].strValue = "us";
cfgValues["kb_variant"].strValue = STRVAL_EMPTY;
cfgValues["kb_options"].strValue = STRVAL_EMPTY;
cfgValues["kb_rules"].strValue = STRVAL_EMPTY;
cfgValues["kb_model"].strValue = STRVAL_EMPTY;
cfgValues["repeat_rate"].intValue = 25;
cfgValues["repeat_delay"].intValue = 600;
cfgValues["natural_scroll"].intValue = 0;
cfgValues["numlock_by_default"].intValue = 0;
cfgValues["disable_while_typing"].intValue = 1;
cfgValues["clickfinger_behavior"].intValue = 0;
cfgValues["middle_button_emulation"].intValue = 0;
cfgValues["tap-to-click"].intValue = 1;
}
void CConfigManager::init() {
loadConfigLoadVars();
@ -132,33 +155,58 @@ void CConfigManager::configSetValueSafe(const std::string& COMMAND, const std::s
parseError = "Error setting value <" + VALUE + "> for field <" + COMMAND + ">: No such field.";
}
return;
if (COMMAND.find("device:") == 0 /* devices parsed later */) {
parseError = "";
} else {
return;
}
}
SConfigValue* CONFIGENTRY = nullptr;
auto& CONFIGENTRY = configValues.at(COMMAND);
if (CONFIGENTRY.intValue != -1) {
if (COMMAND.find("device:") == 0) {
const auto DEVICE = COMMAND.substr(7).substr(0, COMMAND.find_last_of(':') - 7);
const auto CONFIGVAR = COMMAND.substr(COMMAND.find_last_of(':') + 1);
if (!deviceConfigExists(DEVICE))
setDeviceDefaultVars(DEVICE);
auto it = deviceConfigs.find(DEVICE);
if (it->second.find(CONFIGVAR) == it->second.end()) {
parseError = "Error setting value <" + VALUE + "> for field <" + COMMAND + ">: No such field.";
return;
}
CONFIGENTRY = &it->second.at(CONFIGVAR);
} else {
CONFIGENTRY = &configValues.at(COMMAND);
}
CONFIGENTRY->set = true;
if (CONFIGENTRY->intValue != -1) {
try {
if (VALUE.find("0x") == 0) {
// Values with 0x are hex
const auto VALUEWITHOUTHEX = VALUE.substr(2);
CONFIGENTRY.intValue = stol(VALUEWITHOUTHEX, nullptr, 16);
CONFIGENTRY->intValue = stol(VALUEWITHOUTHEX, nullptr, 16);
} else
CONFIGENTRY.intValue = stol(VALUE);
CONFIGENTRY->intValue = stol(VALUE);
} catch (...) {
Debug::log(WARN, "Error reading value of %s", COMMAND.c_str());
parseError = "Error setting value <" + VALUE + "> for field <" + COMMAND + ">.";
}
} else if (CONFIGENTRY.floatValue != -1) {
} else if (CONFIGENTRY->floatValue != -1) {
try {
CONFIGENTRY.floatValue = stof(VALUE);
CONFIGENTRY->floatValue = stof(VALUE);
} catch (...) {
Debug::log(WARN, "Error reading value of %s", COMMAND.c_str());
parseError = "Error setting value <" + VALUE + "> for field <" + COMMAND + ">.";
}
} else if (CONFIGENTRY.strValue != "") {
} else if (CONFIGENTRY->strValue != "") {
try {
CONFIGENTRY.strValue = VALUE;
CONFIGENTRY->strValue = VALUE;
} catch (...) {
Debug::log(WARN, "Error reading value of %s", COMMAND.c_str());
parseError = "Error setting value <" + VALUE + "> for field <" + COMMAND + ">.";
@ -611,8 +659,8 @@ std::string CConfigManager::parseKeyword(const std::string& COMMAND, const std::
parseError = "";
// invalidate layouts jic
for (auto& m : g_pCompositor->m_lMonitors)
g_pLayoutManager->getCurrentLayout()->recalculateMonitor(m.ID);
for (auto& m : g_pCompositor->m_vMonitors)
g_pLayoutManager->getCurrentLayout()->recalculateMonitor(m->ID);
// Update window border colors
g_pCompositor->updateAllWindowsBorders();
@ -704,6 +752,7 @@ void CConfigManager::loadConfigLoadVars() {
g_pAnimationManager->removeAllBeziers();
m_mAdditionalReservedAreas.clear();
configDynamicVars.clear();
deviceConfigs.clear();
// paths
configPaths.clear();
@ -772,8 +821,8 @@ void CConfigManager::loadConfigLoadVars() {
ifs.close();
}
for (auto& m : g_pCompositor->m_lMonitors)
g_pLayoutManager->getCurrentLayout()->recalculateMonitor(m.ID);
for (auto& m : g_pCompositor->m_vMonitors)
g_pLayoutManager->getCurrentLayout()->recalculateMonitor(m->ID);
// Update the keyboard layout to the cfg'd one if this is not the first launch
if (!isFirstLaunch)
@ -806,6 +855,10 @@ void CConfigManager::loadConfigLoadVars() {
// Update window border colors
g_pCompositor->updateAllWindowsBorders();
// Force the compositor to fully re-render all monitors
for (auto& m : g_pCompositor->m_vMonitors)
m->forceFullFrames = 2;
}
void CConfigManager::tick() {
@ -843,7 +896,7 @@ void CConfigManager::tick() {
}
std::mutex configmtx;
SConfigValue CConfigManager::getConfigValueSafe(std::string val) {
SConfigValue CConfigManager::getConfigValueSafe(const std::string& val) {
std::lock_guard<std::mutex> lg(configmtx);
SConfigValue copy = configValues[val];
@ -851,15 +904,38 @@ SConfigValue CConfigManager::getConfigValueSafe(std::string val) {
return copy;
}
int CConfigManager::getInt(std::string v) {
SConfigValue CConfigManager::getConfigValueSafeDevice(const std::string& dev, const std::string& val) {
std::lock_guard<std::mutex> lg(configmtx);
const auto it = deviceConfigs.find(dev);
if (it == deviceConfigs.end()) {
return SConfigValue();
}
SConfigValue copy = it->second[val];
// fallback if not set explicitly
if (!copy.set) {
for (auto& cv : configValues) {
if (cv.first.find(val) == cv.first.length() - val.length()) {
copy = cv.second;
}
}
}
return copy;
}
int CConfigManager::getInt(const std::string& v) {
return getConfigValueSafe(v).intValue;
}
float CConfigManager::getFloat(std::string v) {
float CConfigManager::getFloat(const std::string& v) {
return getConfigValueSafe(v).floatValue;
}
std::string CConfigManager::getString(std::string v) {
std::string CConfigManager::getString(const std::string& v) {
const auto VAL = getConfigValueSafe(v).strValue;
if (VAL == STRVAL_EMPTY)
@ -868,6 +944,23 @@ std::string CConfigManager::getString(std::string v) {
return VAL;
}
int CConfigManager::getDeviceInt(const std::string& dev, const std::string& v) {
return getConfigValueSafeDevice(dev, v).intValue;
}
float CConfigManager::getDeviceFloat(const std::string& dev, const std::string& v) {
return getConfigValueSafeDevice(dev, v).floatValue;
}
std::string CConfigManager::getDeviceString(const std::string& dev, const std::string& v) {
const auto VAL = getConfigValueSafeDevice(dev, v).strValue;
if (VAL == STRVAL_EMPTY)
return "";
return VAL;
}
void CConfigManager::setInt(std::string v, int val) {
configValues[v].intValue = val;
}
@ -964,14 +1057,30 @@ void CConfigManager::dispatchExecOnce() {
}
void CConfigManager::performMonitorReload() {
for (auto& m : g_pCompositor->m_lMonitors) {
auto rule = getMonitorRuleFor(m.szName);
g_pHyprRenderer->applyMonitorRule(&m, &rule);
bool overAgain = false;
for (auto& m : g_pCompositor->m_vMonitors) {
auto rule = getMonitorRuleFor(m->szName);
if (!g_pHyprRenderer->applyMonitorRule(m.get(), &rule)) {
overAgain = true;
break;
}
}
if (overAgain)
performMonitorReload();
m_bWantsMonitorReload = false;
}
SConfigValue* CConfigManager::getConfigValuePtr(std::string val) {
return &configValues[val];
}
bool CConfigManager::deviceConfigExists(const std::string& dev) {
const auto it = deviceConfigs.find(dev);
return it != deviceConfigs.end();
}

View file

@ -20,6 +20,8 @@ struct SConfigValue {
int64_t intValue = -1;
float floatValue = -1;
std::string strValue = "";
bool set = false; // used for device configs
};
struct SMonitorRule {
@ -52,13 +54,18 @@ public:
void tick();
void init();
int getInt(std::string);
float getFloat(std::string);
std::string getString(std::string);
int getInt(const std::string&);
float getFloat(const std::string&);
std::string getString(const std::string&);
void setFloat(std::string, float);
void setInt(std::string, int);
void setString(std::string, std::string);
int getDeviceInt(const std::string&, const std::string&);
float getDeviceFloat(const std::string&, const std::string&);
std::string getDeviceString(const std::string&, const std::string&);
bool deviceConfigExists(const std::string&);
SConfigValue* getConfigValuePtr(std::string);
SMonitorRule getMonitorRuleFor(std::string);
@ -81,6 +88,7 @@ private:
std::unordered_map<std::string, time_t> configModifyTimes; // stores modify times
std::unordered_map<std::string, std::string> configDynamicVars; // stores dynamic vars declared by the user
std::unordered_map<std::string, SConfigValue> configValues;
std::unordered_map<std::string, std::unordered_map<std::string, SConfigValue>> deviceConfigs; // stores device configs
std::string configCurrentPath;
@ -100,12 +108,15 @@ private:
// internal methods
void setDefaultVars();
void setDeviceDefaultVars(const std::string&);
void applyUserDefinedVars(std::string&, const size_t);
void loadConfigLoadVars();
SConfigValue getConfigValueSafe(std::string);
SConfigValue getConfigValueSafe(const std::string&);
SConfigValue getConfigValueSafeDevice(const std::string&, const std::string&);
void parseLine(std::string&);
void configSetValueSafe(const std::string&, const std::string&);
void handleDeviceConfig(const std::string&, const std::string&);
void handleRawExec(const std::string&, const std::string&);
void handleMonitor(const std::string&, const std::string&);
void handleBind(const std::string&, const std::string&, bool locked = false);

View file

@ -71,6 +71,7 @@ dwindle {
# example binds
bind=SUPER,Q,exec,kitty
bind=SUPER,RETURN,exec,alacritty
bind=SUPER,C,killactive,
bind=SUPER,M,exit,
bind=SUPER,E,exec,dolphin

View file

@ -15,9 +15,9 @@
std::string monitorsRequest() {
std::string result = "";
for (auto& m : g_pCompositor->m_lMonitors) {
result += getFormat("Monitor %s (ID %i):\n\t%ix%i@%f at %ix%i\n\tactive workspace: %i (%s)\n\treserved: %i %i %i %i\n\n",
m.szName.c_str(), m.ID, (int)m.vecSize.x, (int)m.vecSize.y, m.refreshRate, (int)m.vecPosition.x, (int)m.vecPosition.y, m.activeWorkspace, g_pCompositor->getWorkspaceByID(m.activeWorkspace)->m_szName.c_str(), (int)m.vecReservedTopLeft.x, (int)m.vecReservedTopLeft.y, (int)m.vecReservedBottomRight.x, (int)m.vecReservedBottomRight.y);
for (auto& m : g_pCompositor->m_vMonitors) {
result += getFormat("Monitor %s (ID %i):\n\t%ix%i@%f at %ix%i\n\tactive workspace: %i (%s)\n\treserved: %i %i %i %i\n\tscale: %.2f\n\ttransform: %i\n\n",
m->szName.c_str(), m->ID, (int)m->vecPixelSize.x, (int)m->vecPixelSize.y, m->refreshRate, (int)m->vecPosition.x, (int)m->vecPosition.y, m->activeWorkspace, g_pCompositor->getWorkspaceByID(m->activeWorkspace)->m_szName.c_str(), (int)m->vecReservedTopLeft.x, (int)m->vecReservedTopLeft.y, (int)m->vecReservedBottomRight.x, (int)m->vecReservedBottomRight.y, m->scale, (int)m->transform);
}
return result;
@ -25,19 +25,21 @@ std::string monitorsRequest() {
std::string clientsRequest() {
std::string result = "";
for (auto& w : g_pCompositor->m_lWindows) {
if (w.m_bIsMapped)
result += getFormat("Window %x -> %s:\n\tat: %i,%i\n\tsize: %i,%i\n\tworkspace: %i (%s)\n\tfloating: %i\n\tmonitor: %i\n\tclass: %s\n\n",
&w, w.m_szTitle.c_str(), (int)w.m_vRealPosition.vec().x, (int)w.m_vRealPosition.vec().y, (int)w.m_vRealSize.vec().x, (int)w.m_vRealSize.vec().y, w.m_iWorkspaceID, (w.m_iWorkspaceID == -1 ? "" : g_pCompositor->getWorkspaceByID(w.m_iWorkspaceID) ? g_pCompositor->getWorkspaceByID(w.m_iWorkspaceID)->m_szName.c_str() : std::string("Invalid workspace " + std::to_string(w.m_iWorkspaceID)).c_str()), (int)w.m_bIsFloating, w.m_iMonitorID, g_pXWaylandManager->getAppIDClass(&w).c_str());
for (auto& w : g_pCompositor->m_vWindows) {
if (w->m_bIsMapped) {
result += getFormat("Window %x -> %s:\n\tat: %i,%i\n\tsize: %i,%i\n\tworkspace: %i (%s)\n\tfloating: %i\n\tmonitor: %i\n\tclass: %s\n\ttitle: %s\n\tpid: %i\n\n",
&w, w->m_szTitle.c_str(), (int)w->m_vRealPosition.vec().x, (int)w->m_vRealPosition.vec().y, (int)w->m_vRealSize.vec().x, (int)w->m_vRealSize.vec().y, w->m_iWorkspaceID, (w->m_iWorkspaceID == -1 ? "" : g_pCompositor->getWorkspaceByID(w->m_iWorkspaceID) ? g_pCompositor->getWorkspaceByID(w->m_iWorkspaceID)->m_szName.c_str() : std::string("Invalid workspace " + std::to_string(w->m_iWorkspaceID)).c_str()), (int)w->m_bIsFloating, w->m_iMonitorID, g_pXWaylandManager->getAppIDClass(w.get()).c_str(), g_pXWaylandManager->getTitle(w.get()).c_str(), w->getPID());
}
}
return result;
}
std::string workspacesRequest() {
std::string result = "";
for (auto& w : g_pCompositor->m_lWorkspaces) {
for (auto& w : g_pCompositor->m_vWorkspaces) {
result += getFormat("workspace ID %i (%s) on monitor %s:\n\twindows: %i\n\thasfullscreen: %i\n\n",
w.m_iID, w.m_szName.c_str(), g_pCompositor->getMonitorFromID(w.m_iMonitorID)->szName.c_str(), g_pCompositor->getWindowsOnWorkspace(w.m_iID), (int)w.m_bHasFullscreenWindow);
w->m_iID, w->m_szName.c_str(), g_pCompositor->getMonitorFromID(w->m_iMonitorID)->szName.c_str(), g_pCompositor->getWindowsOnWorkspace(w->m_iID), (int)w->m_bHasFullscreenWindow);
}
return result;
}
@ -48,17 +50,17 @@ std::string activeWindowRequest() {
if (!g_pCompositor->windowValidMapped(PWINDOW))
return "Invalid";
return getFormat("Window %x -> %s:\n\tat: %i,%i\n\tsize: %i,%i\n\tworkspace: %i (%s)\n\tfloating: %i\n\tmonitor: %i\n\tclass: %s\n\n",
PWINDOW, PWINDOW->m_szTitle.c_str(), (int)PWINDOW->m_vRealPosition.vec().x, (int)PWINDOW->m_vRealPosition.vec().y, (int)PWINDOW->m_vRealSize.vec().x, (int)PWINDOW->m_vRealSize.vec().y, PWINDOW->m_iWorkspaceID, (PWINDOW->m_iWorkspaceID == -1 ? "" : g_pCompositor->getWorkspaceByID(PWINDOW->m_iWorkspaceID)->m_szName.c_str()), (int)PWINDOW->m_bIsFloating, (int)PWINDOW->m_iMonitorID, g_pXWaylandManager->getAppIDClass(PWINDOW).c_str());
return getFormat("Window %x -> %s:\n\tat: %i,%i\n\tsize: %i,%i\n\tworkspace: %i (%s)\n\tfloating: %i\n\tmonitor: %i\n\tclass: %s\n\ttitle: %s\n\tpid: %i\n\n",
PWINDOW, PWINDOW->m_szTitle.c_str(), (int)PWINDOW->m_vRealPosition.vec().x, (int)PWINDOW->m_vRealPosition.vec().y, (int)PWINDOW->m_vRealSize.vec().x, (int)PWINDOW->m_vRealSize.vec().y, PWINDOW->m_iWorkspaceID, (PWINDOW->m_iWorkspaceID == -1 ? "" : g_pCompositor->getWorkspaceByID(PWINDOW->m_iWorkspaceID)->m_szName.c_str()), (int)PWINDOW->m_bIsFloating, (int)PWINDOW->m_iMonitorID, g_pXWaylandManager->getAppIDClass(PWINDOW).c_str(), g_pXWaylandManager->getTitle(PWINDOW).c_str(), PWINDOW->getPID());
}
std::string layersRequest() {
std::string result = "";
for (auto& mon : g_pCompositor->m_lMonitors) {
for (auto& mon : g_pCompositor->m_vMonitors) {
result += getFormat("Monitor %s:\n");
int layerLevel = 0;
for (auto& level : mon.m_aLayerSurfaceLists) {
for (auto& level : mon->m_aLayerSurfaceLists) {
result += getFormat("\tLayer level %i:\n", layerLevel);
for (auto& layer : level) {
@ -173,6 +175,12 @@ std::string reloadRequest() {
return "ok";
}
std::string killRequest() {
g_pInputManager->setClickMode(CLICKMODE_KILL);
return "ok";
}
std::string getReply(std::string);
std::string dispatchBatch(std::string request) {
@ -214,6 +222,8 @@ std::string getReply(std::string request) {
return workspacesRequest();
else if (request == "clients")
return clientsRequest();
else if (request == "kill")
return killRequest();
else if (request == "activewindow")
return activeWindowRequest();
else if (request == "layers")

View file

@ -120,7 +120,7 @@ int CHyprMonitorDebugOverlay::draw(int offset) {
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};
m_wbLastDrawnBox = {(int)g_pCompositor->m_vMonitors.front()->vecPosition.x, (int)g_pCompositor->m_vMonitors.front()->vecPosition.y + offset - 1, (int)maxX + 2, yOffset - offset + 2};
g_pHyprRenderer->damageBox(&m_wbLastDrawnBox);
return yOffset - offset;
@ -140,7 +140,7 @@ void CHyprDebugOverlay::frameData(SMonitor* pMonitor) {
void CHyprDebugOverlay::draw() {
const auto PMONITOR = &g_pCompositor->m_lMonitors.front();
const auto PMONITOR = g_pCompositor->m_vMonitors.front().get();
if (!m_pCairoSurface || !m_pCairo) {
m_pCairoSurface = cairo_image_surface_create(CAIRO_FORMAT_ARGB32, PMONITOR->vecSize.x, PMONITOR->vecSize.y);
@ -155,8 +155,8 @@ void CHyprDebugOverlay::draw() {
// draw the things
int offsetY = 0;
for (auto& m : g_pCompositor->m_lMonitors) {
offsetY += m_mMonitorOverlays[&m].draw(offsetY);
for (auto& m : g_pCompositor->m_vMonitors) {
offsetY += m_mMonitorOverlays[m.get()].draw(offsetY);
offsetY += 5; // for padding between mons
}

View file

@ -14,6 +14,9 @@ void Debug::init(std::string IS) {
void Debug::log(LogLevel level, const char* fmt, ...) {
if (disableLogs && *disableLogs)
return;
// log to a file
std::ofstream ofs;
ofs.open(logFile, std::ios::out | std::ios::app);

View file

@ -17,4 +17,5 @@ namespace Debug {
void log(LogLevel level, const char* fmt, ...);
inline std::string logFile;
inline int64_t* disableLogs = nullptr;
};

View file

@ -55,17 +55,7 @@ void Events::listener_mouseAxis(wl_listener* listener, void* data) {
void Events::listener_requestMouse(wl_listener* listener, void* data) {
const auto EVENT = (wlr_seat_pointer_request_set_cursor_event*)data;
if (!g_pHyprRenderer->shouldRenderCursor())
return;
if (!EVENT->surface) {
g_pHyprRenderer->m_bWindowRequestedCursorHide = true;
} else {
g_pHyprRenderer->m_bWindowRequestedCursorHide = false;
}
if (EVENT->seat_client == g_pCompositor->m_sSeat.seat->pointer_state.focused_client)
wlr_cursor_set_surface(g_pCompositor->m_sWLRCursor, EVENT->surface, EVENT->hotspot_x, EVENT->hotspot_y);
g_pInputManager->processMouseRequest(EVENT);
}
void Events::listener_newInput(wl_listener* listener, void* data) {

View file

@ -36,7 +36,7 @@ void Events::listener_newLayerSurface(wl_listener* listener, void* data) {
SLayerSurface* layerSurface = PMONITOR->m_aLayerSurfaceLists[WLRLAYERSURFACE->pending.layer].back();
if (!WLRLAYERSURFACE->output) {
WLRLAYERSURFACE->output = g_pCompositor->m_lMonitors.front().output; // TODO: current mon
WLRLAYERSURFACE->output = g_pCompositor->m_vMonitors.front()->output; // TODO: current mon
}
layerSurface->hyprListener_commitLayerSurface.initCallback(&WLRLAYERSURFACE->surface->events.commit, &Events::listener_commitLayerSurface, layerSurface, "layerSurface");
@ -145,7 +145,7 @@ void Events::listener_unmapLayerSurface(void* owner, void* data) {
layersurface->fadingOut = true;
g_pCompositor->m_lSurfacesFadingOut.push_back(layersurface);
g_pCompositor->m_vSurfacesFadingOut.push_back(layersurface);
if (layersurface->layerSurface->mapped)
layersurface->layerSurface->mapped = false;
@ -179,7 +179,7 @@ void Events::listener_commitLayerSurface(void* owner, void* data) {
if (!PMONITOR)
return;
wlr_box geomFixed = {layersurface->geometry.x + PMONITOR->vecPosition.x, layersurface->geometry.y + PMONITOR->vecPosition.y, layersurface->geometry.width, layersurface->geometry.height};
wlr_box geomFixed = {layersurface->geometry.x, layersurface->geometry.y, layersurface->geometry.width, layersurface->geometry.height};
g_pHyprRenderer->damageBox(&geomFixed);
// fix if it changed its mon
@ -206,6 +206,5 @@ void Events::listener_commitLayerSurface(void* owner, void* data) {
layersurface->position = Vector2D(layersurface->geometry.x, layersurface->geometry.y);
// TODO: optimize this. This does NOT need to be here but it prevents some issues with full DT.
g_pHyprRenderer->damageMonitor(PMONITOR);
g_pHyprRenderer->damageSurface(layersurface->layerSurface->surface, layersurface->position.x, layersurface->position.y);
}

View file

@ -21,24 +21,24 @@ void Events::listener_change(wl_listener* listener, void* data) {
// layout got changed, let's update monitors.
const auto CONFIG = wlr_output_configuration_v1_create();
for (auto& m : g_pCompositor->m_lMonitors) {
const auto CONFIGHEAD = wlr_output_configuration_head_v1_create(CONFIG, m.output);
for (auto& m : g_pCompositor->m_vMonitors) {
const auto CONFIGHEAD = wlr_output_configuration_head_v1_create(CONFIG, m->output);
// TODO: clients off of disabled
wlr_box BOX;
wlr_output_layout_get_box(g_pCompositor->m_sWLROutputLayout, m.output, &BOX);
wlr_output_layout_get_box(g_pCompositor->m_sWLROutputLayout, m->output, &BOX);
//m.vecSize.x = BOX.width;
// m.vecSize.y = BOX.height;
m.vecPosition.x = BOX.x;
m.vecPosition.y = BOX.y;
//m->vecSize.x = BOX.width;
// m->vecSize.y = BOX.height;
m->vecPosition.x = BOX.x;
m->vecPosition.y = BOX.y;
CONFIGHEAD->state.enabled = m.output->enabled;
CONFIGHEAD->state.mode = m.output->current_mode;
CONFIGHEAD->state.x = m.vecPosition.x;
CONFIGHEAD->state.y = m.vecPosition.y;
CONFIGHEAD->state.enabled = m->output->enabled;
CONFIGHEAD->state.mode = m->output->current_mode;
CONFIGHEAD->state.x = m->vecPosition.x;
CONFIGHEAD->state.y = m->vecPosition.y;
wlr_output_set_custom_mode(m.output, m.vecPixelSize.x, m.vecPixelSize.y, (int)(round(m.refreshRate * 1000)));
wlr_output_set_custom_mode(m->output, m->vecPixelSize.x, m->vecPixelSize.y, (int)(round(m->refreshRate * 1000)));
}
wlr_output_manager_v1_set_configuration(g_pCompositor->m_sWLROutputMgr, CONFIG);
@ -90,8 +90,7 @@ void Events::listener_newOutput(wl_listener* listener, void* data) {
newMonitor.vecSize = monitorRule.resolution;
newMonitor.refreshRate = monitorRule.refreshRate;
g_pCompositor->m_lMonitors.push_back(newMonitor);
const auto PNEWMONITOR = &g_pCompositor->m_lMonitors.back();
const auto PNEWMONITOR = g_pCompositor->m_vMonitors.emplace_back(std::make_unique<SMonitor>(newMonitor)).get();
PNEWMONITOR->hyprListener_monitorFrame.initCallback(&OUTPUT->events.frame, &Events::listener_monitorFrame, PNEWMONITOR);
PNEWMONITOR->hyprListener_monitorDestroy.initCallback(&OUTPUT->events.destroy, &Events::listener_monitorDestroy, PNEWMONITOR);
@ -115,10 +114,10 @@ void Events::listener_newOutput(wl_listener* listener, void* data) {
// Workspace
std::string newDefaultWorkspaceName = "";
auto WORKSPACEID = monitorRule.defaultWorkspace == "" ? g_pCompositor->m_lWorkspaces.size() + 1 : getWorkspaceIDFromString(monitorRule.defaultWorkspace, newDefaultWorkspaceName);
auto WORKSPACEID = monitorRule.defaultWorkspace == "" ? g_pCompositor->m_vWorkspaces.size() + 1 : getWorkspaceIDFromString(monitorRule.defaultWorkspace, newDefaultWorkspaceName);
if (WORKSPACEID == INT_MAX || WORKSPACEID == (long unsigned int)SPECIAL_WORKSPACE_ID) {
WORKSPACEID = g_pCompositor->m_lWorkspaces.size() + 1;
WORKSPACEID = g_pCompositor->m_vWorkspaces.size() + 1;
newDefaultWorkspaceName = std::to_string(WORKSPACEID);
Debug::log(LOG, "Invalid workspace= directive name in monitor parsing, workspace name \"%s\" is invalid.", monitorRule.defaultWorkspace);
@ -135,13 +134,12 @@ void Events::listener_newOutput(wl_listener* listener, void* data) {
g_pLayoutManager->getCurrentLayout()->recalculateMonitor(PNEWMONITOR->ID);
PNEWWORKSPACE->startAnim(true,true,true);
} else {
PNEWWORKSPACE = &g_pCompositor->m_lWorkspaces.emplace_back(newMonitor.ID);
PNEWWORKSPACE = g_pCompositor->m_vWorkspaces.emplace_back(std::make_unique<CWorkspace>(newMonitor.ID, newDefaultWorkspaceName)).get();
// We are required to set the name here immediately
wlr_ext_workspace_handle_v1_set_name(PNEWWORKSPACE->m_pWlrHandle, newDefaultWorkspaceName.c_str());
PNEWWORKSPACE->m_iID = WORKSPACEID;
PNEWWORKSPACE->m_szName = newDefaultWorkspaceName;
}
PNEWMONITOR->activeWorkspace = PNEWWORKSPACE->m_iID;
@ -174,6 +172,9 @@ void Events::listener_monitorFrame(void* owner, void* data) {
static auto *const PDEBUGOVERLAY = &g_pConfigManager->getConfigValuePtr("debug:overlay")->intValue;
static auto *const PDAMAGETRACKINGMODE = &g_pConfigManager->getConfigValuePtr("general:damage_tracking_internal")->intValue;
static auto *const PDAMAGEBLINK = &g_pConfigManager->getConfigValuePtr("debug:damage_blink")->intValue;
static int damageBlinkCleanup = 0; // because double-buffered
if (*PDEBUGOVERLAY == 1) {
startRender = std::chrono::high_resolution_clock::now();
@ -227,7 +228,7 @@ void Events::listener_monitorFrame(void* owner, void* data) {
return;
}
if (!hasChanged && *PDAMAGETRACKINGMODE != DAMAGE_TRACKING_NONE && PMONITOR->forceFullFrames == 0) {
if (!hasChanged && *PDAMAGETRACKINGMODE != DAMAGE_TRACKING_NONE && PMONITOR->forceFullFrames == 0 && damageBlinkCleanup == 0) {
pixman_region32_fini(&damage);
wlr_output_rollback(PMONITOR->output);
wlr_output_schedule_frame(PMONITOR->output); // we update shit at the monitor's Hz so we need to schedule frames because rollback wont
@ -235,7 +236,7 @@ void Events::listener_monitorFrame(void* owner, void* data) {
}
// if we have no tracking or full tracking, invalidate the entire monitor
if (*PDAMAGETRACKINGMODE == DAMAGE_TRACKING_NONE || *PDAMAGETRACKINGMODE == DAMAGE_TRACKING_MONITOR || PMONITOR->forceFullFrames > 0) {
if (*PDAMAGETRACKINGMODE == DAMAGE_TRACKING_NONE || *PDAMAGETRACKINGMODE == DAMAGE_TRACKING_MONITOR || PMONITOR->forceFullFrames > 0 || damageBlinkCleanup > 0) {
pixman_region32_union_rect(&damage, &damage, 0, 0, (int)PMONITOR->vecTransformedSize.x, (int)PMONITOR->vecTransformedSize.y);
pixman_region32_copy(&g_pHyprOpenGL->m_rOriginalDamageRegion, &damage);
@ -281,6 +282,16 @@ void Events::listener_monitorFrame(void* owner, void* data) {
endRenderOverlay = std::chrono::high_resolution_clock::now();
}
if (*PDAMAGEBLINK && damageBlinkCleanup == 0) {
wlr_box monrect = {0, 0, PMONITOR->vecPixelSize.x, PMONITOR->vecPixelSize.y};
g_pHyprOpenGL->renderRect(&monrect, CColor(255,0,255,100), 0);
damageBlinkCleanup = 1;
} else if (*PDAMAGEBLINK) {
damageBlinkCleanup++;
if (damageBlinkCleanup > 3)
damageBlinkCleanup = 0;
}
wlr_renderer_begin(g_pCompositor->m_sWLRRenderer, PMONITOR->vecPixelSize.x, PMONITOR->vecPixelSize.y);
wlr_output_render_software_cursors(PMONITOR->output, NULL);
@ -299,6 +310,9 @@ void Events::listener_monitorFrame(void* owner, void* data) {
if (*PDAMAGETRACKINGMODE == DAMAGE_TRACKING_NONE || *PDAMAGETRACKINGMODE == DAMAGE_TRACKING_MONITOR)
pixman_region32_union_rect(&frameDamage, &frameDamage, 0, 0, (int)PMONITOR->vecTransformedSize.x, (int)PMONITOR->vecTransformedSize.y);
if (*PDAMAGEBLINK)
pixman_region32_union(&frameDamage, &frameDamage, &damage);
wlr_output_set_damage(PMONITOR->output, &frameDamage);
pixman_region32_fini(&frameDamage);
pixman_region32_fini(&damage);
@ -324,9 +338,9 @@ void Events::listener_monitorDestroy(void* owner, void* data) {
SMonitor* pMonitor = nullptr;
for (auto& m : g_pCompositor->m_lMonitors) {
if (m.szName == OUTPUT->name) {
pMonitor = &m;
for (auto& m : g_pCompositor->m_vMonitors) {
if (m->szName == OUTPUT->name) {
pMonitor = m.get();
break;
}
}
@ -335,7 +349,7 @@ void Events::listener_monitorDestroy(void* owner, void* data) {
return;
// Cleanup everything. Move windows back, snap cursor, shit.
const auto BACKUPMON = &g_pCompositor->m_lMonitors.front();
const auto BACKUPMON = g_pCompositor->m_vMonitors.front().get();
if (!BACKUPMON) {
Debug::log(CRIT, "No monitors! Unplugged last! Exiting.");
@ -351,9 +365,9 @@ void Events::listener_monitorDestroy(void* owner, void* data) {
// move workspaces
std::deque<CWorkspace*> wspToMove;
for (auto& w : g_pCompositor->m_lWorkspaces) {
if (w.m_iMonitorID == pMonitor->ID) {
wspToMove.push_back(&w);
for (auto& w : g_pCompositor->m_vWorkspaces) {
if (w->m_iMonitorID == pMonitor->ID) {
wspToMove.push_back(w.get());
}
}
@ -364,27 +378,23 @@ void Events::listener_monitorDestroy(void* owner, void* data) {
pMonitor->activeWorkspace = -1;
for (auto it = g_pCompositor->m_lWorkspaces.begin(); it != g_pCompositor->m_lWorkspaces.end(); ++it) {
if (it->m_iMonitorID == pMonitor->ID) {
it = g_pCompositor->m_lWorkspaces.erase(it);
}
}
g_pCompositor->m_vWorkspaces.erase(std::remove_if(g_pCompositor->m_vWorkspaces.begin(), g_pCompositor->m_vWorkspaces.end(), [&](std::unique_ptr<CWorkspace>& el) { return el->m_iMonitorID == pMonitor->ID; }));
Debug::log(LOG, "Removed monitor %s!", pMonitor->szName.c_str());
g_pEventManager->postEvent(SHyprIPCEvent("monitorremoved", pMonitor->szName));
g_pCompositor->m_lMonitors.remove(*pMonitor);
g_pCompositor->m_vMonitors.erase(std::remove_if(g_pCompositor->m_vMonitors.begin(), g_pCompositor->m_vMonitors.end(), [&](std::unique_ptr<SMonitor>& el) { return el.get() == pMonitor; }));
// update the pMostHzMonitor
if (pMostHzMonitor == pMonitor) {
int mostHz = 0;
SMonitor* pMonitorMostHz = nullptr;
for (auto& m : g_pCompositor->m_lMonitors) {
if (m.refreshRate > mostHz) {
pMonitorMostHz = &m;
mostHz = m.refreshRate;
for (auto& m : g_pCompositor->m_vMonitors) {
if (m->refreshRate > mostHz) {
pMonitorMostHz = m.get();
mostHz = m->refreshRate;
}
}

View file

@ -76,8 +76,7 @@ void Events::listener_newPopup(void* owner, void* data) {
const auto WLRPOPUP = (wlr_xdg_popup*)data;
g_pCompositor->m_lXDGPopups.push_back(SXDGPopup());
const auto PNEWPOPUP = &g_pCompositor->m_lXDGPopups.back();
const auto PNEWPOPUP = g_pCompositor->m_vXDGPopups.emplace_back(std::make_unique<SXDGPopup>()).get();
const auto PMONITOR = g_pCompositor->getMonitorFromID(layersurface->monitorID);
@ -97,8 +96,7 @@ void Events::listener_newPopupXDG(void* owner, void* data) {
const auto WLRPOPUP = (wlr_xdg_popup*)data;
g_pCompositor->m_lXDGPopups.push_back(SXDGPopup());
const auto PNEWPOPUP = &g_pCompositor->m_lXDGPopups.back();
const auto PNEWPOPUP = g_pCompositor->m_vXDGPopups.emplace_back(std::make_unique<SXDGPopup>()).get();
const auto PMONITOR = g_pCompositor->getMonitorFromID(PWINDOW->m_iMonitorID);
@ -122,8 +120,7 @@ void Events::listener_newPopupFromPopupXDG(void* owner, void* data) {
const auto WLRPOPUP = (wlr_xdg_popup*)data;
g_pCompositor->m_lXDGPopups.push_back(SXDGPopup());
const auto PNEWPOPUP = &g_pCompositor->m_lXDGPopups.back();
const auto PNEWPOPUP = g_pCompositor->m_vXDGPopups.emplace_back(std::make_unique<SXDGPopup>()).get();
PNEWPOPUP->popup = WLRPOPUP;
PNEWPOPUP->parentPopup = PPOPUP;
@ -170,5 +167,5 @@ void Events::listener_destroyPopupXDG(void* owner, void* data) {
PPOPUP->pSurfaceTree = nullptr;
}
g_pCompositor->m_lXDGPopups.remove(*PPOPUP);
g_pCompositor->m_vXDGPopups.erase(std::remove_if(g_pCompositor->m_vXDGPopups.begin(), g_pCompositor->m_vXDGPopups.end(), [&](std::unique_ptr<SXDGPopup>& el) { return el.get() == PPOPUP; }));
}

View file

@ -43,6 +43,9 @@ void Events::listener_mapWindow(void* owner, void* data) {
PWINDOW->m_szTitle = g_pXWaylandManager->getTitle(PWINDOW);
PWINDOW->m_fAlpha = 255.f;
if (PWINDOW->m_iX11Type == 2)
g_pCompositor->moveUnmanagedX11ToWindows(PWINDOW);
// Set all windows tiled regardless of anything
g_pXWaylandManager->setWindowStyleTiled(PWINDOW, WLR_EDGE_LEFT | WLR_EDGE_RIGHT | WLR_EDGE_TOP | WLR_EDGE_BOTTOM);
@ -57,7 +60,7 @@ void Events::listener_mapWindow(void* owner, void* data) {
const auto PWINDOWSURFACE = g_pXWaylandManager->getWindowSurface(PWINDOW);
if (!PWINDOWSURFACE) {
g_pCompositor->m_lWindows.remove(*PWINDOW);
g_pCompositor->removeWindowFromVectorSafe(PWINDOW);
return;
}
@ -97,7 +100,7 @@ void Events::listener_mapWindow(void* owner, void* data) {
PWINDOW->m_iMonitorID = PMONITOR->ID;
} else {
const long int MONITOR = std::stoi(MONITORSTR);
if (MONITOR >= (long int)g_pCompositor->m_lMonitors.size() || MONITOR < (long int)0)
if (MONITOR >= (long int)g_pCompositor->m_vMonitors.size() || MONITOR < (long int)0)
PWINDOW->m_iMonitorID = 0;
else
PWINDOW->m_iMonitorID = MONITOR;
@ -228,11 +231,9 @@ void Events::listener_mapWindow(void* owner, void* data) {
PWINDOW->m_vPseudoSize = PWINDOW->m_vRealSize.goalv() - Vector2D(10,10);
}
if (!PWINDOW->m_bNoFocus)
if (!PWINDOW->m_bNoFocus && !PWINDOW->m_bNoInitialFocus)
g_pCompositor->focusWindow(PWINDOW);
PWINDOW->m_pSurfaceTree = SubsurfaceTree::createTreeRoot(g_pXWaylandManager->getWindowSurface(PWINDOW), addViewCoords, PWINDOW, PWINDOW);
Debug::log(LOG, "Window got assigned a surfaceTreeNode %x", PWINDOW->m_pSurfaceTree);
if (!PWINDOW->m_bIsX11) {
@ -260,16 +261,25 @@ void Events::listener_mapWindow(void* owner, void* data) {
}
if (requestsFullscreen) {
// fix fullscreen on requested (basically do a switcheroo)
if (PWORKSPACE->m_bHasFullscreenWindow) {
const auto PFULLWINDOW = g_pCompositor->getFullscreenWindowOnWorkspace(PWORKSPACE->m_iID);
g_pLayoutManager->getCurrentLayout()->fullscreenRequestForWindow(PFULLWINDOW, FULLSCREEN_FULL, false);
g_pXWaylandManager->setWindowFullscreen(PFULLWINDOW, PFULLWINDOW->m_bIsFullscreen);
}
g_pCompositor->setWindowFullscreen(PWINDOW, true, FULLSCREEN_FULL);
}
PWINDOW->m_pSurfaceTree = SubsurfaceTree::createTreeRoot(g_pXWaylandManager->getWindowSurface(PWINDOW), addViewCoords, PWINDOW, PWINDOW);
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);
}
void Events::listener_unmapWindow(void* owner, void* data) {
CWindow* PWINDOW = (CWindow*)owner;
Debug::log(LOG, "Window %x unmapped", PWINDOW);
Debug::log(LOG, "Window %x unmapped (class %s)", PWINDOW, g_pXWaylandManager->getAppIDClass(PWINDOW).c_str());
if (!PWINDOW->m_bIsX11) {
Debug::log(LOG, "Unregistered late callbacks XDG: %x %x %x %x", &PWINDOW->hyprListener_commitWindow.m_sListener.link, &PWINDOW->hyprListener_setTitleWindow.m_sListener.link, &PWINDOW->hyprListener_fullscreenWindow.m_sListener.link, &PWINDOW->hyprListener_newPopupXDG.m_sListener.link);
@ -285,6 +295,11 @@ void Events::listener_unmapWindow(void* owner, void* data) {
PWINDOW->hyprListener_setTitleWindow.removeCallback();
}
if (PWINDOW->m_bIsFullscreen) {
g_pLayoutManager->getCurrentLayout()->fullscreenRequestForWindow(PWINDOW, FULLSCREEN_FULL, false);
g_pXWaylandManager->setWindowFullscreen(PWINDOW, PWINDOW->m_bIsFullscreen);
}
// Allow the renderer to catch the last frame.
g_pHyprOpenGL->makeWindowSnapshot(PWINDOW);
@ -318,12 +333,14 @@ void Events::listener_unmapWindow(void* owner, void* data) {
PWINDOW->m_bFadingOut = true;
g_pCompositor->m_lWindowsFadingOut.push_back(PWINDOW);
g_pCompositor->m_vWindowsFadingOut.emplace_back(PWINDOW);
g_pHyprRenderer->damageMonitor(g_pCompositor->getMonitorFromID(PWINDOW->m_iMonitorID));
const auto PMONITOR = g_pCompositor->getMonitorFromID(PWINDOW->m_iMonitorID);
// do the animation thing
PWINDOW->m_vOriginalClosedPos = PWINDOW->m_vRealPosition.vec();
PWINDOW->m_vOriginalClosedPos = PWINDOW->m_vRealPosition.vec() - PMONITOR->vecPosition;
PWINDOW->m_vOriginalClosedSize = PWINDOW->m_vRealSize.vec();
if (!PWINDOW->m_bX11DoesntWantBorders) // don't animate out if they weren't animated in.
@ -347,7 +364,10 @@ void Events::listener_commitWindow(void* owner, void* data) {
void Events::listener_destroyWindow(void* owner, void* data) {
CWindow* PWINDOW = (CWindow*)owner;
Debug::log(LOG, "Window %x destroyed, queueing.", PWINDOW);
Debug::log(LOG, "Window %x destroyed, queueing. (class %s)", PWINDOW, g_pXWaylandManager->getAppIDClass(PWINDOW).c_str());
if (PWINDOW->m_bIsX11)
Debug::log(LOG, "XWayland class raw: %s", PWINDOW->m_uSurface.xwayland->_class);
if (PWINDOW == g_pCompositor->m_pLastWindow) {
g_pCompositor->m_pLastWindow = nullptr;
@ -393,9 +413,9 @@ void Events::listener_fullscreenWindow(void* owner, void* data) {
const auto REQUESTED = &PWINDOW->m_uSurface.xdg->toplevel->requested;
if (REQUESTED->fullscreen != PWINDOW->m_bIsFullscreen)
g_pLayoutManager->getCurrentLayout()->fullscreenRequestForWindow(PWINDOW, FULLSCREEN_FULL, true);
g_pLayoutManager->getCurrentLayout()->fullscreenRequestForWindow(PWINDOW, FULLSCREEN_FULL, REQUESTED->fullscreen);
} else {
g_pLayoutManager->getCurrentLayout()->fullscreenRequestForWindow(PWINDOW, FULLSCREEN_FULL, true);
g_pLayoutManager->getCurrentLayout()->fullscreenRequestForWindow(PWINDOW, FULLSCREEN_FULL, !PWINDOW->m_bIsFullscreen);
}
Debug::log(LOG, "Window %x fullscreen to %i", PWINDOW, PWINDOW->m_bIsFullscreen);
@ -455,15 +475,18 @@ void Events::listener_configureX11(void* owner, void* data) {
void Events::listener_surfaceXWayland(wl_listener* listener, void* data) {
const auto XWSURFACE = (wlr_xwayland_surface*)data;
Debug::log(LOG, "New XWayland Surface created.");
Debug::log(LOG, "New XWayland Surface created (class %s).", XWSURFACE->_class);
if (XWSURFACE->parent)
Debug::log(LOG, "Window parent data: %s at %x", XWSURFACE->parent->_class, XWSURFACE->parent);
g_pCompositor->m_lWindows.emplace_back();
const auto PNEWWINDOW = &g_pCompositor->m_lWindows.back();
const auto PNEWWINDOW = XWSURFACE->override_redirect ? g_pCompositor->m_dUnmanagedX11Windows.emplace_back(std::make_unique<CWindow>()).get() : g_pCompositor->m_vWindows.emplace_back(std::make_unique<CWindow>()).get();
PNEWWINDOW->m_uSurface.xwayland = XWSURFACE;
PNEWWINDOW->m_iX11Type = XWSURFACE->override_redirect ? 2 : 1;
PNEWWINDOW->m_bIsX11 = true;
PNEWWINDOW->m_pX11Parent = g_pCompositor->getX11Parent(PNEWWINDOW);
PNEWWINDOW->hyprListener_mapWindow.initCallback(&XWSURFACE->events.map, &Events::listener_mapWindow, PNEWWINDOW, "XWayland Window");
PNEWWINDOW->hyprListener_unmapWindow.initCallback(&XWSURFACE->events.unmap, &Events::listener_unmapWindow, PNEWWINDOW, "XWayland Window");
PNEWWINDOW->hyprListener_destroyWindow.initCallback(&XWSURFACE->events.destroy, &Events::listener_destroyWindow, PNEWWINDOW, "XWayland Window");
@ -473,13 +496,12 @@ void Events::listener_newXDGSurface(wl_listener* listener, void* data) {
// A window got opened
const auto XDGSURFACE = (wlr_xdg_surface*)data;
Debug::log(LOG, "New XDG Surface created. (%ix%i at %i %i)", XDGSURFACE->current.geometry.width, XDGSURFACE->current.geometry.height, XDGSURFACE->current.geometry.x, XDGSURFACE->current.geometry.y);
Debug::log(LOG, "New XDG Surface created. (class: %s)", XDGSURFACE->toplevel->app_id);
if (XDGSURFACE->role != WLR_XDG_SURFACE_ROLE_TOPLEVEL)
return; // TODO: handle?
g_pCompositor->m_lWindows.emplace_back();
const auto PNEWWINDOW = &g_pCompositor->m_lWindows.back();
const auto PNEWWINDOW = g_pCompositor->m_vWindows.emplace_back(std::make_unique<CWindow>()).get();
PNEWWINDOW->m_uSurface.xdg = XDGSURFACE;
PNEWWINDOW->hyprListener_mapWindow.initCallback(&XDGSURFACE->events.map, &Events::listener_mapWindow, PNEWWINDOW, "XDG Window");

View file

@ -33,56 +33,47 @@ public:
// gets the current vector value (real time)
const Vector2D& vec() const {
RASSERT(m_eVarType == AVARTYPE_VECTOR, "Tried to access vec() of AVARTYPE %i!", m_eVarType);
return m_vValue;
}
// gets the current float value (real time)
const float& fl() const {
RASSERT(m_eVarType == AVARTYPE_FLOAT, "Tried to access fl() of AVARTYPE %i!", m_eVarType);
return m_fValue;
}
// gets the current color value (real time)
const CColor& col() const {
RASSERT(m_eVarType == AVARTYPE_COLOR, "Tried to access col() of AVARTYPE %i!", m_eVarType);
return m_cValue;
}
// gets the goal vector value
const Vector2D& goalv() const {
RASSERT(m_eVarType == AVARTYPE_VECTOR, "Tried to access goalv() of AVARTYPE %i!", m_eVarType);
return m_vGoal;
}
// gets the goal float value
const float& goalf() const {
RASSERT(m_eVarType == AVARTYPE_FLOAT, "Tried to access goalf() of AVARTYPE %i!", m_eVarType);
return m_fGoal;
}
// gets the goal color value
const CColor& goalc() const {
RASSERT(m_eVarType == AVARTYPE_COLOR, "Tried to access goalc() of AVARTYPE %i!", m_eVarType);
return m_cGoal;
}
void operator=(const Vector2D& v) {
RASSERT(m_eVarType == AVARTYPE_VECTOR, "Tried to access =v of AVARTYPE %i!", m_eVarType);
m_vGoal = v;
animationBegin = std::chrono::system_clock::now();
m_vBegun = m_vValue;
}
void operator=(const float& v) {
RASSERT(m_eVarType == AVARTYPE_FLOAT, "Tried to access =f of AVARTYPE %i!", m_eVarType);
m_fGoal = v;
animationBegin = std::chrono::system_clock::now();
m_fBegun = m_fValue;
}
void operator=(const CColor& v) {
RASSERT(m_eVarType == AVARTYPE_COLOR, "Tried to access =c of AVARTYPE %i!", m_eVarType);
m_cGoal = v;
animationBegin = std::chrono::system_clock::now();
m_cBegun = m_cValue;
@ -90,7 +81,6 @@ public:
// Sets the actual stored value, without affecting the goal, but resets the timer
void setValue(const Vector2D& v) {
RASSERT(m_eVarType == AVARTYPE_VECTOR, "Tried to access setValue(v) of AVARTYPE %i!", m_eVarType);
m_vValue = v;
animationBegin = std::chrono::system_clock::now();
m_vBegun = m_vValue;
@ -98,7 +88,6 @@ public:
// Sets the actual stored value, without affecting the goal, but resets the timer
void setValue(const float& v) {
RASSERT(m_eVarType == AVARTYPE_FLOAT, "Tried to access setValue(f) of AVARTYPE %i!", m_eVarType);
m_fValue = v;
animationBegin = std::chrono::system_clock::now();
m_vBegun = m_vValue;
@ -106,7 +95,6 @@ public:
// Sets the actual stored value, without affecting the goal, but resets the timer
void setValue(const CColor& v) {
RASSERT(m_eVarType == AVARTYPE_COLOR, "Tried to access setValue(c) of AVARTYPE %i!", m_eVarType);
m_cValue = v;
animationBegin = std::chrono::system_clock::now();
m_vBegun = m_vValue;
@ -114,21 +102,18 @@ public:
// Sets the actual value and goal
void setValueAndWarp(const Vector2D& v) {
RASSERT(m_eVarType == AVARTYPE_VECTOR, "Tried to access setValueAndWarp(v) of AVARTYPE %i!", m_eVarType);
m_vGoal = v;
warp();
}
// Sets the actual value and goal
void setValueAndWarp(const float& v) {
RASSERT(m_eVarType == AVARTYPE_FLOAT, "Tried to access setValueAndWarp(f) of AVARTYPE %i!", m_eVarType);
m_fGoal = v;
warp();
}
// Sets the actual value and goal
void setValueAndWarp(const CColor& v) {
RASSERT(m_eVarType == AVARTYPE_COLOR, "Tried to access setValueAndWarp(c) of AVARTYPE %i!", m_eVarType);
m_cGoal = v;
warp();
}

View file

@ -4,6 +4,41 @@
#include "../Compositor.hpp"
#include <sys/utsname.h>
static const float transforms[][9] = {{
1.0f, 0.0f, 0.0f,
0.0f, 1.0f, 0.0f,
0.0f, 0.0f, 1.0f,
},{
0.0f, 1.0f, 0.0f,
-1.0f, 0.0f, 0.0f,
0.0f, 0.0f, 1.0f,
},{
-1.0f, 0.0f, 0.0f,
0.0f, -1.0f, 0.0f,
0.0f, 0.0f, 1.0f,
},{
0.0f, -1.0f, 0.0f,
1.0f, 0.0f, 0.0f,
0.0f, 0.0f, 1.0f,
},{
-1.0f, 0.0f, 0.0f,
0.0f, 1.0f, 0.0f,
0.0f, 0.0f, 1.0f,
},{
0.0f, 1.0f, 0.0f,
1.0f, 0.0f, 0.0f,
0.0f, 0.0f, 1.0f,
},{
1.0f, 0.0f, 0.0f,
0.0f, -1.0f, 0.0f,
0.0f, 0.0f, 1.0f,
},{
0.0f, -1.0f, 0.0f,
-1.0f, 0.0f, 0.0f,
0.0f, 0.0f, 1.0f,
},
};
void addWLSignal(wl_signal* pSignal, wl_listener* pListener, void* pOwner, std::string ownerString) {
ASSERT(pSignal);
ASSERT(pListener);
@ -79,8 +114,8 @@ std::string getFormat(const char *fmt, ...) {
}
void scaleBox(wlr_box* box, float scale) {
box->width = std::round((box->x + box->width) * scale) - std::round(box->x * scale);
box->height = std::round((box->y + box->height) * scale) - std::round(box->y * scale);
box->width = std::round(box->width * scale);
box->height = std::round(box->height * scale);
box->x = std::round(box->x * scale);
box->y = std::round(box->y * scale);
}
@ -135,8 +170,8 @@ float getPlusMinusKeywordResult(std::string source, float relative) {
return result;
}
bool isNumber(const std::string& str) {
return std::ranges::all_of(str.begin(), str.end(), [](char c) { return isdigit(c) != 0 || c == '-'; });
bool isNumber(const std::string& str, bool allowfloat) {
return std::ranges::all_of(str.begin(), str.end(), [&](char c) { return isdigit(c) != 0 || c == '-' || (allowfloat && c == '.'); });
}
bool isDirection(const std::string& arg) {
@ -184,12 +219,12 @@ int getWorkspaceIDFromString(const std::string& in, std::string& outName) {
int lowestID = 99999;
int highestID = -99999;
for (auto& w : g_pCompositor->m_lWorkspaces) {
if (w.m_iID < lowestID)
lowestID = w.m_iID;
for (auto& w : g_pCompositor->m_vWorkspaces) {
if (w->m_iID < lowestID)
lowestID = w->m_iID;
if (w.m_iID > highestID)
highestID = w.m_iID;
if (w->m_iID > highestID)
highestID = w->m_iID;
}
if (remains < 0)
@ -264,4 +299,25 @@ void logSystemInfo() {
Debug::log(LOG, "os-release:");
Debug::log(NONE, "%s", execAndGet("cat /etc/os-release").c_str());
}
}
void matrixProjection(float mat[9], int w, int h, wl_output_transform tr) {
memset(mat, 0, sizeof(*mat) * 9);
const float* t = transforms[tr];
float x = 2.0f / w;
float y = 2.0f / h;
// Rotation + reflection
mat[0] = x * t[0];
mat[1] = x * t[1];
mat[3] = y * -t[3];
mat[4] = y * -t[4];
// Translation
mat[2] = -copysign(1.0f, mat[0] + mat[1]);
mat[5] = -copysign(1.0f, mat[3] + mat[4]);
// Identity
mat[8] = 1.0f;
}

View file

@ -7,11 +7,13 @@ void wlr_signal_emit_safe(struct wl_signal *signal, void *data);
std::string getFormat(const char *fmt, ...); // Basically Debug::log to a string
void scaleBox(wlr_box*, float);
std::string removeBeginEndSpacesTabs(std::string);
bool isNumber(const std::string&);
bool isNumber(const std::string&, bool allowfloat = false);
bool isDirection(const std::string&);
int getWorkspaceIDFromString(const std::string&, std::string&);
float vecToRectDistanceSquared(const Vector2D& vec, const Vector2D& p1, const Vector2D& p2);
void logSystemInfo();
std::string execAndGet(const char*);
float getPlusMinusKeywordResult(std::string in, float relative);
float getPlusMinusKeywordResult(std::string in, float relative);
void matrixProjection(float mat[9], int w, int h, wl_output_transform tr);

View file

@ -188,16 +188,27 @@ void Events::listener_commitSubsurface(void* owner, void* data) {
// no damaging if it's not visible
if (!g_pHyprRenderer->shouldRenderWindow(pNode->pWindowOwner)) {
if (g_pConfigManager->getInt("debug:log_damage"))
static auto* const PLOGDAMAGE = &g_pConfigManager->getConfigValuePtr("debug:log_damage")->intValue;
if (*PLOGDAMAGE)
Debug::log(LOG, "Refusing to commit damage from %x because it's invisible.", pNode->pWindowOwner);
return;
}
int lx = 0, ly = 0;
addSurfaceGlobalOffset(pNode, &lx, &ly);
// I do not think this is correct, but it solves a lot of issues with some apps (e.g. firefox)
// What this does is that basically, if the pNode is a child of some other node, on commit,
// it will also damage (check & damage if needed) all its siblings.
if (pNode->pParent) for (auto& cs : pNode->pParent->childSubsurfaces) {
const auto NODECOORDS = pNode->pSubsurface ? Vector2D(pNode->pSubsurface->pSubsurface->current.x, pNode->pSubsurface->pSubsurface->current.y) : Vector2D();
if (&cs != pNode->pSubsurface && cs.pSubsurface) {
g_pHyprRenderer->damageSurface(cs.pSubsurface->surface, lx - NODECOORDS.x + cs.pSubsurface->current.x, ly - NODECOORDS.y + cs.pSubsurface->current.y);
}
}
g_pHyprRenderer->damageSurface(pNode->pSurface, lx, ly);
}

View file

@ -71,7 +71,12 @@ struct SKeyboard {
bool active = false;
xkb_rule_names currentRules;
std::string name = "";
xkb_rule_names currentRules = {0};
int repeatRate = 0;
int repeatDelay = 0;
int numlockOn = -1;
// For the list lookup
bool operator==(const SKeyboard& rhs) {
@ -87,6 +92,8 @@ struct SMouse {
pixman_region32_t confinedTo;
std::string name = "";
DYNLISTENER(commitConstraint);
DYNLISTENER(destroyMouse);
@ -168,6 +175,8 @@ struct STablet {
wlr_tablet_v2_tablet* wlrTabletV2 = nullptr;
wlr_input_device* wlrDevice = nullptr;
std::string name = "";
bool operator==(const STablet& b) {
return wlrDevice == b.wlrDevice;
}
@ -186,6 +195,8 @@ struct STabletTool {
bool active = true;
std::string name = "";
DYNLISTENER(TabletToolDestroy);
DYNLISTENER(TabletToolSetCursor);
@ -198,6 +209,8 @@ struct STabletPad {
wlr_tablet_v2_tablet_pad* wlrTabletPadV2 = nullptr;
STablet* pTabletParent = nullptr;
std::string name = "";
DYNLISTENER(Attach);
DYNLISTENER(Button);
DYNLISTENER(Strip);

View file

@ -1,7 +1,7 @@
#include "Workspace.hpp"
#include "../Compositor.hpp"
CWorkspace::CWorkspace(int monitorID, bool special) {
CWorkspace::CWorkspace(int monitorID, std::string name, bool special) {
const auto PMONITOR = g_pCompositor->getMonitorFromID(monitorID);
if (!PMONITOR) {
@ -10,7 +10,7 @@ CWorkspace::CWorkspace(int monitorID, bool special) {
}
m_iMonitorID = monitorID;
m_szName = name;
m_bIsSpecialWorkspace = special;
if (!special) {
@ -30,6 +30,8 @@ CWorkspace::CWorkspace(int monitorID, bool special) {
m_fAlpha.m_pWorkspace = this;
m_fAlpha.create(AVARTYPE_FLOAT, &g_pConfigManager->getConfigValuePtr("animations:workspaces_speed")->floatValue, &g_pConfigManager->getConfigValuePtr("animations:workspaces")->intValue, &g_pConfigManager->getConfigValuePtr("animations:workspaces_curve")->strValue, nullptr, AVARDAMAGE_ENTIRE);
m_fAlpha.setValueAndWarp(255.f);
g_pEventManager->postEvent({"createworkspace", m_szName}, true);
}
CWorkspace::~CWorkspace() {
@ -42,6 +44,8 @@ CWorkspace::~CWorkspace() {
wlr_ext_workspace_handle_v1_destroy(m_pWlrHandle);
m_pWlrHandle = nullptr;
}
g_pEventManager->postEvent({"destroyworkspace", m_szName}, true);
}
void CWorkspace::startAnim(bool in, bool left, bool instant) {

View file

@ -10,7 +10,7 @@ enum eFullscreenMode : uint8_t {
class CWorkspace {
public:
CWorkspace(int monitorID, bool special = false);
CWorkspace(int monitorID, std::string name, bool special = false);
~CWorkspace();
// Workspaces ID-based have IDs > 0

View file

@ -12,7 +12,7 @@ void CHyprError::createQueued() {
m_tTexture.destroyTexture();
}
const auto PMONITOR = &g_pCompositor->m_lMonitors.front();
const auto PMONITOR = g_pCompositor->m_vMonitors.front().get();
const auto CAIROSURFACE = cairo_image_surface_create(CAIRO_FORMAT_ARGB32, PMONITOR->vecSize.x, PMONITOR->vecSize.y);
@ -95,11 +95,11 @@ void CHyprError::draw() {
m_tTexture.destroyTexture();
m_bIsCreated = false;
m_szQueued = "";
g_pHyprRenderer->damageMonitor(&g_pCompositor->m_lMonitors.front());
g_pHyprRenderer->damageMonitor(g_pCompositor->m_vMonitors.front().get());
return;
}
const auto PMONITOR = &g_pCompositor->m_lMonitors.front();
const auto PMONITOR = g_pCompositor->m_vMonitors.front().get();
if (g_pHyprOpenGL->m_RenderData.pMonitor != PMONITOR)
return; // wrong mon

View file

@ -88,6 +88,9 @@ extern "C" {
#include <wlr/types/wlr_pointer_constraints_v1.h>
#include <wlr/types/wlr_relative_pointer_v1.h>
#include <wlr/interfaces/wlr_keyboard.h>
#include <wlr/types/wlr_xdg_foreign_registry.h>
#include <wlr/types/wlr_xdg_foreign_v1.h>
#include <wlr/types/wlr_xdg_foreign_v2.h>
}
#undef class
@ -114,3 +117,5 @@ extern "C" {
#include "helpers/Vector2D.hpp"
#include "ext-workspace-unstable-v1-protocol.h"
#include <algorithm>

View file

@ -176,9 +176,11 @@ void CHyprDwindleLayout::applyNodeDataToWindow(SDwindleNodeData* pNode) {
g_pXWaylandManager->setWindowSize(PWINDOW, calcSize);
}
PWINDOW->updateWindowDecos();
}
void CHyprDwindleLayout::onWindowCreated(CWindow* pWindow) {
void CHyprDwindleLayout::onWindowCreatedTiling(CWindow* pWindow) {
if (pWindow->m_bIsFloating)
return;
@ -309,7 +311,7 @@ void CHyprDwindleLayout::onWindowCreated(CWindow* pWindow) {
}
}
void CHyprDwindleLayout::onWindowRemoved(CWindow* pWindow) {
void CHyprDwindleLayout::onWindowRemovedTiling(CWindow* pWindow) {
const auto PNODE = getNodeFromWindow(pWindow);
@ -399,145 +401,8 @@ void CHyprDwindleLayout::recalculateMonitor(const int& monid) {
}
}
void CHyprDwindleLayout::changeWindowFloatingMode(CWindow* pWindow) {
if (pWindow->m_bIsFullscreen) {
Debug::log(LOG, "Rejecting a change float order because window is fullscreen.");
// restore its' floating mode
pWindow->m_bIsFloating = !pWindow->m_bIsFloating;
return;
}
const auto PNODE = getNodeFromWindow(pWindow);
if (!PNODE) {
const auto PNEWMON = g_pCompositor->getMonitorFromVector(pWindow->m_vRealPosition.vec() + pWindow->m_vRealSize.vec() / 2.f);
pWindow->m_iMonitorID = PNEWMON->ID;
pWindow->m_iWorkspaceID = PNEWMON->activeWorkspace;
// save real pos cuz the func applies the default 5,5 mid
const auto PSAVEDPOS = pWindow->m_vRealPosition.vec();
const auto PSAVEDSIZE = pWindow->m_vRealSize.vec();
// if the window is pseudo, update its size
pWindow->m_vPseudoSize = pWindow->m_vRealSize.vec();
onWindowCreated(pWindow);
pWindow->m_vRealPosition.setValue(PSAVEDPOS);
pWindow->m_vRealSize.setValue(PSAVEDSIZE);
// fix pseudo leaving artifacts
g_pHyprRenderer->damageMonitor(g_pCompositor->getMonitorFromID(pWindow->m_iMonitorID));
} else {
onWindowRemoved(pWindow);
g_pCompositor->moveWindowToTop(pWindow);
}
}
void CHyprDwindleLayout::onBeginDragWindow() {
const auto DRAGGINGWINDOW = g_pInputManager->currentlyDraggedWindow;
m_vBeginDragSizeXY = Vector2D();
// Window will be floating. Let's check if it's valid. It should be, but I don't like crashing.
if (!g_pCompositor->windowValidMapped(DRAGGINGWINDOW)) {
Debug::log(ERR, "Dragging attempted on an invalid window!");
return;
}
if (DRAGGINGWINDOW->m_bIsFullscreen) {
Debug::log(LOG, "Rejecting drag on a fullscreen window.");
return;
}
const auto PWORKSPACE = g_pCompositor->getWorkspaceByID(DRAGGINGWINDOW->m_iWorkspaceID);
if (PWORKSPACE->m_bHasFullscreenWindow) {
Debug::log(LOG, "Rejecting drag on a fullscreen workspace.");
return;
}
DRAGGINGWINDOW->m_bDraggingTiled = false;
if (!DRAGGINGWINDOW->m_bIsFloating) {
if (g_pInputManager->dragButton == BTN_LEFT) {
changeWindowFloatingMode(DRAGGINGWINDOW);
DRAGGINGWINDOW->m_bIsFloating = true;
DRAGGINGWINDOW->m_bDraggingTiled = true;
}
}
m_vBeginDragXY = g_pInputManager->getMouseCoordsInternal();
m_vBeginDragPositionXY = DRAGGINGWINDOW->m_vRealPosition.vec();
m_vBeginDragSizeXY = DRAGGINGWINDOW->m_vRealSize.vec();
m_vLastDragXY = m_vBeginDragXY;
g_pHyprRenderer->damageWindow(DRAGGINGWINDOW);
}
void CHyprDwindleLayout::onEndDragWindow() {
const auto DRAGGINGWINDOW = g_pInputManager->currentlyDraggedWindow;
if (!g_pCompositor->windowValidMapped(DRAGGINGWINDOW))
return;
if (DRAGGINGWINDOW->m_bDraggingTiled) {
DRAGGINGWINDOW->m_bIsFloating = false;
changeWindowFloatingMode(DRAGGINGWINDOW);
}
g_pHyprRenderer->damageWindow(DRAGGINGWINDOW);
}
void CHyprDwindleLayout::onMouseMove(const Vector2D& mousePos) {
const auto DRAGGINGWINDOW = g_pInputManager->currentlyDraggedWindow;
// Window invalid or drag begin size 0,0 meaning we rejected it.
if (!g_pCompositor->windowValidMapped(DRAGGINGWINDOW) || m_vBeginDragSizeXY == Vector2D()) {
g_pInputManager->currentlyDraggedWindow = nullptr;
return;
}
const auto DELTA = Vector2D(mousePos.x - m_vBeginDragXY.x, mousePos.y - m_vBeginDragXY.y);
const auto TICKDELTA = Vector2D(mousePos.x - m_vLastDragXY.x, mousePos.y - m_vLastDragXY.y);
if (abs(TICKDELTA.x) < 1.f && abs(TICKDELTA.y) < 1.f)
return;
m_vLastDragXY = mousePos;
g_pHyprRenderer->damageWindow(DRAGGINGWINDOW);
if (g_pInputManager->dragButton == BTN_LEFT) {
DRAGGINGWINDOW->m_vRealPosition.setValueAndWarp(m_vBeginDragPositionXY + DELTA);
g_pXWaylandManager->setWindowSize(DRAGGINGWINDOW, DRAGGINGWINDOW->m_vRealSize.goalv());
} else {
if (DRAGGINGWINDOW->m_bIsFloating) {
DRAGGINGWINDOW->m_vRealSize.setValueAndWarp(m_vBeginDragSizeXY + DELTA);
DRAGGINGWINDOW->m_vRealSize.setValueAndWarp(Vector2D(std::clamp(DRAGGINGWINDOW->m_vRealSize.vec().x, (double)20, (double)999999), std::clamp(DRAGGINGWINDOW->m_vRealSize.vec().y, (double)20, (double)999999)));
g_pXWaylandManager->setWindowSize(DRAGGINGWINDOW, DRAGGINGWINDOW->m_vRealSize.goalv());
} else {
resizeActiveWindow(TICKDELTA, DRAGGINGWINDOW);
}
}
// get middle point
Vector2D middle = DRAGGINGWINDOW->m_vRealPosition.vec() + DRAGGINGWINDOW->m_vRealSize.vec() / 2.f;
// and check its monitor
const auto PMONITOR = g_pCompositor->getMonitorFromVector(middle);
if (PMONITOR) {
DRAGGINGWINDOW->m_iMonitorID = PMONITOR->ID;
DRAGGINGWINDOW->m_iWorkspaceID = PMONITOR->activeWorkspace;
}
g_pHyprRenderer->damageWindow(DRAGGINGWINDOW);
bool CHyprDwindleLayout::isWindowTiled(CWindow* pWindow) {
return getNodeFromWindow(pWindow) != nullptr;
}
void CHyprDwindleLayout::resizeActiveWindow(const Vector2D& pixResize, CWindow* pWindow) {
@ -551,6 +416,7 @@ void CHyprDwindleLayout::resizeActiveWindow(const Vector2D& pixResize, CWindow*
if (!PNODE) {
PWINDOW->m_vRealSize = Vector2D(std::clamp((PWINDOW->m_vRealSize.goalv() + pixResize).x, (double)20, (double)999999), std::clamp((PWINDOW->m_vRealSize.goalv() + pixResize).y, (double)20, (double)999999));
PWINDOW->updateWindowDecos();
return;
}
@ -627,55 +493,6 @@ void CHyprDwindleLayout::resizeActiveWindow(const Vector2D& pixResize, CWindow*
TOPCONTAINER->recalcSizePosRecursive();
}
void CHyprDwindleLayout::onWindowCreatedFloating(CWindow* pWindow) {
wlr_box desiredGeometry = {0};
g_pXWaylandManager->getGeometryForWindow(pWindow, &desiredGeometry);
const auto PMONITOR = g_pCompositor->getMonitorFromID(pWindow->m_iMonitorID);
if (!PMONITOR){
Debug::log(ERR, "Window %x (%s) has an invalid monitor in onWindowCreatedFloating!!!", pWindow, pWindow->m_szTitle.c_str());
return;
}
if (desiredGeometry.width <= 0 || desiredGeometry.height <= 0) {
const auto PWINDOWSURFACE = g_pXWaylandManager->getWindowSurface(pWindow);
pWindow->m_vRealSize = Vector2D(PWINDOWSURFACE->current.width, PWINDOWSURFACE->current.height);
pWindow->m_vRealPosition = Vector2D(PMONITOR->vecPosition.x + (PMONITOR->vecSize.x - pWindow->m_vRealSize.vec().x) / 2.f, PMONITOR->vecPosition.y + (PMONITOR->vecSize.y - pWindow->m_vRealSize.vec().y) / 2.f);
} else {
// we respect the size.
pWindow->m_vRealSize = Vector2D(desiredGeometry.width, desiredGeometry.height);
// check if it's on the correct monitor!
Vector2D middlePoint = Vector2D(desiredGeometry.x, desiredGeometry.y) + Vector2D(desiredGeometry.width, desiredGeometry.height) / 2.f;
// TODO: detect a popup in a more consistent way.
if (!g_pCompositor->isPointOnAnyMonitor(middlePoint) || (desiredGeometry.x == 0 && desiredGeometry.y == 0)) {
// if it's not, fall back to the center placement
pWindow->m_vRealPosition = PMONITOR->vecPosition + Vector2D((PMONITOR->vecSize.x - desiredGeometry.width) / 2.f, (PMONITOR->vecSize.y - desiredGeometry.height) / 2.f);
} else {
// if it is, we respect where it wants to put itself, but apply monitor offset if outside
// most of these are popups
if (const auto POPENMON = g_pCompositor->getMonitorFromVector(middlePoint); POPENMON->ID != PMONITOR->ID) {
pWindow->m_vRealPosition = Vector2D(desiredGeometry.x, desiredGeometry.y) - POPENMON->vecPosition + PMONITOR->vecPosition;
} else {
pWindow->m_vRealPosition = Vector2D(desiredGeometry.x, desiredGeometry.y);
}
}
}
if (pWindow->m_bX11DoesntWantBorders) {
pWindow->m_vRealPosition.setValue(pWindow->m_vRealPosition.goalv());
pWindow->m_vRealSize.setValue(pWindow->m_vRealSize.goalv());
}
g_pXWaylandManager->setWindowSize(pWindow, pWindow->m_vRealSize.goalv());
g_pCompositor->fixXWaylandWindowsOnWorkspace(PMONITOR->activeWorkspace);
g_pCompositor->moveWindowToTop(pWindow);
}
void CHyprDwindleLayout::fullscreenRequestForWindow(CWindow* pWindow, eFullscreenMode fullscreenMode, bool on) {
if (!g_pCompositor->windowValidMapped(pWindow))
return;
@ -731,6 +548,8 @@ void CHyprDwindleLayout::fullscreenRequestForWindow(CWindow* pWindow, eFullscree
fakeNode.position = PMONITOR->vecPosition + PMONITOR->vecReservedTopLeft;
fakeNode.size = PMONITOR->vecSize - PMONITOR->vecReservedTopLeft - PMONITOR->vecReservedBottomRight;
fakeNode.workspaceID = pWindow->m_iWorkspaceID;
pWindow->m_vPosition = fakeNode.position;
pWindow->m_vSize = fakeNode.size;
applyNodeDataToWindow(&fakeNode);
}
@ -1001,20 +820,4 @@ void CHyprDwindleLayout::toggleSplit(CWindow* pWindow) {
std::string CHyprDwindleLayout::getLayoutName() {
return "dwindle";
}
void CHyprDwindleLayout::moveActiveWindow(const Vector2D& delta, CWindow* pWindow) {
const auto PWINDOW = pWindow ? pWindow : g_pCompositor->m_pLastWindow;
if (!g_pCompositor->windowValidMapped(PWINDOW))
return;
if (!PWINDOW->m_bIsFloating) {
Debug::log(LOG, "Dwindle cannot move a tiled window in moveActiveWindow!");
return;
}
PWINDOW->m_vRealPosition = PWINDOW->m_vRealPosition.goalv() + delta;
g_pHyprRenderer->damageWindow(PWINDOW);
}

View file

@ -42,17 +42,12 @@ struct SDwindleNodeData {
class CHyprDwindleLayout : public IHyprLayout {
public:
virtual void onWindowCreated(CWindow*);
virtual void onWindowRemoved(CWindow*);
virtual void onWindowCreatedTiling(CWindow*);
virtual void onWindowRemovedTiling(CWindow*);
virtual bool isWindowTiled(CWindow*);
virtual void recalculateMonitor(const int&);
virtual void recalculateWindow(CWindow*);
virtual void changeWindowFloatingMode(CWindow*);
virtual void onBeginDragWindow();
virtual void resizeActiveWindow(const Vector2D&, CWindow* pWindow = nullptr);
virtual void moveActiveWindow(const Vector2D&, CWindow* pWindow = nullptr);
virtual void onEndDragWindow();
virtual void onMouseMove(const Vector2D&);
virtual void onWindowCreatedFloating(CWindow*);
virtual void fullscreenRequestForWindow(CWindow*, eFullscreenMode, bool);
virtual std::any layoutMessage(SLayoutMessageHeader, std::string);
virtual SWindowRenderLayoutHints requestRenderHints(CWindow*);
@ -60,15 +55,10 @@ public:
virtual void alterSplitRatioBy(CWindow*, float);
virtual std::string getLayoutName();
private:
private:
std::list<SDwindleNodeData> m_lDwindleNodesData;
Vector2D m_vBeginDragXY;
Vector2D m_vLastDragXY;
Vector2D m_vBeginDragPositionXY;
Vector2D m_vBeginDragSizeXY;
int getNodesOnWorkspace(const int&);
void applyNodeDataToWindow(SDwindleNodeData*);
SDwindleNodeData* getNodeFromWindow(CWindow*);

233
src/layout/IHyprLayout.cpp Normal file
View file

@ -0,0 +1,233 @@
#include "IHyprLayout.hpp"
#include "../defines.hpp"
#include "../Compositor.hpp"
void IHyprLayout::onWindowCreated(CWindow* pWindow) {
if (pWindow->m_bIsFloating) {
onWindowCreatedFloating(pWindow);
} else {
onWindowCreatedTiling(pWindow);
}
}
void IHyprLayout::onWindowRemoved(CWindow* pWindow) {
if (pWindow->m_bIsFloating) {
onWindowRemovedFloating(pWindow);
} else {
onWindowRemovedTiling(pWindow);
}
}
void IHyprLayout::onWindowRemovedFloating(CWindow* pWindow) {
return; // no-op
}
void IHyprLayout::onWindowCreatedFloating(CWindow* pWindow) {
wlr_box desiredGeometry = {0};
g_pXWaylandManager->getGeometryForWindow(pWindow, &desiredGeometry);
const auto PMONITOR = g_pCompositor->getMonitorFromID(pWindow->m_iMonitorID);
if (!PMONITOR) {
Debug::log(ERR, "Window %x (%s) has an invalid monitor in onWindowCreatedFloating!!!", pWindow, pWindow->m_szTitle.c_str());
return;
}
if (desiredGeometry.width <= 0 || desiredGeometry.height <= 0) {
const auto PWINDOWSURFACE = g_pXWaylandManager->getWindowSurface(pWindow);
pWindow->m_vRealSize = Vector2D(PWINDOWSURFACE->current.width, PWINDOWSURFACE->current.height);
pWindow->m_vRealPosition = Vector2D(PMONITOR->vecPosition.x + (PMONITOR->vecSize.x - pWindow->m_vRealSize.vec().x) / 2.f, PMONITOR->vecPosition.y + (PMONITOR->vecSize.y - pWindow->m_vRealSize.vec().y) / 2.f);
} else {
// we respect the size.
pWindow->m_vRealSize = Vector2D(desiredGeometry.width, desiredGeometry.height);
// check if it's on the correct monitor!
Vector2D middlePoint = Vector2D(desiredGeometry.x, desiredGeometry.y) + Vector2D(desiredGeometry.width, desiredGeometry.height) / 2.f;
// TODO: detect a popup in a more consistent way.
if (!g_pCompositor->isPointOnAnyMonitor(middlePoint) || (desiredGeometry.x == 0 && desiredGeometry.y == 0)) {
// if it's not, fall back to the center placement
pWindow->m_vRealPosition = PMONITOR->vecPosition + Vector2D((PMONITOR->vecSize.x - desiredGeometry.width) / 2.f, (PMONITOR->vecSize.y - desiredGeometry.height) / 2.f);
} else {
// if it is, we respect where it wants to put itself, but apply monitor offset if outside
// most of these are popups
if (const auto POPENMON = g_pCompositor->getMonitorFromVector(middlePoint); POPENMON->ID != PMONITOR->ID) {
pWindow->m_vRealPosition = Vector2D(desiredGeometry.x, desiredGeometry.y) - POPENMON->vecPosition + PMONITOR->vecPosition;
} else {
pWindow->m_vRealPosition = Vector2D(desiredGeometry.x, desiredGeometry.y);
}
}
}
if (pWindow->m_bX11DoesntWantBorders) {
pWindow->m_vRealPosition.setValue(pWindow->m_vRealPosition.goalv());
pWindow->m_vRealSize.setValue(pWindow->m_vRealSize.goalv());
}
g_pXWaylandManager->setWindowSize(pWindow, pWindow->m_vRealSize.goalv());
g_pCompositor->fixXWaylandWindowsOnWorkspace(PMONITOR->activeWorkspace);
g_pCompositor->moveWindowToTop(pWindow);
}
void IHyprLayout::onBeginDragWindow() {
const auto DRAGGINGWINDOW = g_pInputManager->currentlyDraggedWindow;
m_vBeginDragSizeXY = Vector2D();
// Window will be floating. Let's check if it's valid. It should be, but I don't like crashing.
if (!g_pCompositor->windowValidMapped(DRAGGINGWINDOW)) {
Debug::log(ERR, "Dragging attempted on an invalid window!");
return;
}
if (DRAGGINGWINDOW->m_bIsFullscreen) {
Debug::log(LOG, "Rejecting drag on a fullscreen window.");
return;
}
const auto PWORKSPACE = g_pCompositor->getWorkspaceByID(DRAGGINGWINDOW->m_iWorkspaceID);
if (PWORKSPACE->m_bHasFullscreenWindow) {
Debug::log(LOG, "Rejecting drag on a fullscreen workspace.");
return;
}
DRAGGINGWINDOW->m_bDraggingTiled = false;
if (!DRAGGINGWINDOW->m_bIsFloating) {
if (g_pInputManager->dragButton == BTN_LEFT) {
changeWindowFloatingMode(DRAGGINGWINDOW);
DRAGGINGWINDOW->m_bIsFloating = true;
DRAGGINGWINDOW->m_bDraggingTiled = true;
}
}
m_vBeginDragXY = g_pInputManager->getMouseCoordsInternal();
m_vBeginDragPositionXY = DRAGGINGWINDOW->m_vRealPosition.vec();
m_vBeginDragSizeXY = DRAGGINGWINDOW->m_vRealSize.vec();
m_vLastDragXY = m_vBeginDragXY;
g_pHyprRenderer->damageWindow(DRAGGINGWINDOW);
}
void IHyprLayout::onEndDragWindow() {
const auto DRAGGINGWINDOW = g_pInputManager->currentlyDraggedWindow;
if (!g_pCompositor->windowValidMapped(DRAGGINGWINDOW))
return;
if (DRAGGINGWINDOW->m_bDraggingTiled) {
DRAGGINGWINDOW->m_bIsFloating = false;
changeWindowFloatingMode(DRAGGINGWINDOW);
}
g_pHyprRenderer->damageWindow(DRAGGINGWINDOW);
}
void IHyprLayout::onMouseMove(const Vector2D& mousePos) {
const auto DRAGGINGWINDOW = g_pInputManager->currentlyDraggedWindow;
// Window invalid or drag begin size 0,0 meaning we rejected it.
if (!g_pCompositor->windowValidMapped(DRAGGINGWINDOW) || m_vBeginDragSizeXY == Vector2D()) {
g_pInputManager->currentlyDraggedWindow = nullptr;
return;
}
const auto DELTA = Vector2D(mousePos.x - m_vBeginDragXY.x, mousePos.y - m_vBeginDragXY.y);
const auto TICKDELTA = Vector2D(mousePos.x - m_vLastDragXY.x, mousePos.y - m_vLastDragXY.y);
if (abs(TICKDELTA.x) < 1.f && abs(TICKDELTA.y) < 1.f)
return;
m_vLastDragXY = mousePos;
g_pHyprRenderer->damageWindow(DRAGGINGWINDOW);
if (g_pInputManager->dragButton == BTN_LEFT) {
DRAGGINGWINDOW->m_vRealPosition.setValueAndWarp(m_vBeginDragPositionXY + DELTA);
DRAGGINGWINDOW->updateWindowDecos();
g_pXWaylandManager->setWindowSize(DRAGGINGWINDOW, DRAGGINGWINDOW->m_vRealSize.goalv());
} else {
if (DRAGGINGWINDOW->m_bIsFloating) {
DRAGGINGWINDOW->m_vRealSize.setValueAndWarp(m_vBeginDragSizeXY + DELTA);
DRAGGINGWINDOW->m_vRealSize.setValueAndWarp(Vector2D(std::clamp(DRAGGINGWINDOW->m_vRealSize.vec().x, (double)20, (double)999999), std::clamp(DRAGGINGWINDOW->m_vRealSize.vec().y, (double)20, (double)999999)));
DRAGGINGWINDOW->updateWindowDecos();
g_pXWaylandManager->setWindowSize(DRAGGINGWINDOW, DRAGGINGWINDOW->m_vRealSize.goalv());
} else {
resizeActiveWindow(TICKDELTA, DRAGGINGWINDOW);
}
}
// get middle point
Vector2D middle = DRAGGINGWINDOW->m_vRealPosition.vec() + DRAGGINGWINDOW->m_vRealSize.vec() / 2.f;
// and check its monitor
const auto PMONITOR = g_pCompositor->getMonitorFromVector(middle);
if (PMONITOR) {
DRAGGINGWINDOW->m_iMonitorID = PMONITOR->ID;
DRAGGINGWINDOW->m_iWorkspaceID = PMONITOR->activeWorkspace;
}
g_pHyprRenderer->damageWindow(DRAGGINGWINDOW);
}
void IHyprLayout::changeWindowFloatingMode(CWindow* pWindow) {
if (pWindow->m_bIsFullscreen) {
Debug::log(LOG, "Rejecting a change float order because window is fullscreen.");
// restore its' floating mode
pWindow->m_bIsFloating = !pWindow->m_bIsFloating;
return;
}
const auto TILED = isWindowTiled(pWindow);
if (!TILED) {
const auto PNEWMON = g_pCompositor->getMonitorFromVector(pWindow->m_vRealPosition.vec() + pWindow->m_vRealSize.vec() / 2.f);
pWindow->m_iMonitorID = PNEWMON->ID;
pWindow->m_iWorkspaceID = PNEWMON->activeWorkspace;
// save real pos cuz the func applies the default 5,5 mid
const auto PSAVEDPOS = pWindow->m_vRealPosition.vec();
const auto PSAVEDSIZE = pWindow->m_vRealSize.vec();
// if the window is pseudo, update its size
pWindow->m_vPseudoSize = pWindow->m_vRealSize.vec();
onWindowCreatedTiling(pWindow);
pWindow->m_vRealPosition.setValue(PSAVEDPOS);
pWindow->m_vRealSize.setValue(PSAVEDSIZE);
// fix pseudo leaving artifacts
g_pHyprRenderer->damageMonitor(g_pCompositor->getMonitorFromID(pWindow->m_iMonitorID));
} else {
onWindowRemovedTiling(pWindow);
g_pCompositor->moveWindowToTop(pWindow);
}
}
void IHyprLayout::moveActiveWindow(const Vector2D& delta, CWindow* pWindow) {
const auto PWINDOW = pWindow ? pWindow : g_pCompositor->m_pLastWindow;
if (!g_pCompositor->windowValidMapped(PWINDOW))
return;
if (!PWINDOW->m_bIsFloating) {
Debug::log(LOG, "Dwindle cannot move a tiled window in moveActiveWindow!");
return;
}
PWINDOW->m_vRealPosition = PWINDOW->m_vRealPosition.goalv() + delta;
g_pHyprRenderer->damageWindow(PWINDOW);
}

View file

@ -22,11 +22,21 @@ public:
The layout HAS TO set the goal pos and size (anim mgr will use it)
If !animationinprogress, then the anim mgr will not apply an anim.
*/
virtual void onWindowCreated(CWindow*) = 0;
virtual void onWindowCreated(CWindow*);
virtual void onWindowCreatedTiling(CWindow*) = 0;
virtual void onWindowCreatedFloating(CWindow*);
/*
Return tiled status
*/
virtual bool isWindowTiled(CWindow*) = 0;
/*
Called when a window is removed (unmapped)
*/
virtual void onWindowRemoved(CWindow*) = 0;
virtual void onWindowRemoved(CWindow*);
virtual void onWindowRemovedTiling(CWindow*) = 0;
virtual void onWindowRemovedFloating(CWindow*);
/*
Called when the monitor requires a layout recalculation
this usually means reserved area changes
@ -42,13 +52,13 @@ public:
/*
Called when a window is requested to be floated
*/
virtual void changeWindowFloatingMode(CWindow*) = 0;
virtual void changeWindowFloatingMode(CWindow*);
/*
Called when a window is clicked on, beginning a drag
this might be a resize, move, whatever the layout defines it
as.
*/
virtual void onBeginDragWindow() = 0;
virtual void onBeginDragWindow();
/*
Called when a user requests a resize of the current window by a vec
Vector2D holds pixel values
@ -60,24 +70,18 @@ public:
Vector2D holds pixel values
Optional pWindow for a specific window
*/
virtual void moveActiveWindow(const Vector2D&, CWindow* pWindow = nullptr) = 0;
virtual void moveActiveWindow(const Vector2D&, CWindow* pWindow = nullptr);
/*
Called when a window is ended being dragged
(mouse up)
*/
virtual void onEndDragWindow() = 0;
virtual void onEndDragWindow();
/*
Called whenever the mouse moves, should the layout want to
do anything with it.
Useful for dragging.
*/
virtual void onMouseMove(const Vector2D&) = 0;
/*
Called when a window is created, but is requesting to be floated.
Warning: this also includes stuff like popups, incorrect handling
of which can result in a crash!
*/
virtual void onWindowCreatedFloating(CWindow*) = 0;
virtual void onMouseMove(const Vector2D&);
/*
Called when a window / the user requests to toggle the fullscreen state of a window
@ -116,4 +120,10 @@ public:
Called when something wants the current layout's name
*/
virtual std::string getLayoutName() = 0;
private:
Vector2D m_vBeginDragXY;
Vector2D m_vLastDragXY;
Vector2D m_vBeginDragPositionXY;
Vector2D m_vBeginDragSizeXY;
};

View file

@ -37,9 +37,18 @@ void CAnimationManager::tick() {
DEFAULTBEZIER = m_mBezierCurves.find("default");
for (auto& av : m_lAnimatedVariables) {
// first of all, check if we need to update it at all
if (!av->isBeingAnimated())
continue;
// get speed
const auto SPEED = *av->m_pSpeed == 0 ? *PANIMSPEED : *av->m_pSpeed;
// get the spent % (0 - 1)
const auto DURATIONPASSED = std::chrono::duration_cast<std::chrono::milliseconds>(std::chrono::system_clock::now() - av->animationBegin).count();
const float SPENT = std::clamp((DURATIONPASSED / 100.f) / SPEED, 0.f, 1.f);
// window stuff
const auto PWINDOW = (CWindow*)av->m_pWindow;
const auto PWORKSPACE = (CWorkspace*)av->m_pWorkspace;
@ -47,7 +56,7 @@ void CAnimationManager::tick() {
wlr_box WLRBOXPREV = {0,0,0,0};
if (PWINDOW) {
WLRBOXPREV = {(int)PWINDOW->m_vRealPosition.vec().x - (int)*PBORDERSIZE - 1, (int)PWINDOW->m_vRealPosition.vec().y - (int)*PBORDERSIZE - 1, (int)PWINDOW->m_vRealSize.vec().x + 2 * (int)*PBORDERSIZE + 2, (int)PWINDOW->m_vRealSize.vec().y + 2 * (int)*PBORDERSIZE + 2};
WLRBOXPREV = PWINDOW->getFullWindowBoundingBox();
} else if (PWORKSPACE) {
const auto PMONITOR = g_pCompositor->getMonitorFromID(PWORKSPACE->m_iMonitorID);
WLRBOXPREV = {(int)PMONITOR->vecPosition.x, (int)PMONITOR->vecPosition.y, (int)PMONITOR->vecSize.x, (int)PMONITOR->vecSize.y};
@ -58,84 +67,68 @@ void CAnimationManager::tick() {
// beziers are with a switch unforto
// TODO: maybe do something cleaner
// get the spent % (0 - 1)
const auto DURATIONPASSED = std::chrono::duration_cast<std::chrono::milliseconds>(std::chrono::system_clock::now() - av->animationBegin).count();
const float SPENT = std::clamp((DURATIONPASSED / 100.f) / SPEED, 0.f, 1.f);
switch (av->m_eVarType) {
case AVARTYPE_FLOAT: {
if (!deltazero(av->m_fValue, av->m_fGoal)) {
// for disabled anims just warp
if (av->m_pEnabled == 0 || animationsDisabled) {
av->warp();
break;
}
const auto DELTA = av->m_fGoal - av->m_fBegun;
const auto BEZIER = m_mBezierCurves.find(*av->m_pBezier);
if (BEZIER != m_mBezierCurves.end())
av->m_fValue = av->m_fBegun + BEZIER->second.getYForPoint(SPENT) * DELTA;
else
av->m_fValue = av->m_fBegun + DEFAULTBEZIER->second.getYForPoint(SPENT) * DELTA;
if (SPENT >= 1.f) {
av->warp();
}
} else {
continue; // dont process
// for disabled anims just warp
if (*av->m_pEnabled == 0 || animationsDisabled) {
av->warp();
break;
}
if (SPENT >= 1.f) {
av->warp();
break;
}
const auto DELTA = av->m_fGoal - av->m_fBegun;
const auto BEZIER = m_mBezierCurves.find(*av->m_pBezier);
if (BEZIER != m_mBezierCurves.end())
av->m_fValue = av->m_fBegun + BEZIER->second.getYForPoint(SPENT) * DELTA;
else
av->m_fValue = av->m_fBegun + DEFAULTBEZIER->second.getYForPoint(SPENT) * DELTA;
break;
}
case AVARTYPE_VECTOR: {
if (!deltazero(av->m_vValue, av->m_vGoal)) {
// for disabled anims just warp
if (av->m_pEnabled == 0 || animationsDisabled) {
av->warp();
break;
}
const auto DELTA = av->m_vGoal - av->m_vBegun;
const auto BEZIER = m_mBezierCurves.find(*av->m_pBezier);
if (BEZIER != m_mBezierCurves.end())
av->m_vValue = av->m_vBegun + DELTA * BEZIER->second.getYForPoint(SPENT);
else
av->m_vValue = av->m_vBegun + DELTA * DEFAULTBEZIER->second.getYForPoint(SPENT);
if (SPENT >= 1.f) {
av->warp();
}
} else {
continue; // dont process
// for disabled anims just warp
if (*av->m_pEnabled == 0 || animationsDisabled) {
av->warp();
break;
}
if (SPENT >= 1.f) {
av->warp();
break;
}
const auto DELTA = av->m_vGoal - av->m_vBegun;
const auto BEZIER = m_mBezierCurves.find(*av->m_pBezier);
if (BEZIER != m_mBezierCurves.end())
av->m_vValue = av->m_vBegun + DELTA * BEZIER->second.getYForPoint(SPENT);
else
av->m_vValue = av->m_vBegun + DELTA * DEFAULTBEZIER->second.getYForPoint(SPENT);
break;
}
case AVARTYPE_COLOR: {
if (!deltazero(av->m_cValue, av->m_cGoal)) {
// for disabled anims just warp
if (av->m_pEnabled == 0 || animationsDisabled) {
av->warp();
break;
}
const auto DELTA = av->m_cGoal - av->m_cBegun;
const auto BEZIER = m_mBezierCurves.find(*av->m_pBezier);
if (BEZIER != m_mBezierCurves.end())
av->m_cValue = av->m_cBegun + DELTA * BEZIER->second.getYForPoint(SPENT);
else
av->m_cValue = av->m_cBegun + DELTA * DEFAULTBEZIER->second.getYForPoint(SPENT);
if (SPENT >= 1.f) {
av->warp();
}
} else {
continue; // dont process
// for disabled anims just warp
if (*av->m_pEnabled == 0 || animationsDisabled) {
av->warp();
break;
}
if (SPENT >= 1.f) {
av->warp();
break;
}
const auto DELTA = av->m_cGoal - av->m_cBegun;
const auto BEZIER = m_mBezierCurves.find(*av->m_pBezier);
if (BEZIER != m_mBezierCurves.end())
av->m_cValue = av->m_cBegun + DELTA * BEZIER->second.getYForPoint(SPENT);
else
av->m_cValue = av->m_cBegun + DELTA * DEFAULTBEZIER->second.getYForPoint(SPENT);
break;
}
default: {
@ -150,8 +143,16 @@ void CAnimationManager::tick() {
if (PWINDOW) {
g_pHyprRenderer->damageWindow(PWINDOW);
for (auto& wd : PWINDOW->m_dWindowDecorations) {
wd->updateWindow(PWINDOW);
PWINDOW->updateWindowDecos();
} else if (PWORKSPACE) {
for (auto& w : g_pCompositor->m_vWindows) {
if (!w->m_bIsMapped || w->m_bHidden)
continue;
if (w->m_iWorkspaceID != PWORKSPACE->m_iID)
continue;
w->updateWindowDecos();
}
}
break;

View file

@ -87,7 +87,7 @@ void CEventManager::startThread() {
// write all queued events
for (auto& ev : m_dQueuedEvents) {
std::string eventString = ev.event + ">>" + ev.data + "\n";
std::string eventString = (ev.event + ">>" + ev.data).substr(0, 1022) + "\n";
for (auto& fd : m_dAcceptedSocketFDs) {
write(fd, eventString.c_str(), eventString.length());
}
@ -104,9 +104,9 @@ void CEventManager::startThread() {
}).detach();
}
void CEventManager::postEvent(const SHyprIPCEvent event) {
void CEventManager::postEvent(const SHyprIPCEvent event, bool force) {
if (m_bIgnoreEvents) {
if (m_bIgnoreEvents && !force) {
Debug::log(WARN, "Suppressed (ignoreevents true) event of type %s, content: %s",event.event.c_str(), event.data.c_str());
return;
}

View file

@ -15,7 +15,7 @@ class CEventManager {
public:
CEventManager();
void postEvent(const SHyprIPCEvent event);
void postEvent(const SHyprIPCEvent event, bool force = false);
void startThread();

View file

@ -30,7 +30,8 @@ CKeybindManager::CKeybindManager() {
m_mDispatchers["resizeactive"] = resizeActive;
m_mDispatchers["moveactive"] = moveActive;
m_mDispatchers["cyclenext"] = circleNext;
m_mDispatchers["focuswindowbyclass"] = focusWindowByClass;
m_mDispatchers["focuswindowbyclass"] = focusWindow;
m_mDispatchers["focuswindow"] = focusWindow;
m_mDispatchers["submap"] = setSubmap;
}
@ -108,7 +109,7 @@ bool CKeybindManager::handleKeybinds(const uint32_t& modmask, const xkb_keysym_t
return found;
}
bool CKeybindManager::handleInternalKeybinds(xkb_keysym_t keysym) {
bool CKeybindManager::handleVT(xkb_keysym_t keysym) {
// Handles the CTRL+ALT+FX TTY keybinds
if (!(keysym >= XKB_KEY_XF86Switch_VT_1 && keysym <= XKB_KEY_XF86Switch_VT_12))
return false;
@ -118,20 +119,37 @@ bool CKeybindManager::handleInternalKeybinds(xkb_keysym_t keysym) {
const int TTY = keysym - XKB_KEY_XF86Switch_VT_1 + 1;
wlr_session_change_vt(PSESSION, TTY);
for (auto& m : g_pCompositor->m_lMonitors) {
g_pHyprOpenGL->destroyMonitorResources(&m); // mark resources as unusable anymore
m.noFrameSchedule = true;
m.framesToSkip = 2;
for (auto& m : g_pCompositor->m_vMonitors) {
g_pHyprOpenGL->destroyMonitorResources(m.get()); // mark resources as unusable anymore
m->noFrameSchedule = true;
m->framesToSkip = 2;
}
Debug::log(LOG, "Switched to VT %i, destroyed all render data, frames to skip for each: 2", TTY);
return true;
}
return false;
}
bool CKeybindManager::handleInternalKeybinds(xkb_keysym_t keysym) {
if (handleVT(keysym))
return true;
// handle ESC while in kill mode
if (g_pInputManager->getClickMode() == CLICKMODE_KILL) {
const auto KBKEY = xkb_keysym_from_name("ESCAPE", XKB_KEYSYM_CASE_INSENSITIVE);
if (keysym == KBKEY) {
g_pInputManager->setClickMode(CLICKMODE_DEFAULT);
return true;
}
}
return false;
}
// Dispatchers
void CKeybindManager::spawn(std::string args) {
@ -204,6 +222,9 @@ void CKeybindManager::toggleActiveFloating(std::string args) {
const auto ACTIVEWINDOW = g_pCompositor->m_pLastWindow;
if (g_pCompositor->windowValidMapped(ACTIVEWINDOW)) {
// remove drag status
g_pInputManager->currentlyDraggedWindow = nullptr;
ACTIVEWINDOW->m_bIsFloating = !ACTIVEWINDOW->m_bIsFloating;
if (ACTIVEWINDOW->m_iWorkspaceID == SPECIAL_WORKSPACE_ID) {
@ -319,8 +340,7 @@ void CKeybindManager::changeworkspace(std::string args) {
if (const auto POLDWORKSPACE = g_pCompositor->getWorkspaceByID(OLDWORKSPACE); POLDWORKSPACE)
POLDWORKSPACE->startAnim(false, ANIMTOLEFT);
g_pCompositor->m_lWorkspaces.emplace_back(PMONITOR->ID, workspaceToChangeTo == SPECIAL_WORKSPACE_ID);
const auto PWORKSPACE = &g_pCompositor->m_lWorkspaces.back();
const auto PWORKSPACE = g_pCompositor->m_vWorkspaces.emplace_back(std::make_unique<CWorkspace>(PMONITOR->ID, workspaceName, workspaceToChangeTo == SPECIAL_WORKSPACE_ID)).get();
// start anim on new workspace
PWORKSPACE->startAnim(true, ANIMTOLEFT);
@ -331,7 +351,6 @@ void CKeybindManager::changeworkspace(std::string args) {
PWORKSPACE->m_iID = workspaceToChangeTo;
PWORKSPACE->m_iMonitorID = PMONITOR->ID;
PWORKSPACE->m_szName = workspaceName;
PMONITOR->specialWorkspaceOpen = false;
@ -437,8 +456,8 @@ void CKeybindManager::moveActiveToWorkspace(std::string args) {
toggleSpecialWorkspace("");
g_pCompositor->getWorkspaceByID(SPECIAL_WORKSPACE_ID)->startAnim(false, false, true);
for (auto& m : g_pCompositor->m_lMonitors)
m.specialWorkspaceOpen = false;
for (auto& m : g_pCompositor->m_vMonitors)
m->specialWorkspaceOpen = false;
}
g_pInputManager->refocus();
@ -643,7 +662,7 @@ void CKeybindManager::focusMonitor(std::string arg) {
Debug::log(ERR, "Error in focusMonitor: invalid num");
}
if (monID > -1 && monID < (int)g_pCompositor->m_lMonitors.size()) {
if (monID > -1 && monID < (int)g_pCompositor->m_vMonitors.size()) {
changeworkspace(std::to_string(g_pCompositor->getMonitorFromID(monID)->activeWorkspace));
} else {
Debug::log(ERR, "Error in focusMonitor: invalid arg 1");
@ -662,9 +681,9 @@ void CKeybindManager::focusMonitor(std::string arg) {
return;
}
} else {
for (auto& m : g_pCompositor->m_lMonitors) {
if (m.szName == arg) {
changeworkspace(std::to_string(m.activeWorkspace));
for (auto& m : g_pCompositor->m_vMonitors) {
if (m->szName == arg) {
changeworkspace(std::to_string(m->activeWorkspace));
return;
}
}
@ -724,11 +743,11 @@ void CKeybindManager::workspaceOpt(std::string args) {
PWORKSPACE->m_bDefaultPseudo = !PWORKSPACE->m_bDefaultPseudo;
// apply
for (auto& w : g_pCompositor->m_lWindows) {
if (!w.m_bIsMapped || w.m_iWorkspaceID != PWORKSPACE->m_iID)
for (auto& w : g_pCompositor->m_vWindows) {
if (!w->m_bIsMapped || w->m_iWorkspaceID != PWORKSPACE->m_iID)
continue;
w.m_bIsPseudotiled = PWORKSPACE->m_bDefaultPseudo;
w->m_bIsPseudotiled = PWORKSPACE->m_bDefaultPseudo;
}
} else if (args == "allfloat") {
PWORKSPACE->m_bDefaultFloating = !PWORKSPACE->m_bDefaultFloating;
@ -736,8 +755,8 @@ void CKeybindManager::workspaceOpt(std::string args) {
// we make a copy because changeWindowFloatingMode might invalidate the iterator
std::deque<CWindow*> ptrs;
for (auto& w : g_pCompositor->m_lWindows)
ptrs.push_back(&w);
for (auto& w : g_pCompositor->m_vWindows)
ptrs.push_back(w.get());
for (auto& w : ptrs) {
if (!w->m_bIsMapped || w->m_iWorkspaceID != PWORKSPACE->m_iID)
@ -841,8 +860,8 @@ void CKeybindManager::toggleSpecialWorkspace(std::string args) {
bool open = false;
for (auto& m : g_pCompositor->m_lMonitors) {
if (m.specialWorkspaceOpen) {
for (auto& m : g_pCompositor->m_vMonitors) {
if (m->specialWorkspaceOpen) {
open = true;
break;
}
@ -854,10 +873,10 @@ void CKeybindManager::toggleSpecialWorkspace(std::string args) {
Debug::log(LOG, "Toggling special workspace to open");
if (open) {
for (auto& m : g_pCompositor->m_lMonitors) {
if (m.specialWorkspaceOpen != !open) {
m.specialWorkspaceOpen = !open;
g_pLayoutManager->getCurrentLayout()->recalculateMonitor(m.ID);
for (auto& m : g_pCompositor->m_vMonitors) {
if (m->specialWorkspaceOpen != !open) {
m->specialWorkspaceOpen = !open;
g_pLayoutManager->getCurrentLayout()->recalculateMonitor(m->ID);
g_pCompositor->getWorkspaceByID(SPECIAL_WORKSPACE_ID)->startAnim(false, false);
}
@ -866,17 +885,28 @@ void CKeybindManager::toggleSpecialWorkspace(std::string args) {
g_pCompositor->m_pLastMonitor->specialWorkspaceOpen = true;
g_pLayoutManager->getCurrentLayout()->recalculateMonitor(g_pCompositor->m_pLastMonitor->ID);
g_pCompositor->getWorkspaceByID(SPECIAL_WORKSPACE_ID)->startAnim(true, true);
const auto PSPECIALWORKSPACE = g_pCompositor->getWorkspaceByID(SPECIAL_WORKSPACE_ID);
PSPECIALWORKSPACE->startAnim(true, true);
PSPECIALWORKSPACE->m_iMonitorID = g_pCompositor->m_pLastMonitor->ID;
}
g_pInputManager->refocus();
}
void CKeybindManager::forceRendererReload(std::string args) {
for (auto& m : g_pCompositor->m_lMonitors) {
auto rule = g_pConfigManager->getMonitorRuleFor(m.szName);
g_pHyprRenderer->applyMonitorRule(&m, &rule, true);
bool overAgain = false;
for (auto& m : g_pCompositor->m_vMonitors) {
auto rule = g_pConfigManager->getMonitorRuleFor(m->szName);
if (!g_pHyprRenderer->applyMonitorRule(m.get(), &rule, true)) {
overAgain = true;
break;
}
}
if (overAgain)
forceRendererReload(args);
}
void CKeybindManager::resizeActive(std::string args) {
@ -988,25 +1018,36 @@ void CKeybindManager::circleNext(std::string) {
wlr_cursor_warp(g_pCompositor->m_sWLRCursor, nullptr, MIDPOINT.x, MIDPOINT.y);
}
void CKeybindManager::focusWindowByClass(std::string clazz) {
std::regex classCheck(clazz);
void CKeybindManager::focusWindow(std::string regexp) {
bool titleRegex = false;
std::regex regexCheck(regexp);
if (regexp.find("title:") == 0) {
titleRegex = true;
regexCheck = std::regex(regexp.substr(6));
}
for (auto& w : g_pCompositor->m_lWindows) {
if (!w.m_bIsMapped || w.m_bHidden)
for (auto& w : g_pCompositor->m_vWindows) {
if (!w->m_bIsMapped || w->m_bHidden)
continue;
const auto windowClass = g_pXWaylandManager->getAppIDClass(&w);
if (titleRegex) {
const auto windowTitle = g_pXWaylandManager->getTitle(w.get());
if (!std::regex_search(windowTitle, regexCheck))
continue;
}
else {
const auto windowClass = g_pXWaylandManager->getAppIDClass(w.get());
if (!std::regex_search(windowClass, regexCheck))
continue;
}
if (!std::regex_search(windowClass, classCheck))
continue;
Debug::log(LOG, "Focusing to window name: %s", w->m_szTitle.c_str());
Debug::log(LOG, "Focusing to window name: %s", w.m_szTitle.c_str());
changeworkspace(std::to_string(w->m_iWorkspaceID));
changeworkspace(std::to_string(w.m_iWorkspaceID));
g_pCompositor->focusWindow(w.get());
g_pCompositor->focusWindow(&w);
const auto MIDPOINT = w.m_vRealPosition.goalv() + w.m_vRealSize.goalv() / 2.f;
const auto MIDPOINT = w->m_vRealPosition.goalv() + w->m_vRealSize.goalv() / 2.f;
wlr_cursor_warp(g_pCompositor->m_sWLRCursor, nullptr, MIDPOINT.x, MIDPOINT.y);

View file

@ -33,6 +33,7 @@ private:
inline static std::string m_szCurrentSelectedSubmap = "";
bool handleInternalKeybinds(xkb_keysym_t);
bool handleVT(xkb_keysym_t);
// -------------- Dispatchers -------------- //
static void killActive(std::string);
@ -60,7 +61,7 @@ private:
static void resizeActive(std::string);
static void moveActive(std::string);
static void circleNext(std::string);
static void focusWindowByClass(std::string);
static void focusWindow(std::string);
static void setSubmap(std::string);
friend class CCompositor;

View file

@ -42,9 +42,6 @@ void CHyprXWaylandManager::activateSurface(wlr_surface* pSurface, bool activate)
}
void CHyprXWaylandManager::activateWindow(CWindow* pWindow, bool activate) {
if (pWindow == g_pCompositor->m_pLastWindow)
return;
if (pWindow->m_bIsX11) {
if (pWindow->m_uSurface.xwayland->minimized)
wlr_xwayland_surface_set_minimized(pWindow->m_uSurface.xwayland, false);
@ -146,8 +143,10 @@ bool CHyprXWaylandManager::shouldBeFloated(CWindow* pWindow) {
if (pWindow->m_uSurface.xwayland->window_type[i] == HYPRATOMS["_NET_WM_WINDOW_TYPE_DIALOG"] || pWindow->m_uSurface.xwayland->window_type[i] == HYPRATOMS["_NET_WM_WINDOW_TYPE_SPLASH"] ||
pWindow->m_uSurface.xwayland->window_type[i] == HYPRATOMS["_NET_WM_WINDOW_TYPE_TOOLBAR"] || pWindow->m_uSurface.xwayland->window_type[i] == HYPRATOMS["_NET_WM_WINDOW_TYPE_UTILITY"] ||
pWindow->m_uSurface.xwayland->window_type[i] == HYPRATOMS["_NET_WM_WINDOW_TYPE_TOOLTIP"] || pWindow->m_uSurface.xwayland->window_type[i] == HYPRATOMS["_NET_WM_WINDOW_TYPE_POPUP_MENU"] ||
pWindow->m_uSurface.xwayland->window_type[i] == HYPRATOMS["_NET_WM_WINDOW_TYPE_DOCK"] || pWindow->m_uSurface.xwayland->window_type[i] == HYPRATOMS["_NET_WM_WINDOW_TYPE_DROPDOWN_MENU"])
pWindow->m_uSurface.xwayland->window_type[i] == HYPRATOMS["_NET_WM_WINDOW_TYPE_DOCK"] || pWindow->m_uSurface.xwayland->window_type[i] == HYPRATOMS["_NET_WM_WINDOW_TYPE_DROPDOWN_MENU"] ||
pWindow->m_uSurface.xwayland->window_type[i] == HYPRATOMS["_NET_WM_WINDOW_TYPE_MENU"])
{
pWindow->m_bNoInitialFocus = true;
return true;
}

View file

@ -37,6 +37,13 @@ void CInputManager::mouseMoveUnified(uint32_t time, bool refocus) {
}
Vector2D mouseCoords = getMouseCoordsInternal();
const auto MOUSECOORDSFLOORED = mouseCoords.floor();
if (MOUSECOORDSFLOORED == m_vLastCursorPosFloored)
return;
m_vLastCursorPosFloored = MOUSECOORDSFLOORED;
const auto PMONITOR = g_pCompositor->getMonitorFromCursor();
bool didConstraintOnCursor = false;
@ -110,10 +117,11 @@ void CInputManager::mouseMoveUnified(uint32_t time, bool refocus) {
Vector2D surfaceCoords;
Vector2D surfacePos = Vector2D(-1337, -1337);
CWindow* pFoundWindow = nullptr;
SLayerSurface* pFoundLayerSurface = nullptr;
// overlay is above fullscreen
if (!foundSurface)
foundSurface = g_pCompositor->vectorToLayerSurface(mouseCoords, &PMONITOR->m_aLayerSurfaceLists[ZWLR_LAYER_SHELL_V1_LAYER_OVERLAY], &surfaceCoords);
foundSurface = g_pCompositor->vectorToLayerSurface(mouseCoords, &PMONITOR->m_aLayerSurfaceLists[ZWLR_LAYER_SHELL_V1_LAYER_OVERLAY], &surfaceCoords, &pFoundLayerSurface);
// then, we check if the workspace doesnt have a fullscreen window
const auto PWORKSPACE = g_pCompositor->getWorkspaceByID(PMONITOR->activeWorkspace);
@ -123,10 +131,10 @@ void CInputManager::mouseMoveUnified(uint32_t time, bool refocus) {
surfacePos = pFoundWindow->m_vRealPosition.vec();
// only check floating because tiled cant be over fullscreen
for (auto w = g_pCompositor->m_lWindows.rbegin(); w != g_pCompositor->m_lWindows.rend(); w++) {
wlr_box box = {w->m_vRealPosition.vec().x, w->m_vRealPosition.vec().y, w->m_vRealSize.vec().x, w->m_vRealSize.vec().y};
if (((w->m_bIsFloating && w->m_bIsMapped && w->m_bCreatedOverFullscreen) || (w->m_iWorkspaceID == SPECIAL_WORKSPACE_ID && PMONITOR->specialWorkspaceOpen)) && wlr_box_contains_point(&box, mouseCoords.x, mouseCoords.y) && g_pCompositor->isWorkspaceVisible(w->m_iWorkspaceID) && !w->m_bHidden) {
pFoundWindow = &(*w);
for (auto w = g_pCompositor->m_vWindows.rbegin(); w != g_pCompositor->m_vWindows.rend(); w++) {
wlr_box box = {(*w)->m_vRealPosition.vec().x, (*w)->m_vRealPosition.vec().y, (*w)->m_vRealSize.vec().x, (*w)->m_vRealSize.vec().y};
if ((((*w)->m_bIsFloating && (*w)->m_bIsMapped && (*w)->m_bCreatedOverFullscreen) || ((*w)->m_iWorkspaceID == SPECIAL_WORKSPACE_ID && PMONITOR->specialWorkspaceOpen)) && wlr_box_contains_point(&box, mouseCoords.x, mouseCoords.y) && g_pCompositor->isWorkspaceVisible((*w)->m_iWorkspaceID) && !(*w)->m_bHidden) {
pFoundWindow = (*w).get();
if (!pFoundWindow->m_bIsX11) {
foundSurface = g_pCompositor->vectorWindowToSurface(mouseCoords, pFoundWindow, surfaceCoords);
@ -141,11 +149,15 @@ void CInputManager::mouseMoveUnified(uint32_t time, bool refocus) {
}
if (!foundSurface)
foundSurface = g_pCompositor->vectorToLayerSurface(mouseCoords, &PMONITOR->m_aLayerSurfaceLists[ZWLR_LAYER_SHELL_V1_LAYER_TOP], &surfaceCoords);
foundSurface = g_pCompositor->vectorToLayerSurface(mouseCoords, &PMONITOR->m_aLayerSurfaceLists[ZWLR_LAYER_SHELL_V1_LAYER_TOP], &surfaceCoords, &pFoundLayerSurface);
// then windows
if (!foundSurface) {
pFoundWindow = g_pCompositor->vectorToWindowIdeal(mouseCoords);
if (PWORKSPACE->m_bHasFullscreenWindow && PWORKSPACE->m_efFullscreenMode == FULLSCREEN_MAXIMIZED)
pFoundWindow = g_pCompositor->getFullscreenWindowOnWorkspace(PWORKSPACE->m_iID);
else
pFoundWindow = g_pCompositor->vectorToWindowIdeal(mouseCoords);
if (pFoundWindow) {
if (!pFoundWindow->m_bIsX11) {
foundSurface = g_pCompositor->vectorWindowToSurface(mouseCoords, pFoundWindow, surfaceCoords);
@ -158,13 +170,16 @@ void CInputManager::mouseMoveUnified(uint32_t time, bool refocus) {
// then surfaces below
if (!foundSurface)
foundSurface = g_pCompositor->vectorToLayerSurface(mouseCoords, &PMONITOR->m_aLayerSurfaceLists[ZWLR_LAYER_SHELL_V1_LAYER_BOTTOM], &surfaceCoords);
foundSurface = g_pCompositor->vectorToLayerSurface(mouseCoords, &PMONITOR->m_aLayerSurfaceLists[ZWLR_LAYER_SHELL_V1_LAYER_BOTTOM], &surfaceCoords, &pFoundLayerSurface);
if (!foundSurface)
foundSurface = g_pCompositor->vectorToLayerSurface(mouseCoords, &PMONITOR->m_aLayerSurfaceLists[ZWLR_LAYER_SHELL_V1_LAYER_BACKGROUND], &surfaceCoords);
foundSurface = g_pCompositor->vectorToLayerSurface(mouseCoords, &PMONITOR->m_aLayerSurfaceLists[ZWLR_LAYER_SHELL_V1_LAYER_BACKGROUND], &surfaceCoords, &pFoundLayerSurface);
if (!foundSurface) {
wlr_xcursor_manager_set_cursor_image(g_pCompositor->m_sWLRXCursorMgr, "left_ptr", g_pCompositor->m_sWLRCursor);
if (m_ecbClickBehavior == CLICKMODE_KILL)
wlr_xcursor_manager_set_cursor_image(g_pCompositor->m_sWLRXCursorMgr, "crosshair", g_pCompositor->m_sWLRCursor);
else
wlr_xcursor_manager_set_cursor_image(g_pCompositor->m_sWLRXCursorMgr, "left_ptr", g_pCompositor->m_sWLRCursor);
wlr_seat_pointer_clear_focus(g_pCompositor->m_sSeat.seat);
@ -199,7 +214,7 @@ void CInputManager::mouseMoveUnified(uint32_t time, bool refocus) {
} else {
g_pCompositor->focusWindow(pFoundWindow, foundSurface);
}
} else
} else if (pFoundLayerSurface && pFoundLayerSurface->layerSurface->current.keyboard_interactive)
g_pCompositor->focusSurface(foundSurface);
wlr_seat_pointer_notify_enter(g_pCompositor->m_sSeat.seat, foundSurface, surfaceLocal.x, surfaceLocal.y);
@ -211,10 +226,70 @@ void CInputManager::onMouseButton(wlr_pointer_button_event* e) {
m_tmrLastCursorMovement.reset();
switch (m_ecbClickBehavior) {
case CLICKMODE_DEFAULT:
processMouseDownNormal(e);
break;
case CLICKMODE_KILL:
processMouseDownKill(e);
break;
default:
break;
}
}
void CInputManager::processMouseRequest(wlr_seat_pointer_request_set_cursor_event* e) {
if (!g_pHyprRenderer->shouldRenderCursor())
return;
if (!e->surface) {
g_pHyprRenderer->m_bWindowRequestedCursorHide = true;
} else {
g_pHyprRenderer->m_bWindowRequestedCursorHide = false;
}
if (m_ecbClickBehavior == CLICKMODE_KILL) {
wlr_xcursor_manager_set_cursor_image(g_pCompositor->m_sWLRXCursorMgr, "crosshair", g_pCompositor->m_sWLRCursor);
return;
}
if (e->seat_client == g_pCompositor->m_sSeat.seat->pointer_state.focused_client)
wlr_cursor_set_surface(g_pCompositor->m_sWLRCursor, e->surface, e->hotspot_x, e->hotspot_y);
}
eClickBehaviorMode CInputManager::getClickMode() {
return m_ecbClickBehavior;
}
void CInputManager::setClickMode(eClickBehaviorMode mode) {
switch (mode) {
case CLICKMODE_DEFAULT:
Debug::log(LOG, "SetClickMode: DEFAULT");
m_ecbClickBehavior = CLICKMODE_DEFAULT;
wlr_xcursor_manager_set_cursor_image(g_pCompositor->m_sWLRXCursorMgr, "left_ptr", g_pCompositor->m_sWLRCursor);
break;
case CLICKMODE_KILL:
Debug::log(LOG, "SetClickMode: KILL");
m_ecbClickBehavior = CLICKMODE_KILL;
// remove constraints
g_pCompositor->m_sSeat.mouse->constraintActive = false;
refocus();
// set cursor
wlr_xcursor_manager_set_cursor_image(g_pCompositor->m_sWLRXCursorMgr, "crosshair", g_pCompositor->m_sWLRCursor);
break;
default:
break;
}
}
void CInputManager::processMouseDownNormal(wlr_pointer_button_event* e) {
const auto PKEYBOARD = wlr_seat_get_keyboard(g_pCompositor->m_sSeat.seat);
if (!PKEYBOARD) { // ???
Debug::log(ERR, "No active keyboard in onMouseButton??");
if (!PKEYBOARD) { // ???
Debug::log(ERR, "No active keyboard in processMouseDownNormal??");
return;
}
@ -242,7 +317,7 @@ void CInputManager::onMouseButton(wlr_pointer_button_event* e) {
currentlyDraggedWindow = nullptr;
dragButton = -1;
}
break;
}
@ -250,7 +325,30 @@ void CInputManager::onMouseButton(wlr_pointer_button_event* e) {
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);
}
}
void CInputManager::processMouseDownKill(wlr_pointer_button_event* e) {
switch (e->state) {
case WLR_BUTTON_PRESSED: {
const auto PWINDOW = g_pCompositor->m_pLastWindow;
if (!g_pCompositor->windowValidMapped(PWINDOW)){
Debug::log(ERR, "Cannot kill invalid window!");
break;
}
// kill the mf
kill(PWINDOW->getPID(), SIGKILL);
break;
}
case WLR_BUTTON_RELEASED:
break;
default:
break;
}
// reset click behavior mode
m_ecbClickBehavior = CLICKMODE_DEFAULT;
}
void CInputManager::onMouseWheel(wlr_pointer_axis_event* e) {
@ -276,16 +374,15 @@ Vector2D CInputManager::getMouseCoordsInternal() {
}
void CInputManager::newKeyboard(wlr_input_device* keyboard) {
m_lKeyboards.push_back(SKeyboard());
const auto PNEWKEYBOARD = &m_lKeyboards.back();
const auto PNEWKEYBOARD = &m_lKeyboards.emplace_back();
PNEWKEYBOARD->keyboard = keyboard;
const auto REPEATRATE = g_pConfigManager->getInt("input:repeat_rate");
const auto REPEATDELAY = g_pConfigManager->getInt("input:repeat_delay");
wlr_keyboard_set_repeat_info(keyboard->keyboard, std::max(0, REPEATRATE), std::max(0, REPEATDELAY));
try {
PNEWKEYBOARD->name = std::string(keyboard->name);
} catch (std::exception& e) {
Debug::log(ERR, "Keyboard had no name???"); // logic error
}
PNEWKEYBOARD->hyprListener_keyboardMod.initCallback(&keyboard->keyboard->events.modifiers, &Events::listener_keyboardMod, PNEWKEYBOARD, "Keyboard");
PNEWKEYBOARD->hyprListener_keyboardKey.initCallback(&keyboard->keyboard->events.key, &Events::listener_keyboardKey, PNEWKEYBOARD, "Keyboard");
@ -308,20 +405,37 @@ void CInputManager::setKeyboardLayout() {
}
void CInputManager::applyConfigToKeyboard(SKeyboard* pKeyboard) {
const auto HASCONFIG = g_pConfigManager->deviceConfigExists(pKeyboard->name);
ASSERT(pKeyboard);
const auto RULES = g_pConfigManager->getString("input:kb_rules");
const auto MODEL = g_pConfigManager->getString("input:kb_model");
const auto LAYOUT = g_pConfigManager->getString("input:kb_layout");
const auto VARIANT = g_pConfigManager->getString("input:kb_variant");
const auto OPTIONS = g_pConfigManager->getString("input:kb_options");
const auto REPEATRATE = HASCONFIG ? g_pConfigManager->getDeviceInt(pKeyboard->name, "repeat_rate") : g_pConfigManager->getInt("input:repeat_rate");
const auto REPEATDELAY = HASCONFIG ? g_pConfigManager->getDeviceInt(pKeyboard->name, "repeat_delay") : g_pConfigManager->getInt("input:repeat_delay");
if (RULES != "" && RULES == pKeyboard->currentRules.rules && MODEL == pKeyboard->currentRules.model && LAYOUT == pKeyboard->currentRules.layout && VARIANT == pKeyboard->currentRules.variant && OPTIONS == pKeyboard->currentRules.options) {
Debug::log(LOG, "Not applying config to keyboard, it did not change.");
return;
const auto NUMLOCKON = HASCONFIG ? g_pConfigManager->getDeviceInt(pKeyboard->name, "numlock_by_default") : g_pConfigManager->getInt("input:numlock_by_default");
const auto RULES = HASCONFIG ? g_pConfigManager->getDeviceString(pKeyboard->name, "kb_rules") : g_pConfigManager->getString("input:kb_rules");
const auto MODEL = HASCONFIG ? g_pConfigManager->getDeviceString(pKeyboard->name, "kb_model") : g_pConfigManager->getString("input:kb_model");
const auto LAYOUT = HASCONFIG ? g_pConfigManager->getDeviceString(pKeyboard->name, "kb_layout") : g_pConfigManager->getString("input:kb_layout");
const auto VARIANT = HASCONFIG ? g_pConfigManager->getDeviceString(pKeyboard->name, "kb_variant") : g_pConfigManager->getString("input:kb_variant");
const auto OPTIONS = HASCONFIG ? g_pConfigManager->getDeviceString(pKeyboard->name, "kb_options") : g_pConfigManager->getString("input:kb_options");
try {
if (NUMLOCKON == pKeyboard->numlockOn && REPEATDELAY == pKeyboard->repeatDelay && REPEATRATE == pKeyboard->repeatRate && RULES != "" && RULES == std::string(pKeyboard->currentRules.rules) && MODEL == std::string(pKeyboard->currentRules.model) && LAYOUT == std::string(pKeyboard->currentRules.layout) && VARIANT == std::string(pKeyboard->currentRules.variant) && OPTIONS == std::string(pKeyboard->currentRules.options)) {
Debug::log(LOG, "Not applying config to keyboard, it did not change.");
return;
}
} catch (std::exception& e) {
// can be libc errors for null std::string
// we can ignore those and just apply
}
wlr_keyboard_set_repeat_info(pKeyboard->keyboard->keyboard, std::max(0, REPEATRATE), std::max(0, REPEATDELAY));
pKeyboard->repeatDelay = REPEATDELAY;
pKeyboard->repeatRate = REPEATRATE;
pKeyboard->numlockOn = NUMLOCKON;
xkb_rule_names rules = {
.rules = RULES.c_str(),
.model = MODEL.c_str(),
@ -355,7 +469,7 @@ void CInputManager::applyConfigToKeyboard(SKeyboard* pKeyboard) {
wlr_keyboard_modifiers wlrMods = {0};
if (g_pConfigManager->getInt("input:numlock_by_default") == 1) {
if (NUMLOCKON == 1) {
// lock numlock
const auto IDX = xkb_map_mod_get_index(KEYMAP, XKB_MOD_NAME_NUM);
@ -378,37 +492,44 @@ void CInputManager::newMouse(wlr_input_device* mouse) {
const auto PMOUSE = &m_lMice.back();
PMOUSE->mouse = mouse;
try {
PMOUSE->name = std::string(mouse->name);
} catch(std::exception& e) {
Debug::log(ERR, "Mouse had no name???"); // logic error
}
const auto HASCONFIG = g_pConfigManager->deviceConfigExists(PMOUSE->name);
if (wlr_input_device_is_libinput(mouse)) {
const auto LIBINPUTDEV = (libinput_device*)wlr_libinput_get_device_handle(mouse);
if (g_pConfigManager->getInt("input:touchpad:clickfinger_behavior") == 0) // toggle software buttons or clickfinger
if ((HASCONFIG ? g_pConfigManager->getDeviceInt(PMOUSE->name, "clickfinger_behavior") : g_pConfigManager->getInt("input:touchpad:clickfinger_behavior")) == 0) // toggle software buttons or clickfinger
libinput_device_config_click_set_method(LIBINPUTDEV, LIBINPUT_CONFIG_CLICK_METHOD_BUTTON_AREAS);
else
libinput_device_config_click_set_method(LIBINPUTDEV, LIBINPUT_CONFIG_CLICK_METHOD_CLICKFINGER);
if (libinput_device_config_middle_emulation_is_available(LIBINPUTDEV)) { // middleclick on r+l mouse button pressed
if (g_pConfigManager->getInt("input:touchpad:middle_button_emulation") == 1)
if ((HASCONFIG ? g_pConfigManager->getDeviceInt(PMOUSE->name, "middle_button_emulation") : g_pConfigManager->getInt("input:touchpad:middle_button_emulation")) == 1)
libinput_device_config_middle_emulation_set_enabled(LIBINPUTDEV, LIBINPUT_CONFIG_MIDDLE_EMULATION_ENABLED);
else
libinput_device_config_middle_emulation_set_enabled(LIBINPUTDEV, LIBINPUT_CONFIG_MIDDLE_EMULATION_DISABLED);
}
if (libinput_device_config_tap_get_finger_count(LIBINPUTDEV)) // this is for tapping (like on a laptop)
if (g_pConfigManager->getInt("input:touchpad:tap-to-click") == 1)
if ((HASCONFIG ? g_pConfigManager->getDeviceInt(PMOUSE->name, "tap-to-click") : g_pConfigManager->getInt("input:touchpad:tap-to-click")) == 1)
libinput_device_config_tap_set_enabled(LIBINPUTDEV, LIBINPUT_CONFIG_TAP_ENABLED);
if (libinput_device_config_scroll_has_natural_scroll(LIBINPUTDEV)) {
double w = 0, h = 0;
if (libinput_device_has_capability(LIBINPUTDEV, LIBINPUT_DEVICE_CAP_POINTER) && libinput_device_get_size(LIBINPUTDEV, &w, &h) == 0) // pointer with size is a touchpad
libinput_device_config_scroll_set_natural_scroll_enabled(LIBINPUTDEV, g_pConfigManager->getInt("input:touchpad:natural_scroll"));
libinput_device_config_scroll_set_natural_scroll_enabled(LIBINPUTDEV, (HASCONFIG ? g_pConfigManager->getDeviceInt(PMOUSE->name, "natural_scroll") : g_pConfigManager->getInt("input:touchpad:natural_scroll")));
else
libinput_device_config_scroll_set_natural_scroll_enabled(LIBINPUTDEV, g_pConfigManager->getInt("input:natural_scroll"));
libinput_device_config_scroll_set_natural_scroll_enabled(LIBINPUTDEV, (HASCONFIG ? g_pConfigManager->getDeviceInt(PMOUSE->name, "natural_scroll") : g_pConfigManager->getInt("input:natural_scroll")));
}
if (libinput_device_config_dwt_is_available(LIBINPUTDEV)) {
const auto DWT = static_cast<enum libinput_config_dwt_state>(g_pConfigManager->getInt("input:touchpad:disable_while_typing") != 0);
const auto DWT = static_cast<enum libinput_config_dwt_state>((HASCONFIG ? g_pConfigManager->getDeviceInt(PMOUSE->name, "disable_while_typing") : g_pConfigManager->getInt("input:touchpad:disable_while_typing")) != 0);
libinput_device_config_dwt_set_enabled(LIBINPUTDEV, DWT);
}
}
@ -497,9 +618,12 @@ void CInputManager::updateDragIcon() {
switch (g_pInputManager->m_sDrag.dragIcon->drag->grab_type) {
case WLR_DRAG_GRAB_KEYBOARD:
break;
case WLR_DRAG_GRAB_KEYBOARD_POINTER:
case WLR_DRAG_GRAB_KEYBOARD_POINTER: {
wlr_box box = {g_pInputManager->m_sDrag.pos.x - 2, g_pInputManager->m_sDrag.pos.y - 2, g_pInputManager->m_sDrag.dragIcon->surface->current.width + 4, g_pInputManager->m_sDrag.dragIcon->surface->current.height + 4};
g_pHyprRenderer->damageBox(&box);
g_pInputManager->m_sDrag.pos = g_pInputManager->getMouseCoordsInternal();
break;
}
default:
break;
}

View file

@ -6,6 +6,11 @@
#include "../../Window.hpp"
#include "../../helpers/Timer.hpp"
enum eClickBehaviorMode {
CLICKMODE_DEFAULT = 0,
CLICKMODE_KILL
};
class CInputManager {
public:
@ -32,6 +37,10 @@ public:
void updateDragIcon();
void updateCapabilities(wlr_input_device*);
void setClickMode(eClickBehaviorMode);
eClickBehaviorMode getClickMode();
void processMouseRequest(wlr_seat_pointer_request_set_cursor_event*);
// for dragging floating windows
CWindow* currentlyDraggedWindow = nullptr;
@ -58,6 +67,13 @@ public:
private:
// for click behavior override
eClickBehaviorMode m_ecbClickBehavior = CLICKMODE_DEFAULT;
Vector2D m_vLastCursorPosFloored = Vector2D();
void processMouseDownNormal(wlr_pointer_button_event* e);
void processMouseDownKill(wlr_pointer_button_event* e);
uint32_t m_uiCapabilities = 0;
void mouseMoveUnified(uint32_t, bool refocus = false);

View file

@ -4,6 +4,12 @@
void CInputManager::newTabletTool(wlr_input_device* pDevice) {
const auto PNEWTABLET = &m_lTablets.emplace_back();
try {
PNEWTABLET->name = std::string(pDevice->name);
} catch (std::exception& e) {
Debug::log(ERR, "Tablet had no name???"); // logic error
}
PNEWTABLET->wlrTablet = pDevice->tablet;
PNEWTABLET->wlrDevice = pDevice;
PNEWTABLET->wlrTabletV2 = wlr_tablet_create(g_pCompositor->m_sWLRTabletManager, g_pCompositor->m_sSeat.seat, pDevice);
@ -151,6 +157,12 @@ STabletTool* CInputManager::ensureTabletToolPresent(wlr_tablet_tool* pTool) {
void CInputManager::newTabletPad(wlr_input_device* pDevice) {
const auto PNEWPAD = &m_lTabletPads.emplace_back();
try {
PNEWPAD->name = std::string(pDevice->name);
} catch (std::exception& e) {
Debug::log(ERR, "Pad had no name???"); // logic error
}
PNEWPAD->wlrTabletPadV2 = wlr_tablet_pad_create(g_pCompositor->m_sWLRTabletManager, g_pCompositor->m_sSeat.seat, pDevice);
PNEWPAD->hyprListener_Button.initCallback(&pDevice->tablet_pad->events.button, [](void* owner, void* data) {

View file

@ -81,6 +81,12 @@ CHyprOpenGLImpl::CHyprOpenGLImpl() {
m_shSHADOW.posAttrib = glGetAttribLocation(prog, "pos");
m_shSHADOW.texAttrib = glGetAttribLocation(prog, "texcoord");
prog = createProgram(QUADVERTSRC, FRAGBORDER1);
m_shBORDER1.program = prog;
m_shBORDER1.proj = glGetUniformLocation(prog, "proj");
m_shBORDER1.posAttrib = glGetAttribLocation(prog, "pos");
m_shBORDER1.texAttrib = glGetAttribLocation(prog, "texcoord");
Debug::log(LOG, "Shaders initialized successfully.");
// End shaders
@ -138,7 +144,9 @@ void CHyprOpenGLImpl::begin(SMonitor* pMonitor, pixman_region32_t* pDamage, bool
glViewport(0, 0, pMonitor->vecPixelSize.x, pMonitor->vecPixelSize.y);
wlr_matrix_projection(m_RenderData.projection, pMonitor->vecPixelSize.x, pMonitor->vecPixelSize.y, WL_OUTPUT_TRANSFORM_NORMAL); // TODO: this is deprecated
matrixProjection(m_RenderData.projection, pMonitor->vecPixelSize.x, pMonitor->vecPixelSize.y, WL_OUTPUT_TRANSFORM_NORMAL);
m_RenderData.pCurrentMonData = &m_mMonitorRenderResources[pMonitor];
glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
@ -146,22 +154,22 @@ void CHyprOpenGLImpl::begin(SMonitor* pMonitor, pixman_region32_t* pDamage, bool
m_iWLROutputFb = m_iCurrentOutputFb;
// ensure a framebuffer for the monitor exists
if (m_mMonitorRenderResources.find(pMonitor) == m_mMonitorRenderResources.end() || m_mMonitorRenderResources[pMonitor].primaryFB.m_Size != pMonitor->vecPixelSize) {
m_mMonitorRenderResources[pMonitor].stencilTex.allocate();
if (m_mMonitorRenderResources.find(pMonitor) == m_mMonitorRenderResources.end() || m_RenderData.pCurrentMonData->primaryFB.m_Size != pMonitor->vecPixelSize) {
m_RenderData.pCurrentMonData->stencilTex.allocate();
m_mMonitorRenderResources[pMonitor].primaryFB.m_pStencilTex = &m_mMonitorRenderResources[pMonitor].stencilTex;
m_mMonitorRenderResources[pMonitor].mirrorFB.m_pStencilTex = &m_mMonitorRenderResources[pMonitor].stencilTex;
m_mMonitorRenderResources[pMonitor].mirrorSwapFB.m_pStencilTex = &m_mMonitorRenderResources[pMonitor].stencilTex;
m_RenderData.pCurrentMonData->primaryFB.m_pStencilTex = &m_RenderData.pCurrentMonData->stencilTex;
m_RenderData.pCurrentMonData->mirrorFB.m_pStencilTex = &m_RenderData.pCurrentMonData->stencilTex;
m_RenderData.pCurrentMonData->mirrorSwapFB.m_pStencilTex = &m_RenderData.pCurrentMonData->stencilTex;
m_mMonitorRenderResources[pMonitor].primaryFB.alloc(pMonitor->vecPixelSize.x, pMonitor->vecPixelSize.y);
m_mMonitorRenderResources[pMonitor].mirrorFB.alloc(pMonitor->vecPixelSize.x, pMonitor->vecPixelSize.y);
m_mMonitorRenderResources[pMonitor].mirrorSwapFB.alloc(pMonitor->vecPixelSize.x, pMonitor->vecPixelSize.y);
m_RenderData.pCurrentMonData->primaryFB.alloc(pMonitor->vecPixelSize.x, pMonitor->vecPixelSize.y);
m_RenderData.pCurrentMonData->mirrorFB.alloc(pMonitor->vecPixelSize.x, pMonitor->vecPixelSize.y);
m_RenderData.pCurrentMonData->mirrorSwapFB.alloc(pMonitor->vecPixelSize.x, pMonitor->vecPixelSize.y);
createBGTextureForMonitor(pMonitor);
}
// bind the primary Hypr Framebuffer
m_mMonitorRenderResources[pMonitor].primaryFB.bind();
m_RenderData.pCurrentMonData->primaryFB.bind();
m_RenderData.pDamage = pDamage;
@ -180,7 +188,7 @@ void CHyprOpenGLImpl::end() {
m_bEndFrame = true;
renderTexture(m_mMonitorRenderResources[m_RenderData.pMonitor].primaryFB.m_cTex, &monbox, 255.f, 0);
renderTexture(m_RenderData.pCurrentMonData->primaryFB.m_cTex, &monbox, 255.f, 0);
m_bEndFrame = false;
}
@ -277,11 +285,11 @@ void CHyprOpenGLImpl::renderRectWithDamage(wlr_box* box, const CColor& col, pixm
static auto *const PMULTISAMPLEEDGES = &g_pConfigManager->getConfigValuePtr("decoration:multisample_edges")->intValue;
// Rounded corners
glUniform2f(glGetUniformLocation(m_shQUAD.program, "topLeft"), (float)TOPLEFT.x, (float)TOPLEFT.y);
glUniform2f(glGetUniformLocation(m_shQUAD.program, "bottomRight"), (float)BOTTOMRIGHT.x, (float)BOTTOMRIGHT.y);
glUniform2f(glGetUniformLocation(m_shQUAD.program, "fullSize"), (float)FULLSIZE.x, (float)FULLSIZE.y);
glUniform1f(glGetUniformLocation(m_shQUAD.program, "radius"), round);
glUniform1i(glGetUniformLocation(m_shQUAD.program, "primitiveMultisample"), (int)(*PMULTISAMPLEEDGES == 1 && round != 0));
glUniform2f(m_shQUAD.getUniformLocation("topLeft"), (float)TOPLEFT.x, (float)TOPLEFT.y);
glUniform2f(m_shQUAD.getUniformLocation("bottomRight"), (float)BOTTOMRIGHT.x, (float)BOTTOMRIGHT.y);
glUniform2f(m_shQUAD.getUniformLocation("fullSize"), (float)FULLSIZE.x, (float)FULLSIZE.y);
glUniform1f(m_shQUAD.getUniformLocation("radius"), round);
glUniform1i(m_shQUAD.getUniformLocation("primitiveMultisample"), (int)(*PMULTISAMPLEEDGES == 1 && round != 0));
glVertexAttribPointer(m_shQUAD.posAttrib, 2, GL_FLOAT, GL_FALSE, 0, fullVerts);
glVertexAttribPointer(m_shQUAD.texAttrib, 2, GL_FLOAT, GL_FALSE, 0, fullVerts);
@ -309,15 +317,15 @@ void CHyprOpenGLImpl::renderTexture(wlr_texture* tex, wlr_box* pBox, float alpha
renderTexture(CTexture(tex), pBox, alpha, round);
}
void CHyprOpenGLImpl::renderTexture(const CTexture& tex, wlr_box* pBox, float alpha, int round, bool discardopaque, bool border, bool allowPrimary) {
void CHyprOpenGLImpl::renderTexture(const CTexture& tex, wlr_box* pBox, float alpha, int round, bool discardopaque, bool allowPrimary) {
RASSERT(m_RenderData.pMonitor, "Tried to render texture without begin()!");
renderTextureInternalWithDamage(tex, pBox, alpha, m_RenderData.pDamage, round, discardopaque, border, false, allowPrimary);
renderTextureInternalWithDamage(tex, pBox, alpha, m_RenderData.pDamage, round, discardopaque, false, allowPrimary);
scissor((wlr_box*)nullptr);
}
void CHyprOpenGLImpl::renderTextureInternalWithDamage(const CTexture& tex, wlr_box* pBox, float alpha, pixman_region32_t* damage, int round, bool discardOpaque, bool border, bool noAA, bool allowPrimary) {
void CHyprOpenGLImpl::renderTextureInternalWithDamage(const CTexture& tex, wlr_box* pBox, float alpha, pixman_region32_t* damage, int round, bool discardOpaque, bool noAA, bool allowPrimary) {
RASSERT(m_RenderData.pMonitor, "Tried to render texture without begin()!");
RASSERT((tex.m_iTexID > 0), "Attempted to draw NULL texture!");
@ -351,23 +359,6 @@ void CHyprOpenGLImpl::renderTextureInternalWithDamage(const CTexture& tex, wlr_b
RASSERT(false, "tex.m_iTarget unsupported!");
}
// stencil for when we want a border
if (border) {
glClearStencil(0);
glClear(GL_STENCIL_BUFFER_BIT);
glEnable(GL_STENCIL_TEST);
glStencilFunc(GL_ALWAYS, 1, -1);
glStencilOp(GL_REPLACE, GL_REPLACE, GL_REPLACE);
// hacky fix to fix broken borders.
// TODO: this is kinda slow... question mark?
renderRect(pBox, CColor(0, 0, 0, 0), round);
glDisable(GL_STENCIL_TEST);
}
glActiveTexture(GL_TEXTURE0);
glBindTexture(tex.m_iTarget, tex.m_iTexID);
@ -389,11 +380,11 @@ void CHyprOpenGLImpl::renderTextureInternalWithDamage(const CTexture& tex, wlr_b
static auto *const PMULTISAMPLEEDGES = &g_pConfigManager->getConfigValuePtr("decoration:multisample_edges")->intValue;
// Rounded corners
glUniform2f(glGetUniformLocation(shader->program, "topLeft"), (float)TOPLEFT.x, (float)TOPLEFT.y);
glUniform2f(glGetUniformLocation(shader->program, "bottomRight"), (float)BOTTOMRIGHT.x, (float)BOTTOMRIGHT.y);
glUniform2f(glGetUniformLocation(shader->program, "fullSize"), (float)FULLSIZE.x, (float)FULLSIZE.y);
glUniform1f(glGetUniformLocation(shader->program, "radius"), round);
glUniform1i(glGetUniformLocation(shader->program, "primitiveMultisample"), (int)(*PMULTISAMPLEEDGES == 1 && round != 0 && !border && !noAA));
glUniform2f(shader->getUniformLocation("topLeft"), (float)TOPLEFT.x, (float)TOPLEFT.y);
glUniform2f(shader->getUniformLocation("bottomRight"), (float)BOTTOMRIGHT.x, (float)BOTTOMRIGHT.y);
glUniform2f(shader->getUniformLocation("fullSize"), (float)FULLSIZE.x, (float)FULLSIZE.y);
glUniform1f(shader->getUniformLocation("radius"), round);
glUniform1i(shader->getUniformLocation("primitiveMultisample"), (int)(*PMULTISAMPLEEDGES == 1 && round != 0 && !noAA));
glVertexAttribPointer(shader->posAttrib, 2, GL_FLOAT, GL_FALSE, 0, fullVerts);
@ -421,30 +412,10 @@ void CHyprOpenGLImpl::renderTextureInternalWithDamage(const CTexture& tex, wlr_b
}
}
if (border) {
glEnable(GL_STENCIL_TEST);
glStencilFunc(GL_EQUAL, 1, -1);
glStencilOp(GL_KEEP, GL_KEEP, GL_REPLACE);
}
glDisableVertexAttribArray(shader->posAttrib);
glDisableVertexAttribArray(shader->texAttrib);
glBindTexture(tex.m_iTarget, 0);
// if border draw
// we dont disable stencil here if we havent touched it.
// some other func might be using it.
if (border) {
auto BORDERCOL = m_pCurrentWindow->m_cRealBorderColor.col();
static auto *const PBORDERSIZE = &g_pConfigManager->getConfigValuePtr("general:border_size")->intValue;
BORDERCOL.a *= alpha / 255.f;
renderBorder(pBox, BORDERCOL, *PBORDERSIZE, round);
glStencilMask(-1);
glStencilFunc(GL_ALWAYS, 1, 0xFF);
glDisable(GL_STENCIL_TEST);
}
}
// This probably isn't the fastest
@ -478,10 +449,10 @@ CFramebuffer* CHyprOpenGLImpl::blurMainFramebufferWithDamage(float a, wlr_box* p
wlr_region_expand(&damage, &damage, pow(2, *PBLURPASSES) * *PBLURSIZE);
// helper
const auto PMIRRORFB = &m_mMonitorRenderResources[m_RenderData.pMonitor].mirrorFB;
const auto PMIRRORSWAPFB = &m_mMonitorRenderResources[m_RenderData.pMonitor].mirrorSwapFB;
const auto PMIRRORFB = &m_RenderData.pCurrentMonData->mirrorFB;
const auto PMIRRORSWAPFB = &m_RenderData.pCurrentMonData->mirrorSwapFB;
CFramebuffer* currentRenderToFB = &m_mMonitorRenderResources[m_RenderData.pMonitor].primaryFB;
CFramebuffer* currentRenderToFB = &m_RenderData.pCurrentMonData->primaryFB;
// declare the draw func
auto drawPass = [&](CShader* pShader, pixman_region32_t* pDamage) {
@ -500,11 +471,11 @@ CFramebuffer* CHyprOpenGLImpl::blurMainFramebufferWithDamage(float a, wlr_box* p
// prep two shaders
glUniformMatrix3fv(pShader->proj, 1, GL_FALSE, glMatrix);
glUniform1f(glGetUniformLocation(pShader->program, "radius"), *PBLURSIZE * (a / 255.f)); // this makes the blursize change with a
glUniform1f(pShader->getUniformLocation("radius"), *PBLURSIZE * (a / 255.f)); // this makes the blursize change with a
if (pShader == &m_shBLUR1)
glUniform2f(glGetUniformLocation(m_shBLUR1.program, "halfpixel"), 0.5f / (m_RenderData.pMonitor->vecPixelSize.x / 2.f), 0.5f / (m_RenderData.pMonitor->vecPixelSize.y / 2.f));
glUniform2f(m_shBLUR1.getUniformLocation("halfpixel"), 0.5f / (m_RenderData.pMonitor->vecPixelSize.x / 2.f), 0.5f / (m_RenderData.pMonitor->vecPixelSize.y / 2.f));
else
glUniform2f(glGetUniformLocation(m_shBLUR2.program, "halfpixel"), 0.5f / (m_RenderData.pMonitor->vecPixelSize.x * 2.f), 0.5f / (m_RenderData.pMonitor->vecPixelSize.y * 2.f));
glUniform2f(m_shBLUR2.getUniformLocation("halfpixel"), 0.5f / (m_RenderData.pMonitor->vecPixelSize.x * 2.f), 0.5f / (m_RenderData.pMonitor->vecPixelSize.y * 2.f));
glUniform1i(pShader->tex, 0);
glVertexAttribPointer(pShader->posAttrib, 2, GL_FLOAT, GL_FALSE, 0, fullVerts);
@ -534,7 +505,7 @@ CFramebuffer* CHyprOpenGLImpl::blurMainFramebufferWithDamage(float a, wlr_box* p
// draw the things.
// first draw is prim -> mirr
PMIRRORFB->bind();
glBindTexture(m_mMonitorRenderResources[m_RenderData.pMonitor].primaryFB.m_cTex.m_iTarget, m_mMonitorRenderResources[m_RenderData.pMonitor].primaryFB.m_cTex.m_iTexID);
glBindTexture(m_RenderData.pCurrentMonData->primaryFB.m_cTex.m_iTarget, m_RenderData.pCurrentMonData->primaryFB.m_cTex.m_iTexID);
// damage region will be scaled, make a temp
pixman_region32_t tempDamage;
@ -566,14 +537,14 @@ CFramebuffer* CHyprOpenGLImpl::blurMainFramebufferWithDamage(float a, wlr_box* p
return currentRenderToFB;
}
void CHyprOpenGLImpl::renderTextureWithBlur(const CTexture& tex, wlr_box* pBox, float a, wlr_surface* pSurface, int round, bool border) {
void CHyprOpenGLImpl::renderTextureWithBlur(const CTexture& tex, wlr_box* pBox, float a, wlr_surface* pSurface, int round) {
RASSERT(m_RenderData.pMonitor, "Tried to render texture with blur without begin()!");
static auto *const PBLURENABLED = &g_pConfigManager->getConfigValuePtr("decoration:blur")->intValue;
static auto* const PNOBLUROVERSIZED = &g_pConfigManager->getConfigValuePtr("decoration:no_blur_on_oversized")->intValue;
if (*PBLURENABLED == 0 || (*PNOBLUROVERSIZED && m_RenderData.primarySurfaceUVTopLeft != Vector2D(-1, -1)) || (m_pCurrentWindow && m_pCurrentWindow->m_sAdditionalConfigData.forceNoBlur)) {
renderTexture(tex, pBox, a, round, false, border, true);
renderTexture(tex, pBox, a, round, false, true);
return;
}
@ -596,7 +567,7 @@ void CHyprOpenGLImpl::renderTextureWithBlur(const CTexture& tex, wlr_box* pBox,
}
if (!pixman_region32_not_empty(&inverseOpaque)) {
renderTexture(tex, pBox, a, round, false, border); // reject blurring a fully opaque window
renderTexture(tex, pBox, a, round, false); // reject blurring a fully opaque window
return;
}
@ -606,7 +577,7 @@ void CHyprOpenGLImpl::renderTextureWithBlur(const CTexture& tex, wlr_box* pBox,
pixman_region32_fini(&inverseOpaque);
// bind primary
m_mMonitorRenderResources[m_RenderData.pMonitor].primaryFB.bind();
m_RenderData.pCurrentMonData->primaryFB.bind();
// make a stencil for rounded corners to work with blur
scissor((wlr_box*)nullptr); // allow the entire window and stencil to render
@ -630,7 +601,7 @@ void CHyprOpenGLImpl::renderTextureWithBlur(const CTexture& tex, wlr_box* pBox,
if (pixman_region32_not_empty(&damage)) {
// render our great blurred FB
static auto *const PBLURIGNOREOPACITY = &g_pConfigManager->getConfigValuePtr("decoration:blur_ignore_opacity")->intValue;
renderTextureInternalWithDamage(POUTFB->m_cTex, &MONITORBOX, *PBLURIGNOREOPACITY ? 255.f : a, &damage, 0, false, false, false, true);
renderTextureInternalWithDamage(POUTFB->m_cTex, &MONITORBOX, *PBLURIGNOREOPACITY ? 255.f : a, &damage, 0, false, false, true);
// render the window, but clear stencil
glClearStencil(0);
@ -638,36 +609,11 @@ void CHyprOpenGLImpl::renderTextureWithBlur(const CTexture& tex, wlr_box* pBox,
// draw window
glDisable(GL_STENCIL_TEST);
renderTextureInternalWithDamage(tex, pBox, a, &damage, round, false, false, true, true);
glEnable(GL_STENCIL_TEST);
// prep stencil for border
glStencilFunc(GL_ALWAYS, 1, -1);
glStencilOp(GL_KEEP, GL_KEEP, GL_REPLACE);
if (border) {
// hacky fix to fix broken borders.
// TODO: this is kinda slow... question mark?
renderRectWithDamage(pBox, CColor(0,0,0,0), &damage, round);
}
// then stop
glStencilFunc(GL_EQUAL, 1, -1);
glStencilOp(GL_KEEP, GL_KEEP, GL_REPLACE);
renderTextureInternalWithDamage(tex, pBox, a, &damage, round, false, false, true);
}
// disable the stencil (if no border), finalize everything
if (!border) {
glStencilMask(-1);
glStencilFunc(GL_ALWAYS, 1, 0xFF);
} else {
auto BORDERCOL = m_pCurrentWindow->m_cRealBorderColor.col();
BORDERCOL.a *= a / 255.f;
static auto *const PBORDERSIZE = &g_pConfigManager->getConfigValuePtr("general:border_size")->intValue;
renderBorder(pBox, BORDERCOL, *PBORDERSIZE, round);
}
glDisable(GL_STENCIL_TEST);
glStencilMask(-1);
glStencilFunc(GL_ALWAYS, 1, 0xFF);
pixman_region32_fini(&damage);
scissor((wlr_box*)nullptr);
}
@ -679,23 +625,67 @@ void pushVert2D(float x, float y, float* arr, int& counter, wlr_box* box) {
counter++;
}
void CHyprOpenGLImpl::renderBorder(wlr_box* box, const CColor& col, int thick, int round) {
void CHyprOpenGLImpl::renderBorder(wlr_box* box, const CColor& col, int round) {
RASSERT((box->width > 0 && box->height > 0), "Tried to render rect with width/height < 0!");
RASSERT(m_RenderData.pMonitor, "Tried to render rect without begin()!");
// this method assumes a set stencil and scaled box
box->x -= thick;
box->y -= thick;
box->width += 2 * thick;
box->height += 2 * thick;
static auto *const PBORDERSIZE = &g_pConfigManager->getConfigValuePtr("general:border_size")->intValue;
static auto *const PMULTISAMPLE = &g_pConfigManager->getConfigValuePtr("decoration:multisample_edges")->intValue;
round += thick; // cuz yeah
// adjust box
box->x -= *PBORDERSIZE;
box->y -= *PBORDERSIZE;
box->width += 2 * *PBORDERSIZE;
box->height += 2 * *PBORDERSIZE;
// only draw on non-stencild.
glStencilFunc(GL_NOTEQUAL, 1, -1);
round += *PBORDERSIZE;
// draw a rounded rect
renderRect(box, col, round);
float matrix[9];
wlr_matrix_project_box(matrix, box, wlr_output_transform_invert(!m_bEndFrame ? WL_OUTPUT_TRANSFORM_NORMAL : m_RenderData.pMonitor->transform), 0, m_RenderData.pMonitor->output->transform_matrix); // TODO: write own, don't use WLR here
float glMatrix[9];
wlr_matrix_multiply(glMatrix, m_RenderData.projection, matrix);
wlr_matrix_multiply(glMatrix, matrixFlip180, glMatrix);
wlr_matrix_transpose(glMatrix, glMatrix);
glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
glUseProgram(m_shBORDER1.program);
glUniformMatrix3fv(m_shBORDER1.proj, 1, GL_FALSE, glMatrix);
glUniform4f(m_shBORDER1.getUniformLocation("color"), col.r / 255.f, col.g / 255.f, col.b / 255.f, col.a / 255.f);
const auto TOPLEFT = Vector2D(round, round);
const auto BOTTOMRIGHT = Vector2D(box->width - round, box->height - round);
const auto FULLSIZE = Vector2D(box->width, box->height);
glUniform2f(m_shBORDER1.getUniformLocation("topLeft"), (float)TOPLEFT.x, (float)TOPLEFT.y);
glUniform2f(m_shBORDER1.getUniformLocation("bottomRight"), (float)BOTTOMRIGHT.x, (float)BOTTOMRIGHT.y);
glUniform2f(m_shBORDER1.getUniformLocation("fullSize"), (float)FULLSIZE.x, (float)FULLSIZE.y);
glUniform1f(m_shBORDER1.getUniformLocation("radius"), round);
glUniform1f(m_shBORDER1.getUniformLocation("thick"), *PBORDERSIZE);
glUniform1i(m_shBORDER1.getUniformLocation("primitiveMultisample"), *PMULTISAMPLE);
glVertexAttribPointer(m_shBORDER1.posAttrib, 2, GL_FLOAT, GL_FALSE, 0, fullVerts);
glVertexAttribPointer(m_shBORDER1.texAttrib, 2, GL_FLOAT, GL_FALSE, 0, fullVerts);
glEnableVertexAttribArray(m_shBORDER1.posAttrib);
glEnableVertexAttribArray(m_shBORDER1.texAttrib);
if (pixman_region32_not_empty(m_RenderData.pDamage)) {
PIXMAN_DAMAGE_FOREACH(m_RenderData.pDamage) {
const auto RECT = RECTSARR[i];
scissor(&RECT);
glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
}
}
glDisableVertexAttribArray(m_shBORDER1.posAttrib);
glDisableVertexAttribArray(m_shBORDER1.texAttrib);
glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
}
void CHyprOpenGLImpl::makeWindowSnapshot(CWindow* pWindow) {
@ -744,7 +734,7 @@ void CHyprOpenGLImpl::makeWindowSnapshot(CWindow* pWindow) {
clear(CColor(0, 0, 0, 0)); // JIC
wlr_box fullMonBox = {0, 0, PMONITOR->vecPixelSize.x, PMONITOR->vecPixelSize.y};
renderTexture(m_mMonitorRenderResources[m_RenderData.pMonitor].primaryFB.m_cTex, &fullMonBox, 255.f, 0);
renderTexture(m_RenderData.pCurrentMonData->primaryFB.m_cTex, &fullMonBox, 255.f, 0);
// restore original fb
#ifndef GLES2
@ -823,12 +813,13 @@ void CHyprOpenGLImpl::renderSnapshot(CWindow** pWindow) {
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));
// the originalClosedPos is relative to the monitor's pos
Vector2D scaleXY = Vector2D((PMONITOR->scale * PWINDOW->m_vRealSize.vec().x / (PWINDOW->m_vOriginalClosedSize.x * PMONITOR->scale)), (PMONITOR->scale * PWINDOW->m_vRealSize.vec().y / (PWINDOW->m_vOriginalClosedSize.y * PMONITOR->scale)));
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);
windowBox.x = ((PWINDOW->m_vRealPosition.vec().x - PMONITOR->vecPosition.x) * PMONITOR->scale) - ((PWINDOW->m_vOriginalClosedPos.x * PMONITOR->scale) * scaleXY.x);
windowBox.y = ((PWINDOW->m_vRealPosition.vec().y - PMONITOR->vecPosition.y) * PMONITOR->scale) - ((PWINDOW->m_vOriginalClosedPos.y * PMONITOR->scale) * scaleXY.y);
pixman_region32_t fakeDamage;
pixman_region32_init_rect(&fakeDamage, 0, 0, PMONITOR->vecPixelSize.x, PMONITOR->vecPixelSize.y);
@ -870,7 +861,6 @@ void CHyprOpenGLImpl::renderRoundedShadow(wlr_box* box, int round, int range, fl
static auto *const PSHADOWCOL = &g_pConfigManager->getConfigValuePtr("decoration:col.shadow")->intValue;
static auto *const PSHADOWPOWER = &g_pConfigManager->getConfigValuePtr("decoration:shadow_render_power")->intValue;
static auto *const PSHADOWIGNOREWINDOW = &g_pConfigManager->getConfigValuePtr("decoration:shadow_ignore_window")->intValue;
const auto SHADOWPOWER = std::clamp((int)*PSHADOWPOWER, 1, 4);
@ -891,20 +881,19 @@ void CHyprOpenGLImpl::renderRoundedShadow(wlr_box* box, int round, int range, fl
glUseProgram(m_shSHADOW.program);
glUniformMatrix3fv(m_shSHADOW.proj, 1, GL_FALSE, glMatrix);
glUniform4f(glGetUniformLocation(m_shSHADOW.program, "color"), col.r / 255.f, col.g / 255.f, col.b / 255.f, col.a / 255.f * a);
glUniform4f(m_shSHADOW.getUniformLocation("color"), col.r / 255.f, col.g / 255.f, col.b / 255.f, col.a / 255.f * a);
const auto TOPLEFT = Vector2D(range + round, range + round);
const auto BOTTOMRIGHT = Vector2D(box->width - (range + round), box->height - (range + round));
const auto FULLSIZE = Vector2D(box->width, box->height);
// Rounded corners
glUniform2f(glGetUniformLocation(m_shSHADOW.program, "topLeft"), (float)TOPLEFT.x, (float)TOPLEFT.y);
glUniform2f(glGetUniformLocation(m_shSHADOW.program, "bottomRight"), (float)BOTTOMRIGHT.x, (float)BOTTOMRIGHT.y);
glUniform2f(glGetUniformLocation(m_shSHADOW.program, "fullSize"), (float)FULLSIZE.x, (float)FULLSIZE.y);
glUniform1f(glGetUniformLocation(m_shSHADOW.program, "radius"), range + round);
glUniform1f(glGetUniformLocation(m_shSHADOW.program, "range"), range);
glUniform1f(glGetUniformLocation(m_shSHADOW.program, "shadowPower"), SHADOWPOWER);
glUniform1i(glGetUniformLocation(m_shSHADOW.program, "ignoreWindow"), *PSHADOWIGNOREWINDOW);
glUniform2f(m_shSHADOW.getUniformLocation("topLeft"), (float)TOPLEFT.x, (float)TOPLEFT.y);
glUniform2f(m_shSHADOW.getUniformLocation("bottomRight"), (float)BOTTOMRIGHT.x, (float)BOTTOMRIGHT.y);
glUniform2f(m_shSHADOW.getUniformLocation("fullSize"), (float)FULLSIZE.x, (float)FULLSIZE.y);
glUniform1f(m_shSHADOW.getUniformLocation("radius"), range + round);
glUniform1f(m_shSHADOW.getUniformLocation("range"), range);
glUniform1f(m_shSHADOW.getUniformLocation("shadowPower"), SHADOWPOWER);
glVertexAttribPointer(m_shSHADOW.posAttrib, 2, GL_FLOAT, GL_FALSE, 0, fullVerts);
glVertexAttribPointer(m_shSHADOW.texAttrib, 2, GL_FLOAT, GL_FALSE, 0, fullVerts);

View file

@ -29,17 +29,6 @@ inline const float fanVertsFull[] = {
-1.0f, 1.0f
};
struct SCurrentRenderData {
SMonitor* pMonitor = nullptr;
float projection[9];
pixman_region32_t* pDamage = nullptr;
bool renderingPrimarySurface = false;
Vector2D primarySurfaceUVTopLeft = Vector2D(-1, -1);
Vector2D primarySurfaceUVBottomRight = Vector2D(-1, -1);
};
struct SMonitorRenderData {
CFramebuffer primaryFB;
CFramebuffer mirrorFB;
@ -48,6 +37,19 @@ struct SMonitorRenderData {
CTexture stencilTex;
};
struct SCurrentRenderData {
SMonitor* pMonitor = nullptr;
float projection[9];
SMonitorRenderData* pCurrentMonData = nullptr;
pixman_region32_t* pDamage = nullptr;
bool renderingPrimarySurface = false;
Vector2D primarySurfaceUVTopLeft = Vector2D(-1, -1);
Vector2D primarySurfaceUVBottomRight = Vector2D(-1, -1);
};
class CHyprOpenGLImpl {
public:
@ -59,9 +61,10 @@ public:
void renderRect(wlr_box*, const CColor&, int round = 0);
void renderRectWithDamage(wlr_box*, const CColor&, pixman_region32_t* damage, int round = 0);
void renderTexture(wlr_texture*, wlr_box*, float a, int round = 0);
void renderTexture(const CTexture&, wlr_box*, float a, int round = 0, bool discardOpaque = false, bool border = false, bool allowPrimary = false);
void renderTextureWithBlur(const CTexture&, wlr_box*, float a, wlr_surface* pSurface, int round = 0, bool border = false);
void renderTexture(const CTexture&, wlr_box*, float a, int round = 0, bool discardOpaque = false, bool allowPrimary = false);
void renderTextureWithBlur(const CTexture&, wlr_box*, float a, wlr_surface* pSurface, int round = 0);
void renderRoundedShadow(wlr_box*, int round, int range, float a = 1.0);
void renderBorder(wlr_box*, const CColor&, int round);
void makeWindowSnapshot(CWindow*);
void makeLayerSnapshot(SLayerSurface*);
@ -101,13 +104,14 @@ private:
bool m_bEndFrame = false;
// Shaders
SQuad m_shQUAD;
CShader m_shQUAD;
CShader m_shRGBA;
CShader m_shRGBX;
CShader m_shEXT;
CShader m_shBLUR1;
CShader m_shBLUR2;
CShader m_shSHADOW;
CShader m_shBORDER1;
//
GLuint createProgram(const std::string&, const std::string&);
@ -117,8 +121,7 @@ private:
// returns the out FB, can be either Mirror or MirrorSwap
CFramebuffer* blurMainFramebufferWithDamage(float a, wlr_box* pBox, pixman_region32_t* damage);
void renderTextureInternalWithDamage(const CTexture&, wlr_box* pBox, float a, pixman_region32_t* damage, int round = 0, bool discardOpaque = false, bool border = false, bool noAA = false, bool allowPrimary = false);
void renderBorder(wlr_box*, const CColor&, int thick = 1, int round = 0);
void renderTextureInternalWithDamage(const CTexture&, wlr_box* pBox, float a, pixman_region32_t* damage, int round = 0, bool discardOpaque = false, bool noAA = false, bool allowPrimary = false);
};
inline std::unique_ptr<CHyprOpenGLImpl> g_pHyprOpenGL;

View file

@ -27,7 +27,13 @@ void renderSurface(struct wlr_surface* surface, int x, int y, void* data) {
if (RDATA->surface && surface == RDATA->surface) {
g_pHyprOpenGL->m_RenderData.renderingPrimarySurface = true;
g_pHyprOpenGL->renderTextureWithBlur(TEXTURE, &windowBox, RDATA->fadeAlpha * RDATA->alpha, surface, rounding, RDATA->decorate);
g_pHyprOpenGL->renderTextureWithBlur(TEXTURE, &windowBox, RDATA->fadeAlpha * RDATA->alpha, surface, rounding);
if (RDATA->decorate) {
auto col = g_pHyprOpenGL->m_pCurrentWindow->m_cRealBorderColor.col();
col.a *= RDATA->fadeAlpha * RDATA->alpha / 255.f;
g_pHyprOpenGL->renderBorder(&windowBox, col, rounding);
}
}
else
g_pHyprOpenGL->renderTexture(TEXTURE, &windowBox, RDATA->fadeAlpha * RDATA->alpha, rounding, false, false);
@ -68,11 +74,11 @@ bool CHyprRenderer::shouldRenderWindow(CWindow* pWindow) {
if (g_pCompositor->isWorkspaceVisible(pWindow->m_iWorkspaceID))
return true;
for (auto& m : g_pCompositor->m_lMonitors) {
if (PWORKSPACE && PWORKSPACE->m_iMonitorID == m.ID && (PWORKSPACE->m_vRenderOffset.isBeingAnimated() || PWORKSPACE->m_fAlpha.isBeingAnimated()))
for (auto& m : g_pCompositor->m_vMonitors) {
if (PWORKSPACE && PWORKSPACE->m_iMonitorID == m->ID && (PWORKSPACE->m_vRenderOffset.isBeingAnimated() || PWORKSPACE->m_fAlpha.isBeingAnimated()))
return true;
if (m.specialWorkspaceOpen && pWindow->m_iWorkspaceID == SPECIAL_WORKSPACE_ID)
if (m->specialWorkspaceOpen && pWindow->m_iWorkspaceID == SPECIAL_WORKSPACE_ID)
return true;
}
@ -82,37 +88,37 @@ bool CHyprRenderer::shouldRenderWindow(CWindow* pWindow) {
void CHyprRenderer::renderWorkspaceWithFullscreenWindow(SMonitor* pMonitor, CWorkspace* pWorkspace, timespec* time) {
CWindow* pWorkspaceWindow = nullptr;
for (auto& w : g_pCompositor->m_lWindows) {
if (w.m_iWorkspaceID != pWorkspace->m_iID || !w.m_bIsFullscreen)
for (auto& w : g_pCompositor->m_vWindows) {
if (w->m_iWorkspaceID != pWorkspace->m_iID || !w->m_bIsFullscreen)
continue;
// found it!
renderWindow(&w, pMonitor, time, pWorkspace->m_efFullscreenMode != FULLSCREEN_FULL);
renderWindow(w.get(), pMonitor, time, pWorkspace->m_efFullscreenMode != FULLSCREEN_FULL);
pWorkspaceWindow = &w;
pWorkspaceWindow = w.get();
}
// then render windows over fullscreen
for (auto& w : g_pCompositor->m_lWindows) {
if (w.m_iWorkspaceID != pWorkspaceWindow->m_iWorkspaceID || !w.m_bCreatedOverFullscreen || !w.m_bIsMapped)
for (auto& w : g_pCompositor->m_vWindows) {
if (w->m_iWorkspaceID != pWorkspaceWindow->m_iWorkspaceID || !w->m_bCreatedOverFullscreen || !w->m_bIsMapped)
continue;
renderWindow(&w, pMonitor, time, true);
renderWindow(w.get(), pMonitor, time, true);
}
// and then special windows
for (auto& w : g_pCompositor->m_lWindows) {
if (!g_pCompositor->windowValidMapped(&w) && !w.m_bFadingOut)
for (auto& w : g_pCompositor->m_vWindows) {
if (!g_pCompositor->windowValidMapped(w.get()) && !w->m_bFadingOut)
continue;
if (w.m_iWorkspaceID != SPECIAL_WORKSPACE_ID)
if (w->m_iWorkspaceID != SPECIAL_WORKSPACE_ID)
continue;
if (!shouldRenderWindow(&w, pMonitor))
if (!shouldRenderWindow(w.get(), pMonitor))
continue;
// render the bad boy
renderWindow(&w, pMonitor, time, true);
renderWindow(w.get(), pMonitor, time, true);
}
// and the overlay layers
@ -130,7 +136,7 @@ void CHyprRenderer::renderWorkspaceWithFullscreenWindow(SMonitor* pMonitor, CWor
renderDragIcon(pMonitor, time);
// if correct monitor draw hyprerror
if (pMonitor == &g_pCompositor->m_lMonitors.front())
if (pMonitor == g_pCompositor->m_vMonitors.front().get())
g_pHyprError->draw();
}
@ -155,7 +161,7 @@ void CHyprRenderer::renderWindow(CWindow* pWindow, SMonitor* pMonitor, timespec*
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 && (pWindow->m_bIsFloating ? *PNOFLOATINGBORDERS == 0 : true);
renderdata.decorate = decorate && !pWindow->m_bX11DoesntWantBorders && (pWindow->m_bIsFloating ? *PNOFLOATINGBORDERS == 0 : true) && (!pWindow->m_bIsFullscreen || PWORKSPACE->m_efFullscreenMode != FULLSCREEN_FULL);
renderdata.rounding = pWindow->m_sAdditionalConfigData.rounding;
// apply window special data
@ -166,8 +172,8 @@ void CHyprRenderer::renderWindow(CWindow* pWindow, SMonitor* pMonitor, timespec*
g_pHyprOpenGL->m_pCurrentWindow = pWindow;
// render window decorations first
for (auto& wd : pWindow->m_dWindowDecorations)
// render window decorations first, if not fullscreen full
if (!pWindow->m_bIsFullscreen || PWORKSPACE->m_efFullscreenMode != FULLSCREEN_FULL) for (auto& wd : pWindow->m_dWindowDecorations)
wd->draw(pMonitor, renderdata.alpha * renderdata.fadeAlpha / 255.f);
if (!pWindow->m_bIsX11) {
@ -238,54 +244,54 @@ void CHyprRenderer::renderAllClientsForMonitor(const int& ID, timespec* time) {
}
// Non-floating
for (auto& w : g_pCompositor->m_lWindows) {
if (!g_pCompositor->windowValidMapped(&w) && !w.m_bFadingOut)
for (auto& w : g_pCompositor->m_vWindows) {
if (w->m_bHidden && !w->m_bIsMapped && !w->m_bFadingOut)
continue;
if (w.m_bIsFloating)
if (w->m_bIsFloating)
continue; // floating are in the second pass
if (w.m_iWorkspaceID == SPECIAL_WORKSPACE_ID)
if (w->m_iWorkspaceID == SPECIAL_WORKSPACE_ID)
continue; // special are in the third pass
if (!shouldRenderWindow(&w, PMONITOR))
if (!shouldRenderWindow(w.get(), PMONITOR))
continue;
// render the bad boy
renderWindow(&w, PMONITOR, time, true);
renderWindow(w.get(), PMONITOR, time, true);
}
// floating on top
for (auto& w : g_pCompositor->m_lWindows) {
if (!g_pCompositor->windowValidMapped(&w) && !w.m_bFadingOut)
for (auto& w : g_pCompositor->m_vWindows) {
if (w->m_bHidden && !w->m_bIsMapped && !w->m_bFadingOut)
continue;
if (!w.m_bIsFloating)
if (!w->m_bIsFloating)
continue;
if (w.m_iWorkspaceID == SPECIAL_WORKSPACE_ID)
if (w->m_iWorkspaceID == SPECIAL_WORKSPACE_ID)
continue;
if (!shouldRenderWindow(&w, PMONITOR))
if (!shouldRenderWindow(w.get(), PMONITOR))
continue;
// render the bad boy
renderWindow(&w, PMONITOR, time, true);
renderWindow(w.get(), PMONITOR, time, true);
}
// and then special
for (auto& w : g_pCompositor->m_lWindows) {
if (!g_pCompositor->windowValidMapped(&w) && !w.m_bFadingOut)
for (auto& w : g_pCompositor->m_vWindows) {
if (w->m_bHidden && !w->m_bIsMapped && !w->m_bFadingOut)
continue;
if (w.m_iWorkspaceID != SPECIAL_WORKSPACE_ID)
if (w->m_iWorkspaceID != SPECIAL_WORKSPACE_ID)
continue;
if (!shouldRenderWindow(&w, PMONITOR))
if (!shouldRenderWindow(w.get(), PMONITOR))
continue;
// render the bad boy
renderWindow(&w, PMONITOR, time, true);
renderWindow(w.get(), PMONITOR, time, true);
}
// Render surfaces above windows for monitor
@ -545,14 +551,19 @@ void CHyprRenderer::damageSurface(wlr_surface* pSurface, double x, double y) {
pixman_region32_init(&damageBox);
wlr_surface_get_effective_damage(pSurface, &damageBox);
if (!pixman_region32_not_empty(&damageBox)) {
pixman_region32_fini(&damageBox);
return;
}
pixman_region32_translate(&damageBox, x, y);
for (auto& m : g_pCompositor->m_lMonitors) {
for (auto& m : g_pCompositor->m_vMonitors) {
double lx = 0, ly = 0;
wlr_output_layout_output_coords(g_pCompositor->m_sWLROutputLayout, m.output, &lx, &ly);
wlr_output_layout_output_coords(g_pCompositor->m_sWLROutputLayout, m->output, &lx, &ly);
pixman_region32_translate(&damageBox, lx, ly);
wlr_region_scale(&damageBox, &damageBox, m.scale);
wlr_output_damage_add(m.damage, &damageBox);
wlr_region_scale(&damageBox, &damageBox, m->scale);
wlr_output_damage_add(m->damage, &damageBox);
pixman_region32_translate(&damageBox, -lx, -ly);
}
@ -565,39 +576,17 @@ void CHyprRenderer::damageSurface(wlr_surface* pSurface, double x, double y) {
}
void CHyprRenderer::damageWindow(CWindow* pWindow) {
if (!pWindow->m_bIsFloating) {
// damage by size & pos
// TODO TEMP: revise when added shadows/etc
wlr_box damageBox = pWindow->getFullWindowBoundingBox();
for (auto& m : g_pCompositor->m_lMonitors) {
wlr_box fixedDamageBox = damageBox;
fixedDamageBox.x -= m.vecPosition.x;
fixedDamageBox.y -= m.vecPosition.y;
scaleBox(&fixedDamageBox, m.scale);
wlr_output_damage_add_box(m.damage, &fixedDamageBox);
}
static auto *const PLOGDAMAGE = &g_pConfigManager->getConfigValuePtr("debug:log_damage")->intValue;
if (*PLOGDAMAGE)
Debug::log(LOG, "Damage: Window floated (%s): xy: %d, %d wh: %d, %d", pWindow->m_szTitle.c_str(), damageBox.x, damageBox.y, damageBox.width, damageBox.height);
} else {
// damage by real size & pos + border size * 2 (JIC)
wlr_box damageBox = pWindow->getFullWindowBoundingBox();
for (auto& m : g_pCompositor->m_lMonitors) {
wlr_box fixedDamageBox = damageBox;
fixedDamageBox.x -= m.vecPosition.x;
fixedDamageBox.y -= m.vecPosition.y;
scaleBox(&fixedDamageBox, m.scale);
wlr_output_damage_add_box(m.damage, &fixedDamageBox);
}
static auto *const PLOGDAMAGE = &g_pConfigManager->getConfigValuePtr("debug:log_damage")->intValue;
if (*PLOGDAMAGE)
Debug::log(LOG, "Damage: Window tiled (%s): xy: %d, %d wh: %d, %d", pWindow->m_szTitle.c_str(), damageBox.x, damageBox.y, damageBox.width, damageBox.height);
wlr_box damageBox = pWindow->getFullWindowBoundingBox();
for (auto& m : g_pCompositor->m_vMonitors) {
wlr_box fixedDamageBox = {damageBox.x - m->vecPosition.x, damageBox.y - m->vecPosition.y, damageBox.width, damageBox.height};
scaleBox(&fixedDamageBox, m->scale);
wlr_output_damage_add_box(m->damage, &fixedDamageBox);
}
static auto* const PLOGDAMAGE = &g_pConfigManager->getConfigValuePtr("debug:log_damage")->intValue;
if (*PLOGDAMAGE)
Debug::log(LOG, "Damage: Window (%s): xy: %d, %d wh: %d, %d", pWindow->m_szTitle.c_str(), damageBox.x, damageBox.y, damageBox.width, damageBox.height);
}
void CHyprRenderer::damageMonitor(SMonitor* pMonitor) {
@ -611,10 +600,10 @@ void CHyprRenderer::damageMonitor(SMonitor* pMonitor) {
}
void CHyprRenderer::damageBox(wlr_box* pBox) {
for (auto& m : g_pCompositor->m_lMonitors) {
wlr_box damageBox = {pBox->x - m.vecPosition.x, pBox->y - m.vecPosition.y, pBox->width, pBox->height};
scaleBox(&damageBox, m.scale);
wlr_output_damage_add_box(m.damage, &damageBox);
for (auto& m : g_pCompositor->m_vMonitors) {
wlr_box damageBox = {pBox->x - m->vecPosition.x, pBox->y - m->vecPosition.y, pBox->width, pBox->height};
scaleBox(&damageBox, m->scale);
wlr_output_damage_add_box(m->damage, &damageBox);
}
static auto *const PLOGDAMAGE = &g_pConfigManager->getConfigValuePtr("debug:log_damage")->intValue;
@ -638,6 +627,9 @@ void CHyprRenderer::renderDragIcon(SMonitor* pMonitor, timespec* time) {
renderdata.h = g_pInputManager->m_sDrag.dragIcon->surface->current.height;
wlr_surface_for_each_surface(g_pInputManager->m_sDrag.dragIcon->surface, renderSurface, &renderdata);
wlr_box box = {g_pInputManager->m_sDrag.pos.x - 2, g_pInputManager->m_sDrag.pos.y - 2, g_pInputManager->m_sDrag.dragIcon->surface->current.width + 4, g_pInputManager->m_sDrag.dragIcon->surface->current.height + 4};
g_pHyprRenderer->damageBox(&box);
}
DAMAGETRACKINGMODES CHyprRenderer::damageTrackingModeFromStr(const std::string& mode) {
@ -651,14 +643,23 @@ DAMAGETRACKINGMODES CHyprRenderer::damageTrackingModeFromStr(const std::string&
return DAMAGE_TRACKING_INVALID;
}
void CHyprRenderer::applyMonitorRule(SMonitor* pMonitor, SMonitorRule* pMonitorRule, bool force) {
bool CHyprRenderer::applyMonitorRule(SMonitor* pMonitor, SMonitorRule* pMonitorRule, bool force) {
Debug::log(LOG, "Applying monitor rule for %s", pMonitor->szName.c_str());
// if it's disabled, disable and ignore
if (pMonitorRule->disabled) {
wlr_output_enable(pMonitor->output, 0);
wlr_output_commit(pMonitor->output);
Events::listener_monitorDestroy(nullptr, pMonitor->output);
return false;
}
// 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) && pMonitor->transform == pMonitorRule->transform) {
Debug::log(LOG, "Not applying a new rule to %s because it's already applied!", pMonitor->szName.c_str());
return;
return true;
}
wlr_output_set_scale(pMonitor->output, pMonitorRule->scale);
@ -697,23 +698,32 @@ void CHyprRenderer::applyMonitorRule(SMonitor* pMonitor, SMonitorRule* pMonitorR
}
if (!found) {
const auto PREFERREDMODE = wlr_output_preferred_mode(pMonitor->output);
wlr_output_set_custom_mode(pMonitor->output, (int)pMonitorRule->resolution.x, (int)pMonitorRule->resolution.y, (int)pMonitorRule->refreshRate * 1000);
pMonitor->vecSize = pMonitorRule->resolution;
if (!PREFERREDMODE) {
Debug::log(ERR, "Monitor %s has NO PREFERRED MODE, and an INVALID one was requested: %ix%i@%2f",
(int)pMonitorRule->resolution.x, (int)pMonitorRule->resolution.y, (float)pMonitorRule->refreshRate);
return;
if (!wlr_output_test(pMonitor->output)) {
Debug::log(ERR, "Custom resolution FAILED, falling back to preferred");
const auto PREFERREDMODE = wlr_output_preferred_mode(pMonitor->output);
if (!PREFERREDMODE) {
Debug::log(ERR, "Monitor %s has NO PREFERRED MODE, and an INVALID one was requested: %ix%i@%2f",
(int)pMonitorRule->resolution.x, (int)pMonitorRule->resolution.y, (float)pMonitorRule->refreshRate);
return true;
}
// Preferred is valid
wlr_output_set_mode(pMonitor->output, PREFERREDMODE);
Debug::log(ERR, "Monitor %s got an invalid requested mode: %ix%i@%2f, using the preferred one instead: %ix%i@%2f",
pMonitor->output->name, (int)pMonitorRule->resolution.x, (int)pMonitorRule->resolution.y, (float)pMonitorRule->refreshRate,
PREFERREDMODE->width, PREFERREDMODE->height, PREFERREDMODE->refresh / 1000.f);
pMonitor->refreshRate = PREFERREDMODE->refresh / 1000.f;
pMonitor->vecSize = Vector2D(PREFERREDMODE->width, PREFERREDMODE->height);
} else {
Debug::log(LOG, "Set a custom mode %ix%i@%2f (mode not found in monitor modes)", (int)pMonitorRule->resolution.x, (int)pMonitorRule->resolution.y, (float)pMonitorRule->refreshRate);
}
// Preferred is valid
wlr_output_set_mode(pMonitor->output, PREFERREDMODE);
Debug::log(ERR, "Monitor %s got an invalid requested mode: %ix%i@%2f, using the preferred one instead: %ix%i@%2f",
pMonitor->output->name, (int)pMonitorRule->resolution.x, (int)pMonitorRule->resolution.y, (float)pMonitorRule->refreshRate,
PREFERREDMODE->width, PREFERREDMODE->height, PREFERREDMODE->refresh / 1000.f);
pMonitor->refreshRate = PREFERREDMODE->refresh / 1000.f;
pMonitor->vecSize = Vector2D(PREFERREDMODE->width, PREFERREDMODE->height);
}
} else {
wlr_output_set_custom_mode(pMonitor->output, (int)pMonitorRule->resolution.x, (int)pMonitorRule->resolution.y, (int)pMonitorRule->refreshRate * 1000);
@ -730,7 +740,7 @@ void CHyprRenderer::applyMonitorRule(SMonitor* pMonitor, SMonitorRule* pMonitorR
if (!wlr_output_commit(pMonitor->output)) {
Debug::log(ERR, "Couldn't commit output named %s", pMonitor->output->name);
return;
return true;
}
int x, y;
@ -752,6 +762,8 @@ void CHyprRenderer::applyMonitorRule(SMonitor* pMonitor, SMonitorRule* pMonitorR
// frame skip
pMonitor->framesToSkip = 1;
return true;
}
void CHyprRenderer::ensureCursorRenderingMode() {
@ -767,8 +779,8 @@ void CHyprRenderer::ensureCursorRenderingMode() {
Debug::log(LOG, "Hiding the cursor (timeout)");
for (auto& m : g_pCompositor->m_lMonitors)
g_pHyprRenderer->damageMonitor(&m); // TODO: maybe just damage the cursor area?
for (auto& m : g_pCompositor->m_vMonitors)
g_pHyprRenderer->damageMonitor(m.get()); // TODO: maybe just damage the cursor area?
} else if (*PCURSORTIMEOUT > PASSEDCURSORSECONDS && !m_bHasARenderedCursor) {
m_bHasARenderedCursor = true;
@ -777,8 +789,8 @@ void CHyprRenderer::ensureCursorRenderingMode() {
Debug::log(LOG, "Showing the cursor (timeout)");
for (auto& m : g_pCompositor->m_lMonitors)
g_pHyprRenderer->damageMonitor(&m); // TODO: maybe just damage the cursor area?
for (auto& m : g_pCompositor->m_vMonitors)
g_pHyprRenderer->damageMonitor(m.get()); // TODO: maybe just damage the cursor area?
}
} else {
m_bHasARenderedCursor = true;

View file

@ -28,7 +28,7 @@ public:
void damageBox(wlr_box*);
void damageBox(const int& x, const int& y, const int& w, const int& h);
void damageMonitor(SMonitor*);
void applyMonitorRule(SMonitor*, SMonitorRule*, bool force = false);
bool applyMonitorRule(SMonitor*, SMonitorRule*, bool force = false);
bool shouldRenderWindow(CWindow*, SMonitor*);
bool shouldRenderWindow(CWindow*);
void ensureCursorRenderingMode();

View file

@ -0,0 +1,13 @@
#include "Shader.hpp"
GLint CShader::getUniformLocation(const std::string& unif) {
const auto itpos = m_muUniforms.find(unif);
if (itpos == m_muUniforms.end()) {
const auto unifLoc = glGetUniformLocation(program, unif.c_str());
m_muUniforms[unif] = unifLoc;
return unifLoc;
}
return itpos->second;
}

View file

@ -1,22 +1,21 @@
#pragma once
#include "../defines.hpp"
struct SQuad {
GLuint program;
GLint proj;
GLint color;
GLint posAttrib;
GLint texAttrib;
};
#include <unordered_map>
class CShader {
public:
GLuint program;
GLint proj;
GLint color;
GLint tex;
GLint alpha;
GLint posAttrib;
GLint texAttrib;
GLint discardOpaque;
GLint getUniformLocation(const std::string&);
private:
std::unordered_map<std::string, GLint> m_muUniforms;
};

View file

@ -1,4 +1,5 @@
#pragma once
#include "shaders/Textures.hpp"
#include "shaders/Shadow.hpp"
#include "shaders/Shadow.hpp"
#include "shaders/Border.hpp"

View file

@ -35,6 +35,17 @@ void CHyprDropShadowDecoration::damageEntire() {
void CHyprDropShadowDecoration::updateWindow(CWindow* pWindow) {
damageEntire();
const auto PWORKSPACE = g_pCompositor->getWorkspaceByID(pWindow->m_iWorkspaceID);
const auto WORKSPACEOFFSET = PWORKSPACE ? PWORKSPACE->m_vRenderOffset.vec() : Vector2D();
if (pWindow->m_vRealPosition.vec() + WORKSPACEOFFSET != m_vLastWindowPos || pWindow->m_vRealSize.vec() != m_vLastWindowSize) {
m_vLastWindowPos = pWindow->m_vRealPosition.vec() + WORKSPACEOFFSET;
m_vLastWindowSize = pWindow->m_vRealSize.vec();
damageEntire();
}
}
void CHyprDropShadowDecoration::draw(SMonitor* pMonitor, float a) {
@ -45,22 +56,70 @@ void CHyprDropShadowDecoration::draw(SMonitor* pMonitor, float a) {
static auto *const PSHADOWS = &g_pConfigManager->getConfigValuePtr("decoration:drop_shadow")->intValue;
static auto *const PSHADOWSIZE = &g_pConfigManager->getConfigValuePtr("decoration:shadow_range")->intValue;
static auto *const PROUNDING = &g_pConfigManager->getConfigValuePtr("decoration:rounding")->intValue;
static auto *const PSHADOWIGNOREWINDOW = &g_pConfigManager->getConfigValuePtr("decoration:shadow_ignore_window")->intValue;
static auto *const PSHADOWOFFSET = &g_pConfigManager->getConfigValuePtr("decoration:shadow_offset")->strValue;
if (*PSHADOWS != 1)
return; // disabled
// update the extents if needed
if (*PSHADOWSIZE != m_seExtents.topLeft.x)
m_seExtents = {{*PSHADOWSIZE + 2, *PSHADOWSIZE + 2}, {*PSHADOWSIZE + 2, *PSHADOWSIZE + 2}};
// get the real offset
Vector2D offset;
try {
if (const auto SPACEPOS = PSHADOWOFFSET->find(' '); SPACEPOS != std::string::npos) {
const auto X = PSHADOWOFFSET->substr(0, SPACEPOS);
const auto Y = PSHADOWOFFSET->substr(SPACEPOS + 1);
m_vLastWindowPos = m_pWindow->m_vRealPosition.vec();
m_vLastWindowSize = m_pWindow->m_vRealSize.vec();
if (isNumber(X, true) && isNumber(Y, true)) {
offset = Vector2D(std::stof(X), std::stof(Y));
}
}
} catch (std::exception& e) {
return; // cannot parse
}
// update the extents
m_seExtents = {{*PSHADOWSIZE + 2 - offset.x, *PSHADOWSIZE + 2 - offset.y}, {*PSHADOWSIZE + 2 + offset.x, *PSHADOWSIZE + 2 + offset.y}};
// draw the shadow
wlr_box fullBox = {m_vLastWindowPos.x - m_seExtents.topLeft.x + 2, m_vLastWindowPos.y - m_seExtents.topLeft.y + 2, m_vLastWindowSize.x + m_seExtents.topLeft.x + m_seExtents.bottomRight.x - 4, m_vLastWindowSize.y + m_seExtents.topLeft.y + m_seExtents.bottomRight.y - 4};
fullBox.x -= pMonitor->vecPosition.x;
fullBox.y -= pMonitor->vecPosition.y;
if (fullBox.width < 1 || fullBox.height < 1)
return; // don't draw invisible shadows
if (*PSHADOWIGNOREWINDOW) {
glClearStencil(0);
glClear(GL_STENCIL_BUFFER_BIT);
glEnable(GL_STENCIL_TEST);
glStencilFunc(GL_ALWAYS, 1, -1);
glStencilOp(GL_KEEP, GL_KEEP, GL_REPLACE);
wlr_box windowBox = {m_vLastWindowPos.x - pMonitor->vecPosition.x, m_vLastWindowPos.y - pMonitor->vecPosition.y, m_vLastWindowSize.x, m_vLastWindowSize.y};
scaleBox(&windowBox, pMonitor->scale);
if (windowBox.width < 1 || windowBox.height < 1) {
glDisable(GL_STENCIL_TEST);
return; // prevent assert failed
}
g_pHyprOpenGL->renderRect(&windowBox, CColor(0,0,0,0), *PROUNDING);
glStencilFunc(GL_NOTEQUAL, 1, -1);
glStencilOp(GL_KEEP, GL_KEEP, GL_REPLACE);
}
scaleBox(&fullBox, pMonitor->scale);
g_pHyprOpenGL->renderRoundedShadow(&fullBox, *PROUNDING, *PSHADOWSIZE, a);
if (*PSHADOWIGNOREWINDOW) {
// cleanup
glClearStencil(0);
glClear(GL_STENCIL_BUFFER_BIT);
glDisable(GL_STENCIL_TEST);
}
}

View file

@ -21,14 +21,18 @@ eDecorationType CHyprGroupBarDecoration::getDecorationType() {
void CHyprGroupBarDecoration::updateWindow(CWindow* pWindow) {
damageEntire();
if (pWindow->m_vRealPosition.vec() != m_vLastWindowPos || pWindow->m_vRealSize.vec() != m_vLastWindowSize) {
const auto PWORKSPACE = g_pCompositor->getWorkspaceByID(pWindow->m_iWorkspaceID);
const auto WORKSPACEOFFSET = PWORKSPACE ? PWORKSPACE->m_vRenderOffset.vec() : Vector2D();
if (pWindow->m_vRealPosition.vec() + WORKSPACEOFFSET != 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_vLastWindowPos = pWindow->m_vRealPosition.vec() + WORKSPACEOFFSET;
m_vLastWindowSize = pWindow->m_vRealSize.vec();
}

View file

@ -16,7 +16,7 @@ struct SWindowDecorationExtents {
class CWindow;
struct SMonitor;
class IHyprWindowDecoration {
interface IHyprWindowDecoration {
public:
virtual ~IHyprWindowDecoration() = 0;

View file

@ -0,0 +1,91 @@
#pragma once
#include <string>
// makes a stencil without corners
inline const std::string FRAGBORDER1 = R"#(
precision mediump float;
varying vec4 v_color;
varying vec2 v_texcoord;
uniform vec2 topLeft;
uniform vec2 bottomRight;
uniform vec2 fullSize;
uniform float radius;
uniform float thick;
uniform int primitiveMultisample;
float getOpacityForPixAndCorner(vec2 pix, vec2 corner) {
if (primitiveMultisample == 0) {
float dis = distance(pix + vec2(0.5, 0.5), corner);
return dis < radius && dis > radius - thick ? 1.0 : 0.0;
}
float distance1 = distance(pix + vec2(0.25, 0.25), corner);
float distance2 = distance(pix + vec2(0.75, 0.25), corner);
float distance3 = distance(pix + vec2(0.25, 0.75), corner);
float distance4 = distance(pix + vec2(0.75, 0.75), corner);
float v1 = distance1 < radius && distance1 > radius - thick ? 1.0 : 0.0;
float v2 = distance2 < radius && distance2 > radius - thick ? 1.0 : 0.0;
float v3 = distance3 < radius && distance3 > radius - thick ? 1.0 : 0.0;
float v4 = distance4 < radius && distance4 > radius - thick ? 1.0 : 0.0;
return (v1 + v2 + v3 + v4) / 4.0;
}
void main() {
vec2 pixCoord = fullSize * v_texcoord;
vec4 pixColor = v_color;
bool done = false;
// check for edges
if (pixCoord[0] < topLeft[0]) {
if (pixCoord[1] < topLeft[1]) {
// top left
pixColor[3] = pixColor[3] * getOpacityForPixAndCorner(pixCoord, topLeft + vec2(1,1));
done = true;
} else if (pixCoord[1] > bottomRight[1]) {
// bottom left
pixColor[3] = pixColor[3] * getOpacityForPixAndCorner(pixCoord, vec2(topLeft[0] + 1.0, bottomRight[1]));
done = true;
}
} else if (pixCoord[0] > bottomRight[0]) {
if (pixCoord[1] < topLeft[1]) {
// top right
pixColor[3] = pixColor[3] * getOpacityForPixAndCorner(pixCoord, vec2(bottomRight[0], topLeft[1] + 1.0));
done = true;
} else if (pixCoord[1] > bottomRight[1]) {
// bottom right
pixColor[3] = pixColor[3] * getOpacityForPixAndCorner(pixCoord, bottomRight);
done = true;
}
}
// now check for other shit
if (!done) {
// distance to all straight bb borders
float distanceT = pixCoord[1];
float distanceB = fullSize[1] - pixCoord[1];
float distanceL = pixCoord[0];
float distanceR = fullSize[0] - pixCoord[0];
// get the smallest
float smallest = min(min(distanceT, distanceB), min(distanceL, distanceR));
if (smallest > thick) {
discard; return;
}
}
if (pixColor[3] == 0.0) {
discard; return;
}
gl_FragColor = pixColor;
}
)#";

View file

@ -13,7 +13,6 @@ uniform vec2 fullSize;
uniform float radius;
uniform float range;
uniform float shadowPower;
uniform int ignoreWindow;
float pixAlphaRoundedDistance(float distanceToCorner) {
if (distanceToCorner > radius) {
@ -75,7 +74,7 @@ void main() {
}
}
if (pixColor[3] == 0.0 || (ignoreWindow == 1 && pixColor[3] == originalAlpha)) {
if (pixColor[3] == 0.0) {
discard; return;
}

@ -1 +1 @@
Subproject commit b89ed9015c3fbe8d339e9d65cf70fdca6e5645bc
Subproject commit 5c4384a1330faedf975c8b8644881d50390f3613